1 | /*globals svgEditor, svgCanvas, $*/
|
---|
2 | /*jslint vars: true, eqeq: true*/
|
---|
3 | /*
|
---|
4 | * ext-helloworld.js
|
---|
5 | *
|
---|
6 | * Licensed under the MIT License
|
---|
7 | *
|
---|
8 | * Copyright(c) 2010 Alexis Deveria
|
---|
9 | *
|
---|
10 | */
|
---|
11 | var kiwianaClicked = false;
|
---|
12 |
|
---|
13 | svgEditor.addExtension("Kiwiana", function() {'use strict';
|
---|
14 |
|
---|
15 |
|
---|
16 |
|
---|
17 | var uiStrings = svgEditor.uiStrings;
|
---|
18 |
|
---|
19 | $.extend(uiStrings, {
|
---|
20 | imagelib: {
|
---|
21 | select_lib: 'Select an image library',
|
---|
22 | show_list: 'Show library list',
|
---|
23 | import_single: 'Import single',
|
---|
24 | import_multi: 'Import multiple',
|
---|
25 | open: 'Open as new document'
|
---|
26 | }
|
---|
27 | });
|
---|
28 |
|
---|
29 | var kimg_libs = [
|
---|
30 | {
|
---|
31 | name: 'Kiwiana library',
|
---|
32 | url: svgEditor.curConfig.extPath + '../../../kiwiana/index.jsp',
|
---|
33 | description: 'A library of Kiwiana SVG files to provide some inspiration to design'
|
---|
34 | },
|
---|
35 | {
|
---|
36 | name: 'Openclipart',
|
---|
37 | url: 'http://openclipart.org/svgedit',
|
---|
38 | description: 'Share and Use Images. Over 50,000 Public Domain SVG Images and Growing.'
|
---|
39 | }
|
---|
40 | ];
|
---|
41 |
|
---|
42 | function closeBrowser() {
|
---|
43 | $('#kimgbrowse_holder').hide();
|
---|
44 | }
|
---|
45 |
|
---|
46 | function importImage(url) {
|
---|
47 | var newImage = svgCanvas.addSvgElementFromJson({
|
---|
48 | "element": "image",
|
---|
49 | "attr": {
|
---|
50 | "x": 0,
|
---|
51 | "y": 0,
|
---|
52 | "width": 0,
|
---|
53 | "height": 0,
|
---|
54 | "id": svgCanvas.getNextId(),
|
---|
55 | "style": "pointer-events:inherit"
|
---|
56 | }
|
---|
57 | });
|
---|
58 | svgCanvas.clearSelection();
|
---|
59 | svgCanvas.addToSelection([newImage]);
|
---|
60 | svgCanvas.setImageURL(url);
|
---|
61 | }
|
---|
62 |
|
---|
63 | var mode = 's';
|
---|
64 | var multi_arr = [];
|
---|
65 | var tranfer_stopped = false;
|
---|
66 | var pending = {};
|
---|
67 | var preview, submit;
|
---|
68 |
|
---|
69 | window.addEventListener("message", function(evt) {
|
---|
70 | // Receive postMessage data
|
---|
71 | var response = evt.data;
|
---|
72 |
|
---|
73 | if (!response || typeof response !== "string") { // Todo: Should namespace postMessage API for this extension and filter out here
|
---|
74 | // Do nothing
|
---|
75 | return;
|
---|
76 | }
|
---|
77 | try { // This block can be removed if embedAPI moves away from a string to an object (if IE9 support not needed)
|
---|
78 | var res = JSON.parse(response);
|
---|
79 | if (res.namespace) { // Part of embedAPI communications
|
---|
80 | return;
|
---|
81 | }
|
---|
82 | }
|
---|
83 | catch (e) {}
|
---|
84 |
|
---|
85 | var char1 = response.charAt(0);
|
---|
86 | var id;
|
---|
87 | var svg_str;
|
---|
88 | var img_str;
|
---|
89 |
|
---|
90 | if (char1 != "{" && tranfer_stopped) {
|
---|
91 | tranfer_stopped = false;
|
---|
92 | return;
|
---|
93 | }
|
---|
94 |
|
---|
95 | if (char1 == '|') {
|
---|
96 | var secondpos = response.indexOf('|', 1);
|
---|
97 | id = response.substr(1, secondpos-1);
|
---|
98 | response = response.substr(secondpos+1);
|
---|
99 | char1 = response.charAt(0);
|
---|
100 | }
|
---|
101 |
|
---|
102 |
|
---|
103 | // Hide possible transfer dialog box
|
---|
104 | $('#dialog_box').hide();
|
---|
105 | var entry, cur_meta;
|
---|
106 | switch (char1) {
|
---|
107 | case '{':
|
---|
108 | // Metadata
|
---|
109 | tranfer_stopped = false;
|
---|
110 | cur_meta = JSON.parse(response);
|
---|
111 |
|
---|
112 | pending[cur_meta.id] = cur_meta;
|
---|
113 |
|
---|
114 | var name = (cur_meta.name || 'file');
|
---|
115 |
|
---|
116 | var message = uiStrings.notification.retrieving.replace('%s', name);
|
---|
117 |
|
---|
118 | if (mode != 'm') {
|
---|
119 | $.process_cancel(message, function() {
|
---|
120 | tranfer_stopped = true;
|
---|
121 | // Should a message be sent back to the frame?
|
---|
122 |
|
---|
123 | $('#dialog_box').hide();
|
---|
124 | });
|
---|
125 | } else {
|
---|
126 | entry = $('<div>' + message + '</div>').data('id', cur_meta.id);
|
---|
127 | preview.append(entry);
|
---|
128 | cur_meta.entry = entry;
|
---|
129 | }
|
---|
130 |
|
---|
131 | return;
|
---|
132 | case '<':
|
---|
133 | svg_str = true;
|
---|
134 | break;
|
---|
135 | case 'd':
|
---|
136 | if (response.indexOf('data:image/svg+xml') === 0) {
|
---|
137 | var pre = 'data:image/svg+xml;base64,';
|
---|
138 | var src = response.substring(pre.length);
|
---|
139 | response = svgedit.utilities.decode64(src);
|
---|
140 | svg_str = true;
|
---|
141 | break;
|
---|
142 | } else if (response.indexOf('data:image/') === 0) {
|
---|
143 | img_str = true;
|
---|
144 | break;
|
---|
145 | }
|
---|
146 | // Else fall through
|
---|
147 | default:
|
---|
148 | // TODO: See if there's a way to base64 encode the binary data stream
|
---|
149 | // var str = 'data:;base64,' + svgedit.utilities.encode64(response, true);
|
---|
150 |
|
---|
151 | // Assume it's raw image data
|
---|
152 | // importImage(str);
|
---|
153 |
|
---|
154 | // Don't give warning as postMessage may have been used by something else
|
---|
155 | if (mode !== 'm') {
|
---|
156 | closeBrowser();
|
---|
157 | } else {
|
---|
158 | pending[id].entry.remove();
|
---|
159 | }
|
---|
160 | // $.alert('Unexpected data was returned: ' + response, function() {
|
---|
161 | // if (mode !== 'm') {
|
---|
162 | // closeBrowser();
|
---|
163 | // } else {
|
---|
164 | // pending[id].entry.remove();
|
---|
165 | // }
|
---|
166 | // });
|
---|
167 | return;
|
---|
168 | }
|
---|
169 |
|
---|
170 | switch (mode) {
|
---|
171 | case 's':
|
---|
172 | // Import one
|
---|
173 | if (svg_str) {
|
---|
174 | svgCanvas.importSvgString(response);
|
---|
175 | } else if (img_str) {
|
---|
176 | importImage(response);
|
---|
177 | }
|
---|
178 | closeBrowser();
|
---|
179 | break;
|
---|
180 | case 'm':
|
---|
181 | // Import multiple
|
---|
182 | multi_arr.push([(svg_str ? 'svg' : 'img'), response]);
|
---|
183 | var title;
|
---|
184 | cur_meta = pending[id];
|
---|
185 | if (svg_str) {
|
---|
186 | if (cur_meta && cur_meta.name) {
|
---|
187 | title = cur_meta.name;
|
---|
188 | } else {
|
---|
189 | // Try to find a title
|
---|
190 | var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement;
|
---|
191 | title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')';
|
---|
192 | }
|
---|
193 | if (cur_meta) {
|
---|
194 | preview.children().each(function() {
|
---|
195 | if ($(this).data('id') == id) {
|
---|
196 | if (cur_meta.preview_url) {
|
---|
197 | $(this).html('<img src="' + cur_meta.preview_url + '">' + title);
|
---|
198 | } else {
|
---|
199 | $(this).text(title);
|
---|
200 | }
|
---|
201 | submit.removeAttr('disabled');
|
---|
202 | }
|
---|
203 | });
|
---|
204 | } else {
|
---|
205 | preview.append('<div>'+title+'</div>');
|
---|
206 | submit.removeAttr('disabled');
|
---|
207 | }
|
---|
208 | } else {
|
---|
209 | if (cur_meta && cur_meta.preview_url) {
|
---|
210 | title = cur_meta.name || '';
|
---|
211 | }
|
---|
212 | if (cur_meta && cur_meta.preview_url) {
|
---|
213 | entry = '<img src="' + cur_meta.preview_url + '">' + title;
|
---|
214 | } else {
|
---|
215 | entry = '<img src="' + response + '">';
|
---|
216 | }
|
---|
217 |
|
---|
218 | if (cur_meta) {
|
---|
219 | preview.children().each(function() {
|
---|
220 | if ($(this).data('id') == id) {
|
---|
221 | $(this).html(entry);
|
---|
222 | submit.removeAttr('disabled');
|
---|
223 | }
|
---|
224 | });
|
---|
225 | } else {
|
---|
226 | preview.append($('<div>').append(entry));
|
---|
227 | submit.removeAttr('disabled');
|
---|
228 | }
|
---|
229 |
|
---|
230 | }
|
---|
231 | break;
|
---|
232 | case 'o':
|
---|
233 | // Open
|
---|
234 | if (!svg_str) {break;}
|
---|
235 | svgEditor.openPrep(function(ok) {
|
---|
236 | if (!ok) {return;}
|
---|
237 | svgCanvas.clear();
|
---|
238 | svgCanvas.setSvgString(response);
|
---|
239 | // updateCanvas();
|
---|
240 | });
|
---|
241 | closeBrowser();
|
---|
242 | break;
|
---|
243 | }
|
---|
244 | }, true);
|
---|
245 |
|
---|
246 | function toggleMulti(show) {
|
---|
247 |
|
---|
248 | $('#lib_framewrap, #kimglib_opts').css({right: (show ? 200 : 10)});
|
---|
249 | if (!preview) {
|
---|
250 | preview = $('<div id=kimglib_preview>').css({
|
---|
251 | position: 'absolute',
|
---|
252 | top: 45,
|
---|
253 | right: 10,
|
---|
254 | width: 180,
|
---|
255 | bottom: 45,
|
---|
256 | background: '#fff',
|
---|
257 | overflow: 'auto'
|
---|
258 | }).insertAfter('#lib_framewrap');
|
---|
259 |
|
---|
260 | submit = $('<button disabled>Import selected</button>')
|
---|
261 | .appendTo('#kimgbrowse')
|
---|
262 | .on("click touchend", function() {
|
---|
263 | $.each(multi_arr, function(i) {
|
---|
264 | var type = this[0];
|
---|
265 | var data = this[1];
|
---|
266 | if (type == 'svg') {
|
---|
267 | svgCanvas.importSvgString(data);
|
---|
268 | } else {
|
---|
269 | importImage(data);
|
---|
270 | }
|
---|
271 | svgCanvas.moveSelectedElements(i*20, i*20, false);
|
---|
272 | });
|
---|
273 | preview.empty();
|
---|
274 | multi_arr = [];
|
---|
275 | $('#kimgbrowse_holder').hide();
|
---|
276 | }).css({
|
---|
277 | position: 'absolute',
|
---|
278 | bottom: 10,
|
---|
279 | right: -10
|
---|
280 | });
|
---|
281 |
|
---|
282 | }
|
---|
283 |
|
---|
284 | preview.toggle(show);
|
---|
285 | submit.toggle(show);
|
---|
286 | }
|
---|
287 |
|
---|
288 | function showBrowser() {
|
---|
289 |
|
---|
290 | var browser = $('#kimgbrowse');
|
---|
291 | if (!browser.length) {
|
---|
292 | $('<div id=kimgbrowse_holder><div id=kimgbrowse class=toolbar_button>\
|
---|
293 | </div></div>').insertAfter('#svg_docprops');
|
---|
294 | browser = $('#kimgbrowse');
|
---|
295 |
|
---|
296 | var all_libs = uiStrings.imagelib.select_lib;
|
---|
297 |
|
---|
298 | var lib_opts = $('<ul id=kimglib_opts>').appendTo(browser);
|
---|
299 | var frame = $('<iframe/>').prependTo(browser).hide().wrap('<div id=lib_framewrap>');
|
---|
300 |
|
---|
301 | var header = $('<h1>').prependTo(browser).text(all_libs).css({
|
---|
302 | position: 'absolute',
|
---|
303 | top: 0,
|
---|
304 | left: 0,
|
---|
305 | width: '100%'
|
---|
306 | });
|
---|
307 |
|
---|
308 | var cancel = $('<button>' + uiStrings.common.cancel + '</button>')
|
---|
309 | .appendTo(browser)
|
---|
310 | .on("click touchend", function() {
|
---|
311 | $('#kimgbrowse_holder').hide();
|
---|
312 | }).css({
|
---|
313 | position: 'absolute',
|
---|
314 | top: 5,
|
---|
315 | right: -10
|
---|
316 | });
|
---|
317 |
|
---|
318 | var leftBlock = $('<span>').css({position:'absolute',top:5,left:10}).appendTo(browser);
|
---|
319 |
|
---|
320 | var back = $('<button hidden>' + uiStrings.imagelib.show_list + '</button>')
|
---|
321 | .appendTo(leftBlock)
|
---|
322 | .on("click touchend", function() {
|
---|
323 | frame.attr('src', 'about:blank').hide();
|
---|
324 | lib_opts.show();
|
---|
325 | header.text(all_libs);
|
---|
326 | back.hide();
|
---|
327 | }).css({
|
---|
328 | 'margin-right': 5
|
---|
329 | }).hide();
|
---|
330 |
|
---|
331 | var type = $('<select><option value=s>' +
|
---|
332 | uiStrings.imagelib.import_single + '</option><option value=m>' +
|
---|
333 | uiStrings.imagelib.import_multi + '</option><option value=o>' +
|
---|
334 | uiStrings.imagelib.open + '</option></select>').appendTo(leftBlock).change(function() {
|
---|
335 | mode = $(this).val();
|
---|
336 | switch (mode) {
|
---|
337 | case 's':
|
---|
338 | case 'o':
|
---|
339 | toggleMulti(false);
|
---|
340 | break;
|
---|
341 |
|
---|
342 | case 'm':
|
---|
343 | // Import multiple
|
---|
344 | toggleMulti(true);
|
---|
345 | break;
|
---|
346 | }
|
---|
347 | }).css({
|
---|
348 | 'margin-top': 10
|
---|
349 | });
|
---|
350 |
|
---|
351 | cancel.prepend($.getSvgIcon('cancel', true));
|
---|
352 | back.prepend($.getSvgIcon('tool_imagelib', true));
|
---|
353 |
|
---|
354 | $.each(kimg_libs, function(i, opts) {
|
---|
355 | $('<li>')
|
---|
356 | .appendTo(lib_opts)
|
---|
357 | .text(opts.name)
|
---|
358 | .on("click touchend", function() {
|
---|
359 | frame.attr('src', opts.url).show();
|
---|
360 | header.text(opts.name);
|
---|
361 | lib_opts.hide();
|
---|
362 | back.show();
|
---|
363 | }).append('<span>' + opts.description + '</span>');
|
---|
364 | });
|
---|
365 |
|
---|
366 | } else {
|
---|
367 | $('#kimgbrowse_holder').show();
|
---|
368 | }
|
---|
369 | }
|
---|
370 |
|
---|
371 |
|
---|
372 |
|
---|
373 | return {
|
---|
374 | name: "Kiwiana",
|
---|
375 | // The icon for 'Kiwiana library'
|
---|
376 | svgicons: svgEditor.curConfig.extPath + "kiwiana-icon.xml",
|
---|
377 |
|
---|
378 | // Multiple buttons can be added in this array
|
---|
379 | buttons: [{
|
---|
380 | // Must match the icon ID in kiwiana-icon.xml
|
---|
381 | id: "kiwiana",
|
---|
382 |
|
---|
383 | // This indicates that the button will be added independently to the buttons in the button
|
---|
384 | // panel on the left side (it will not be unselected when one of the other buttons is selected)
|
---|
385 | type: "context",
|
---|
386 |
|
---|
387 | panel: "tools_left",
|
---|
388 |
|
---|
389 | // Tooltip text
|
---|
390 | title: "Access the Kiwiana Shape Library",
|
---|
391 |
|
---|
392 | // Events
|
---|
393 | events: {
|
---|
394 | 'click': function() {
|
---|
395 |
|
---|
396 | console.log("**** ext-kiwiana click()");
|
---|
397 | showBrowser();
|
---|
398 |
|
---|
399 | // Toggle the Kiwiana button
|
---|
400 | if (kiwianaClicked == true)
|
---|
401 | {
|
---|
402 | kiwianaClicked = false;
|
---|
403 | // Hide advanced features
|
---|
404 | kiwianaButton(kiwianaClicked);
|
---|
405 | }
|
---|
406 | else
|
---|
407 | {
|
---|
408 | kiwianaClicked = true;
|
---|
409 | // Hide advanced features
|
---|
410 | kiwianaButton(kiwianaClicked);
|
---|
411 | }
|
---|
412 | }
|
---|
413 | }
|
---|
414 | }],
|
---|
415 | // This is triggered when the main mouse button is pressed down
|
---|
416 | // on the editor canvas (not the tool panels)
|
---|
417 | mouseDownXX: function() {
|
---|
418 | kiwianaButton(kiwianaClicked);
|
---|
419 |
|
---|
420 | // The returned object must include "started" with
|
---|
421 | // a value of true in order for mouseUp to be triggered
|
---|
422 | return {started: true};
|
---|
423 | },
|
---|
424 |
|
---|
425 | // This is triggered from anywhere, but "started" must have been set
|
---|
426 | // to true (see above). Note that "opts" is an object with event info
|
---|
427 | mouseUpXX: function(opts) {
|
---|
428 | console.log("**** ext-kiwiana mouseUp()");
|
---|
429 | showBrowser();
|
---|
430 | //advancedButton(kiwianaClicked);
|
---|
431 | },
|
---|
432 |
|
---|
433 | elementChangedXX: function(opts)
|
---|
434 | {
|
---|
435 | //kiwianaButton(kiwianaClicked);
|
---|
436 | },
|
---|
437 |
|
---|
438 | callback: function(opts) {
|
---|
439 | //kiwianaClicked = false;
|
---|
440 | //kiwianaButton(kiwianaClicked);
|
---|
441 | console.log("**** ext-kiwiana callback()");
|
---|
442 |
|
---|
443 | $('<style>').text('\
|
---|
444 | #kimgbrowse_holder {\
|
---|
445 | position: absolute;\
|
---|
446 | top: 0;\
|
---|
447 | left: 0;\
|
---|
448 | width: 100%;\
|
---|
449 | height: 100%;\
|
---|
450 | background-color: rgba(0, 0, 0, .5);\
|
---|
451 | z-index: 5;\
|
---|
452 | }\
|
---|
453 | \
|
---|
454 | #kimgbrowse {\
|
---|
455 | position: absolute;\
|
---|
456 | top: 25px;\
|
---|
457 | left: 25px;\
|
---|
458 | right: 25px;\
|
---|
459 | bottom: 25px;\
|
---|
460 | min-width: 300px;\
|
---|
461 | min-height: 200px;\
|
---|
462 | background: #B0B0B0;\
|
---|
463 | border: 1px outset #777;\
|
---|
464 | }\
|
---|
465 | #kimgbrowse h1 {\
|
---|
466 | font-size: 20px;\
|
---|
467 | margin: .4em;\
|
---|
468 | text-align: center;\
|
---|
469 | }\
|
---|
470 | #lib_framewrap,\
|
---|
471 | #kimgbrowse > ul {\
|
---|
472 | position: absolute;\
|
---|
473 | top: 45px;\
|
---|
474 | left: 10px;\
|
---|
475 | right: 10px;\
|
---|
476 | bottom: 10px;\
|
---|
477 | background: white;\
|
---|
478 | margin: 0;\
|
---|
479 | padding: 0;\
|
---|
480 | }\
|
---|
481 | #kimgbrowse > ul {\
|
---|
482 | overflow: auto;\
|
---|
483 | }\
|
---|
484 | #kimgbrowse > div {\
|
---|
485 | border: 1px solid #666;\
|
---|
486 | }\
|
---|
487 | #kimglib_preview > div {\
|
---|
488 | padding: 5px;\
|
---|
489 | font-size: 12px;\
|
---|
490 | }\
|
---|
491 | #kimglib_preview img {\
|
---|
492 | display: block;\
|
---|
493 | margin: 0 auto;\
|
---|
494 | max-height: 100px;\
|
---|
495 | }\
|
---|
496 | #kimgbrowse li {\
|
---|
497 | list-style: none;\
|
---|
498 | padding: .5em;\
|
---|
499 | background: #E8E8E8;\
|
---|
500 | border-bottom: 1px solid #B0B0B0;\
|
---|
501 | line-height: 1.2em;\
|
---|
502 | font-style: sans-serif;\
|
---|
503 | }\
|
---|
504 | #kimgbrowse li > span {\
|
---|
505 | color: #666;\
|
---|
506 | font-size: 15px;\
|
---|
507 | display: block;\
|
---|
508 | }\
|
---|
509 | #kimgbrowse li:hover {\
|
---|
510 | background: #FFC;\
|
---|
511 | cursor: pointer;\
|
---|
512 | }\
|
---|
513 | #kimgbrowse iframe {\
|
---|
514 | width: 100%;\
|
---|
515 | height: 100%;\
|
---|
516 | border: 0;\
|
---|
517 | }\
|
---|
518 | ').appendTo('head');
|
---|
519 |
|
---|
520 |
|
---|
521 | }
|
---|
522 | };
|
---|
523 | });
|
---|
524 |
|
---|
525 | // Function: kiwianaButton
|
---|
526 | // Unless kiwiana button is selected, advanced features will be hidden
|
---|
527 | this.kiwianaButton = function() {
|
---|
528 |
|
---|
529 | console.log("kiwianaButton");
|
---|
530 | //showBrowser();
|
---|
531 | }
|
---|
532 |
|
---|
533 |
|
---|
534 |
|
---|
535 |
|
---|