summernote-rails 0.6.16.0 → 0.7.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -8
  3. data/lib/summernote-rails/version.rb +1 -1
  4. data/vendor/assets/javascripts/summernote/locales/ar-AR.js +7 -0
  5. data/vendor/assets/javascripts/summernote/locales/ca-ES.js +59 -7
  6. data/vendor/assets/javascripts/summernote/locales/cs-CZ.js +7 -0
  7. data/vendor/assets/javascripts/summernote/locales/da-DK.js +7 -0
  8. data/vendor/assets/javascripts/summernote/locales/de-DE.js +7 -0
  9. data/vendor/assets/javascripts/summernote/locales/es-ES.js +53 -4
  10. data/vendor/assets/javascripts/summernote/locales/es-EU.js +7 -0
  11. data/vendor/assets/javascripts/summernote/locales/fa-IR.js +7 -0
  12. data/vendor/assets/javascripts/summernote/locales/fi-FI.js +7 -0
  13. data/vendor/assets/javascripts/summernote/locales/fr-FR.js +7 -0
  14. data/vendor/assets/javascripts/summernote/locales/he-IL.js +7 -0
  15. data/vendor/assets/javascripts/summernote/locales/hu-HU.js +7 -0
  16. data/vendor/assets/javascripts/summernote/locales/id-ID.js +7 -0
  17. data/vendor/assets/javascripts/summernote/locales/it-IT.js +7 -0
  18. data/vendor/assets/javascripts/summernote/locales/ja-JP.js +7 -0
  19. data/vendor/assets/javascripts/summernote/locales/ko-KR.js +14 -2
  20. data/vendor/assets/javascripts/summernote/locales/nb-NO.js +7 -0
  21. data/vendor/assets/javascripts/summernote/locales/nl-NL.js +7 -0
  22. data/vendor/assets/javascripts/summernote/locales/pl-PL.js +7 -0
  23. data/vendor/assets/javascripts/summernote/locales/pt-BR.js +7 -0
  24. data/vendor/assets/javascripts/summernote/locales/ro-RO.js +7 -0
  25. data/vendor/assets/javascripts/summernote/locales/ru-RU.js +12 -0
  26. data/vendor/assets/javascripts/summernote/locales/sk-SK.js +7 -0
  27. data/vendor/assets/javascripts/summernote/locales/sl-SI.js +7 -0
  28. data/vendor/assets/javascripts/summernote/locales/sr-RS-Latin.js +7 -0
  29. data/vendor/assets/javascripts/summernote/locales/sr-RS.js +7 -0
  30. data/vendor/assets/javascripts/summernote/locales/sv-SE.js +7 -0
  31. data/vendor/assets/javascripts/summernote/locales/th-TH.js +11 -4
  32. data/vendor/assets/javascripts/summernote/locales/tr-TR.js +7 -0
  33. data/vendor/assets/javascripts/summernote/locales/uk-UA.js +12 -0
  34. data/vendor/assets/javascripts/summernote/locales/vi-VN.js +7 -0
  35. data/vendor/assets/javascripts/summernote/locales/zh-CN.js +7 -0
  36. data/vendor/assets/javascripts/summernote/locales/zh-TW.js +7 -0
  37. data/vendor/assets/javascripts/summernote/plugin/hello/summernote-ext-hello.js +82 -0
  38. data/vendor/assets/javascripts/summernote/plugin/specialchars/summernote-ext-specialchars.js +316 -0
  39. data/vendor/assets/javascripts/summernote/summernote.js +3354 -3813
  40. data/vendor/assets/stylesheets/summernote.css +1 -1
  41. metadata +4 -5
  42. data/vendor/assets/javascripts/summernote/plugin/summernote-ext-hello.js +0 -89
  43. data/vendor/assets/javascripts/summernote/plugin/summernote-ext-hint.js +0 -270
  44. data/vendor/assets/javascripts/summernote/plugin/summernote-ext-video.js +0 -573
@@ -25,6 +25,13 @@
25
25
  url: 'Bilde-URL',
26
26
  remove: 'Fjern bilde'
27
27
  },
28
+ video: {
29
+ video: 'Video',
30
+ videoLink: 'Videolenke',
31
+ insert: 'Sett inn video',
32
+ url: 'Video-URL',
33
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion eller Youku)'
34
+ },
28
35
  link: {
29
36
  link: 'Lenke',
30
37
  insert: 'Sett inn lenke',
@@ -25,6 +25,13 @@
25
25
  url: 'URL van de afbeelding',
26
26
  remove: 'Verwijder afbeelding'
27
27
  },
28
+ video: {
29
+ video: 'Video',
30
+ videoLink: 'Video link',
31
+ insert: 'Video invoegen',
32
+ url: 'URL van de video',
33
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion of Youku)'
34
+ },
28
35
  link: {
29
36
  link: 'Link',
30
37
  insert: 'Link invoegen',
@@ -32,6 +32,13 @@
32
32
  url: 'Adres URL grafiki',
33
33
  remove: 'Usuń grafikę'
34
34
  },
