promethee 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/promethee-editor.js +2 -0
  3. data/app/assets/stylesheets/promethee-editor.sass +1 -0
  4. data/app/views/promethee/_edit.html.erb +18 -18
  5. data/app/views/promethee/_localize.html.erb +49 -0
  6. data/app/views/promethee/_show.html.erb +2 -2
  7. data/app/views/promethee/components/_text_edit.html.erb +12 -8
  8. data/app/views/promethee/partials/_page.html.erb +1 -1
  9. data/lib/promethee/core_ext/form_builder.rb +4 -0
  10. data/lib/promethee/core_ext/form_helper.rb +4 -0
  11. data/lib/promethee/core_ext/tags.rb +9 -0
  12. data/lib/promethee/rails/engine.rb +0 -1
  13. data/lib/promethee/rails/version.rb +1 -1
  14. data/vendor/assets/fonts/summernote.eot +0 -0
  15. data/vendor/assets/fonts/summernote.ttf +0 -0
  16. data/vendor/assets/fonts/summernote.woff +0 -0
  17. data/vendor/assets/javascripts/angular-summernote.js +207 -0
  18. data/vendor/assets/javascripts/summernote/index.js +1 -0
  19. data/vendor/assets/javascripts/summernote/locales/ar-AR.js +104 -0
  20. data/vendor/assets/javascripts/summernote/locales/bg-BG.js +99 -0
  21. data/vendor/assets/javascripts/summernote/locales/ca-ES.js +147 -0
  22. data/vendor/assets/javascripts/summernote/locales/cs-CZ.js +103 -0
  23. data/vendor/assets/javascripts/summernote/locales/da-DK.js +114 -0
  24. data/vendor/assets/javascripts/summernote/locales/de-DE.js +110 -0
  25. data/vendor/assets/javascripts/summernote/locales/el-GR.js +147 -0
  26. data/vendor/assets/javascripts/summernote/locales/es-ES.js +147 -0
  27. data/vendor/assets/javascripts/summernote/locales/es-EU.js +103 -0
  28. data/vendor/assets/javascripts/summernote/locales/fa-IR.js +105 -0
  29. data/vendor/assets/javascripts/summernote/locales/fi-FI.js +104 -0
  30. data/vendor/assets/javascripts/summernote/locales/fr-FR.js +154 -0
  31. data/vendor/assets/javascripts/summernote/locales/gl-ES.js +147 -0
  32. data/vendor/assets/javascripts/summernote/locales/he-IL.js +107 -0
  33. data/vendor/assets/javascripts/summernote/locales/hr-HR.js +104 -0
  34. data/vendor/assets/javascripts/summernote/locales/hu-HU.js +135 -0
  35. data/vendor/assets/javascripts/summernote/locales/id-ID.js +103 -0
  36. data/vendor/assets/javascripts/summernote/locales/index.js +1 -0
  37. data/vendor/assets/javascripts/summernote/locales/it-IT.js +104 -0
  38. data/vendor/assets/javascripts/summernote/locales/ja-JP.js +133 -0
  39. data/vendor/assets/javascripts/summernote/locales/ko-KR.js +115 -0
  40. data/vendor/assets/javascripts/summernote/locales/lt-LT.js +107 -0
  41. data/vendor/assets/javascripts/summernote/locales/lt-LV.js +135 -0
  42. data/vendor/assets/javascripts/summernote/locales/mn-MN.js +118 -0
  43. data/vendor/assets/javascripts/summernote/locales/nb-NO.js +104 -0
  44. data/vendor/assets/javascripts/summernote/locales/nl-NL.js +104 -0
  45. data/vendor/assets/javascripts/summernote/locales/pl-PL.js +112 -0
  46. data/vendor/assets/javascripts/summernote/locales/pt-BR.js +138 -0
  47. data/vendor/assets/javascripts/summernote/locales/pt-PT.js +103 -0
  48. data/vendor/assets/javascripts/summernote/locales/ro-RO.js +102 -0
  49. data/vendor/assets/javascripts/summernote/locales/ru-RU.js +112 -0
  50. data/vendor/assets/javascripts/summernote/locales/sk-SK.js +102 -0
  51. data/vendor/assets/javascripts/summernote/locales/sl-SI.js +106 -0
  52. data/vendor/assets/javascripts/summernote/locales/sr-RS-Latin.js +104 -0
  53. data/vendor/assets/javascripts/summernote/locales/sr-RS.js +104 -0
  54. data/vendor/assets/javascripts/summernote/locales/sv-SE.js +104 -0
  55. data/vendor/assets/javascripts/summernote/locales/ta-IN.js +113 -0
  56. data/vendor/assets/javascripts/summernote/locales/th-TH.js +106 -0
  57. data/vendor/assets/javascripts/summernote/locales/tr-TR.js +154 -0
  58. data/vendor/assets/javascripts/summernote/locales/uk-UA.js +111 -0
  59. data/vendor/assets/javascripts/summernote/locales/vi-VN.js +104 -0
  60. data/vendor/assets/javascripts/summernote/locales/zh-CN.js +142 -0
  61. data/vendor/assets/javascripts/summernote/locales/zh-TW.js +113 -0
  62. data/vendor/assets/javascripts/summernote/plugin/databasic/summernote-ext-databasic.css +16 -0
  63. data/vendor/assets/javascripts/summernote/plugin/databasic/summernote-ext-databasic.js +303 -0
  64. data/vendor/assets/javascripts/summernote/plugin/hello/summernote-ext-hello.js +82 -0
  65. data/vendor/assets/javascripts/summernote/plugin/specialchars/summernote-ext-specialchars.js +315 -0
  66. data/vendor/assets/javascripts/summernote/summernote-bs4.js +7990 -0
  67. data/vendor/assets/javascripts/summernote/summernote-lite.js +8598 -0
  68. data/vendor/assets/javascripts/summernote/summernote.js +7987 -0
  69. data/vendor/assets/stylesheets/summernote-bs4.css +1 -0
  70. data/vendor/assets/stylesheets/summernote-lite.css +1 -0
  71. data/vendor/assets/stylesheets/summernote.scss +1 -0
  72. metadata +60 -1
