|  |  | 
 |  |  |   document.addEventListener("touchmove", touchHandler, true); | 
 |  |  |   document.addEventListener("touchend", touchHandler, true); | 
 |  |  |   document.addEventListener("touchcancel", touchHandler, true); | 
 |  |  |    | 
 |  |  |  | 
 |  |  |   if(!window.methodDraw) window.methodDraw = function($) { | 
 |  |  |     var svgCanvas; | 
 |  |  |     var Editor = {}; | 
 |  |  |     var is_ready = false; | 
 |  |  |     curConfig = { | 
 |  |  |       canvas_expansion: 1,  | 
 |  |  |       dimensions: [580,400],  | 
 |  |  |       canvas_expansion: 1, | 
 |  |  |       dimensions: [580,400], | 
 |  |  |       initFill: {color: 'fff', opacity: 1}, | 
 |  |  |       initStroke: {width: 1.5, color: '000', opacity: 1}, | 
 |  |  |       initOpacity: 1, | 
 |  |  | 
 |  |  |           "key_down":"Down", | 
 |  |  |           "key_backspace":"Backspace", | 
 |  |  |           "key_del":"Del" | 
 |  |  |    | 
 |  |  |  | 
 |  |  |         }, | 
 |  |  |         // This is needed if the locale is English, since the locale strings are not read in that instance. | 
 |  |  |         layers: { | 
 |  |  | 
 |  |  |           "retrieving": 'Retrieving "%s" ...' | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     var curPrefs = {}; //$.extend({}, defaultPrefs); | 
 |  |  |     var customHandlers = {}; | 
 |  |  |     Editor.curConfig = curConfig; | 
 |  |  |     Editor.tool_scale = 1; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     Editor.setConfig = function(opts) { | 
 |  |  |       $.extend(true, curConfig, opts); | 
 |  |  |       if(opts.extensions) { | 
 |  |  |         curConfig.extensions = opts.extensions; | 
 |  |  |       } | 
 |  |  |     } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     // Extension mechanisms must call setCustomHandlers with two functions: opts.open and opts.save | 
 |  |  |     // opts.open's responsibilities are: | 
 |  |  |     //  - invoke a file chooser dialog in 'open' mode | 
 |  |  |     //  - let user pick a SVG file | 
 |  |  |     //  - calls setCanvas.setSvgString() with the string contents of that file | 
 |  |  |     // opts.save's responsibilities are: | 
 |  |  |     //  - accept the string contents of the current document  | 
 |  |  |     //  - accept the string contents of the current document | 
 |  |  |     //  - invoke a file chooser dialog in 'save' mode | 
 |  |  |     //  - save the file to location chosen by the user | 
 |  |  |     Editor.setCustomHandlers = function(opts) { | 
 |  |  | 
 |  |  |         customHandlers = opts; | 
 |  |  |       }); | 
 |  |  |     } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     Editor.randomizeIds = function() { | 
 |  |  |       svgCanvas.randomizeIds(arguments) | 
 |  |  |     } | 
 |  |  | 
 |  |  |       $("body").toggleClass("touch", svgedit.browser.isTouch()); | 
 |  |  |       $("#canvas_width").val(curConfig.dimensions[0]); | 
 |  |  |       $("#canvas_height").val(curConfig.dimensions[1]); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var extFunc = function() { | 
 |  |  |         $.each(curConfig.extensions, function() { | 
 |  |  |           var extname = this; | 
 |  |  | 
 |  |  |           }); | 
 |  |  |         }); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Load extensions | 
 |  |  |       // Bit of a hack to run extensions in local Opera/IE9 | 
 |  |  |       if(document.location.protocol === 'file:') { | 
 |  |  | 
 |  |  |           'zoom':'zoom.png', | 
 |  |  |           'delete':'delete.png', | 
 |  |  |           'spapelib':'shapelib.png', | 
 |  |  |           'node_delete':'node_delete.png',         | 
 |  |  |           'node_delete':'node_delete.png', | 
 |  |  |           'align_left':'align-left.png', | 
 |  |  |           'align_center':'align-center.png', | 
 |  |  |           'align_right':'align-right.png', | 
 |  |  | 
 |  |  |           if (tleft.length != 0) { | 
 |  |  |             var min_height = tleft.offset().top + tleft.outerHeight(); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Look for any missing flyout icons from plugins | 
 |  |  |           $('.tools_flyout').each(function() { | 
 |  |  |             var shower = $('#' + this.id + '_show'); | 
 |  |  | 
 |  |  |             } | 
 |  |  |           }); | 
 |  |  |           methodDraw.runCallbacks(); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           setTimeout(function() { | 
 |  |  |             $('.flyout_arrow_horiz:empty').each(function() { | 
 |  |  |               $(this).append($.getSvgIcon('arrow_right').width(5).height(5)); | 
 |  |  | 
 |  |  |           }, 1); | 
 |  |  |         } | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#rulers').on("dblclick", function(e){ | 
 |  |  |         $("#base_unit_container").css({ | 
 |  |  |           top: e.pageY-10, | 
 |  |  | 
 |  |  |       $("#base_unit_container") | 
 |  |  |         .on("mouseleave mouseenter", function(e){ | 
 |  |  |           t = setTimeout(function(){$("#base_unit_container").fadeOut(500)}, 200) | 
 |  |  |           if(event.type == "mouseover") clearTimeout(t)   | 
 |  |  |           if(event.type == "mouseover") clearTimeout(t) | 
 |  |  |         }) | 
 |  |  |       $("#base_unit") | 
 |  |  |         .on("change", function(e) { | 
 |  |  | 
 |  |  |       Editor.canvas = svgCanvas = new $.SvgCanvas(document.getElementById("svgcanvas"), curConfig); | 
 |  |  |       Editor.show_save_warning = false; | 
 |  |  |       Editor.paintBox = {fill: null, stroke:null, canvas:null}; | 
 |  |  |       var palette = ["#444444", "#482816", "#422C10", "#3B2F0E", "#32320F",  | 
 |  |  |                      "#293414", "#1F361B", "#153723", "#0C372C",  | 
 |  |  |                      "#083734", "#0E353B", "#1A333F", "#273141",  | 
 |  |  |                      "#332D40", "#3E2A3C", "#462735", "#4B252D",  | 
 |  |  |                      "#4D2425", "#4C261D", "#666666", "#845335", "#7B572D",  | 
 |  |  |                      "#6F5C2A", "#62612C", "#546433", "#46673D",  | 
 |  |  |                      "#396849", "#306856", "#2D6862", "#33666C",  | 
 |  |  |                      "#426373", "#535F75", "#645A73", "#74556D",  | 
 |  |  |                      "#805064", "#884D58", "#8B4D4B", "#894F3F",  | 
 |  |  |                      "#999999", "#C48157", "#B8874D", "#A98E49", "#97944B",  | 
 |  |  |                      "#849854", "#729C62", "#619E73", "#559E84",  | 
 |  |  |                      "#529D94", "#5B9BA2", "#6D97AB", "#8391AE",  | 
 |  |  |                      "#9A8AAB", "#AF84A3", "#BF7E96", "#C97A86",  | 
 |  |  |                      "#CE7975", "#CC7C65", "#BBBBBB", "#FFB27C", "#FABA6F",  | 
 |  |  |       var palette = ["#444444", "#482816", "#422C10", "#3B2F0E", "#32320F", | 
 |  |  |                      "#293414", "#1F361B", "#153723", "#0C372C", | 
 |  |  |                      "#083734", "#0E353B", "#1A333F", "#273141", | 
 |  |  |                      "#332D40", "#3E2A3C", "#462735", "#4B252D", | 
 |  |  |                      "#4D2425", "#4C261D", "#666666", "#845335", "#7B572D", | 
 |  |  |                      "#6F5C2A", "#62612C", "#546433", "#46673D", | 
 |  |  |                      "#396849", "#306856", "#2D6862", "#33666C", | 
 |  |  |                      "#426373", "#535F75", "#645A73", "#74556D", | 
 |  |  |                      "#805064", "#884D58", "#8B4D4B", "#894F3F", | 
 |  |  |                      "#999999", "#C48157", "#B8874D", "#A98E49", "#97944B", | 
 |  |  |                      "#849854", "#729C62", "#619E73", "#559E84", | 
 |  |  |                      "#529D94", "#5B9BA2", "#6D97AB", "#8391AE", | 
 |  |  |                      "#9A8AAB", "#AF84A3", "#BF7E96", "#C97A86", | 
 |  |  |                      "#CE7975", "#CC7C65", "#BBBBBB", "#FFB27C", "#FABA6F", | 
 |  |  |                      "#E6C36A", "#CFCA6D", "#B8D078", "#A0D58A", | 
 |  |  |                      "#8CD79F", "#7DD8B5", "#7AD6CA", "#84D3DB",  | 
 |  |  |                      "#9ACEE6", "#B6C7EA", "#D3BEE7", "#EDB6DC",  | 
 |  |  |                      "#FFAFCC", "#FFAAB8", "#FFA9A2", "#FFAC8D",  | 
 |  |  |                      "#DDDDDD", "#FFE7A2", "#FFF093", "#FFFA8D", "#FFFF91",  | 
 |  |  |                      "#EEFF9F", "#D1FFB4", "#B9FFCE", "#A8FFE9",  | 
 |  |  |                      "#A4FFFF", "#B1FFFF", "#CBFFFF", "#EDFFFF",  | 
 |  |  |                      "#FFF5FF", "#FFEBFF", "#FFE2FF", "#FFDCEC",  | 
 |  |  |                      "#8CD79F", "#7DD8B5", "#7AD6CA", "#84D3DB", | 
 |  |  |                      "#9ACEE6", "#B6C7EA", "#D3BEE7", "#EDB6DC", | 
 |  |  |                      "#FFAFCC", "#FFAAB8", "#FFA9A2", "#FFAC8D", | 
 |  |  |                      "#DDDDDD", "#FFE7A2", "#FFF093", "#FFFA8D", "#FFFF91", | 
 |  |  |                      "#EEFF9F", "#D1FFB4", "#B9FFCE", "#A8FFE9", | 
 |  |  |                      "#A4FFFF", "#B1FFFF", "#CBFFFF", "#EDFFFF", | 
 |  |  |                      "#FFF5FF", "#FFEBFF", "#FFE2FF", "#FFDCEC", | 
 |  |  |                      "#FFDBD2", "#FFDFB8" | 
 |  |  |                  ], | 
 |  |  |         isMac = (navigator.platform.indexOf("Mac") >= 0), | 
 |  |  | 
 |  |  |         default_img_url = curConfig.imgPath + "placeholder.svg", | 
 |  |  |         workarea = $("#workarea"), | 
 |  |  |         canv_menu = $("#cmenu_canvas"), | 
 |  |  |         exportWindow = null,  | 
 |  |  |         exportWindow = null, | 
 |  |  |         tool_scale = 1, | 
 |  |  |         ui_context = 'toolbars', | 
 |  |  |         orig_source = ''; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |  | 
 |  |  |       // This puts the correct shortcuts in the menus | 
 |  |  |       if (!isMac) { | 
 |  |  |        $('.shortcut').each(function(){ | 
 |  |  |          var text = $(this).text(); | 
 |  |  |          $(this).text(text.split("⌘").join("Ctrl+")) | 
 |  |  |        });  | 
 |  |  |        }); | 
 |  |  |       } | 
 |  |  |  | 
 |  |  |       // This sets up alternative dialog boxes. They mostly work the same way as | 
 |  |  |       // their UI counterparts, expect instead of returning the result, a callback | 
 |  |  |       // needs to be included that returns the result as its first parameter. | 
 |  |  |       // In the future we may want to add additional types of dialog boxes, since  | 
 |  |  |       // In the future we may want to add additional types of dialog boxes, since | 
 |  |  |       // they should be easy to handle this way. | 
 |  |  |       (function() { | 
 |  |  |         $('#dialog_container').draggable({cancel:'#dialog_content, #dialog_buttons *', containment: 'window'}); | 
 |  |  |         var box = $('#dialog_box'), btn_holder = $('#dialog_buttons'); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var dbox = function(type, msg, callback, defText) { | 
 |  |  |           $('#dialog_content').html('<p>'+msg.replace(/\n/g,'</p><p>')+'</p>') | 
 |  |  |             .toggleClass('prompt',(type=='prompt')); | 
 |  |  |           btn_holder.empty(); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var ok = $('<input type="button" value="' + uiStrings.common.ok + '">').appendTo(btn_holder); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |           if(type != 'alert') { | 
 |  |  |             $('<input type="button" value="' + uiStrings.common.cancel + '">') | 
 |  |  |               .appendTo(btn_holder) | 
 |  |  |               .on("click touchstart", function() { box.hide();callback(false)}); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(type == 'prompt') { | 
 |  |  |             var input = $('<input type="text">').prependTo(btn_holder); | 
 |  |  |             input.val(defText || ''); | 
 |  |  |             input.bind('keydown', 'return', function() {ok.trigger("click touchstart");}); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(type == 'process') { | 
 |  |  |             ok.hide(); | 
 |  |  |           } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |           box.show(); | 
 |  |  |            | 
 |  |  |           ok.on("click touchstart", function() {  | 
 |  |  |  | 
 |  |  |           ok.on("click touchstart", function() { | 
 |  |  |             box.hide(); | 
 |  |  |             var resp = (type == 'prompt')?input.val():true; | 
 |  |  |             if(callback) callback(resp); | 
 |  |  |           }).focus(); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(type == 'prompt') input.focus(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $.alert = function(msg, cb) { dbox('alert', msg, cb);}; | 
 |  |  |         $.confirm = function(msg, cb) { dbox('confirm', msg, cb);}; | 
 |  |  |         $.process_cancel = function(msg, cb) {  dbox('process', msg, cb);}; | 
 |  |  |         $.prompt = function(msg, txt, cb) { dbox('prompt', msg, cb, txt);}; | 
 |  |  |       }()); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var setSelectMode = function() { | 
 |  |  |         var curr = $('.tool_button_current'); | 
 |  |  |         if(curr.length && curr[0].id !== 'tool_select') { | 
 |  |  | 
 |  |  |         } | 
 |  |  |         svgCanvas.setMode('select'); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var setEyedropperMode = function() { | 
 |  |  |         var curr = $('.tool_button_current'); | 
 |  |  |         if(curr.length && curr[0].id !== 'tool_eyedropper') { | 
 |  |  | 
 |  |  |         } | 
 |  |  |         svgCanvas.setMode('eyedropper'); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var togglePathEditMode = function(editmode, elems) { | 
 |  |  |         $('#tools_bottom_2,#tools_bottom_3').toggle(!editmode); | 
 |  |  |         if(editmode) { | 
 |  |  | 
 |  |  |             selector.reset(elems[0]); | 
 |  |  |             selector.selectorRect.setAttribute('display', 'inline'); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           setIcon('#tool_select', 'select'); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       // used to make the flyouts stay on the screen longer the very first time | 
 |  |  |       var flyoutspeed = 1250; | 
 |  |  |       var textBeingEntered = false; | 
 |  |  | 
 |  |  |       var docprops = false; | 
 |  |  |       var preferences = false; | 
 |  |  |       var cur_context = ''; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var saveHandler = function(window,svg) { | 
 |  |  |         Editor.show_save_warning = false; | 
 |  |  |        | 
 |  |  |         // by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs)  | 
 |  |  |  | 
 |  |  |         // by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs) | 
 |  |  |         // can just provide their own custom save handler and might not want the XML prolog | 
 |  |  |         svg = '<?xml version="1.0"?>\n' + svg; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         // Opens the SVG in new window, with warning about Mozilla bug #308590 when applicable | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var ua = navigator.userAgent; | 
 |  |  |  | 
 |  |  |         // Chrome 5 (and 6?) don't allow saving, show source instead ( http://code.google.com/p/chromium/issues/detail?id=46735 ) | 
 |  |  |         // IE9 doesn't allow standalone Data URLs ( https://connect.microsoft.com/IE/feedback/details/542600/data-uri-images-fail-when-loaded-by-themselves ) | 
 |  |  |         if(~ua.indexOf('MSIE')) { | 
 |  |  |           showSourceEditor(0,true); | 
 |  |  |           return;  | 
 |  |  |           return; | 
 |  |  |         } | 
 |  |  |         var win = window.open("data:image/svg+xml;base64," + Utils.encode64(svg)); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         // Alert will only appear the first time saved OR the first time the bug is encountered | 
 |  |  |         var done = $.pref('save_notice_done'); | 
 |  |  |         if(done !== "all") { | 
 |  |  |      | 
 |  |  |  | 
 |  |  |           var note = uiStrings.notification.saveFromBrowser.replace('%s', 'SVG'); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Check if FF and has <defs/> | 
 |  |  |           if(ua.indexOf('Gecko/') !== -1) { | 
 |  |  |             if(svg.indexOf('<defs') !== -1) { | 
 |  |  | 
 |  |  |               $.pref('save_notice_done', 'part'); | 
 |  |  |             } | 
 |  |  |           } else { | 
 |  |  |             $.pref('save_notice_done', 'all');  | 
 |  |  |             $.pref('save_notice_done', 'all'); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(done !== 'part') { | 
 |  |  |             win.alert(note); | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var exportHandler = function(window, data) { | 
 |  |  |         var issues = data.issues; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(!$('#export_canvas').length) { | 
 |  |  |           $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body'); | 
 |  |  |         } | 
 |  |  |         var c = $('#export_canvas')[0]; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         c.width = svgCanvas.contentW; | 
 |  |  |         c.height = svgCanvas.contentH; | 
 |  |  |         canvg(c, data.svg, {renderCallback: function() { | 
 |  |  | 
 |  |  |           var done = $.pref('export_notice_done'); | 
 |  |  |           if(done !== "all") { | 
 |  |  |             var note = uiStrings.notification.saveFromBrowser.replace('%s', 'PNG'); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // Check if there's issues | 
 |  |  |             if(issues.length) { | 
 |  |  |               var pre = "\n \u2022 "; | 
 |  |  |               note += ("\n\n" + uiStrings.notification.noteTheseIssues + pre + issues.join(pre)); | 
 |  |  |             }  | 
 |  |  |              | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // Note that this will also prevent the notice even though new issues may appear later. | 
 |  |  |             // May want to find a way to deal with that without annoying the user | 
 |  |  |             $.pref('export_notice_done', 'all');  | 
 |  |  |             $.pref('export_notice_done', 'all'); | 
 |  |  |             exportWindow.alert(note); | 
 |  |  |           } | 
 |  |  |         }}); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // called when we've selected a different element | 
 |  |  |       var selectedChanged = function(window,elems) {         | 
 |  |  |       var selectedChanged = function(window,elems) { | 
 |  |  |         var mode = svgCanvas.getMode(); | 
 |  |  |         if(mode === "select") setSelectMode(); | 
 |  |  |         if (mode === "pathedit") return updateContextPanel(); | 
 |  |  | 
 |  |  |           multiselected: multiselected | 
 |  |  |         }); | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       // Call when part of element is in process of changing, generally | 
 |  |  |       // on mousemove actions like rotate, move, etc. | 
 |  |  |       var elementTransition = function(window,elems) { | 
 |  |  |         var mode = svgCanvas.getMode(); | 
 |  |  |         var elem = elems[0]; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(!elem) return; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         multiselected = (elems.length >= 2 && elems[1] != null) ? elems : null; | 
 |  |  |         // Only updating fields for single elements for now | 
 |  |  |         if(!multiselected) { | 
 |  |  | 
 |  |  |               rotateCursor(ang); | 
 |  |  |               $('#tool_reorient').toggleClass('disabled', ang == 0); | 
 |  |  |               break; | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // TODO: Update values that change on move/resize, etc | 
 |  |  | //            case "select": | 
 |  |  | //            case "resize": | 
 |  |  | 
 |  |  |           elems: elems | 
 |  |  |         }); | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       // called when any element has changed | 
 |  |  |       var elementChanged = function(window,elems) { | 
 |  |  |         var mode = svgCanvas.getMode(); | 
 |  |  |         if(mode === "select") { | 
 |  |  |           setSelectMode(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         for (var i = 0; i < elems.length; ++i) { | 
 |  |  |           var elem = elems[i]; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // if the element changed was the svg, then it could be a resolution change | 
 |  |  |           if (elem && elem.tagName === "svg") { | 
 |  |  |             //populateLayers(); | 
 |  |  |             updateCanvas(); | 
 |  |  |           }  | 
 |  |  |           } | 
 |  |  |           // Update selectedElement if element is no longer part of the image. | 
 |  |  |           // This occurs for the text elements in Firefox | 
 |  |  |           else if(elem && selectedElement && selectedElement.parentNode == null) { | 
 |  |  | 
 |  |  |             selectedElement = elem; | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         Editor.show_save_warning = true; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         // we update the contextual panel with potentially new | 
 |  |  |         // positional/sizing information (we DON'T want to update the | 
 |  |  |         // toolbar here as that creates an infinite loop) | 
 |  |  |         // also this updates the history buttons | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         // we tell it to skip focusing the text control if the | 
 |  |  |         // text element was previously in focus | 
 |  |  |         updateContextPanel(); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         // In the event a gradient was flipped: | 
 |  |  |         if(selectedElement && mode === "select") { | 
 |  |  |           Editor.paintBox.fill.update(); | 
 |  |  |           Editor.paintBox.stroke.update(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         svgCanvas.runExtensions("elementChanged", { | 
 |  |  |           elems: elems | 
 |  |  |         }); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var zoomChanged = function(window, bbox, autoCenter) { | 
 |  |  |         var scrbar = 15, | 
 |  |  |           res = svgCanvas.getResolution(), | 
 |  |  | 
 |  |  |         if(!z_info) return; | 
 |  |  |         var zoomlevel = z_info.zoom, | 
 |  |  |           bb = z_info.bbox; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(zoomlevel < .001) { | 
 |  |  |           changeZoom({value: .1}); | 
 |  |  |           return; | 
 |  |  | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |         animateZoom() | 
 |  |  |          | 
 |  |  |          | 
 |  |  |          | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //if(autoCenter) { | 
 |  |  |         //  updateCanvas(); | 
 |  |  |         //} else { | 
 |  |  |         //  updateCanvas(false, {x: bb.x * zoomlevel + (bb.width * zoomlevel)/2, y: bb.y * zoomlevel + (bb.height * zoomlevel)/2}); | 
 |  |  |         //} | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         if(svgCanvas.getMode() == 'zoom' && bb.width) { | 
 |  |  |           // Go to select if a zoom box was drawn | 
 |  |  |           setSelectMode(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         zoomDone(); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#cur_context_panel').delegate('a', 'click', function() { | 
 |  |  |         var link = $(this); | 
 |  |  |         if(link.attr('data-root')) { | 
 |  |  | 
 |  |  |         svgCanvas.clearSelection(); | 
 |  |  |         return false; | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var contextChanged = function(win, context) { | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var link_str = ''; | 
 |  |  |         if(context) { | 
 |  |  |           var str = ''; | 
 |  |  |           link_str = '<a href="#" data-root="y">' + svgCanvas.getCurrentDrawing().getCurrentLayerName() + '</a>'; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           $(context).parentsUntil('#svgcontent > g').andSelf().each(function() { | 
 |  |  |             if(this.id) { | 
 |  |  |               str += ' > ' + this.id; | 
 |  |  | 
 |  |  |         $('#cur_context_panel').toggle(!!context).html(link_str); | 
 |  |  |  | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Makes sure the current selected paint is available to work with | 
 |  |  |       var prepPaints = function() { | 
 |  |  |         Editor.paintBox.fill.prep(); | 
 |  |  |         Editor.paintBox.stroke.prep(); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var flyout_funcs = {}; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var setupFlyouts = function(holders) { | 
 |  |  |         $.each(holders, function(hold_sel, btn_opts) { | 
 |  |  |           var buttons = $(hold_sel).children(); | 
 |  |  | 
 |  |  |             .each(function(i) { | 
 |  |  |               // Get this buttons options | 
 |  |  |               var opts = btn_opts[i]; | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               // Remember the function that goes with this ID | 
 |  |  |               flyout_funcs[opts.sel] = opts.fn; | 
 |  |  |  | 
 |  |  | 
 |  |  |                 var options = opts; | 
 |  |  |                 //find the currently selected tool if comes from keystroke | 
 |  |  |                 if (event.type === "keydown") { | 
 |  |  |                   var flyoutIsSelected = $(options.parent + "_show").hasClass('tool_button_current');  | 
 |  |  |                   var flyoutIsSelected = $(options.parent + "_show").hasClass('tool_button_current'); | 
 |  |  |                   var currentOperation = $(options.parent + "_show").attr("data-curopt"); | 
 |  |  |                   $.each(holders[opts.parent], function(i, tool){ | 
 |  |  |                     if (tool.sel == currentOperation) { | 
 |  |  | 
 |  |  |             // Set first as default | 
 |  |  |             shower.attr('data-curopt', btn_opts[0].sel); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var timer; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var pos = $(show_sel).position(); | 
 |  |  |           $(hold_sel).css({'left': pos.left+34, 'top': pos.top+77}); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Clicking the "show" icon should set the current mode | 
 |  |  |           shower.mousedown(function(evt) { | 
 |  |  |             $('#workarea').one("mousedown", function(){$('#tools_shapelib').hide()}) | 
 |  |  | 
 |  |  |               flyout_funcs[opt](); | 
 |  |  |             } | 
 |  |  |           }); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           //  $('#tools_rect').mouseleave(function(){$('#tools_rect').fadeOut();}); | 
 |  |  |         }); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         setFlyoutTitles(); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var makeFlyoutHolder = function(id, child) { | 
 |  |  |         var div = $('<div>',{ | 
 |  |  |           'class': 'tools_flyout', | 
 |  |  |           id: id | 
 |  |  |         }).appendTo('#svg_editor').append(child); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         return div; | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var setFlyoutPositions = function() { | 
 |  |  |         $('.tools_flyout').each(function() { | 
 |  |  |           var shower = $('#' + this.id + '_show'); | 
 |  |  | 
 |  |  |           $(this).css({left: (pos.left + w)*tool_scale, top: pos.top}); | 
 |  |  |         }); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var setFlyoutTitles = function() { | 
 |  |  |         $('.tools_flyout').each(function() { | 
 |  |  |           var shower = $('#' + this.id + '_show'); | 
 |  |  |           if(shower.data('isLibrary')) return; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var tooltips = []; | 
 |  |  |           $(this).children().each(function() { | 
 |  |  |             tooltips.push(this.title); | 
 |  |  | 
 |  |  |         }); | 
 |  |  |       } | 
 |  |  |  | 
 |  |  |       var resize_timer;      | 
 |  |  |        | 
 |  |  |       var resize_timer; | 
 |  |  |  | 
 |  |  |       var extAdded = function(window, ext) { | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         var cb_called = false; | 
 |  |  |         var resize_done = false; | 
 |  |  |         var cb_ready = true; // Set to false to delay callback (e.g. wait for $.svgIcons) | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         function prepResize() { | 
 |  |  |           if(resize_timer) { | 
 |  |  |             clearTimeout(resize_timer); | 
 |  |  | 
 |  |  |             resize_timer = setTimeout(function() { | 
 |  |  |               resize_done = true; | 
 |  |  |               setIconSize(curPrefs.iconsize); | 
 |  |  |             }, 50);  | 
 |  |  |             }, 50); | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var runCallback = function() { | 
 |  |  |           if(ext.callback && !cb_called && cb_ready) { | 
 |  |  |             cb_called = true; | 
 |  |  |             ext.callback(); | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         var btn_selects = []; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         if(ext.context_tools) { | 
 |  |  |           $.each(ext.context_tools, function(i, tool) { | 
 |  |  |             // Add select tool | 
 |  |  |             var cont_id = tool.container_id?(' id="' + tool.container_id + '"'):""; | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             var panel = $('#' + tool.panel); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // create the panel if it doesn't exist | 
 |  |  |             if(!panel.length) | 
 |  |  |               panel = $('<div>', {id: tool.panel}).appendTo("#tools_top").hide(); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // TODO: Allow support for other types, or adding to existing tool | 
 |  |  |             switch (tool.type) { | 
 |  |  |             case 'tool_button': | 
 |  |  | 
 |  |  |               html += "</select></label>"; | 
 |  |  |               // Creates the tool, hides & adds it, returns the select element | 
 |  |  |               var sel = $(html).appendTo(panel).find('select'); | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               $.each(tool.events, function(evt, func) { | 
 |  |  |                 $(sel).bind(evt, func); | 
 |  |  |               }); | 
 |  |  |               break; | 
 |  |  |             case 'button-select':  | 
 |  |  |             case 'button-select': | 
 |  |  |               var html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">' | 
 |  |  |                 + '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button></div>'; | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               var list = $('<ul id="' + tool.id + '_opts"></ul>').appendTo('#option_lists'); | 
 |  |  |               if(tool.colnum) { | 
 |  |  |                 list.addClass('optcols' + tool.colnum); | 
 |  |  |               } | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               // Creates the tool, hides & adds it, returns the select element | 
 |  |  |               var dropdown = $(html).appendTo(panel).children(); | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               btn_selects.push({ | 
 |  |  |                 elem: ('#' + tool.id), | 
 |  |  |                 list: ('#' + tool.id + '_opts'), | 
 |  |  | 
 |  |  |               break; | 
 |  |  |             case 'input': | 
 |  |  |               var html = '<label' + cont_id + '>' | 
 |  |  |                 + '<span id="' + tool.id + '_label">'  | 
 |  |  |                 + '<span id="' + tool.id + '_label">' | 
 |  |  |                 + tool.label + ':</span>' | 
 |  |  |                 + '<input id="' + tool.id + '" title="' + tool.title | 
 |  |  |                 + '" size="' + (tool.size || "4") + '" value="' + (tool.defval || "") + '" type="text"/></label>' | 
 |  |  |                  | 
 |  |  |  | 
 |  |  |               // Creates the tool, hides & adds it, returns the select element | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               // Add to given tool.panel | 
 |  |  |               var inp = $(html).appendTo(panel).find('input'); | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               if(tool.spindata) { | 
 |  |  |                 inp.SpinButton(tool.spindata); | 
 |  |  |               } | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               if(tool.events) { | 
 |  |  |                 $.each(tool.events, function(evt, func) { | 
 |  |  |                   inp.bind(evt, func); | 
 |  |  |                 }); | 
 |  |  |               } | 
 |  |  |               break; | 
 |  |  |                | 
 |  |  |  | 
 |  |  |             default: | 
 |  |  |               break; | 
 |  |  |             } | 
 |  |  |           }); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(ext.buttons) { | 
 |  |  |           var fallback_obj = {}, | 
 |  |  |             placement_obj = {}, | 
 |  |  |             svgicons = ext.svgicons; | 
 |  |  |           var holders = {}; | 
 |  |  |            | 
 |  |  |          | 
 |  |  |  | 
 |  |  |  | 
 |  |  |           // Add buttons given by extension | 
 |  |  |           $.each(ext.buttons, function(i, btn) { | 
 |  |  |             var icon; | 
 |  |  | 
 |  |  |                 placement_obj['#' + id] = svgicon; | 
 |  |  |               } | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             var cls, parent; | 
 |  |  |              | 
 |  |  |              | 
 |  |  |              | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             // Set button up according to its type | 
 |  |  |             switch ( btn.type ) { | 
 |  |  |             case 'mode_flyout': | 
 |  |  | 
 |  |  |                 $('<div>', {id: btn.panel}).appendTo("#tools_top"); | 
 |  |  |               break; | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             var button = $((btn.list || btn.type == 'app_menu')?'<li/>':'<div/>') | 
 |  |  |               .attr("id", id) | 
 |  |  |               .attr("title", btn.title) | 
 |  |  | 
 |  |  |   //              var opts = btn.includeWith; | 
 |  |  |   //              // opts.button, default, position | 
 |  |  |                 var ref_btn = $(button); | 
 |  |  |                  | 
 |  |  |  | 
 |  |  |                 var flyout_holder = ref_btn.parent(); | 
 |  |  |                 // Create a flyout menu if there isn't one already | 
 |  |  |                 if(!ref_btn.parent().hasClass('tools_flyout')) { | 
 |  |  | 
 |  |  |                   var show_btn = ref_btn.clone() | 
 |  |  |                     .attr('id',tls_id + '_show') | 
 |  |  |                     .append($('<div>',{'class':'flyout_arrow_horiz'})); | 
 |  |  |                      | 
 |  |  |  | 
 |  |  |                   ref_btn.before(show_btn); | 
 |  |  |                  | 
 |  |  |  | 
 |  |  |                   // Create a flyout div | 
 |  |  |                   flyout_holder = makeFlyoutHolder(tls_id, ref_btn); | 
 |  |  |                   flyout_holder.data('isLibrary', true); | 
 |  |  |                   show_btn.data('isLibrary', true); | 
 |  |  |                 }  | 
 |  |  |                  | 
 |  |  |                  | 
 |  |  |                  | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |   //              var ref_data = Actions.getButtonData(opts.button); | 
 |  |  |                  | 
 |  |  |  | 
 |  |  |                 placement_obj['#' + tls_id + '_show'] = btn.id; | 
 |  |  |                 // TODO: Find way to set the current icon using the iconloader if this is not default | 
 |  |  |                  | 
 |  |  |  | 
 |  |  |                 // Include data for extension button as well as ref button | 
 |  |  |                 var cur_h = holders['#'+flyout_holder[0].id] = [{ | 
 |  |  |                   sel: '#'+id, | 
 |  |  | 
 |  |  |               } else if(btn.type == 'app_menu' || btn.type == 'menu') { | 
 |  |  |                 button.append(btn.title); | 
 |  |  |               } | 
 |  |  |                | 
 |  |  |  | 
 |  |  |             } else if(btn.list) { | 
 |  |  |               // Add button to list | 
 |  |  |               button.addClass('push_button'); | 
 |  |  | 
 |  |  |               var opts = btn.includeWith; | 
 |  |  |               // opts.button, default, position | 
 |  |  |               var ref_btn = $(opts.button); | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               var flyout_holder = ref_btn.parent(); | 
 |  |  |               // Create a flyout menu if there isn't one already | 
 |  |  |               if(!ref_btn.parent().hasClass('tools_flyout')) { | 
 |  |  | 
 |  |  |                 var show_btn = ref_btn.clone() | 
 |  |  |                   .attr('id',tls_id + '_show') | 
 |  |  |                   .append($('<div>',{'class':'flyout_arrow_horiz'})); | 
 |  |  |                    | 
 |  |  |  | 
 |  |  |                 ref_btn.before(show_btn); | 
 |  |  |                | 
 |  |  |  | 
 |  |  |                 // Create a flyout div | 
 |  |  |                 flyout_holder = makeFlyoutHolder(tls_id, ref_btn); | 
 |  |  |               }  | 
 |  |  |                | 
 |  |  |               } | 
 |  |  |  | 
 |  |  |               var ref_data = Actions.getButtonData(opts.button); | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               if(opts.isDefault) { | 
 |  |  |                 placement_obj['#' + tls_id + '_show'] = btn.id; | 
 |  |  |               }  | 
 |  |  |               } | 
 |  |  |               // TODO: Find way to set the current icon using the iconloader if this is not default | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               // Include data for extension button as well as ref button | 
 |  |  |               var cur_h = holders['#'+flyout_holder[0].id] = [{ | 
 |  |  |                 sel: '#'+id, | 
 |  |  | 
 |  |  |                 key: btn.key, | 
 |  |  |                 isDefault: btn.includeWith?btn.includeWith.isDefault:0 | 
 |  |  |               }, ref_data]; | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} | 
 |  |  |                  | 
 |  |  |  | 
 |  |  |               var pos  = ("position" in opts)?opts.position:'last'; | 
 |  |  |               var len = flyout_holder.children().length; | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               // Add at given position or end | 
 |  |  |               if(!isNaN(pos) && pos >= 0 && pos < len) { | 
 |  |  |                 flyout_holder.children().eq(pos).before(button); | 
 |  |  | 
 |  |  |                 flyout_holder.append(button); | 
 |  |  |                 cur_h.reverse(); | 
 |  |  |               } | 
 |  |  |             }  | 
 |  |  |              | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if(!svgicons) { | 
 |  |  |               button.append(icon); | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             if(!btn.list) { | 
 |  |  |               // Add given events to button | 
 |  |  |               $.each(btn.events, function(name, func) { | 
 |  |  | 
 |  |  |             } | 
 |  |  |             setupFlyouts(holders); | 
 |  |  |           }); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           $.each(btn_selects, function() { | 
 |  |  |             addAltDropDown(this.elem, this.list, this.callback, {seticon: true});  | 
 |  |  |             addAltDropDown(this.elem, this.list, this.callback, {seticon: true}); | 
 |  |  |           }); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if (svgicons) | 
 |  |  |             cb_ready = false; // Delay callback | 
 |  |  |  | 
 |  |  | 
 |  |  |               cb_ready = true; // Ready for callback | 
 |  |  |               runCallback(); | 
 |  |  |             } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |           }); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         runCallback(); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var getPaint = function(color, opac, type) { | 
 |  |  |         // update the editor's fill paint | 
 |  |  |         var opts = null; | 
 |  |  | 
 |  |  |           } else { | 
 |  |  |             refElem =  $("#" + type + "_color defs *")[0]; | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           opts = { alpha: opac }; | 
 |  |  |           opts[refElem.tagName] = refElem; | 
 |  |  |         }  | 
 |  |  |         } | 
 |  |  |         else if (color.indexOf("#") === 0) { | 
 |  |  |           opts = { | 
 |  |  |             alpha: opac, | 
 |  |  | 
 |  |  |           }; | 
 |  |  |         } | 
 |  |  |         return new $.jGraduate.Paint(opts); | 
 |  |  |       };   | 
 |  |  |        | 
 |  |  |       }; | 
 |  |  |  | 
 |  |  |       // set the canvas properties at init | 
 |  |  |       var res = svgCanvas.getResolution(); | 
 |  |  |       if(curConfig.baseUnit !== "px") { | 
 |  |  |         res.w = svgedit.units.convertUnit(res.w) + curConfig.baseUnit; | 
 |  |  |         res.h = svgedit.units.convertUnit(res.h) + curConfig.baseUnit; | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var createBackground = function(fill) { | 
 |  |  |         svgCanvas.createLayer("background") | 
 |  |  |         cur_shape = svgCanvas.addSvgElementFromJson({ | 
 |  |  | 
 |  |  |         svgCanvas.setCurrentLayer("Layer 1") | 
 |  |  |         svgCanvas.setCurrentLayerPosition("1") | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // create a new layer background if it doesn't exist | 
 |  |  |       if (!document.getElementById('canvas_background')) createBackground(); | 
 |  |  |       var fill = document.getElementById('canvas_background').getAttribute("fill"); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // updates the toolbar (colors, opacity, etc) based on the selected element | 
 |  |  |       // This function also updates the opacity and id elements that are in the context panel | 
 |  |  |       var updateToolbar = function() { | 
 |  |  | 
 |  |  |           case 'a': | 
 |  |  |             // Look for common styles | 
 |  |  |             var gWidth = null; | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             var childs = selectedElement.getElementsByTagName('*'); | 
 |  |  |             for(var i = 0, len = childs.length; i < len; i++) { | 
 |  |  |               var swidth = childs[i].getAttribute("stroke-width"); | 
 |  |  | 
 |  |  |                 gWidth = null; | 
 |  |  |               } | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             $('#stroke_width').val(gWidth === null ? "0" : gWidth); | 
 |  |  |             updateContextPanel(); | 
 |  |  |             break; | 
 |  |  | 
 |  |  |             //removed because multiselect shouldnt set color | 
 |  |  |             //Editor.paintBox.fill.update(false); | 
 |  |  |             //Editor.paintBox.stroke.update(false); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             $('#stroke_width').val(selectedElement.getAttribute("stroke-width") || 0); | 
 |  |  |             var dash = selectedElement.getAttribute("stroke-dasharray") || "none" | 
 |  |  |             $('option', '#stroke_style').removeAttr('selected'); | 
 |  |  | 
 |  |  |             $.fn.dragInput.updateCursor($('#stroke_width')[0]) | 
 |  |  |             $.fn.dragInput.updateCursor($('#blur')[0]) | 
 |  |  |           } | 
 |  |  |    | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         // All elements including image and group have opacity | 
 |  |  |         if(selectedElement != null) { | 
 |  |  |           var opac_perc = ((selectedElement.getAttribute("opacity")||1.0)*100); | 
 |  |  | 
 |  |  |           $.fn.dragInput.updateCursor($('#group_opacity')[0]) | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var setImageURL = Editor.setImageURL = function(url) { | 
 |  |  |         if(!url) url = default_img_url; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         svgCanvas.setImageURL(url); | 
 |  |  |         $('#image_url').val(url); | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var setInputWidth = function(elem) { | 
 |  |  |         var w = Math.min(Math.max(12 + elem.value.length * 6, 50), 300); | 
 |  |  |         $(elem).width(w); | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       // updates the context panel tools based on the selected element | 
 |  |  |       var updateContextPanel = function(e) { | 
 |  |  |       var elem = selectedElement; | 
 |  |  |         // If element has just been deleted, consider it null | 
 |  |  |         if(elem != null && !elem.parentNode) elem = null; | 
 |  |  |         if (multiselected && multiselected[0] != null && !multiselected[0].parentNode) multiselected = false; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName(); | 
 |  |  |         var currentMode = svgCanvas.getMode(); | 
 |  |  |         var unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null; | 
 |  |  |         var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if (is_node) { | 
 |  |  |           $('.context_panel').hide(); | 
 |  |  |           $('#path_node_panel').show(); | 
 |  |  | 
 |  |  |           var point = path.getNodePoint(); | 
 |  |  |           $('#tool_add_subpath').removeClass('push_button_pressed').addClass('tool_button'); | 
 |  |  |           $('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Show open/close button based on selected point | 
 |  |  |           setIcon('#tool_openclose_path', path.closed_subpath ? 'open_path' : 'close_path'); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(point) { | 
 |  |  |             var seg_type = $('#seg_type'); | 
 |  |  |             if(unit) { | 
 |  |  | 
 |  |  |               seg_type.val(4).attr('disabled','disabled'); | 
 |  |  |             } | 
 |  |  |           } | 
 |  |  |           $("#tools_top").removeClass("multiselected")         | 
 |  |  |           $("#tools_top").removeClass("multiselected") | 
 |  |  |           $("#stroke_panel").hide(); | 
 |  |  |           $("#canvas_panel").hide(); | 
 |  |  |           return; | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var menu_items = $('#cmenu_canvas li'); | 
 |  |  |         $('.context_panel').hide(); | 
 |  |  |         $('.menu_item', '#edit_menu').addClass('disabled'); | 
 |  |  |         $('.menu_item', '#object_menu').addClass('disabled'); | 
 |  |  |          | 
 |  |  |          | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         //hack to show the proper multialign box | 
 |  |  |         if (multiselected) { | 
 |  |  |           multiselected = multiselected.filter(Boolean); | 
 |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         if (!elem && !multiselected) { | 
 |  |  |           $("#tools_top").removeClass("multiselected")         | 
 |  |  |           $("#tools_top").removeClass("multiselected") | 
 |  |  |           $("#stroke_panel").hide(); | 
 |  |  |           $("#canvas_panel").show(); | 
 |  |  |         } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         if (elem != null) { | 
 |  |  |           $("#stroke_panel").show(); | 
 |  |  |           var elname = elem.nodeName; | 
 |  |  |           var angle = svgCanvas.getRotationAngle(elem); | 
 |  |  |           $('#angle').val(Math.round(angle)); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var blurval = svgCanvas.getBlur(elem); | 
 |  |  |           $('#blur').val(blurval); | 
 |  |  |           if(!is_node && currentMode != 'pathedit') { | 
 |  |  | 
 |  |  |                 y = bb.y; | 
 |  |  |               } | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             if(unit) { | 
 |  |  |               x = svgedit.units.convertUnit(x); | 
 |  |  |               y = svgedit.units.convertUnit(y); | 
 |  |  | 
 |  |  |               $("#path_x").val(Math.round(x)) | 
 |  |  |               $("#path_y").val(Math.round(y)) | 
 |  |  |             } | 
 |  |  |                        | 
 |  |  |  | 
 |  |  |             // Elements in this array cannot be converted to a path | 
 |  |  |             var no_path = ['image', 'text', 'path', 'g', 'use'].indexOf(elname) == -1; | 
 |  |  |             if (no_path) $('.action_path_convert_selected').removeClass('disabled'); | 
 |  |  |             if (elname === "path") $('.action_path_selected').removeClass('disabled'); | 
 |  |  |    | 
 |  |  |  | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var link_href = null; | 
 |  |  |           if (el_name === 'a') { | 
 |  |  |             link_href = svgCanvas.getHref(elem); | 
 |  |  |             $('#g_panel').show(); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(elem.parentNode.tagName === 'a') { | 
 |  |  |             if(!$(elem).siblings().length) { | 
 |  |  |               $('#a_panel').show(); | 
 |  |  |               link_href = svgCanvas.getHref(elem.parentNode); | 
 |  |  |             } | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Hide/show the make_link buttons | 
 |  |  |           $('#tool_make_link, #tool_make_link').toggle(!link_href); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(link_href) { | 
 |  |  |             $('#link_url').val(link_href); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // update contextual tools here | 
 |  |  |           var panels = { | 
 |  |  |             g: [], | 
 |  |  | 
 |  |  |             image: ['width','height', 'x', 'y'], | 
 |  |  |             circle: ['cx','cy','r'], | 
 |  |  |             ellipse: ['cx','cy','rx','ry'], | 
 |  |  |             line: ['x1','y1','x2','y2'],  | 
 |  |  |             line: ['x1','y1','x2','y2'], | 
 |  |  |             text: ['x', 'y'], | 
 |  |  |             'use': [], | 
 |  |  |             path : [] | 
 |  |  |           }; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var el_name = elem.tagName; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if($(elem).data('gsvg')) { | 
 |  |  |             $('#g_panel').show(); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if (el_name == "path" || el_name == "polyline") { | 
 |  |  |             $('#path_panel').show(); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(panels[el_name]) { | 
 |  |  |             var cur_panel = panels[el_name]; | 
 |  |  |             $('#' + el_name + '_panel').show(); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // corner radius has to live in a different panel | 
 |  |  |             // because otherwise it changes the position of the  | 
 |  |  |             // because otherwise it changes the position of the | 
 |  |  |             // of the elements | 
 |  |  |             if(el_name == "rect") $("#cornerRadiusLabel").show() | 
 |  |  |             else $("#cornerRadiusLabel").hide() | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             $.each(cur_panel, function(i, item) { | 
 |  |  |               var attrVal = elem.getAttribute(item); | 
 |  |  |               if(curConfig.baseUnit !== 'px' && elem[item]) { | 
 |  |  |                 var bv = elem[item].baseVal.value; | 
 |  |  |                 attrVal = svgedit.units.convertUnit(bv); | 
 |  |  |               } | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               //update the draginput cursors | 
 |  |  |               var name_item = document.getElementById(el_name + '_' + item); | 
 |  |  |               name_item.value = Math.round(attrVal) || 0; | 
 |  |  | 
 |  |  |                 $.fn.dragInput.updateCursor(name_item ); | 
 |  |  |               } | 
 |  |  |             }); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             if(el_name == 'text') { | 
 |  |  |               var font_family = elem.getAttribute("font-family"); | 
 |  |  |               var select = document.getElementById("font_family_dropdown"); | 
 |  |  |               select.selectedIndex = 3 | 
 |  |  |                | 
 |  |  |               $('#text_panel').css("display", "inline");   | 
 |  |  |  | 
 |  |  |               $('#text_panel').css("display", "inline"); | 
 |  |  |               $('#tool_italic').toggleClass('active', svgCanvas.getItalic()) | 
 |  |  |               $('#tool_bold').toggleClass('active', svgCanvas.getBold()) | 
 |  |  |               $('#font_family').val(font_family); | 
 |  |  | 
 |  |  |           menu_items[(el_name === 'g' ? 'en':'dis') + 'ableContextMenuItems']('#ungroup'); | 
 |  |  |           menu_items[((el_name === 'g' || !multiselected) ? 'dis':'en') + 'ableContextMenuItems']('#group'); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if (multiselected) { | 
 |  |  |           $('#multiselected_panel').show(); | 
 |  |  |           $('.action_multi_selected').removeClass('disabled'); | 
 |  |  |           menu_items | 
 |  |  |             .enableContextMenuItems('#group') | 
 |  |  |             .disableContextMenuItems('#ungroup'); | 
 |  |  |         }  | 
 |  |  |          | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         if (!elem) { | 
 |  |  |           menu_items.disableContextMenuItems('#delete,#cut,#copy,#group,#ungroup,#move_front,#move_up,#move_down,#move_back'); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         // update history buttons | 
 |  |  |         if (undoMgr.getUndoStackSize() > 0) { | 
 |  |  |           $('#tool_undo').removeClass( 'disabled'); | 
 |  |  | 
 |  |  |         else { | 
 |  |  |           $('#tool_redo').addClass( 'disabled'); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         svgCanvas.addedNew = false; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if ( (elem && !is_node) || multiselected) { | 
 |  |  |           // update the selected elements' layer | 
 |  |  |           $('#selLayerNames').removeAttr('disabled').val(currentLayerName); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Enable regular menu options | 
 |  |  |           canv_menu.enableContextMenuItems('#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       $('#text').on("focus", function(e){ textBeingEntered = true; } ); | 
 |  |  |       $('#text').on("blur", function(){ textBeingEntered = false; } ); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // bind the selected event to our function that handles updates to the UI | 
 |  |  |       svgCanvas.bind("selected", selectedChanged); | 
 |  |  |       svgCanvas.bind("transition", elementTransition); | 
 |  |  | 
 |  |  |       svgCanvas.bind("contextset", contextChanged); | 
 |  |  |       svgCanvas.bind("extension_added", extAdded); | 
 |  |  |       svgCanvas.textActions.setInputElem($("#text")[0]); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var str = '<div class="palette_item transparent" data-rgb="none"></div>\ | 
 |  |  |                 <div class="palette_item black" data-rgb="#000000"></div>\ | 
 |  |  |                 <div class="palette_item white" data-rgb="#ffffff"></div>' | 
 |  |  | 
 |  |  |         str += '<div class="palette_item" style="background-color: ' + item + ';" data-rgb="' + item + '"></div>'; | 
 |  |  |       }); | 
 |  |  |       $('#palette').append(str); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var changeFontSize = function(ctl) { | 
 |  |  |         svgCanvas.setFontSize(ctl.value); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var changeStrokeWidth = function(ctl) { | 
 |  |  |         var val = ctl.value; | 
 |  |  |         if(val == 0 && selectedElement && ['line', 'polyline'].indexOf(selectedElement.nodeName) >= 0) { | 
 |  |  | 
 |  |  |         } | 
 |  |  |         svgCanvas.setStrokeWidth(val); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       //cache | 
 |  |  |       var $indicator = $('#tool_angle_indicator') | 
 |  |  |       var $reorient = $('#tool_reorient') | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       rotateCursor = function(angle){ | 
 |  |  |         var rotate_string = 'rotate('+ angle + 'deg)' | 
 |  |  |         $indicator.css({ | 
 |  |  | 
 |  |  |           'transform': rotate_string | 
 |  |  |         }); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var changeRotationAngle = function(ctl) { | 
 |  |  |         var preventUndo = true; | 
 |  |  |         svgCanvas.setRotationAngle(ctl.value, preventUndo); | 
 |  |  |         rotateCursor(ctl.value) | 
 |  |  |         $('#tool_reorient').toggleClass('disabled', ctl.value == 0); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var changeZoom = function(ctl) { | 
 |  |  |         var zoomlevel = ctl.value / 100; | 
 |  |  |         if(zoomlevel < .001) { | 
 |  |  | 
 |  |  |           width: 0, | 
 |  |  |           height: 0, | 
 |  |  |           // center pt of scroll position | 
 |  |  |           x: (w_area[0].scrollLeft + w_area.width()/2)/zoom,  | 
 |  |  |           x: (w_area[0].scrollLeft + w_area.width()/2)/zoom, | 
 |  |  |           y: (w_area[0].scrollTop + w_area.height()/2)/zoom, | 
 |  |  |           zoom: zoomlevel | 
 |  |  |         }, true); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var changeBlur = function(ctl, completed) { | 
 |  |  |         val = ctl.value; | 
 |  |  |         $('#blur').val(val); | 
 |  |  | 
 |  |  |           svgCanvas.setBlurNoUndo(val); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var operaRepaint = function() { | 
 |  |  |         // Repaints canvas in Opera. Needed for stroke-dasharray change as well as fill change | 
 |  |  |         if(!window.opera) return; | 
 |  |  |         $('<p/>').hide().appendTo('body').remove(); | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       $('#stroke_style').change(function(){ | 
 |  |  |         svgCanvas.setStrokeAttr('stroke-dasharray', $(this).val()); | 
 |  |  |         $("#stroke_style_label").html(this.options[this.selectedIndex].text) | 
 |  |  |         operaRepaint(); | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#seg_type').change(function() { | 
 |  |  |         svgCanvas.setSegType($(this).val()); | 
 |  |  |         $("#seg_type_label").html(this.options[this.selectedIndex].text) | 
 |  |  |       }); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       // Lose focus for select elements when changed (Allows keyboard shortcuts to work better) | 
 |  |  |       $('select').change(function(){$(this).blur();}); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       $('#font_family').change(function() { | 
 |  |  |         svgCanvas.setFontFamily(this.value); | 
 |  |  |       }); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |       $('#text').keyup(function(){ | 
 |  |  |         svgCanvas.setTextContent(this.value); | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       changeAttribute = function(el, completed) { | 
 |  |  |         var attr = el.getAttribute("data-attr"); | 
 |  |  |         var multiplier = el.getAttribute("data-multiplier") || 1; | 
 |  |  | 
 |  |  |         //if (!noUndo) svgCanvas.changeSelectedAttribute(attr, val); | 
 |  |  |         svgCanvas.changeSelectedAttributeNoUndo(attr, val); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       picking = false; | 
 |  |  |       $(document).on("mouseup", function(){picking = false;}) | 
 |  |  |  | 
 |  |  | 
 |  |  |           var color = $(this).attr('data-rgb'); | 
 |  |  |           var paint = null; | 
 |  |  |           var noUndo = true; | 
 |  |  |           if (evt.type == "mousedown") noUndo = false  | 
 |  |  |           if (evt.type == "mousedown") noUndo = false | 
 |  |  |           // Webkit-based browsers returned 'initial' here for no stroke | 
 |  |  |           if (color === 'transparent' || color === 'initial' || color === '#none') { | 
 |  |  |             color = 'none'; | 
 |  |  | 
 |  |  |           else { | 
 |  |  |             paint = new $.jGraduate.Paint({alpha: 100, solidColor: color.substr(1)}); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           Editor.paintBox[picker].setPaint(paint); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if (isStroke) { | 
 |  |  |             svgCanvas.setColor('stroke', color, noUndo); | 
 |  |  |             if (color != 'none' && svgCanvas.getStrokeOpacity() != 1) { | 
 |  |  | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |       }).bind('contextmenu', function(e) {e.preventDefault()}); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       $("#toggle_stroke_tools").toggle(function() { | 
 |  |  |         $(".stroke_tool").css('display','table-cell'); | 
 |  |  |         $(this).addClass('expanded'); | 
 |  |  | 
 |  |  |         $(this).removeClass('expanded'); | 
 |  |  |         resetScrollPos(); | 
 |  |  |       }); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       // This is a common function used when a tool has been clicked (chosen) | 
 |  |  |       // It does several common things: | 
 |  |  |       // - removes the tool_button_current class from whatever tool currently has it | 
 |  |  | 
 |  |  |         $(button).addClass('tool_button_current').removeClass('tool_button'); | 
 |  |  |         return true; | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       (function() { | 
 |  |  |         var last_x = null, last_y = null, w_area = workarea[0],  | 
 |  |  |         var last_x = null, last_y = null, w_area = workarea[0], | 
 |  |  |           panning = false, keypan = false; | 
 |  |  |          | 
 |  |  |         var move_pan = function(evt) {     | 
 |  |  |  | 
 |  |  |         var move_pan = function(evt) { | 
 |  |  |             if(panning === false) return; | 
 |  |  |  | 
 |  |  |             w_area.scrollLeft -= (evt.clientX - last_x); | 
 |  |  | 
 |  |  |             if(evt.type === 'mouseup' || evt.type === 'touchend') panning = false; | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var start_pan = function(evt) { | 
 |  |  |           if(evt.button === 1 || keypan === true || (evt.originalEvent.touches && evt.originalEvent.touches.length >= 2)) { | 
 |  |  |             panning = true; | 
 |  |  | 
 |  |  |             return false; | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $('#svgcanvas') | 
 |  |  |           .on('mousemove mouseup touchend', move_pan) | 
 |  |  |           .on("mousedown touchmove", start_pan) | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $(window).mouseup(function() { | 
 |  |  |           panning = false; | 
 |  |  |         }); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $(document).bind('keydown', 'space', function(evt) { | 
 |  |  |           evt.preventDefault(); | 
 |  |  |           svgCanvas.spaceKey = keypan = true; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |         }).bind('keyup', 'space', function(evt) { | 
 |  |  |           evt.preventDefault(); | 
 |  |  |           svgCanvas.spaceKey = keypan = false; | 
 |  |  | 
 |  |  |           } | 
 |  |  |         }) | 
 |  |  |       }()); | 
 |  |  |        | 
 |  |  |        | 
 |  |  |  | 
 |  |  |  | 
 |  |  |       function setStrokeOpt(opt, changeElem) { | 
 |  |  |         var id = opt.id; | 
 |  |  |         var bits = id.split('_'); | 
 |  |  |         var pre = bits[0]; | 
 |  |  |         var val = bits[1]; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |         if(changeElem) { | 
 |  |  |           svgCanvas.setStrokeAttr('stroke-' + pre, val); | 
 |  |  |         } | 
 |  |  | 
 |  |  |         setIcon('#cur_' + pre , id, 20); | 
 |  |  |         $(opt).addClass('current').siblings().removeClass('current'); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       //menu handling | 
 |  |  |       var menus = $('.menu'); | 
 |  |  |       var blinker = function(e) { | 
 |  |  | 
 |  |  |           if(!$(e.target).hasClass("disabled") && $(e.target).hasClass("menu_item")) blinker(e) | 
 |  |  |           else $('#menu_bar').removeClass('active') | 
 |  |  |  | 
 |  |  |         }   | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('.menu_item').on('mousedown touchstart', function(e){blinker(e)}); | 
 |  |  |       $("svg, body").on('mousedown  touchstart', function(e){closer(e)}); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var accumulatedDelta = 0 | 
 |  |  |       $('#workarea').on('mousewheel', function(e, delta, deltaX, deltaY){ | 
 |  |  |         if (e.altKey || e.ctrlKey) { | 
 |  |  | 
 |  |  |           $("#zoom").val(parseInt(zoom + deltaY*(e.altKey ? 10 : 5))).change() | 
 |  |  |         } | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('.menu_title') | 
 |  |  |         .on('mousedown', function() { | 
 |  |  |           $("#tools_shapelib").hide() | 
 |  |  | 
 |  |  |            $(this).parent().addClass('open'); | 
 |  |  |          }); | 
 |  |  |  | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Made public for UI customization. | 
 |  |  |       // TODO: Group UI functions into a public methodDraw.ui interface. | 
 |  |  |       Editor.addDropDown = function(elem, callback, dropUp) { | 
 |  |  |         if ($(elem).length == 0) return; // Quit if called on non-existant element | 
 |  |  |         var button = $(elem).find('button'); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var list = $(elem).find('ul').attr('id', $(elem)[0].id + '-list'); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(!dropUp) { | 
 |  |  |           // Move list to place where it can overflow container | 
 |  |  |           $('#option_lists').append(list); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var on_button = false; | 
 |  |  |         if(dropUp) { | 
 |  |  |           $(elem).addClass('dropup'); | 
 |  |  |         } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |         list.find('li').bind('mouseup', callback); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $(window).mouseup(function(evt) { | 
 |  |  |           if(!on_button) { | 
 |  |  |             button.removeClass('down'); | 
 |  |  | 
 |  |  |           } | 
 |  |  |           on_button = false; | 
 |  |  |         }); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         button.bind('mousedown',function() { | 
 |  |  |           if (!button.hasClass('down')) { | 
 |  |  |             button.addClass('down'); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             if(!dropUp) { | 
 |  |  |               var pos = $(elem).offset(); | 
 |  |  |               // position slider | 
 |  |  | 
 |  |  |               }); | 
 |  |  |             } | 
 |  |  |             list.show(); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             on_button = true; | 
 |  |  |           } else { | 
 |  |  |             button.removeClass('down'); | 
 |  |  | 
 |  |  |           on_button = false; | 
 |  |  |         }); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // TODO: Combine this with addDropDown or find other way to optimize | 
 |  |  |       var addAltDropDown = function(elem, list, callback, opts) { | 
 |  |  |         var button = $(elem); | 
 |  |  | 
 |  |  |           callback.apply(this, arguments); | 
 |  |  |  | 
 |  |  |         }); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $(window).mouseup(function(evt) { | 
 |  |  |           if(!on_button) { | 
 |  |  |             button.removeClass('down'); | 
 |  |  | 
 |  |  |           } | 
 |  |  |           on_button = false; | 
 |  |  |         }); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var height = list.height(); | 
 |  |  |         $(elem).bind('mousedown',function() { | 
 |  |  |           var off = $(elem).offset(); | 
 |  |  | 
 |  |  |             off.top += $(elem).height(); | 
 |  |  |           } | 
 |  |  |           $(list).offset(off); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if (!button.hasClass('down')) { | 
 |  |  |             button.addClass('down'); | 
 |  |  |             list.show(); | 
 |  |  | 
 |  |  |         }).mouseout(function() { | 
 |  |  |           on_button = false; | 
 |  |  |         }); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(opts.multiclick) { | 
 |  |  |           list.mousedown(function() { | 
 |  |  |             on_button = true; | 
 |  |  |           }); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#font_family_dropdown').change(function() { | 
 |  |  |         var fam = this.options[this.selectedIndex].value | 
 |  |  |         var fam_display = this.options[this.selectedIndex].text | 
 |  |  |         $('#preview_font').html(fam_display).css("font-family", fam); | 
 |  |  |         $('#font_family').val(fam).change(); | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('div', '#position_opts').each(function(){ | 
 |  |  |         this.addEventListener("mouseup", function(){ | 
 |  |  |           var letter = this.id.replace('tool_pos','').charAt(0); | 
 |  |  |           svgCanvas.alignSelectedElements(letter, 'page'); | 
 |  |  |         }) | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       /* | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       When a flyout icon is selected | 
 |  |  |         (if flyout) { | 
 |  |  |         - Change the icon | 
 |  |  |         - Make pressing the button run its stuff | 
 |  |  |         } | 
 |  |  |         - Run its stuff | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       When its shortcut key is pressed | 
 |  |  |         - If not current in list, do as above | 
 |  |  |         , else: | 
 |  |  |         - Just run its stuff | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       */ | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Unfocus text input when workarea is mousedowned. | 
 |  |  |       (function() { | 
 |  |  |         var inp; | 
 |  |  |         var unfocus = function() { | 
 |  |  |           $(inp).blur(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $('#svg_editor').find('button, select, input:not(#text)').focus(function() { | 
 |  |  |           inp = this; | 
 |  |  |           ui_context = 'toolbars'; | 
 |  |  | 
 |  |  |             $('#text').focus(); | 
 |  |  |           } | 
 |  |  |         }); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |       }()); | 
 |  |  |  | 
 |  |  |       var clickSelect = function() { | 
 |  |  | 
 |  |  |           svgCanvas.setMode('select'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickFHPath = function() { | 
 |  |  |         if (toolButtonClick('#tool_fhpath')) { | 
 |  |  |           svgCanvas.setMode('fhpath'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickLine = function() { | 
 |  |  |         if (toolButtonClick('#tool_line')) { | 
 |  |  |           svgCanvas.setMode('line'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickSquare = function(){ | 
 |  |  |         if (toolButtonClick('#tool_square')) { | 
 |  |  |           svgCanvas.setMode('square'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickRect = function(){ | 
 |  |  |         if (toolButtonClick('#tool_rect')) { | 
 |  |  |           svgCanvas.setMode('rect'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickFHRect = function(){ | 
 |  |  |         if (toolButtonClick('#tool_fhrect')) { | 
 |  |  |           svgCanvas.setMode('fhrect'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickCircle = function(){ | 
 |  |  |         if (toolButtonClick('#tool_circle')) { | 
 |  |  |           svgCanvas.setMode('circle'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickEllipse = function(){ | 
 |  |  |         if (toolButtonClick('#tool_ellipse')) { | 
 |  |  |           svgCanvas.setMode('ellipse'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickFHEllipse = function(){ | 
 |  |  |         if (toolButtonClick('#tool_fhellipse')) { | 
 |  |  |           svgCanvas.setMode('fhellipse'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickImage = function(){ | 
 |  |  |         if (toolButtonClick('#tool_image')) { | 
 |  |  |           svgCanvas.setMode('image'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickZoom = function(){ | 
 |  |  |         if (toolButtonClick('#tool_zoom')) { | 
 |  |  |           svgCanvas.setMode('zoom'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var dblclickZoom = function(){ | 
 |  |  |         if (toolButtonClick('#tool_zoom')) { | 
 |  |  |           zoomImage(); | 
 |  |  |           setSelectMode(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickText = function(){ | 
 |  |  |         if (toolButtonClick('#tool_text')) { | 
 |  |  |           svgCanvas.setMode('text'); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickPath = function(){ | 
 |  |  |         if (toolButtonClick('#tool_path')) { | 
 |  |  |           svgCanvas.setMode('path'); | 
 |  |  | 
 |  |  |           path.deletePathNode(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var cutSelected = function() { | 
 |  |  |         if (selectedElement != null || multiselected) { | 
 |  |  |           flash($('#edit_menu')); | 
 |  |  |           svgCanvas.cutSelectedElements(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var copySelected = function() { | 
 |  |  |         if (selectedElement != null || multiselected) { | 
 |  |  |           flash($('#edit_menu')); | 
 |  |  |           svgCanvas.copySelectedElements(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var pasteSelected = function() { | 
 |  |  |         flash($('#edit_menu')); | 
 |  |  |         var zoom = svgCanvas.getZoom();        | 
 |  |  |         var x = (workarea[0].scrollLeft + workarea.width()/2)/zoom  - svgCanvas.contentW;  | 
 |  |  |         var zoom = svgCanvas.getZoom(); | 
 |  |  |         var x = (workarea[0].scrollLeft + workarea.width()/2)/zoom  - svgCanvas.contentW; | 
 |  |  |         var y = (workarea[0].scrollTop + workarea.height()/2)/zoom  - svgCanvas.contentH; | 
 |  |  |         svgCanvas.pasteElements('point', x, y);  | 
 |  |  |         svgCanvas.pasteElements('point', x, y); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var moveToTopSelected = function() { | 
 |  |  |         if (selectedElement != null) { | 
 |  |  |           flash($('#object_menu')); | 
 |  |  |           svgCanvas.moveToTopSelectedElement(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var moveToBottomSelected = function() { | 
 |  |  |         if (selectedElement != null) { | 
 |  |  |           flash($('#object_menu')); | 
 |  |  |           svgCanvas.moveToBottomSelectedElement(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var moveUpSelected = function() { | 
 |  |  |         if (selectedElement != null) { | 
 |  |  |         flash($('#object_menu')); | 
 |  |  | 
 |  |  |           svgCanvas.moveUpDownSelected("Down"); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var moveUpDownSelected = function(dir) { | 
 |  |  |         if (selectedElement != null) { | 
 |  |  |           flash($('#object_menu')); | 
 |  |  | 
 |  |  |           updateContextPanel(); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var reorientPath = function() { | 
 |  |  |         if (selectedElement != null) { | 
 |  |  |           path.reorient(); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var makeHyperlink = function() { | 
 |  |  |         if (selectedElement != null || multiselected) { | 
 |  |  |           $.prompt(uiStrings.notification.enterNewLinkURL, "http://", function(url) { | 
 |  |  | 
 |  |  |           }); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var moveSelected = function(dx,dy) { | 
 |  |  |         if (selectedElement != null || multiselected) { | 
 |  |  |           if(curConfig.gridSnapping) { | 
 |  |  | 
 |  |  |           svgCanvas.moveSelectedElements(dx,dy); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var linkControlPoints = function() { | 
 |  |  |       //  var linked = document.getElementById('tool_node_link').checked; | 
 |  |  |       //  path.linkControlPoints(linked); | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clonePathNode = function() { | 
 |  |  |         if (path.getNodePoint()) { | 
 |  |  |           path.clonePathNode(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var deletePathNode = function() { | 
 |  |  |         if (path.getNodePoint()) { | 
 |  |  |           path.deletePathNode(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var addSubPath = function() { | 
 |  |  |         var button = $('#tool_add_subpath'); | 
 |  |  |         var sp = !button.hasClass('push_button_pressed'); | 
 |  |  | 
 |  |  |         } else { | 
 |  |  |           button.removeClass('push_button_pressed').addClass('tool_button'); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         path.addSubPath(sp); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var opencloseSubPath = function() { | 
 |  |  |         path.opencloseSubPath(); | 
 |  |  |       }  | 
 |  |  |        | 
 |  |  |       } | 
 |  |  |  | 
 |  |  |       var selectNext = function() { | 
 |  |  |         svgCanvas.cycleElement(1); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var selectPrev = function() { | 
 |  |  |         svgCanvas.cycleElement(0); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var rotateSelected = function(cw,step) { | 
 |  |  |         if (selectedElement == null || multiselected) return; | 
 |  |  |         if(!cw) step *= -1; | 
 |  |  | 
 |  |  |         svgCanvas.setRotationAngle(new_angle); | 
 |  |  |         updateContextPanel(); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickClear = function(){ | 
 |  |  |         var dims = curConfig.dimensions; | 
 |  |  |         $.confirm(uiStrings.notification.QwantToClear, function(ok) { | 
 |  |  | 
 |  |  |           svgCanvas.runExtensions('onNewDocument'); | 
 |  |  |         }); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickBold = function(){ | 
 |  |  |         svgCanvas.setBold( !svgCanvas.getBold() ); | 
 |  |  |         updateContextPanel(); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickItalic = function(){ | 
 |  |  |         svgCanvas.setItalic( !svgCanvas.getItalic() ); | 
 |  |  |         updateContextPanel(); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickExport = function() { | 
 |  |  |         // Open placeholder window (prevents popup) | 
 |  |  |         if(!customHandlers.pngsave)  { | 
 |  |  | 
 |  |  |           }); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // by default, svgCanvas.open() is a no-op. | 
 |  |  |       // it is up to an extension mechanism (opera widget, etc)  | 
 |  |  |       // it is up to an extension mechanism (opera widget, etc) | 
 |  |  |       // to call setCustomHandlers() which will make it do something | 
 |  |  |       var clickOpen = function(){ | 
 |  |  |         svgCanvas.open(); | 
 |  |  |       }; | 
 |  |  |       var clickImport = function(){ | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var flash = function($menu){ | 
 |  |  |         var menu_title = $menu.prev(); | 
 |  |  |         menu_title.css({ | 
 |  |  | 
 |  |  |         }); | 
 |  |  |         setTimeout(function(){menu_title.removeAttr("style")}, 200); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickUndo = function(){ | 
 |  |  |         if (undoMgr.getUndoStackSize() > 0) { | 
 |  |  |           flash($('#edit_menu')); | 
 |  |  |           undoMgr.undo(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickRedo = function(){ | 
 |  |  |         if (undoMgr.getRedoStackSize() > 0) { | 
 |  |  |           flash($('#edit_menu')); | 
 |  |  |           undoMgr.redo(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickGroup = function(){ | 
 |  |  |         // group | 
 |  |  |         if (multiselected) { | 
 |  |  | 
 |  |  |           svgCanvas.ungroupSelectedElement(); | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickClone = function(){ | 
 |  |  |         flash($('#edit_menu')); | 
 |  |  |         svgCanvas.cloneSelectedElements(20,20); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickAlign = function() { | 
 |  |  |         var letter = this.id.replace('tool_align','').charAt(0); | 
 |  |  |         svgCanvas.alignSelectedElements(letter, $('#align_relative_to').val()); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickSwitch = function() { | 
 |  |  |         var stroke_rect = document.querySelector('#tool_stroke rect'); | 
 |  |  |         $("#tool_stroke").toggleClass('active') | 
 |  |  | 
 |  |  |         var fill = getPaint(fill_color, fill_opacity, "fill"); | 
 |  |  |         Editor.paintBox.fill.setPaint(stroke, true); | 
 |  |  |         Editor.paintBox.stroke.setPaint(fill, true); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var zoomImage = function(multiplier) { | 
 |  |  |         var res = svgCanvas.getResolution(); | 
 |  |  |         multiplier = multiplier?res.zoom * multiplier:1; | 
 |  |  | 
 |  |  |         zoomDone(); | 
 |  |  |         updateCanvas(true); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var zoomDone = function() { | 
 |  |  |     //    updateBgImage(); | 
 |  |  |         updateWireFrame(); | 
 |  |  |         //updateCanvas(); // necessary? | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var clickWireframe = function() { | 
 |  |  |         flash($('#view_menu')); | 
 |  |  |         var wf = !$('#tool_wireframe').hasClass('push_button_pressed'); | 
 |  |  |         if (wf)  | 
 |  |  |         if (wf) | 
 |  |  |           $('#tool_wireframe').addClass('push_button_pressed'); | 
 |  |  |         else | 
 |  |  |           $('#tool_wireframe').removeClass('push_button_pressed'); | 
 |  |  |         workarea.toggleClass('wireframe'); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(supportsNonSS) return; | 
 |  |  |         var wf_rules = $('#wireframe_rules'); | 
 |  |  |         if(!wf_rules.length) { | 
 |  |  | 
 |  |  |         } else { | 
 |  |  |           wf_rules.empty(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         updateWireFrame(); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickSnapGrid = function() { | 
 |  |  |         flash($('#view_menu')); | 
 |  |  |         var sg = !$('#tool_snap').hasClass('push_button_pressed'); | 
 |  |  |         if (sg)  | 
 |  |  |         if (sg) | 
 |  |  |           $('#tool_snap').addClass('push_button_pressed'); | 
 |  |  |         else | 
 |  |  |           $('#tool_snap').removeClass('push_button_pressed');    | 
 |  |  |           $('#tool_snap').removeClass('push_button_pressed'); | 
 |  |  |         curConfig.gridSnapping = sg; | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var minimizeModal = function() { | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if (window.self != window.top) { //we're in an iframe | 
 |  |  |           top.exit_fullscreen(); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickRulers = function() { | 
 |  |  |         flash($('#view_menu')); | 
 |  |  |         var rulers = !$('#tool_rulers').hasClass('push_button_pressed'); | 
 |  |  | 
 |  |  |         } | 
 |  |  |         $('#rulers').toggle(!!curConfig.showRulers) | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var updateWireFrame = function() { | 
 |  |  |         // Test support | 
 |  |  |         if(supportsNonSS) return; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         var rule = "#workarea.wireframe #svgcontent * { stroke-width: " + 1/svgCanvas.getZoom() + "px; }"; | 
 |  |  |         $('#wireframe_rules').text(workarea.hasClass('wireframe') ? rule : ""); | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var showSourceEditor = function(e, forSaving){ | 
 |  |  |         if (editingsource) return; | 
 |  |  |         flash($('#view_menu')); | 
 |  |  |         editingsource = true; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $('#save_output_btns').toggle(!!forSaving); | 
 |  |  |         $('#tool_source_back').toggle(!forSaving); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var str = orig_source = svgCanvas.getSvgString(); | 
 |  |  |         $('#svg_source_textarea').val(str); | 
 |  |  |         $('#svg_source_editor').fadeIn(); | 
 |  |  |         $('#svg_source_textarea').focus().select(); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var clickSave = function(){ | 
 |  |  |         flash($('#file_menu')); | 
 |  |  |         // In the future, more options can be provided here | 
 |  |  | 
 |  |  |         } | 
 |  |  |         svgCanvas.save(saveOpts); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var saveSourceEditor = function(){ | 
 |  |  |         if (!editingsource) return; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         var saveChanges = function() { | 
 |  |  |           svgCanvas.clearSelection(); | 
 |  |  |           hideSourceEditor(); | 
 |  |  |           zoomImage(); | 
 |  |  |           prepPaints(); | 
 |  |  |         } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         if (!svgCanvas.setSvgString($('#svg_source_textarea').val())) { | 
 |  |  |           $.confirm(uiStrings.notification.QerrorsRevertToSource, function(ok) { | 
 |  |  |             if(!ok) return false; | 
 |  |  | 
 |  |  |         } else { | 
 |  |  |           saveChanges(); | 
 |  |  |         } | 
 |  |  |         setSelectMode();     | 
 |  |  |         setSelectMode(); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       function setBackground(color, url) { | 
 |  |  | //        if(color == curPrefs.bkgd_color && url == curPrefs.bkgd_url) return; | 
 |  |  |         $.pref('bkgd_color', color); | 
 |  |  |         $.pref('bkgd_url', url); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         // This should be done in svgcanvas.js for the borderRect fill | 
 |  |  |         svgCanvas.setBackground(color, url); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var setIcon = Editor.setIcon = function(elem, icon_id, forcedSize) { | 
 |  |  |         var icon = (typeof icon_id === 'string') ? $.getSvgIcon(icon_id, true) : icon_id.clone(); | 
 |  |  |         if(!icon) { | 
 |  |  | 
 |  |  |  | 
 |  |  |         $(elem).find("img").replaceWith(icon); | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var ua_prefix; | 
 |  |  |       (ua_prefix = function() { | 
 |  |  |         var regex = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/; | 
 |  |  | 
 |  |  |             return prop.match(regex)[0]; | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |         // Nothing found so far? | 
 |  |  |         if('WebkitOpacity' in someScript.style) return 'Webkit'; | 
 |  |  |         if('KhtmlOpacity' in someScript.style) return 'Khtml'; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         return ''; | 
 |  |  |       }()); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var scaleElements = function(elems, scale) { | 
 |  |  |         var prefix = '-' + ua_prefix.toLowerCase() + '-'; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var sides = ['top', 'left', 'bottom', 'right']; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |         elems.each(function() { | 
 |  |  | //          console.log('go', scale); | 
 |  |  |  | 
 |  |  |           // Handled in CSS | 
 |  |  |           // this.style[ua_prefix + 'Transform'] = 'scale(' + scale + ')'; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |           var el = $(this); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var w = el.outerWidth() * (scale - 1); | 
 |  |  |           var h = el.outerHeight() * (scale - 1); | 
 |  |  |           var margins = {}; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           for(var i = 0; i < 4; i++) { | 
 |  |  |             var s = sides[i]; | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             var cur = el.data('orig_margin-' + s); | 
 |  |  |             if(cur == null) { | 
 |  |  |               cur = parseInt(el.css('margin-' + s)); | 
 |  |  | 
 |  |  |             } else if(s === 'bottom') { | 
 |  |  |               val += h; | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             el.css('margin-' + s, val); | 
 |  |  | //            el.css('outline', '1px solid red'); | 
 |  |  |           } | 
 |  |  |         }); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var setIconSize = Editor.setIconSize = function(size, force) { | 
 |  |  |         if(size == curPrefs.size && !force) return; | 
 |  |  | //        return; | 
 |  |  | //        var elems = $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open'); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var sel_toscale = '#tools_top .toolset, #editor_panel > *, #history_panel > *,\ | 
 |  |  |         #main_button, #tools_left > *, #path_node_panel > *, #multiselected_panel > *,\ | 
 |  |  |         #g_panel > *, #tool_font_size > *, .tools_flyout'; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var elems = $(sel_toscale); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var scale = 1; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(typeof size == 'number') { | 
 |  |  |           scale = size; | 
 |  |  |         } else { | 
 |  |  |           var icon_sizes = { s:.75, m:1, l:1.25, xl:1.5 }; | 
 |  |  |           scale = icon_sizes[size]; | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         Editor.tool_scale = tool_scale = scale; | 
 |  |  |          | 
 |  |  |         setFlyoutPositions();        | 
 |  |  |  | 
 |  |  |         setFlyoutPositions(); | 
 |  |  |         var hidden_ps = elems.parents(':hidden'); | 
 |  |  |         hidden_ps.css('visibility', 'hidden').show(); | 
 |  |  |         scaleElements(elems, scale); | 
 |  |  |         hidden_ps.css('visibility', 'visible').hide(); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var rule_elem = $('#tool_size_rules'); | 
 |  |  |         if(!rule_elem.length) { | 
 |  |  |           rule_elem = $('<style id="tool_size_rules"><\/style>').appendTo('head'); | 
 |  |  |         } else { | 
 |  |  |           rule_elem.empty(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(size != 'm') { | 
 |  |  |           var style_str = ''; | 
 |  |  |           $.each(cssResizeRules, function(selector, rules) { | 
 |  |  | 
 |  |  |           ); | 
 |  |  |           rule_elem.text(style_str); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         setFlyoutPositions(); | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var cancelOverlays = function() { | 
 |  |  |         $('#dialog_box').hide(); | 
 |  |  |         if (!editingsource && !docprops && !preferences) { | 
 |  |  | 
 |  |  |           } | 
 |  |  |           return; | 
 |  |  |         }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         if (editingsource) { | 
 |  |  |           if (orig_source !== $('#svg_source_textarea').val()) { | 
 |  |  |             $.confirm(uiStrings.notification.QignoreSourceChanges, function(ok) { | 
 |  |  | 
 |  |  |         } | 
 |  |  |         resetScrollPos(); | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var hideSourceEditor = function(){ | 
 |  |  |         $('#svg_source_editor').hide(); | 
 |  |  |         editingsource = false; | 
 |  |  | 
 |  |  |       }; | 
 |  |  |  | 
 |  |  |       var win_wh = {width:$(window).width(), height:$(window).height()}; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var resetScrollPos = $.noop, curScrollPos; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       /* Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9) | 
 |  |  |       if(svgedit.browser.isIE()) { | 
 |  |  |         (function() { | 
 |  |  |           resetScrollPos = function() { | 
 |  |  |             if(workarea[0].scrollLeft === 0  | 
 |  |  |             if(workarea[0].scrollLeft === 0 | 
 |  |  |             && workarea[0].scrollTop === 0) { | 
 |  |  |               workarea[0].scrollLeft = curScrollPos.left; | 
 |  |  |               workarea[0].scrollTop = curScrollPos.top; | 
 |  |  |             } | 
 |  |  |           } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |           curScrollPos = { | 
 |  |  |             left: workarea[0].scrollLeft, | 
 |  |  |             top: workarea[0].scrollTop | 
 |  |  |           }; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           $(window).resize(resetScrollPos); | 
 |  |  |           methodDraw.ready(function() { | 
 |  |  |             // TODO: Find better way to detect when to do this to minimize | 
 |  |  | 
 |  |  |               resetScrollPos(); | 
 |  |  |             }, 500); | 
 |  |  |           }); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           workarea.scroll(function() { | 
 |  |  |             curScrollPos = { | 
 |  |  |               left: workarea[0].scrollLeft, | 
 |  |  | 
 |  |  |           }); | 
 |  |  |         }()); | 
 |  |  |       }*/ | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $(window).resize(function(evt) { | 
 |  |  |           updateCanvas(); | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       (function() { | 
 |  |  |         workarea.scroll(function() { | 
 |  |  |           // TODO:  jQuery's scrollLeft/Top() wouldn't require a null check | 
 |  |  | 
 |  |  |             $('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft; | 
 |  |  |           } | 
 |  |  |           if ($('#ruler_y').length != 0) { | 
 |  |  |             $('#ruler_y')[0].scrollTop = workarea[0].scrollTop;  | 
 |  |  |             $('#ruler_y')[0].scrollTop = workarea[0].scrollTop; | 
 |  |  |           } | 
 |  |  |         }); | 
 |  |  |  | 
 |  |  |       }()); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#url_notice').click(function() { | 
 |  |  |         $.alert(this.title); | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#change_image_url').click(promptImgURL); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       function promptImgURL() { | 
 |  |  |         var curhref = svgCanvas.getHref(selectedElement); | 
 |  |  |         curhref = curhref.indexOf("data:") === 0?"":curhref; | 
 |  |  | 
 |  |  |           if(url) setImageURL(url); | 
 |  |  |         }); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // TODO: go back to the color boxes having white background-color and then setting | 
 |  |  |       //       background-image to none.png (otherwise partially transparent gradients look weird)   | 
 |  |  |       //       background-image to none.png (otherwise partially transparent gradients look weird) | 
 |  |  |       var colorPicker = function(elem) { | 
 |  |  |         var picker = elem[0].id == 'stroke_color' ? 'stroke' : 'fill'; | 
 |  |  |         var is_background = elem[0].id == "canvas_color" | 
 |  |  |         if (is_background) picker = 'canvas' | 
 |  |  | //        var opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity')); | 
 |  |  |         var paint = Editor.paintBox[picker].paint; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var title = (picker == 'stroke' ? 'Pick a Stroke Paint and Opacity' : 'Pick a Fill Paint and Opacity'); | 
 |  |  |         var was_none = false; | 
 |  |  |         var pos = is_background ? {'right': 175, 'top': 50} : {'left': 50, 'bottom': 50} | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $("#color_picker") | 
 |  |  |           .draggable({cancel:'.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker', containment: 'window'}) | 
 |  |  |           .removeAttr("style") | 
 |  |  |           .css(pos) | 
 |  |  |           .jGraduate( | 
 |  |  |           {  | 
 |  |  |           { | 
 |  |  |             paint: paint, | 
 |  |  |             window: { pickerTitle: title }, | 
 |  |  |             images: { clientPath: curConfig.jGraduatePath }, | 
 |  |  | 
 |  |  |           }, | 
 |  |  |           function(p) { | 
 |  |  |             paint = new $.jGraduate.Paint(p); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             Editor.paintBox[picker].setPaint(paint); | 
 |  |  |             svgCanvas.setPaint(picker, paint); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             $('#color_picker').hide(); | 
 |  |  |           }, | 
 |  |  |           function(p) { | 
 |  |  |             $('#color_picker').hide(); | 
 |  |  |           }); | 
 |  |  |       }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       var PaintBox = function(container, type) { | 
 |  |  |         var background = document.getElementById("canvas_background"); | 
 |  |  |         var cur = {color: "fff", opacity: 1} | 
 |  |  | 
 |  |  |           fill="#' + cur.color + '" opacity="' + cur.opacity + '"/>\ | 
 |  |  |           <defs><linearGradient id="gradbox_"/></defs></svg>', 'text/xml'); | 
 |  |  |         var docElem = svgdocbox.documentElement; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         docElem = $(container)[0].appendChild(document.importNode(docElem, true)); | 
 |  |  |         if (type === 'canvas') docElem.setAttribute('width',60.5); | 
 |  |  |         else docElem.setAttribute('width',"100%"); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         this.rect = docElem.firstChild; | 
 |  |  |         this.defs = docElem.getElementsByTagName('defs')[0]; | 
 |  |  |         this.grad = this.defs.firstChild; | 
 |  |  | 
 |  |  |             } | 
 |  |  |             else createBackground(fillAttr) | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           if(apply) { | 
 |  |  |             svgCanvas.setColor(this.type, fillAttr, true); | 
 |  |  |             svgCanvas.setPaintOpacity(this.type, opac, true); | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         this.update = function(apply) { | 
 |  |  |           if(!selectedElement) return; | 
 |  |  |           var type = this.type; | 
 |  |  | 
 |  |  |           case 'use': | 
 |  |  |           case 'image': | 
 |  |  |           case 'foreignObject': | 
 |  |  |             // These elements don't have fill or stroke, so don't change  | 
 |  |  |             // These elements don't have fill or stroke, so don't change | 
 |  |  |             // the current value | 
 |  |  |             return; | 
 |  |  |           case 'g': | 
 |  |  |           case 'a': | 
 |  |  |             var gPaint = null; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |             var childs = selectedElement.getElementsByTagName('*'); | 
 |  |  |             for(var i = 0, len = childs.length; i < len; i++) { | 
 |  |  |               var elem = childs[i]; | 
 |  |  | 
 |  |  |               return; | 
 |  |  |             } | 
 |  |  |             var paintColor = gPaint; | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             var paintOpacity = 1; | 
 |  |  |             break; | 
 |  |  |           default: | 
 |  |  | 
 |  |  |             if (isNaN(paintOpacity)) { | 
 |  |  |               paintOpacity = 1.0; | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             var defColor = type === "fill" ? "black" : "none"; | 
 |  |  |             var paintColor = selectedElement.getAttribute(type) || defColor; | 
 |  |  |           } | 
 |  |  | 
 |  |  |             svgCanvas.setPaintOpacity(type, paintOpacity, true); | 
 |  |  |           } | 
 |  |  |  | 
 |  |  |           paintOpacity *= 100;           | 
 |  |  |            | 
 |  |  |           paintOpacity *= 100; | 
 |  |  |  | 
 |  |  |           var paint = getPaint(paintColor, paintOpacity, type); | 
 |  |  |           // update the rect inside #fill_color/#stroke_color | 
 |  |  |           this.setPaint(paint); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         this.prep = function() { | 
 |  |  |           var ptype = this.paint.type; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |           switch ( ptype ) { | 
 |  |  |             case 'linearGradient': | 
 |  |  |             case 'radialGradient': | 
 |  |  | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       Editor.paintBox.fill = new PaintBox('#fill_color', 'fill'); | 
 |  |  |       Editor.paintBox.stroke = new PaintBox('#stroke_color', 'stroke'); | 
 |  |  |       Editor.paintBox.canvas = new PaintBox('#canvas_color', 'canvas'); | 
 |  |  |  | 
 |  |  |       $('#stroke_width').val(curConfig.initStroke.width); | 
 |  |  |       $('#group_opacity').val(curConfig.initOpacity * 100); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Use this SVG elem to test vectorEffect support | 
 |  |  |       var test_el = Editor.paintBox.fill.rect.cloneNode(false); | 
 |  |  |       test_el.setAttribute('style','vector-effect:non-scaling-stroke'); | 
 |  |  | 
 |  |  |       } | 
 |  |  |       $(blur_test).remove(); | 
 |  |  |  | 
 |  |  |        | 
 |  |  |        | 
 |  |  |  | 
 |  |  |  | 
 |  |  |       // Test for embedImage support (use timeout to not interfere with page load) | 
 |  |  |       setTimeout(function() { | 
 |  |  |         svgCanvas.embedImage('images/placeholder.svg', function(datauri) { | 
 |  |  | 
 |  |  |           } | 
 |  |  |         }); | 
 |  |  |       },1000); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |       $('#tool_fill').click(function(){ | 
 |  |  |         if ($('#tool_fill').hasClass('active')) { | 
 |  |  |           colorPicker($('#fill_color')); | 
 |  |  | 
 |  |  |           $("#tool_stroke").removeClass('active'); | 
 |  |  |         } | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#tool_stroke').on("click", function(){ | 
 |  |  |         if ($('#tool_stroke').hasClass('active')) { | 
 |  |  |           colorPicker($('#stroke_color')); | 
 |  |  | 
 |  |  |           $("#tool_fill").removeClass('active'); | 
 |  |  |         } | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#tool_canvas').on("click touchstart", function(){ | 
 |  |  |           colorPicker($('#canvas_color')); | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#tool_stroke').on("touchstart", function(){ | 
 |  |  |           $('#tool_stroke').addClass('active'); | 
 |  |  |           $("#tool_fill").removeClass('active'); | 
 |  |  | 
 |  |  |           $("#tool_stroke").removeClass('active'); | 
 |  |  |           colorPicker($('#fill_color')); | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#zoom_select').on("change", function() { | 
 |  |  |         var val = this.options[this.selectedIndex].text | 
 |  |  |         val = val.split("%")[0] | 
 |  |  |         $("#zoom").val(val).trigger("change") | 
 |  |  |       }); | 
 |  |  |      | 
 |  |  |       $('.push_button').mousedown(function() {  | 
 |  |  |  | 
 |  |  |       $('.push_button').mousedown(function() { | 
 |  |  |         if (!$(this).hasClass('disabled')) { | 
 |  |  |           $(this).addClass('push_button_pressed').removeClass('push_button'); | 
 |  |  |         } | 
 |  |  | 
 |  |  |       }).mouseup(function() { | 
 |  |  |         $(this).removeClass('push_button_pressed').addClass('push_button'); | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |      | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     //  function changeResolution(x,y) { | 
 |  |  |     //    var zoom = svgCanvas.getResolution().zoom; | 
 |  |  |     //    setResolution(x * zoom, y * zoom); | 
 |  |  |     //  } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var centerCanvas = function() { | 
 |  |  |         // this centers the canvas vertically in the workarea (horizontal handled in CSS) | 
 |  |  |         workarea.css('line-height', workarea.height() + 'px'); | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $(window).bind('load resize', centerCanvas); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       function stepFontSize(elem, step) { | 
 |  |  |         var orig_val = elem.value-0; | 
 |  |  |         var sug_val = orig_val + step; | 
 |  |  |         var increasing = sug_val >= orig_val; | 
 |  |  |         if(step === 0) return orig_val; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(orig_val >= 24) { | 
 |  |  |           if(increasing) { | 
 |  |  |             return Math.round(orig_val * 1.1); | 
 |  |  | 
 |  |  |           } | 
 |  |  |         } else if(orig_val <= 1) { | 
 |  |  |           if(increasing) { | 
 |  |  |             return orig_val * 2;       | 
 |  |  |             return orig_val * 2; | 
 |  |  |           } else { | 
 |  |  |             return orig_val / 2; | 
 |  |  |           } | 
 |  |  | 
 |  |  |           return sug_val; | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       function stepZoom(elem, step) { | 
 |  |  |         var orig_val = elem.value-0; | 
 |  |  |         if(orig_val === 0) return 100; | 
 |  |  |         var sug_val = orig_val + step; | 
 |  |  |         if(step === 0) return orig_val; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(orig_val >= 100) { | 
 |  |  |           return sug_val; | 
 |  |  |         } else { | 
 |  |  | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |     var changeCanvasSize = function(ctl){ | 
 |  |  |       var width = $("#canvas_width"); | 
 |  |  |       var height = $("#canvas_height"); | 
 |  |  |       var w = width.val(); | 
 |  |  |       var h = height.val() | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       if(w != "fit" && !svgedit.units.isValidUnit('width', w)) { | 
 |  |  |         $.alert(uiStrings.notification.invalidAttrValGiven); | 
 |  |  |         width.parent().addClass('error'); | 
 |  |  | 
 |  |  |         $.alert(uiStrings.notification.invalidAttrValGiven); | 
 |  |  |         height.parent().addClass('error'); | 
 |  |  |         return false; | 
 |  |  |       }  | 
 |  |  |       } | 
 |  |  |       height.parent().removeClass('error'); | 
 |  |  |       if(!svgCanvas.setResolution(w, h)) { | 
 |  |  |         $.alert(uiStrings.notification.noContentToFitTo); | 
 |  |  | 
 |  |  |       } | 
 |  |  |        updateCanvas(); | 
 |  |  |     } | 
 |  |  |      | 
 |  |  |      | 
 |  |  |  | 
 |  |  |  | 
 |  |  |       $('#resolution').change(function(){ | 
 |  |  |         var w = $('#canvas_width')[0]; | 
 |  |  |         var h = $('#canvas_height')[0]; | 
 |  |  | 
 |  |  |           var res = svgCanvas.getResolution() | 
 |  |  |           w.value = res.w | 
 |  |  |           h.value = res.h | 
 |  |  |            | 
 |  |  |  | 
 |  |  |         } else { | 
 |  |  |           var dims = this.value.split('x'); | 
 |  |  |           dims[0] = parseInt(dims[0]);  | 
 |  |  |           dims[0] = parseInt(dims[0]); | 
 |  |  |           dims[1] = parseInt(dims[1]); | 
 |  |  |           var diff_w = dims[0] - w.value; | 
 |  |  |           var diff_h = dims[1] - h.value; | 
 |  |  | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#zoom').change(function(){ | 
 |  |  |         changeZoom(this) | 
 |  |  |       }) | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       //Prevent browser from erroneously repopulating fields | 
 |  |  |       $('input,select').attr("autocomplete","off"); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Associate all button actions as well as non-button keyboard shortcuts | 
 |  |  |       var Actions = function() { | 
 |  |  |         // sel:'selector', fn:function, evt:'event', key:[key, preventDefault, NoDisableInInput] | 
 |  |  | 
 |  |  |           {sel:'#tool_italic', fn: clickItalic, evt: 'mousedown',  key: [modKey + 'I', true]}, | 
 |  |  |           //{sel:'#sidepanel_handle', fn: toggleSidePanel, key: ['X']}, | 
 |  |  |           {sel:'#copy_save_done', fn: cancelOverlays, evt: 'click'}, | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Shortcuts not associated with buttons | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           {key: 'ctrl+left', fn: function(){rotateSelected(0,1)}}, | 
 |  |  |           {key: 'ctrl+right', fn: function(){rotateSelected(1,1)}}, | 
 |  |  |           {key: 'ctrl+shift+left', fn: function(){rotateSelected(0,5)}},           | 
 |  |  |           {key: 'ctrl+shift+left', fn: function(){rotateSelected(0,5)}}, | 
 |  |  |           {key: 'ctrl+shift+right', fn: function(){rotateSelected(1,5)}}, | 
 |  |  |           {key: 'shift+O', fn: selectPrev}, | 
 |  |  |           {key: 'shift+P', fn: selectNext}, | 
 |  |  | 
 |  |  |           {key: ['alt+shift+up', true], fn: function(){svgCanvas.cloneSelectedElements(0,-10)}}, | 
 |  |  |           {key: ['alt+shift+down', true], fn: function(){svgCanvas.cloneSelectedElements(0,10)}}, | 
 |  |  |           {key: ['alt+shift+left', true], fn: function(){svgCanvas.cloneSelectedElements(-10,0)}}, | 
 |  |  |           {key: ['alt+shift+right', true], fn: function(){svgCanvas.cloneSelectedElements(10,0)}},   | 
 |  |  |           {key: ['alt+shift+right', true], fn: function(){svgCanvas.cloneSelectedElements(10,0)}}, | 
 |  |  |           {key: modKey + 'A', fn: function(){svgCanvas.selectAllInCurrentLayer();}}, | 
 |  |  |           {key: 'I', fn: function(){setEyedropperMode()}}, | 
 |  |  |  | 
 |  |  | 
 |  |  |           {key: modKey + 'shift+z', fn: clickRedo}, | 
 |  |  |           {key: 'esc', fn: minimizeModal} | 
 |  |  |         ]; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         // Tooltips not directly associated with a single function | 
 |  |  |         var key_assocs = { | 
 |  |  |           '4/Shift+4': '#tools_rect_show', | 
 |  |  |           '5/Shift+5': '#tools_ellipse_show' | 
 |  |  |         }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |         return { | 
 |  |  |           setAll: function() { | 
 |  |  |             var flyouts = {}; | 
 |  |  |              | 
 |  |  |             $.each(tool_buttons, function(i, opts)  {        | 
 |  |  |  | 
 |  |  |             $.each(tool_buttons, function(i, opts)  { | 
 |  |  |               // Bind function to button | 
 |  |  |               if(opts.sel) { | 
 |  |  |                 var btn = $(opts.sel); | 
 |  |  |                 if (btn.length == 0) return true; // Skip if markup does not exist | 
 |  |  |                 if(opts.evt) { | 
 |  |  |                   if (svgedit.browser.isTouch() && opts.evt === "click") opts.evt = "mousedown"  | 
 |  |  |                   if (svgedit.browser.isTouch() && opts.evt === "click") opts.evt = "mousedown" | 
 |  |  |                   btn[opts.evt](opts.fn); | 
 |  |  |                 } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |                 // Add to parent flyout menu, if able to be displayed | 
 |  |  |                 if(opts.parent && $(opts.parent + '_show').length != 0) { | 
 |  |  |                   var f_h = $(opts.parent); | 
 |  |  |                   if(!f_h.length) { | 
 |  |  |                     f_h = makeFlyoutHolder(opts.parent.substr(1)); | 
 |  |  |                   } | 
 |  |  |                    | 
 |  |  |  | 
 |  |  |                   f_h.append(btn); | 
 |  |  |                    | 
 |  |  |  | 
 |  |  |                   if(!$.isArray(flyouts[opts.parent])) { | 
 |  |  |                     flyouts[opts.parent] = []; | 
 |  |  |                   } | 
 |  |  |                   flyouts[opts.parent].push(opts); | 
 |  |  |                 } | 
 |  |  |               } | 
 |  |  |                | 
 |  |  |                | 
 |  |  |  | 
 |  |  |  | 
 |  |  |               // Bind function to shortcut key | 
 |  |  |               if(opts.key) { | 
 |  |  |                 // Set shortcut based on options | 
 |  |  | 
 |  |  |                   var modifier_key =  keyval.split("+")[0]; | 
 |  |  |                   if (modifier_key == "ctrl") keyval.replace("ctrl", "cmd") | 
 |  |  |                 } | 
 |  |  |                  | 
 |  |  |  | 
 |  |  |                 $.each(keyval.split('/'), function(i, key) { | 
 |  |  |                   $(document).bind('keydown', key, function(e) { | 
 |  |  |                     fn(); | 
 |  |  | 
 |  |  |                     return false; | 
 |  |  |                   }); | 
 |  |  |                 }); | 
 |  |  |                  | 
 |  |  |  | 
 |  |  |                 // Put shortcut in title | 
 |  |  |                 if(opts.sel && !opts.hidekey && btn.attr('title')) { | 
 |  |  |                   var new_title = btn.attr('title').split('[')[0] + ' (' + keyval + ')'; | 
 |  |  | 
 |  |  |                 } | 
 |  |  |               } | 
 |  |  |             }); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // Setup flyouts | 
 |  |  |             setupFlyouts(flyouts); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             $(window).bind('keydown', 'tab', function(e) { | 
 |  |  |               if(ui_context === 'canvas') { | 
 |  |  |                 e.preventDefault(); | 
 |  |  | 
 |  |  |                 selectPrev(); | 
 |  |  |               } | 
 |  |  |             }); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             $('#tool_zoom').dblclick(dblclickZoom); | 
 |  |  |           }, | 
 |  |  |           setTitles: function() { | 
 |  |  |             $.each(key_assocs, function(keyval, sel)  { | 
 |  |  |               var menu = ($(sel).parents('#main_menu').length); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |               $(sel).each(function() { | 
 |  |  |                 if(menu) { | 
 |  |  |                   var t = $(this).text().split(' [')[0]; | 
 |  |  |                 } else { | 
 |  |  |                   var t = this.title.split(' [')[0];               | 
 |  |  |                   var t = this.title.split(' [')[0]; | 
 |  |  |                 } | 
 |  |  |                 var key_str = ''; | 
 |  |  |                 // Shift+Up | 
 |  |  | 
 |  |  |           } | 
 |  |  |         }; | 
 |  |  |       }(); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       Actions.setAll(); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Select given tool | 
 |  |  |       Editor.ready(function() { | 
 |  |  |         var tool, | 
 |  |  | 
 |  |  |           tool = $("#tool_select"); | 
 |  |  |         } | 
 |  |  |         tool.click().mouseup(); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(curConfig.wireframe) { | 
 |  |  |           $('#tool_wireframe').click(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(curConfig.showlayers) { | 
 |  |  |           toggleSidePanel(); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         $('#rulers').toggle(!!curConfig.showRulers); | 
 |  |  |       }); | 
 |  |  |      | 
 |  |  |        | 
 |  |  |       $('#canvas_height').dragInput({ min: 10,   max: null,  step: 10,  callback: changeCanvasSize,    cursor: false, dragAdjust: .1         });  | 
 |  |  |       $('#canvas_width') .dragInput({ min: 10,   max: null,  step: 10,  callback: changeCanvasSize,    cursor: false, dragAdjust: .1         });                          | 
 |  |  |       $('#rect_width')   .dragInput({ min: 1,    max: null,  step:  1,  callback: changeAttribute,     cursor: false                         });  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |       $('#canvas_height').dragInput({ min: 10,   max: null,  step: 10,  callback: changeCanvasSize,    cursor: false, dragAdjust: .1         }); | 
 |  |  |       $('#canvas_width') .dragInput({ min: 10,   max: null,  step: 10,  callback: changeCanvasSize,    cursor: false, dragAdjust: .1         }); | 
 |  |  |       $('#rect_width')   .dragInput({ min: 1,    max: null,  step:  1,  callback: changeAttribute,     cursor: false                         }); | 
 |  |  |       $('#rect_height')  .dragInput({ min: 1,    max: null,  step:  1,  callback: changeAttribute,     cursor: false                         }); | 
 |  |  |       $('#ellipse_cx')   .dragInput({ min: 1,    max: null,  step:  1,  callback: changeAttribute,     cursor: false                         }); | 
 |  |  |       $('#ellipse_cy')   .dragInput({ min: 1,    max: null,  step:  1,  callback: changeAttribute,     cursor: false                         }); | 
 |  |  | 
 |  |  |       $('#font_size')    .dragInput({ min: 1, max: 250, step: 1, callback: changeFontSize, cursor: true, stepfunc: stepFontSize, dragAdjust: .15 }); | 
 |  |  |       $('#group_opacity').dragInput({ min: 0,    max: 100,   step:  5,  callback: changeAttribute,       cursor: true,  start: 100             }); | 
 |  |  |       $('#blur')         .dragInput({ min: 0,    max: 10,    step: .1,  callback: changeBlur,          cursor: true,  start: 0               }); | 
 |  |  |         // Set default zoom  | 
 |  |  |         // Set default zoom | 
 |  |  |       $('#zoom').val(svgCanvas.getZoom() * 100); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $("#workarea").contextMenu({ | 
 |  |  |           menu: 'cmenu_canvas', | 
 |  |  |           inSpeed: 0 | 
 |  |  | 
 |  |  |             case 'group': | 
 |  |  |               svgCanvas.groupSelectedElements(); | 
 |  |  |               break; | 
 |  |  |             case 'ungroup':          | 
 |  |  |               svgCanvas.ungroupSelectedElement();   | 
 |  |  |             case 'ungroup': | 
 |  |  |               svgCanvas.ungroupSelectedElement(); | 
 |  |  |               break; | 
 |  |  |             case 'move_front': | 
 |  |  |               moveToTopSelected(); | 
 |  |  | 
 |  |  |                 } | 
 |  |  |                 break; | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |       }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('.contextMenu li').mousedown(function(ev) { | 
 |  |  |         ev.preventDefault(); | 
 |  |  |       }) | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       $('#cmenu_canvas li').disableContextMenu(); | 
 |  |  |       canv_menu.enableContextMenuItems('#delete,#cut,#copy'); | 
 |  |  |        | 
 |  |  |       window.onbeforeunload = function() {  | 
 |  |  |         // Suppress warning if page is empty  | 
 |  |  |  | 
 |  |  |       window.onbeforeunload = function() { | 
 |  |  |         // Suppress warning if page is empty | 
 |  |  |         if(undoMgr.getUndoStackSize() === 0) { | 
 |  |  |           Editor.show_save_warning = false; | 
 |  |  |         } | 
 |  |  | 
 |  |  |         // show_save_warning is set to "false" when the page is saved. | 
 |  |  |         if(!curConfig.no_save_warning && Editor.show_save_warning) { | 
 |  |  |           // Browser already asks question about closing the page | 
 |  |  |           return uiStrings.notification.unsavedChanges;  | 
 |  |  |           return uiStrings.notification.unsavedChanges; | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       Editor.openPrep = function(func) { | 
 |  |  |         $('#main_menu').hide(); | 
 |  |  |         if(undoMgr.getUndoStackSize() === 0) { | 
 |  |  | 
 |  |  |           $.confirm(uiStrings.notification.QwantToOpen, func); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |       if (window.FileReader) { | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var import_image = function(e) { | 
 |  |  |           e.stopPropagation(); | 
 |  |  |           e.preventDefault(); | 
 |  |  | 
 |  |  |           if (file) { | 
 |  |  |             if(file.type.indexOf("image") != -1) { | 
 |  |  |               //detected an image | 
 |  |  |              | 
 |  |  |  | 
 |  |  |               //svg handing | 
 |  |  |               if(file.type.indexOf("svg") != -1) { | 
 |  |  |                 var reader = new FileReader(); | 
 |  |  | 
 |  |  |                 }; | 
 |  |  |                 reader.readAsText(file); | 
 |  |  |               } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |               //image handling | 
 |  |  |               else { | 
 |  |  |                 var reader = new FileReader(); | 
 |  |  | 
 |  |  |             } | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var workarea = $("#workarea") | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         function onDragEnter(e) { | 
 |  |  |           e.stopPropagation(); | 
 |  |  |           e.preventDefault(); | 
 |  |  | 
 |  |  |         workarea[0].addEventListener('dragover', onDragOver, false); | 
 |  |  |         workarea[0].addEventListener('dragleave', onDragLeave, false); | 
 |  |  |         workarea[0].addEventListener('drop', import_image, false); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var open = $('<input type="file">').change(function() { | 
 |  |  |           var f = this; | 
 |  |  |           Editor.openPrep(function(ok) { | 
 |  |  | 
 |  |  |           }); | 
 |  |  |         }); | 
 |  |  |         $("#tool_open").show().prepend(open); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var img_import = $('<input type="file">').change(import_image); | 
 |  |  |         $("#tool_import").show().prepend(img_import); | 
 |  |  |       } | 
 |  |  |  | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       var updateCanvas = Editor.updateCanvas = function(center, new_ctr) { | 
 |  |  |         var w = workarea.width(), h = workarea.height(); | 
 |  |  |         var w_orig = w, h_orig = h; | 
 |  |  |         var zoom = svgCanvas.getZoom(); | 
 |  |  |         var w_area = workarea; | 
 |  |  |         var cnvs = $("#svgcanvas"); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var old_ctr = { | 
 |  |  |           x: w_area[0].scrollLeft + w_orig/2, | 
 |  |  |           y: w_area[0].scrollTop + h_orig/2 | 
 |  |  |         }; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var multi = curConfig.canvas_expansion; | 
 |  |  |         w = Math.max(w_orig, svgCanvas.contentW * zoom * multi); | 
 |  |  |         h = Math.max(h_orig, svgCanvas.contentH * zoom * multi); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(w == w_orig && h == h_orig) { | 
 |  |  |           workarea.css('overflow','hidden'); | 
 |  |  |         } else { | 
 |  |  |           workarea.css('overflow','scroll'); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var old_can_y = cnvs.height()/2; | 
 |  |  |         var old_can_x = cnvs.width()/2; | 
 |  |  |         cnvs.width(w).height(h); | 
 |  |  |         var new_can_y = h/2; | 
 |  |  |         var new_can_x = w/2; | 
 |  |  |         var offset = svgCanvas.updateCanvas(w, h); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var ratio = new_can_x / old_can_x; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |         var scroll_x = w/2 - w_orig/2; | 
 |  |  |         var scroll_y = h/2 - h_orig/2; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(!new_ctr) { | 
 |  |  |      | 
 |  |  |  | 
 |  |  |           var old_dist_x = old_ctr.x - old_can_x; | 
 |  |  |           var new_x = new_can_x + old_dist_x * ratio; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |           var old_dist_y = old_ctr.y - old_can_y; | 
 |  |  |           var new_y = new_can_y + old_dist_y * ratio; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |           new_ctr = { | 
 |  |  |             x: new_x, | 
 |  |  |             y: new_y | 
 |  |  |           }; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |         } else { | 
 |  |  |           new_ctr.x += offset.x, | 
 |  |  |           new_ctr.y += offset.y; | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         //width.val(offset.x) | 
 |  |  |         //height.val(offset.y) | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         if(center) { | 
 |  |  |           // Go to top-left for larger documents | 
 |  |  |           if(svgCanvas.contentW > w_area.width()) { | 
 |  |  | 
 |  |  |           workarea.scroll(); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Make [1,2,5] array | 
 |  |  |       var r_intervals = []; | 
 |  |  |       for(var i = .1; i < 1E5; i *= 10) { | 
 |  |  | 
 |  |  |         r_intervals.push(2 * i); | 
 |  |  |         r_intervals.push(5 * i); | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       function updateRulers(scanvas, zoom) { | 
 |  |  |         var workarea = document.getElementById("workarea"); | 
 |  |  |         var title_show = document.getElementById("title_show"); | 
 |  |  | 
 |  |  |         var offset_y = 48; | 
 |  |  |         if(!zoom) zoom = svgCanvas.getZoom(); | 
 |  |  |         if(!scanvas) scanvas = $("#svgcanvas"); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var limit = 30000; | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var c_elem = svgCanvas.getContentElem(); | 
 |  |  |          | 
 |  |  |  | 
 |  |  |         var units = svgedit.units.getTypeMap(); | 
 |  |  |         var unit = units[curConfig.baseUnit]; // 1 = 1px | 
 |  |  |        | 
 |  |  |  | 
 |  |  |         for(var d = 0; d < 2; d++) { | 
 |  |  |           var is_x = (d === 0); | 
 |  |  |           var dim = is_x ? 'x' : 'y'; | 
 |  |  |           var lentype = is_x?'width':'height'; | 
 |  |  |           var content_d = c_elem.getAttribute(dim)-0; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var $hcanv_orig = $('#ruler_' + dim + ' canvas:first'); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Bit of a hack to fully clear the canvas in Safari & IE9 | 
 |  |  |           $hcanv = $hcanv_orig.clone(); | 
 |  |  |           $hcanv_orig.replaceWith($hcanv); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var hcanv = $hcanv[0]; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Set the canvas size to the width of the container | 
 |  |  |           var ruler_len = scanvas[lentype]()*2; | 
 |  |  |           var total_len = ruler_len; | 
 |  |  |           hcanv.parentNode.style[lentype] = total_len + 'px'; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var canv_count = 1; | 
 |  |  |           var ctx_num = 0; | 
 |  |  |           var ctx_arr; | 
 |  |  |           var ctx = hcanv.getContext("2d"); | 
 |  |  |            | 
 |  |  |           ctx.fillStyle = "rgb(200,0,0)";  | 
 |  |  |           ctx.fillRect(0,0,hcanv.width,hcanv.height);  | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           ctx.fillStyle = "rgb(200,0,0)"; | 
 |  |  |           ctx.fillRect(0,0,hcanv.width,hcanv.height); | 
 |  |  |  | 
 |  |  |           // Remove any existing canvasses | 
 |  |  |           $hcanv.siblings().remove(); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Create multiple canvases when necessary (due to browser limits) | 
 |  |  |           if(ruler_len >= limit) { | 
 |  |  |             var num = parseInt(ruler_len / limit) + 1; | 
 |  |  | 
 |  |  |               hcanv.parentNode.appendChild(copy); | 
 |  |  |               ctx_arr[i] = copy.getContext('2d'); | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             copy[lentype] = ruler_len % limit; | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // set copy width to last | 
 |  |  |             ruler_len = limit; | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           hcanv[lentype] = ruler_len; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var u_multi = unit * zoom; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Calculate the main number interval | 
 |  |  |           var raw_m = 50 / u_multi; | 
 |  |  |           var multi = 1; | 
 |  |  | 
 |  |  |               break; | 
 |  |  |             } | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           var big_int = multi * u_multi; | 
 |  |  |           ctx.font = "normal 9px 'Lucida Grande', sans-serif"; | 
 |  |  |           ctx.fillStyle = "#777"; | 
 |  |  | 
 |  |  |               ctx.moveTo(15, cur_d); | 
 |  |  |               ctx.lineTo(0, cur_d); | 
 |  |  |             } | 
 |  |  |    | 
 |  |  |  | 
 |  |  |             var num = (label_pos - content_d) / u_multi; | 
 |  |  |             var label; | 
 |  |  |             if(multi >= 1) { | 
 |  |  | 
 |  |  |               var decs = (multi+'').split('.')[1].length; | 
 |  |  |               label = num.toFixed(decs)-0; | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // Do anything special for negative numbers? | 
 |  |  | //            var is_neg = label < 0; | 
 |  |  | //            real_d2 = Math.abs(real_d2); | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             // Change 1000s to Ks | 
 |  |  |             if(label !== 0 && label !== 1000 && label % 1000 === 0) { | 
 |  |  |               label = (label / 1000) + 'K'; | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             if(is_x) { | 
 |  |  |               ctx.fillText(label, ruler_d+2, 8); | 
 |  |  |               ctx.fillStyle = "#777"; | 
 |  |  | 
 |  |  |                 ctx.fillStyle = "#777"; | 
 |  |  |               } | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |  | 
 |  |  |             var part = big_int / 10; | 
 |  |  |             for(var i = 1; i < 10; i++) { | 
 |  |  |               var sub_d = Math.round(ruler_d + part * i) + .5; | 
 |  |  | 
 |  |  |                 ruler_d -= limit; | 
 |  |  |                 sub_d = Math.round(ruler_d + part * i) + .5; | 
 |  |  |               } | 
 |  |  |                | 
 |  |  |  | 
 |  |  |               var line_num = (i % 2)?12:10; | 
 |  |  |               if(is_x) { | 
 |  |  |                 ctx.moveTo(sub_d, 15); | 
 |  |  | 
 |  |  |           ctx.stroke(); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |      | 
 |  |  |  | 
 |  |  | //      $(function() { | 
 |  |  |         updateCanvas(true); | 
 |  |  | //      }); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |     //  var revnums = "svg-editor.js ($Rev: 2083 $) "; | 
 |  |  |     //  revnums += svgCanvas.getVersion(); | 
 |  |  |     //  $('#copyright')[0].setAttribute("title", revnums); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       // Callback handler for embedapi.js | 
 |  |  |       try{ | 
 |  |  |         var json_encode = function(obj){ | 
 |  |  | 
 |  |  |         var cbid = parseInt(e.data.substr(0, e.data.indexOf(";"))); | 
 |  |  |         try{ | 
 |  |  |           e.source.postMessage("SVGe"+cbid+";"+json_encode(eval(e.data)), "*"); | 
 |  |  |         }catch(err){           | 
 |  |  |         }catch(err){ | 
 |  |  |           e.source.postMessage("SVGe"+cbid+";error:"+err.message, "*"); | 
 |  |  |         } | 
 |  |  |       }, false) | 
 |  |  |       }catch(err){ | 
 |  |  |         window.embed_error = err; | 
 |  |  |       } | 
 |  |  |        | 
 |  |  |      | 
 |  |  |      | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |       // For Compatibility with older extensions | 
 |  |  |       $(function() { | 
 |  |  |         window.svgCanvas = svgCanvas; | 
 |  |  |         svgCanvas.ready = methodDraw.ready; | 
 |  |  |       }); | 
 |  |  |      | 
 |  |  |      | 
 |  |  |  | 
 |  |  |  | 
 |  |  |       Editor.setLang = function(lang, allStrings) { | 
 |  |  |         $.pref('lang', lang); | 
 |  |  |         $('#lang_select').val(lang); | 
 |  |  |         if(allStrings) { | 
 |  |  |          | 
 |  |  |  | 
 |  |  |           var notif = allStrings.notification; | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           svgCanvas.runExtensions("langChanged", lang); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Update flyout tooltips | 
 |  |  |           setFlyoutTitles(); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Copy title for certain tool elements | 
 |  |  |           var elems = { | 
 |  |  |             '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block', | 
 |  |  | 
 |  |  |             '#linejoin_miter': '#cur_linejoin', | 
 |  |  |             '#linecap_butt': '#cur_linecap' | 
 |  |  |           } | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           $.each(elems, function(source, dest) { | 
 |  |  |             $(dest).attr('title', $(source)[0].title); | 
 |  |  |           }); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |           // Copy alignment titles | 
 |  |  |           $('#multiselected_panel div[id^=tool_align]').each(function() { | 
 |  |  |             $('#tool_pos' + this.id.substr(10))[0].title = this.title; | 
 |  |  |           }); | 
 |  |  |            | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |       }; | 
 |  |  |     }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     var callbacks = []; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     function loadSvgString(str, callback) { | 
 |  |  |       var success = svgCanvas.setSvgString(str) !== false; | 
 |  |  |       callback = callback || $.noop; | 
 |  |  | 
 |  |  |         }); | 
 |  |  |       } | 
 |  |  |     } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     Editor.ready = function(cb) { | 
 |  |  |       if(!is_ready) { | 
 |  |  |         callbacks.push(cb); | 
 |  |  | 
 |  |  |       }); | 
 |  |  |       is_ready = true; | 
 |  |  |     }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     Editor.loadFromString = function(str) { | 
 |  |  |       Editor.ready(function() { | 
 |  |  |         loadSvgString(str); | 
 |  |  |       }); | 
 |  |  |     }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     Editor.loadFromURL = function(url, opts) { | 
 |  |  |       if(!opts) opts = {}; | 
 |  |  |  | 
 |  |  |       var cache = opts.cache; | 
 |  |  |       var cb = opts.callback; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |       Editor.ready(function() { | 
 |  |  |         $.ajax({ | 
 |  |  |           'url': url, | 
 |  |  | 
 |  |  |         }); | 
 |  |  |       }); | 
 |  |  |     }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     Editor.loadFromDataURI = function(str) { | 
 |  |  |       Editor.ready(function() { | 
 |  |  |         var pre = 'data:image/svg+xml;base64,'; | 
 |  |  | 
 |  |  |         loadSvgString(svgedit.utilities.decode64(src)); | 
 |  |  |       }); | 
 |  |  |     }; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     Editor.addExtension = function() { | 
 |  |  |       var args = arguments; | 
 |  |  |        | 
 |  |  |  | 
 |  |  |       // Note that we don't want this on Editor.ready since some extensions | 
 |  |  |       // may want to run before then (like server_opensave). | 
 |  |  |       $(function() { | 
 |  |  | 
 |  |  |  | 
 |  |  |     return Editor; | 
 |  |  |   }(jQuery); | 
 |  |  |    | 
 |  |  |  | 
 |  |  |   // Run init once DOM is loaded | 
 |  |  |   $(methodDraw.init); | 
 |  |  |    | 
 |  |  |  | 
 |  |  | })(); | 
 |  |  |  | 
 |  |  | })(); |