35
+ video: {
36
+ video: 'Wideo',
37
+ videoLink: 'Adres wideo',
38
+ insert: 'Wstaw wideo',
39
+ url: 'Adres wideo',
40
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, lub Youku)'
41
+ },
35
42
  link: {
36
43
  link: 'Odnośnik',
37
44
  insert: 'Wstaw odnośnik',
@@ -24,6 +24,13 @@
24
24
  selectFromFiles: 'Selecione a partir dos arquivos',
25
25
  url: 'URL da image'
26
26
  },
27
+ video: {
28
+ video: 'Vídeo',
29
+ videoLink: 'Link para vídeo',
30
+ insert: 'Inserir vídeo',
31
+ url: 'URL do vídeo?',
32
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, ou Youku)'
33
+ },
27
34
  link: {
28
35
  link: 'Link',
29
36
  insert: 'Inserir link',
@@ -23,6 +23,13 @@
23
23
  selectFromFiles: 'Alege din fişiere',
24
24
  url: 'URL imagine'
25
25
  },
26
+ video: {
27
+ video: 'Video',
28
+ videoLink: 'Link video',
29
+ insert: 'Inserează video',
30
+ url: 'URL video?',
31
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, sau Youku)'
32
+ },
26
33
  link: {
27
34
  link: 'Link',
28
35
  insert: 'Inserează link',
@@ -22,11 +22,23 @@
22
22
  floatLeft: 'Расположить слева',
23
23
  floatRight: 'Расположить справа',
24
24
  floatNone: 'Расположение по-умолчанию',
25
+ shapeRounded: 'Форма: Закругленная',
26
+ shapeCircle: 'Форма: Круг',
27
+ shapeThumbnail: 'Форма: Миниатюра',
28
+ shapeNone: 'Форма: Нет',
25
29
  dragImageHere: 'Перетащите сюда картинку',
30
+ dropImage: 'Перетащите картинку',
26
31
  selectFromFiles: 'Выбрать из файлов',
27
32
  url: 'URL картинки',
28
33
  remove: 'Удалить картинку'
29
34
  },
35
+ video: {
36
+ video: 'Видео',
37
+ videoLink: 'Ссылка на видео',
38
+ insert: 'Вставить видео',
39
+ url: 'URL видео',
40
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion или Youku)'
41
+ },
30
42
  link: {
31
43
  link: 'Ссылка',
32
44
  insert: 'Вставить ссылку',
@@ -23,6 +23,13 @@
23
23
  selectFromFiles: 'Vybrať súbor',
24
24
  url: 'URL obrázku'
25
25
  },
26
+ video: {
27
+ video: 'Video',
28
+ videoLink: 'Odkaz videa',
29
+ insert: 'Vložiť video',
30
+ url: 'URL videa?',
31
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion nebo Youku)'
32
+ },
26
33
  link: {
27
34
  link: 'Odkaz',
28
35
  insert: 'Vytvoriť odkaz',
@@ -27,6 +27,13 @@
27
27
  url: 'URL naslov slike',
28
28
  remove: 'Odstrani sliko'
29
29
  },
30
+ video: {
31
+ video: 'Video',
32
+ videoLink: 'Video povezava',
33
+ insert: 'Vstavi video',
34
+ url: 'Povezava do videa',
35
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion ali Youku)'
36
+ },
30
37
  link: {
31
38
  link: 'Povezava',
32
39
  insert: 'Vstavi povezavo',
@@ -24,6 +24,13 @@
24
24
  url: 'Adresa slike',
25
25
  remove: 'Ukloni sliku'
26
26
  },
27
+ video: {
28
+ video: 'Video',
29
+ videoLink: 'Veza ka videu',
30
+ insert: 'Umetni video',
31
+ url: 'URL video',
32
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion ili Youku)'
33
+ },
27
34
  link: {
28
35
  link: 'Veza',
29
36
  insert: 'Umetni vezu',
@@ -24,6 +24,13 @@
24
24
  url: 'Адреса слике',
25
25
  remove: 'Уклони слику'
26
26
  },
27
+ video: {
28
+ video: 'Видео',
29
+ videoLink: 'Веза ка видеу',
30
+ insert: 'Уметни видео',
31
+ url: 'URL видео',
32
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion или Youku)'
33
+ },
27
34
  link: {
28
35
  link: 'Веза',
29
36
  insert: 'Уметни везу',
@@ -25,6 +25,13 @@
25
25
  url: 'Länk till bild',
26
26
  remove: 'Ta bort bild'
27
27
  },
