add editable footer

closes #346
pull/356/head
Kaalleen 2018-11-15 17:39:25 +01:00 zatwierdzone przez GitHub
rodzic f5c85183d9
commit 05aaf36d6d
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 435 dodań i 97 usunięć

Wyświetl plik

@ -285,8 +285,8 @@ $(function() {
/* Contendeditable Fields */
$('[contenteditable="true"]').on('focusout', function() {
/* change svg scale */
$('body').on('focusout', '[contenteditable="true"]:not(.footer-info)', function() {
/* change svg scale */
var content = $(this).text();
var field_name = $(this).attr('data-field-name');
if(field_name == 'svg-scale') {
@ -323,6 +323,9 @@ $(function() {
item.val(value).trigger('initialize');
} else if (item.is('figure.inksimulation')) {
setSVGTransform(item, value);
} else if (item.is('div.footer-info')) {
$('#footer-info-text').html(value);
item.html(value);
} else {
item.text(value);
}
@ -336,7 +339,7 @@ $(function() {
}, 500);
});
$('[contenteditable="true"]').keypress(function(e) {
$('body').on('keypress', '[contenteditable="true"]:not(#footer-info-text)', function(e) {
if (e.which == 13) {
// pressing enter defocuses the element
this.blur();
@ -347,6 +350,20 @@ $(function() {
}
});
$('#footer-info-text[contenteditable="true"]').keypress(function(e) {
if (e.which == 13) {
if($(this).find('div').length > 2) {
return false;
} else {
return true;
}
}
});
$('#footer-info-text[contenteditable="true"]').focusout(function() {
updateFooter();
});
/* Settings Bar */
$('button.close').click(function() {
@ -397,6 +414,128 @@ $(function() {
$(this).addClass("active");
});
// Footer
function getEditMode(){
return $('#switch-mode').prop('checked');
}
$('#switch-mode').change(function() {
var editMode = getEditMode();
if (editMode) {
$('#footer-info-text').text( $('#footer-info-text' ).html());
$('#tool-bar .edit-only').prop("disabled", true);
} else {
$('#footer-info-text').css('display', 'block');
var sourceText = $('#footer-info-text').text();
$('#footer-info-text').html( sourceText );
$('#tool-bar .tb-button.edit-only').prop('disabled', false);
}
});
function updateFooter() {
var editMode = getEditMode();
var footerText = '';
if (editMode) {
footerText = $('#footer-info-text' ).text();
} else {
footerText = $('#footer-info-text').html();
}
$('.footer-info').html(footerText);
var content = $('.footer-info').html();
$.postJSON('/settings/footer-info', {value: content});
}
function formatText(selection, value) {
var htmlMode = getEditMode();
if(!htmlMode) {
if(window.getSelection().toString()){
document.execCommand(selection, false, value);
updateFooter();
}
}
}
$('#tb-bold').click(function(selection) {
formatText('bold');
});
$('#tb-italic').click(function() {
formatText('italic');
});
$('#tb-underline').click(function() {
formatText('underline');
});
$('#tb-remove').click(function() {
formatText('removeFormat');
});
$('#tb-hyperlink').click(function() {
formatText('createlink', 'tempurl');
$('#footer-url').css('display', 'block');
});
$('#url-ok').click(function() {
var link = $('#footer-link').val();
$('#footer-info-text a[href="tempurl"]').attr('href', link);
$('#footer-link').val('https://');
$('#footer-url').css('display', 'none');
updateFooter();
});
$('#url-cancel').click(function() {
$('#footer-info-text a[href="tempurl"]').contents().unwrap();
$('#footer-link').val('https://');
$('#footer-url').css('display', 'none');
updateFooter();
});
$('#tb-mail').click(function() {
formatText('createlink', 'tempurl');
$('#footer-email').css('display', 'block');
});
$('#mail-ok').click(function() {
var link = 'mailto:' + $('#footer-mail').val();
$('#footer-info-text a[href="tempurl"]').attr('href', link);
$('#footer-mail').val('@');
$('#footer-email').css('display', 'none');
updateFooter();
});
$('#mail-cancel').click(function() {
$('#footer-info-text a[href="tempurl"]').contents().unwrap();
$('#footer-mail').val('@');
$('#footer-email').css('display', 'none');
updateFooter();
});
$('#tb-reset').click(function() {
$('#footer-reset').css('display', 'block');
});
$('#reset-ok').click(function() {
var htmlMode = getEditMode();
if(!htmlMode) {
$('#footer-info-text').html($('#footer-info-original').html());
} else {
$('#footer-info-text').text($('#footer-info-original').html());
}
$('#footer-reset').css('display', 'none');
updateFooter();
});
$('#reset-cancel').click(function() {
$('#footer-reset').css('display', 'none');
});
$('body').on("click", ".edit-footer-link", function() {
$("button.settings").trigger("click");
$("#branding-tab").trigger("click");
});
// Paper Size
$('select#printing-size').on('change initialize', function(){
$('.page').toggleClass('a4', $(this).find(':selected').val() == 'a4');
@ -555,8 +694,8 @@ $(function() {
});
// Logo
$('#logo-picker').change(function(e) {
var file = e.originalEvent.currentTarget.files[0];
$(document).on("change", ".logo-picker", function(e) {
var file = e.currentTarget.files[0];
var reader = new FileReader();
reader.onloadend = function() {
var data = reader.result;
@ -580,6 +719,7 @@ $(function() {
if (logo.startsWith("data:")) {
settings["logo"] = logo;
}
settings["footer-info"] = $("[data-field-name='footer-info']").html();
settings["machine-speed"] = $("[data-field-name='machine-speed']").val();
settings["time-additional"] = $("[data-field-name='time-additional']").val();

Wyświetl plik

@ -199,6 +199,12 @@ body {
border: 1px solid #413232;
padding: 5px;
cursor: pointer;
background: white;
color: black;
}
#settings-ui button.tab {
background: transparent;
}
#settings-ui button.active {
@ -256,6 +262,133 @@ body {
pointer-events: none;
}
.logo-ui {
float: left;
}
.brandlogo-ui {
width: auto !important;
}
.brandlogo-ui img {
background: white;
}
.logo-legend {
display: inline !important;
position: relative;
line-height: 30mm;
padding: 5px;
border: 1px solid #413232;
background: white;
margin-left: 1em;
cursor: pointer;
}
#edit-footer {
position: relative;
}
#footer-info-text {
width: 100%;
min-height: 5em;
border: 1px solid darkgrey;
padding: 12px;
overflow-y: scroll;
background: white;
}
#tool-bar .tb-button {
border: 1px solid darkgrey;
border-bottom: none;
margin-bottom: -0.2em;
cursor: pointer;
color: #413232;
height: 2.2em;
vertical-align: top;
}
#tool-bar .tb-button:disabled {
background: #eaeaea;
color: white;
cursor: auto;
}
#edit-mode {
display: inline;
position: relative;
border: 1px solid darkgray;
padding: 0 5px 10px 0;
vertical-align: top;
}
#edit-mode input {
visibility: hidden;
}
#edit-mode label {
cursor: pointer;
vertical-align: middle;
background: white;
color: #413232;
}
#edit-mode label:after {
opacity: 0.1;
content: '';
position: absolute;
width: 9px;
height: 5px;
background: transparent;
top: 6px;
left: 7px;
border: 3px solid black;
border-top: none;
border-right: none;
transform: rotate(-45deg);
}
#edit-mode label:hover::after {
opacity: 0.5;
}
#edit-mode input[type=checkbox]:checked + label:after {
opacity: 1;
}
#edit-mode span {
margin-left: 1em;
}
div#footer-url, div#footer-email, div#footer-reset {
display: none;
position: absolute;
background: white;
border: 1px solid black;
padding: 5mm;
top: 0;
left: 0;
z-index: 10;
}
div#footer-info-original {
visibility: hidden;
width: 0;
height: 0;
}
.notice--warning {
padding: 1em;
font-size: 0.75em;
text-indent: initial;
border: 1px solid #d0d0d0;
background: white;
}
.ff-serif {
font-family: serif;
}
#modal-background {
display: none;
z-index: 3;
@ -322,10 +455,9 @@ body {
/* hide the actual file picker control, since we just want them to click the
* image instead
*/
#logo-picker {
width: 0px;
height: 0px;
opacity: 0;
.logo-picker {
visibility: hidden;
position: absolute;
}
.logo-instructions {
@ -510,6 +642,7 @@ body {
padding-left: 3px;
padding-right: 3px;
margin: 0px 1px 0px 1px;
cursor: pointer;
}
input.realistic {
@ -524,6 +657,15 @@ body {
pointer-events: none;
}
figure.inksimulation div {
display: none;
}
/* Display svg buttons only with svg hover */
figure.inksimulation:hover > div {
display: block;
}
/* Color Swatches */
.color-palette {
@ -799,6 +941,7 @@ body {
white-space: wrap;
text-align: center;
padding-top: 2mm;
position: relative;
}
@ -809,6 +952,25 @@ body {
margin-top: 0;
}
.edit-footer-link {
display: none;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
line-height: 15mm;
background: #ffffffbf;
font-size: x-large;
cursor: pointer;
height: 15mm;
border: 1px dashed #cccbcb;
}
footer:hover > .edit-footer-link {
display: block;
}
/* Messages */
#errors.show {
@ -987,30 +1149,18 @@ body {
margin: 0 !important;
}
figure.inksimulation div {
figure.inksimulation div,
.ui,
#settings-ui,
#errors,
span.logo-instructions {
display: none;
}
.ui {
display: none;
}
#settings-ui {
display: none !important;
}
#errors {
display: none !important;
}
.header-field:not(:empty)::before {
content: attr(data-label);
padding-right: 0.5em;
}
span.logo-instructions {
display: none;
}
}
@page {

Wyświetl plik

@ -1,6 +1,7 @@
<footer>
<p class="num_pages">{{ _('Page') }} <span class="page-num"></span>/<span class="total-page-num"></span></p>
<p>Proudly generated with <a href="http://inkstitch.org/" target="_blank">Ink/Stitch</a></p>
<div class="footer-info" data-field-name="footer-info">{{ _('Proudly generated with') }} <a href="http://inkstitch.org/" target="_blank">Ink/Stitch</a></div>
<div class="edit-footer-link"></div>
</footer>

Wyświetl plik

@ -1,7 +1,7 @@
<figure class="brandlogo">
<label for="logo-picker">
<label class="logo-upload">
<img src="{{ logo.src or "resources/inkstitch-logo.svg" }}" alt="{{ logo.title }}" title="{{ logo.title }}" data-field-name="logo">
<input type=file id="logo-picker" />
<input type=file class="logo-picker" />
<span class="logo-instructions">{{ _("Click to choose another logo") }}</span>
</label>
</figure>

Wyświetl plik

@ -16,82 +16,129 @@
<div id="tabs">
<button class="tab active">{{ _('Page Setup') }}</button>
<button class="tab" id="branding-tab">{{ _('Branding') }}</button>
<button class="tab">{{ _('Estimated Time') }}</button>
<button class="tab">{{ _('Design') }}</button>
</div>
<div id="fieldsets-ui">
<fieldset id="ui-page-setup">
<fieldset>
<legend>{{ _('Page Setup') }}</legend>
<div>
<p class="select-container">
<label for="printing-size">{{ _('Printing Size') }}:</label>
<select id="printing-size" data-field-name="paper-size">
<option value="letter" selected="selected">Letter</option>
<option value="a4">A4</option>
</select>
</p>
</div>
<div>
<fieldset>
<legend>{{ _('Print Layouts') }}</legend>
<p><input type="checkbox" class="view" id="client-overview" data-field-name="client-overview" /><label for="client-overview">{{ _('Client Overview') }}</label></p>
<p><input type="checkbox" class="view" id="client-detailedview" data-field-name="client-detailedview" /><label for="client-detailedview">{{ _('Client Detailed View') }}</label></p>
<p><input type="checkbox" class="view" id="operator-overview" data-field-name="operator-overview" CHECKED /><label for="operator-overview">{{ _('Operator Overview') }}</label></p>
<p><input type="checkbox" class="view" id="operator-detailedview" data-field-name="operator-detailedview" CHECKED /><label for="operator-detailedview">{{ _('Operator Detailed View') }}</label></p>
<p style="text-indent: 1.5em;">{{ _('Thumbnail size') }}: <input type="range" min="15" max="110" value="15" step="5" id="operator-detailedview-thumbnail-size" data-field-name="operator-detailedview-thumbnail-size" style="vertical-align: middle;"> <span id="display-thumbnail-size">15mm</span>
</p>
</fieldset>
<button class="save-settings" title="{{ _("Includes these Page Setup, estimated time settings and also the icon.") }}">{{ _("Save as defaults") }}</button>
</div>
</fieldset>
<fieldset id="ui-time" class="ui-tab">
<legend>{{ _('Estimated Time') }}</legend>
<fieldset>
<legend>{{ _('Machine Settings') }}</legend>
<p>
<input class="view" type="number" id="machine-speed" data-field-name="machine-speed" min="0" value="700" title="{{ _('Average Machine Speed') }}" />
<label for="machine-speed">{{ _('stitches per minute ') }}</label>
</p>
</fieldset>
<fieldset>
<legend>{{ _('Time Factors') }}</legend>
<p>
<input type="number" id="time-additional" data-field-name="time-additional" min="0" value="0" />
<label for="time-additional" title="{{ _('Includes average time for preparing the machine, thread breaks and/or bobbin changes, etc.') }}">{{ _('seconds to add to total time*') }}</label>
</p>
<p>
<input type="number" id="time-color-change" data-field-name="time-color-change" min="0" value="10" />
<label for="time-color-change" title="{{ _('This will be added to the total time.') }}">{{ _('seconds needed for a color change*') }}</label></p>
<p>
<input type="number" id="time-trims" data-field-name="time-trims" min="0" value="10" />
<label for="time-trims">{{ _('seconds needed for trim') }}</label></p>
</fieldset>
<fieldset>
<legend>{{ _('Display Time On') }}</legend>
<p>
<p><input type="checkbox" class="time-display" id="time-clo" data-field-name="time-clo" /><label for="time-clo">{{ _('Client Overview') }}</label></p>
<p><input type="checkbox" class="time-display" id="time-cld" data-field-name="time-cld" /><label for="time-cld">{{ _('Client Detailed View') }}</label></p>
<p><input type="checkbox" class="time-display" id="time-opo" data-field-name="time-opo" CHECKED /><label for="time-opo">{{ _('Operator Overview') }}</label></p>
<p><input type="checkbox" class="time-display" id="time-opd" data-field-name="time-opd" CHECKED /><label for="time-opd">{{ _('Operator Detailed View') }}</label></p>
</p>
</fieldset>
<button class="save-settings" title="{{ _("Includes these Page Setup, estimated time settings and also the icon.") }}">{{ _("Save as defaults") }}</button>
</fieldset>
<fieldset id="ui-design" class="ui-tab">
<legend>{{ _('Design') }}</legend>
<p class="select-container"><label for="thread-palette">{{ _('Thread Palette') }}:</label>
<select id="thread-palette" data-field-name="thread-palette">
{% if selected_palette is none %}
<option value="" selected>{{ _('None') }}</option>
{% endif %}
{% for palette in palettes %}
<option value="{{ palette }}" {{ "selected" if palette == selected_palette.name else "" }}>{{ palette }}</option>
{% endfor %}
</select>
<p class="select-container">
<label for="printing-size">{{ _('Printing Size') }}:</label>
<select id="printing-size" data-field-name="paper-size">
<option value="letter" selected="selected">Letter</option>
<option value="a4">A4</option>
</select>
</p>
</fieldset>
</div><!-- END FIELDSETS-UI -->
</div><!-- END SETTINGS-UI-->
<fieldset>
<legend>{{ _('Print Layouts') }}</legend>
<p><input type="checkbox" class="view" id="client-overview" data-field-name="client-overview" /><label for="client-overview">{{ _('Client Overview') }}</label></p>
<p><input type="checkbox" class="view" id="client-detailedview" data-field-name="client-detailedview" /><label for="client-detailedview">{{ _('Client Detailed View') }}</label></p>
<p><input type="checkbox" class="view" id="operator-overview" data-field-name="operator-overview" CHECKED /><label for="operator-overview">{{ _('Operator Overview') }}</label></p>
<p><input type="checkbox" class="view" id="operator-detailedview" data-field-name="operator-detailedview" CHECKED /><label for="operator-detailedview">{{ _('Operator Detailed View') }}</label></p>
<p style="text-indent: 1.5em;">{{ _('Thumbnail size') }}: <input type="range" min="15" max="110" value="15" step="5" id="operator-detailedview-thumbnail-size" data-field-name="operator-detailedview-thumbnail-size" style="vertical-align: middle;"> <span id="display-thumbnail-size">15mm</span></p>
</fieldset>
<button class="save-settings" title="{{ _("Includes these Page Setup, estimated time settings and also the icon.") }}">{{ _("Save as defaults") }}</button>
</fieldset>
<fieldset id="ui-branding" class="ui-tab">
<fieldset>
<legend>{{ _('Logo') }}</legend>
<figure class="brandlogo brandlogo-ui">
<label class="logo-legend">
{{ ('Choose File') }}
<img src="{{ logo.src or "resources/inkstitch-logo.svg" }}" alt="{{ logo.title }}" title="{{ logo.title }}" data-field-name="logo" class="logo-ui">
<input type=file class="logo-picker" />
</label>
</figure>
</fieldset>
<fieldset id="edit-footer">
<legend>{{ _('Footer: Operator contact information') }}</legend>
<div id="tool-bar">
<button id="tb-bold" class="tb-button ff-serif edit-only" title="Bold"><b>B</b></button>
<button id="tb-italic" class="tb-button ff-serif edit-only" title="Italic"><i>I</i></button>
<button id="tb-underline" class="tb-button ff-serif edit-only" title="Underline"><u>U</u></button>
<button id="tb-remove" class="tb-button ff-serif edit-only" title="Remove formatting"><u style="vertical-align: super; font-size: 60%;">A</u><span style="vertical-align: sub; font-size: 80%;">A</span></button>
<button id="tb-hyperlink" class="tb-button edit-only" title="Hyperlink"></button>
<button id="tb-mail" class="tb-button edit-only" title="E-Mail"></button>
<button id="tb-reset" class="tb-button" title="Reset text"></button>
<p id="edit-mode"><input type="checkbox" id="switch-mode" name="switch-mode" /> <label for="switch-mode">{{ ('Show HTML') }}</label></p>
<div id="footer-url">
<p>{{ _("Enter URL") }}: <input type="text" id="footer-link" name="footer-link" value="https://" /></p>
<p><button id="url-ok">{{ _("OK") }}</button> <button id="url-cancel">{{ _("Cancel") }}</button></p>
</div>
<div id="footer-email">
<p>{{ _("Enter E-Mail") }}: <input type="text" id="footer-mail" name="footer-mail" value="@" /></p>
<p><button id="mail-ok">{{ _("OK") }}</button> <button id="mail-cancel">{{ _("Cancel") }}</button></p>
</div>
<div id="footer-info-original">{{ _("Proudly generated with") }} <a href="http://inkstitch.org/" target="_blank">Ink/Stitch</a></div>
<div id="footer-reset">
<p>{{ _("This will reset your custom text to the default.") }}</p>
<p>{{ _("All changes will be lost.") }}</p>
<p><button id="reset-ok">{{ _("OK") }}</button> <button id="reset-cancel">{{ _("Cancel") }}</button></p>
</div>
</div>
<div id="footer-info-text" contenteditable="true"><div>{{ _("Proudly generated with") }} <a href="http://inkstitch.org/" target="_blank">Ink/Stitch</a></div></div>
<p class="notice--warning"><b>Note</b>: If you are using Firefox, use visible URLs. Links will not be printed to PDF with this browser.</p>
</fieldset>
<button class="save-settings" title="{{ _('Includes these Page Setup, estimated time settings and also the icon.') }}">{{ _("Save as defaults") }}</button>
</fieldset>
<fieldset id="ui-time" class="ui-tab">
<legend>{{ _('Estimated Time') }}</legend>
<fieldset>
<legend>{{ _('Machine Settings') }}</legend>
<p>
<input class="view" type="number" id="machine-speed" data-field-name="machine-speed" min="0" value="700" title="{{ _('Average Machine Speed') }}" />
<label for="machine-speed">{{ _('stitches per minute ') }}</label>
</p>
</fieldset>
<fieldset>
<legend>{{ _('Time Factors') }}</legend>
<p>
<input type="number" id="time-additional" data-field-name="time-additional" min="0" value="0" />
<label for="time-additional" title="{{ _('Includes average time for preparing the machine, thread breaks and/or bobbin changes, etc.') }}">{{ _('seconds to add to total time*') }}</label>
</p>
<p>
<input type="number" id="time-color-change" data-field-name="time-color-change" min="0" value="10" />
<label for="time-color-change" title="{{ _('This will be added to the total time.') }}">{{ _('seconds needed for a color change*') }}</label></p>
<p>
<input type="number" id="time-trims" data-field-name="time-trims" min="0" value="10" />
<label for="time-trims">{{ _('seconds needed for trim') }}</label></p>
</fieldset>
<fieldset>
<legend>{{ _('Display Time On') }}</legend>
<p>
<p><input type="checkbox" class="time-display" id="time-clo" data-field-name="time-clo" /><label for="time-clo">{{ _('Client Overview') }}</label></p>
<p><input type="checkbox" class="time-display" id="time-cld" data-field-name="time-cld" /><label for="time-cld">{{ _('Client Detailed View') }}</label></p>
<p><input type="checkbox" class="time-display" id="time-opo" data-field-name="time-opo" CHECKED /><label for="time-opo">{{ _('Operator Overview') }}</label></p>
<p><input type="checkbox" class="time-display" id="time-opd" data-field-name="time-opd" CHECKED /><label for="time-opd">{{ _('Operator Detailed View') }}</label></p>
</p>
</fieldset>
<button class="save-settings" title="{{ _('Includes page setup, estimated time and also the branding.') }}">{{ _("Save as defaults") }}</button>
</fieldset>
<fieldset id="ui-design" class="ui-tab">
<legend>{{ _('Design') }}</legend>
<p class="select-container"><label for="thread-palette">{{ _('Thread Palette') }}:</label>
<select id="thread-palette" data-field-name="thread-palette">
{% if selected_palette is none %}
<option value="" selected>{{ _('None') }}</option>
{% endif %}
{% for palette in palettes %}
<option value="{{ palette }}" {{ "selected" if palette == selected_palette.name else "" }}>{{ palette }}</option>
{% endfor %}
</select>
</p>
</fieldset>
</div><!-- END FIELDSETS-UI -->
</div><!-- END SETTINGS-UI-->
<div id="modal-background" class="modal"></div>
<div id="modal-content" class="modal">