diff options
| author | Lex Neva <lexelby@users.noreply.github.com> | 2018-04-28 13:40:52 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-04-28 13:40:52 -0400 |
| commit | 14828d6fa2d290fb5f10b2e5956b2fa1153588d5 (patch) | |
| tree | 8e163688d30fd6ec23b1c7d5977ccceb97091264 /print/resources/inkstitch.js | |
| parent | 69d231b4eb197bfe135ec7e146b53c5de975b9d9 (diff) | |
| parent | 8e3dd74a286d4549fdb1dd9cc7a9fcfadb85bb9e (diff) | |
Merge pull request #148 from lexelby/lexelby-print-features
additional print features
Diffstat (limited to 'print/resources/inkstitch.js')
| -rw-r--r-- | print/resources/inkstitch.js | 259 |
1 files changed, 223 insertions, 36 deletions
diff --git a/print/resources/inkstitch.js b/print/resources/inkstitch.js index 454c9ae2..498b1211 100644 --- a/print/resources/inkstitch.js +++ b/print/resources/inkstitch.js @@ -1,3 +1,12 @@ +$.postJSON = function(url, data, success=null) { + return $.ajax(url, { + type: 'POST', + data: JSON.stringify(data), + contentType: 'application/json', + success: success + }); +}; + function ping() { $.get("/ping") .done(function() { setTimeout(ping, 1000) }) @@ -13,46 +22,178 @@ function setPageNumbers() { }); } -// set preview svg scale to fit into its box -function scaleInksimulation() { - $('.inksimulation').each(function() { +// Scale SVG (fit || full size) +function scaleSVG(element, scale = 'fit') { + + // always center svg + transform = "translate(-50%, -50%)"; + + if(scale == 'fit') { var scale = Math.min( - $(this).width() / $(this).find('svg').width(), - $(this).height() / $(this).find('svg').height() + element.width() / element.find('svg').width(), + element.height() / element.find('svg').height() ); + } + + transform += " scale(" + scale + ")"; + var label = parseInt(scale*100); - // center the SVG - transform = "translate(-50%, -50%)"; + element.find('svg').css({ transform: transform }); + element.find('.scale').text(label); +} - if(scale <= 1) { - transform += " scale(" + scale + ")"; - label = parseInt(scale*100) + '%'; - } else { - label = "100%"; - } +// set preview svg scale to fit into its box if transform is not set +function scaleAllSvg() { + $('.page').each(function() { + if( $(this).find('.inksimulation svg').css('transform') == 'none') { + scaleSVG($(this).find('.inksimulation'), 'fit'); + } + }); +} - $(this).find('svg').css({ transform: transform }); - $(this).find('figcaption span').text(label); - }); +var saveTimerHandles = {}; + +function setSVGTransform(figure, transform) { + var field_name = $(figure).data('field-name'); + var scale = transform.match(/-?[\d\.]+/g)[0]; + figure.find('svg').css({ transform: transform }); + figure.find(".scale").text(parseInt(scale*100)); + + // avoid spamming updates + if (saveTimerHandles[field_name] != null) + clearTimeout(saveTimerHandles[field_name]); + + saveTimerHandles[field_name] = setTimeout(function() { + $.postJSON('/settings/' + field_name, {value: transform}); + }, 250); } $(function() { setTimeout(ping, 1000); setPageNumbers(); - scaleInksimulation(); - /* Contendeditable Fields */ + /* SCALING AND MOVING SVG */ - // When we focus out from a contenteditable field, we want to - // set the same content to all fields with the same classname - document.querySelectorAll('[contenteditable="true"]').forEach(function(elem) { - elem.addEventListener('focusout', function() { - var content = $(this).html(); - var field_name = $(this).attr('data-field-name'); - $('[data-field-name="' + field_name + '"]').html(content); - }); + /* Mousewheel scaling */ + $('figure.inksimulation').on( 'DOMMouseScroll mousewheel', function (e) { + if(e.ctrlKey == true) { + + var svg = $(this).find('svg'); + var transform = svg.css('transform').match(/-?[\d\.]+/g); + var scale = parseFloat(transform[0]); + + if (e.originalEvent.detail > 0 || e.originalEvent.wheelDelta < 0) { + // scroll down = zoom out + scale *= 0.97; + if (scale < 0.01) + scale = 0.01; + } else { + //scroll up + scale *= 1.03; + } + + // set modified scale + transform[0] = scale; + transform[3] = scale; + + setSVGTransform($(this), 'matrix(' + transform + ')'); + + //prevent page fom scrolling + return false; + } + }); + + /* Fit SVG */ + $('button.svg-fit').click(function() { + var svgfigure = $(this).closest('figure'); + scaleSVG(svgfigure, 'fit'); + }); + + /* Full Size SVG */ + $('button.svg-full').click(function() { + var svgfigure = $(this).closest('figure'); + scaleSVG(svgfigure, '1'); }); + /* Drag SVG */ + $('figure.inksimulation').on('mousedown', function(e) { + var p0 = { x: e.pageX, y: e.pageY }; + var start_transform = $(this).find('svg').css('transform').match(/-?[\d\.]+/g); + var start_offset = { x: parseFloat(start_transform[4]), y: parseFloat(start_transform[5]) }; + + $(this).css({cursor: 'move'}); + $(this).on('mousemove', function(e) { + var p1 = { x: e.pageX, y: e.pageY }; + // set modified translate + var transform = $(this).find('svg').css('transform').match(/-?[\d\.]+/g); + transform[4] = start_offset.x + (p1.x - p0.x); + transform[5] = start_offset.y + (p1.y - p0.y); + + // I'd ike to use setSVGTransform() here but this code runs many + // times per second and it's just too CPU-intensive. + $(this).find('svg').css({transform: 'matrix(' + transform + ')'}); + }); + }).on('mouseup', function(e) { + $(this).css({cursor: 'auto'}); + $(this).data('p0', null); + $(this).off('mousemove'); + + // set it using setSVGTransform() to ensure that it's saved to the server + setSVGTransform($(this), $(this).find('svg').css('transform')); + }); + + /* Apply transforms to All */ + $('button.svg-apply').click(function() { + var transform = $(this).parent().siblings('svg').css('transform'); + $('.inksimulation').each(function() { + setSVGTransform($(this), transform); + }) + }); + + /* Contendeditable Fields */ + + $('[contenteditable="true"]').on('focusout', function() { + /* change svg scale */ + var content = $(this).html(); + var field_name = $(this).attr('data-field-name'); + if(field_name == 'svg-scale') { + var scale = parseInt(content); + var svg = $(this).parent().siblings('svg'); + var transform = svg.css('transform').match(/-?[\d\.]+/g); + + transform[0] = scale / 100; + transform[3] = scale / 100; + svg.css({ transform: 'matrix(' + transform + ')' }); + } else { + /* When we focus out from a contenteditable field, we want to + * set the same content to all fields with the same classname */ + $('[data-field-name="' + field_name + '"]').html(content); + $.postJSON('/settings/' + field_name, {value: content}); + } + }); + + // load up initial metadata values + $.getJSON('/settings', function(settings) { + $.each(settings, function(field_name, value) { + $('[data-field-name="' + field_name + '"]').each(function(i, item) { + var item = $(item); + if (item.is(':checkbox')) { + item.prop('checked', value).trigger('change'); + } else if (item.is('img')) { + item.attr('src', value); + } else if (item.is('select')) { + item.val(value).trigger('change'); + } else if (item.is('figure.inksimulation')) { + setSVGTransform(item, value); + } else { + item.text(value); + } + }); + }); + // wait until page size is set (if they've specified one) and then scale SVGs to fit + setTimeout(function() { scaleAllSvg() }, 500); + }); + $('[contenteditable="true"]').keypress(function(e) { if (e.which == 13) { // pressing enter defocuses the element @@ -64,14 +205,26 @@ $(function() { return true; } }); - - + + /* Settings Bar */ - + $('button.close').click(function() { $.post('/shutdown', {}) .done(function(data) { window.close(); + + /* Chrome and Firefox both have a rule: scripts can only close windows + * that they opened. Chrome seems to have an exception for windows that + * were opened by an outside program, so the above works fine. Firefox + * steadfastly refuses to allow us to close the window, so we'll tell + * the user (in their language) that they can close it. + */ + setTimeout(function() { + document.open(); + document.write("<html><body>" + data + "</body></html>"); + document.close(); + }, 1000); }); }); @@ -92,20 +245,54 @@ $(function() { $('#close-settings').click(function(){ $('#settings-ui').hide(); }); - + /* Settings */ - + // Paper Size $('select#printing-size').change(function(){ - $('.page').toggleClass('a4'); + var size = $(this).find(':selected').val(); + $('.page').toggleClass('a4', size == 'a4'); + $.postJSON('/settings/paper-size', {value: size}); }); - + //Checkbox $(':checkbox').change(function() { - $('.' + this.id).toggle(); + var checked = $(this).prop('checked'); + var field_name = $(this).attr('data-field-name'); + + $('.' + field_name).toggle(checked); setPageNumbers(); - scaleInksimulation(); + + $.postJSON('/settings/' + field_name, {value: checked}); + }); + + // Logo + $('#logo-picker').change(function(e) { + var file = e.originalEvent.srcElement.files[0]; + var reader = new FileReader(); + reader.onloadend = function() { + var data = reader.result; + $('figure.brandlogo img').attr('src', data); + $.postJSON('/settings/logo', {value: data}); + }; + reader.readAsDataURL(file); + }); + + // "save as defaults" button + $('#save-settings').click(function(e) { + var settings = {}; + settings["client-overview"] = $("[data-field-name='client-overview']").is(':checked'); + settings["client-detailedview"] = $("[data-field-name='client-detailedview']").is(':checked'); + settings["operator-overview"] = $("[data-field-name='operator-overview']").is(':checked'); + settings["operator-detailedview"] = $("[data-field-name='operator-detailedview']").is(':checked'); + settings["paper-size"] = $('select#printing-size').find(':selected').val(); + + var logo = $("figure.brandlogo img").attr('src'); + if (logo.startsWith("data:")) { + settings["logo"] = logo; + } + + $.postJSON('/defaults', {'value': settings}); }); - }); |