@@ -0,0 +1,16 @@
1
+ .ext-databasic {
2
+ position: relative;
3
+ display: block;
4
+ min-height: 50px;
5
+ background-color: cyan;
6
+ text-align: center;
7
+ padding: 20px;
8
+ border: 1px solid white;
9
+ border-radius: 10px;
10
+ }
11
+
12
+ .ext-databasic p {
13
+ color: white;
14
+ font-size: 1.2em;
15
+ margin: 0;
16
+ }
@@ -0,0 +1,303 @@
1
+ (function (factory) {
2
+ /* global define */
3
+ if (typeof define === 'function' && define.amd) {
4
+ // AMD. Register as an anonymous module.
5
+ define(['jquery'], factory);
6
+ } else if (typeof module === 'object' && module.exports) {
7
+ // Node/CommonJS
8
+ module.exports = factory(require('jquery'));
9
+ } else {
10
+ // Browser globals
11
+ factory(window.jQuery);
12
+ }
13
+ }(function ($) {
14
+
15
+ // pull in some summernote core functions
16
+ var ui = $.summernote.ui;
17
+ var dom = $.summernote.dom;
18
+
19
+ // define the popover plugin
20
+ var DataBasicPlugin = function (context) {
21
+ var self = this;
22
+ var options = context.options;
23
+ var lang = options.langInfo;
24
+
25
+ self.icon = '<i class="fa fa-object-group"/>';
26
+
27
+ // add context menu button for dialog
28
+ context.memo('button.databasic', function () {
29
+ return ui.button({
30
+ contents: self.icon,
31
+ tooltip: lang.databasic.insert,
32
+ click: context.createInvokeHandler('databasic.showDialog')
33
+ }).render();
34
+ });
35
+
36
+ // add popover edit button
37
+ context.memo('button.databasicDialog', function () {
38
+ return ui.button({
39
+ contents: self.icon,
40
+ tooltip: lang.databasic.edit,
41
+ click: context.createInvokeHandler('databasic.showDialog')
42
+ }).render();
43
+ });
44
+
45
+ // add popover size buttons
46
+ context.memo('button.databasicSize100', function () {
47
+ return ui.button({
48
+ contents: '<span class="note-fontsize-10">100%</span>',
49
+ tooltip: lang.image.resizeFull,
50
+ click: context.createInvokeHandler('editor.resize', '1')
51
+ }).render();
52
+ });
53
+ context.memo('button.databasicSize50', function () {
54
+ return ui.button({
55
+ contents: '<span class="note-fontsize-10">50%</span>',
56
+ tooltip: lang.image.resizeHalf,
57
+ click: context.createInvokeHandler('editor.resize', '0.5')
58
+ }).render();
59
+ });
60
+ context.memo('button.databasicSize25', function () {
61
+ return ui.button({
62
+ contents: '<span class="note-fontsize-10">25%</span>',
63
+ tooltip: lang.image.resizeQuarter,
64
+ click: context.createInvokeHandler('editor.resize', '0.25')
65
+ }).render();
66
+ });
67
+
68
+ self.events = {
69
+ 'summernote.init': function (we, e) {
70
+ // update existing containers
71
+ $('data.ext-databasic', e.editable).each(function () { self.setContent($(this)); });
72
+ // TODO: make this an undo snapshot...
73
+ },
74
+ 'summernote.keyup summernote.mouseup summernote.change summernote.scroll': function () {
75
+ self.update();
76
+ },
77
+ 'summernote.dialog.shown': function () {
78
+ self.hidePopover();
79
+ }
80
+ };
81
+
82
+ self.initialize = function () {
83
+ // create dialog markup
84
+ var $container = options.dialogsInBody ? $(document.body) : context.layoutInfo.editor;
85
+
86
+ var body = '<div class="form-group row-fluid">' +
87
+ '<label>' + lang.databasic.testLabel + '</label>' +
88
+ '<input class="ext-databasic-test form-control" type="text" />' +
89
+ '</div>';
90
+ var footer = '<button href="#" class="btn btn-primary ext-databasic-save">' + lang.databasic.insert + '</button>';
91
+
92
+ self.$dialog = ui.dialog({
93
+ title: lang.databasic.name,
94
+ fade: options.dialogsFade,
95
+ body: body,
96
+ footer: footer
97
+ }).render().appendTo($container);
98
+
99
+ // create popover
100
+ self.$popover = ui.popover({
101
+ className: 'ext-databasic-popover'
102
+ }).render().appendTo('body');
103
+ var $content = self.$popover.find('.popover-content');
104
+
105
+ context.invoke('buttons.build', $content, options.popover.databasic);
106
+ };
107
+
108
+ self.destroy = function () {
109
+ self.$popover.remove();
110
+ self.$popover = null;
111
+ self.$dialog.remove();
112
+ self.$dialog = null;
113
+ };
114
+
115
+ self.update = function () {
116
+ // Prevent focusing on editable when invoke('code') is executed
117
+ if (!context.invoke('editor.hasFocus')) {
118
+ self.hidePopover();
119
+ return;
120
+ }
121
+
122
+ var rng = context.invoke('editor.createRange');
123
+ var visible = false;
124
+
125
+ if (rng.isOnData())
126
+ {
127
+ var $data = $(rng.sc).closest('data.ext-databasic');
128
+
129
+ if ($data.length)
130
+ {
131
+ var pos = dom.posFromPlaceholder($data[0]);
132
+
133
+ self.$popover.css({
134
+ display: 'block',
135
+ left: pos.left,
136
+ top: pos.top
137
+ });
138
+
139
+ // save editor target to let size buttons resize the container
140
+ context.invoke('editor.saveTarget', $data[0]);
141
+
142
+ visible = true;
143
+ }
144
+
145
+ }
146
+
147
+ // hide if not visible
148
+ if (!visible) {
149
+ self.hidePopover();
150
+ }
151
+
152
+ };
153
+
154
+ self.hidePopover = function () {
155
+ self.$popover.hide();
156
+ };
157
+
158
+ // define plugin dialog
159
+ self.getInfo = function () {
160
+ var rng = context.invoke('editor.createRange');
161
+
162
+ if (rng.isOnData())
163
+ {
164
+ var $data = $(rng.sc).closest('data.ext-databasic');
165
+
166
+ if ($data.length)
167
+ {
168
+ // Get the first node on range(for edit).
169
+ return {
170
+ node: $data,
171
+ test: $data.attr('data-test')
172
+ };
173
+ }
174
+ }
175
+
176
+ return {};
177
+ };
178
+
179
+ self.setContent = function ($node) {
180
+ $node.html('<p contenteditable="false">' + self.icon + ' ' + lang.databasic.name + ': ' +
181
+ $node.attr('data-test') + '</p>');
182
+ };
183
+
184
+ self.updateNode = function (info) {
185
+ self.setContent(info.node
186
+ .attr('data-test', info.test));
187
+ };
188
+
189
+ self.createNode = function (info) {
190
+ var $node = $('<data class="ext-databasic"></data>');
191
+
192
+ if ($node) {
193
+ // save node to info structure
194
+ info.node = $node;
195
+ // insert node into editor dom
196
+ context.invoke('editor.insertNode', $node[0]);
197
+ }
198
+
199
+ return $node;
200
+ };
201
+
202
+ self.showDialog = function () {
203
+ var info = self.getInfo();
204
+ var newNode = !info.node;
205
+ context.invoke('editor.saveRange');
206
+
207
+ self
208
+ .openDialog(info)
209
+ .then(function (dialogInfo) {
210
+ // [workaround] hide dialog before restore range for IE range focus
211
+ ui.hideDialog(self.$dialog);
212
+ context.invoke('editor.restoreRange');
213
+
214
+ // insert a new node
215
+ if (newNode)
216
+ {
217
+ self.createNode(info);
218
+ }
219
+
220
+ // update info with dialog info
221
+ $.extend(info, dialogInfo);
222
+
223
+ self.updateNode(info);
224
+ })
225
+ .fail(function () {
226
+ context.invoke('editor.restoreRange');
227
+ });
228
+
229
+ };
230
+
231
+ self.openDialog = function (info) {
232
+ return $.Deferred(function (deferred) {
233
+ var $inpTest = self.$dialog.find('.ext-databasic-test');
234
+ var $saveBtn = self.$dialog.find('.ext-databasic-save');
235
+ var onKeyup = function (event) {
236
+ if (event.keyCode === 13)
237
+ {
238
+ $saveBtn.trigger('click');
239
+ }
240
+ };
241
+
242
+ ui.onDialogShown(self.$dialog, function () {
243
+ context.triggerEvent('dialog.shown');
244
+
245
+ $inpTest.val(info.test).on('input', function () {
246
+ ui.toggleBtn($saveBtn, $inpTest.val());
247
+ }).trigger('focus').on('keyup', onKeyup);
248
+
249
+ $saveBtn
250
+ .text(info.node ? lang.databasic.edit : lang.databasic.insert)
251
+ .click(function (event) {
252
+ event.preventDefault();
253
+
254
+ deferred.resolve({ test: $inpTest.val() });
255
+ });
256
+
257
+ // init save button
258
+ ui.toggleBtn($saveBtn, $inpTest.val());
259
+ });
260
+
261
+ ui.onDialogHidden(self.$dialog, function () {
262
+ $inpTest.off('input keyup');
263
+ $saveBtn.off('click');
264
+
265
+ if (deferred.state() === 'pending') {
266
+ deferred.reject();
267
+ }
268
+ });
269
+
270
+ ui.showDialog(self.$dialog);
271
+ });
272
+ };
273
+ };
274
+
275
+ // Extends summernote
276
+ $.extend(true, $.summernote, {
277
+ plugins: {
278
+ databasic: DataBasicPlugin
279
+ },
280
+
281
+ options: {
282
+ popover: {
283
+ databasic: [
284
+ ['databasic', ['databasicDialog', 'databasicSize100', 'databasicSize50', 'databasicSize25']]
285
+ ]
286
+ }
287
+ },
288
+
289
+ // add localization texts
290
+ lang: {
291
+ 'en-US': {
292
+ databasic: {
293
+ name: 'Basic Data Container',
294
+ insert: 'insert basic data container',
295
+ edit: 'edit basic data container',
296
+ testLabel: 'test input'
297
+ }
298
+ }
299
+ }
300
+
301
+ });
302
+
303
+ }));
@@ -0,0 +1,82 @@
1
+ (function (factory) {
2
+ /* global define */
3
+ if (typeof define === 'function' && define.amd) {
4
+ // AMD. Register as an anonymous module.
5
+ define(['jquery'], factory);
6
+ } else if (typeof module === 'object' && module.exports) {
7
+ // Node/CommonJS
8
+ module.exports = factory(require('jquery'));
9
+ } else {
10
+ // Browser globals
11
+ factory(window.jQuery);
12
+ }
13
+ }(function ($) {
14
+
15
+ // Extends plugins for adding hello.
16
+ // - plugin is external module for customizing.
17
+ $.extend($.summernote.plugins, {
18
+ /**
19
+ * @param {Object} context - context object has status of editor.
20
+ */
21
+ 'hello': function (context) {
22
+ var self = this;
23
+
24
+ // ui has renders to build ui elements.
25
+ // - you can create a button with `ui.button`
26
+ var ui = $.summernote.ui;
27
+
28
+ // add hello button
29
+ context.memo('button.hello', function () {
30
+ // create button
31
+ var button = ui.button({
32
+ contents: '<i class="fa fa-child"/> Hello',
33
+ tooltip: 'hello',
34
+ click: function () {
35
+ self.$panel.show();
36
+ self.$panel.hide(500);
37
+ // invoke insertText method with 'hello' on editor module.
38
+ context.invoke('editor.insertText', 'hello');
39
+ }
40
+ });
41
+
42
+ // create jQuery object from button instance.
43
+ var $hello = button.render();
44
+ return $hello;
45
+ });
46
+
47
+ // This events will be attached when editor is initialized.
48
+ this.events = {
49
+ // This will be called after modules are initialized.
50
+ 'summernote.init': function (we, e) {
51
+ console.log('summernote initialized', we, e);
52
+ },
53
+ // This will be called when user releases a key on editable.
54
+ 'summernote.keyup': function (we, e) {
55
+ console.log('summernote keyup', we, e);
56
+ }
57
+ };
58
+
59
+ // This method will be called when editor is initialized by $('..').summernote();
60
+ // You can create elements for plugin
61
+ this.initialize = function () {
62
+ this.$panel = $('<div class="hello-panel"/>').css({
63
+ position: 'absolute',
64
+ width: 100,
65
+ height: 100,
66
+ left: '50%',
67
+ top: '50%',
68
+ background: 'red'
69
+ }).hide();
70
+
71
+ this.$panel.appendTo('body');
72
+ };
73
+
74
+ // This methods will be called when editor is destroyed by $('..').summernote('destroy');
75
+ // You should remove elements on `initialize`.
76
+ this.destroy = function () {
77
+ this.$panel.remove();
78
+ this.$panel = null;
79
+ };
80
+ }
81
+ });
82
+ }));
@@ -0,0 +1,315 @@
1
+ (function (factory) {
2
+ /* global define */
3
+ if (typeof define === 'function' && define.amd) {
4
+ // AMD. Register as an anonymous module.
5
+ define(['jquery'], factory);
6
+ } else if (typeof module === 'object' && module.exports) {
7
+ // Node/CommonJS
8
+ module.exports = factory(require('jquery'));
9
+ } else {
10
+ // Browser globals
11
+ factory(window.jQuery);
12
+ }
13
+ }(function ($) {
14
+ $.extend($.summernote.plugins, {
15
+ 'specialchars': function (context) {
16
+ var self = this;
17
+ var ui = $.summernote.ui;
18
+
19
+ var $editor = context.layoutInfo.editor;
20
+ var options = context.options;
21
+ var lang = options.langInfo;
22
+
23
+ var KEY = {
24
+ UP: 38,
25
+ DOWN: 40,
26
+ LEFT: 37,
27
+ RIGHT: 39,
28
+ ENTER: 13
29
+ };
30
+ var COLUMN_LENGTH = 15;
31
+ var COLUMN_WIDTH = 35;
32
+
33
+ var currentColumn, currentRow, totalColumn, totalRow = 0;
34
+
35
+ // special characters data set
36
+ var specialCharDataSet = [
37
+ '&quot;', '&amp;', '&lt;', '&gt;', '&iexcl;', '&cent;',
38
+ '&pound;', '&curren;', '&yen;', '&brvbar;', '&sect;',
39
+ '&uml;', '&copy;', '&ordf;', '&laquo;', '&not;',
40
+ '&reg;', '&macr;', '&deg;', '&plusmn;', '&sup2;',
41
+ '&sup3;', '&acute;', '&micro;', '&para;', '&middot;',
42
+ '&cedil;', '&sup1;', '&ordm;', '&raquo;', '&frac14;',
43
+ '&frac12;', '&frac34;', '&iquest;', '&times;', '&divide;',
44
+ '&fnof;', '&circ;', '&tilde;', '&ndash;', '&mdash;',
45
+ '&lsquo;', '&rsquo;', '&sbquo;', '&ldquo;', '&rdquo;',
46
+ '&bdquo;', '&dagger;', '&Dagger;', '&bull;', '&hellip;',
47
+ '&permil;', '&prime;', '&Prime;', '&lsaquo;', '&rsaquo;',
48
+ '&oline;', '&frasl;', '&euro;', '&image;', '&weierp;',
49
+ '&real;', '&trade;', '&alefsym;', '&larr;', '&uarr;',
50
+ '&rarr;', '&darr;', '&harr;', '&crarr;', '&lArr;',
51
+ '&uArr;', '&rArr;', '&dArr;', '&hArr;', '&forall;',
52
+ '&part;', '&exist;', '&empty;', '&nabla;', '&isin;',
53
+ '&notin;', '&ni;', '&prod;', '&sum;', '&minus;',
54
+ '&lowast;', '&radic;', '&prop;', '&infin;', '&ang;',
55
+ '&and;', '&or;', '&cap;', '&cup;', '&int;',
56
+ '&there4;', '&sim;', '&cong;', '&asymp;', '&ne;',
57
+ '&equiv;', '&le;', '&ge;', '&sub;', '&sup;',
58
+ '&nsub;', '&sube;', '&supe;', '&oplus;', '&otimes;',
59
+ '&perp;', '&sdot;', '&lceil;', '&rceil;', '&lfloor;',
60
+ '&rfloor;', '&loz;', '&spades;', '&clubs;', '&hearts;',
61
+ '&diams;'
62
+ ];
63
+
64
+ context.memo('button.specialCharacter', function () {
65
+ return ui.button({
66
+ contents: '<i class="fa fa-font fa-flip-vertical">',
67
+ tooltip: lang.specialChar.specialChar,
68
+ click: function () {
69
+ self.show();
70
+ }
71
+ }).render();
72
+ });
73
+
74
+ /**
75
+ * Make Special Characters Table
76
+ *
77
+ * @member plugin.specialChar
78
+ * @private
79
+ * @return {jQuery}
80
+ */
81
+ this.makeSpecialCharSetTable = function () {
82
+ var $table = $('<table/>');
83
+ $.each(specialCharDataSet, function (idx, text) {
84
+ var $td = $('<td/>').addClass('note-specialchar-node');
85
+ var $tr = (idx % COLUMN_LENGTH === 0) ? $('<tr/>') : $table.find('tr').last();
86
+
87
+ var $button = ui.button({
88
+ callback: function ($node) {
89
+ $node.html(text);
90
+ $node.attr('title', text);
91
+ $node.attr('data-value', encodeURIComponent(text));
92
+ $node.css({
93
+ width: COLUMN_WIDTH,
94
+ 'margin-right': '2px',
95
+ 'margin-bottom': '2px'
96
+ });
97
+ }
98
+ }).render();
99
+
100
+ $td.append($button);
101
+
102
+ $tr.append($td);
103
+ if (idx % COLUMN_LENGTH === 0) {
104
+ $table.append($tr);
105
+ }
106
+ });
107
+
108
+ totalRow = $table.find('tr').length;
109
+ totalColumn = COLUMN_LENGTH;
110
+
111
+ return $table;
112
+ };
113
+
114
+ this.initialize = function () {
115
+ var $container = options.dialogsInBody ? $(document.body) : $editor;
116
+
117
+ var body = '<div class="form-group row-fluid">' + this.makeSpecialCharSetTable()[0].outerHTML + '</div>';
118
+
119
+ this.$dialog = ui.dialog({
120
+ title: lang.specialChar.select,
121
+ body: body
122
+ }).render().appendTo($container);
123
+ };
124
+
125
+ this.show = function () {
126
+ var text = context.invoke('editor.getSelectedText');
127
+ context.invoke('editor.saveRange');
128
+ this.showSpecialCharDialog(text).then(function (selectChar) {
129
+ context.invoke('editor.restoreRange');
130
+
131
+ // build node
132
+ var $node = $('<span></span>').html(selectChar)[0];
133
+
134
+ if ($node) {
135
+ // insert video node
136
+ context.invoke('editor.insertNode', $node);
137
+ }
138
+ }).fail(function () {
139
+ context.invoke('editor.restoreRange');
140
+ });
141
+ };
142
+
143
+ /**
144
+ * show image dialog
145
+ *
146
+ * @param {jQuery} $dialog
147
+ * @return {Promise}
148
+ */
149
+ this.showSpecialCharDialog = function (text) {
150
+ return $.Deferred(function (deferred) {
151
+ var $specialCharDialog = self.$dialog;
152
+ var $specialCharNode = $specialCharDialog.find('.note-specialchar-node');
153
+ var $selectedNode = null;
154
+ var ARROW_KEYS = [KEY.UP, KEY.DOWN, KEY.LEFT, KEY.RIGHT];
155
+ var ENTER_KEY = KEY.ENTER;
156
+
157
+ function addActiveClass($target) {
158
+ if (!$target) {
159
+ return;
160
+ }
161
+ $target.find('button').addClass('active');
162
+ $selectedNode = $target;
163
+ }
164
+
165
+ function removeActiveClass($target) {
166
+ $target.find('button').removeClass('active');
167
+ $selectedNode = null;
168
+ }
169
+
170
+ // find next node
171
+ function findNextNode(row, column) {
172
+ var findNode = null;
173
+ $.each($specialCharNode, function (idx, $node) {
174
+ var findRow = Math.ceil((idx + 1) / COLUMN_LENGTH);
175
+ var findColumn = ((idx + 1) % COLUMN_LENGTH === 0) ? COLUMN_LENGTH : (idx + 1) % COLUMN_LENGTH;
176
+ if (findRow === row && findColumn === column) {
177
+ findNode = $node;
178
+ return false;
179
+ }
180
+ });
181
+ return $(findNode);
182
+ }
183
+
184
+ function arrowKeyHandler(keyCode) {
185
+ // left, right, up, down key
186
+ var $nextNode;
187
+ var lastRowColumnLength = $specialCharNode.length % totalColumn;
188
+
189
+ if (KEY.LEFT === keyCode) {
190
+
191
+ if (currentColumn > 1) {
192
+ currentColumn = currentColumn - 1;
193
+ } else if (currentRow === 1 && currentColumn === 1) {
194
+ currentColumn = lastRowColumnLength;
195
+ currentRow = totalRow;
196
+ } else {
197
+ currentColumn = totalColumn;
198
+ currentRow = currentRow - 1;
199
+ }
200
+
201
+ } else if (KEY.RIGHT === keyCode) {
202
+
203
+ if (currentRow === totalRow && lastRowColumnLength === currentColumn) {
204
+ currentColumn = 1;
205
+ currentRow = 1;
206
+ } else if (currentColumn < totalColumn) {
207
+ currentColumn = currentColumn + 1;
208
+ } else {
209
+ currentColumn = 1;
210
+ currentRow = currentRow + 1;
211
+ }
212
+
213
+ } else if (KEY.UP === keyCode) {
214
+ if (currentRow === 1 && lastRowColumnLength < currentColumn) {
215
+ currentRow = totalRow - 1;
216
+ } else {
217
+ currentRow = currentRow - 1;
218
+ }
219
+ } else if (KEY.DOWN === keyCode) {
220
+ currentRow = currentRow + 1;
221
+ }
222
+
223
+ if (currentRow === totalRow && currentColumn > lastRowColumnLength) {
224
+ currentRow = 1;
225
+ } else if (currentRow > totalRow) {
226
+ currentRow = 1;
227
+ } else if (currentRow < 1) {
228
+ currentRow = totalRow;
229
+ }
230
+
231
+ $nextNode = findNextNode(currentRow, currentColumn);
232
+
233
+ if ($nextNode) {
234
+ removeActiveClass($selectedNode);
235
+ addActiveClass($nextNode);
236
+ }
237
+ }
238
+
239
+ function enterKeyHandler() {
240
+ if (!$selectedNode) {
241
+ return;
242
+ }
243
+
244
+ deferred.resolve(decodeURIComponent($selectedNode.find('button').attr('data-value')));
245
+ $specialCharDialog.modal('hide');
246
+ }
247
+
248
+ function keyDownEventHandler(event) {
249
+ event.preventDefault();
250
+ var keyCode = event.keyCode;
251
+ if (keyCode === undefined || keyCode === null) {
252
+ return;
253
+ }
254
+ // check arrowKeys match
255
+ if (ARROW_KEYS.indexOf(keyCode) > -1) {
256
+ if ($selectedNode === null) {
257
+ addActiveClass($specialCharNode.eq(0));
258
+ currentColumn = 1;
259
+ currentRow = 1;
260
+ return;
261
+ }
262
+ arrowKeyHandler(keyCode);
263
+ } else if (keyCode === ENTER_KEY) {
264
+ enterKeyHandler();
265
+ }
266
+ return false;
267
+ }
268
+
269
+ // remove class
270
+ removeActiveClass($specialCharNode);
271
+
272
+ // find selected node
273
+ if (text) {
274
+ for (var i = 0; i < $specialCharNode.length; i++) {
275
+ var $checkNode = $($specialCharNode[i]);
276
+ if ($checkNode.text() === text) {
277
+ addActiveClass($checkNode);
278
+ currentRow = Math.ceil((i + 1) / COLUMN_LENGTH);
279
+ currentColumn = (i + 1) % COLUMN_LENGTH;
280
+ }
281
+ }
282
+ }
283
+
284
+ ui.onDialogShown(self.$dialog, function () {
285
+
286
+ $(document).on('keydown', keyDownEventHandler);
287
+
288
+ self.$dialog.find('button').tooltip();
289
+
290
+ $specialCharNode.on('click', function (event) {
291
+ event.preventDefault();
292
+ deferred.resolve(decodeURIComponent($(event.currentTarget).find('button').attr('data-value')));
293
+ ui.hideDialog(self.$dialog);
294
+ });
295
+
296
+ });
297
+
298
+ ui.onDialogHidden(self.$dialog, function () {
299
+ $specialCharNode.off('click');
300
+
301
+ self.$dialog.find('button').tooltip('destroy');
302
+
303
+ $(document).off('keydown', keyDownEventHandler);
304
+
305
+ if (deferred.state() === 'pending') {
306
+ deferred.reject();
307
+ }
308
+ });
309
+
310
+ ui.showDialog(self.$dialog);
311
+ });
312
+ };
313
+ }
314
+ });
315
+ }));