x-editable-rails 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f6fdf15b9dba5e939debe9387b5a18fbf5303249
4
- data.tar.gz: 5a05eb8fc0b7217d406745d0e9bb7675f713428a
3
+ metadata.gz: 69573b9d19da5508621bb001ce70a965119f1db6
4
+ data.tar.gz: 9f88c437a7dce38761fd95f6f2252aa72349d058
5
5
  SHA512:
6
- metadata.gz: e748ea5acba0ede342cba31f235e8635eda1793a5243859c8367d2e2ce4536cecf2ad75e70d707592121a4070b50508679a0e73ca99ffa8f4b9d62df16e870ef
7
- data.tar.gz: 46ed0d36e34c70202979fac240806f5703b74e6c368229c469ca858d335eb16d2afa856e23e4d522286bacb953249029da8f230d8c4d43772587f3567f5ad4a0
6
+ metadata.gz: 9b3a7a35c33960682fbb9a9ee376fdfaf03df325902b9677554c007ef6825f35f597112e8439f6ba085f2712fe40f3bfaaa28ee649cb98be0cafde79ec29e085
7
+ data.tar.gz: 67884243ae8d543d92b46412ed460b9c44c452bf7c441f78cc7fb1ccad229b59fdf24c5ef0e0b8bd6e1f7de62adb3cb193547617c6b03dd7ac3ba48625acfd43
data/README.md CHANGED
@@ -87,6 +87,29 @@ And don't forget to activate it
87
87
  $('.editable').editable()
