sketchily 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Sketchily
2
2
 
3
3
  Sketchily allows the easy integration of svg-edit with any rails application.
4
- Currently supports and provides svg-edit-2.6.
4
+
5
+ Currently supports and provides `svg-edit-2.6`.
5
6
 
6
7
  ## Installation
7
8
 
@@ -19,13 +20,68 @@ Or install it yourself as:
19
20
 
20
21
  ## Usage
21
22
 
22
- Sketchily adds new form elements which can be accessed by calling f.sketchily or simply sketchily from inside a form_for |f| or sketchily_tag from inside a form_tag.
23
- Both of these functions work exactly like the equivalent hidden_field functions, except that svg-edit is displayed instead.
24
- The f.sketchily format accepts a method name and an options hash.
25
- The sketchily format accepts an object name, a method name and an options hash.
26
- The sketchily_tag format accepts a tag name, the svg string to be edited and an options hash.
27
- Currently available options are width, height, show_menu (true if you want svg-edit's menu to be displayed), hide_image_tool (true if you want to hide the image tool button), canvas_width (number specifying initial canvas width), canvas_height (number specifying initial canvas height), canvas_expansion (0 if you want to disable scrolling), hide_rulers (true if you want to hide the canvas rulers) and other standard html attributes for the input tag.
28
- It is recommended that the database entries associated with sketchily form elements be of type 'text'.
23
+ Sketchily adds new form elements which can be accessed by calling:
24
+
25
+ - `f.sketchily` or simply `sketchily` from inside a `form_for @my_object |f|`
26
+ - `sketchily_tag` from inside a `form_tag`
27
+
28
+ This gem also adds a helper method that can be called to display the resulting SVG images (without an editor):
29
+
30
+ - `sketchily_show` from any view template
31
+
32
+ ### `sketchily` and `sketchily_tag` functions
33
+
34
+ - Both of these functions work exactly like the equivalent `hidden_field` functions, except that svg-edit is displayed instead.
35
+ - The `f.sketchily` format accepts a method name and an options hash.
36
+ - The sketchily format accepts an object name, a method name and an options hash.
37
+ - The `sketchily_tag` format accepts a tag name, the svg string to be edited and an options hash.
38
+
39
+ Currently available options are:
40
+
41
+ - `width`
42
+ - `height`
43
+ - `show_menu` (true if you want svg-edit's menu to be displayed)
44
+ - `hide_image_tool` (true if you want to hide the image tool button)
45
+ - `canvas_width` (number specifying initial canvas width)
46
+ - `canvas_height` (number specifying initial canvas height)
47
+ - `canvas_expansion` (0 if you want to disable scrolling)
48
+ - `hide_rulers` (true if you want to hide the canvas rulers)
49
+ - other standard html attributes for the input tag
50
+
51
+ It is recommended that the database entries associated with sketchily form elements be of type `text`.
52
+
53
+ Example usage (haml):
54
+
55
+ = form_for @shirt do |f|
56
+ f.text_field :title
57
+ f.sketchily :svg
58
+
59
+ ### `sketchily_show` helper
60
+
61
+ - This function takes the base64-encoded SVG string as an argument and an options hash.
62
+ - The SVG string can be directly read from the field used by the previous functions.
63
+
64
+ Currently available options are:
65
+
66
+ - `width`
67
+ - `height`
68
+
69
+ Passing only one of those options should keep the aspect ratio constant in most browsers.
70
+
71
+ Example usage (haml):
72
+
73
+ = sketchily_show @shirt.svg, :width => "500"
74
+
75
+ ## Browser Support
76
+
77
+ Although more testing is needed, we currently believe sketchily supports any browsers that svg-edit 2.6 supports, namely:
78
+
79
+ - Firefox 1.5+
80
+ - Opera 9.50+
81
+ - Safari 4+
82
+ - Chrome 1+
83
+ - IE 9+
84
+ - IE 6+ (with the Chrome Frame plugin)
29
85
 
30
86
  ## Contributing
31
87
 
@@ -36,4 +92,3 @@ It is recommended that the database entries associated with sketchily form eleme
36
92
  5. Commit your changes (`git commit -am 'Add some feature'`)
37
93
  6. Push to the branch (`git push origin my-new-feature`)
38
94
  7. Create new pull request
39
-
@@ -4,25 +4,18 @@
4
4
  #
5
5
  # Additionally, they may override the following variables:
6
6
  show_menu ||= false
7
- hide_image_tool ||= false
8
- canvas_width ||= 640,
9
- canvas_height ||= 480,
10
- canvas_expansion ||= 3
11
- hide_rulers ||= false
12
7
  width ||= "750px"
13
8
  height ||= "650px" %>
14
9
 
15
10
  <%= javascript_include_tag "embedapi" %>
16
11
  <%= javascript_include_tag "svgutils" %>
17
-
18
12
  <script type="text/javascript">
19
13
  <%= render :partial => "sketchily/embed",
20
14
  :formats => :js,
21
15
  :locals => {:id => id,
22
16
  :value => value,
23
- :show_menu => show_menu,
24
- :hide_image_tool => hide_image_tool} %>
17
+ :show_menu => show_menu} %>
25
18
  </script>
26
19
 
27
- <iframe src="/assets/svg-editor.html?source=&dimensions=<%= "#{canvas_width},#{canvas_height}" %>&canvas_expansion=<%= canvas_expansion %>&showRulers=<%= !hide_rulers %>"
20
+ <iframe src="/assets/svg-editor.html?source="
28
21
  width="<%= width %>" height="<%= height %>" id="svgedit_<%= id %>" onload="initEmbed_<%= id %>();"></iframe>
@@ -8,6 +8,13 @@
8
8
 
9
9
  var svgCanvas_<%= id %> = null;
10
10
 
11
+ function attachSubmitHandler_<%= id %>() {
12
+ $("input#<%= id %>").closest("form").one("submit", function(event) {
13
+ svgCanvas_<%= id %>.getSvgString()(handleSvgData_<%= id %>);
14
+ return false;
15
+ });
16
+ }
17
+
11
18
  function handleSvgData_<%= id %>(data, error) {
12
19
  if (error) {
13
20
  alert('Error: ' + error);
@@ -15,6 +22,7 @@ function handleSvgData_<%= id %>(data, error) {
15
22
  else {
16
23
  $("input#<%= id %>").attr("value", svgedit.utilities.encode64("<?xml version=\"1.0\"?>\n" + data));
17
24
  $("input#<%= id %>").closest("form").submit();
25
+ attachSubmitHandler_<%= id %>();
18
26
  }
19
27
  }
20
28
 
@@ -41,10 +49,7 @@ function initEmbed_<%= id %>() {
41
49
  imageTool.style.display = 'none';
42
50
  <% end %>
43
51
 
44
- $("input#<%= id %>").closest("form").one("submit", function(event) {
45
- svgCanvas_<%= id %>.getSvgString()(handleSvgData_<%= id %>);
46
- event.preventDefault();
47
- });
52
+ attachSubmitHandler_<%= id %>();
48
53
 
49
54
  svgCanvas_<%= id %>.setSvgString(svgedit.utilities.decode64("<%= value.try(:squish) %>"));
50
55
  }
@@ -8,6 +8,13 @@
8
8
 
9
9
  var svgCanvas_<%= id %> = null;
10
10
 
11
+ function attachSubmitHandler_<%= id %>() {
12
+ $("input#<%= id %>").closest("form").one("submit", function(event) {
13
+ svgCanvas_<%= id %>.getSvgString()(handleSvgData_<%= id %>);
14
+ event.preventDefault();
15
+ });
16
+ }
17
+
11
18
  function handleSvgData_<%= id %>(data, error) {
12
19
  if (error) {
13
20
  alert('Error: ' + error);
@@ -15,6 +22,7 @@ function handleSvgData_<%= id %>(data, error) {
15
22
  else {
16
23
  $("input#<%= id %>").attr("value", svgedit.utilities.encode64("<?xml version=\"1.0\"?>\n" + data));
17
24
  $("input#<%= id %>").closest("form").submit();
25
+ attachSubmitHandler_<%= id %>();
18
26
  }
19
27
  }
20
28
 
@@ -36,15 +44,12 @@ function initEmbed_<%= id %>() {
36
44
  toolsTop.style.right = '2px';
37
45
  <% end %>
38
46
 
39
- <% if hide_image %>
47
+ <% if hide_image_tool %>
40
48
  var imageTool = doc.getElementById('tool_image');
41
49
  imageTool.style.display = 'none';
42
50
  <% end %>
43
51
 
44
- $("input#<%= id %>").closest("form").one("submit", function(event) {
45
- svgCanvas_<%= id %>.getSvgString()(handleSvgData_<%= id %>);
46
- event.preventDefault();
47
- });
52
+ attachSubmitHandler_<%= id %>();
48
53
 
49
54
  svgCanvas_<%= id %>.setSvgString(svgedit.utilities.decode64("<%= value.try(:squish) %>"));
50
55
  }
@@ -4,20 +4,16 @@
4
4
  # method
5
5
  # options %>
6
6
 
7
- <% sketchily_tag = ActionView::Helpers::InstanceTag.new(object_name, method, template, options.delete(:object)) %>
7
+ <% sketchily_tag = ActionView::Helpers::InstanceTag.new(object_name, method, template, options.delete(:object))
8
+ sketchily_tag.value = sketchily_tag.value(sketchily_tag.object).try(:squish).try(:html_safe) %>
8
9
 
9
10
  <%= render :partial => "sketchily/embed",
10
11
  :formats => :html,
11
12
  :locals => {:id => sketchily_tag.send(:tag_id),
12
13
  :value => sketchily_tag.value(sketchily_tag.object),
13
14
  :show_menu => options[:show_menu],
14
- :hide_image_tool => options[:hide_image_tool],
15
- :canvas_width => options[:canvas_width],
16
- :canvas_height => options[:canvas_height],
17
- :canvas_expansion => options[:canvas_expansion],
18
- :hide_rulers => options[:hide_rulers],
19
15
  :width => options[:width],
20
16
  :height => options[:height]} %>
21
17
 
22
- <%= sketchily_tag.to_input_field_tag("hidden", options.except(:show_menu, :hide_image_tool, :canvas_dimensions, :canvas_expansion, :hide_rulers, :width, :height)) %>
18
+ <%= sketchily_tag.to_input_field_tag("hidden", options.except(:show_menu, :width, :height)) %>
23
19
 
@@ -9,13 +9,8 @@
9
9
  :locals => {:id => id,
10
10
  :value => value,
11
11
  :show_menu => options[:show_menu],
12
- :hide_image_tool => options[:hide_image_tool],
13
- :canvas_width => options[:canvas_width],
14
- :canvas_height => options[:canvas_height],
15
- :canvas_expansion => options[:canvas_expansion],
16
- :hide_rulers => options[:hide_rulers],
17
12
  :width => options[:width],
18
13
  :height => options[:height]} %>
19
14
 
20
- <%= tag :input, { "type" => "hidden", "name" => name, "id" => id, "value" => value }.update(options.except(:show_menu, :hide_image_tool, :canvas_dimensions, :canvas_expansion, :hide_rulers, :width, :height).stringify_keys) %>
15
+ <%= tag :input, { "type" => "hidden", "name" => name, "id" => id, "value" => value.try(:squish).try(:html_safe) }.update(options.except(:show_menu, :width, :height).stringify_keys) %>
21
16
 
@@ -3,6 +3,7 @@ module Sketchily
3
3
 
4
4
  VIEW = ActionView::Base.new
5
5
  VIEW.view_paths << "#{ROOT}/app/views"
6
+ VIEW.view_paths << "#{ROOT}/app/views/sketchily"
6
7
 
7
8
  def self.render(options = {}, local_assigns = {}, &block)
8
9
  VIEW.render(options, local_assigns, &block)
@@ -12,5 +13,4 @@ end
12
13
  require "sketchily/engine"
13
14
  require "sketchily/sketchily"
14
15
  require "sketchily/sketchily_tag"
15
- require "sketchily/sketchily_show"
16
16
 
@@ -0,0 +1,28 @@
1
+ module Sketchily
2
+ module FormBuilderInstanceMethods
3
+ def sketchily(method, options = {})
4
+ Sketchily.render(:partial => "sketchily/sketchily",
5
+ :locals => {:template => @template, :object_name => @object_name,
6
+ :method => method, :options => objectify_options(options)}).html_safe
7
+ end
8
+
9
+ def svg_edit(method, options = {})
10
+ sketchily(method, options)
11
+ end
12
+ end
13
+
14
+ module ActionViewBaseInstanceMethods
15
+ def sketchily(object_name, method, options = {})
16
+ Sketchily.render(:partial => "sketchily/sketchily",
17
+ :locals => {:template => self, :object_name => object_name,
18
+ :method => method, :options => objectify_options(options)}).html_safe
19
+ end
20
+
21
+ def svg_edit(object_name, method, options = {})
22
+ sketchily(object_name, method, options)
23
+ end
24
+ end
25
+ end
26
+
27
+ ActionView::Helpers::FormBuilder.send :include, Sketchily::FormBuilderInstanceMethods
28
+ ActionView::Base.send :include, Sketchily::ActionViewBaseInstanceMethods
@@ -0,0 +1,15 @@
1
+ module SketchilyTag
2
+ module ActionViewBaseInstanceMethods
3
+ def sketchily_tag(name, value = nil, options = {})
4
+ Sketchily.render(:partial => "sketchily/sketchily_tag",
5
+ :locals => {:name => name, :id => sanitize_to_id(name),
6
+ :value => value, :options => options}).html_safe
7
+ end
8
+
9
+ def svg_edit_tag(name, value = nil, options = {})
10
+ sketchily_tag(name, value, options)
11
+ end
12
+ end
13
+ end
14
+
15
+ ActionView::Base.send :include, SketchilyTag::ActionViewBaseInstanceMethods
@@ -0,0 +1,15 @@
1
+ module Sketchily
2
+ module FormHelperInstanceMethods
3
+ def sketchily(object_name, method, options = {})
4
+ ActionView::Helpers::InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("hidden", options)
5
+ end
6
+ end
7
+
8
+ module FormBuilderInstanceMethods
9
+ def sketchily(method, options = {})
10
+ @template.hidden_field(@object_name, method, objectify_options(options))
11
+ end
12
+ end
13
+ end
14
+
15
+ ActionView::Helpers::FormBuilder.send :include, Sketchily::InstanceMethods
@@ -1,7 +1,7 @@
1
1
  module SvgEditTag
2
2
  module InstanceMethods
3
3
  def svg_edit_tag(name, value = nil, options = {})
4
- render :partial => "svg/svg_edit_tag", :locals => {:name => name, :value => value, :options => options}
4
+ tag :input, { "type" => "text", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys)
5
5
  end
6
6
  end
7
7
  end
@@ -1,3 +1,3 @@
1
1
  module Sketchily
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,3 +1,3 @@
1
1
  module Sketchily
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,9 @@
1
+ Connecting to database specified by database.yml
2
+ Rendered /home/dantemss/Desktop/sketchily/app/views/sketchily/_sketchily.html.erb (24.5ms)
3
+ Rendered /home/dantemss/Desktop/sketchily/app/views/sketchily/_sketchily.html.erb (4.7ms)
4
+ Rendered /home/dantemss/Desktop/sketchily/app/views/sketchily/_sketchily.html.erb (4.6ms)
5
+ Connecting to database specified by database.yml
6
+ Rendered /home/dantemss/Desktop/sketchily/app/views/sketchily/_sketchily.html.erb (6.7ms)
7
+ Connecting to database specified by database.yml
8
+ Rendered /home/dantemss/Desktop/sketchily/app/views/sketchily/_sketchily.html.erb (17.6ms)
9
+ Connecting to database specified by database.yml
@@ -0,0 +1,18 @@
1
+ # Configure Rails Environment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
+ require "rails/test_help"
6
+
7
+ require "minitest/autorun"
8
+ require "minitest/rails"
9
+
10
+ Rails.backtrace_cleaner.remove_silencers!
11
+
12
+ # Load support files
13
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
14
+
15
+ # Load fixtures from the engine
16
+ if ActiveSupport::TestCase.method_defined?(:fixture_path=)
17
+ ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
18
+ end
@@ -0,0 +1,453 @@
1
+ /*
2
+ * ext-imagelib.js
3
+ *
4
+ * Licensed under the MIT License
5
+ *
6
+ * Copyright(c) 2010 Alexis Deveria
7
+ *
8
+ */
9
+
10
+ svgEditor.addExtension("imagelib", function() {
11
+
12
+ var uiStrings = svgEditor.uiStrings;
13
+
14
+ $.extend(uiStrings, {
15
+ imagelib: {
16
+ select_lib: 'Select an image library',
17
+ show_list: 'Show library list',
18
+ import_single: 'Import single',
19
+ import_multi: 'Import multiple',
20
+ open: 'Open as new document'
21
+ }
22
+ });
23
+
24
+ var img_libs = [/*{
25
+ name: 'Demo library (local)',
26
+ url: '/assets/extensions/imagelib/index.html',
27
+ description: 'Demonstration library for SVG-edit on this server'
28
+ }, */
29
+ {
30
+ name: 'IAN Symbol Libraries',
31
+ url: 'http://ian.umces.edu/symbols/catalog/svgedit/album_chooser.php',
32
+ description: 'Free library of illustrations'
33
+ }
34
+ ];
35
+
36
+ var xlinkns = "http://www.w3.org/1999/xlink";
37
+
38
+ function closeBrowser() {
39
+ $('#imgbrowse_holder').hide();
40
+ }
41
+
42
+ function importImage(url) {
43
+ var newImage = svgCanvas.addSvgElementFromJson({
44
+ "element": "image",
45
+ "attr": {
46
+ "x": 0,
47
+ "y": 0,
48
+ "width": 0,
49
+ "height": 0,
50
+ "id": svgCanvas.getNextId(),
51
+ "style": "pointer-events:inherit"
52
+ }
53
+ });
54
+ svgCanvas.clearSelection();
55
+ svgCanvas.addToSelection([newImage]);
56
+ svgCanvas.setImageURL(url);
57
+ }
58
+
59
+ var mode = 's';
60
+ var multi_arr = [];
61
+ var cur_meta;
62
+ var tranfer_stopped = false;
63
+ var pending = {};
64
+
65
+ window.addEventListener("message", function(evt) {
66
+ // Receive postMessage data
67
+ var response = evt.data;
68
+
69
+ if(!response) {
70
+ // Do nothing
71
+ return;
72
+ }
73
+
74
+ var char1 = response.charAt(0);
75
+
76
+ var svg_str;
77
+ var img_str;
78
+
79
+ if(char1 != "{" && tranfer_stopped) {
80
+ tranfer_stopped = false;
81
+ return;
82
+ }
83
+
84
+ if(char1 == '|') {
85
+ var secondpos = response.indexOf('|', 1);
86
+ var id = response.substr(1, secondpos-1);
87
+ response = response.substr(secondpos+1);
88
+ char1 = response.charAt(0);
89
+
90
+ }
91
+
92
+
93
+ // Hide possible transfer dialog box
94
+ $('#dialog_box').hide();
95
+
96
+ switch (char1) {
97
+ case '{':
98
+ // Metadata
99
+ tranfer_stopped = false;
100
+ var cur_meta = JSON.parse(response);
101
+
102
+ pending[cur_meta.id] = cur_meta;
103
+
104
+ var name = (cur_meta.name || 'file');
105
+
106
+ var message = uiStrings.notification.retrieving.replace('%s', name);
107
+
108
+ if(mode != 'm') {
109
+ $.process_cancel(message, function() {
110
+ tranfer_stopped = true;
111
+ // Should a message be sent back to the frame?
112
+
113
+ $('#dialog_box').hide();
114
+ });
115
+ } else {
116
+ var entry = $('<div>' + message + '</div>').data('id', cur_meta.id);
117
+ preview.append(entry);
118
+ cur_meta.entry = entry;
119
+ }
120
+
121
+ return;
122
+ case '<':
123
+ svg_str = true;
124
+ break;
125
+ case 'd':
126
+ if(response.indexOf('data:image/svg+xml') === 0) {
127
+ var pre = 'data:image/svg+xml;base64,';
128
+ var src = response.substring(pre.length);
129
+ response = svgCanvas.Utils.decode64(src);
130
+ svg_str = true;
131
+ break;
132
+ } else if(response.indexOf('data:image/') === 0) {
133
+ img_str = true;
134
+ break;
135
+ }
136
+ // Else fall through
137
+ default:
138
+ // TODO: See if there's a way to base64 encode the binary data stream
139
+ // var str = 'data:;base64,' + svgCanvas.Utils.encode64(response, true);
140
+
141
+ // Assume it's raw image data
142
+ // importImage(str);
143
+
144
+ // Don't give warning as postMessage may have been used by something else
145
+ if(mode !== 'm') {
146
+ closeBrowser();
147
+ } else {
148
+ pending[id].entry.remove();
149
+ }
150
+ // $.alert('Unexpected data was returned: ' + response, function() {
151
+ // if(mode !== 'm') {
152
+ // closeBrowser();
153
+ // } else {
154
+ // pending[id].entry.remove();
155
+ // }
156
+ // });
157
+ return;
158
+ }
159
+
160
+ switch (mode) {
161
+ case 's':
162
+ // Import one
163
+ if(svg_str) {
164
+ svgCanvas.importSvgString(response);
165
+ } else if(img_str) {
166
+ importImage(response);
167
+ }
168
+ closeBrowser();
169
+ break;
170
+ case 'm':
171
+ // Import multiple
172
+ multi_arr.push([(svg_str ? 'svg' : 'img'), response]);
173
+ var cur_meta = pending[id];
174
+ if(svg_str) {
175
+ if(cur_meta && cur_meta.name) {
176
+ var title = cur_meta.name;
177
+ } else {
178
+ // Try to find a title
179
+ var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement;
180
+ var title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')';
181
+ }
182
+ if(cur_meta) {
183
+ preview.children().each(function() {
184
+ if($(this).data('id') == id) {
185
+ if(cur_meta.preview_url) {
186
+ $(this).html('<img src="' + cur_meta.preview_url + '">' + title);
187
+ } else {
188
+ $(this).text(title);
189
+ }
190
+ submit.removeAttr('disabled');
191
+ }
192
+ });
193
+ } else {
194
+ preview.append('<div>'+title+'</div>');
195
+ submit.removeAttr('disabled');
196
+ }
197
+ } else {
198
+ if(cur_meta && cur_meta.preview_url) {
199
+ var title = cur_meta.name || '';
200
+ }
201
+ if(cur_meta && cur_meta.preview_url) {
202
+ var entry = '<img src="' + cur_meta.preview_url + '">' + title;
203
+ } else {
204
+ var entry = '<img src="' + response + '">';
205
+ }
206
+
207
+ if(cur_meta) {
208
+ preview.children().each(function() {
209
+ if($(this).data('id') == id) {
210
+ $(this).html(entry);
211
+ submit.removeAttr('disabled');
212
+ }
213
+ });
214
+ } else {
215
+ preview.append($('<div>').append(entry));
216
+ submit.removeAttr('disabled');
217
+ }
218
+
219
+ }
220
+ break;
221
+ case 'o':
222
+ // Open
223
+ if(!svg_str) break;
224
+ svgEditor.openPrep(function(ok) {
225
+ if(!ok) return;
226
+ svgCanvas.clear();
227
+ svgCanvas.setSvgString(response);
228
+ // updateCanvas();
229
+ });
230
+ closeBrowser();
231
+ break;
232
+ }
233
+ }, true);
234
+
235
+ var preview, submit;
236
+
237
+ function toggleMulti(show) {
238
+
239
+ $('#lib_framewrap, #imglib_opts').css({right: (show ? 200 : 10)});
240
+ if(!preview) {
241
+ preview = $('<div id=imglib_preview>').css({
242
+ position: 'absolute',
243
+ top: 45,
244
+ right: 10,
245
+ width: 180,
246
+ bottom: 45,
247
+ background: '#fff',
248
+ overflow: 'auto'
249
+ }).insertAfter('#lib_framewrap');
250
+
251
+ submit = $('<button disabled>Import selected</button>')
252
+ .appendTo('#imgbrowse')
253
+ .on("click touchend", function() {
254
+ $.each(multi_arr, function(i) {
255
+ var type = this[0];
256
+ var data = this[1];
257
+ if(type == 'svg') {
258
+ svgCanvas.importSvgString(data);
259
+ } else {
260
+ importImage(data);
261
+ }
262
+ svgCanvas.moveSelectedElements(i*20, i*20, false);
263
+ });
264
+ preview.empty();
265
+ multi_arr = [];
266
+ $('#imgbrowse_holder').hide();
267
+ }).css({
268
+ position: 'absolute',
269
+ bottom: 10,
270
+ right: -10
271
+ });
272
+
273
+ }
274
+
275
+ preview.toggle(show);
276
+ submit.toggle(show);
277
+ }
278
+
279
+ function showBrowser() {
280
+
281
+ var browser = $('#imgbrowse');
282
+ if(!browser.length) {
283
+ $('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>\
284
+ </div></div>').insertAfter('#svg_docprops');
285
+ browser = $('#imgbrowse');
286
+
287
+ var all_libs = uiStrings.imagelib.select_lib;
288
+
289
+ var lib_opts = $('<ul id=imglib_opts>').appendTo(browser);
290
+ var frame = $('<iframe/>').prependTo(browser).hide().wrap('<div id=lib_framewrap>');
291
+
292
+ var header = $('<h1>').prependTo(browser).text(all_libs).css({
293
+ position: 'absolute',
294
+ top: 0,
295
+ left: 0,
296
+ width: '100%'
297
+ });
298
+
299
+ var cancel = $('<button>' + uiStrings.common.cancel + '</button>')
300
+ .appendTo(browser)
301
+ .on("click touchend", function() {
302
+ $('#imgbrowse_holder').hide();
303
+ }).css({
304
+ position: 'absolute',
305
+ top: 5,
306
+ right: -10
307
+ });
308
+
309
+ var leftBlock = $('<span>').css({position:'absolute',top:5,left:10}).appendTo(browser);
310
+
311
+ var back = $('<button hidden>' + uiStrings.imagelib.show_list + '</button>')
312
+ .appendTo(leftBlock)
313
+ .on("click touchend", function() {
314
+ frame.attr('src', 'about:blank').hide();
315
+ lib_opts.show();
316
+ header.text(all_libs);
317
+ back.hide();
318
+ }).css({
319
+ 'margin-right': 5
320
+ }).hide();
321
+
322
+ var type = $('<select><option value=s>' +
323
+ uiStrings.imagelib.import_single + '</option><option value=m>' +
324
+ uiStrings.imagelib.import_multi + '</option><option value=o>' +
325
+ uiStrings.imagelib.open + '</option></select>').appendTo(leftBlock).change(function() {
326
+ mode = $(this).val();
327
+ switch (mode) {
328
+ case 's':
329
+ case 'o':
330
+ toggleMulti(false);
331
+ break;
332
+
333
+ case 'm':
334
+ // Import multiple
335
+ toggleMulti(true);
336
+ }
337
+ }).css({
338
+ 'margin-top': 10
339
+ });
340
+
341
+ cancel.prepend($.getSvgIcon('cancel', true));
342
+ back.prepend($.getSvgIcon('tool_imagelib', true));
343
+
344
+ $.each(img_libs, function(i, opts) {
345
+ $('<li>')
346
+ .appendTo(lib_opts)
347
+ .text(opts.name)
348
+ .on("click touchend", function() {
349
+ frame.attr('src', opts.url).show();
350
+ header.text(opts.name);
351
+ lib_opts.hide();
352
+ back.show();
353
+ }).append('<span>' + opts.description + '</span>');
354
+ });
355
+
356
+ } else {
357
+ $('#imgbrowse_holder').show();
358
+ }
359
+ }
360
+
361
+ return {
362
+ svgicons: "/assets/extensions/ext-imagelib.xml",
363
+ buttons: [{
364
+ id: "tool_imagelib",
365
+ type: "app_menu", // _flyout
366
+ position: 4,
367
+ title: "Image library",
368
+ events: {
369
+ "mouseup": showBrowser
370
+ }
371
+ }],
372
+ callback: function() {
373
+
374
+ $('<style>').text('\
375
+ #imgbrowse_holder {\
376
+ position: absolute;\
377
+ top: 0;\
378
+ left: 0;\
379
+ width: 100%;\
380
+ height: 100%;\
381
+ background-color: rgba(0, 0, 0, .5);\
382
+ z-index: 5;\
383
+ }\
384
+ \
385
+ #imgbrowse {\
386
+ position: absolute;\
387
+ top: 25px;\
388
+ left: 25px;\
389
+ right: 25px;\
390
+ bottom: 25px;\
391
+ min-width: 300px;\
392
+ min-height: 200px;\
393
+ background: #B0B0B0;\
394
+ border: 1px outset #777;\
395
+ }\
396
+ #imgbrowse h1 {\
397
+ font-size: 20px;\
398
+ margin: .4em;\
399
+ text-align: center;\
400
+ }\
401
+ #lib_framewrap,\
402
+ #imgbrowse > ul {\
403
+ position: absolute;\
404
+ top: 45px;\
405
+ left: 10px;\
406
+ right: 10px;\
407
+ bottom: 10px;\
408
+ background: white;\
409
+ margin: 0;\
410
+ padding: 0;\
411
+ }\
412
+ #imgbrowse > ul {\
413
+ overflow: auto;\
414
+ }\
415
+ #imgbrowse > div {\
416
+ border: 1px solid #666;\
417
+ }\
418
+ #imglib_preview > div {\
419
+ padding: 5px;\
420
+ font-size: 12px;\
421
+ }\
422
+ #imglib_preview img {\
423
+ display: block;\
424
+ margin: 0 auto;\
425
+ max-height: 100px;\
426
+ }\
427
+ #imgbrowse li {\
428
+ list-style: none;\
429
+ padding: .5em;\
430
+ background: #E8E8E8;\
431
+ border-bottom: 1px solid #B0B0B0;\
432
+ line-height: 1.2em;\
433
+ font-style: sans-serif;\
434
+ }\
435
+ #imgbrowse li > span {\
436
+ color: #666;\
437
+ font-size: 15px;\
438
+ display: block;\
439
+ }\
440
+ #imgbrowse li:hover {\
441
+ background: #FFC;\
442
+ cursor: pointer;\
443
+ }\
444
+ #imgbrowse iframe {\
445
+ width: 100%;\
446
+ height: 100%;\
447
+ border: 0;\
448
+ }\
449
+ ').appendTo('head');
450
+ }
451
+ }
452
+ });
453
+