vue_crud 0.1.9.6 → 0.1.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/vue_crud/froala_generator.rb +12 -0
  3. data/lib/generators/vue_crud/sortable.rb +10 -0
  4. data/lib/generators/vue_crud/templates/assets/images/froala_editor/color_picker.png +0 -0
  5. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/froala_editor.js +11089 -0
  6. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/languages/en_gb.js +178 -0
  7. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/languages/zh_cn.js +234 -0
  8. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/languages/zh_tw.js +234 -0
  9. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/align.js +119 -0
  10. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/char_counter.js +150 -0
  11. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/code_beautifier.js +3271 -0
  12. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/code_view.js +311 -0
  13. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/colors.js +350 -0
  14. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/draggable.js +379 -0
  15. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/emoticons.js +347 -0
  16. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/entities.js +113 -0
  17. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/file.js +609 -0
  18. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/font_family.js +178 -0
  19. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/font_size.js +116 -0
  20. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/forms.js +415 -0
  21. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/fullscreen.js +209 -0
  22. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/image.js +2401 -0
  23. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/image_manager.js +921 -0
  24. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/inline_style.js +86 -0
  25. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/line_breaker.js +435 -0
  26. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/link.js +997 -0
  27. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/lists.js +382 -0
  28. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/paragraph_format.js +293 -0
  29. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/paragraph_style.js +139 -0
  30. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/quick_insert.js +342 -0
  31. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/quote.js +138 -0
  32. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/save.js +176 -0
  33. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/table.js +3123 -0
  34. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/url.js +113 -0
  35. data/lib/generators/vue_crud/templates/assets/javascripts/froala_editor/plugins/video.js +1135 -0
  36. data/lib/generators/vue_crud/templates/assets/javascripts/sortable.js +1249 -0
  37. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/froala_editor.scss +1008 -0
  38. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/froala_style.scss +273 -0
  39. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/char_counter.scss +46 -0
  40. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/code_view.scss +102 -0
  41. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/colors.scss +129 -0
  42. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/draggable.scss +32 -0
  43. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/emoticons.scss +27 -0
  44. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/file.scss +135 -0
  45. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/fullscreen.scss +28 -0
  46. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/image.scss +233 -0
  47. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/image_manager.scss +370 -0
  48. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/line_breaker.scss +26 -0
  49. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/quick_insert.scss +56 -0
  50. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/table.scss +156 -0
  51. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/plugins/video.scss +136 -0
  52. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/themes/dark.scss +1087 -0
  53. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/themes/gray.scss +1087 -0
  54. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/themes/red.scss +1087 -0
  55. data/lib/generators/vue_crud/templates/assets/stylesheets/froala_editor/themes/royal.scss +1087 -0
  56. data/lib/generators/vue_crud/templates/vue_crud.html +54 -71
  57. data/lib/vue_crud/version.rb +1 -1
  58. data/vendor/assets/javascripts/vue_crud.js +212 -59
  59. metadata +56 -2
