summernote-rails 0.6.10.0 → 0.6.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d45118cd2c6daef234a3b91115d357913e0d586e
4
- data.tar.gz: 8784f964bfed64720568d152cda3a49945f8e4ee
3
+ metadata.gz: 1f980d45866bbcf650bb0b08d938d53d25bbea16
4
+ data.tar.gz: 3026217d30c1fed40150e6c72f34f2a47f2c03eb
5
5
  SHA512:
6
- metadata.gz: 41334e91c1d3d7fa593ac98013c465e782ade847ebb2468b8fdee19dac878432433c6177b800c7bde754836fa76e8b94dd462f256a4f2d20e7a7e20c57478d40
7
- data.tar.gz: af11b642c2fe451e5942ecb2a7ab9ecabc0e0161596b77b137b95bcbd10dc26323dc60fd821393f470019daa38023c8d4eecd40e558b1511df7bad667c046d04
6
+ metadata.gz: 02d890be63fbcc32719d9cd8393f55c339bfab7b9e2df3475896b378678594834ef59b931cda1b350e31953f31f0c58d996e48eaad62bea3e0fb30f155d87cdf
7
+ data.tar.gz: bd0080560c3e877f668948e14f703dd35335e4bc73d3a70b2d90ef6c9a267558e5fb023c15ad83e1d9698ae8970d93e5c0886223cf39a5ff3366f19ad767e17a
@@ -1,5 +1,5 @@
1
1
  module SummernoteRails
2
2
  module Rails
3
- VERSION = "0.6.10.0"
3
+ VERSION = "0.6.16.0"
4
4
  end
5
5
  end
@@ -19,8 +19,14 @@
19
19
  floatLeft: 'Linksbündig',
20
20
  floatRight: 'Rechtsbündig',
21
21
  floatNone: 'Kein Textfluss',
22
+ shapeRounded: 'Rahmen: Abgerundet',
23
+ shapeCircle: 'Rahmen: Kreisförmig',
24
+ shapeThumbnail: 'Rahmen: Thumbnail',
25
+ shapeNone: 'Kein Rahmen',
22
26
  dragImageHere: 'Ziehen Sie ein Bild mit der Maus hierher',
23
27
  selectFromFiles: 'Wählen Sie eine Datei aus',
28
+ maximumFileSize: 'Maximale Dateigröße',
29
+ maximumFileSizeError: 'Maximale Dateigröße überschritten',
24
30
  url: 'Grafik URL',
25
31
  remove: 'Grafik entfernen'
26
32
  },
@@ -0,0 +1,107 @@
1
+ (function ($) {
2
+ $.extend($.summernote.lang, {
3
+ 'lt-LT': {
4
+ font: {
5
+ bold: 'Paryškintas',
6
+ italic: 'Kursyvas',
7
+ underline: 'Pabrėžtas',
8
+ clear: 'Be formatavimo',
9
+ height: 'Eilutės aukštis',
10
+ name: 'Šrifto pavadinimas',
11
+ strikethrough: 'Perbrauktas',
12
+ superscript: 'Viršutinis',
13
+ subscript: 'Indeksas',
14
+ size: 'Šrifto dydis'
15
+ },
16
+ image: {
17
+ image: 'Paveikslėlis',
18
+ insert: 'Įterpti paveikslėlį',
19
+ resizeFull: 'Pilnas dydis',
20
+ resizeHalf: 'Sumažinti dydį 50%',
21
+ resizeQuarter: 'Sumažinti dydį 25%',
22
+ floatLeft: 'Kairinis lygiavimas',
23
+ floatRight: 'Dešininis lygiavimas',
24
+ floatNone: 'Jokio lygiavimo',
25
+ shapeRounded: 'Forma: apvalūs kraštai',
26
+ shapeCircle: 'Forma: apskritimas',
27
+ shapeThumbnail: 'Forma: miniatiūra',
28
+ shapeNone: 'Forma: jokia',
29
+ dragImageHere: 'Vilkite paveikslėlį čia',
30
+ selectFromFiles: 'Pasirinkite failą',
31
+ maximumFileSize: 'Maskimalus failo dydis',
32
+ maximumFileSizeError: 'Maskimalus failo dydis viršytas!',
33
+ url: 'Paveikslėlio URL adresas',
34
+ remove: 'Ištrinti paveikslėlį'
35
+ },
36
+ link: {
37
+ link: 'Nuoroda',
38
+ insert: 'Įterpti nuorodą',
39
+ unlink: 'Pašalinti nuorodą',
40
+ edit: 'Redaguoti',
41
+ textToDisplay: 'Rodomas tekstas',
42
+ url: 'Koks URL adresas yra susietas?',
43
+ openInNewWindow: 'Atidaryti naujame lange'
44
+ },
45
+ table: {
46
+ table: 'Lentelė'
47
+ },
48
+ hr: {
49
+ insert: 'Įterpti horizontalią liniją'
50
+ },
51
+ style: {
52
+ style: 'Stilius',
53
+ normal: 'Normalus',
54
+ blockquote: 'Citata',
55
+ pre: 'Kodas',
56
+ h1: 'Antraštė 1',
57
+ h2: 'Antraštė 2',
58
+ h3: 'Antraštė 3',
59
+ h4: 'Antraštė 4',
60
+ h5: 'Antraštė 5',
61
+ h6: 'Antraštė 6'
62
+ },
63
+ lists: {
64
+ unordered: 'Suženklintasis sąrašas',
65
+ ordered: 'Sunumeruotas sąrašas'
66
+ },
67
+ options: {
68
+ help: 'Pagalba',
69
+ fullscreen: 'Viso ekrano režimas',
70
+ codeview: 'HTML kodo peržiūra'
71
+ },
72
+ paragraph: {
73
+ paragraph: 'Pastraipa',
74
+ outdent: 'Sumažinti įtrauką',
75
+ indent: 'Padidinti įtrauką',
76
+ left: 'Kairinė lygiuotė',
77
+ center: 'Centrinė lygiuotė',
78
+ right: 'Dešininė lygiuotė',
79
+ justify: 'Abipusis išlyginimas'
80
+ },
81
+ color: {
82
+ recent: 'Paskutinė naudota spalva',
83
+ more: 'Daugiau spalvų',
84
+ background: 'Fono spalva',
85
+ foreground: 'Šrifto spalva',
86
+ transparent: 'Permatoma',
87
+ setTransparent: 'Nustatyti skaidrumo intensyvumą',
88
+ reset: 'Atkurti',
89
+ resetToDefault: 'Atstatyti numatytąją spalvą'
90
+ },
91
+ shortcut: {
92
+ shortcuts: 'Spartieji klavišai',
93
+ close: 'Uždaryti',
94
+ textFormatting: 'Teksto formatavimas',
95
+ action: 'Veiksmas',
96
+ paragraphFormatting: 'Pastraipos formatavimas',
97
+ documentStyle: 'Dokumento stilius',
98
+ extraKeys: 'Papildomi klavišų deriniai'
99
+ },
100
+ history: {
101
+ undo: 'Anuliuoti veiksmą',
102
+ redo: 'Perdaryti veiksmą'
103
+ }
104
+
105
+ }
106
+ });
107
+ })(jQuery);
@@ -9,20 +9,29 @@
9
9
  height: '行高',
10
10
  name: '字体',
11
11
  strikethrough: '删除线',
12
+ subscript: '下标',
13
+ superscript: '上标',
12
14
  size: '字号'
13
15
  },
