: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Super simple wysiwyg editor v0.7.1
* Copyright 2013-2015 Alan Hong. and other contributors
* summernote may be freely distributed under the MIT license./
* MODIFIED: Adding support for CodeMirror callbacks.
* If we've got any callbacks for code mirror, register them.
* Date: 2015-12-31T12:09Z
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
module.exports = factory(require('jquery'));
* func utils (for high-order func's arg)
* @alternateClassName func
var func = (function () {
var eq = function (itemA) {
return function (itemB) {
var eq2 = function (itemA, itemB) {
var peq2 = function (propName) {
return function (itemA, itemB) {
return itemA[propName] === itemB[propName];
return !f.apply(f, arguments);
var and = function (fA, fB) {
return fA(item) && fB(item);
var self = function (a) {
* generate a globally-unique id
* @param {String} [prefix]
var uniqueId = function (prefix) {
var id = ++idCounter + '';
return prefix ? prefix + id : id;
* returns bnd (bounds) from rect
* - IE Compatability Issue: http://goo.gl/sRLOAo
* - Scroll Issue: http://goo.gl/sNjUc
* @return {Object} bounds
* @return {Number} bounds.top
* @return {Number} bounds.left
* @return {Number} bounds.width
* @return {Number} bounds.height
var rect2bnd = function (rect) {
var $document = $(document);
top: rect.top + $document.scrollTop(),
left: rect.left + $document.scrollLeft(),
width: rect.right - rect.left,
height: rect.bottom - rect.top
* returns a copy of the object where the keys have become the values and the values the keys.
var invertObject = function (obj) {
if (obj.hasOwnProperty(key)) {
inverted[obj[key]] = key;
* @param {String} namespace
* @param {String} [prefix]
var namespaceToCamel = function (namespace, prefix) {
return prefix + namespace.split('.').map(function (name) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
invertObject: invertObject,
namespaceToCamel: namespaceToCamel
* @alternateClassName list
var list = (function () {
* returns the first item of an array.
var head = function (array) {
* returns the last item of an array.
var last = function (array) {
return array[array.length - 1];
* returns everything but the last entry of the array.
var initial = function (array) {
return array.slice(0, array.length - 1);
* returns the rest of the items in an array.
var tail = function (array) {
var find = function (array, pred) {
for (var idx = 0, len = array.length; idx < len; idx ++) {
* returns true if all of the values in the array pass the predicate truth test.
var all = function (array, pred) {
for (var idx = 0, len = array.length; idx < len; idx ++) {
var indexOf = function (array, item) {
return $.inArray(item, array);
* returns true if the value is present in the list.
var contains = function (array, item) {
return indexOf(array, item) !== -1;
* @param {Array} array - array
* @param {Function} fn - iterator
var sum = function (array, fn) {
return array.reduce(function (memo, v) {
* returns a copy of the collection with array type.
* @param {Collection} collection - collection eg) node.childNodes, ...
var from = function (collection) {
var result = [], idx = -1, length = collection.length;
result[idx] = collection[idx];
* returns whether list is empty or not
var isEmpty = function (array) {
return !array || !array.length;
* cluster elements by predicate function.
* @param {Array} array - array
* @param {Function} fn - predicate function for cluster rule
var clusterBy = function (array, fn) {
if (!array.length) { return []; }
return aTail.reduce(function (memo, v) {
if (fn(last(aLast), v)) {
* returns a copy of the array with all falsy values removed
* @param {Array} array - array
* @param {Function} fn - predicate function for cluster rule
var compact = function (array) {
for (var idx = 0, len = array.length; idx < len; idx ++) {
if (array[idx]) { aResult.push(array[idx]); }
* produces a duplicate-free version of the array
var unique = function (array) {
for (var idx = 0, len = array.length; idx < len; idx ++) {
if (!contains(results, array[idx])) {
results.push(array[idx]);
var next = function (array, item) {
var idx = indexOf(array, item);
if (idx === -1) { return null; }
var prev = function (array, item) {
var idx = indexOf(array, item);
if (idx === -1) { return null; }
return { head: head, last: last, initial: initial, tail: tail,
prev: prev, next: next, find: find, contains: contains,
all: all, sum: sum, from: from, isEmpty: isEmpty,
clusterBy: clusterBy, compact: compact, unique: unique };
var isSupportAmd = typeof define === 'function' && define.amd;
* returns whether font is installed or not.
* @param {String} fontName
var isFontInstalled = function (fontName) {
var testFontName = fontName === 'Comic Sans MS' ? 'Courier New' : 'Comic Sans MS';
var $tester = $('<div>').css({
}).text('mmmmmmmmmwwwwwww').appendTo(document.body);
var originalWidth = $tester.css('fontFamily', testFontName).width();
var width = $tester.css('fontFamily', fontName + ',' + testFontName).width();
return originalWidth !== width;
var userAgent = navigator.userAgent;
var isMSIE = /MSIE|Trident/i.test(userAgent);
var matches = /MSIE (\d+[.]\d+)/.exec(userAgent);
browserVersion = parseFloat(matches[1]);
matches = /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(userAgent);
browserVersion = parseFloat(matches[1]);
* Object which check platform and agent
* @alternateClassName agent
isMac: navigator.appVersion.indexOf('Mac') > -1,
isFF: /firefox/i.test(userAgent),
isWebkit: /webkit/i.test(userAgent),
isSafari: /safari/i.test(userAgent),
browserVersion: browserVersion,
jqueryVersion: parseFloat($.fn.jquery),
isSupportAmd: isSupportAmd,
hasCodeMirror: isSupportAmd ? require.specified('codemirror') : !!window.CodeMirror,
isFontInstalled: isFontInstalled,
isW3CRangeSupport: !!document.createRange
var NBSP_CHAR = String.fromCharCode(160);
var ZERO_WIDTH_NBSP_CHAR = '\ufeff';
* @alternateClassName dom
* returns whether node is `note-editable` or not.
var isEditable = function (node) {
return node && $(node).hasClass('note-editable');
* @method isControlSizing
* returns whether node is `note-control-sizing` or not.
var isControlSizing = function (node) {
return node && $(node).hasClass('note-control-sizing');
* @method makePredByNodeName
* returns predicate which judge whether nodeName is same
* @param {String} nodeName
var makePredByNodeName = function (nodeName) {
nodeName = nodeName.toUpperCase();
return node && node.nodeName.toUpperCase() === nodeName;
* @return {Boolean} true if node's type is text(3)
var isText = function (node) {
return node && node.nodeType === 3;
* @return {Boolean} true if node's type is element(1)
var isElement = function (node) {
return node && node.nodeType === 1;
* ex) br, col, embed, hr, img, input, ...
* @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
var isVoid = function (node) {
return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON/.test(node.nodeName.toUpperCase());
var isPara = function (node) {