1 | /*
|
---|
2 | * ext-foreignobject.js
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License, Version 2
|
---|
5 | *
|
---|
6 | * Copyright(c) 2010 Jacques Distler
|
---|
7 | * Copyright(c) 2010 Alexis Deveria
|
---|
8 | *
|
---|
9 | */
|
---|
10 |
|
---|
11 | methodDraw.addExtension("foreignObject", function(S) {
|
---|
12 | var svgcontent = S.svgcontent,
|
---|
13 | addElem = S.addSvgElementFromJson,
|
---|
14 | selElems,
|
---|
15 | svgns = "http://www.w3.org/2000/svg",
|
---|
16 | xlinkns = "http://www.w3.org/1999/xlink",
|
---|
17 | xmlns = "http://www.w3.org/XML/1998/namespace",
|
---|
18 | xmlnsns = "http://www.w3.org/2000/xmlns/",
|
---|
19 | se_ns = "http://svg-edit.googlecode.com",
|
---|
20 | htmlns = "http://www.w3.org/1999/xhtml",
|
---|
21 | mathns = "http://www.w3.org/1998/Math/MathML",
|
---|
22 | editingforeign = false,
|
---|
23 | svgdoc = S.svgroot.parentNode.ownerDocument,
|
---|
24 | started,
|
---|
25 | newFO;
|
---|
26 |
|
---|
27 |
|
---|
28 | var properlySourceSizeTextArea = function(){
|
---|
29 | // TODO: remove magic numbers here and get values from CSS
|
---|
30 | var height = $('#svg_source_container').height() - 80;
|
---|
31 | $('#svg_source_textarea').css('height', height);
|
---|
32 | };
|
---|
33 |
|
---|
34 | function showPanel(on) {
|
---|
35 | var fc_rules = $('#fc_rules');
|
---|
36 | if(!fc_rules.length) {
|
---|
37 | fc_rules = $('<style id="fc_rules"><\/style>').appendTo('head');
|
---|
38 | }
|
---|
39 | fc_rules.text(!on?"":" #tool_topath { display: none !important; }");
|
---|
40 | $('#foreignObject_panel').toggle(on);
|
---|
41 | }
|
---|
42 |
|
---|
43 | function toggleSourceButtons(on) {
|
---|
44 | $('#tool_source_save, #tool_source_cancel').toggle(!on);
|
---|
45 | $('#foreign_save, #foreign_cancel').toggle(on);
|
---|
46 | }
|
---|
47 |
|
---|
48 |
|
---|
49 | // Function: setForeignString(xmlString, elt)
|
---|
50 | // This function sets the content of element elt to the input XML.
|
---|
51 | //
|
---|
52 | // Parameters:
|
---|
53 | // xmlString - The XML text.
|
---|
54 | // elt - the parent element to append to
|
---|
55 | //
|
---|
56 | // Returns:
|
---|
57 | // This function returns false if the set was unsuccessful, true otherwise.
|
---|
58 | function setForeignString(xmlString) {
|
---|
59 | var elt = selElems[0];
|
---|
60 | try {
|
---|
61 | // convert string into XML document
|
---|
62 | var newDoc = Utils.text2xml('<svg xmlns="'+svgns+'" xmlns:xlink="'+xlinkns+'">'+xmlString+'</svg>');
|
---|
63 | // run it through our sanitizer to remove anything we do not support
|
---|
64 | S.sanitizeSvg(newDoc.documentElement);
|
---|
65 | elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt);
|
---|
66 | S.call("changed", [elt]);
|
---|
67 | svgCanvas.clearSelection();
|
---|
68 | } catch(e) {
|
---|
69 | console.log(e);
|
---|
70 | return false;
|
---|
71 | }
|
---|
72 |
|
---|
73 | return true;
|
---|
74 | };
|
---|
75 |
|
---|
76 | function showForeignEditor() {
|
---|
77 | var elt = selElems[0];
|
---|
78 | if (!elt || editingforeign) return;
|
---|
79 | editingforeign = true;
|
---|
80 | toggleSourceButtons(true);
|
---|
81 | elt.removeAttribute('fill');
|
---|
82 |
|
---|
83 | var str = S.svgToString(elt, 0);
|
---|
84 | $('#svg_source_textarea').val(str);
|
---|
85 | $('#svg_source_editor').fadeIn();
|
---|
86 | properlySourceSizeTextArea();
|
---|
87 | $('#svg_source_textarea').focus();
|
---|
88 | }
|
---|
89 |
|
---|
90 | function setAttr(attr, val) {
|
---|
91 | svgCanvas.changeSelectedAttribute(attr, val);
|
---|
92 | S.call("changed", selElems);
|
---|
93 | }
|
---|
94 |
|
---|
95 |
|
---|
96 | return {
|
---|
97 | name: "foreignObject",
|
---|
98 | svgicons: "extensions/foreignobject-icons.xml",
|
---|
99 | buttons: [{
|
---|
100 | id: "tool_foreign",
|
---|
101 | type: "mode",
|
---|
102 | title: "Foreign Object Tool",
|
---|
103 | events: {
|
---|
104 | 'click': function() {
|
---|
105 | svgCanvas.setMode('foreign')
|
---|
106 | }
|
---|
107 | }
|
---|
108 | },{
|
---|
109 | id: "edit_foreign",
|
---|
110 | type: "context",
|
---|
111 | panel: "foreignObject_panel",
|
---|
112 | title: "Edit ForeignObject Content",
|
---|
113 | events: {
|
---|
114 | 'click': function() {
|
---|
115 | showForeignEditor();
|
---|
116 | }
|
---|
117 | }
|
---|
118 | }],
|
---|
119 |
|
---|
120 | context_tools: [{
|
---|
121 | type: "input",
|
---|
122 | panel: "foreignObject_panel",
|
---|
123 | title: "Change foreignObject's width",
|
---|
124 | id: "foreign_width",
|
---|
125 | label: "w",
|
---|
126 | size: 3,
|
---|
127 | events: {
|
---|
128 | change: function() {
|
---|
129 | setAttr('width', this.value);
|
---|
130 | }
|
---|
131 | }
|
---|
132 | },{
|
---|
133 | type: "input",
|
---|
134 | panel: "foreignObject_panel",
|
---|
135 | title: "Change foreignObject's height",
|
---|
136 | id: "foreign_height",
|
---|
137 | label: "h",
|
---|
138 | events: {
|
---|
139 | change: function() {
|
---|
140 | setAttr('height', this.value);
|
---|
141 | }
|
---|
142 | }
|
---|
143 | }, {
|
---|
144 | type: "input",
|
---|
145 | panel: "foreignObject_panel",
|
---|
146 | title: "Change foreignObject's font size",
|
---|
147 | id: "foreign_font_size",
|
---|
148 | label: "font-size",
|
---|
149 | size: 2,
|
---|
150 | defval: 16,
|
---|
151 | events: {
|
---|
152 | change: function() {
|
---|
153 | setAttr('font-size', this.value);
|
---|
154 | }
|
---|
155 | }
|
---|
156 | }
|
---|
157 |
|
---|
158 |
|
---|
159 | ],
|
---|
160 | callback: function() {
|
---|
161 | $('#foreignObject_panel').hide();
|
---|
162 |
|
---|
163 | var endChanges = function() {
|
---|
164 | $('#svg_source_editor').hide();
|
---|
165 | editingforeign = false;
|
---|
166 | $('#svg_source_textarea').blur();
|
---|
167 | toggleSourceButtons(false);
|
---|
168 | }
|
---|
169 |
|
---|
170 | // TODO: Needs to be done after orig icon loads
|
---|
171 | setTimeout(function() {
|
---|
172 | // Create source save/cancel buttons
|
---|
173 | var save = $('#tool_source_save').clone()
|
---|
174 | .hide().attr('id', 'foreign_save').unbind()
|
---|
175 | .appendTo("#tool_source_back").click(function() {
|
---|
176 |
|
---|
177 | if (!editingforeign) return;
|
---|
178 |
|
---|
179 | if (!setForeignString($('#svg_source_textarea').val())) {
|
---|
180 | $.confirm("Errors found. Revert to original?", function(ok) {
|
---|
181 | if(!ok) return false;
|
---|
182 | endChanges();
|
---|
183 | });
|
---|
184 | } else {
|
---|
185 | endChanges();
|
---|
186 | }
|
---|
187 | // setSelectMode();
|
---|
188 | });
|
---|
189 |
|
---|
190 | var cancel = $('#tool_source_cancel').clone()
|
---|
191 | .hide().attr('id', 'foreign_cancel').unbind()
|
---|
192 | .appendTo("#tool_source_back").click(function() {
|
---|
193 | endChanges();
|
---|
194 | });
|
---|
195 |
|
---|
196 | }, 3000);
|
---|
197 | },
|
---|
198 | mouseDown: function(opts) {
|
---|
199 | var e = opts.event;
|
---|
200 |
|
---|
201 | if(svgCanvas.getMode() == "foreign") {
|
---|
202 |
|
---|
203 | started = true;
|
---|
204 | newFO = S.addSvgElementFromJson({
|
---|
205 | "element": "foreignObject",
|
---|
206 | "attr": {
|
---|
207 | "x": opts.start_x,
|
---|
208 | "y": opts.start_y,
|
---|
209 | "id": S.getNextId(),
|
---|
210 | "font-size": 16, //cur_text.font_size,
|
---|
211 | "width": "48",
|
---|
212 | "height": "20",
|
---|
213 | "style": "pointer-events:inherit"
|
---|
214 | }
|
---|
215 | });
|
---|
216 | var m = svgdoc.createElementNS(mathns, 'math');
|
---|
217 | m.setAttributeNS(xmlnsns, 'xmlns', mathns);
|
---|
218 | m.setAttribute('display', 'inline');
|
---|
219 | var mi = svgdoc.createElementNS(mathns, 'mi');
|
---|
220 | mi.setAttribute('mathvariant', 'normal');
|
---|
221 | mi.textContent = "\u03A6";
|
---|
222 | var mo = svgdoc.createElementNS(mathns, 'mo');
|
---|
223 | mo.textContent = "\u222A";
|
---|
224 | var mi2 = svgdoc.createElementNS(mathns, 'mi');
|
---|
225 | mi2.textContent = "\u2133";
|
---|
226 | m.appendChild(mi);
|
---|
227 | m.appendChild(mo);
|
---|
228 | m.appendChild(mi2);
|
---|
229 | newFO.appendChild(m);
|
---|
230 | return {
|
---|
231 | started: true
|
---|
232 | }
|
---|
233 | }
|
---|
234 | },
|
---|
235 | mouseUp: function(opts) {
|
---|
236 | var e = opts.event;
|
---|
237 | if(svgCanvas.getMode() == "foreign" && started) {
|
---|
238 | var attrs = $(newFO).attr(["width", "height"]);
|
---|
239 | keep = (attrs.width != 0 || attrs.height != 0);
|
---|
240 | svgCanvas.addToSelection([newFO], true);
|
---|
241 |
|
---|
242 | return {
|
---|
243 | keep: keep,
|
---|
244 | element: newFO
|
---|
245 | }
|
---|
246 |
|
---|
247 | }
|
---|
248 |
|
---|
249 | },
|
---|
250 | selectedChanged: function(opts) {
|
---|
251 | // Use this to update the current selected elements
|
---|
252 | selElems = opts.elems;
|
---|
253 |
|
---|
254 | var i = selElems.length;
|
---|
255 |
|
---|
256 | while(i--) {
|
---|
257 | var elem = selElems[i];
|
---|
258 | if(elem && elem.tagName == "foreignObject") {
|
---|
259 | if(opts.selectedElement && !opts.multiselected) {
|
---|
260 | $('#foreign_font_size').val(elem.getAttribute("font-size"));
|
---|
261 | $('#foreign_width').val(elem.getAttribute("width"));
|
---|
262 | $('#foreign_height').val(elem.getAttribute("height"));
|
---|
263 |
|
---|
264 | showPanel(true);
|
---|
265 | } else {
|
---|
266 | showPanel(false);
|
---|
267 | }
|
---|
268 | } else {
|
---|
269 | showPanel(false);
|
---|
270 | }
|
---|
271 | }
|
---|
272 | },
|
---|
273 | elementChanged: function(opts) {
|
---|
274 | var elem = opts.elems[0];
|
---|
275 | }
|
---|
276 | };
|
---|
277 | });
|
---|