Socket
Socket
Sign inDemoInstall

summernote

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

summernote - npm Package Compare versions

Comparing version 0.6.1 to 0.6.5

CONTRIBUTING.md

2

bower.json
{
"name": "summernote",
"version": "0.6.1",
"version": "0.6.5",
"main": [

@@ -5,0 +5,0 @@ "./dist/summernote.js",

@@ -77,2 +77,26 @@ module.exports = function (grunt) {

// compress: summernote-{{version}}-dist.zip
compress: {
main: {
options: {
archive: function () {
return 'dist/summernote-{{version}}-dist.zip'.replace(
'{{version}}',
grunt.config('pkg.version')
);
}
},
files: [{
expand: true,
src: [
'dist/*.js',
'dist/summernote.css'
]
}, {
src: ['plugin/*.js'],
dest: 'dist/'
}]
}
},
// connect configuration.

@@ -124,14 +148,17 @@ connect: {

// server
// load all grunts/*.js
grunt.loadTasks('grunts');
// server: runt server for development
grunt.registerTask('server', ['connect', 'watch']);
// build: build summernote.js
grunt.loadTasks('build');
// test: unit test on test folder
grunt.registerTask('test', ['jshint', 'qunit']);
// dist
// dist: make dist files
grunt.registerTask('dist', ['build', 'test', 'uglify', 'recess']);
// deploy: compress dist files
grunt.registerTask('deploy', ['dist', 'compress']);
// default: server

@@ -138,0 +165,0 @@ grunt.registerTask('default', ['server']);

### Change Log
#### v0.6.4 ~ v0.6.5 2015-04-26
* Support more range API: range.pasteHTML, range.getWordRange
* Merge summernote-ext-fontstyle.js plugin with base code
* Bugfix : #1003, #1026, #1038, some of #1012
#### v0.6.3 2015-04-08
* Support external API access
* Support callbacks with jquery custom event.
#### v0.6.2 2015-03-14
* Fixed text drag and drop bug.
#### v0.6.1 2015-02-08

@@ -4,0 +16,0 @@ * Fixed bugs about links, bullets and ranges.

@@ -10,3 +10,5 @@ (function ($) {

height: 'إرتفاع السطر',
name: 'الخط'
name: 'الخط',
strikethrough: 'فى وسطه خط',
size: 'الحجم'
},

@@ -13,0 +15,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: 'Treure estil de lletra',
height: 'Alçada de línia'
height: 'Alçada de línia',
strikethrough: 'Ratllat',
size: 'Mida de lletra'
},

@@ -12,0 +14,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: 'Odstranit styl písma',
height: 'Výška řádku'
height: 'Výška řádku',
strikethrough: 'Přeškrtnuté',
size: 'Velikost písma'
},

@@ -12,0 +14,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'Højde',
name: 'Skrifttype'
name: 'Skrifttype',
strikethrough: 'Gennemstreget',
subscript: 'Sænket skrift',
superscript: 'Hævet skrift',
size: 'Skriftstørrelse'
},

@@ -13,0 +17,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: 'Zurücksetzen',
height: 'Zeilenhöhe'
height: 'Zeilenhöhe',
strikethrough: 'Durchgestrichen',
size: 'Schriftgröße'
},

@@ -12,0 +14,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'Altura de línea',
name: 'Fuente'
name: 'Fuente',
strikethrough: 'Tachado',
superscript: 'Superíndice',
subscript: 'Subíndice',
size: 'Tamaño de la fuente'
},

@@ -13,0 +17,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Lerro altuera',
name: 'Tipografia'
name: 'Tipografia',
strikethrough: 'Marratua',
size: 'Letren neurria'
},

@@ -13,0 +15,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'فاصله ی خطی',
name: 'اسم فونت'
name: 'اسم فونت',
strikethrough: 'Strike',
size: 'اندازه ی فونت'
},

@@ -13,0 +15,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Riviväli',
name: 'Kirjasintyyppi'
name: 'Kirjasintyyppi',
strikethrough: 'Yliviivaus',
size: 'Kirjasinkoko'
},

@@ -13,0 +15,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'Interligne',
name: 'Famille de police'
name: 'Famille de police',
strikethrough: 'Barré',
superscript: 'Exposant',
subscript: 'Indicé',
size: 'Taille de police'
},

@@ -13,0 +17,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'גובה',
name: 'גופן'
name: 'גופן',
strikethrough: 'קו חוצה',
subscript: 'כתב תחתי',
superscript: 'כתב עילי',
size: 'גודל גופן'
},

@@ -13,0 +17,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Sorköz',
name: 'Betűtípus'
name: 'Betűtípus',
strikethrough: 'Áthúzott',
size: 'Betűméret'
},

@@ -13,0 +15,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: 'Bersihkan gaya',
height: 'Jarak baris'
height: 'Jarak baris',
strikethrough: 'Coret',
size: 'Ukuran font'
},

@@ -12,0 +14,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Altezza della linea di testo',
name: 'Famiglia Font'
name: 'Famiglia Font',
strikethrough: 'Testo barrato',
size: 'Dimensione del carattere'
},

@@ -13,0 +15,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: '文字高',
name: 'フォント'
name: 'フォント',
strikethrough: '取り消し線',
size: '大きさ'
},

@@ -13,0 +15,0 @@ image: {

(function ($) {
console.log('hit');
$.extend($.summernote.lang, {

@@ -10,3 +11,7 @@ 'ko-KR': {

height: '줄간격',
name: '글꼴'
name: '글꼴',
superscript: '위 첨자',
subscript: '아래 첨자',
strikethrough: '취소선',
size: '글자 크기'
},

@@ -13,0 +18,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Linjehøyde',
name: 'Skrifttype'
name: 'Skrifttype',
strikethrough: 'Gjennomstrek',
size: 'Skriftstørrelse'
},

@@ -13,0 +15,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Regelhoogte',
name: 'Lettertype'
name: 'Lettertype',
strikethrough: 'Doorhalen',
size: 'Tekstgrootte'
},

@@ -13,0 +15,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Interlinia',
name: 'Czcionka'
name: 'Czcionka',
strikethrough: 'Przekreślenie',
size: 'Rozmiar'
},

@@ -22,5 +24,12 @@ image: {

floatNone: 'Równo z tekstem',
dragImageHere: 'Przeciągnij grafikę tutaj',
shapeRounded: 'Kształt: zaokrąglone',
shapeCircle: 'Kształt: okrąg',
shapeThumbnail: 'Kształt: miniatura',
shapeNone: 'Kształt: brak',
dragImageHere: 'Przeciągnij grafikę lub tekst tutaj',
dropImage: 'Przeciągnij grafikę lub tekst',
selectFromFiles: 'Wybierz z dysku',
url: 'URL grafiki',
maximumFileSize: 'Limit wielkości pliku',
maximumFileSizeError: 'Przekroczono limit wielkości pliku.',
url: 'Adres URL grafiki',
remove: 'Usuń grafikę'

@@ -34,3 +43,3 @@ },

textToDisplay: 'Tekst do wyświetlenia',
url: 'Na jaki URL powinien przenosić ten link?',
url: 'Na jaki adres URL powinien przenosić ten odnośnik?',
openInNewWindow: 'Otwórz w nowym oknie'

@@ -63,3 +72,3 @@ },

fullscreen: 'Pełny ekran',
codeview: 'Zródło'
codeview: 'Źródło'
},

@@ -86,3 +95,3 @@ paragraph: {

shortcut: {
shortcuts: 'Skróty klawiszone',
shortcuts: 'Skróty klawiaturowe',
close: 'Zamknij',

@@ -92,3 +101,4 @@ textFormatting: 'Formatowanie tekstu',

paragraphFormatting: 'Formatowanie akapitu',
documentStyle: 'Styl dokumentu'
documentStyle: 'Styl dokumentu',
extraKeys: 'Dodatkowe klawisze'
},

@@ -95,0 +105,0 @@ history: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Altura da linha',
name: 'Fonte'
name: 'Fonte',
strikethrough: 'Riscado',
size: 'Tamanho da fonte'
},

@@ -13,0 +15,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: 'Înlătură formatare font',
height: 'Înălțime rând'
height: 'Înălțime rând',
strikethrough: 'Tăiat',
size: 'Dimensiune font'
},

@@ -12,0 +14,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'Высота линии',
name: 'Шрифт'
name: 'Шрифт',
strikethrough: 'Зачёркнутый',
subscript: 'Нижний индекс',
superscript: 'Верхний индекс',
size: 'Размер шрифта'
},

@@ -13,0 +17,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: 'Odstrániť štýl písma',
height: 'Výška riadku'
height: 'Výška riadku',
strikethrough: 'Preškrtnuté',
size: 'Veľkosť písma'
},

@@ -12,0 +14,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'Razmik med vrsticami',
name: 'Pisava'
name: 'Pisava',
strikethrough: 'Prečrtano',
subscript: 'Podpisano',
superscript: 'Nadpisano',
size: 'Velikost pisave'
},

@@ -13,0 +17,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: 'Ukloni stilove fonta',
height: 'Visina linije'
height: 'Visina linije',
strikethrough: 'Precrtano',
size: 'Veličina fonta'
},

@@ -12,0 +14,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: 'Уклони стилове фонта',
height: 'Висина линије'
height: 'Висина линије',
strikethrough: 'Прецртано',
size: 'Величина фонта'
},

@@ -12,0 +14,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Radavstånd',
name: 'Teckensnitt'
name: 'Teckensnitt',
strikethrough: 'Genomstruken',
size: 'Teckenstorlek'
},

@@ -13,0 +15,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'ความสูงบรรทัด',
name: 'แบบตัวอักษร'
name: 'แบบตัวอักษร',
strikethrough: 'ขีดฆ่า',
subscript: 'ตัวห้อย',
superscript: 'ตัวยก',
size: 'ขนาดตัวอักษร'
},

@@ -13,0 +17,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'Satır yüksekliği',
name: 'Yazı Tipi'
name: 'Yazı Tipi',
strikethrough: 'Üstü çizili',
subscript: 'Subscript',
superscript: 'Superscript',
size: 'Yazı tipi boyutu'
},