@@ -0,0 +1,997 @@
1
+ /*!
2
+ * froala_editor v2.3.3 (https://www.froala.com/wysiwyg-editor)
3
+ * License https://froala.com/wysiwyg-editor/terms/
4
+ * Copyright 2014-2016 Froala Labs
5
+ */
6
+
7
+ (function (factory) {
8
+ if (typeof define === 'function' && define.amd) {
9
+ // AMD. Register as an anonymous module.
10
+ define(['jquery'], factory);
11
+ } else if (typeof module === 'object' && module.exports) {
12
+ // Node/CommonJS
13
+ module.exports = function( root, jQuery ) {
14
+ if ( jQuery === undefined ) {
15
+ // require('jQuery') returns a factory that requires window to
16
+ // build a jQuery instance, we normalize how we use modules
17
+ // that require this pattern but the window provided is a noop
18
+ // if it's defined (how jquery works)
19
+ if ( typeof window !== 'undefined' ) {
20
+ jQuery = require('jquery');
21
+ }
22
+ else {
23
+ jQuery = require('jquery')(root);
24
+ }
25
+ }
26
+ factory(jQuery);
27
+ return jQuery;
28
+ };
29
+ } else {
30
+ // Browser globals
31
+ factory(jQuery);
32
+ }
33
+ }(function ($) {
34
+
35
+ 'use strict';
36
+
37
+ $.extend($.FE.POPUP_TEMPLATES, {
38
+ 'link.edit': '[_BUTTONS_]',
39
+ 'link.insert': '[_BUTTONS_][_INPUT_LAYER_]'
40
+ })
41
+
42
+ $.extend($.FE.DEFAULTS, {
43
+ linkEditButtons: ['linkOpen', 'linkStyle', 'linkEdit', 'linkRemove'],
44
+ linkInsertButtons: ['linkBack', '|', 'linkList'],
45
+ linkAttributes: {},
46
+ linkAutoPrefix: 'http://',
47
+ linkStyles: {
48
+ 'fr-green': 'Green',
49
+ 'fr-strong': 'Thick'
50
+ },
51
+ linkMultipleStyles: true,
52
+ linkConvertEmailAddress: true,
53
+ linkAlwaysBlank: false,
54
+ linkAlwaysNoFollow: false,
55
+ linkList: [
56
+ {
57
+ text: 'Froala',
58
+ href: 'https://froala.com',
59
+ target: '_blank'
60
+ },
61
+ {
62
+ text: 'Google',
63
+ href: 'https://google.com',
64
+ target: '_blank'
65
+ },
66
+ {
67
+ displayText: 'Facebook',
68
+ href: 'https://facebook.com'
69
+ }
70
+ ],
71
+ linkText: true
72
+ });
73
+
74
+ $.FE.PLUGINS.link = function (editor) {
75
+ function get () {
76
+ var $current_image = editor.image ? editor.image.get() : null;
77
+
78
+ if (!$current_image && editor.$wp) {
79
+ var s_el = editor.selection.element();
80
+ var e_el = editor.selection.endElement();
81
+
82
+ if (s_el.tagName != 'A' && !editor.node.isElement(s_el)) {
83
+ s_el = $(s_el).parentsUntil(editor.$el, 'a:first').get(0);
84
+ }
85
+
86
+ if (e_el.tagName != 'A' && !editor.node.isElement(e_el)) {
87
+ e_el = $(e_el).parentsUntil(editor.$el, 'a:first').get(0);
88
+ }
89
+
90
+ if (e_el && e_el == s_el && e_el.tagName == 'A') {
91
+ return s_el;
92
+ }
93
+
94
+ return null;
95
+ }
96
+ else if (editor.$el.get(0).tagName == 'A' && editor.core.hasFocus()) {
97
+ return editor.$el.get(0);
98
+ }
99
+ else {
100
+ if ($current_image && $current_image.get(0).parentNode && $current_image.get(0).parentNode.tagName == 'A') {
101
+ return $current_image.get(0).parentNode;
102
+ }
103
+ }
104
+ }
105
+
106
+ function allSelected () {
107
+ var $current_image = editor.image ? editor.image.get() : null;
108
+
109
+ var selectedLinks = [];
110
+ if ($current_image) {
111
+ if ($current_image.get(0).parentNode.tagName == 'A') {
112
+ selectedLinks.push($current_image.get(0).parentNode);
113
+ }
114
+ }
115
+ else {
116
+ var range;
117
+ var containerEl;
118
+ var links;
119
+ var linkRange;
120
+
121
+ if (editor.win.getSelection) {
122
+ var sel = editor.win.getSelection();
123
+ if (sel.getRangeAt && sel.rangeCount) {
124
+ linkRange = editor.doc.createRange();
125
+ for (var r = 0; r < sel.rangeCount; ++r) {
126
+ range = sel.getRangeAt(r);
127
+ containerEl = range.commonAncestorContainer;
128
+
129
+ if (containerEl && containerEl.nodeType != 1) {
130
+ containerEl = containerEl.parentNode;
131
+ }
132
+
133
+ if (containerEl && containerEl.nodeName.toLowerCase() == 'a') {
134
+ selectedLinks.push(containerEl);
135
+ } else {
136
+ links = containerEl.getElementsByTagName('a');
137
+ for (var i = 0; i < links.length; ++i) {
138
+ linkRange.selectNodeContents(links[i]);
139
+ if (linkRange.compareBoundaryPoints(range.END_TO_START, range) < 1 && linkRange.compareBoundaryPoints(range.START_TO_END, range) > -1) {
140
+ selectedLinks.push(links[i]);
141
+ }
142
+ }
143
+ }
144
+ }
145
+ // linkRange.detach();
146
+ }
147
+ } else if (editor.doc.selection && editor.doc.selection.type != 'Control') {
148
+ range = editor.doc.selection.createRange();
149
+ containerEl = range.parentElement();
150
+ if (containerEl.nodeName.toLowerCase() == 'a') {
151
+ selectedLinks.push(containerEl);
152
+ } else {
153
+ links = containerEl.getElementsByTagName('a');
154
+ linkRange = editor.doc.body.createTextRange();
155
+ for (var j = 0; j < links.length; ++j) {
156
+ linkRange.moveToElementText(links[j]);
157
+ if (linkRange.compareEndPoints('StartToEnd', range) > -1 && linkRange.compareEndPoints('EndToStart', range) < 1) {
158
+ selectedLinks.push(links[j]);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+
165
+ return selectedLinks;
166
+ }
167
+
168
+ function _edit (e) {
169
+ _hideEditPopup();
170
+
171
+ setTimeout (function () {
172
+ // No event passed.
173
+ // Event passed and (left click or other event type).
174
+ if (!e || (e && (e.which == 1 || e.type != 'mouseup'))) {
175
+ var link = get();
176
+ var $current_image = editor.image ? editor.image.get() : null;
177
+
178
+ if (link && !$current_image) {
179
+ if (editor.image) {
180
+ var contents = editor.node.contents(link);
181
+
182
+ // https://github.com/froala/wysiwyg-editor/issues/1103
183
+ if (contents.length == 1 && contents[0].tagName == 'IMG') {
184
+ var range = editor.selection.ranges(0);
185
+ if (range.startOffset === 0 && range.endOffset === 0) {
186
+ $(link).before($.FE.MARKERS);
187
+ }
188
+ else {
189
+ $(link).after($.FE.MARKERS);
190
+ }
191
+
192
+ editor.selection.restore();
193
+ return false;
194
+ }
195
+ }
196
+
197
+ if (e) {
198
+ e.stopPropagation();
199
+ }
200
+
201
+ _showEditPopup(link);
202
+ }
203
+ }
204
+ }, editor.helpers.isIOS() ? 100 : 0);
205
+ }
206
+
207
+ function _showEditPopup (link) {
208
+ var $popup = editor.popups.get('link.edit');
209
+ if (!$popup) $popup = _initEditPopup();
210
+
211
+ var $link = $(link);
212
+
213
+ if (!editor.popups.isVisible('link.edit')) {
214
+ editor.popups.refresh('link.edit');
215
+ }
216
+
217
+ editor.popups.setContainer('link.edit', $(editor.opts.scrollableContainer));
218
+ var left = $link.offset().left + $(link).outerWidth() / 2;
219
+ var top = $link.offset().top + $link.outerHeight();
220
+
221
+ editor.popups.show('link.edit', left, top, $link.outerHeight());
222
+ }
223
+
224
+ function _hideEditPopup () {
225
+ editor.popups.hide('link.edit');
226
+ }
227
+
228
+ function _initEditPopup () {
229
+ // Link buttons.
230
+ var link_buttons = '';
231
+ if (editor.opts.linkEditButtons.length > 1) {
232
+ if (editor.$el.get(0).tagName == 'A' && editor.opts.linkEditButtons.indexOf('linkRemove') >= 0) {
233
+ editor.opts.linkEditButtons.splice(editor.opts.linkEditButtons.indexOf('linkRemove'), 1);
234
+ }
235
+
236
+ link_buttons = '<div class="fr-buttons">' + editor.button.buildList(editor.opts.linkEditButtons) + '</div>';
237
+ }
238
+
239
+ var template = {
240
+ buttons: link_buttons
241
+ };
242
+
243
+ // Set the template in the popup.
244
+ var $popup = editor.popups.create('link.edit', template);
245
+
246
+ if (editor.$wp) {
247
+ editor.events.$on(editor.$wp, 'scroll.link-edit', function () {
248
+ if (get() && editor.popups.isVisible('link.edit')) {
249
+ _showEditPopup(get());
250
+ }
251
+ });
252
+ }
253
+
254
+ return $popup;
255
+ }
256
+
257
+ /**
258
+ * Hide link insert popup.
259
+ */
260
+ function _hideInsertPopup () {
261
+ }
262
+
263
+ function _refreshInsertPopup () {
264
+ var $popup = editor.popups.get('link.insert');
265
+ var link = get();
266
+
267
+ if (link) {
268
+ var $link = $(link);
269
+ var text_inputs = $popup.find('input.fr-link-attr[type="text"]');
270
+ var check_inputs = $popup.find('input.fr-link-attr[type="checkbox"]');
271
+
272
+
273
+ var i;
274
+ var $input;
275
+ for (i = 0; i < text_inputs.length; i++) {
276
+ $input = $(text_inputs[i]);
277
+ $input.val($link.attr($input.attr('name') || ''));
278
+ }
279
+
280
+ check_inputs.prop('checked', false);
281
+ for (i = 0; i < check_inputs.length; i++) {
282
+ $input = $(check_inputs[i]);
283
+ if ($link.attr($input.attr('name')) == $input.data('checked')) {
284
+ $input.prop('checked', true);
285
+ }
286
+ }
287
+
288
+ $popup.find('input.fr-link-attr[type="text"][name="text"]').val($link.text());
289
+ }
290
+ else {
291
+ $popup.find('input.fr-link-attr[type="text"]').val('');
292
+ $popup.find('input.fr-link-attr[type="checkbox"]').prop('checked', false);
293
+ $popup.find('input.fr-link-attr[type="text"][name="text"]').val(editor.selection.text());
294
+ }
295
+
296
+ $popup.find('input.fr-link-attr').trigger('change');
297
+
298
+ var $current_image = editor.image ? editor.image.get() : null;
299
+ if ($current_image) {
300
+ $popup.find('.fr-link-attr[name="text"]').parent().hide();
301
+ }
302
+ else {
303
+ $popup.find('.fr-link-attr[name="text"]').parent().show();
304
+ }
305
+ }
306
+
307
+ function _showInsertPopup () {
308
+ var $btn = editor.$tb.find('.fr-command[data-cmd="insertLink"]');
309
+
310
+ var $popup = editor.popups.get('link.insert');
311
+ if (!$popup) $popup = _initInsertPopup();
312
+
313
+ if (!$popup.hasClass('fr-active')) {
314
+ editor.popups.refresh('link.insert');
315
+ editor.popups.setContainer('link.insert', editor.$tb || $(editor.opts.scrollableContainer));
316
+
317
+ if ($btn.is(':visible')) {
318
+ var left = $btn.offset().left + $btn.outerWidth() / 2;
319
+ var top = $btn.offset().top + (editor.opts.toolbarBottom ? 10 : $btn.outerHeight() - 10);
320
+ editor.popups.show('link.insert', left, top, $btn.outerHeight());
321
+ }
322
+ else {
323
+ editor.position.forSelection($popup);
324
+ editor.popups.show('link.insert');
325
+ }
326
+ }
327
+ }
328
+
329
+ function _initInsertPopup (delayed) {
330
+ if (delayed) {
331
+ editor.popups.onRefresh('link.insert', _refreshInsertPopup);
332
+ editor.popups.onHide('link.insert', _hideInsertPopup);
333
+
334
+ return true;
335
+ }
336
+
337
+ // Image buttons.
338
+ var link_buttons = '';
339
+ if (editor.opts.linkInsertButtons.length >= 1) {
340
+ link_buttons = '<div class="fr-buttons">' + editor.button.buildList(editor.opts.linkInsertButtons) + '</div>';
341
+ }
342
+
343
+ var checkmark = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="10" height="10" viewBox="0 0 32 32"><path d="M27 4l-15 15-7-7-5 5 12 12 20-20z" fill="#FFF"></path></svg>';
344
+
345
+ // Image by url layer.
346
+ var input_layer = '';
347
+ var tab_idx = 0;
348
+ input_layer = '<div class="fr-link-insert-layer fr-layer fr-active" id="fr-link-insert-layer-' + editor.id + '">';
349
+ input_layer += '<div class="fr-input-line"><input name="href" type="text" class="fr-link-attr" placeholder="URL" tabIndex="' + (++tab_idx) + '"></div>';
350
+
351
+ if (editor.opts.linkText) {
352
+ input_layer += '<div class="fr-input-line"><input name="text" type="text" class="fr-link-attr" placeholder="' + editor.language.translate('Text') + '" tabIndex="' + (++tab_idx) + '"></div>';
353
+ }
354
+
355
+ // Add any additional fields.
356
+ for (var attr in editor.opts.linkAttributes) {
357
+ if (editor.opts.linkAttributes.hasOwnProperty(attr)) {
358
+ var placeholder = editor.opts.linkAttributes[attr];
359
+ input_layer += '<div class="fr-input-line"><input name="' + attr + '" type="text" class="fr-link-attr" placeholder="' + editor.language.translate(placeholder) + '" tabIndex="' + (++tab_idx) + '"></div>';
360
+ }
361
+ }
362
+
363
+ if (!editor.opts.linkAlwaysBlank) {
364
+ input_layer += '<div class="fr-checkbox-line"><span class="fr-checkbox"><input name="target" class="fr-link-attr" data-checked="_blank" type="checkbox" id="fr-link-target-' + editor.id + '" tabIndex="' + (++tab_idx) + '"><span>' + checkmark + '</span></span><label for="fr-link-target-' + editor.id + '">' + editor.language.translate('Open in new tab') + '</label></div>';
365
+ }
366
+
367
+ input_layer += '<div class="fr-action-buttons"><button class="fr-command fr-submit" data-cmd="linkInsert" href="#" tabIndex="' + (++tab_idx) + '" type="button">' + editor.language.translate('Insert') + '</button></div></div>'
368
+
369
+ var template = {
370
+ buttons: link_buttons,
371
+ input_layer: input_layer
372
+ }
373
+
374
+ // Set the template in the popup.
375
+ var $popup = editor.popups.create('link.insert', template);
376
+
377
+ if (editor.$wp) {
378
+ editor.events.$on(editor.$wp, 'scroll.link-insert', function () {
379
+ var $current_image = editor.image ? editor.image.get() : null;
380
+ if ($current_image && editor.popups.isVisible('link.insert')) {
381
+ imageLink();
382
+ }
383
+
384
+ if (get && editor.popups.isVisible('link.insert')) {
385
+ update();
386
+ }
387
+ });
388
+ }
389
+
390
+ return $popup;
391
+ }
392
+
393
+ function remove () {
394
+ var link = get();
395
+ var $current_image = editor.image ? editor.image.get() : null;
396
+
397
+ if (editor.events.trigger('link.beforeRemove', [link]) === false) return false;
398
+
399
+ if ($current_image && link) {
400
+ $current_image.unwrap();
401
+ editor.image.edit($current_image);
402
+ }
403
+ else if (link) {
404
+ editor.selection.save();
405
+ $(link).replaceWith($(link).html());
406
+ editor.selection.restore();
407
+ _hideEditPopup();
408
+ }
409
+ }
410
+
411
+ function _init () {
412
+ // Edit on keyup.
413
+ editor.events.on('keyup', function (e) {
414
+ if (e.which != $.FE.KEYCODE.ESC) {
415
+ _edit(e);
416
+ }
417
+ });
418
+
419
+ editor.events.on('window.mouseup', _edit);
420
+
421
+ if (editor.helpers.isMobile()) {
422
+ editor.events.$on(editor.$doc, 'selectionchange', _edit);
423
+ }
424
+
425
+ _initInsertPopup(true);
426
+
427
+ // Init on link.
428
+ if (editor.$el.get(0).tagName == 'A') {
429
+ editor.$el.addClass('fr-view');
430
+ }
431
+ }
432
+
433
+ function usePredefined (val) {
434
+ var link = editor.opts.linkList[val];
435
+
436
+ var $popup = editor.popups.get('link.insert');
437
+ var text_inputs = $popup.find('input.fr-link-attr[type="text"]');
438
+ var check_inputs = $popup.find('input.fr-link-attr[type="checkbox"]');
439
+
440
+ var $input;
441
+ var i;
442
+ for (i = 0; i < text_inputs.length; i++) {
443
+ $input = $(text_inputs[i]);
444
+ if (link[$input.attr('name')]) {
445
+ $input.val(link[$input.attr('name')]);
446
+ }
447
+ else if ($input.attr('name') != 'text') {
448
+ $input.val('');
449
+ }
450
+ }
451
+
452
+ for (i = 0; i < check_inputs.length; i++) {
453
+ $input = $(check_inputs[i]);
454
+ $input.prop('checked', $input.data('checked') == link[$input.attr('name')]);
455
+ }
456
+ }
457
+
458
+ function insertCallback () {
459
+ var $popup = editor.popups.get('link.insert');
460
+ var text_inputs = $popup.find('input.fr-link-attr[type="text"]');
461
+ var check_inputs = $popup.find('input.fr-link-attr[type="checkbox"]');
462
+
463
+ var href = text_inputs.filter('[name="href"]').val();
464
+ var text = text_inputs.filter('[name="text"]').val();
465
+
466
+ var attrs = {};
467
+ var $input;
468
+ var i;
469
+ for (i = 0; i < text_inputs.length; i++) {
470
+ $input = $(text_inputs[i]);
471
+ if (['href', 'text'].indexOf($input.attr('name')) < 0) {
472
+ attrs[$input.attr('name')] = $input.val();
473
+ }
474
+ }
475
+
476
+ for (i = 0; i < check_inputs.length; i++) {
477
+ $input = $(check_inputs[i]);
478
+ if ($input.is(':checked')) {
479
+ attrs[$input.attr('name')] = $input.data('checked');
480
+ }
481
+ else {
482
+ attrs[$input.attr('name')] = $input.data('unchecked');
483
+ }
484
+ }
485
+
486
+ var t = $(editor.o_win).scrollTop();
487
+ insert(href, text, attrs);
488
+ $(editor.o_win).scrollTop(t);
489
+ }
490
+
491
+ function _split () {
492
+ if (!editor.selection.isCollapsed()) {
493
+ editor.selection.save();
494
+ var markers = editor.$el.find('.fr-marker').addClass('fr-unprocessed').toArray();
495
+ while (markers.length) {
496
+ var $marker = $(markers.pop());
497
+ $marker.removeClass('fr-unprocessed');
498
+
499
+ var deep_parent = editor.node.deepestParent($marker.get(0));
500
+ if (deep_parent) {
501
+ var node = $marker.get(0);
502
+ var close_str = '';
503
+ var open_str = '';
504
+ do {
505
+ node = node.parentNode;
506
+ if (!editor.node.isBlock(node)) {
507
+ close_str = close_str + editor.node.closeTagString(node);
508
+ open_str = editor.node.openTagString(node) + open_str;
509
+ }
510
+ } while (node != deep_parent);
511
+
512
+ var marker_str = editor.node.openTagString($marker.get(0)) + $marker.html() + editor.node.closeTagString($marker.get(0));
513
+
514
+ $marker.replaceWith('<span id="fr-break"></span>');
515
+ var h = $(deep_parent).html();
516
+ h = h.replace(/<span id="fr-break"><\/span>/g, close_str + marker_str + open_str);
517
+
518
+ $(deep_parent).html(h);
519
+ }
520
+
521
+ markers = editor.$el.find('.fr-marker.fr-unprocessed').toArray();
522
+ }
523
+
524
+ editor.selection.restore();
525
+ }
526
+ }
527
+
528
+ /**
529
+ * Insert link into the editor.
530
+ */
531
+ function insert (href, text, attrs) {
532
+ if (typeof attrs == 'undefined') attrs = {};
533
+
534
+ // Get image if we have one selected.
535
+ var $current_image = editor.image ? editor.image.get() : null;
536
+
537
+ if (!$current_image && editor.$el.get(0).tagName != 'A') {
538
+ editor.selection.restore();
539
+ editor.popups.hide('link.insert');
540
+ }
541
+ else if (editor.$el.get(0).tagName == 'A') {
542
+ editor.$el.focus();
543
+ }
544
+
545
+ var original_href = href;
546
+
547
+ // Convert email address.
548
+ if (editor.opts.linkConvertEmailAddress) {
549
+ var regex = /^[\w._]+@[a-z\u00a1-\uffff0-9_-]+?\.[a-z\u00a1-\uffff0-9]{2,}$/i;
550
+
551
+ if (regex.test(href) && !/^mailto:.*/i.test(href)) {
552
+ href = 'mailto:' + href;
553
+ }
554
+ }
555
+
556
+ // Add autoprefix.
557
+ if (editor.opts.linkAutoPrefix !== '' && !/^(mailto|tel|sms|notes|data):.*/i.test(href) && !/^data:image.*/i.test(href) && !/^(https?:|ftps?:|file:|)\/\//i.test(href)) {
558
+ // Do prefix only if starting character is not absolute.
559
+ if (['/', '{', '[', '#', '('].indexOf((href || '')[0]) < 0) {
560
+ href = editor.opts.linkAutoPrefix + href;
561
+ }
562
+ }
563
+
564
+ // Sanitize the URL.
565
+ href = editor.helpers.sanitizeURL(href);
566
+
567
+ // Default attributs.
568
+ if (editor.opts.linkAlwaysBlank) attrs.target = '_blank';
569
+ if (editor.opts.linkAlwaysNoFollow) attrs.rel = 'nofollow';
570
+
571
+ // Format text.
572
+ text = text || '';
573
+
574
+ if (href === editor.opts.linkAutoPrefix) {
575
+ var $popup = editor.popups.get('link.insert');
576
+ $popup.find('input[name="href"]').addClass('fr-error');
577
+ editor.events.trigger('link.bad', [original_href]);
578
+ return false;
579
+ }
580
+
581
+ // Check if we have selection only in one link.
582
+ var link = get();
583
+ var $link;
584
+
585
+ if (link) {
586
+ $link = $(link);
587
+
588
+ // Clear attributes.
589
+ var a_list = editor.node.rawAttributes(link);
590
+ for (var attr in a_list) {
591
+ if (a_list.hasOwnProperty(attr)) {
592
+ if (attr != 'class' && attr != 'style') {
593
+ $link.removeAttr(attr);
594
+ }
595
+ }
596
+ }
597
+
598
+ $link.attr('href', href);
599
+
600
+ // Change text if it is different.
601
+ if (text.length > 0 && $link.text() != text && !$current_image) {
602
+ $link.text(text);
603
+ }
604
+
605
+ if (!$current_image) {
606
+ $link
607
+ .prepend($.FE.START_MARKER)
608
+ .append($.FE.END_MARKER);
609
+ }
610
+
611
+ // Set attributes.
612
+ $link.attr(attrs);
613
+
614
+ if (!$current_image) {
615
+ editor.selection.restore();
616
+ }
617
+ }
618
+ else {
619
+ // We don't have any image selected.
620
+ if (!$current_image) {
621
+ // Remove current links.
622
+ editor.format.remove('a');
623
+
624
+ // Nothing is selected.
625
+ if (editor.selection.isCollapsed()) {
626
+ text = (text.length === 0 ? original_href : text);
627
+ editor.html.insert('<a href="' + href + '">' + $.FE.START_MARKER + text + $.FE.END_MARKER + '</a>');
628
+ editor.selection.restore();
629
+ }
630
+ else {
631
+ if (text.length > 0 && text != editor.selection.text().replace(/\n/g, '')) {
632
+ editor.selection.remove();
633
+ editor.html.insert('<a href="' + href + '">' + $.FE.START_MARKER + text + $.FE.END_MARKER + '</a>');
634
+ editor.selection.restore();
635
+ }
636
+ else {
637
+ _split();
638
+
639
+ // Add link.
640
+ editor.format.apply('a', { href: href });
641
+ }
642
+ }
643
+ }
644
+ else {
645
+ // Just wrap current image with a link.
646
+ $current_image.wrap('<a href="' + href + '"></a>');
647
+ }
648
+
649
+ // Set attributes.
650
+ var links = allSelected();
651
+ for (var i = 0; i < links.length; i++) {
652
+ $link = $(links[i]);
653
+ $link.attr(attrs);
654
+ $link.removeAttr('_moz_dirty');
655
+ }
656
+
657
+ // Show link edit if only one link.
658
+ if (links.length == 1 && editor.$wp && !$current_image) {
659
+ $(links[0])
660
+ .prepend($.FE.START_MARKER)
661
+ .append($.FE.END_MARKER);
662
+
663
+ editor.selection.restore();
664
+ }
665
+ }
666
+
667
+ // Hide popup and try to edit.
668
+ if (!$current_image) {
669
+ _edit();
670
+ }
671
+ else {
672
+ var $pop = editor.popups.get('link.insert');
673
+ $pop.find('input:focus').blur();
674
+ editor.image.edit($current_image);
675
+ }
676
+ }
677
+
678
+ function update () {
679
+ _hideEditPopup();
680
+
681
+ var link = get();
682
+ if (link) {
683
+ var $popup = editor.popups.get('link.insert');
684
+ if (!$popup) $popup = _initInsertPopup();
685
+
686
+ if (!editor.popups.isVisible('link.insert')) {
687
+ editor.popups.refresh('link.insert');
688
+ editor.selection.save();
689
+
690
+ if (editor.helpers.isMobile()) {
691
+ editor.events.disableBlur();
692
+ editor.$el.blur();
693
+ editor.events.enableBlur();
694
+ }
695
+ }
696
+
697
+ editor.popups.setContainer('link.insert', $(editor.opts.scrollableContainer));
698
+ var $ref = (editor.image ? editor.image.get() : null) || $(link);
699
+ var left = $ref.offset().left + $ref.outerWidth() / 2;
700
+ var top = $ref.offset().top + $ref.outerHeight();
701
+
702
+ editor.popups.show('link.insert', left, top, $ref.outerHeight());
703
+ }
704
+ }
705
+
706
+ function back () {
707
+ var $current_image = editor.image ? editor.image.get() : null;
708
+ if (!$current_image) {
709
+ editor.events.disableBlur();
710
+ editor.selection.restore();
711
+ editor.events.enableBlur();
712
+
713
+ var link = get();
714
+
715
+ if (link && editor.$wp) {
716
+ editor.selection.restore();
717
+ _hideEditPopup();
718
+ _edit();
719
+ }
720
+ else if (editor.$el.get(0).tagName == 'A') {
721
+ editor.$el.focus();
722
+ _edit();
723
+ }
724
+ else {
725
+ editor.popups.hide('link.insert');
726
+ editor.toolbar.showInline();
727
+ }
728
+ }
729
+ else {
730
+ editor.image.back();
731
+ }
732
+ }
733
+
734
+ function imageLink () {
735
+ var $current_image = editor.image ? editor.image.get() : null;
736
+
737
+ if ($current_image) {
738
+ var $popup = editor.popups.get('link.insert');
739
+ if (!$popup) $popup = _initInsertPopup();
740
+
741
+ _refreshInsertPopup(true);
742
+ editor.popups.setContainer('link.insert', $(editor.opts.scrollableContainer));
743
+ var left = $current_image.offset().left + $current_image.outerWidth() / 2;
744
+ var top = $current_image.offset().top + $current_image.outerHeight();
745
+
746
+ editor.popups.show('link.insert', left, top, $current_image.outerHeight());
747
+ }
748
+ }
749
+
750
+ /**
751
+ * Apply specific style.
752
+ */
753
+ function applyStyle (val, linkStyles, multipleStyles) {
754
+ if (typeof multipleStyles == 'undefined') multipleStyles = editor.opts.linkMultipleStyles;
755
+ if (typeof linkStyles == 'undefined') linkStyles = editor.opts.linkStyles;
756
+
757
+ var link = get();
758
+ if (!link) return false;
759
+
760
+ // Remove multiple styles.
761
+ if (!multipleStyles) {
762
+ var styles = Object.keys(linkStyles);
763
+ styles.splice(styles.indexOf(val), 1);
764
+ $(link).removeClass(styles.join(' '));
765
+ }
766
+
767
+ $(link).toggleClass(val);
768
+
769
+ _edit();
770
+ }
771
+
772
+ return {
773
+ _init: _init,
774
+ remove: remove,
775
+ showInsertPopup: _showInsertPopup,
776
+ usePredefined: usePredefined,
777
+ insertCallback: insertCallback,
778
+ insert: insert,
779
+ update: update,
780
+ get: get,
781
+ allSelected: allSelected,
782
+ back: back,
783
+ imageLink: imageLink,
784
+ applyStyle: applyStyle
785
+ }
786
+ }
787
+
788
+ // Register the link command.
789
+ $.FE.DefineIcon('insertLink', { NAME: 'link' });
790
+ $.FE.RegisterShortcut($.FE.KEYCODE.K, 'insertLink', null, 'K');
791
+ $.FE.RegisterCommand('insertLink', {
792
+ title: 'Insert Link',
793
+ undo: false,
794
+ focus: true,
795
+ refreshOnCallback: false,
796
+ popup: true,
797
+ callback: function () {
798
+ if (!this.popups.isVisible('link.insert')) {
799
+ this.link.showInsertPopup();
800
+ }
801
+ else {
802
+ if (this.$el.find('.fr-marker')) {
803
+ this.events.disableBlur();
804
+ this.selection.restore();
805
+ }
806
+ this.popups.hide('link.insert');
807
+ }
808
+ },
809
+ plugin: 'link'
810
+ })
811
+
812
+ $.FE.DefineIcon('linkOpen', { NAME: 'external-link' });
813
+ $.FE.RegisterCommand('linkOpen', {
814
+ title: 'Open Link',
815
+ undo: false,
816
+ refresh: function ($btn) {
817
+ var link = this.link.get();
818
+ if (link) {
819
+ $btn.removeClass('fr-hidden');
820
+ }
821
+ else {
822
+ $btn.addClass('fr-hidden');
823
+ }
824
+ },
825
+ callback: function () {
826
+ var link = this.link.get();
827
+ if (link) {
828
+ this.o_win.open(link.href);
829
+ }
830
+ }
831
+ })
832
+
833
+ $.FE.DefineIcon('linkEdit', { NAME: 'edit' });
834
+ $.FE.RegisterCommand('linkEdit', {
835
+ title: 'Edit Link',
836
+ undo: false,
837
+ refreshAfterCallback: false,
838
+ callback: function () {
839
+ this.link.update();
840
+ },
841
+ refresh: function ($btn) {
842
+ var link = this.link.get();
843
+ if (link) {
844
+ $btn.removeClass('fr-hidden');
845
+ }
846
+ else {
847
+ $btn.addClass('fr-hidden');
848
+ }
849
+ }
850
+ })
851
+
852
+ $.FE.DefineIcon('linkRemove', { NAME: 'unlink' });
853
+ $.FE.RegisterCommand('linkRemove', {
854
+ title: 'Unlink',
855
+ callback: function () {
856
+ this.link.remove();
857
+ },
858
+ refresh: function ($btn) {
859
+ var link = this.link.get();
860
+ if (link) {
861
+ $btn.removeClass('fr-hidden');
862
+ }
863
+ else {
864
+ $btn.addClass('fr-hidden');
865
+ }
866
+ }
867
+ })
868
+
869
+ $.FE.DefineIcon('linkBack', { NAME: 'arrow-left' });
870
+ $.FE.RegisterCommand('linkBack', {
871
+ title: 'Back',
872
+ undo: false,
873
+ focus: false,
874
+ back: true,
875
+ refreshAfterCallback: false,
876
+ callback: function () {
877
+ this.link.back();
878
+ },
879
+ refresh: function ($btn) {
880
+ var link = this.link.get();
881
+ var $current_image = this.image ? this.image.get() : null;
882
+ if (!$current_image && !link && !this.opts.toolbarInline) {
883
+ $btn.addClass('fr-hidden');
884
+ $btn.next('.fr-separator').addClass('fr-hidden');
885
+ }
886
+ else {
887
+ $btn.removeClass('fr-hidden');
888
+ $btn.next('.fr-separator').removeClass('fr-hidden');
889
+ }
890
+ }
891
+ });
892
+
893
+ $.FE.DefineIcon('linkList', { NAME: 'search' });
894
+ $.FE.RegisterCommand('linkList', {
895
+ title: 'Choose Link',
896
+ type: 'dropdown',
897
+ focus: false,
898
+ undo: false,
899
+ refreshAfterCallback: false,
900
+ html: function () {
901
+ var c = '<ul class="fr-dropdown-list">';
902
+ var options = this.opts.linkList;
903
+ for (var i = 0; i < options.length; i++) {
904
+ c += '<li><a class="fr-command" data-cmd="linkList" data-param1="' + i + '">' + (options[i].displayText || options[i].text) + '</a></li>';
905
+ }
906
+ c += '</ul>';
907
+
908
+ return c;
909
+ },
910
+ callback: function (cmd, val) {
911
+ this.link.usePredefined(val);
912
+ }
913
+ })
914
+
915
+ $.FE.RegisterCommand('linkInsert', {
916
+ focus: false,
917
+ refreshAfterCallback: false,
918
+ callback: function () {
919
+ this.link.insertCallback();
920
+ },
921
+ refresh: function ($btn) {
922
+ var link = this.link.get();
923
+ if (link) {
924
+ $btn.text(this.language.translate('Update'));
925
+ }
926
+ else {
927
+ $btn.text(this.language.translate('Insert'));
928
+ }
929
+ }
930
+ })
931
+
932
+ // Image link.
933
+ $.FE.DefineIcon('imageLink', { NAME: 'link' })
934
+ $.FE.RegisterCommand('imageLink', {
935
+ title: 'Insert Link',
936
+ undo: false,
937
+ focus: false,
938
+ callback: function () {
939
+ this.link.imageLink();
940
+ },
941
+ refresh: function ($btn) {
942
+ var link = this.link.get();
943
+ var $prev;
944
+
945
+ if (link) {
946
+ $prev = $btn.prev();
947
+ if ($prev.hasClass('fr-separator')) {
948
+ $prev.removeClass('fr-hidden');
949
+ }
950
+
951
+ $btn.addClass('fr-hidden');
952
+ }
953
+ else {
954
+ $prev = $btn.prev();
955
+ if ($prev.hasClass('fr-separator')) {
956
+ $prev.addClass('fr-hidden');
957
+ }
958
+
959
+ $btn.removeClass('fr-hidden');
960
+ }
961
+ }
962
+ })
963
+
964
+ // Link styles.
965
+ $.FE.DefineIcon('linkStyle', { NAME: 'magic' })
966
+ $.FE.RegisterCommand('linkStyle', {
967
+ title: 'Style',
968
+ type: 'dropdown',
969
+ html: function () {
970
+ var c = '<ul class="fr-dropdown-list">';
971
+ var options = this.opts.linkStyles;
972
+ for (var cls in options) {
973
+ if (options.hasOwnProperty(cls)) {
974
+ c += '<li><a class="fr-command" data-cmd="linkStyle" data-param1="' + cls + '">' + this.language.translate(options[cls]) + '</a></li>';
975
+ }
976
+ }
977
+ c += '</ul>';
978
+
979
+ return c;
980
+ },
981
+ callback: function (cmd, val) {
982
+ this.link.applyStyle(val);
983
+ },
984
+ refreshOnShow: function ($btn, $dropdown) {
985
+ var link = this.link.get();
986
+
987
+ if (link) {
988
+ var $link = $(link);
989
+ $dropdown.find('.fr-command').each (function () {
990
+ var cls = $(this).data('param1');
991
+ $(this).toggleClass('fr-active', $link.hasClass(cls));
992
+ })
993
+ }
994
+ }
995
+ })
996
+
997
+ }));