summernote-rails 0.6.10.0 → 0.6.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 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