88
88
  ```
89
89
 
90
+ Wysihtml5 editor
91
+
92
+ If you want edit text with wysihtml5 editor, you need to load his dependencies
93
+ For js
94
+ ```coffee
95
+ #= require editable/bootstrap-editable
96
+ #= require editable/inputs-ext/bootstrap-wysihtml5/wysihtml5
97
+ #= require editable/inputs-ext/bootstrap-wysihtml5/bootstrap-wysihtml5
98
+ #= require editable/inputs-ext/wysihtml5
99
+ #= require editable/rails
100
+ ```
101
+
102
+ And css
103
+ ```sass
104
+ //= require editable/bootstrap-editable
105
+ //= require editable/inputs-ext/bootstrap-wysihtml5
106
+ //= require editable/inputs-ext/wysiwyg-color
107
+ ```
108
+
109
+ ```ruby
110
+ = editable @page, :content, nested: :translations, nid: @page.translation.id, type: :wysihtml5, e: @page.content.html_safe
111
+ ```
112
+
90
113
  ## Contributing
91
114
 
92
115
  1. Fork it
@@ -1,7 +1,7 @@
1
1
  module X
2
2
  module Editable
3
3
  module Rails
4
- VERSION = "1.2.2"
4
+ VERSION = "1.3.0"
5
5
  end
6
6
  end
7
7
  end
@@ -8,19 +8,17 @@ module X
8
8
  if can? :edit, object and xeditable?
9
9
  model = object.class.to_s.downcase
10
10
  model_param = model.gsub('::', '_')
11
- model_name = model.gsub('::', '/')
12
11
  klass = options[:nested] ? object.class.const_get(options[:nested].to_s.singularize.capitalize) : object.class
13
- content_tag :a, href: "#", class: "editable",
12
+ content_tag :a, href: '#', class: 'editable', title: options.fetch(:title, klass.human_attribute_name(method)),
14
13
  data: {
15
- type: 'text',
14
+ type: options.fetch(:type, 'text'),
16
15
  model: model_param,
17
16
  name: method,
18
17
  url: data_url,
19
- nested: (options[:nested] if options[:nested]),
20
- nid: (options[:nid] if options[:nid]),
21
- :'original-title' => klass.human_attribute_name(method)
18
+ nested: options[:nested],
19
+ nid: options[:nid]
22
20
  } do
23
- object.send(method)
21
+ object.send(method).try(:html_safe)
24
22
  end
25
23
  else
26
24
  options[:e]
@@ -0,0 +1,170 @@
1
+ /**
2
+ Address editable input.
3
+ Internally value stored as {city: "Moscow", street: "Lenina", building: "15"}
4
+
5
+ @class address
6
+ @extends abstractinput
7
+ @final
8
+ @example
9
+ <a href="#" id="address" data-type="address" data-pk="1">awesome</a>
10
+ <script>
11
+ $(function(){
12
+ $('#address').editable({
13
+ url: '/post',
14
+ title: 'Enter city, street and building #',
15
+ value: {
16
+ city: "Moscow",
17
+ street: "Lenina",
18
+ building: "15"
19
+ }
20
+ });
21
+ });
22
+ </script>
23
+ **/
24
+ (function ($) {
25
+ "use strict";
26
+
27
+ var Address = function (options) {
28
+ this.init('address', options, Address.defaults);
29
+ };
30
+
31
+ //inherit from Abstract input
32
+ $.fn.editableutils.inherit(Address, $.fn.editabletypes.abstractinput);
33
+
34
+ $.extend(Address.prototype, {
35
+ /**
36
+ Renders input from tpl
37
+
38
+ @method render()
39
+ **/
40
+ render: function() {
41
+ this.$input = this.$tpl.find('input');
42
+ },
43
+
44
+ /**
45
+ Default method to show value in element. Can be overwritten by display option.
46
+
47
+ @method value2html(value, element)
48
+ **/
49
+ value2html: function(value, element) {
50
+ if(!value) {
51
+ $(element).empty();
52
+ return;
53
+ }
54
+ var html = $('<div>').text(value.city).html() + ', ' + $('<div>').text(value.street).html() + ' st., bld. ' + $('<div>').text(value.building).html();
55
+ $(element).html(html);
56
+ },
57
+
58
+ /**
59
+ Gets value from element's html
60
+
61
+ @method html2value(html)
62
+ **/
63
+ html2value: function(html) {
64
+ /*
65
+ you may write parsing method to get value by element's html
66
+ e.g. "Moscow, st. Lenina, bld. 15" => {city: "Moscow", street: "Lenina", building: "15"}
67
+ but for complex structures it's not recommended.
68
+ Better set value directly via javascript, e.g.
69
+ editable({
70
+ value: {
71
+ city: "Moscow",
72
+ street: "Lenina",
73
+ building: "15"
74
+ }
75
+ });
76
+ */
77
+ return null;
78
+ },
79
+
80
+ /**
81
+ Converts value to string.
82
+ It is used in internal comparing (not for sending to server).
83
+
84
+ @method value2str(value)
85
+ **/
86
+ value2str: function(value) {
87
+ var str = '';
88
+ if(value) {
89
+ for(var k in value) {
90
+ str = str + k + ':' + value[k] + ';';
91
+ }
92
+ }
93
+ return str;
94
+ },
95
+
96
+ /*
97
+ Converts string to value. Used for reading value from 'data-value' attribute.
98
+
99
+ @method str2value(str)
100
+ */
101
+ str2value: function(str) {
102
+ /*
103
+ this is mainly for parsing value defined in data-value attribute.
104
+ If you will always set value by javascript, no need to overwrite it
105
+ */
106
+ return str;
107
+ },
108
+
109
+ /**
110
+ Sets value of input.
111
+
112
+ @method value2input(value)
113
+ @param {mixed} value
114
+ **/
115
+ value2input: function(value) {
116
+ if(!value) {
117
+ return;
118
+ }
119
+ this.$input.filter('[name="city"]').val(value.city);
120
+ this.$input.filter('[name="street"]').val(value.street);
121
+ this.$input.filter('[name="building"]').val(value.building);
122
+ },
123
+
124
+ /**
125
+ Returns value of input.
126
+
127
+ @method input2value()
128
+ **/
129
+ input2value: function() {
130
+ return {
131
+ city: this.$input.filter('[name="city"]').val(),
132
+ street: this.$input.filter('[name="street"]').val(),
133
+ building: this.$input.filter('[name="building"]').val()
134
+ };
135
+ },
136
+
137
+ /**
138
+ Activates input: sets focus on the first field.
139
+
140
+ @method activate()
141
+ **/
142
+ activate: function() {
143
+ this.$input.filter('[name="city"]').focus();
144
+ },
145
+
146
+ /**
147
+ Attaches handler to submit form in case of 'showbuttons=false' mode
148
+
149
+ @method autosubmit()
150
+ **/
151
+ autosubmit: function() {
152
+ this.$input.keydown(function (e) {
153
+ if (e.which === 13) {
154
+ $(this).closest('form').submit();
155
+ }
156
+ });
157
+ }
158
+ });
159
+
160
+ Address.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
161
+ tpl: '<div class="editable-address"><label><span>City: </span><input type="text" name="city" class="input-small"></label></div>'+
162
+ '<div class="editable-address"><label><span>Street: </span><input type="text" name="street" class="input-small"></label></div>'+
163
+ '<div class="editable-address"><label><span>Building: </span><input type="text" name="building" class="input-mini"></label></div>',
164
+
165
+ inputclass: ''
166
+ });
167
+
168
+ $.fn.editabletypes.address = Address;
169
+
170
+ }(window.jQuery));
@@ -0,0 +1,499 @@
1
+ !function($, wysi) {
2
+ "use strict";
3
+
4
+ var tpl = {
5
+ "font-styles": function(locale, options) {
6
+ var size = (options && options.size) ? ' btn-'+options.size : '';
7
+ return "<li class='dropdown'>" +
8
+ "<a class='btn dropdown-toggle" + size + "' data-toggle='dropdown' href='#'>" +
9
+ "<i class='icon-font'></i>&nbsp;<span class='current-font'>" + locale.font_styles.normal + "</span>&nbsp;<b class='caret'></b>" +
10
+ "</a>" +
11
+ "<ul class='dropdown-menu'>" +
12
+ "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='div' tabindex='-1'>" + locale.font_styles.normal + "</a></li>" +
13
+ "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h1' tabindex='-1'>" + locale.font_styles.h1 + "</a></li>" +
14
+ "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h2' tabindex='-1'>" + locale.font_styles.h2 + "</a></li>" +
15
+ "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h3' tabindex='-1'>" + locale.font_styles.h3 + "</a></li>" +
16
+ "</ul>" +
17
+ "</li>";
18
+ },
19
+
20
+ "emphasis": function(locale, options) {
21
+ var size = (options && options.size) ? ' btn-'+options.size : '';
22
+ return "<li>" +
23
+ "<div class='btn-group'>" +
24
+ "<a class='btn" + size + "' data-wysihtml5-command='bold' title='CTRL+B' tabindex='-1'>" + locale.emphasis.bold + "</a>" +
25
+ "<a class='btn" + size + "' data-wysihtml5-command='italic' title='CTRL+I' tabindex='-1'>" + locale.emphasis.italic + "</a>" +
26
+ "<a class='btn" + size + "' data-wysihtml5-command='underline' title='CTRL+U' tabindex='-1'>" + locale.emphasis.underline + "</a>" +
27
+ "</div>" +
28
+ "</li>";
29
+ },
30
+
31
+ "lists": function(locale, options) {
32
+ var size = (options && options.size) ? ' btn-'+options.size : '';
33
+ return "<li>" +
34
+ "<div class='btn-group'>" +
35
+ "<a class='btn" + size + "' data-wysihtml5-command='insertUnorderedList' title='" + locale.lists.unordered + "' tabindex='-1'><i class='icon-list'></i></a>" +
36
+ "<a class='btn" + size + "' data-wysihtml5-command='insertOrderedList' title='" + locale.lists.ordered + "' tabindex='-1'><i class='icon-th-list'></i></a>" +
37
+ "<a class='btn" + size + "' data-wysihtml5-command='Outdent' title='" + locale.lists.outdent + "' tabindex='-1'><i class='icon-indent-right'></i></a>" +
38
+ "<a class='btn" + size + "' data-wysihtml5-command='Indent' title='" + locale.lists.indent + "' tabindex='-1'><i class='icon-indent-left'></i></a>" +
39
+ "</div>" +
40
+ "</li>";
41
+ },
42
+
43
+ "link": function(locale, options) {
44
+ var size = (options && options.size) ? ' btn-'+options.size : '';
45
+ return "<li>" +
46
+ "<div class='bootstrap-wysihtml5-insert-link-modal modal hide fade'>" +
47
+ "<div class='modal-header'>" +
48
+ "<a class='close' data-dismiss='modal'>&times;</a>" +
49
+ "<h3>" + locale.link.insert + "</h3>" +
50
+ "</div>" +
51
+ "<div class='modal-body'>" +
52
+ "<input value='http://' class='bootstrap-wysihtml5-insert-link-url input-xlarge'>" +
53
+ "</div>" +
54
+ "<div class='modal-footer'>" +
55
+ "<a href='#' class='btn' data-dismiss='modal'>" + locale.link.cancel + "</a>" +
56
+ "<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.link.insert + "</a>" +
57
+ "</div>" +
58
+ "</div>" +
59
+ "<a class='btn" + size + "' data-wysihtml5-command='createLink' title='" + locale.link.insert + "' tabindex='-1'><i class='icon-share'></i></a>" +
60
+ "</li>";
61
+ },
62
+
63
+ "image": function(locale, options) {
64
+ var size = (options && options.size) ? ' btn-'+options.size : '';
65
+ return "<li>" +
66
+ "<div class='bootstrap-wysihtml5-insert-image-modal modal hide fade'>" +
67
+ "<div class='modal-header'>" +
68
+ "<a class='close' data-dismiss='modal'>&times;</a>" +
69
+ "<h3>" + locale.image.insert + "</h3>" +
70
+ "</div>" +
71
+ "<div class='modal-body'>" +
72
+ "<input value='http://' class='bootstrap-wysihtml5-insert-image-url input-xlarge'>" +
73
+ "</div>" +
74
+ "<div class='modal-footer'>" +
75
+ "<a href='#' class='btn' data-dismiss='modal'>" + locale.image.cancel + "</a>" +
76
+ "<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.image.insert + "</a>" +
77
+ "</div>" +
78
+ "</div>" +
79
+ "<a class='btn" + size + "' data-wysihtml5-command='insertImage' title='" + locale.image.insert + "' tabindex='-1'><i class='icon-picture'></i></a>" +
80
+ "</li>";
81
+ },
82
+
83
+ "html": function(locale, options) {
84
+ var size = (options && options.size) ? ' btn-'+options.size : '';
85
+ return "<li>" +
86
+ "<div class='btn-group'>" +
87
+ "<a class='btn" + size + "' data-wysihtml5-action='change_view' title='" + locale.html.edit + "' tabindex='-1'><i class='icon-pencil'></i></a>" +
88
+ "</div>" +
89
+ "</li>";
90
+ },
91
+
92
+ "color": function(locale, options) {
93
+ var size = (options && options.size) ? ' btn-'+options.size : '';
94
+ return "<li class='dropdown'>" +
95
+ "<a class='btn dropdown-toggle" + size + "' data-toggle='dropdown' href='#' tabindex='-1'>" +
96
+ "<span class='current-color'>" + locale.colours.black + "</span>&nbsp;<b class='caret'></b>" +
97
+ "</a>" +
98
+ "<ul class='dropdown-menu'>" +
99
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='black'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='black'>" + locale.colours.black + "</a></li>" +
100
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='silver'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='silver'>" + locale.colours.silver + "</a></li>" +
101
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='gray'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='gray'>" + locale.colours.gray + "</a></li>" +
102
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='maroon'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='maroon'>" + locale.colours.maroon + "</a></li>" +
103
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='red'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='red'>" + locale.colours.red + "</a></li>" +
104
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='purple'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='purple'>" + locale.colours.purple + "</a></li>" +
105
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='green'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='green'>" + locale.colours.green + "</a></li>" +
106
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='olive'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='olive'>" + locale.colours.olive + "</a></li>" +
107
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='navy'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='navy'>" + locale.colours.navy + "</a></li>" +
108
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='blue'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='blue'>" + locale.colours.blue + "</a></li>" +
109
+ "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='orange'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='orange'>" + locale.colours.orange + "</a></li>" +
110
+ "</ul>" +
111
+ "</li>";
112
+ }
113
+ };
114
+
115
+ var templates = function(key, locale, options) {
116
+ return tpl[key](locale, options);
117
+ };
118
+
119
+
120
+ var Wysihtml5 = function(el, options) {
121
+ this.el = el;
122
+ var toolbarOpts = options || defaultOptions;
123
+ for(var t in toolbarOpts.customTemplates) {
124
+ tpl[t] = toolbarOpts.customTemplates[t];
125
+ }
126
+ this.toolbar = this.createToolbar(el, toolbarOpts);
127
+ this.editor = this.createEditor(options);
128
+
129
+ window.editor = this.editor;
130
+
131
+ $('iframe.wysihtml5-sandbox').each(function(i, el){
132
+ $(el.contentWindow).off('focus.wysihtml5').on({
133
+ 'focus.wysihtml5' : function(){
134
+ $('li.dropdown').removeClass('open');
135
+ }
136
+ });
137
+ });
138
+ };
139
+
140
+ Wysihtml5.prototype = {
141
+
142
+ constructor: Wysihtml5,
143
+
144
+ createEditor: function(options) {
145
+ options = options || {};
146
+
147
+ // Add the toolbar to a clone of the options object so multiple instances
148
+ // of the WYISYWG don't break because "toolbar" is already defined
149
+ options = $.extend(true, {}, options);
150
+ options.toolbar = this.toolbar[0];
151
+
152
+ var editor = new wysi.Editor(this.el[0], options);
153
+
154
+ if(options && options.events) {
155
+ for(var eventName in options.events) {
156
+ editor.on(eventName, options.events[eventName]);
157
+ }
158
+ }
159
+ return editor;
160
+ },
161
+
162
+ createToolbar: function(el, options) {
163
+ var self = this;
164
+ var toolbar = $("<ul/>", {
165
+ 'class' : "wysihtml5-toolbar",
166
+ 'style': "display:none"
167
+ });
168
+ var culture = options.locale || defaultOptions.locale || "en";
169
+ for(var key in defaultOptions) {
170
+ var value = false;
171
+
172
+ if(options[key] !== undefined) {
173
+ if(options[key] === true) {
174
+ value = true;
175
+ }
176
+ } else {
177
+ value = defaultOptions[key];
178
+ }
179
+
180
+ if(value === true) {
181
+ toolbar.append(templates(key, locale[culture], options));
182
+
183
+ if(key === "html") {
184
+ this.initHtml(toolbar);
185
+ }
186
+
187
+ if(key === "link") {
188
+ this.initInsertLink(toolbar);
189
+ }
190
+
191
+ if(key === "image") {
192
+ this.initInsertImage(toolbar);
193
+ }
194
+ }
195
+ }
196
+
197
+ if(options.toolbar) {
198
+ for(key in options.toolbar) {
199
+ toolbar.append(options.toolbar[key]);
200
+ }
201
+ }
202
+
203
+ toolbar.find("a[data-wysihtml5-command='formatBlock']").click(function(e) {
204
+ var target = e.target || e.srcElement;
205
+ var el = $(target);
206
+ self.toolbar.find('.current-font').text(el.html());
207
+ });
208
+
209
+ toolbar.find("a[data-wysihtml5-command='foreColor']").click(function(e) {
210
+ var target = e.target || e.srcElement;
211
+ var el = $(target);
212
+ self.toolbar.find('.current-color').text(el.html());
213
+ });
214
+
215
+ this.el.before(toolbar);
216
+
217
+ return toolbar;
218
+ },
219
+
220
+ initHtml: function(toolbar) {
221
+ var changeViewSelector = "a[data-wysihtml5-action='change_view']";
222
+ toolbar.find(changeViewSelector).click(function(e) {
223
+ toolbar.find('a.btn').not(changeViewSelector).toggleClass('disabled');
224
+ });
225
+ },
226
+
227
+ initInsertImage: function(toolbar) {
228
+ var self = this;
229
+ var insertImageModal = toolbar.find('.bootstrap-wysihtml5-insert-image-modal');
230
+ var urlInput = insertImageModal.find('.bootstrap-wysihtml5-insert-image-url');
231
+ var insertButton = insertImageModal.find('a.btn-primary');
232
+ var initialValue = urlInput.val();
233
+ var caretBookmark;
234
+
235
+ var insertImage = function() {
236
+ var url = urlInput.val();
237
+ urlInput.val(initialValue);
238
+ self.editor.currentView.element.focus();
239
+ if (caretBookmark) {
240
+ self.editor.composer.selection.setBookmark(caretBookmark);
241
+ caretBookmark = null;
242
+ }
243
+ self.editor.composer.commands.exec("insertImage", url);
244
+ };
245
+
246
+ urlInput.keypress(function(e) {
247
+ if(e.which == 13) {
248
+ insertImage();
249
+ insertImageModal.modal('hide');
250
+ }
251
+ });
252
+
253
+ insertButton.click(insertImage);
254
+
255
+ insertImageModal.on('shown', function() {
256
+ urlInput.focus();
257
+ });
258
+
259
+ insertImageModal.on('hide', function() {
260
+ self.editor.currentView.element.focus();
261
+ });
262
+
263
+ toolbar.find('a[data-wysihtml5-command=insertImage]').click(function() {
264
+ var activeButton = $(this).hasClass("wysihtml5-command-active");
265
+
266
+ if (!activeButton) {
267
+ self.editor.currentView.element.focus(false);
268
+ caretBookmark = self.editor.composer.selection.getBookmark();
269
+ insertImageModal.appendTo('body').modal('show');
270
+ insertImageModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) {
271
+ e.stopPropagation();
272
+ });
273
+ return false;
274
+ }
275
+ else {
276
+ return true;
277
+ }
278
+ });
279
+ },
280
+
281
+ initInsertLink: function(toolbar) {
282
+ var self = this;
283
+ var insertLinkModal = toolbar.find('.bootstrap-wysihtml5-insert-link-modal');
284
+ var urlInput = insertLinkModal.find('.bootstrap-wysihtml5-insert-link-url');
285
+ var insertButton = insertLinkModal.find('a.btn-primary');
286
+ var initialValue = urlInput.val();
287
+ var caretBookmark;
288
+
289
+ var insertLink = function() {
290
+ var url = urlInput.val();
291
+ urlInput.val(initialValue);
292
+ self.editor.currentView.element.focus();
293
+ if (caretBookmark) {
294
+ self.editor.composer.selection.setBookmark(caretBookmark);
295
+ caretBookmark = null;
296
+ }
297
+ self.editor.composer.commands.exec("createLink", {
298
+ href: url,
299
+ target: "_blank",
300
+ rel: "nofollow"
301
+ });
302
+ };
303
+ var pressedEnter = false;
304
+
305
+ urlInput.keypress(function(e) {
306
+ if(e.which == 13) {
307
+ insertLink();
308
+ insertLinkModal.modal('hide');
309
+ }
310
+ });
311
+
312
+ insertButton.click(insertLink);
313
+
314
+ insertLinkModal.on('shown', function() {
315
+ urlInput.focus();
316
+ });
317
+
318
+ insertLinkModal.on('hide', function() {
319
+ self.editor.currentView.element.focus();
320
+ });
321
+
322
+ toolbar.find('a[data-wysihtml5-command=createLink]').click(function() {
323
+ var activeButton = $(this).hasClass("wysihtml5-command-active");
324
+
325
+ if (!activeButton) {
326
+ self.editor.currentView.element.focus(false);
327
+ caretBookmark = self.editor.composer.selection.getBookmark();
328
+ insertLinkModal.appendTo('body').modal('show');
329
+ insertLinkModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) {
330
+ e.stopPropagation();
331
+ });
332
+ return false;
333
+ }
334
+ else {
335
+ return true;
336
+ }
337
+ });
338
+ }
339
+ };
340
+
341
+ // these define our public api
342
+ var methods = {
343
+ resetDefaults: function() {
344
+ $.fn.wysihtml5.defaultOptions = $.extend(true, {}, $.fn.wysihtml5.defaultOptionsCache);
345
+ },
346
+ bypassDefaults: function(options) {
347
+ return this.each(function () {
348
+ var $this = $(this);
349
+ $this.data('wysihtml5', new Wysihtml5($this, options));
350
+ });
351
+ },
352
+ shallowExtend: function (options) {
353
+ var settings = $.extend({}, $.fn.wysihtml5.defaultOptions, options || {});
354
+ var that = this;
355
+ return methods.bypassDefaults.apply(that, [settings]);
356
+ },
357
+ deepExtend: function(options) {
358
+ var settings = $.extend(true, {}, $.fn.wysihtml5.defaultOptions, options || {});
359
+ var that = this;
360
+ return methods.bypassDefaults.apply(that, [settings]);
361
+ },
362
+ init: function(options) {
363
+ var that = this;
364
+ return methods.shallowExtend.apply(that, [options]);
365
+ }
366
+ };
367
+
368
+ $.fn.wysihtml5 = function ( method ) {
369
+ if ( methods[method] ) {
370
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
371
+ } else if ( typeof method === 'object' || ! method ) {
372
+ return methods.init.apply( this, arguments );
373
+ } else {
374
+ $.error( 'Method ' + method + ' does not exist on jQuery.wysihtml5' );
375
+ }
376
+ };
377
+
378
+ $.fn.wysihtml5.Constructor = Wysihtml5;
379
+
380
+ var defaultOptions = $.fn.wysihtml5.defaultOptions = {
381
+ "font-styles": true,
382
+ "color": false,
383
+ "emphasis": true,
384
+ "lists": true,
385
+ "html": false,
386
+ "link": true,
387
+ "image": true,
388
+ events: {},
389
+ parserRules: {
390
+ classes: {
391
+ // (path_to_project/lib/css/wysiwyg-color.css)
392
+ "wysiwyg-color-silver" : 1,
393
+ "wysiwyg-color-gray" : 1,
394
+ "wysiwyg-color-white" : 1,
395
+ "wysiwyg-color-maroon" : 1,
396
+ "wysiwyg-color-red" : 1,
397
+ "wysiwyg-color-purple" : 1,
398
+ "wysiwyg-color-fuchsia" : 1,
399
+ "wysiwyg-color-green" : 1,
400
+ "wysiwyg-color-lime" : 1,
401
+ "wysiwyg-color-olive" : 1,
402
+ "wysiwyg-color-yellow" : 1,
403
+ "wysiwyg-color-navy" : 1,
404
+ "wysiwyg-color-blue" : 1,
405
+ "wysiwyg-color-teal" : 1,
406
+ "wysiwyg-color-aqua" : 1,
407
+ "wysiwyg-color-orange" : 1
408
+ },
409
+ tags: {
410
+ "b": {},
411
+ "i": {},
412
+ "br": {},
413
+ "ol": {},
414
+ "ul": {},
415
+ "li": {},
416
+ "h1": {},
417
+ "h2": {},
418
+ "h3": {},
419
+ "blockquote": {},
420
+ "u": 1,
421
+ "img": {
422
+ "check_attributes": {
423
+ "width": "numbers",
424
+ "alt": "alt",
425
+ "src": "url",
426
+ "height": "numbers"
427
+ }
428
+ },
429
+ "a": {
430
+ set_attributes: {
431
+ target: "_blank",
432
+ rel: "nofollow"
433
+ },
434
+ check_attributes: {
435
+ href: "url" // important to avoid XSS
436
+ }
437
+ },
438
+ "span": 1,
439
+ "div": 1,
440
+ // to allow save and edit files with code tag hacks
441
+ "code": 1,
442
+ "pre": 1
443
+ }
444
+ },
445
+ stylesheets: ["./lib/css/wysiwyg-color.css"], // (path_to_project/lib/css/wysiwyg-color.css)
446
+ locale: "en"
447
+ };
448
+
449
+ if (typeof $.fn.wysihtml5.defaultOptionsCache === 'undefined') {
450
+ $.fn.wysihtml5.defaultOptionsCache = $.extend(true, {}, $.fn.wysihtml5.defaultOptions);
451
+ }
452
+
453
+ var locale = $.fn.wysihtml5.locale = {
454
+ en: {
455
+ font_styles: {
456
+ normal: "Normal text",
457
+ h1: "Heading 1",
458
+ h2: "Heading 2",
459
+ h3: "Heading 3"
460
+ },
461
+ emphasis: {
462
+ bold: "Bold",
463
+ italic: "Italic",
464
+ underline: "Underline"
465
+ },
466
+ lists: {
467
+ unordered: "Unordered list",
468
+ ordered: "Ordered list",
469
+ outdent: "Outdent",
470
+ indent: "Indent"
471
+ },
472
+ link: {
473
+ insert: "Insert link",
474
+ cancel: "Cancel"
475
+ },
476
+ image: {
477
+ insert: "Insert image",
478
+ cancel: "Cancel"
479
+ },
480
+ html: {
481
+ edit: "Edit HTML"
482
+ },
483
+ colours: {
484
+ black: "Black",
485
+ silver: "Silver",
486
+ gray: "Grey",
487
+ maroon: "Maroon",
488
+ red: "Red",
489
+ purple: "Purple",
490
+ green: "Green",
491
+ olive: "Olive",
492
+ navy: "Navy",
493
+ blue: "Blue",
494
+ orange: "Orange"
495
+ }
496
+ }
497
+ };
498
+
499
+ }(window.jQuery, window.wysihtml5);