@@ -13,0 +17,0 @@ image: {

@@ -10,3 +10,7 @@ (function ($) {

height: 'Висота лінії',
name: 'Шрифт'
name: 'Шрифт',
strikethrough: 'Закреслений',
subscript: 'Нижній індекс',
superscript: 'Верхній індекс',
size: 'Розмір шрифту'
},

@@ -13,0 +17,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: 'Khoảng Cách Hàng',
name: 'Phông Chữ'
name: 'Phông Chữ',
strikethrough: 'Gạch Ngang',
size: 'Cỡ Chữ'
},

@@ -13,0 +15,0 @@ image: {

@@ -10,3 +10,5 @@ (function ($) {

height: '行高',
name: '字体'
name: '字体',
strikethrough: '删除线',
size: '字号'
},

@@ -13,0 +15,0 @@ image: {

@@ -9,3 +9,5 @@ (function ($) {

clear: '清除格式',
height: '行高'
height: '行高',
strikethrough: '刪除線',
size: '字體大小'
},

@@ -12,0 +14,0 @@ image: {

{
"name": "summernote",
"description": "Super Simple WYSIWYG Editor on Bootstrap",
"version": "0.6.1",
"version": "0.6.5",
"keywords": [

@@ -23,7 +23,8 @@ "editor",

"grunt-contrib-jshint": "0.7.2",
"grunt-contrib-qunit": "*",
"grunt-contrib-qunit": "0.5.2",
"grunt-contrib-uglify": "~0.2.2",
"grunt-recess": "*",
"grunt-contrib-watch": "*",
"grunt-contrib-connect": "*",
"grunt-contrib-compress": "*",
"grunt-recess": "*",
"grunt-exec": "^0.4.6",

@@ -30,0 +31,0 @@ "connect-livereload": "*"

@@ -11,5 +11,4 @@ (function (factory) {

}(function ($) {
// template, editor
// template
var tmpl = $.summernote.renderer.getTemplate();
var editor = $.summernote.eventHandler.getEditor();

@@ -69,3 +68,3 @@ /**

events: { // events
hello: function (layoutInfo) {
hello: function (event, editor, layoutInfo) {
// Get current editable node

@@ -77,3 +76,3 @@ var $editable = layoutInfo.editable();

},
helloDropdown: function (layoutInfo, value) {
helloDropdown: function (event, editor, layoutInfo, value) {
// Get current editable node

@@ -85,3 +84,3 @@ var $editable = layoutInfo.editable();

},
helloImage : function (layoutInfo) {
helloImage : function (event, editor, layoutInfo) {
var $editable = layoutInfo.editable();

@@ -88,0 +87,0 @@

@@ -11,5 +11,4 @@ (function (factory) {

}(function ($) {
// template, editor
// template
var tmpl = $.summernote.renderer.getTemplate();
var editor = $.summernote.eventHandler.getEditor();

@@ -99,2 +98,3 @@ // core functions: range, dom

// this is not a known video link. Now what, Cat? Now what?
return false;
}

@@ -237,3 +237,3 @@

events: {
showVideoDialog: function (layoutInfo) {
showVideoDialog: function (event, editor, layoutInfo) {
var $dialog = layoutInfo.dialog(),

@@ -251,5 +251,10 @@ $editable = layoutInfo.editable(),

editor.restoreRange($editable);
// insert video node
editor.insertNode($editable, createVideoNode(url));
// build node
var $node = createVideoNode(url);
if ($node) {
// insert video node
editor.insertNode($editable, $node);
}
}).fail(function () {

@@ -256,0 +261,0 @@ // when cancel button clicked

@@ -71,2 +71,3 @@ define([

editor: function () { return $editor; },
holder : function () { return $editor.data('holder'); },
editable: function () { return $editor; },

@@ -85,2 +86,3 @@ popover: makeFinder('#note-popover-'),

editor: function () { return $editor; },
holder : function () { return $editor.data('holder'); },
dropzone: makeFinder('.note-dropzone'),

@@ -99,2 +101,26 @@ toolbar: makeFinder('.note-toolbar'),

/**
* returns makeLayoutInfo from editor's descendant node.
*
* @private
* @param {Node} descendant
* @return {Object}
*/
var makeLayoutInfo = function (descendant) {
var $target = $(descendant).closest('.note-editor, .note-air-editor, .note-air-layout');
if (!$target.length) {
return null;
}
var $editor;
if ($target.is('.note-editor, .note-air-editor')) {
$editor = $target;
} else {
$editor = $('#note-editor-' + list.last($target.attr('id').split('-')));
}
return buildLayoutInfo($editor);
};
/**
* @method makePredByNodeName

@@ -220,2 +246,3 @@ *

* blank HTML for cursor position
* - [workaround] for MSIE IE doesn't works with bogus br
*/

@@ -664,2 +691,17 @@ var blankHTML = agent.isMSIE ? '&nbsp;' : '<br>';

/**
* returns whether point has character or not.
*
* @param {Point} point
* @return {Boolean}
*/
var isCharPoint = function (point) {
if (!isText(point.node)) {
return false;
}
var ch = point.node.nodeValue.charAt(point.offset - 1);
return ch && (ch !== ' ' && ch !== NBSP_CHAR);
};
/**
* @method walkPoint

@@ -728,9 +770,13 @@ *

* @param {BoundaryPoint} point
* @param {Boolean} [isSkipPaddingBlankHTML]
* @param {Object} [options]
* @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
* @param {Boolean} [options.isNotSplitEdgePoint] - default: false
* @return {Node} right node of boundaryPoint
*/
var splitNode = function (point, isSkipPaddingBlankHTML) {
// split #text
if (isText(point.node)) {
// edge case
var splitNode = function (point, options) {
var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML;
var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint;
// edge case
if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) {
if (isLeftEdgePoint(point)) {

@@ -741,17 +787,19 @@ return point.node;

}
}
// split #text
if (isText(point.node)) {
return point.node.splitText(point.offset);
}
} else {
var childNode = point.node.childNodes[point.offset];
var clone = insertAfter(point.node.cloneNode(false), point.node);
appendChildNodes(clone, listNext(childNode));
// split element
var childNode = point.node.childNodes[point.offset];
var clone = insertAfter(point.node.cloneNode(false), point.node);
appendChildNodes(clone, listNext(childNode));
if (!isSkipPaddingBlankHTML) {
paddingBlankHTML(point.node);
paddingBlankHTML(clone);
}
if (!isSkipPaddingBlankHTML) {
paddingBlankHTML(point.node);
paddingBlankHTML(clone);
return clone;
}
return clone;
};

@@ -766,6 +814,8 @@

* @param {BoundaryPoint} point
* @param {Boolean} [isSkipPaddingBlankHTML]
* @param {Object} [options]
* @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
* @param {Boolean} [options.isNotSplitEdgePoint] - default: false
* @return {Node} right node of boundaryPoint
*/
var splitTree = function (root, point, isSkipPaddingBlankHTML) {
var splitTree = function (root, point, options) {
// ex) [#text, <span>, <p>]

@@ -777,19 +827,14 @@ var ancestors = listAncestor(point.node, func.eq(root));

} else if (ancestors.length === 1) {
return splitNode(point, isSkipPaddingBlankHTML);
return splitNode(point, options);
}
return ancestors.reduce(function (node, parent) {
var clone = insertAfter(parent.cloneNode(false), parent);
if (node === point.node) {
node = splitNode(point, isSkipPaddingBlankHTML);
node = splitNode(point, options);
}
appendChildNodes(clone, listNext(node));
if (!isSkipPaddingBlankHTML) {
paddingBlankHTML(parent);
paddingBlankHTML(clone);
}
return clone;
return splitNode({
node: parent,
offset: node ? dom.position(node) : nodeLength(parent)
}, options);
});

@@ -822,5 +867,13 @@ };

// split with splitTree
var pivot = splitRoot && splitTree(splitRoot, point, isInline);
// if splitRoot is exists, split with splitTree
var pivot = splitRoot && splitTree(splitRoot, point, {
isSkipPaddingBlankHTML: isInline,
isNotSplitEdgePoint: isInline
});
// if container is point.node, find pivot with point.offset
if (!pivot && container === point.node) {
pivot = point.node.childNodes[point.offset];
}
return {

@@ -916,2 +969,14 @@ rightNode: pivot,

/**
* @param {jQuery} $node
* @param {Boolean} [stripLinebreaks] - default: false
*/
var value = function ($node, stripLinebreaks) {
var val = isTextarea($node[0]) ? $node.val() : $node.html();
if (stripLinebreaks) {
return val.replace(/[\n\r]/g, '');
}
return val;
};
/**
* @method html

@@ -925,3 +990,3 @@ *

var html = function ($node, isNewlineOnBlock) {
var markup = isTextarea($node[0]) ? $node.val() : $node.html();
var markup = value($node);

@@ -944,10 +1009,2 @@ if (isNewlineOnBlock) {

var value = function ($textarea, stripLinebreaks) {
var val = $textarea.val();
if (stripLinebreaks) {
return val.replace(/[\n\r]/g, '');
}
return val;
};
return {

@@ -966,2 +1023,3 @@ /** @property {String} NBSP_CHAR */

buildLayoutInfo: buildLayoutInfo,
makeLayoutInfo: makeLayoutInfo,
isText: isText,

@@ -972,2 +1030,3 @@ isVoid: isVoid,

isInline: isInline,
isBlock: func.not(isInline),
isBodyInline: isBodyInline,

@@ -1008,2 +1067,3 @@ isBody: isBody,

nextPointUntil: nextPointUntil,
isCharPoint: isCharPoint,
walkPoint: walkPoint,

@@ -1010,0 +1070,0 @@ ancestor: ancestor,

@@ -101,2 +101,14 @@ define('summernote/core/func', function () {

/**
* @param {String} namespace
* @param {String} [prefix]
* @return {String}
*/
var namespaceToCamel = function (namespace, prefix) {
prefix = prefix || '';
return prefix + namespace.split('.').map(function (name) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
}).join('');
};
return {

@@ -113,3 +125,4 @@ eq: eq,

rect2bnd: rect2bnd,
invertObject: invertObject
invertObject: invertObject,
namespaceToCamel: namespaceToCamel
};

@@ -116,0 +129,0 @@ })();

define([
'summernote/core/list'
], function (list) {
'summernote/core/list',
'summernote/core/func'
], function (list, func) {
/**

@@ -12,54 +13,59 @@ * @class core.key

*/
var key = {
/**
* @method isEdit
*
* @param {Number} keyCode
* @return {Boolean}
*/
isEdit: function (keyCode) {
return list.contains([8, 9, 13, 32], keyCode);
},
/**
* @property {Object} nameFromCode
* @property {String} nameFromCode.8 "BACKSPACE"
*/
nameFromCode: {
'8': 'BACKSPACE',
'9': 'TAB',
'13': 'ENTER',
'32': 'SPACE',
var key = (function () {
var keyMap = {
'BACKSPACE': 8,
'TAB': 9,
'ENTER': 13,
'SPACE': 32,
// Number: 0-9
'48': 'NUM0',
'49': 'NUM1',
'50': 'NUM2',
'51': 'NUM3',
'52': 'NUM4',
'53': 'NUM5',
'54': 'NUM6',
'55': 'NUM7',
'56': 'NUM8',
'NUM0': 48,
'NUM1': 49,
'NUM2': 50,
'NUM3': 51,
'NUM4': 52,
'NUM5': 53,
'NUM6': 54,
'NUM7': 55,
'NUM8': 56,
// Alphabet: a-z
'66': 'B',
'69': 'E',
'73': 'I',
'74': 'J',
'75': 'K',
'76': 'L',
'82': 'R',
'83': 'S',
'85': 'U',
'89': 'Y',
'90': 'Z',
'B': 66,
'E': 69,
'I': 73,
'J': 74,
'K': 75,
'L': 76,
'R': 82,
'S': 83,
'U': 85,
'Y': 89,
'Z': 90,
'191': 'SLASH',
'219': 'LEFTBRACKET',
'220': 'BACKSLASH',
'221': 'RIGHTBRACKET'
}
};
'SLASH': 191,
'LEFTBRACKET': 219,
'BACKSLASH': 220,
'RIGHTBRACKET': 221
};
return {
/**
* @method isEdit
*
* @param {Number} keyCode
* @return {Boolean}
*/
isEdit: function (keyCode) {
return list.contains([8, 9, 13, 32], keyCode);
},
/**
* @property {Object} nameFromCode
* @property {String} nameFromCode.8 "BACKSPACE"
*/
nameFromCode: func.invertObject(keyMap),
code: keyMap
};
})();
return key;
});

@@ -186,7 +186,33 @@ define([

}
return this;
};
/**
* Moves the scrollbar to start container(sc) of current range
*
* @return {WrappedRange}
*/
this.scrollIntoView = function () {
if (this.sc.scrollIntoView) {
this.sc.scrollIntoView(false);
}
return this;
};
/**
* set a focus into start container of current range
*
* @return {WrappedRange}
*/
this.focus = function () {
this.sc.focus();
return this;
};
/**
* @return {WrappedRange}
*/
this.normalize = function () {

@@ -491,2 +517,17 @@

};
/**
* insert html at current cursor
*/
this.pasteHTML = function (markup) {
var self = this;
var contentsContainer = $('<div></div>').html(markup)[0];
var childNodes = list.from(contentsContainer.childNodes);
this.wrapBodyInlineWithPara().deleteContents();
return $.map(childNodes.reverse(), function (childNode) {
return self.insertNode(childNode);
}).reverse();
};

@@ -502,2 +543,33 @@ /**

};
/**
* returns range for word before cursor
*
* @param {Boolean} [findAfter] - find after cursor, default: false
* @return {WrappedRange}
*/
this.getWordRange = function (findAfter) {
var endPoint = this.getEndPoint();
if (!dom.isCharPoint(endPoint)) {
return this;
}
var startPoint = dom.prevPointUntil(endPoint, function (point) {
return !dom.isCharPoint(point);
});
if (findAfter) {
endPoint = dom.nextPointUntil(endPoint, function (point) {
return !dom.isCharPoint(point);
});
}
return new WrappedRange(
startPoint.node,
startPoint.offset,
endPoint.node,
endPoint.offset
);
};

@@ -504,0 +576,0 @@ /**

@@ -190,3 +190,5 @@ define([

offset: dom.position(last) + 1
}, true) : null;
}, {
isSkipPaddingBlankHTML: true
}) : null;

@@ -196,3 +198,5 @@ var middleList = dom.splitTree(headList, {

offset: dom.position(head)
}, true);
}, {
isSkipPaddingBlankHTML: true
});

@@ -199,0 +203,0 @@ paras = isEscapseToBody ? dom.listDescendant(middleList, dom.isLi) :

@@ -14,3 +14,3 @@ define(['summernote/core/range'], function (range) {

var rng = range.create();
var emptyBookmark = {s: {path: [0], offset: 0}, e: {path: [0], offset: 0}};
var emptyBookmark = {s: {path: [], offset: 0}, e: {path: [], offset: 0}};

@@ -17,0 +17,0 @@ return {

@@ -17,2 +17,3 @@ define([

*
* [workaround] for old jQuery
* passing an array of style properties to .css()

@@ -19,0 +20,0 @@ * will result in an object of property-value pairs.

define([
'summernote/core/dom',
'summernote/core/range'
], function (dom, range) {
'summernote/core/range',
'summernote/editing/Bullet'
], function (dom, range, Bullet) {

@@ -14,2 +15,5 @@ /**

// a Bullet instance to toggle lists off
var bullet = new Bullet();
/**

@@ -49,10 +53,18 @@ * insert tab

if (splitRoot) {
nextPara = dom.splitTree(splitRoot, rng.getStartPoint());
// if it is an empty line with li
if (dom.isEmpty(splitRoot) && dom.isLi(splitRoot)) {
// disable UL/OL and escape!
bullet.toggleList(splitRoot.parentNode.nodeName);
return;
// if new line has content (not a line break)
} else {
nextPara = dom.splitTree(splitRoot, rng.getStartPoint());
var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);
emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));
var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);
emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));
$.each(emptyAnchors, function (idx, anchor) {
dom.remove(anchor);
});
$.each(emptyAnchors, function (idx, anchor) {
dom.remove(anchor);
});
}
// no paragraph: insert empty paragraph

@@ -69,3 +81,4 @@ } else {

range.create(nextPara, 0).normalize().select();
range.create(nextPara, 0).normalize().select().focus().scrollIntoView();
};

@@ -72,0 +85,0 @@

define([
'summernote/core/agent', 'summernote/core/dom', 'summernote/core/async', 'summernote/core/key', 'summernote/core/list',
'summernote/editing/Style', 'summernote/editing/Editor', 'summernote/editing/History',
'summernote/module/Toolbar', 'summernote/module/Popover', 'summernote/module/Handle', 'summernote/module/Dialog'
], function (agent, dom, async, key, list,
Style, Editor, History,
Toolbar, Popover, Handle, Dialog) {
'summernote/core/agent',
'summernote/core/func',
'summernote/core/dom',
'summernote/core/async',
'summernote/core/key',
'summernote/core/list',
'summernote/editing/History',
'summernote/module/Editor',
'summernote/module/Toolbar',
'summernote/module/Statusbar',
'summernote/module/Popover',
'summernote/module/Handle',
'summernote/module/Fullscreen',
'summernote/module/Codeview',
'summernote/module/DragAndDrop',
'summernote/module/Clipboard',
'summernote/module/LinkDialog',
'summernote/module/ImageDialog',
'summernote/module/HelpDialog'
], function (agent, func, dom, async, key, list, History,
Editor, Toolbar, Statusbar, Popover, Handle, Fullscreen, Codeview,
DragAndDrop, Clipboard, LinkDialog, ImageDialog, HelpDialog) {
var CodeMirror;
if (agent.hasCodeMirror) {
if (agent.isSupportAmd) {
require(['CodeMirror'], function (cm) {
CodeMirror = cm;
});
} else {
CodeMirror = window.CodeMirror;
}
}
/**

@@ -24,40 +29,65 @@ * @class EventHandler

* EventHandler
* - TODO: new instance per a editor
* - TODO: rename EventHandler
*/
var EventHandler = function () {
var $window = $(window);
var $document = $(document);
var $scrollbar = $('html, body');
/**
* Modules
*/
var modules = this.modules = {
editor: new Editor(this),
toolbar: new Toolbar(this),
statusbar: new Statusbar(this),
popover: new Popover(this),
handle: new Handle(this),
fullscreen: new Fullscreen(this),
codeview: new Codeview(this),
dragAndDrop: new DragAndDrop(this),
clipboard: new Clipboard(this),
linkDialog: new LinkDialog(this),
imageDialog: new ImageDialog(this),
helpDialog: new HelpDialog(this)
};
var editor = new Editor();
var toolbar = new Toolbar(), popover = new Popover();
var handle = new Handle(), dialog = new Dialog();
// TODO refactor modules and eventHandler
// - remove this method and use custom event from $holder instead
this.invoke = function () {
var moduleAndMethod = list.head(list.from(arguments));
var args = list.tail(list.from(arguments));
var splits = moduleAndMethod.split('.');
var hasSeparator = splits.length > 1;
var moduleName = hasSeparator && list.head(splits);
var methodName = hasSeparator ? list.last(splits) : list.head(splits);
var module = this.getModule(moduleName);
var method = module[methodName];
return method && method.apply(module, args);
};
/**
* get editor
* @returns {editing.Editor}
* returns module
*
* @param {String} moduleName - name of module
* @return {Module} - defaults is editor
*/
this.getEditor = function () {
return editor;
this.getModule = function (moduleName) {
return this.modules[moduleName] || this.modules.editor;
};
/**
* returns makeLayoutInfo from editor's descendant node.
*
* @private
* @param {Node} descendant
* @return {Object}
* @param {jQuery} $holder
* @param {Object} callbacks
* @param {String} eventNamespace
* @returns {Function}
*/
var makeLayoutInfo = function (descendant) {
var $target = $(descendant).closest('.note-editor, .note-air-editor, .note-air-layout');
if (!$target.length) { return null; }
var $editor;
if ($target.is('.note-editor, .note-air-editor')) {
$editor = $target;
} else {
$editor = $('#note-editor-' + list.last($target.attr('id').split('-')));
}
return dom.buildLayoutInfo($editor);
var bindCustomEvent = this.bindCustomEvent = function ($holder, callbacks, eventNamespace) {
return function () {
var callback = callbacks[func.namespaceToCamel(eventNamespace, 'on')];
if (callback) {
callback(arguments);
}
return $holder.trigger('summernote.' + eventNamespace, arguments);
};
};

@@ -72,5 +102,6 @@

*/
var insertImages = function (layoutInfo, files) {
this.insertImages = function (layoutInfo, files) {
var $editor = layoutInfo.editor(),
$editable = layoutInfo.editable();
$editable = layoutInfo.editable(),
$holder = layoutInfo.holder();

@@ -82,3 +113,3 @@ var callbacks = $editable.data('callbacks');

if (callbacks.onImageUpload) {
callbacks.onImageUpload(files, editor, $editable);
bindCustomEvent($holder, callbacks, 'image.upload')([files]);
// else insert Image as dataURL

@@ -89,14 +120,8 @@ } else {

if (options.maximumImageFileSize && options.maximumImageFileSize < file.size) {
if (callbacks.onImageUploadError) {
callbacks.onImageUploadError(options.langInfo.image.maximumFileSizeError);
} else {
alert(options.langInfo.image.maximumFileSizeError);
}
bindCustomEvent($holder, callbacks, 'image.upload.error')(options.langInfo.image.maximumFileSizeError);
} else {
async.readFileAsDataURL(file).then(function (sDataURL) {
editor.insertImage($editable, sDataURL, filename);
modules.editor.insertImage($editable, sDataURL, filename);
}).fail(function () {
if (callbacks.onImageUploadError) {
callbacks.onImageUploadError();
}
bindCustomEvent($holder, callbacks, 'image.upload.error')(options.langInfo.image.maximumFileSizeError);
});

@@ -113,18 +138,3 @@ }

showLinkDialog: function (layoutInfo) {
var $editor = layoutInfo.editor(),
$dialog = layoutInfo.dialog(),
$editable = layoutInfo.editable(),
linkInfo = editor.getLinkInfo($editable);
var options = $editor.data('options');
editor.saveRange($editable);
dialog.showLinkDialog($editable, $dialog, linkInfo).then(function (linkInfo) {
editor.restoreRange($editable);
editor.createLink($editable, linkInfo, options);
// hide popover after creating link
popover.hide(layoutInfo.popover());
}).fail(function () {
editor.restoreRange($editable);
});
modules.linkDialog.show(layoutInfo);
},

@@ -136,19 +146,3 @@

showImageDialog: function (layoutInfo) {
var $dialog = layoutInfo.dialog(),
$editable = layoutInfo.editable();
editor.saveRange($editable);
dialog.showImageDialog($editable, $dialog).then(function (data) {
editor.restoreRange($editable);
if (typeof data === 'string') {
// image url
editor.insertImage($editable, data);
} else {
// array of files
insertImages(layoutInfo, data);
}
}).fail(function () {
editor.restoreRange($editable);
});
modules.imageDialog.show(layoutInfo);
},

@@ -160,104 +154,17 @@

showHelpDialog: function (layoutInfo) {
var $dialog = layoutInfo.dialog(),
$editable = layoutInfo.editable();
editor.saveRange($editable, true);
dialog.showHelpDialog($editable, $dialog).then(function () {
editor.restoreRange($editable);
});
modules.helpDialog.show(layoutInfo);
},
/**
* @param {Object} layoutInfo
*/
fullscreen: function (layoutInfo) {
var $editor = layoutInfo.editor(),
$toolbar = layoutInfo.toolbar(),
$editable = layoutInfo.editable(),
$codable = layoutInfo.codable();
var resize = function (size) {
$editable.css('height', size.h);
$codable.css('height', size.h);
if ($codable.data('cmeditor')) {
$codable.data('cmeditor').setsize(null, size.h);
}
};
$editor.toggleClass('fullscreen');
var isFullscreen = $editor.hasClass('fullscreen');
if (isFullscreen) {
$editable.data('orgheight', $editable.css('height'));
$window.on('resize', function () {
resize({
h: $window.height() - $toolbar.outerHeight()
});
}).trigger('resize');
$scrollbar.css('overflow', 'hidden');
} else {
$window.off('resize');
resize({
h: $editable.data('orgheight')
});
$scrollbar.css('overflow', 'visible');
}
toolbar.updateFullscreen($toolbar, isFullscreen);
modules.fullscreen.toggle(layoutInfo);
},
/**
* @param {Object} layoutInfo
*/
codeview: function (layoutInfo) {
var $editor = layoutInfo.editor(),
$toolbar = layoutInfo.toolbar(),
$editable = layoutInfo.editable(),
$codable = layoutInfo.codable(),
$popover = layoutInfo.popover(),
$handle = layoutInfo.handle();
var options = $editor.data('options');
var cmEditor, server;
$editor.toggleClass('codeview');
var isCodeview = $editor.hasClass('codeview');
if (isCodeview) {
$codable.val(dom.html($editable, options.prettifyHtml));
$codable.height($editable.height());
toolbar.deactivate($toolbar);
popover.hide($popover);
handle.hide($handle);
$codable.focus();
// activate CodeMirror as codable
if (agent.hasCodeMirror) {
cmEditor = CodeMirror.fromTextArea($codable[0], options.codemirror);
// CodeMirror TernServer
if (options.codemirror.tern) {
server = new CodeMirror.TernServer(options.codemirror.tern);
cmEditor.ternServer = server;
cmEditor.on('cursorActivity', function (cm) {
server.updateArgHints(cm);
});
}
// CodeMirror hasn't Padding.
cmEditor.setSize(null, $editable.outerHeight());
$codable.data('cmEditor', cmEditor);
}
} else {
// deactivate CodeMirror as codable
if (agent.hasCodeMirror) {
cmEditor = $codable.data('cmEditor');
$codable.val(cmEditor.getValue());
cmEditor.toTextArea();
}
$editable.html(dom.value($codable, options.prettifyHtml) || dom.emptyPara);
$editable.height(options.height ? $codable.height() : 'auto');
toolbar.activate($toolbar);
$editable.focus();
}
toolbar.updateCodeview(layoutInfo.toolbar(), isCodeview);
modules.codeview.toggle(layoutInfo);
}

@@ -276,4 +183,4 @@ };

setTimeout(function () {
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
var styleInfo = editor.currentStyle(event.target);
var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
var styleInfo = modules.editor.currentStyle(event.target);
if (!styleInfo) { return; }

@@ -283,7 +190,7 @@

if (!isAirMode) {
toolbar.update(layoutInfo.toolbar(), styleInfo);
modules.toolbar.update(layoutInfo.toolbar(), styleInfo);
}
popover.update(layoutInfo.popover(), styleInfo, isAirMode);
handle.update(layoutInfo.handle(), styleInfo, isAirMode);
modules.popover.update(layoutInfo.popover(), styleInfo, isAirMode);
modules.handle.update(layoutInfo.handle(), styleInfo, isAirMode);
}, 0);

@@ -293,105 +200,8 @@ };

var hScroll = function (event) {
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
//hide popover and handle when scrolled
popover.hide(layoutInfo.popover());
handle.hide(layoutInfo.handle());
modules.popover.hide(layoutInfo.popover());
modules.handle.hide(layoutInfo.handle());
};
/**
* paste clipboard image
*
* @param {Event} event
*/
var hPasteClipboardImage = function (event) {
var clipboardData = event.originalEvent.clipboardData;
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
var $editable = layoutInfo.editable();
if (!clipboardData || !clipboardData.items || !clipboardData.items.length) {
var callbacks = $editable.data('callbacks');
// only can run if it has onImageUpload method
if (!callbacks.onImageUpload) {
return;
}
// save cursor
editor.saveNode($editable);
editor.saveRange($editable);
$editable.html('');
setTimeout(function () {
var $img = $editable.find('img');
var datauri = $img[0].src;
var data = atob(datauri.split(',')[1]);
var array = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++) {
array[i] = data.charCodeAt(i);
}
var blob = new Blob([array], { type : 'image/png'});
blob.name = 'clipboard.png';
editor.restoreNode($editable);
editor.restoreRange($editable);
insertImages(layoutInfo, [blob]);
editor.afterCommand($editable);
}, 0);
return;
}
var item = list.head(clipboardData.items);
var isClipboardImage = item.kind === 'file' && item.type.indexOf('image/') !== -1;
if (isClipboardImage) {
insertImages(layoutInfo, [item.getAsFile()]);
}
editor.afterCommand($editable);
};
/**
* `mousedown` event handler on $handle
* - controlSizing: resize image
*
* @param {MouseEvent} event
*/
var hHandleMousedown = function (event) {
if (dom.isControlSizing(event.target)) {
event.preventDefault();
event.stopPropagation();
var layoutInfo = makeLayoutInfo(event.target),
$handle = layoutInfo.handle(), $popover = layoutInfo.popover(),
$editable = layoutInfo.editable(),
$editor = layoutInfo.editor();
var target = $handle.find('.note-control-selection').data('target'),
$target = $(target), posStart = $target.offset(),
scrollTop = $document.scrollTop();
var isAirMode = $editor.data('options').airMode;
$document.on('mousemove', function (event) {
editor.resizeTo({
x: event.clientX - posStart.left,
y: event.clientY - (posStart.top - scrollTop)
}, $target, !event.shiftKey);
handle.update($handle, {image: target}, isAirMode);
popover.update($popover, {image: target}, isAirMode);
}).one('mouseup', function () {
$document.off('mousemove');
editor.afterCommand($editable);
});
if (!$target.data('ratio')) { // original ratio.
$target.data('ratio', $target.height() / $target.width());
}
}
};
var hToolbarAndPopoverMousedown = function (event) {

@@ -413,3 +223,3 @@ // prevent default event when insertTable (FF, Webkit)

var layoutInfo = makeLayoutInfo(event.target);
var layoutInfo = dom.makeLayoutInfo(event.target);

@@ -430,7 +240,7 @@ // before command: detect control selection element($target)

if ($.isFunction($.summernote.pluginEvents[eventName])) {
$.summernote.pluginEvents[eventName](event, editor, layoutInfo, value);
} else if (editor[eventName]) { // on command
$.summernote.pluginEvents[eventName](event, modules.editor, layoutInfo, value);
} else if (modules.editor[eventName]) { // on command
var $editable = layoutInfo.editable();
$editable.trigger('focus');
editor[eventName]($editable, value, $target);
$editable.focus();
modules.editor[eventName]($editable, value, $target);
event.preventDefault();

@@ -445,3 +255,3 @@ } else if (commands[eventName]) {

var options = layoutInfo.editor().data('options', options);
var module = options.airMode ? popover : toolbar;
var module = options.airMode ? modules.popover : modules.toolbar;
module.updateRecentColor(list.head($btn), eventName, value);

@@ -454,30 +264,2 @@ }

var EDITABLE_PADDING = 24;
/**
* `mousedown` event handler on statusbar
*
* @param {MouseEvent} event
*/
var hStatusbarMousedown = function (event) {
event.preventDefault();
event.stopPropagation();
var $editable = makeLayoutInfo(event.target).editable();
var nEditableTop = $editable.offset().top - $document.scrollTop();
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
var options = layoutInfo.editor().data('options');
$document.on('mousemove', function (event) {
var nHeight = event.clientY - (nEditableTop + EDITABLE_PADDING);
nHeight = (options.minHeight > 0) ? Math.max(nHeight, options.minHeight) : nHeight;
nHeight = (options.maxHeight > 0) ? Math.min(nHeight, options.maxHeight) : nHeight;
$editable.height(nHeight);
}).one('mouseup', function () {
$document.off('mousemove');
});
};
var PX_PER_EM = 18;

@@ -524,88 +306,4 @@ var hDimensionPickerMove = function (event, options) {

};
/**
* Drag and Drop Events
*
* @param {Object} layoutInfo - layout Informations
* @param {Object} options
*/
var handleDragAndDropEvent = function (layoutInfo, options) {
if (options.disableDragAndDrop) {
// prevent default drop event
$document.on('drop', function (e) {
e.preventDefault();
});
} else {
attachDragAndDropEvent(layoutInfo, options);
}
};
/**
* attach Drag and Drop Events
*
* @param {Object} layoutInfo - layout Informations
* @param {Object} options
*/
var attachDragAndDropEvent = function (layoutInfo, options) {
var collection = $(),
$dropzone = layoutInfo.dropzone,
$dropzoneMessage = layoutInfo.dropzone.find('.note-dropzone-message');
// show dropzone on dragenter when dragging a object to document
// -but only if the editor is visible, i.e. has a positive width and height
$document.on('dragenter', function (e) {
var isCodeview = layoutInfo.editor.hasClass('codeview');
if (!isCodeview && !collection.length && layoutInfo.editor.width() > 0 && layoutInfo.editor.height() > 0) {
layoutInfo.editor.addClass('dragover');
$dropzone.width(layoutInfo.editor.width());
$dropzone.height(layoutInfo.editor.height());
$dropzoneMessage.text(options.langInfo.image.dragImageHere);
}
collection = collection.add(e.target);
}).on('dragleave', function (e) {
collection = collection.not(e.target);
if (!collection.length) {
layoutInfo.editor.removeClass('dragover');
}
}).on('drop', function () {
collection = $();
layoutInfo.editor.removeClass('dragover');
});
// change dropzone's message on hover.
$dropzone.on('dragenter', function () {
$dropzone.addClass('hover');
$dropzoneMessage.text(options.langInfo.image.dropImage);
}).on('dragleave', function () {
$dropzone.removeClass('hover');
$dropzoneMessage.text(options.langInfo.image.dragImageHere);
});
// attach dropImage
$dropzone.on('drop', function (event) {
event.preventDefault();
var dataTransfer = event.originalEvent.dataTransfer;
var html = dataTransfer.getData('text/html');
var text = dataTransfer.getData('text/plain');
var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
layoutInfo.editable().focus();
insertImages(layoutInfo, dataTransfer.files);
} else if (html) {
$(html).each(function () {
layoutInfo.editable().focus();
editor.insertNode(layoutInfo.editable(), this);
});
} else if (text) {
layoutInfo.editable().focus();
editor.insertText(layoutInfo.editable(), text);
}
}).on('dragover', false); // prevent default dragover event
};
/**
* bind KeyMap on keydown

@@ -617,20 +315,20 @@ *

this.bindKeyMap = function (layoutInfo, keyMap) {
var $editor = layoutInfo.editor;
var $editable = layoutInfo.editable;
var $editor = layoutInfo.editor();
var $editable = layoutInfo.editable();
layoutInfo = makeLayoutInfo($editable);
$editable.on('keydown', function (event) {
var aKey = [];
var keys = [];
// modifier
if (event.metaKey) { aKey.push('CMD'); }
if (event.ctrlKey && !event.altKey) { aKey.push('CTRL'); }
if (event.shiftKey) { aKey.push('SHIFT'); }
if (event.metaKey) { keys.push('CMD'); }
if (event.ctrlKey && !event.altKey) { keys.push('CTRL'); }
if (event.shiftKey) { keys.push('SHIFT'); }
// keycode
var keyName = key.nameFromCode[event.keyCode];
if (keyName) { aKey.push(keyName); }
if (keyName) {
keys.push(keyName);
}
var eventName = keyMap[aKey.join('+')];
var eventName = keyMap[keys.join('+')];
if (eventName) {

@@ -640,6 +338,6 @@ if ($.summernote.pluginEvents[eventName]) {

if ($.isFunction(plugin)) {
plugin(event, editor, layoutInfo);
plugin(event, modules.editor, layoutInfo);
}
} else if (editor[eventName]) {
editor[eventName]($editable, $editor.data('options'));
} else if (modules.editor[eventName]) {
modules.editor[eventName]($editable, $editor.data('options'));
event.preventDefault();

@@ -651,3 +349,3 @@ } else if (commands[eventName]) {

} else if (key.isEdit(event.keyCode)) {
editor.afterCommand($editable);
modules.editor.afterCommand($editable);
}

@@ -662,10 +360,2 @@ });

* @param {Object} options - user options include custom event handlers
* @param {function(event)} [options.onenter] - enter key handler
* @param {function(event)} [options.onfocus]
* @param {function(event)} [options.onblur]
* @param {function(event)} [options.onkeyup]
* @param {function(event)} [options.onkeydown]
* @param {function(event)} [options.onpaste]
* @param {function(event)} [options.onToolBarclick]
* @param {function(event)} [options.onChange]
*/

@@ -677,30 +367,28 @@ this.attach = function (layoutInfo, options) {

}
layoutInfo.editable.on('mousedown', hMousedown);
layoutInfo.editable.on('keyup mouseup', hToolbarAndPopoverUpdate);
layoutInfo.editable.on('scroll', hScroll);
layoutInfo.editable.on('paste', hPasteClipboardImage);
layoutInfo.editable().on('mousedown', hMousedown);
layoutInfo.editable().on('keyup mouseup', hToolbarAndPopoverUpdate);
layoutInfo.editable().on('scroll', hScroll);
modules.clipboard.attach(layoutInfo, options);
// handler for handle and popover
layoutInfo.handle.on('mousedown', hHandleMousedown);
layoutInfo.popover.on('click', hToolbarAndPopoverClick);
layoutInfo.popover.on('mousedown', hToolbarAndPopoverMousedown);
modules.handle.attach(layoutInfo, options);
layoutInfo.popover().on('click', hToolbarAndPopoverClick);
layoutInfo.popover().on('mousedown', hToolbarAndPopoverMousedown);
// handler for drag and drop
modules.dragAndDrop.attach(layoutInfo, options);
// handlers for frame mode (toolbar, statusbar)
if (!options.airMode) {
// handler for drag and drop
handleDragAndDropEvent(layoutInfo, options);
// handler for toolbar
layoutInfo.toolbar.on('click', hToolbarAndPopoverClick);
layoutInfo.toolbar.on('mousedown', hToolbarAndPopoverMousedown);
layoutInfo.toolbar().on('click', hToolbarAndPopoverClick);
layoutInfo.toolbar().on('mousedown', hToolbarAndPopoverMousedown);
// handler for statusbar
if (!options.disableResizeEditor) {
layoutInfo.statusbar.on('mousedown', hStatusbarMousedown);
}
modules.statusbar.attach(layoutInfo, options);
}
// handler for table dimension
var $catcherContainer = options.airMode ? layoutInfo.popover :
layoutInfo.toolbar;
var $catcherContainer = options.airMode ? layoutInfo.popover() :
layoutInfo.toolbar();
var $catcher = $catcherContainer.find('.note-dimension-picker-mousecatcher');

@@ -715,7 +403,8 @@ $catcher.css({

// save options on editor
layoutInfo.editor.data('options', options);
layoutInfo.editor().data('options', options);
// ret styleWithCSS for backColor / foreColor clearing with 'inherit'.
if (!agent.isMSIE) {
// protect FF Error: NS_ERROR_FAILURE: Failure
// [workaround] for Firefox
// - protect FF Error: NS_ERROR_FAILURE: Failure
setTimeout(function () {

@@ -727,59 +416,108 @@ document.execCommand('styleWithCSS', 0, options.styleWithSpan);

// History
var history = new History(layoutInfo.editable);
layoutInfo.editable.data('NoteHistory', history);
var history = new History(layoutInfo.editable());
layoutInfo.editable().data('NoteHistory', history);
// basic event callbacks (lowercase)
// enter, focus, blur, keyup, keydown
if (options.onenter) {
layoutInfo.editable.keypress(function (event) {
if (event.keyCode === key.ENTER) { options.onenter(event); }
// All editor status will be saved on editable with jquery's data
// for support multiple editor with singleton object.
layoutInfo.editable().data('callbacks', {
onInit: options.onInit,
onFocus: options.onFocus,
onBlur: options.onBlur,
onKeydown: options.onKeydown,
onKeyup: options.onKeyup,
onMousedown: options.onMousedown,
onEnter: options.onEnter,
onPaste: options.onPaste,
onBeforeCommand: options.onBeforeCommand,
onChange: options.onChange,
onImageUpload: options.onImageUpload,
onImageUploadError: options.onImageUploadError,
onMediaDelete : options.onMediaDelete
});
// Textarea: auto filling the code before form submit.
if (dom.isTextarea(list.head(layoutInfo.holder()))) {
layoutInfo.holder().closest('form').submit(function () {
var contents = layoutInfo.holder().code();
layoutInfo.holder().val(contents);
// callback on submit
if (options.onsubmit) {
options.onsubmit(contents);
}
});
}
};
if (options.onfocus) { layoutInfo.editable.focus(options.onfocus); }
if (options.onblur) { layoutInfo.editable.blur(options.onblur); }
if (options.onkeyup) { layoutInfo.editable.keyup(options.onkeyup); }
if (options.onkeydown) { layoutInfo.editable.keydown(options.onkeydown); }
if (options.onpaste) { layoutInfo.editable.on('paste', options.onpaste); }
/**
* attach jquery custom event
*
* @param {Object} layoutInfo - layout Informations
*/
this.attachCustomEvent = function (layoutInfo, options) {
var $holder = layoutInfo.holder();
var $editable = layoutInfo.editable();
var callbacks = $editable.data('callbacks');
$editable.focus(bindCustomEvent($holder, callbacks, 'focus'));
$editable.blur(bindCustomEvent($holder, callbacks, 'blur'));
$editable.keydown(function (event) {
if (event.keyCode === key.code.ENTER) {
bindCustomEvent($holder, callbacks, 'enter').call(this, event);
}
bindCustomEvent($holder, callbacks, 'keydown').call(this, event);
});
$editable.keyup(bindCustomEvent($holder, callbacks, 'keyup'));
$editable.on('mousedown', bindCustomEvent($holder, callbacks, 'mousedown'));
$editable.on('mouseup', bindCustomEvent($holder, callbacks, 'mouseup'));
$editable.on('scroll', bindCustomEvent($holder, callbacks, 'scroll'));
$editable.on('paste', bindCustomEvent($holder, callbacks, 'paste'));
// [workaround] for old IE - IE8 don't have input events
if (agent.isMSIE) {
var sDomEvents = 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted';
$editable.on(sDomEvents, bindCustomEvent($holder, callbacks, 'change'));
} else {
$editable.on('input', bindCustomEvent($holder, callbacks, 'change'));
}
// callbacks for advanced features (camel)
if (options.onToolbarClick) { layoutInfo.toolbar.click(options.onToolbarClick); }
if (options.onChange) {
var hChange = function () {
editor.triggerOnChange(layoutInfo.editable);
};
if (!options.airMode) {
layoutInfo.toolbar().click(bindCustomEvent($holder, callbacks, 'toolbar.click'));
layoutInfo.popover().click(bindCustomEvent($holder, callbacks, 'popover.click'));
}
if (agent.isMSIE) {
var sDomEvents = 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted';
layoutInfo.editable.on(sDomEvents, hChange);
} else {
layoutInfo.editable.on('input', hChange);
// Textarea: auto filling the code before form submit.
if (dom.isTextarea(list.head($holder))) {
$holder.closest('form').submit(function (e) {
bindCustomEvent($holder, callbacks, 'submit').call(this, e, $holder.code());
});
}
// fire init event
bindCustomEvent($holder, callbacks, 'init')(layoutInfo);
// fire plugin init event
for (var i = 0, len = $.summernote.plugins.length; i < len; i++) {
if ($.isFunction($.summernote.plugins[i].init)) {
$.summernote.plugins[i].init(layoutInfo);
}
}
// All editor status will be saved on editable with jquery's data
// for support multiple editor with singleton object.
layoutInfo.editable.data('callbacks', {
onBeforeChange: options.onBeforeChange,
onChange: options.onChange,
onAutoSave: options.onAutoSave,
onImageUpload: options.onImageUpload,
onImageUploadError: options.onImageUploadError,
onFileUpload: options.onFileUpload,
onFileUploadError: options.onFileUpload,
onMediaDelete : options.onMediaDelete
});
};
this.detach = function (layoutInfo, options) {
layoutInfo.editable.off();
layoutInfo.holder().off();
layoutInfo.editable().off();
layoutInfo.popover.off();
layoutInfo.handle.off();
layoutInfo.dialog.off();
layoutInfo.popover().off();
layoutInfo.handle().off();
layoutInfo.dialog().off();
if (!options.airMode) {
layoutInfo.dropzone.off();
layoutInfo.toolbar.off();
layoutInfo.statusbar.off();
layoutInfo.dropzone().off();
layoutInfo.toolbar().off();
layoutInfo.statusbar().off();
}

@@ -786,0 +524,0 @@ };

define([
'summernote/core/list'
], function (list) {
'summernote/core/list',
'summernote/core/agent'
], function (list, agent) {
/**

@@ -87,6 +88,14 @@ * @class module.Button

if (!!selectedFont) {
selectedFont = list.head(selectedFont.split(','));
selectedFont = selectedFont.replace(/\'/g, '');
var list = selectedFont.split(',');
for (var i = 0, len = list.length; i < len; i++) {
selectedFont = list[i].replace(/[\'\"]/g, '').replace(/\s+$/, '').replace(/^\s+/, '');
if (agent.isFontInstalled(selectedFont)) {
break;
}
}
$fontname.find('.note-current-fontname').text(selectedFont);
checkDropdownMenu($fontname, selectedFont);
}

@@ -93,0 +102,0 @@ }

@@ -1,2 +0,4 @@

define('summernote/module/Handle', function () {
define([
'summernote/core/dom'
], function (dom) {
/**

@@ -7,4 +9,52 @@ * @class module.Handle

*/
var Handle = function () {
var Handle = function (handler) {
var $document = $(document);
/**
* `mousedown` event handler on $handle
* - controlSizing: resize image
*
* @param {MouseEvent} event
*/
var hHandleMousedown = function (event) {
if (dom.isControlSizing(event.target)) {
event.preventDefault();
event.stopPropagation();
var layoutInfo = dom.makeLayoutInfo(event.target),
$handle = layoutInfo.handle(),
$popover = layoutInfo.popover(),
$editable = layoutInfo.editable(),
$editor = layoutInfo.editor();
var target = $handle.find('.note-control-selection').data('target'),
$target = $(target), posStart = $target.offset(),
scrollTop = $document.scrollTop();
var isAirMode = $editor.data('options').airMode;
$document.on('mousemove', function (event) {
handler.invoke('editor.resizeTo', {
x: event.clientX - posStart.left,
y: event.clientY - (posStart.top - scrollTop)
}, $target, !event.shiftKey);
handler.invoke('handle.update', $handle, {image: target}, isAirMode);
handler.invoke('popover.update', $popover, {image: target}, isAirMode);
}).one('mouseup', function () {
$document.off('mousemove');
handler.invoke('editor.afterCommand', $editable);
});
if (!$target.data('ratio')) { // original ratio.
$target.data('ratio', $target.height() / $target.width());
}
}
};
this.attach = function (layoutInfo) {
layoutInfo.handle().on('mousedown', hHandleMousedown);
};
/**
* update handle

@@ -11,0 +61,0 @@ * @param {jQuery} $handle

@@ -67,3 +67,9 @@ define([

var href = $(styleInfo.anchor).attr('href');
var target = $(styleInfo.anchor).attr('target');
$anchor.attr('href', href).html(href);
if (!target) {
$anchor.removeAttr('target');
} else {
$anchor.attr('target', '_blank');
}
showPopover($linkPopover, posFromPlaceholder(styleInfo.anchor, isAirMode));

@@ -70,0 +76,0 @@ } else {

define([
'summernote/core/list',
'summernote/core/dom',
'summernote/module/Button'
], function (list, Button) {
], function (list, dom, Button) {
/**

@@ -47,3 +48,2 @@ * @class module.Toolbar

/**
*
* @param {jQuery} $container

@@ -58,3 +58,2 @@ * @param {Boolean} [bFullscreen=false]

/**
*
* @param {jQuery} $container

@@ -66,3 +65,35 @@ * @param {Boolean} [isCodeview=false]

$btn.toggleClass('active', isCodeview);
if (isCodeview) {
this.deactivate($container);
} else {
this.activate($container);
}
};
/**
* get button in toolbar
*
* @param {jQuery} $editable
* @param {String} name
* @return {jQuery}
*/
this.get = function ($editable, name) {
var $toolbar = dom.makeLayoutInfo($editable).toolbar();
return $toolbar.find('[data-name=' + name + ']');
};
/**
* set button state
* @param {jQuery} $editable
* @param {String} name
* @param {Boolean} [isActive=true]
*/
this.setButtonState = function ($editable, name, isActive) {
isActive = (isActive === false) ? false : true;
var $button = this.get($editable, name);
$button.toggleClass('active', isActive);
};
};

@@ -69,0 +100,0 @@

define([
'summernote/core/agent', 'summernote/core/dom', 'summernote/core/func'
'summernote/core/agent',
'summernote/core/dom',
'summernote/core/func'
], function (agent, dom, func) {

@@ -72,8 +74,10 @@ /**

var tplPopover = function (className, content) {
return '<div class="' + className + ' popover bottom in" style="display: none;">' +
var $popover = $('<div class="' + className + ' popover bottom in" style="display: none;">' +
'<div class="arrow"></div>' +
'<div class="popover-content">' +
content +
'</div>' +
'</div>';
'</div>');
$popover.find('.popover-content').append(content);
return $popover;
};

@@ -99,8 +103,6 @@

) +
'<form class="note-modal-form">' +
'<div class="modal-body">' + body + '</div>' +
(footer ?
'<div class="modal-footer">' + footer + '</div>' : ''
) +
'</form>' +
'<div class="modal-body">' + body + '</div>' +
(footer ?
'<div class="modal-footer">' + footer + '</div>' : ''
) +
'</div>' +

@@ -112,4 +114,4 @@ '</div>' +

var tplButtonInfo = {
picture: function (lang) {
return tplIconButton('fa fa-picture-o', {
picture: function (lang, options) {
return tplIconButton(options.iconPrefix + 'picture-o', {
event: 'showImageDialog',

@@ -120,4 +122,4 @@ title: lang.image.image,

},
link: function (lang) {
return tplIconButton('fa fa-link', {
link: function (lang, options) {
return tplIconButton(options.iconPrefix + 'link', {
event: 'showLinkDialog',

@@ -128,3 +130,3 @@ title: lang.link.link,

},
table: function (lang) {
table: function (lang, options) {
var dropdown = '<ul class="note-table dropdown-menu">' +

@@ -138,3 +140,3 @@ '<div class="note-dimension-picker">' +

'</ul>';
return tplIconButton('fa fa-table', {
return tplIconButton(options.iconPrefix + 'table', {
title: lang.table.table,

@@ -155,3 +157,3 @@ dropdown: dropdown

return tplIconButton('fa fa-magic', {
return tplIconButton(options.iconPrefix + 'magic', {
title: lang.style.style,

@@ -162,2 +164,3 @@ dropdown: '<ul class="dropdown-menu">' + items + '</ul>'

fontname: function (lang, options) {
var realFontList = [];
var items = options.fontNames.reduce(function (memo, v) {

@@ -167,8 +170,13 @@ if (!agent.isFontInstalled(v) && options.fontNamesIgnoreCheck.indexOf(v) === -1) {

}
realFontList.push(v);
return memo + '<li><a data-event="fontName" href="#" data-value="' + v + '" style="font-family:\'' + v + '\'">' +
'<i class="fa fa-check"></i> ' + v +
'<i class="' + options.iconPrefix + 'check"></i> ' + v +
'</a></li>';
}, '');
var hasDefaultFont = agent.isFontInstalled(options.defaultFontName);
var defaultFontName = (hasDefaultFont) ? options.defaultFontName : realFontList[0];
var label = '<span class="note-current-fontname">' +
options.defaultFontName +
defaultFontName +
'</span>';

@@ -180,4 +188,17 @@ return tplButton(label, {

},
color: function (lang) {
var colorButtonLabel = '<i class="fa fa-font" style="color:black;background-color:yellow;"></i>';
fontsize: function (lang, options) {
var items = options.fontSizes.reduce(function (memo, v) {
return memo + '<li><a data-event="fontSize" href="#" data-value="' + v + '">' +
'<i class="fa fa-check"></i> ' + v +
'</a></li>';
}, '');
var label = '<span class="note-current-fontsize">11</span>';
return tplButton(label, {
title: lang.font.size,
dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
});
},
color: function (lang, options) {
var colorButtonLabel = '<i class="' + options.iconPrefix + 'font" style="color:black;background-color:yellow;"></i>';
var colorButton = tplButton(colorButtonLabel, {

@@ -217,4 +238,4 @@ className: 'note-recent-color',

},
bold: function (lang) {
return tplIconButton('fa fa-bold', {
bold: function (lang, options) {
return tplIconButton(options.iconPrefix + 'bold', {
event: 'bold',

@@ -224,4 +245,4 @@ title: lang.font.bold

},
italic: function (lang) {
return tplIconButton('fa fa-italic', {
italic: function (lang, options) {
return tplIconButton(options.iconPrefix + 'italic', {
event: 'italic',

@@ -231,4 +252,4 @@ title: lang.font.italic

},
underline: function (lang) {
return tplIconButton('fa fa-underline', {
underline: function (lang, options) {
return tplIconButton(options.iconPrefix + 'underline', {
event: 'underline',

@@ -238,4 +259,22 @@ title: lang.font.underline

},
clear: function (lang) {
return tplIconButton('fa fa-eraser', {
strikethrough: function (lang) {
return tplIconButton('fa fa-strikethrough', {
event: 'strikethrough',
title: lang.font.strikethrough
});
},
superscript: function (lang) {
return tplIconButton('fa fa-superscript', {
event: 'superscript',
title: lang.font.superscript
});
},
subscript: function (lang) {
return tplIconButton('fa fa-subscript', {
event: 'subscript',
title: lang.font.subscript
});
},
clear: function (lang, options) {
return tplIconButton(options.iconPrefix + 'eraser', {
event: 'removeFormat',

@@ -245,4 +284,4 @@ title: lang.font.clear

},
ul: function (lang) {
return tplIconButton('fa fa-list-ul', {
ul: function (lang, options) {
return tplIconButton(options.iconPrefix + 'list-ul', {
event: 'insertUnorderedList',

@@ -252,4 +291,4 @@ title: lang.lists.unordered

},
ol: function (lang) {
return tplIconButton('fa fa-list-ol', {
ol: function (lang, options) {
return tplIconButton(options.iconPrefix + 'list-ol', {
event: 'insertOrderedList',

@@ -259,16 +298,16 @@ title: lang.lists.ordered

},
paragraph: function (lang) {
var leftButton = tplIconButton('fa fa-align-left', {
paragraph: function (lang, options) {
var leftButton = tplIconButton(options.iconPrefix + 'align-left', {
title: lang.paragraph.left,
event: 'justifyLeft'
});
var centerButton = tplIconButton('fa fa-align-center', {
var centerButton = tplIconButton(options.iconPrefix + 'align-center', {
title: lang.paragraph.center,
event: 'justifyCenter'
});
var rightButton = tplIconButton('fa fa-align-right', {
var rightButton = tplIconButton(options.iconPrefix + 'align-right', {
title: lang.paragraph.right,
event: 'justifyRight'
});
var justifyButton = tplIconButton('fa fa-align-justify', {
var justifyButton = tplIconButton(options.iconPrefix + 'align-justify', {
title: lang.paragraph.justify,

@@ -278,7 +317,7 @@ event: 'justifyFull'

var outdentButton = tplIconButton('fa fa-outdent', {
var outdentButton = tplIconButton(options.iconPrefix + 'outdent', {
title: lang.paragraph.outdent,
event: 'outdent'
});
var indentButton = tplIconButton('fa fa-indent', {
var indentButton = tplIconButton(options.iconPrefix + 'indent', {
title: lang.paragraph.indent,

@@ -297,3 +336,3 @@ event: 'indent'

return tplIconButton('fa fa-align-left', {
return tplIconButton(options.iconPrefix + 'align-left', {
title: lang.paragraph.paragraph,

@@ -306,7 +345,7 @@ dropdown: dropdown

return memo + '<li><a data-event="lineHeight" href="#" data-value="' + parseFloat(v) + '">' +
'<i class="fa fa-check"></i> ' + v +
'<i class="' + options.iconPrefix + 'check"></i> ' + v +
'</a></li>';
}, '');
return tplIconButton('fa fa-text-height', {
return tplIconButton(options.iconPrefix + 'text-height', {
title: lang.font.height,

@@ -317,4 +356,4 @@ dropdown: '<ul class="dropdown-menu">' + items + '</ul>'

},
help: function (lang) {
return tplIconButton('fa fa-question', {
help: function (lang, options) {
return tplIconButton(options.iconPrefix + 'question', {
event: 'showHelpDialog',

@@ -325,4 +364,4 @@ title: lang.options.help,

},
fullscreen: function (lang) {
return tplIconButton('fa fa-arrows-alt', {
fullscreen: function (lang, options) {
return tplIconButton(options.iconPrefix + 'arrows-alt', {
event: 'fullscreen',

@@ -332,4 +371,4 @@ title: lang.options.fullscreen

},
codeview: function (lang) {
return tplIconButton('fa fa-code', {
codeview: function (lang, options) {
return tplIconButton(options.iconPrefix + 'code', {
event: 'codeview',

@@ -339,4 +378,4 @@ title: lang.options.codeview

},
undo: function (lang) {
return tplIconButton('fa fa-undo', {
undo: function (lang, options) {
return tplIconButton(options.iconPrefix + 'undo', {
event: 'undo',

@@ -346,4 +385,4 @@ title: lang.history.undo

},
redo: function (lang) {
return tplIconButton('fa fa-repeat', {
redo: function (lang, options) {
return tplIconButton(options.iconPrefix + 'repeat', {
event: 'redo',

@@ -353,4 +392,4 @@ title: lang.history.redo

},
hr: function (lang) {
return tplIconButton('fa fa-minus', {
hr: function (lang, options) {
return tplIconButton(options.iconPrefix + 'minus', {
event: 'insertHorizontalRule',

@@ -364,3 +403,3 @@ title: lang.hr.insert

var tplLinkPopover = function () {
var linkButton = tplIconButton('fa fa-edit', {
var linkButton = tplIconButton(options.iconPrefix + 'edit', {
title: lang.link.edit,

@@ -370,3 +409,3 @@ event: 'showLinkDialog',

});
var unlinkButton = tplIconButton('fa fa-unlink', {
var unlinkButton = tplIconButton(options.iconPrefix + 'unlink', {
title: lang.link.unlink,

@@ -399,3 +438,3 @@ event: 'unlink'

var leftButton = tplIconButton('fa fa-align-left', {
var leftButton = tplIconButton(options.iconPrefix + 'align-left', {
title: lang.image.floatLeft,

@@ -405,3 +444,3 @@ event: 'floatMe',

});
var rightButton = tplIconButton('fa fa-align-right', {
var rightButton = tplIconButton(options.iconPrefix + 'align-right', {
title: lang.image.floatRight,

@@ -411,3 +450,3 @@ event: 'floatMe',

});
var justifyButton = tplIconButton('fa fa-align-justify', {
var justifyButton = tplIconButton(options.iconPrefix + 'align-justify', {
title: lang.image.floatNone,

@@ -418,3 +457,3 @@ event: 'floatMe',

var roundedButton = tplIconButton('fa fa-square', {
var roundedButton = tplIconButton(options.iconPrefix + 'square', {
title: lang.image.shapeRounded,

@@ -424,3 +463,3 @@ event: 'imageShape',

});
var circleButton = tplIconButton('fa fa-circle-o', {
var circleButton = tplIconButton(options.iconPrefix + 'circle-o', {
title: lang.image.shapeCircle,

@@ -430,3 +469,3 @@ event: 'imageShape',

});
var thumbnailButton = tplIconButton('fa fa-picture-o', {
var thumbnailButton = tplIconButton(options.iconPrefix + 'picture-o', {
title: lang.image.shapeThumbnail,

@@ -436,3 +475,3 @@ event: 'imageShape',

});
var noneButton = tplIconButton('fa fa-times', {
var noneButton = tplIconButton(options.iconPrefix + 'times', {
title: lang.image.shapeNone,

@@ -443,3 +482,3 @@ event: 'imageShape',

var removeButton = tplIconButton('fa fa-trash-o', {
var removeButton = tplIconButton(options.iconPrefix + 'trash-o', {
title: lang.image.remove,

@@ -458,20 +497,30 @@ event: 'removeMedia',

var tplAirPopover = function () {
var content = '';
var $content = $('<div />');
for (var idx = 0, len = options.airPopover.length; idx < len; idx ++) {
var group = options.airPopover[idx];
content += '<div class="note-' + group[0] + ' btn-group">';
var $group = $('<div class="note-' + group[0] + ' btn-group">');
for (var i = 0, lenGroup = group[1].length; i < lenGroup; i++) {
content += tplButtonInfo[group[1][i]](lang, options);
var $button = $(tplButtonInfo[group[1][i]](lang, options));
$button.attr('data-name', group[1][i]);
$group.append($button);
}
content += '</div>';
$content.append($group);
}
return tplPopover('note-air-popover', content);
return tplPopover('note-air-popover', $content.children());
};
return '<div class="note-popover">' +
tplLinkPopover() +
tplImagePopover() +
(options.airMode ? tplAirPopover() : '') +
'</div>';
var $notePopover = $('<div class="note-popover" />');
$notePopover.append(tplLinkPopover());
$notePopover.append(tplImagePopover());
if (options.airMode) {
$notePopover.append(tplAirPopover());
}
return $notePopover;
};

@@ -821,3 +870,3 @@

//04. create Toolbar
var toolbarHTML = '';
var $toolbar = $('<div class="note-toolbar btn-toolbar" />');
for (var idx = 0, len = options.toolbar.length; idx < len; idx ++) {

@@ -827,3 +876,3 @@ var groupName = options.toolbar[idx][0];

toolbarHTML += '<div class="note-' + groupName + ' btn-group">';
var $group = $('<div class="note-' + groupName + ' btn-group" />');
for (var i = 0, btnLength = groupButtons.length; i < btnLength; i++) {

@@ -833,10 +882,11 @@ var buttonInfo = tplButtonInfo[groupButtons[i]];

if (!$.isFunction(buttonInfo)) { continue; }
toolbarHTML += buttonInfo(langInfo, options);
var $button = $(buttonInfo(langInfo, options));
$button.attr('data-name', groupButtons[i]); // set button's alias, becuase to get button element from $toolbar
$group.append($button);
}
toolbarHTML += '</div>';
$toolbar.append($group);
}
toolbarHTML = '<div class="note-toolbar btn-toolbar">' + toolbarHTML + '</div>';
var $toolbar = $(toolbarHTML).prependTo($editor);
$toolbar.prependTo($editor);
var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];

@@ -868,2 +918,6 @@ createPalette($toolbar, options);

this.hasNoteEditor = function ($holder) {
return this.noteEditorFromHolder($holder).length > 0;
};
this.noteEditorFromHolder = function ($holder) {

@@ -886,6 +940,2 @@ if ($holder.hasClass('note-air-editor')) {

this.createLayout = function ($holder, options) {
if (this.noteEditorFromHolder($holder).length) {
return;
}
if (options.airMode) {

@@ -902,16 +952,14 @@ this.createLayoutByAirMode($holder, options);

* @param {jQuery} $holder - placeholder
* @returns {Object}
* @return {Object}
*/
this.layoutInfoFromHolder = function ($holder) {
var $editor = this.noteEditorFromHolder($holder);
if (!$editor.length) { return; }
if (!$editor.length) {
return;
}
var layoutInfo = dom.buildLayoutInfo($editor);
// cache all properties.
for (var key in layoutInfo) {
if (layoutInfo.hasOwnProperty(key)) {
layoutInfo[key] = layoutInfo[key].call();
}
}
return layoutInfo;
// connect $holder to $editor
$editor.data('holder', $holder);
return dom.buildLayoutInfo($editor);
};

@@ -932,9 +980,9 @@

layoutInfo.popover.remove();
layoutInfo.handle.remove();
layoutInfo.dialog.remove();
layoutInfo.popover().remove();
layoutInfo.handle().remove();
layoutInfo.dialog().remove();
} else {
$holder.html(layoutInfo.editable.html());
$holder.html(layoutInfo.editable().html());
layoutInfo.editor.remove();
layoutInfo.editor().remove();
$holder.show();

@@ -941,0 +989,0 @@ }

define([
'summernote/core/agent', 'summernote/core/dom',
'summernote/core/agent',
'summernote/core/list',
'summernote/core/dom',
'summernote/core/range',
'summernote/settings',
'summernote/EventHandler', 'summernote/Renderer'
], function (agent, dom, range, settings, EventHandler, Renderer) {
'summernote/defaults',
'summernote/EventHandler',
'summernote/Renderer'
], function (agent, list, dom, range,
defaults, EventHandler, Renderer) {

@@ -14,3 +18,3 @@ // jQuery namespace for summernote

*
* @mixin settings
* @mixin defaults
* @singleton

@@ -21,4 +25,7 @@ *

// extends default `settings`
$.extend($.summernote, settings);
// extends default settings
// - $.summernote.version
// - $.summernote.options
// - $.summernote.lang
$.extend($.summernote, defaults);

@@ -63,3 +70,5 @@ var renderer = new Renderer();

*/
pluginEvents: {}
pluginEvents: {},
plugins : []
});

@@ -125,2 +134,6 @@

$.summernote.addPlugin = function (plugin) {
// save plugin list
$.summernote.plugins.push(plugin);
if (plugin.buttons) {

@@ -171,7 +184,15 @@ $.each(plugin.buttons, function (name, button) {

* @member $.fn
* @param {Object} options reference to $.summernote.options
* @returns {this}
* @param {Object|String} options reference to $.summernote.options
* @return {this}
*/
summernote: function (options) {
// extend default options
summernote: function () {
// check first argument's type
// - {String}: External API call {{module}}.{{method}}
// - {Object}: init options
var type = $.type(list.head(arguments));
var isExternalAPICalled = type === 'string';
var isInitOptions = type === 'object';
// extend default options with custom user options
var options = isInitOptions ? list.head(arguments) : {};
options = $.extend({}, $.summernote.options, options);

@@ -186,36 +207,39 @@

// createLayout with options
renderer.createLayout($holder, options);
// if layout isn't created yet, createLayout and attach events
if (!renderer.hasNoteEditor($holder)) {
renderer.createLayout($holder, options);
var info = renderer.layoutInfoFromHolder($holder);
eventHandler.attach(info, options);
var layoutInfo = renderer.layoutInfoFromHolder($holder);
// Textarea: auto filling the code before form submit.
if (dom.isTextarea($holder[0])) {
$holder.closest('form').submit(function () {
var contents = $holder.code();
$holder.val(contents);
eventHandler.attach(layoutInfo, options);
eventHandler.attachCustomEvent(layoutInfo, options);
// callback on submit
if (options.onsubmit) {
options.onsubmit(contents);
}
});
}
});
// focus on first editable element
if (this.first().length && options.focus) {
var info = renderer.layoutInfoFromHolder(this.first());
info.editable.focus();
}
// callback on init
if (this.length && options.oninit) {
if (!isExternalAPICalled && this.length && options.oninit) {
options.oninit();
}
var $first = this.first();
if ($first.length) {
var layoutInfo = renderer.layoutInfoFromHolder($first);
// external API
if (isExternalAPICalled) {
var moduleAndMethod = list.head(list.from(arguments));
var args = list.tail(list.from(arguments));
// TODO now external API only works for editor
var params = [moduleAndMethod, layoutInfo.editable()].concat(args);
return eventHandler.invoke.apply(eventHandler, params);
} else if (options.focus) {
// focus on first editable element for initialize editor
layoutInfo.editable().focus();
}
}
return this;
},
//

@@ -238,19 +262,23 @@ /**

* @member $.fn
* @param {String} [sHTML] - HTML contents(optional, set)
* @returns {this|String} - context(set) or HTML contents of note(get).
* @param {String} [html] - HTML contents(optional, set)
* @return {this|String} - context(set) or HTML contents of note(get).
*/
code: function (sHTML) {
code: function (html) {
// get the HTML contents of note
if (sHTML === undefined) {
if (html === undefined) {
var $holder = this.first();
if (!$holder.length) { return; }
var info = renderer.layoutInfoFromHolder($holder);
if (!!(info && info.editable)) {
var isCodeview = info.editor.hasClass('codeview');
if (isCodeview && agent.hasCodeMirror) {
info.codable.data('cmEditor').save();
}
return isCodeview ? info.codable.val() : info.editable.html();
if (!$holder.length) {
return;
}
return dom.isTextarea($holder[0]) ? $holder.val() : $holder.html();
var layoutInfo = renderer.layoutInfoFromHolder($holder);
var $editable = layoutInfo && layoutInfo.editable();
if ($editable && $editable.length) {
var isCodeview = eventHandler.invoke('codeview.isActivated', layoutInfo);
eventHandler.invoke('codeview.sync', layoutInfo);
return isCodeview ? layoutInfo.codable().val() :
layoutInfo.editable().html();
}
return dom.value($holder);
}

@@ -260,4 +288,7 @@

this.each(function (i, holder) {
var info = renderer.layoutInfoFromHolder($(holder));
if (info && info.editable) { info.editable.html(sHTML); }
var layoutInfo = renderer.layoutInfoFromHolder($(holder));
var $editable = layoutInfo && layoutInfo.editable();
if ($editable) {
$editable.html(html);
}
});

@@ -274,3 +305,3 @@

* @member $.fn
* @returns {this}
* @return {this}
*/

@@ -281,7 +312,9 @@ destroy: function () {

if (!renderer.hasNoteEditor($holder)) {
return;
}
var info = renderer.layoutInfoFromHolder($holder);
if (!info || !info.editable) { return; }
var options = info.editor().data('options');
var options = info.editor.data('options');
eventHandler.detach(info, options);

@@ -288,0 +321,0 @@ renderer.removeLayout($holder, info, options);

@@ -243,3 +243,20 @@ /**

});
test('dom.splitPoint', function () {
var $editable, $para, $br;
$editable = $('<div class="note-editable"><p><br></p></div>');
$para = $editable.clone().find('p');
$br = $para.find('br');
deepEqual(dom.splitPoint({
node: $para[0],
offset: 0
}, true), {
rightNode: $br[0],
container: $para[0]
}, 'splitPoint empty paragraph with inline should returns rightNode:<br> container:<p>');
});
};
});

@@ -124,2 +124,53 @@ /**

test('rng.pasteHTML', function () {
var $cont, $p, $b, markup;
// split text with inline nodes
$cont = $('<div class="note-editable"><p>text</p></div>');
$p = $cont.find('p');
markup = '<span>span</span><i>italic</i>';
range.create($p[0].firstChild, 2).pasteHTML(markup);
equalsToUpperCase($cont.html(), '<p>te<span>span</span><i>italic</i>xt</p>', 'rng.pasteHTML with inlines should not split text.');
// split inline node with inline nodes
$cont = $('<div class="note-editable"><p><b>bold</b></p></div>');
$p = $cont.find('p');
$b = $cont.find('b');
markup = '<span>span</span><i>italic</i>';
range.create($b[0].firstChild, 2).pasteHTML(markup);
equalsToUpperCase(
$cont.html(),
'<p><b>bo</b><span>span</span><i>italic</i><b>ld</b></p>',
'rng.pasteHTML with inlines should not split text.'
);
// split inline node with inline and block nodes
$cont = $('<div class="note-editable"><p><b>bold</b></p></div>');
$p = $cont.find('p');
$b = $cont.find('b');
markup = '<span>span</span><p><i>italic</i></p>';
range.create($b[0].firstChild, 2).pasteHTML(markup);
equalsToUpperCase(
$cont.html(),
'<p><b>bo</b><span>span</span></p><p><i>italic</i></p><p><b>ld</b></p>',
'rng.pasteHTML with inlines should not split text.'
);
// split inline node with inline and block
$cont = $('<div class="note-editable"><p><b>bold</b></p></div>');
$p = $cont.find('p');
$b = $cont.find('b');
markup = '<span>span</span><p><i>italic</i></p>';
range.create($b[0].firstChild, 2).pasteHTML(markup);
equalsToUpperCase(
$cont.html(),
'<p><b>bo</b><span>span</span></p><p><i>italic</i></p><p><b>ld</b></p>',
'rng.pasteHTML with inlines should not split text.'
);
});
test('rng.deleteContents', function () {

@@ -182,3 +233,52 @@ var $cont, $p, $b, $u;

});
test('rng.getWordRange', function () {
var $cont, rng;
$cont = $('<div class="note-editable">super simple wysiwyg editor</div>');
// no word before cursor
rng = range.create(
$cont[0].firstChild, 0
).getWordRange();
deepEqual([
rng.sc, rng.so, rng.ec, rng.eo
], [
$cont[0].firstChild, 0, $cont[0].firstChild, 0
], 'rng.getWordRange with no word before cursor should return itself');
// find word before cursor
rng = range.create(
$cont[0].firstChild, 5
).getWordRange();
deepEqual([
rng.sc, rng.so, rng.ec, rng.eo
], [
$cont[0].firstChild, 0, $cont[0].firstChild, 5
], 'rng.getWordRange with word before cursor should return expanded range');
rng = range.create(
$cont[0].firstChild, 3
).getWordRange();
deepEqual([
rng.sc, rng.so, rng.ec, rng.eo
], [
$cont[0].firstChild, 0, $cont[0].firstChild, 3
], 'rng.getWordRange with half word before cursor should expanded range');
rng = range.create(
$cont[0].firstChild, 12
).getWordRange();
deepEqual([
rng.sc, rng.so, rng.ec, rng.eo
], [
$cont[0].firstChild, 6, $cont[0].firstChild, 12
], 'rng.getWordRange with half word before cursor should expanded range');
});
};
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc