/*globals svgEditor, svgedit, svgCanvas, $*/ /*jslint vars: true, eqeq: true, todo: true*/ /* * ext-foreignobject.js * * Licensed under the Apache License, Version 2 * * Copyright(c) 2010 Jacques Distler * Copyright(c) 2010 Alexis Deveria * */ svgEditor.addExtension("foreignObject", function(S) { var NS = svgedit.NS, Utils = svgedit.utilities, svgcontent = S.svgcontent, addElem = S.addSvgElementFromJson, selElems, editingforeign = false, svgdoc = S.svgroot.parentNode.ownerDocument, started, newFO; var properlySourceSizeTextArea = function () { // TODO: remove magic numbers here and get values from CSS var height = $('#svg_source_container').height() - 80; $('#svg_source_textarea').css('height', height); }; function showPanel(on) { var fc_rules = $('#fc_rules'); if(!fc_rules.length) { fc_rules = $('').appendTo('head'); } fc_rules.text(!on?"":" #tool_topath { display: none !important; }"); $('#foreignObject_panel').toggle(on); } function toggleSourceButtons(on) { $('#tool_source_save, #tool_source_cancel').toggle(!on); $('#foreign_save, #foreign_cancel').toggle(on); } // Function: setForeignString(xmlString, elt) // This function sets the content of element elt to the input XML. // // Parameters: // xmlString - The XML text. // elt - the parent element to append to // // Returns: // This function returns false if the set was unsuccessful, true otherwise. function setForeignString(xmlString) { var elt = selElems[0]; try { // convert string into XML document var newDoc = Utils.text2xml('' + xmlString + ''); // run it through our sanitizer to remove anything we do not support S.sanitizeSvg(newDoc.documentElement); elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt); S.call("changed", [elt]); svgCanvas.clearSelection(); } catch(e) { console.log(e); return false; } return true; } function showForeignEditor() { var elt = selElems[0]; if (!elt || editingforeign) {return;} editingforeign = true; toggleSourceButtons(true); elt.removeAttribute('fill'); var str = S.svgToString(elt, 0); $('#svg_source_textarea').val(str); $('#svg_source_editor').fadeIn(); properlySourceSizeTextArea(); $('#svg_source_textarea').focus(); } function setAttr(attr, val) { svgCanvas.changeSelectedAttribute(attr, val); S.call("changed", selElems); } return { name: "foreignObject", svgicons: svgEditor.curConfig.extPath + "foreignobject-icons.xml", buttons: [{ id: "tool_foreign", type: "mode", title: "Foreign Object Tool", events: { 'click': function() { svgCanvas.setMode('foreign'); } } },{ id: "edit_foreign", type: "context", panel: "foreignObject_panel", title: "Edit ForeignObject Content", events: { 'click': function() { showForeignEditor(); } } }], context_tools: [{ type: "input", panel: "foreignObject_panel", title: "Change foreignObject's width", id: "foreign_width", label: "w", size: 3, events: { change: function() { setAttr('width', this.value); } } },{ type: "input", panel: "foreignObject_panel", title: "Change foreignObject's height", id: "foreign_height", label: "h", events: { change: function() { setAttr('height', this.value); } } }, { type: "input", panel: "foreignObject_panel", title: "Change foreignObject's font size", id: "foreign_font_size", label: "font-size", size: 2, defval: 16, events: { change: function() { setAttr('font-size', this.value); } } } ], callback: function() { $('#foreignObject_panel').hide(); var endChanges = function() { $('#svg_source_editor').hide(); editingforeign = false; $('#svg_source_textarea').blur(); toggleSourceButtons(false); }; // TODO: Needs to be done after orig icon loads setTimeout(function() { // Create source save/cancel buttons var save = $('#tool_source_save').clone() .hide().attr('id', 'foreign_save').unbind() .appendTo("#tool_source_back").click(function() { if (!editingforeign) {return;} if (!setForeignString($('#svg_source_textarea').val())) { $.confirm("Errors found. Revert to original?", function(ok) { if(!ok) {return false;} endChanges(); }); } else { endChanges(); } // setSelectMode(); }); var cancel = $('#tool_source_cancel').clone() .hide().attr('id', 'foreign_cancel').unbind() .appendTo("#tool_source_back").click(function() { endChanges(); }); }, 3000); }, mouseDown: function(opts) { var e = opts.event; if(svgCanvas.getMode() == "foreign") { started = true; newFO = S.addSvgElementFromJson({ "element": "foreignObject", "attr": { "x": opts.start_x, "y": opts.start_y, "id": S.getNextId(), "font-size": 16, //cur_text.font_size, "width": "48", "height": "20", "style": "pointer-events:inherit" } }); var m = svgdoc.createElementNS(NS.MATH, 'math'); m.setAttributeNS(NS.XMLNS, 'xmlns', NS.MATH); m.setAttribute('display', 'inline'); var mi = svgdoc.createElementNS(NS.MATH, 'mi'); mi.setAttribute('mathvariant', 'normal'); mi.textContent = "\u03A6"; var mo = svgdoc.createElementNS(NS.MATH, 'mo'); mo.textContent = "\u222A"; var mi2 = svgdoc.createElementNS(NS.MATH, 'mi'); mi2.textContent = "\u2133"; m.appendChild(mi); m.appendChild(mo); m.appendChild(mi2); newFO.appendChild(m); return { started: true }; } }, mouseUp: function(opts) { var e = opts.event; if(svgCanvas.getMode() == "foreign" && started) { var attrs = $(newFO).attr(["width", "height"]); var keep = (attrs.width != 0 || attrs.height != 0); svgCanvas.addToSelection([newFO], true); return { keep: keep, element: newFO }; } }, selectedChanged: function(opts) { // Use this to update the current selected elements selElems = opts.elems; var i = selElems.length; while(i--) { var elem = selElems[i]; if(elem && elem.tagName === 'foreignObject') { if(opts.selectedElement && !opts.multiselected) { $('#foreign_font_size').val(elem.getAttribute("font-size")); $('#foreign_width').val(elem.getAttribute("width")); $('#foreign_height').val(elem.getAttribute("height")); showPanel(true); } else { showPanel(false); } } else { showPanel(false); } } }, elementChanged: function(opts) { var elem = opts.elems[0]; } }; });