28
+ video: {
29
+ video: 'Filmklipp',
30
+ videoLink: 'Länk till filmklipp',
31
+ insert: 'Infoga filmklipp',
32
+ url: 'Länk till filmklipp',
33
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion eller Youku)'
34
+ },
28
35
  link: {
29
36
  link: 'Länk',
30
37
  insert: 'Infoga länk',
@@ -8,10 +8,10 @@
8
8
  clear: 'ล้างรูปแบบตัวอักษร',
9
9
  height: 'ความสูงบรรทัด',
10
10
  name: 'แบบตัวอักษร',
11
- strikethrough: 'ขีดฆ่า',
12
- subscript: 'ตัวห้อย',
13
- superscript: 'ตัวยก',
14
- size: 'ขนาดตัวอักษร'
11
+ strikethrough: 'ขีดฆ่า',
12
+ subscript: 'ตัวห้อย',
13
+ superscript: 'ตัวยก',
14
+ size: 'ขนาดตัวอักษร'
15
15
  },
16
16
  image: {
17
17
  image: 'รูปภาพ',
@@ -27,6 +27,13 @@
27
27
  url: 'ที่อยู่ URL ของรูปภาพ',
28
28
  remove: 'ลบรูปภาพ'
29
29
  },
30
+ video: {
31
+ video: 'วีดีโอ',
32
+ videoLink: 'ลิงก์ของวีดีโอ',
33
+ insert: 'แทรกวีดีโอ',
34
+ url: 'ที่อยู่ URL ของวีดีโอ?',
35
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion หรือ Youku)'
36
+ },
30
37
  link: {
31
38
  link: 'ตัวเชื่อมโยง',
32
39
  insert: 'แทรกตัวเชื่อมโยง',
@@ -31,6 +31,13 @@
31
31
  url: 'Resim bağlantısı',
32
32
  remove: 'Resimi Kaldır'
33
33
  },
34
+ video: {
35
+ video: 'Video',
36
+ videoLink: 'Video bağlantısı',
37
+ insert: 'Video ekle',
38
+ url: 'Video bağlantısı?',
39
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion veya Youku)'
40
+ },
34
41
  link: {
35
42
  link: 'Bağlantı',
36
43
  insert: 'Bağlantı ekle',
@@ -22,11 +22,23 @@
22
22
  floatLeft: 'Розташувати ліворуч',
23
23
  floatRight: 'Розташувати праворуч',
24
24
  floatNone: 'Початкове розташування',
25
+ shapeRounded: 'Форма: Заокруглена',
26
+ shapeCircle: 'Форма: Коло',
27
+ shapeThumbnail: 'Форма: Мініатюра',
28
+ shapeNone: 'Форма: Немає',
25
29
  dragImageHere: 'Перетягніть сюди картинку',
30
+ dropImage: 'Перетягніть картинку',
26
31
  selectFromFiles: 'Вибрати з файлів',
27
32
  url: 'URL картинки',
28
33
  remove: 'Видалити картинку'
29
34
  },
35
+ video: {
36
+ video: 'Відео',
37
+ videoLink: 'Посилання на відео',
38
+ insert: 'Вставити відео',
39
+ url: 'URL відео',
40
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion чи Youku)'
41
+ },
30
42
  link: {
31
43
  link: 'Посилання',
32
44
  insert: 'Вставити посилання',
@@ -25,6 +25,13 @@
25
25
  url: 'URL',
26
26
  remove: 'Ghỡ Bỏ'
27
27
  },
28
+ video: {
29
+ video: 'Video',
30
+ videoLink: 'Đường Dẫn đến Video',
31
+ insert: 'Chèn Video',
32
+ url: 'URL',
33
+ providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion và Youku)'
34
+ },
28
35
  link: {
29
36
  link: 'Đường Dẫn',
30
37
  insert: 'Chèn Đường Dẫn',
@@ -33,6 +33,13 @@
33
33
  url: '图片地址',
34
34
  remove: '移除图片'
35
35
  },
36
+ video: {
37
+ video: '视频',
38
+ videoLink: '视频链接',
39
+ insert: '插入视频',
40
+ url: '视频地址',
41
+ providers: '(优酷, Instagram, DailyMotion, Youtube等)'
42
+ },
36
43
  link: {
37
44
  link: '链接',
38
45
  insert: '插入链接',
@@ -33,6 +33,13 @@
33
33
  url: '圖片網址',
34
34
  remove: '移除圖片'
35
35
  },
36
+ video: {
37
+ video: '影片',
38
+ videoLink: '影片連結',
39
+ insert: '插入影片',
40
+ url: '影片網址',
41
+ providers: '(優酷, Instagram, DailyMotion, Youtube等)'
42
+ },
36
43
  link: {
37
44
  link: '連結',
38
45
  insert: '插入連結',
@@ -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,316 @@
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').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').data('value')));
293
+ ui.hideDialog(self.$dialog);
294
+ });
295
+
296
+
297
+ });
298
+
299
+ ui.onDialogHidden(self.$dialog, function () {
300
+ $specialCharNode.off('click');
301
+
302
+ self.$dialog.find('button').tooltip('destroy');
303
+
304
+ $(document).off('keydown', keyDownEventHandler);
305
+
306
+ if (deferred.state() === 'pending') {
307
+ deferred.reject();
308
+ }
309
+ });
310
+
311
+ ui.showDialog(self.$dialog);
312
+ });
313
+ };
314
+ }
315
+ });
316
+ }));