14
16
  image: {
15
17
  image: '图片',
16
18
  insert: '插入图片',
17
- resizeFull: '调整至 100%',
18
- resizeHalf: '调整至 50%',
19
- resizeQuarter: '调整至 25%',
20
- floatLeft: '左浮动',
21
- floatRight: '右浮动',
22
- floatNone: '不浮动',
23
- dragImageHere: '将图片拖至此处',
19
+ resizeFull: '缩放至 100%',
20
+ resizeHalf: '缩放至 50%',
21
+ resizeQuarter: '缩放至 25%',
22
+ floatLeft: '靠左浮动',
23
+ floatRight: '靠右浮动',
24
+ floatNone: '取消浮动',
25
+ shapeRounded: '形状: 圆角',
26
+ shapeCircle: '形状: 圆',
27
+ shapeThumbnail: '形状: 缩略图',
28
+ shapeNone: '形状: 无',
29
+ dragImageHere: '将图片拖拽至此处',
24
30
  selectFromFiles: '从本地上传',
25
- url: '图片地址'
31
+ maximumFileSize: '文件大小最大值',
32
+ maximumFileSizeError: '文件大小超出最大值。',
33
+ url: '图片地址',
34
+ remove: '移除图片'
26
35
  },
27
36
  link: {
28
37
  link: '链接',
@@ -85,7 +94,8 @@
85
94
  textFormatting: '文本格式',
86
95
  action: '动作',
87
96
  paragraphFormatting: '段落格式',
88
- documentStyle: '文档样式'
97
+ documentStyle: '文档样式',
98
+ extraKeys: '额外按键'
89
99
  },
90
100
  history: {
91
101
  undo: '撤销',
@@ -7,8 +7,11 @@
7
7
  underline: '底線',
8
8
  clear: '清除格式',
9
9
  height: '行高',
10
+ name: '字體',
10
11
  strikethrough: '刪除線',
11
- size: '字體大小'
12
+ subscript: '下標',
13
+ superscript: '上標',
14
+ size: '字號'
12
15
  },
13
16
  image: {
14
17
  image: '圖片',
@@ -19,9 +22,16 @@
19
22
  floatLeft: '靠左浮動',
20
23
  floatRight: '靠右浮動',
21
24
  floatNone: '取消浮動',
25
+ shapeRounded: '形狀: 圓角',
26
+ shapeCircle: '形狀: 圓',
27
+ shapeThumbnail: '形狀: 縮略圖',
28
+ shapeNone: '形狀: 無',
22
29
  dragImageHere: '將圖片拖曳至此處',
23
30
  selectFromFiles: '從本機上傳',
24
- url: '圖片網址'
31
+ maximumFileSize: '文件大小最大值',
32
+ maximumFileSizeError: '文件大小超出最大值。',
33
+ url: '圖片網址',
34
+ remove: '移除圖片'
25
35
  },
26
36
  link: {
27
37
  link: '連結',
@@ -84,7 +94,8 @@
84
94
  textFormatting: '文字格式',
85
95
  action: '動作',
86
96
  paragraphFormatting: '段落格式',
87
- documentStyle: '文件格式'
97
+ documentStyle: '文件格式',
98
+ extraKeys: '額外按鍵'
88
99
  },
89
100
  history: {
90
101
  undo: '復原',
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Super simple wysiwyg editor on Bootstrap v0.6.10
2
+ * Super simple wysiwyg editor on Bootstrap v0.6.16
3
3
  * http://summernote.org/
4
4
  *
5
5
  * summernote.js
6
6
  * Copyright 2013-2015 Alan Hong. and other contributors
7
7
  * summernote may be freely distributed under the MIT license./
8
8
  *
9
- * Date: 2015-07-12T14:23Z
9
+ * Date: 2015-08-03T16:40Z
10
10
  */
11
11
  (function (factory) {
12
12
  /* global define */
@@ -80,6 +80,47 @@
80
80
  };
81
81
  }
82
82
 
83
+ if (!Array.prototype.map) {
84
+ /**
85
+ * Array.prototype.map polyfill
86
+ *
87
+ * @param {Function} callback
88
+ * @return {Array}
89
+ *
90
+ * @see https://goo.gl/SMWaMK
91
+ */
92
+ Array.prototype.map = function (callback, thisArg) {
93
+ var T, A, k;
94
+ if (this === null) {
95
+ throw new TypeError(' this is null or not defined');
96
+ }
97
+
98
+ var O = Object(this);
99
+ var len = O.length >>> 0;
100
+ if (typeof callback !== 'function') {
101
+ throw new TypeError(callback + ' is not a function');
102
+ }
103
+
104
+ if (arguments.length > 1) {
105
+ T = thisArg;
106
+ }
107
+
108
+ A = new Array(len);
109
+ k = 0;
110
+
111
+ while (k < len) {
112
+ var kValue, mappedValue;
113
+ if (k in O) {
114
+ kValue = O[k];
115
+ mappedValue = callback.call(T, kValue, k, O);
116
+ A[k] = mappedValue;
117
+ }
118
+ k++;
119
+ }
120
+ return A;
121
+ };
122
+ }
123
+
83
124
  var isSupportAmd = typeof define === 'function' && define.amd;
84
125
 
85
126
  /**
@@ -106,6 +147,18 @@
106
147
  };
107
148
 
108
149
  var userAgent = navigator.userAgent;
150
+ var isMSIE = /MSIE|Trident/i.test(userAgent);
151
+ var browserVersion;
152
+ if (isMSIE) {
153
+ var matches = /MSIE (\d+[.]\d+)/.exec(userAgent);
154
+ if (matches) {
155
+ browserVersion = parseFloat(matches[1]);
156
+ }
157
+ matches = /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(userAgent);
158
+ if (matches) {
159
+ browserVersion = parseFloat(matches[1]);
160
+ }
161
+ }
109
162
 
110
163
  /**
111
164
  * @class core.agent
@@ -119,12 +172,14 @@
119
172
  /** @property {Boolean} [isMac=false] true if this agent is Mac */
120
173
  isMac: navigator.appVersion.indexOf('Mac') > -1,
121
174
  /** @property {Boolean} [isMSIE=false] true if this agent is a Internet Explorer */
122
- isMSIE: /MSIE|Trident/i.test(userAgent),
175
+ isMSIE: isMSIE,
123
176
  /** @property {Boolean} [isFF=false] true if this agent is a Firefox */
124
177
  isFF: /firefox/i.test(userAgent),
125
178
  isWebkit: /webkit/i.test(userAgent),
126
179
  /** @property {Boolean} [isSafari=false] true if this agent is a Safari */
127
180
  isSafari: /safari/i.test(userAgent),
181
+ /** @property {Float} browserVersion current browser version */
182
+ browserVersion: browserVersion,
128
183
  /** @property {String} jqueryVersion current jQuery version string */
129
184
  jqueryVersion: parseFloat($.fn.jquery),
130
185
  isSupportAmd: isSupportAmd,
@@ -329,11 +384,18 @@
329
384
  return true;
330
385
  };
331
386
 
387
+ /**
388
+ * returns index of item
389
+ */
390
+ var indexOf = function (array, item) {
391
+ return $.inArray(item, array);
392
+ };
393
+
332
394
  /**
333
395
  * returns true if the value is present in the list.
334
396
  */
335
397
  var contains = function (array, item) {
336
- return $.inArray(item, array) !== -1;
398
+ return indexOf(array, item) !== -1;
337
399
  };
338
400
 
339
401
  /**
@@ -418,7 +480,7 @@
418
480
  * @param {Array} array
419
481
  */
420
482
  var next = function (array, item) {
421
- var idx = array.indexOf(item);
483
+ var idx = indexOf(array, item);
422
484
  if (idx === -1) { return null; }
423
485
 
424
486
  return array[idx + 1];
@@ -429,12 +491,11 @@
429
491
  * @param {Array} array
430
492
  */
431
493
  var prev = function (array, item) {
432
- var idx = array.indexOf(item);
494
+ var idx = indexOf(array, item);
433
495
  if (idx === -1) { return null; }
434
496
 
435
497
  return array[idx - 1];
436
498
  };
437
-
438
499
 
439
500
  return { head: head, last: last, initial: initial, tail: tail,
440
501
  prev: prev, next: next, find: find, contains: contains,
@@ -516,13 +577,13 @@
516
577
 
517
578
  // frame mode
518
579
  } else {
519
- makeFinder = function (sClassName, sBaseElement) {
520
- var $baseElement = sBaseElement ? $(sBaseElement) : $editor;
521
- return function () { return $baseElement.find(sClassName); };
580
+ makeFinder = function (className, $base) {
581
+ $base = $base || $editor;
582
+ return function () { return $base.find(className); };
522
583
  };
523
584
 
524
585
  var options = $editor.data('options');
525
- var dialogHolder = (options && options.dialogsInBody) ? document.body : null;
586
+ var $dialogHolder = (options && options.dialogsInBody) ? $(document.body) : null;
526
587
 
527
588
  return {
528
589
  editor: function () { return $editor; },
@@ -534,7 +595,7 @@
534
595
  statusbar: makeFinder('.note-statusbar'),
535
596
  popover: makeFinder('.note-popover'),
536
597
  handle: makeFinder('.note-handle'),
537
- dialog: makeFinder('.note-dialog', dialogHolder)
598
+ dialog: makeFinder('.note-dialog', $dialogHolder)
538
599
  };
539
600
  }
540
601
  };
@@ -595,7 +656,7 @@
595
656
  * @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
596
657
  */
597
658
  var isVoid = function (node) {
598
- return node && /^BR|^IMG|^HR/.test(node.nodeName.toUpperCase());
659
+ return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON/.test(node.nodeName.toUpperCase());
599
660
  };
600
661
 
601
662
  var isPara = function (node) {
@@ -618,6 +679,7 @@
618
679
  var isInline = function (node) {
619
680
  return !isBodyContainer(node) &&
620
681
  !isList(node) &&
682
+ !isHr(node) &&
621
683
  !isPara(node) &&
622
684
  !isTable(node) &&
623
685
  !isBlockquote(node);
@@ -627,6 +689,8 @@
627
689
  return node && /^UL|^OL/.test(node.nodeName.toUpperCase());
628
690
  };
629
691
 
692
+ var isHr = makePredByNodeName('HR');
693
+
630
694
  var isCell = function (node) {
631
695
  return node && /^TD|^TH/.test(node.nodeName.toUpperCase());
632
696
  };
@@ -684,9 +748,10 @@
684
748
 
685
749
  /**
686
750
  * blank HTML for cursor position
687
- * - [workaround] for MSIE IE doesn't works with bogus br
751
+ * - [workaround] old IE only works with &nbsp;
752
+ * - [workaround] IE11 and other browser works with bogus br
688
753
  */
689
- var blankHTML = agent.isMSIE ? '&nbsp;' : '<br>';
754
+ var blankHTML = agent.isMSIE && agent.browserVersion < 11 ? '&nbsp;' : '<br>';
690
755
 
691
756
  /**
692
757
  * @method nodeLength
@@ -1200,7 +1265,7 @@
1200
1265
  */
1201
1266
  var makeOffsetPath = function (ancestor, node) {
1202
1267
  var ancestors = listAncestor(node, func.eq(ancestor));
1203
- return $.map(ancestors, position).reverse();
1268
+ return ancestors.map(position).reverse();
1204
1269
  };
1205
1270
 
1206
1271
  /**
@@ -1750,8 +1815,8 @@
1750
1815
 
1751
1816
  // point on block's edge
1752
1817
  var block = dom.ancestor(point.node, dom.isBlock);
1753
- if ((dom.isLeftEdgePointOf(point, block) && !isLeftToRight) ||
1754
- (dom.isRightEdgePointOf(point, block) && isLeftToRight)) {
1818
+ if (((dom.isLeftEdgePointOf(point, block) || dom.isVoid(dom.prevPoint(point).node)) && !isLeftToRight) ||
1819
+ ((dom.isRightEdgePointOf(point, block) || dom.isVoid(dom.nextPoint(point).node)) && isLeftToRight)) {
1755
1820
 
1756
1821
  // returns point already on visible point
1757
1822
  if (dom.isVisiblePoint(point)) {
@@ -2059,14 +2124,13 @@
2059
2124
  * insert html at current cursor
2060
2125
  */
2061
2126
  this.pasteHTML = function (markup) {
2062
- var self = this;
2063
2127
  var contentsContainer = $('<div></div>').html(markup)[0];
2064
2128
  var childNodes = list.from(contentsContainer.childNodes);
2065
2129
 
2066
- this.wrapBodyInlineWithPara().deleteContents();
2130
+ var rng = this.wrapBodyInlineWithPara().deleteContents();
2067
2131
 
2068
- return $.map(childNodes.reverse(), function (childNode) {
2069
- return self.insertNode(childNode);
2132
+ return childNodes.reverse().map(function (childNode) {
2133
+ return rng.insertNode(childNode);
2070
2134
  }).reverse();
2071
2135
  };
2072
2136
 
@@ -2320,7 +2384,7 @@
2320
2384
  */
2321
2385
  var defaults = {
2322
2386
  /** @property */
2323
- version: '0.6.10',
2387
+ version: '0.6.16',
2324
2388
 
2325
2389
  /**
2326
2390
  *
@@ -2361,9 +2425,12 @@
2361
2425
  disableLinkTarget: false, // hide link Target Checkbox
2362
2426
  disableDragAndDrop: false, // disable drag and drop event
2363
2427
  disableResizeEditor: false, // disable resizing editor
2428
+ disableResizeImage: false, // disable resizing image
2364
2429
 
2365
2430
  shortcuts: true, // enable keyboard shortcuts
2366
2431
 
2432
+ textareaAutoSync: true, // enable textarea auto sync
2433
+
2367
2434
  placeholder: false, // enable placeholder text
2368
2435
  prettifyHtml: true, // enable prettifying html while toggling codeview
2369
2436
 
@@ -2435,6 +2502,8 @@
2435
2502
  }
2436
2503
  },
2437
2504
 
2505
+ dialogsInBody: false, // false will add dialogs into editor
2506
+
2438
2507
  codemirror: { // codemirror options
2439
2508
  mode: 'text/html',
2440
2509
  htmlMode: true,
@@ -2822,6 +2891,7 @@
2822
2891
  'R': 82,
2823
2892
  'S': 83,
2824
2893
  'U': 85,
2894
+ 'V': 86,
2825
2895
  'Y': 89,
2826
2896
  'Z': 90,
2827
2897
 
@@ -2892,6 +2962,11 @@
2892
2962
  * undo
2893
2963
  */
2894
2964
  this.undo = function () {
2965
+ // Create snap shot if not yet recorded
2966
+ if ($editable.html() !== stack[stackOffset].contents) {
2967
+ this.recordUndo();
2968
+ }
2969
+
2895
2970
  if (0 < stackOffset) {
2896
2971
  stackOffset--;
2897
2972
  applySnapshot(stack[stackOffset]);
@@ -2958,6 +3033,19 @@
2958
3033
  return $obj.css.call($obj, propertyNames);
2959
3034
  };
2960
3035
 
3036
+ /**
3037
+ * returns style object from node
3038
+ *
3039
+ * @param {jQuery} $node
3040
+ * @return {Object}
3041
+ */
3042
+ this.fromNode = function ($node) {
3043
+ var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height'];
3044
+ var styleInfo = jQueryCSS($node, properties) || {};
3045
+ styleInfo['font-size'] = parseInt(styleInfo['font-size'], 10);
3046
+ return styleInfo;
3047
+ };
3048
+
2961
3049
  /**
2962
3050
  * paragraph level style
2963
3051
  *
@@ -2994,9 +3082,9 @@
2994
3082
  }
2995
3083
 
2996
3084
  var pred = dom.makePredByNodeName(nodeName);
2997
- var nodes = $.map(rng.nodes(dom.isText, {
3085
+ var nodes = rng.nodes(dom.isText, {
2998
3086
  fullyContains: true
2999
- }), function (text) {
3087
+ }).map(function (text) {
3000
3088
  return dom.singleChildAncestor(text, pred) || dom.wrap(text, nodeName);
3001
3089
  });
3002
3090
 
@@ -3009,7 +3097,7 @@
3009
3097
  });
3010
3098
  }
3011
3099
 
3012
- return $.map(nodes, function (node) {
3100
+ return nodes.map(function (node) {
3013
3101
  var siblings = dom.withClosestSiblings(node, pred);
3014
3102
  var head = list.head(siblings);
3015
3103
  var tails = list.tail(siblings);
@@ -3028,15 +3116,11 @@
3028
3116
  * get current style on cursor
3029
3117
  *
3030
3118
  * @param {WrappedRange} rng
3031
- * @param {Node} target - target element on event
3032
3119
  * @return {Object} - object contains style properties.
3033
3120
  */
3034
- this.current = function (rng, target) {
3121
+ this.current = function (rng) {
3035
3122
  var $cont = $(dom.isText(rng.sc) ? rng.sc.parentNode : rng.sc);
3036
- var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height'];
3037
- var styleInfo = jQueryCSS($cont, properties) || {};
3038
-
3039
- styleInfo['font-size'] = parseInt(styleInfo['font-size'], 10);
3123
+ var styleInfo = this.fromNode($cont);
3040
3124
 
3041
3125
  // document.queryCommandState for toggle state
3042
3126
  styleInfo['font-bold'] = document.queryCommandState('bold') ? 'bold' : 'normal';
@@ -3063,7 +3147,6 @@
3063
3147
  styleInfo['line-height'] = lineHeight.toFixed(1);
3064
3148
  }
3065
3149
 
3066
- styleInfo.image = dom.isImg(target) && target;
3067
3150
  styleInfo.anchor = rng.isOnAnchor() && dom.ancestor(rng.sc, dom.isAnchor);
3068
3151
  styleInfo.ancestors = dom.listAncestor(rng.sc, dom.isEditable);
3069
3152
  styleInfo.range = rng;
@@ -3221,7 +3304,7 @@
3221
3304
  var listNode = prevList || dom.insertAfter(dom.create(listName || 'UL'), last);
3222
3305
 
3223
3306
  // P to LI
3224
- paras = $.map(paras, function (para) {
3307
+ paras = paras.map(function (para) {
3225
3308
  return dom.isPurePara(para) ? dom.replace(para, 'LI') : para;
3226
3309
  });
3227
3310
 
@@ -3271,7 +3354,7 @@
3271
3354
 
3272
3355
  // LI to P
3273
3356
  if (isEscapseToBody || !dom.isList(headList.parentNode)) {
3274
- paras = $.map(paras, function (para) {
3357
+ paras = paras.map(function (para) {
3275
3358
  return dom.replace(para, 'P');
3276
3359
  });
3277
3360
  }
@@ -3515,17 +3598,32 @@
3515
3598
  $editable[0].appendChild(child[index]);
3516
3599
  }
3517
3600
  };
3601
+
3518
3602
  /**
3519
3603
  * @method currentStyle
3520
3604
  *
3521
3605
  * current style
3522
3606
  *
3523
3607
  * @param {Node} target
3524
- * @return {Boolean} false if range is no
3608
+ * @return {Object|Boolean} unfocus
3525
3609
  */
3526
3610
  this.currentStyle = function (target) {
3527
- var rng = range.create().normalize();
3528
- return rng ? rng.isOnEditable() && style.current(rng, target) : false;
3611
+ var rng = range.create();
3612
+ var styleInfo = rng && rng.isOnEditable() ? style.current(rng.normalize()) : {};
3613
+ if (dom.isImg(target)) {
3614
+ styleInfo.image = target;
3615
+ }
3616
+ return styleInfo;
3617
+ };
3618
+
3619
+ /**
3620
+ * style from node
3621
+ *
3622
+ * @param {jQuery} $node
3623
+ * @return {Object}
3624
+ */
3625
+ this.styleFromNode = function ($node) {
3626
+ return style.fromNode($node);
3529
3627
  };
3530
3628
 
3531
3629
  var triggerOnBeforeChange = function ($editable) {
@@ -3698,7 +3796,7 @@
3698
3796
  var commands = ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript',
3699
3797
  'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull',
3700
3798
  'formatBlock', 'removeFormat',
3701
- 'backColor', 'foreColor', 'insertHorizontalRule', 'fontName'];
3799
+ 'backColor', 'foreColor', 'fontName'];
3702
3800
 
3703
3801
  for (var idx = 0, len = commands.length; idx < len; idx ++) {
3704
3802
  this[commands[idx]] = (function (sCmd) {
@@ -3920,6 +4018,22 @@
3920
4018
  }
3921
4019
  };
3922
4020
 
4021
+ /**
4022
+ * insert horizontal rule
4023
+ * @param {jQuery} $editable
4024
+ */
4025
+ this.insertHorizontalRule = function ($editable) {
4026
+ beforeCommand($editable);
4027
+
4028
+ var rng = range.create();
4029
+ var hrNode = rng.insertNode($('<HR/>')[0]);
4030
+ if (hrNode.nextSibling) {
4031
+ range.create(hrNode.nextSibling, 0).normalize().select();
4032
+ }
4033
+
4034
+ afterCommand($editable);
4035
+ };
4036
+
3923
4037
  /**
3924
4038
  * remove bogus node and character
3925
4039
  */
@@ -3986,7 +4100,7 @@
3986
4100
  this.createLink = function ($editable, linkInfo, options) {
3987
4101
  var linkUrl = linkInfo.url;
3988
4102
  var linkText = linkInfo.text;
3989
- var isNewWindow = linkInfo.newWindow;
4103
+ var isNewWindow = linkInfo.isNewWindow;
3990
4104
  var rng = linkInfo.range || this.createRange($editable);
3991
4105
  var isTextChanged = rng.toString() !== linkText;
3992
4106
 
@@ -4104,6 +4218,13 @@
4104
4218
  */
4105
4219
  this.floatMe = function ($editable, value, $target) {
4106
4220
  beforeCommand($editable);
4221
+ // bootstrap
4222
+ $target.removeClass('pull-left pull-right');
4223
+ if (value && value !== 'none') {
4224
+ $target.addClass('pull-' + value);
4225
+ }
4226
+
4227
+ // fallback for non-bootstrap
4107
4228
  $target.css('float', value);
4108
4229
  afterCommand($editable);
4109
4230
  };
@@ -4522,15 +4643,17 @@
4522
4643
  *
4523
4644
  * @private
4524
4645
  * @param {Node} placeholder
4525
- * @param {Boolean} isAirMode
4526
- * @return {Object}
4527
- * @return {Number} return.left
4528
- * @return {Number} return.top
4646
+ * @param {Object} options
4647
+ * @param {Boolean} options.isAirMode
4648
+ * @return {Position}
4529
4649
  */
4530
- var posFromPlaceholder = function (placeholder, isAirMode) {
4650
+ var posFromPlaceholder = function (placeholder, options) {
4651
+ var isAirMode = options && options.isAirMode;
4652
+ var isLeftTop = options && options.isLeftTop;
4653
+
4531
4654
  var $placeholder = $(placeholder);
4532
4655
  var pos = isAirMode ? $placeholder.offset() : $placeholder.position();
4533
- var height = $placeholder.outerHeight(true); // include margin
4656
+ var height = isLeftTop ? 0 : $placeholder.outerHeight(true); // include margin
4534
4657
 
4535
4658
  // popover below placeholder.
4536
4659
  return {
@@ -4576,20 +4699,25 @@
4576
4699
  } else {
4577
4700
  $anchor.attr('target', '_blank');
4578
4701
  }
4579
- showPopover($linkPopover, posFromPlaceholder(styleInfo.anchor, isAirMode));
4702
+ showPopover($linkPopover, posFromPlaceholder(styleInfo.anchor, {
4703
+ isAirMode: isAirMode
4704
+ }));
4580
4705
  } else {
4581
4706
  $linkPopover.hide();
4582
4707
  }
4583
4708
 
4584
4709
  var $imagePopover = $popover.find('.note-image-popover');
4585
4710
  if (styleInfo.image) {
4586
- showPopover($imagePopover, posFromPlaceholder(styleInfo.image, isAirMode));
4711
+ showPopover($imagePopover, posFromPlaceholder(styleInfo.image, {
4712
+ isAirMode: isAirMode,
4713
+ isLeftTop: true
4714
+ }));
4587
4715
  } else {
4588
4716
  $imagePopover.hide();
4589
4717
  }
4590
4718
 
4591
4719
  var $airPopover = $popover.find('.note-air-popover');
4592
- if (isAirMode && !styleInfo.range.isCollapsed()) {
4720
+ if (isAirMode && styleInfo.range && !styleInfo.range.isCollapsed()) {
4593
4721
  var rect = list.last(styleInfo.range.getClientRects());
4594
4722
  if (rect) {
4595
4723
  var bnd = func.rect2bnd(rect);
@@ -4990,106 +5118,84 @@
4990
5118
  };
4991
5119
 
4992
5120
  var Clipboard = function (handler) {
4993
-
4994
5121
  var $paste;
4995
5122
 
4996
5123
  this.attach = function (layoutInfo) {
4997
-
4998
- if (window.clipboardData || agent.isFF) {
5124
+ // [workaround] getting image from clipboard
5125
+ // - IE11 and Firefox: CTRL+v hook
5126
+ // - Webkit: event.clipboardData
5127
+ if ((agent.isMSIE && agent.browserVersion > 10) || agent.isFF) {
4999
5128
  $paste = $('<div />').attr('contenteditable', true).css({
5000
5129
  position : 'absolute',
5001
5130
  left : -100000,
5002
5131
  opacity : 0
5003
5132
  });
5004
- layoutInfo.editable().after($paste);
5005
- $paste.on('paste', hPasteClipboardImage);
5006
5133
 
5007
5134
  layoutInfo.editable().on('keydown', function (e) {
5008
- if (e.ctrlKey && e.keyCode === 86) { // CTRL+V
5135
+ if (e.ctrlKey && e.keyCode === key.code.V) {
5009
5136
  handler.invoke('saveRange', layoutInfo.editable());
5010
- if ($paste) {
5011
- $paste.focus();
5012
- }
5137
+ $paste.focus();
5138
+
5139
+ setTimeout(function () {
5140
+ pasteByHook(layoutInfo);
5141
+ }, 0);
5013
5142
  }
5014
5143
  });
5015
- }
5016
5144
 
5017
- layoutInfo.editable().on('paste', hPasteClipboardImage);
5145
+ layoutInfo.editable().before($paste);
5146
+ } else {
5147
+ layoutInfo.editable().on('paste', pasteByEvent);
5148
+ }
5018
5149
  };
5019
5150
 
5020
- var hPasteContent = function (handler, $paste, $editable) {
5021
- var pasteContent = $('<div />').html($paste.html());
5151
+ var pasteByHook = function (layoutInfo) {
5152
+ var $editable = layoutInfo.editable();
5153
+ var node = $paste[0].firstChild;
5154
+
5155
+ if (dom.isImg(node)) {
5156
+ var dataURI = node.src;
5157
+ var decodedData = atob(dataURI.split(',')[1]);
5158
+ var array = new Uint8Array(decodedData.length);
5159
+ for (var i = 0; i < decodedData.length; i++) {
5160
+ array[i] = decodedData.charCodeAt(i);
5161
+ }
5162
+
5163
+ var blob = new Blob([array], { type : 'image/png' });
5164
+ blob.name = 'clipboard.png';
5165
+
5166
+ handler.invoke('restoreRange', $editable);
5167
+ handler.invoke('focus', $editable);
5168
+ handler.insertImages(layoutInfo, [blob]);
5169
+ } else {
5170
+ var pasteContent = $('<div />').html($paste.html()).html();
5171
+ handler.invoke('restoreRange', $editable);
5172
+ handler.invoke('focus', $editable);
5173
+
5174
+ if (pasteContent) {
5175
+ handler.invoke('pasteHTML', $editable, pasteContent);
5176
+ }
5177
+ }
5022
5178
 
5023
- handler.invoke('restoreRange', $editable);
5024
- handler.invoke('focus', $editable);
5025
- handler.invoke('pasteHTML', $editable, pasteContent.html());
5026
5179
  $paste.empty();
5027
5180
  };
5028
5181
 
5029
5182
  /**
5030
- * paste clipboard image
5183
+ * paste by clipboard event
5031
5184
  *
5032
5185
  * @param {Event} event
5033
5186
  */
5034
- var hPasteClipboardImage = function (event) {
5035
-
5187
+ var pasteByEvent = function (event) {
5036
5188
  var clipboardData = event.originalEvent.clipboardData;
5037
5189
  var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
5038
5190
  var $editable = layoutInfo.editable();
5039
5191
 
5040
- if (!clipboardData || !clipboardData.items || !clipboardData.items.length) {
5041
-
5042
- var callbacks = $editable.data('callbacks');
5043
- // only can run if it has onImageUpload method
5044
- if (!callbacks.onImageUpload) {
5045
- hPasteContent(handler, $paste, $editable);
5046
- return;
5192
+ if (clipboardData && clipboardData.items && clipboardData.items.length) {
5193
+ var item = list.head(clipboardData.items);
5194
+ if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
5195
+ handler.insertImages(layoutInfo, [item.getAsFile()]);
5047
5196
  }
5048
-
5049
- setTimeout(function () {
5050
- if (!$paste) {
5051
- return;
5052
- }
5053
-
5054
- var imgNode = $paste[0].firstChild;
5055
- if (!imgNode) {
5056
- hPasteContent(handler, $paste, $editable);
5057
- return;
5058
- }
5059
-
5060
- if (!dom.isImg(imgNode)) {
5061
- hPasteContent(handler, $paste, $editable);
5062
- } else {
5063
- handler.invoke('restoreRange', $editable);
5064
- var datauri = imgNode.src;
5065
-
5066
- var data = atob(datauri.split(',')[1]);
5067
- var array = new Uint8Array(data.length);
5068
- for (var i = 0; i < data.length; i++) {
5069
- array[i] = data.charCodeAt(i);
5070
- }
5071
-
5072
- var blob = new Blob([array], { type : 'image/png' });
5073
- blob.name = 'clipboard.png';
5074
- handler.invoke('focus', $editable);
5075
- handler.insertImages(layoutInfo, [blob]);
5076
-
5077
- $paste.empty();
5078
- }
5079
-
5080
- }, 0);
5081
-
5082
- return;
5083
- }
5084
-
5085
- var item = list.head(clipboardData.items);
5086
- var isClipboardImage = item.kind === 'file' && item.type.indexOf('image/') !== -1;
5087
-
5088
- if (isClipboardImage) {
5089
- handler.insertImages(layoutInfo, [item.getAsFile()]);
5197
+ handler.invoke('editor.afterCommand', $editable);
5090
5198
  }
5091
-
5092
- handler.invoke('editor.afterCommand', $editable);
5093
5199
  };
5094
5200
  };
5095
5201
 
@@ -5167,7 +5273,7 @@
5167
5273
  bindEnterKey($linkUrl, $linkBtn);
5168
5274
  bindEnterKey($linkText, $linkBtn);
5169
5275
 
5170
- $openInNewWindow.prop('checked', linkInfo.newWindow);
5276
+ $openInNewWindow.prop('checked', linkInfo.isNewWindow);
5171
5277
 
5172
5278
  $linkBtn.one('click', function (event) {
5173
5279
  event.preventDefault();
@@ -5176,7 +5282,7 @@
5176
5282
  range: linkInfo.range,
5177
5283
  url: $linkUrl.val(),
5178
5284
  text: $linkText.val(),
5179
- newWindow: $openInNewWindow.is(':checked')
5285
+ isNewWindow: $openInNewWindow.is(':checked')
5180
5286
  });
5181
5287
  $linkDialog.modal('hide');
5182
5288
  });
@@ -5362,6 +5468,8 @@
5362
5468
  * - TODO: new instance per a editor
5363
5469
  */
5364
5470
  var EventHandler = function () {
5471
+ var self = this;
5472
+
5365
5473
  /**
5366
5474
  * Modules
5367
5475
  */
@@ -5513,20 +5621,31 @@
5513
5621
  hToolbarAndPopoverUpdate(event);
5514
5622
  };
5515
5623
 
5624
+ /**
5625
+ * update sytle info
5626
+ * @param {Object} styleInfo
5627
+ * @param {Object} layoutInfo
5628
+ */
5629
+ this.updateStyleInfo = function (styleInfo, layoutInfo) {
5630
+ if (!styleInfo) {
5631
+ return;
5632
+ }
5633
+ var isAirMode = layoutInfo.editor().data('options').airMode;
5634
+ if (!isAirMode) {
5635
+ modules.toolbar.update(layoutInfo.toolbar(), styleInfo);
5636
+ }
5637
+
5638
+ modules.popover.update(layoutInfo.popover(), styleInfo, isAirMode);
5639
+ modules.handle.update(layoutInfo.handle(), styleInfo, isAirMode);
5640
+ };
5641
+
5516
5642
  var hToolbarAndPopoverUpdate = function (event) {
5643
+ var target = event.target;
5517
5644
  // delay for range after mouseup
5518
5645
  setTimeout(function () {
5519
- var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
5520
- var styleInfo = modules.editor.currentStyle(event.target);
5521
- if (!styleInfo) { return; }
5522
-
5523
- var isAirMode = layoutInfo.editor().data('options').airMode;
5524
- if (!isAirMode) {
5525
- modules.toolbar.update(layoutInfo.toolbar(), styleInfo);
5526
- }
5527
-
5528
- modules.popover.update(layoutInfo.popover(), styleInfo, isAirMode);
5529
- modules.handle.update(layoutInfo.handle(), styleInfo, isAirMode);
5646
+ var layoutInfo = dom.makeLayoutInfo(target);
5647
+ var styleInfo = modules.editor.currentStyle(target);
5648
+ self.updateStyleInfo(styleInfo, layoutInfo);
5530
5649
  }, 0);
5531
5650
  };
5532
5651
 
@@ -5548,47 +5667,49 @@
5548
5667
  var hToolbarAndPopoverClick = function (event) {
5549
5668
  var $btn = $(event.target).closest('[data-event]');
5550
5669
 
5551
- if ($btn.length) {
5552
- var eventName = $btn.attr('data-event'),
5553
- value = $btn.attr('data-value'),
5554
- hide = $btn.attr('data-hide');
5670
+ if (!$btn.length) {
5671
+ return;
5672
+ }
5555
5673
 
5556
- var layoutInfo = dom.makeLayoutInfo(event.target);
5674
+ var eventName = $btn.attr('data-event'),
5675
+ value = $btn.attr('data-value'),
5676
+ hide = $btn.attr('data-hide');
5557
5677
 
5558
- // before command: detect control selection element($target)
5559
- var $target;
5560
- if ($.inArray(eventName, ['resize', 'floatMe', 'removeMedia', 'imageShape']) !== -1) {
5561
- var $selection = layoutInfo.handle().find('.note-control-selection');
5562
- $target = $($selection.data('target'));
5563
- }
5678
+ var layoutInfo = dom.makeLayoutInfo(event.target);
5564
5679
 
5565
- // If requested, hide the popover when the button is clicked.
5566
- // Useful for things like showHelpDialog.
5567
- if (hide) {
5568
- $btn.parents('.popover').hide();
5569
- }
5680
+ // before command: detect control selection element($target)
5681
+ var $target;
5682
+ if ($.inArray(eventName, ['resize', 'floatMe', 'removeMedia', 'imageShape']) !== -1) {
5683
+ var $selection = layoutInfo.handle().find('.note-control-selection');
5684
+ $target = $($selection.data('target'));
5685
+ }
5570
5686
 
5571
- if ($.isFunction($.summernote.pluginEvents[eventName])) {
5572
- $.summernote.pluginEvents[eventName](event, modules.editor, layoutInfo, value);
5573
- } else if (modules.editor[eventName]) { // on command
5574
- var $editable = layoutInfo.editable();
5575
- $editable.focus();
5576
- modules.editor[eventName]($editable, value, $target);
5577
- event.preventDefault();
5578
- } else if (commands[eventName]) {
5579
- commands[eventName].call(this, layoutInfo);
5580
- event.preventDefault();
5581
- }
5687
+ // If requested, hide the popover when the button is clicked.
5688
+ // Useful for things like showHelpDialog.
5689
+ if (hide) {
5690
+ $btn.parents('.popover').hide();
5691
+ }
5582
5692
 
5583
- // after command
5584
- if ($.inArray(eventName, ['backColor', 'foreColor']) !== -1) {
5585
- var options = layoutInfo.editor().data('options', options);
5586
- var module = options.airMode ? modules.popover : modules.toolbar;
5587
- module.updateRecentColor(list.head($btn), eventName, value);
5588
- }
5693
+ if ($.isFunction($.summernote.pluginEvents[eventName])) {
5694
+ $.summernote.pluginEvents[eventName](event, modules.editor, layoutInfo, value);
5695
+ } else if (modules.editor[eventName]) { // on command
5696
+ var $editable = layoutInfo.editable();
5697
+ $editable.focus();
5698
+ modules.editor[eventName]($editable, value, $target);
5699
+ event.preventDefault();
5700
+ } else if (commands[eventName]) {
5701
+ commands[eventName].call(this, layoutInfo);
5702
+ event.preventDefault();
5703
+ }
5589
5704
 
5590
- hToolbarAndPopoverUpdate(event);
5705
+ // after command
5706
+ if ($.inArray(eventName, ['backColor', 'foreColor']) !== -1) {
5707
+ var options = layoutInfo.editor().data('options', options);
5708
+ var module = options.airMode ? modules.popover : modules.toolbar;
5709
+ module.updateRecentColor(list.head($btn), eventName, value);
5591
5710
  }
5711
+
5712
+ hToolbarAndPopoverUpdate(event);
5592
5713
  };
5593
5714
 
5594
5715
  var PX_PER_EM = 18;
@@ -5769,12 +5890,8 @@
5769
5890
  onToolbarClick: options.onToolbarClick
5770
5891
  });
5771
5892
 
5772
- // Textarea: auto filling the code before form submit.
5773
- if (dom.isTextarea(list.head(layoutInfo.holder()))) {
5774
- layoutInfo.holder().closest('form').submit(function () {
5775
- layoutInfo.holder().val(layoutInfo.holder().code());
5776
- });
5777
- }
5893
+ var styleInfo = modules.editor.styleFromNode(layoutInfo.editable());
5894
+ this.updateStyleInfo(styleInfo, layoutInfo);
5778
5895
  };
5779
5896
 
5780
5897
  /**
@@ -5804,8 +5921,8 @@
5804
5921
 
5805
5922
  $editable.on('paste', bindCustomEvent($holder, callbacks, 'paste'));
5806
5923
 
5807
- // [workaround] for old IE - IE8 don't have input events
5808
- // - TODO check IE version
5924
+ // [workaround] IE doesn't have input events for contentEditable
5925
+ // - see: https://goo.gl/4bfIvA
5809
5926
  var changeEventName = agent.isMSIE ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input';
5810
5927
  $editable.on(changeEventName, function () {
5811
5928
  bindCustomEvent($holder, callbacks, 'change')($editable.html(), $editable);
@@ -5819,10 +5936,18 @@
5819
5936
  // Textarea: auto filling the code before form submit.
5820
5937
  if (dom.isTextarea(list.head($holder))) {
5821
5938
  $holder.closest('form').submit(function (e) {
5939
+ layoutInfo.holder().val(layoutInfo.holder().code());
5822
5940
  bindCustomEvent($holder, callbacks, 'submit').call(this, e, $holder.code());
5823
5941
  });
5824
5942
  }
5825
5943
 
5944
+ // textarea auto sync
5945
+ if (dom.isTextarea(list.head($holder)) && options.textareaAutoSync) {
5946
+ $holder.on('summernote.change', function () {
5947
+ layoutInfo.holder().val(layoutInfo.holder().code());
5948
+ });
5949
+ }
5950
+
5826
5951
  // fire init event
5827
5952
  bindCustomEvent($holder, callbacks, 'init')(layoutInfo);
5828
5953
 
@@ -5882,7 +6007,7 @@
5882
6007
  return (dropdown ? '<div class="btn-group' +
5883
6008
  (className ? ' ' + className : '') + '">' : '') +
5884
6009
  '<button type="button"' +
5885
- ' class="btn btn-default btn-sm btn-small' +
6010
+ ' class="btn btn-default btn-sm' +
5886
6011
  ((!dropdown && className) ? ' ' + className : '') +
5887
6012
  (dropdown ? ' dropdown-toggle' : '') +
5888
6013
  '"' +
@@ -6024,7 +6149,7 @@
6024
6149
  fontname: function (lang, options) {
6025
6150
  var realFontList = [];
6026
6151
  var items = options.fontNames.reduce(function (memo, v) {
6027
- if (!agent.isFontInstalled(v) && options.fontNamesIgnoreCheck.indexOf(v) === -1) {
6152
+ if (!agent.isFontInstalled(v) && !list.contains(options.fontNamesIgnoreCheck, v)) {
6028
6153
  return memo;
6029
6154
  }
6030
6155
  realFontList.push(v);
@@ -6317,8 +6442,8 @@
6317
6442
  value: 'none'
6318
6443
  });
6319
6444
 
6320
- var content = '<div class="btn-group">' + fullButton + halfButton + quarterButton + '</div>' +
6321
- '<div class="btn-group">' + leftButton + rightButton + justifyButton + '</div>' +
6445
+ var content = (options.disableResizeImage ? '' : '<div class="btn-group">' + fullButton + halfButton + quarterButton + '</div>') +
6446
+ '<div class="btn-group">' + leftButton + rightButton + justifyButton + '</div><br>' +
6322
6447
  '<div class="btn-group">' + roundedButton + circleButton + thumbnailButton + noneButton + '</div>' +
6323
6448
  '<div class="btn-group">' + removeButton + '</div>';
6324
6449
  return tplPopover('note-image-popover', content);
@@ -6355,15 +6480,17 @@
6355
6480
  return $notePopover;
6356
6481
  };
6357
6482
 
6358
- var tplHandles = function () {
6483
+ var tplHandles = function (options) {
6359
6484
  return '<div class="note-handle">' +
6360
6485
  '<div class="note-control-selection">' +
6361
6486
  '<div class="note-control-selection-bg"></div>' +
6362
6487
  '<div class="note-control-holder note-control-nw"></div>' +
6363
6488
  '<div class="note-control-holder note-control-ne"></div>' +
6364
6489
  '<div class="note-control-holder note-control-sw"></div>' +
6365
- '<div class="note-control-sizing note-control-se"></div>' +
6366
- '<div class="note-control-selection-info"></div>' +
6490
+ '<div class="' +
6491
+ (options.disableResizeImage ? 'note-control-holder' : 'note-control-sizing') +
6492
+ ' note-control-se"></div>' +
6493
+ (options.disableResizeImage ? '' : '<div class="note-control-selection-info"></div>') +
6367
6494
  '</div>' +
6368
6495
  '</div>';
6369
6496
  };
@@ -6485,27 +6612,27 @@
6485
6612
  imageLimitation = '<small>' + lang.image.maximumFileSize + ' : ' + readableSize + '</small>';
6486
6613
  }
6487
6614
 
6488
- var body = '<div class="form-group row-fluid note-group-select-from-files">' +
6615
+ var body = '<div class="form-group row note-group-select-from-files">' +
6489
6616
  '<label>' + lang.image.selectFromFiles + '</label>' +
6490
- '<input class="note-image-input" type="file" name="files" accept="image/*" multiple="multiple" />' +
6617
+ '<input class="note-image-input form-control" type="file" name="files" accept="image/*" multiple="multiple" />' +
6491
6618
  imageLimitation +
6492
6619
  '</div>' +
6493
- '<div class="form-group row-fluid">' +
6620
+ '<div class="form-group row">' +
6494
6621
  '<label>' + lang.image.url + '</label>' +
6495
- '<input class="note-image-url form-control span12" type="text" />' +
6622
+ '<input class="note-image-url form-control col-md-12" type="text" />' +
6496
6623
  '</div>';
6497
6624
  var footer = '<button href="#" class="btn btn-primary note-image-btn disabled" disabled>' + lang.image.insert + '</button>';
6498
6625
  return tplDialog('note-image-dialog', lang.image.insert, body, footer);
6499
6626
  },
6500
6627
 
6501
6628
  link: function (lang, options) {
6502
- var body = '<div class="form-group row-fluid">' +
6629
+ var body = '<div class="form-group row">' +
6503
6630
  '<label>' + lang.link.textToDisplay + '</label>' +
6504
- '<input class="note-link-text form-control span12" type="text" />' +
6631
+ '<input class="note-link-text form-control col-md-12" type="text" />' +
6505
6632
  '</div>' +
6506
- '<div class="form-group row-fluid">' +
6633
+ '<div class="form-group row">' +
6507
6634
  '<label>' + lang.link.url + '</label>' +
6508
- '<input class="note-link-url form-control span12" type="text" value="http://" />' +
6635
+ '<input class="note-link-url form-control col-md-12" type="text" value="http://" />' +
6509
6636
  '</div>' +
6510
6637
  (!options.disableLinkTarget ?
6511
6638
  '<div class="checkbox">' +
@@ -6523,7 +6650,7 @@
6523
6650
  '<div class="title">' + lang.shortcut.shortcuts + '</div>' +
6524
6651
  (agent.isMac ? tplShortcutTable(lang, options) : replaceMacKeys(tplShortcutTable(lang, options))) +
6525
6652
  '<p class="text-center">' +
6526
- '<a href="//summernote.org/" target="_blank">Summernote 0.6.10</a> · ' +
6653
+ '<a href="//summernote.org/" target="_blank">Summernote 0.6.16</a> · ' +
6527
6654
  '<a href="//github.com/summernote/summernote" target="_blank">Project</a> · ' +
6528
6655
  '<a href="//github.com/summernote/summernote/issues" target="_blank">Issues</a>' +
6529
6656
  '</p>';
@@ -6624,7 +6751,7 @@
6624
6751
  var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];
6625
6752
  var id = func.uniqueId();
6626
6753
 
6627
- $holder.addClass('note-air-editor note-editable');
6754
+ $holder.addClass('note-air-editor note-editable panel-body');
6628
6755
  $holder.attr({
6629
6756
  'id': 'note-editor-' + id,
6630
6757
  'contentEditable': true
@@ -6641,7 +6768,7 @@
6641
6768
  createPalette($popover, options);
6642
6769
 
6643
6770
  // create Handle
6644
- var $handle = $(tplHandles());
6771
+ var $handle = $(tplHandles(options));
6645
6772
  $handle.addClass('note-air-layout');
6646
6773
  $handle.attr('id', 'note-handle-' + id);
6647
6774
  $handle.appendTo(body);
@@ -6666,7 +6793,7 @@
6666
6793
  var langInfo = options.langInfo;
6667
6794
 
6668
6795
  //01. create Editor
6669
- var $editor = $('<div class="note-editor"></div>');
6796
+ var $editor = $('<div class="note-editor panel panel-default" />');
6670
6797
  if (options.width) {
6671
6798
  $editor.width(options.width);
6672
6799
  }
@@ -6676,10 +6803,12 @@
6676
6803
  $('<div class="note-statusbar">' + (options.disableResizeEditor ? '' : tplStatusbar()) + '</div>').prependTo($editor);
6677
6804
  }
6678
6805
 
6679
- //03. create Editable
6806
+ //03 editing area
6807
+ var $editingArea = $('<div class="note-editing-area" />');
6808
+ //03. create editable
6680
6809
  var isContentEditable = !$holder.is(':disabled');
6681
- var $editable = $('<div class="note-editable" contentEditable="' + isContentEditable + '"></div>')
6682
- .prependTo($editor);
6810
+ var $editable = $('<div class="note-editable panel-body" contentEditable="' + isContentEditable + '"></div>').prependTo($editingArea);
6811
+
6683
6812
  if (options.height) {
6684
6813
  $editable.height(options.height);
6685
6814
  }
@@ -6691,13 +6820,23 @@
6691
6820
  $editable.attr('data-placeholder', placeholder);
6692
6821
  }
6693
6822
 
6694
- $editable.html(dom.html($holder));
6823
+ $editable.html(dom.html($holder) || dom.emptyPara);
6695
6824
 
6696
6825
  //031. create codable
6697
- $('<textarea class="note-codable"></textarea>').prependTo($editor);
6826
+ $('<textarea class="note-codable"></textarea>').prependTo($editingArea);
6827
+
6828
+ //04. create Popover
6829
+ var $popover = $(tplPopovers(langInfo, options)).prependTo($editingArea);
6830
+ createPalette($popover, options);
6831
+ createTooltip($popover, keyMap);
6832
+
6833
+ //05. handle(control selection, ...)
6834
+ $(tplHandles(options)).prependTo($editingArea);
6835
+
6836
+ $editingArea.prependTo($editor);
6698
6837
 
6699
- //04. create Toolbar
6700
- var $toolbar = $('<div class="note-toolbar btn-toolbar" />');
6838
+ //06. create Toolbar
6839
+ var $toolbar = $('<div class="note-toolbar panel-heading" />');
6701
6840
  for (var idx = 0, len = options.toolbar.length; idx < len; idx ++) {
6702
6841
  var groupName = options.toolbar[idx][0];
6703
6842
  var groupButtons = options.toolbar[idx][1];
@@ -6715,30 +6854,21 @@
6715
6854
  $toolbar.append($group);
6716
6855
  }
6717
6856
 
6718
- $toolbar.prependTo($editor);
6719
6857
  var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];
6720
6858
  createPalette($toolbar, options);
6721
6859
  createTooltip($toolbar, keyMap, 'bottom');
6860
+ $toolbar.prependTo($editor);
6722
6861
 
6723
- //05. create Popover
6724
- var $popover = $(tplPopovers(langInfo, options)).prependTo($editor);
6725
- createPalette($popover, options);
6726
- createTooltip($popover, keyMap);
6727
-
6728
- //06. handle(control selection, ...)
6729
- $(tplHandles()).prependTo($editor);
6730
-
6731
- var $dialogContainer = options.dialogsInBody ? document.body : $editor;
6862
+ //07. create Dropzone
6863
+ $('<div class="note-dropzone"><div class="note-dropzone-message"></div></div>').prependTo($editor);
6732
6864
 
6733
- //07. create Dialog
6865
+ //08. create Dialog
6866
+ var $dialogContainer = options.dialogsInBody ? $(document.body) : $editor;
6734
6867
  var $dialog = $(tplDialogs(langInfo, options)).prependTo($dialogContainer);
6735
6868
  $dialog.find('button.close, a.modal-close').click(function () {
6736
6869
  $(this).closest('.modal').modal('hide');
6737
6870
  });
6738
6871
 
6739
- //08. create Dropzone
6740
- $('<div class="note-dropzone"><div class="note-dropzone-message"></div></div>').prependTo($editor);
6741
-
6742
6872
  //09. Editor/Holder switch
6743
6873
  $editor.insertAfter($holder);
6744
6874
  $holder.hide();
@@ -7066,7 +7196,6 @@
7066
7196
 
7067
7197
  eventHandler.attach(layoutInfo, options);
7068
7198
  eventHandler.attachCustomEvent(layoutInfo, options);
7069
-
7070
7199
  }
7071
7200
  });
7072
7201