/** * Kendo UI v2016.1.226 (http://www.telerik.com/kendo-ui) * Copyright 2016 Telerik AD. All rights reserved. * * Kendo UI commercial licenses may be obtained at * http://www.telerik.com/purchase/license-agreement/kendo-ui-complete * If you do not own a commercial license, this file shall be governed by the trial license terms. */ (function (f, define) { define('util/undoredostack', ['kendo.core'], f); }(function () { (function (kendo) { var UndoRedoStack = kendo.Observable.extend({ init: function (options) { kendo.Observable.fn.init.call(this, options); this.clear(); }, events: [ 'undo', 'redo' ], push: function (command) { this.stack = this.stack.slice(0, this.currentCommandIndex + 1); this.currentCommandIndex = this.stack.push(command) - 1; }, undo: function () { if (this.canUndo()) { var command = this.stack[this.currentCommandIndex--]; command.undo(); this.trigger('undo', { command: command }); } }, redo: function () { if (this.canRedo()) { var command = this.stack[++this.currentCommandIndex]; command.redo(); this.trigger('redo', { command: command }); } }, clear: function () { this.stack = []; this.currentCommandIndex = -1; }, canUndo: function () { return this.currentCommandIndex >= 0; }, canRedo: function () { return this.currentCommandIndex != this.stack.length - 1; } }); kendo.deepExtend(kendo, { util: { UndoRedoStack: UndoRedoStack } }); }(kendo)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/main', [ 'util/undoredostack', 'kendo.combobox', 'kendo.dropdownlist', 'kendo.window', 'kendo.colorpicker' ], f); }(function () { (function ($, undefined) { var kendo = window.kendo, Class = kendo.Class, Widget = kendo.ui.Widget, os = kendo.support.mobileOS, browser = kendo.support.browser, extend = $.extend, proxy = $.proxy, deepExtend = kendo.deepExtend, keys = kendo.keys; var ToolTemplate = Class.extend({ init: function (options) { this.options = options; }, getHtml: function () { var options = this.options; return kendo.template(options.template, { useWithBlock: false })(options); } }); var EditorUtils = { editorWrapperTemplate: '' + '' + '' + '', buttonTemplate: '#= data.title #', colorPickerTemplate: '
', comboBoxTemplate: '', separatorTemplate: '', overflowAnchorTemplate: '', formatByName: function (name, format) { for (var i = 0; i < format.length; i++) { if ($.inArray(name, format[i].tags) >= 0) { return format[i]; } } }, registerTool: function (toolName, tool) { var toolOptions = tool.options; if (toolOptions && toolOptions.template) { toolOptions.template.options.cssClass = 'k-' + toolName; } if (!tool.name) { tool.options.name = toolName; tool.name = toolName.toLowerCase(); } Editor.defaultTools[toolName] = tool; }, registerFormat: function (formatName, format) { Editor.fn.options.formats[formatName] = format; } }; var messages = { bold: 'Bold', italic: 'Italic', underline: 'Underline', strikethrough: 'Strikethrough', superscript: 'Superscript', subscript: 'Subscript', justifyCenter: 'Center text', justifyLeft: 'Align text left', justifyRight: 'Align text right', justifyFull: 'Justify', insertUnorderedList: 'Insert unordered list', insertOrderedList: 'Insert ordered list', indent: 'Indent', outdent: 'Outdent', createLink: 'Insert hyperlink', unlink: 'Remove hyperlink', insertImage: 'Insert image', insertFile: 'Insert file', insertHtml: 'Insert HTML', viewHtml: 'View HTML', fontName: 'Select font family', fontNameInherit: '(inherited font)', fontSize: 'Select font size', fontSizeInherit: '(inherited size)', formatBlock: 'Format', formatting: 'Format', foreColor: 'Color', backColor: 'Background color', style: 'Styles', emptyFolder: 'Empty Folder', editAreaTitle: 'Editable area. Press F10 for toolbar.', uploadFile: 'Upload', orderBy: 'Arrange by:', orderBySize: 'Size', orderByName: 'Name', invalidFileType: 'The selected file "{0}" is not valid. Supported file types are {1}.', deleteFile: 'Are you sure you want to delete "{0}"?', overwriteFile: 'A file with name "{0}" already exists in the current directory. Do you want to overwrite it?', directoryNotFound: 'A directory with this name was not found.', imageWebAddress: 'Web address', imageAltText: 'Alternate text', imageWidth: 'Width (px)', imageHeight: 'Height (px)', fileWebAddress: 'Web address', fileTitle: 'Title', linkWebAddress: 'Web address', linkText: 'Text', linkToolTip: 'ToolTip', linkOpenInNewWindow: 'Open link in new window', dialogUpdate: 'Update', dialogInsert: 'Insert', dialogCancel: 'Cancel', createTable: 'Create table', createTableHint: 'Create a {0} x {1} table', addColumnLeft: 'Add column on the left', addColumnRight: 'Add column on the right', addRowAbove: 'Add row above', addRowBelow: 'Add row below', deleteRow: 'Delete row', deleteColumn: 'Delete column' }; var supportedBrowser = !os || os.ios && os.flatVersion >= 500 || !os.ios && typeof document.documentElement.contentEditable != 'undefined'; var toolGroups = { basic: [ 'bold', 'italic', 'underline' ], alignment: [ 'justifyLeft', 'justifyCenter', 'justifyRight' ], lists: [ 'insertUnorderedList', 'insertOrderedList' ], indenting: [ 'indent', 'outdent' ], links: [ 'createLink', 'unlink' ], tables: [ 'createTable', 'addColumnLeft', 'addColumnRight', 'addRowAbove', 'addRowBelow', 'deleteRow', 'deleteColumn' ] }; var Editor = Widget.extend({ init: function (element, options) { var that = this, value, editorNS = kendo.ui.editor, toolbarContainer, toolbarOptions, type; var domElement; var dom = editorNS.Dom; if (!supportedBrowser) { return; } Widget.fn.init.call(that, element, options); that.options = deepExtend({}, that.options, options); that.options.tools = that.options.tools.slice(); element = that.element; domElement = element[0]; type = dom.name(domElement); this._registerHandler(element.closest('form'), 'submit', proxy(that.update, that, undefined)); toolbarOptions = extend({}, that.options); toolbarOptions.editor = that; if (type == 'textarea') { that._wrapTextarea(); toolbarContainer = that.wrapper.find('.k-editor-toolbar'); if (domElement.id) { toolbarContainer.attr('aria-controls', domElement.id); } } else { that.element.attr('contenteditable', true).addClass('k-widget k-editor k-editor-inline'); toolbarOptions.popup = true; toolbarContainer = $(''); var block = this.isBlock(html); editor.focus(); var range = editor.getRange(); range.deleteContents(); if (range.startContainer == editor.document) { range.selectNodeContents(editor.body); } var marker = new Marker(); var caret = marker.addCaret(range); var parent = this.splittableParent(block, caret); var unwrap = false; var splittable = parent != editor.body && !dom.is(parent, 'td'); if (options.split && splittable && (block || dom.isInline(parent))) { range.selectNode(caret); editorNS.RangeUtils.split(range, parent, true); unwrap = true; } var fragment = this.htmlToFragment(html); if (fragment.firstChild && fragment.firstChild.className === 'k-paste-container') { var fragmentsHtml = []; for (i = 0, l = fragment.childNodes.length; i < l; i++) { fragmentsHtml.push(fragment.childNodes[i].innerHTML); } fragment = this.htmlToFragment(fragmentsHtml.join('
')); } $(fragment.childNodes).filter('table').addClass('k-table').end().find('table').addClass('k-table'); range.insertNode(fragment); parent = this.splittableParent(block, caret); if (unwrap) { while (caret.parentNode != parent) { dom.unwrap(caret.parentNode); } dom.unwrap(caret.parentNode); } dom.normalize(range.commonAncestorContainer); caret.style.display = 'inline'; dom.restoreScrollTop(editor.document); dom.scrollTo(caret); marker.removeCaret(range); var rangeEnd = range.commonAncestorContainer.parentNode; if (range.collapsed && dom.name(rangeEnd) == 'tbody') { range.setStartAfter($(rangeEnd).closest('table')[0]); range.collapse(true); } editor.selectRange(range); } }); var Cleaner = Class.extend({ clean: function (html) { var that = this, replacements = that.replacements, i, l; for (i = 0, l = replacements.length; i < l; i += 2) { html = html.replace(replacements[i], replacements[i + 1]); } return html; } }); var ScriptCleaner = Cleaner.extend({ init: function () { this.replacements = [ /<(\/?)script([^>]*)>/i, '<$1telerik:script$2>' ]; }, applicable: function (html) { return /]*>/i.test(html); } }); var TabCleaner = Cleaner.extend({ init: function () { var replacement = ' '; this.replacements = [ /]*>\s*<\/span>/gi, replacement, /\t/gi, replacement, /    /gi, replacement ]; }, applicable: function (html) { return /    |class="?Apple-tab-span/i.test(html); } }); var MSWordFormatCleaner = Cleaner.extend({ init: function () { this.replacements = [ /<\?xml[^>]*>/gi, '', //g, '', /"/g, '\'', /(?:
 [\s\r\n]+|
)*(<\/?(h[1-6]|hr|p|div|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|address|pre|form|blockquote|dl|dt|dd|dir|fieldset)[^>]*>)(?:
 [\s\r\n]+|
)*/g, '$1', /

/g, '

', /
(?!\n)/g, ' ', /]*)>(\s| )+]*>(\s| )*<\/tr>/gi, '', /]*>(\s| )*<\/tbody>/gi, '', /]*>(\s| )*<\/table>/gi, '', /

/g, '
', /^\s*( )+/gi, '', /( |]*>)+\s*$/gi, '', /mso-[^;"]*;?/gi, '', /<(\/?)b(\s[^>]*)?>/gi, '<$1strong$2>', /<(\/?)font(\s[^>]*)?>/gi, this.convertFontMatch, /<(\/?)i(\s[^>]*)?>/gi, '<$1em$2>', / <\/o:p>/gi, ' ', /<\/?(meta|link|style|o:|v:|x:)[^>]*>((?:.|\n)*?<\/(meta|link|style|o:|v:|x:)[^>]*>)?/gi, '', /<\/o>/g, '', /style=(["|'])\s*\1/g, '', /(]*>)?\n/g, function ($0, $1) { return $1 ? $0 : ' '; } ]; }, convertFontMatch: function (match, closing, args) { var faceRe = /face=['"]([^'"]+)['"]/i; var face = faceRe.exec(args); var family = args && face && face[1]; if (closing) { return '
'; } else if (family) { return ''; } else { return ''; } }, applicable: function (html) { return /class="?Mso/i.test(html) || /style="[^"]*mso-/i.test(html) || /urn:schemas-microsoft-com:office/.test(html); }, stripEmptyAnchors: function (html) { return html.replace(/]*)>\s*<\/a>/gi, function (a, attributes) { if (!attributes || attributes.indexOf('href') < 0) { return ''; } return a; }); }, listType: function (html) { var startingSymbol; if (/^(]*texhtml[^>]*>)?]*(Symbol|Wingdings)[^>]*>/i.test(html)) { startingSymbol = true; } html = html.replace(/<\/?\w+[^>]*>/g, '').replace(/ /g, '\xA0'); if (!startingSymbol && /^[\u2022\u00b7\u00a7\u00d8o]\u00a0+/.test(html) || startingSymbol && /^.\u00a0+/.test(html)) { return 'ul'; } if (/^\s*\w+[\.\)]\u00a0{2,}/.test(html)) { return 'ol'; } }, _convertToLi: function (p) { var content; if (p.childNodes.length == 1) { content = p.firstChild.innerHTML.replace(/^\w+[\.\)]( )+ /, ''); } else { dom.remove(p.firstChild); if (p.firstChild.nodeType == 3) { if (/^[ivx]+\.$/i.test(p.firstChild.nodeValue)) { dom.remove(p.firstChild); } } if (/^( |\s)+$/i.test(p.firstChild.innerHTML)) { dom.remove(p.firstChild); } content = p.innerHTML; } dom.remove(p); return dom.create(document, 'li', { innerHTML: content }); }, lists: function (placeholder) { var blockChildren = $(dom.blockElements.join(','), placeholder), lastMargin = -1, lastType, name, levels = { 'ul': {}, 'ol': {} }, li = placeholder, i, p, type, margin, list, key, child; for (i = 0; i < blockChildren.length; i++) { p = blockChildren[i]; type = this.listType(p.innerHTML); name = dom.name(p); if (name == 'td') { continue; } if (!type || name != 'p') { if (!p.innerHTML) { dom.remove(p); } else { levels = { 'ul': {}, 'ol': {} }; li = placeholder; lastMargin = -1; } continue; } margin = parseFloat(p.style.marginLeft || 0); list = levels[type][margin]; if (margin > lastMargin || !list) { list = dom.create(document, type); if (li == placeholder) { dom.insertBefore(list, p); } else { li.appendChild(list); } levels[type][margin] = list; } if (lastType != type) { for (key in levels) { for (child in levels[key]) { if ($.contains(list, levels[key][child])) { delete levels[key][child]; } } } } li = this._convertToLi(p); list.appendChild(li); lastMargin = margin; lastType = type; } }, removeAttributes: function (element) { var attributes = element.attributes, i = attributes.length; while (i--) { if (dom.name(attributes[i]) != 'colspan') { element.removeAttributeNode(attributes[i]); } } }, createColGroup: function (row) { var cells = row.cells; var table = $(row).closest('table'); var colgroup = table.children('colgroup'); if (cells.length < 2) { return; } else if (colgroup.length) { cells = colgroup.children(); colgroup[0].parentNode.removeChild(colgroup[0]); } colgroup = $($.map(cells, function (cell) { var width = cell.width; if (width && parseInt(width, 10) !== 0) { return kendo.format('', width); } return ''; }).join('')); if (!colgroup.is('colgroup')) { colgroup = $('').append(colgroup); } colgroup.prependTo(table); }, convertHeaders: function (row) { var cells = row.cells, i, boldedCells = $.map(cells, function (cell) { var child = $(cell).children('p').children('strong')[0]; if (child && dom.name(child) == 'strong') { return child; } }); if (boldedCells.length == cells.length) { for (i = 0; i < boldedCells.length; i++) { dom.unwrap(boldedCells[i]); } $(row).closest('table').find('colgroup').after('').end().find('thead').append(row); for (i = 0; i < cells.length; i++) { dom.changeTag(cells[i], 'th'); } } }, removeParagraphs: function (cells) { var i, j, len, cell, paragraphs; for (i = 0; i < cells.length; i++) { this.removeAttributes(cells[i]); cell = $(cells[i]); paragraphs = cell.children('p'); for (j = 0, len = paragraphs.length; j < len; j++) { if (j < len - 1) { dom.insertAfter(dom.create(document, 'br'), paragraphs[j]); } dom.unwrap(paragraphs[j]); } } }, removeDefaultColors: function (spans) { for (var i = 0; i < spans.length; i++) { if (/^\s*color:\s*[^;]*;?$/i.test(spans[i].style.cssText)) { dom.unwrap(spans[i]); } } }, tables: function (placeholder) { var tables = $(placeholder).find('table'), that = this, rows, firstRow, longestRow, i, j; for (i = 0; i < tables.length; i++) { rows = tables[i].rows; longestRow = firstRow = rows[0]; for (j = 1; j < rows.length; j++) { if (rows[j].cells.length > longestRow.cells.length) { longestRow = rows[j]; } } that.createColGroup(longestRow); that.convertHeaders(firstRow); that.removeAttributes(tables[i]); that.removeParagraphs(tables.eq(i).find('td,th')); that.removeDefaultColors(tables.eq(i).find('span')); } }, headers: function (placeholder) { var titles = $(placeholder).find('p.MsoTitle'); for (var i = 0; i < titles.length; i++) { dom.changeTag(titles[i], 'h1'); } }, clean: function (html) { var that = this, placeholder; html = Cleaner.fn.clean.call(that, html); html = that.stripEmptyAnchors(html); placeholder = dom.create(document, 'div', { innerHTML: html }); that.headers(placeholder); that.lists(placeholder); that.tables(placeholder); html = placeholder.innerHTML.replace(/(<[^>]*)\s+class="?[^"\s>]*"?/gi, '$1'); return html; } }); var WebkitFormatCleaner = Cleaner.extend({ init: function () { this.replacements = [ /\s+class="Apple-style-span[^"]*"/gi, '', /<(div|p|h[1-6])\s+style="[^"]*"/gi, '<$1', /^
(.*)<\/div>$/, '$1' ]; }, applicable: function (html) { return /class="?Apple-style-span|style="[^"]*-webkit-nbsp-mode/i.test(html); } }); var PrintCommand = Command.extend({ init: function (options) { Command.fn.init.call(this, options); this.managesUndoRedo = true; }, exec: function () { var editor = this.editor; if (kendo.support.browser.msie) { editor.document.execCommand('print', false, null); } else if (editor.window.print) { editor.window.print(); } } }); var ExportPdfCommand = Command.extend({ init: function (options) { this.async = true; Command.fn.init.call(this, options); }, exec: function () { var that = this; var range = this.lockRange(true); this.editor.saveAsPDF().then(function () { that.releaseRange(range); }); } }); extend(editorNS, { _finishUpdate: finishUpdate, Command: Command, GenericCommand: GenericCommand, InsertHtmlCommand: InsertHtmlCommand, InsertHtmlTool: InsertHtmlTool, TypingHandler: TypingHandler, SystemHandler: SystemHandler, BackspaceHandler: BackspaceHandler, Keyboard: Keyboard, Clipboard: Clipboard, Cleaner: Cleaner, TabCleaner: TabCleaner, MSWordFormatCleaner: MSWordFormatCleaner, WebkitFormatCleaner: WebkitFormatCleaner, PrintCommand: PrintCommand, ExportPdfCommand: ExportPdfCommand }); registerTool('insertHtml', new InsertHtmlTool({ template: new ToolTemplate({ template: EditorUtils.dropDownListTemplate, title: 'Insert HTML', initialValue: 'Insert HTML' }) })); registerTool('print', new Tool({ command: PrintCommand, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Print' }) })); registerTool('pdf', new Tool({ command: ExportPdfCommand, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Export PDF' }) })); }(window.kendo.jQuery)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/inlineformat', ['editor/system'], f); }(function () { (function ($) { var kendo = window.kendo, Class = kendo.Class, Editor = kendo.ui.editor, formats = kendo.ui.Editor.fn.options.formats, EditorUtils = Editor.EditorUtils, Tool = Editor.Tool, ToolTemplate = Editor.ToolTemplate, FormatTool = Editor.FormatTool, dom = Editor.Dom, RangeUtils = Editor.RangeUtils, extend = $.extend, registerTool = Editor.EditorUtils.registerTool, registerFormat = Editor.EditorUtils.registerFormat, KMARKER = 'k-marker'; var InlineFormatFinder = Class.extend({ init: function (format) { this.format = format; }, numberOfSiblings: function (referenceNode) { var textNodesCount = 0, elementNodesCount = 0, markerCount = 0, parentNode = referenceNode.parentNode, node; for (node = parentNode.firstChild; node; node = node.nextSibling) { if (node != referenceNode) { if (node.className == KMARKER) { markerCount++; } else if (node.nodeType == 3) { textNodesCount++; } else { elementNodesCount++; } } } if (markerCount > 1 && parentNode.firstChild.className == KMARKER && parentNode.lastChild.className == KMARKER) { return 0; } else { return elementNodesCount + textNodesCount; } }, findSuitable: function (sourceNode, skip) { if (!skip && this.numberOfSiblings(sourceNode) > 0) { return null; } var node = sourceNode.parentNode; var tags = this.format[0].tags; while (!dom.ofType(node, tags)) { if (this.numberOfSiblings(node) > 0) { return null; } node = node.parentNode; } return node; }, findFormat: function (sourceNode) { var format = this.format, attrEquals = dom.attrEquals, i, len, node, tags, attributes; for (i = 0, len = format.length; i < len; i++) { node = sourceNode; tags = format[i].tags; attributes = format[i].attr; if (node && dom.ofType(node, tags) && attrEquals(node, attributes)) { return node; } while (node) { node = dom.parentOfType(node, tags); if (node && attrEquals(node, attributes)) { return node; } } } return null; }, isFormatted: function (nodes) { var i, len; for (i = 0, len = nodes.length; i < len; i++) { if (this.findFormat(nodes[i])) { return true; } } return false; } }); var InlineFormatter = Class.extend({ init: function (format, values) { this.finder = new InlineFormatFinder(format); this.attributes = extend({}, format[0].attr, values); this.tag = format[0].tags[0]; }, wrap: function (node) { return dom.wrap(node, dom.create(node.ownerDocument, this.tag, this.attributes)); }, activate: function (range, nodes) { if (this.finder.isFormatted(nodes)) { this.split(range); this.remove(nodes); } else { this.apply(nodes); } }, toggle: function (range) { var nodes = RangeUtils.textNodes(range); if (nodes.length > 0) { this.activate(range, nodes); } }, apply: function (nodes) { var formatNodes = []; var i, l, node, formatNode; for (i = 0, l = nodes.length; i < l; i++) { node = nodes[i]; formatNode = this.finder.findSuitable(node); if (formatNode) { dom.attr(formatNode, this.attributes); } else { while (!dom.isBlock(node.parentNode) && node.parentNode.childNodes.length == 1) { node = node.parentNode; } formatNode = this.wrap(node); } formatNodes.push(formatNode); } this.consolidate(formatNodes); }, remove: function (nodes) { var i, l, formatNode; for (i = 0, l = nodes.length; i < l; i++) { formatNode = this.finder.findFormat(nodes[i]); if (formatNode) { if (this.attributes && this.attributes.style) { dom.unstyle(formatNode, this.attributes.style); if (!formatNode.style.cssText && !formatNode.attributes['class']) { dom.unwrap(formatNode); } } else { dom.unwrap(formatNode); } } } }, split: function (range) { var nodes = RangeUtils.textNodes(range); var l = nodes.length; var i, formatNode; if (l > 0) { for (i = 0; i < l; i++) { formatNode = this.finder.findFormat(nodes[i]); if (formatNode) { RangeUtils.split(range, formatNode, true); } } } }, consolidate: function (nodes) { var node, last; while (nodes.length > 1) { node = nodes.pop(); last = nodes[nodes.length - 1]; if (node.previousSibling && node.previousSibling.className == KMARKER) { last.appendChild(node.previousSibling); } if (node.tagName == last.tagName && node.previousSibling == last && node.style.cssText == last.style.cssText) { while (node.firstChild) { last.appendChild(node.firstChild); } dom.remove(node); } } } }); var GreedyInlineFormatFinder = InlineFormatFinder.extend({ init: function (format, greedyProperty) { this.format = format; this.greedyProperty = greedyProperty; InlineFormatFinder.fn.init.call(this, format); }, getInlineCssValue: function (node) { var attributes = node.attributes; var trim = $.trim; var i, l, attribute, name, attributeValue, css, pair, cssIndex, len; var propertyAndValue, property, value; if (!attributes) { return; } for (i = 0, l = attributes.length; i < l; i++) { attribute = attributes[i]; name = attribute.nodeName; attributeValue = attribute.nodeValue; if (attribute.specified && name == 'style') { css = trim(attributeValue || node.style.cssText).split(';'); for (cssIndex = 0, len = css.length; cssIndex < len; cssIndex++) { pair = css[cssIndex]; if (pair.length) { propertyAndValue = pair.split(':'); property = trim(propertyAndValue[0].toLowerCase()); value = trim(propertyAndValue[1]); if (property != this.greedyProperty) { continue; } return property.indexOf('color') >= 0 ? dom.toHex(value) : value; } } } } }, getFormatInner: function (node) { var $node = $(dom.isDataNode(node) ? node.parentNode : node); var parents = $node.parentsUntil('[contentEditable]').addBack().toArray().reverse(); var i, len, value; for (i = 0, len = parents.length; i < len; i++) { value = this.greedyProperty == 'className' ? parents[i].className : this.getInlineCssValue(parents[i]); if (value) { return value; } } return 'inherit'; }, getFormat: function (nodes) { var result = this.getFormatInner(nodes[0]), i, len; for (i = 1, len = nodes.length; i < len; i++) { if (result != this.getFormatInner(nodes[i])) { return ''; } } return result; }, isFormatted: function (nodes) { return this.getFormat(nodes) !== ''; } }); var GreedyInlineFormatter = InlineFormatter.extend({ init: function (format, values, greedyProperty) { InlineFormatter.fn.init.call(this, format, values); this.values = values; this.finder = new GreedyInlineFormatFinder(format, greedyProperty); if (greedyProperty) { this.greedyProperty = kendo.toCamelCase(greedyProperty); } }, activate: function (range, nodes) { var greedyProperty = this.greedyProperty; var action = 'apply'; this.split(range); if (greedyProperty && this.values.style[greedyProperty] == 'inherit') { action = 'remove'; } this[action](nodes); } }); var InlineFormatTool = FormatTool.extend({ init: function (options) { FormatTool.fn.init.call(this, extend(options, { finder: new InlineFormatFinder(options.format), formatter: function () { return new InlineFormatter(options.format); } })); } }); var DelayedExecutionTool = Tool.extend({ update: function (ui, nodes) { var list = ui.data(this.type); list.close(); list.value(this.finder.getFormat(nodes)); } }); var FontTool = DelayedExecutionTool.extend({ init: function (options) { Tool.fn.init.call(this, options); this.type = kendo.support.browser.msie || kendo.support.touch ? 'kendoDropDownList' : 'kendoComboBox'; this.format = [{ tags: ['span'] }]; this.finder = new GreedyInlineFormatFinder(this.format, options.cssAttr); }, command: function (commandArguments) { var options = this.options, format = this.format, style = {}; return new Editor.FormatCommand(extend(commandArguments, { formatter: function () { style[options.domAttr] = commandArguments.value; return new GreedyInlineFormatter(format, { style: style }, options.cssAttr); } })); }, initialize: function (ui, initOptions) { var editor = initOptions.editor, options = this.options, toolName = options.name, dataSource, defaultValue = []; if (options.defaultValue) { defaultValue = [{ text: editor.options.messages[options.defaultValue[0].text], value: options.defaultValue[0].value }]; } dataSource = defaultValue.concat(options.items ? options.items : editor.options[toolName] || []); ui[this.type]({ dataTextField: 'text', dataValueField: 'value', dataSource: dataSource, change: function () { Tool.exec(editor, toolName, this.value()); }, highlightFirst: false }); ui.closest('.k-widget').removeClass('k-' + toolName).find('*').addBack().attr('unselectable', 'on'); ui.data(this.type).value('inherit'); } }); var ColorTool = Tool.extend({ init: function (options) { Tool.fn.init.call(this, options); this.format = [{ tags: ['span'] }]; this.finder = new GreedyInlineFormatFinder(this.format, options.cssAttr); }, options: { palette: 'websafe' }, update: function () { this._widget.close(); }, command: function (commandArguments) { var options = this.options, format = this.format, style = {}; return new Editor.FormatCommand(extend(commandArguments, { formatter: function () { style[options.domAttr] = commandArguments.value; return new GreedyInlineFormatter(format, { style: style }, options.cssAttr); } })); }, initialize: function (ui, initOptions) { var editor = initOptions.editor, toolName = this.name, options = extend({}, ColorTool.fn.options, this.options), palette = options.palette; ui = this._widget = new kendo.ui.ColorPicker(ui, { toolIcon: 'k-' + options.name, palette: palette, change: function () { var color = ui.value(); if (color) { Tool.exec(editor, toolName, color); } editor.focus(); }, activate: function (e) { e.preventDefault(); ui.trigger('change'); } }); ui.wrapper.attr({ title: initOptions.title, unselectable: 'on' }).find('*').attr('unselectable', 'on'); } }); extend(Editor, { InlineFormatFinder: InlineFormatFinder, InlineFormatter: InlineFormatter, DelayedExecutionTool: DelayedExecutionTool, GreedyInlineFormatFinder: GreedyInlineFormatFinder, GreedyInlineFormatter: GreedyInlineFormatter, InlineFormatTool: InlineFormatTool, FontTool: FontTool, ColorTool: ColorTool }); registerFormat('bold', [ { tags: [ 'strong', 'b' ] }, { tags: ['span'], attr: { style: { fontWeight: 'bold' } } } ]); registerTool('bold', new InlineFormatTool({ key: 'B', ctrl: true, format: formats.bold, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Bold' }) })); registerFormat('italic', [ { tags: [ 'em', 'i' ] }, { tags: ['span'], attr: { style: { fontStyle: 'italic' } } } ]); registerTool('italic', new InlineFormatTool({ key: 'I', ctrl: true, format: formats.italic, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Italic' }) })); registerFormat('underline', [ { tags: ['span'], attr: { style: { textDecoration: 'underline' } } }, { tags: ['u'] } ]); registerTool('underline', new InlineFormatTool({ key: 'U', ctrl: true, format: formats.underline, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Underline' }) })); registerFormat('strikethrough', [ { tags: [ 'del', 'strike' ] }, { tags: ['span'], attr: { style: { textDecoration: 'line-through' } } } ]); registerTool('strikethrough', new InlineFormatTool({ format: formats.strikethrough, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Strikethrough' }) })); registerFormat('superscript', [{ tags: ['sup'] }]); registerTool('superscript', new InlineFormatTool({ format: formats.superscript, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Superscript' }) })); registerFormat('subscript', [{ tags: ['sub'] }]); registerTool('subscript', new InlineFormatTool({ format: formats.subscript, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Subscript' }) })); registerTool('foreColor', new ColorTool({ cssAttr: 'color', domAttr: 'color', name: 'foreColor', template: new ToolTemplate({ template: EditorUtils.colorPickerTemplate, title: 'Color' }) })); registerTool('backColor', new ColorTool({ cssAttr: 'background-color', domAttr: 'backgroundColor', name: 'backColor', template: new ToolTemplate({ template: EditorUtils.colorPickerTemplate, title: 'Background Color' }) })); registerTool('fontName', new FontTool({ cssAttr: 'font-family', domAttr: 'fontFamily', name: 'fontName', defaultValue: [{ text: 'fontNameInherit', value: 'inherit' }], template: new ToolTemplate({ template: EditorUtils.comboBoxTemplate, title: 'Font Name' }) })); registerTool('fontSize', new FontTool({ cssAttr: 'font-size', domAttr: 'fontSize', name: 'fontSize', defaultValue: [{ text: 'fontSizeInherit', value: 'inherit' }], template: new ToolTemplate({ template: EditorUtils.comboBoxTemplate, title: 'Font Size' }) })); }(window.kendo.jQuery)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/formatblock', ['editor/inlineformat'], f); }(function () { (function ($) { var kendo = window.kendo, Class = kendo.Class, extend = $.extend, Editor = kendo.ui.editor, formats = kendo.ui.Editor.fn.options.formats, dom = Editor.Dom, Command = Editor.Command, ToolTemplate = Editor.ToolTemplate, FormatTool = Editor.FormatTool, EditorUtils = Editor.EditorUtils, registerTool = EditorUtils.registerTool, registerFormat = EditorUtils.registerFormat, RangeUtils = Editor.RangeUtils; var BlockFormatFinder = Class.extend({ init: function (format) { this.format = format; }, contains: function (node, children) { var i, len, child; for (i = 0, len = children.length; i < len; i++) { child = children[i]; if (!child || !dom.isAncestorOrSelf(node, child)) { return false; } } return true; }, findSuitable: function (nodes) { var format = this.format, suitable = [], i, len, candidate; for (i = 0, len = nodes.length; i < len; i++) { for (var f = format.length - 1; f >= 0; f--) { candidate = dom.ofType(nodes[i], format[f].tags) ? nodes[i] : dom.closestEditableOfType(nodes[i], format[f].tags); if (candidate) { break; } } if (!candidate || candidate.contentEditable === 'true') { return []; } if ($.inArray(candidate, suitable) < 0) { suitable.push(candidate); } } for (i = 0, len = suitable.length; i < len; i++) { if (this.contains(suitable[i], suitable)) { return [suitable[i]]; } } return suitable; }, findFormat: function (sourceNode) { var format = this.format, i, len, node, tags, attributes; var editableParent = dom.editableParent(sourceNode); for (i = 0, len = format.length; i < len; i++) { node = sourceNode; tags = format[i].tags; attributes = format[i].attr; while (node && dom.isAncestorOf(editableParent, node)) { if (dom.ofType(node, tags) && dom.attrEquals(node, attributes)) { return node; } node = node.parentNode; } } return null; }, getFormat: function (nodes) { var that = this, findFormat = function (node) { return that.findFormat(dom.isDataNode(node) ? node.parentNode : node); }, result = findFormat(nodes[0]), i, len; if (!result) { return ''; } for (i = 1, len = nodes.length; i < len; i++) { if (result != findFormat(nodes[i])) { return ''; } } return result.nodeName.toLowerCase(); }, isFormatted: function (nodes) { for (var i = 0, len = nodes.length; i < len; i++) { if (!this.findFormat(nodes[i])) { return false; } } return true; } }); var BlockFormatter = Class.extend({ init: function (format, values) { this.format = format; this.values = values; this.finder = new BlockFormatFinder(format); }, wrap: function (tag, attributes, nodes) { var commonAncestor = nodes.length == 1 ? dom.blockParentOrBody(nodes[0]) : dom.commonAncestor.apply(null, nodes); if (dom.isInline(commonAncestor)) { commonAncestor = dom.blockParentOrBody(commonAncestor); } var ancestors = dom.significantChildNodes(commonAncestor), position = dom.findNodeIndex(ancestors[0]), wrapper = dom.create(commonAncestor.ownerDocument, tag, attributes), i, ancestor; for (i = 0; i < ancestors.length; i++) { ancestor = ancestors[i]; if (dom.isBlock(ancestor)) { dom.attr(ancestor, attributes); if (wrapper.childNodes.length) { dom.insertBefore(wrapper, ancestor); wrapper = wrapper.cloneNode(false); } position = dom.findNodeIndex(ancestor) + 1; continue; } wrapper.appendChild(ancestor); } if (wrapper.firstChild) { dom.insertAt(commonAncestor, wrapper, position); } }, apply: function (nodes) { var format, values = this.values; function attributes(format) { return extend({}, format && format.attr, values); } var images = dom.filter('img', nodes); var imageFormat = EditorUtils.formatByName('img', this.format); var imageAttributes = attributes(imageFormat); $.each(images, function () { dom.attr(this, imageAttributes); }); if (images.length == nodes.length) { return; } var nonImages = dom.filter('img', nodes, true); var formatNodes = this.finder.findSuitable(nonImages); if (formatNodes.length) { for (var i = 0, len = formatNodes.length; i < len; i++) { format = EditorUtils.formatByName(dom.name(formatNodes[i]), this.format); dom.attr(formatNodes[i], attributes(format)); } } else { format = this.format[0]; this.wrap(format.tags[0], attributes(format), nonImages); } }, remove: function (nodes) { var i, l, formatNode, namedFormat, name; for (i = 0, l = nodes.length; i < l; i++) { formatNode = this.finder.findFormat(nodes[i]); if (formatNode) { name = dom.name(formatNode); if (name == 'div' && !formatNode.getAttribute('class')) { dom.unwrap(formatNode); } else { namedFormat = EditorUtils.formatByName(name, this.format); if (namedFormat.attr.style) { dom.unstyle(formatNode, namedFormat.attr.style); } if (namedFormat.attr.className) { dom.removeClass(formatNode, namedFormat.attr.className); } } } } }, toggle: function (range) { var that = this, nodes = RangeUtils.nodes(range); if (that.finder.isFormatted(nodes)) { that.remove(nodes); } else { that.apply(nodes); } } }); var GreedyBlockFormatter = Class.extend({ init: function (format, values) { var that = this; that.format = format; that.values = values; that.finder = new BlockFormatFinder(format); }, apply: function (nodes) { var format = this.format; var blocks = dom.blockParents(nodes); var formatTag = format[0].tags[0]; var i, len, list, formatter, range; var element; var tagName; if (blocks.length) { for (i = 0, len = blocks.length; i < len; i++) { tagName = dom.name(blocks[i]); if (tagName == 'li') { list = blocks[i].parentNode; formatter = new Editor.ListFormatter(list.nodeName.toLowerCase(), formatTag); range = this.editor.createRange(); range.selectNode(blocks[i]); formatter.toggle(range); } else if (formatTag && (tagName == 'td' || blocks[i].attributes.contentEditable)) { new BlockFormatter(format, this.values).apply(blocks[i].childNodes); } else { element = dom.changeTag(blocks[i], formatTag); dom.attr(element, format[0].attr); } } } else { new BlockFormatter(format, this.values).apply(nodes); } }, toggle: function (range) { var nodes = RangeUtils.textNodes(range); if (!nodes.length) { range.selectNodeContents(range.commonAncestorContainer); nodes = RangeUtils.textNodes(range); if (!nodes.length) { nodes = dom.significantChildNodes(range.commonAncestorContainer); } } this.apply(nodes); } }); var FormatCommand = Command.extend({ init: function (options) { options.formatter = options.formatter(); Command.fn.init.call(this, options); } }); var BlockFormatTool = FormatTool.extend({ init: function (options) { FormatTool.fn.init.call(this, extend(options, { finder: new BlockFormatFinder(options.format), formatter: function () { return new BlockFormatter(options.format); } })); } }); extend(Editor, { BlockFormatFinder: BlockFormatFinder, BlockFormatter: BlockFormatter, GreedyBlockFormatter: GreedyBlockFormatter, FormatCommand: FormatCommand, BlockFormatTool: BlockFormatTool }); var listElements = [ 'ul', 'ol', 'li' ]; registerFormat('justifyLeft', [ { tags: dom.nonListBlockElements, attr: { style: { textAlign: 'left' } } }, { tags: ['img'], attr: { style: { 'float': 'left', display: '', marginLeft: '', marginRight: '' } } }, { tags: listElements, attr: { style: { textAlign: 'left', listStylePosition: '' } } } ]); registerTool('justifyLeft', new BlockFormatTool({ format: formats.justifyLeft, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Justify Left' }) })); registerFormat('justifyCenter', [ { tags: dom.nonListBlockElements, attr: { style: { textAlign: 'center' } } }, { tags: ['img'], attr: { style: { display: 'block', marginLeft: 'auto', marginRight: 'auto', 'float': '' } } }, { tags: listElements, attr: { style: { textAlign: 'center', listStylePosition: 'inside' } } } ]); registerTool('justifyCenter', new BlockFormatTool({ format: formats.justifyCenter, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Justify Center' }) })); registerFormat('justifyRight', [ { tags: dom.nonListBlockElements, attr: { style: { textAlign: 'right' } } }, { tags: ['img'], attr: { style: { 'float': 'right', display: '', marginLeft: '', marginRight: '' } } }, { tags: listElements, attr: { style: { textAlign: 'right', listStylePosition: 'inside' } } } ]); registerTool('justifyRight', new BlockFormatTool({ format: formats.justifyRight, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Justify Right' }) })); registerFormat('justifyFull', [ { tags: dom.nonListBlockElements, attr: { style: { textAlign: 'justify' } } }, { tags: ['img'], attr: { style: { display: 'block', marginLeft: 'auto', marginRight: 'auto', 'float': '' } } }, { tags: listElements, attr: { style: { textAlign: 'justify', listStylePosition: '' } } } ]); registerTool('justifyFull', new BlockFormatTool({ format: formats.justifyFull, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Justify Full' }) })); }(window.kendo.jQuery)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/linebreak', ['editor/formatblock'], f); }(function () { (function ($) { var kendo = window.kendo, extend = $.extend, editorNS = kendo.ui.editor, dom = editorNS.Dom, Command = editorNS.Command, Tool = editorNS.Tool, BlockFormatter = editorNS.BlockFormatter, normalize = dom.normalize, RangeUtils = editorNS.RangeUtils, registerTool = editorNS.EditorUtils.registerTool; var ParagraphCommand = Command.extend({ init: function (options) { this.options = options; Command.fn.init.call(this, options); }, _insertMarker: function (doc, range) { var marker = dom.create(doc, 'a'), container; marker.className = 'k-marker'; range.insertNode(marker); if (!marker.parentNode) { container = range.commonAncestorContainer; container.innerHTML = ''; container.appendChild(marker); } normalize(marker.parentNode); return marker; }, _moveFocus: function (range, candidate) { if (dom.isEmpty(candidate)) { range.setStartBefore(candidate); } else { range.selectNodeContents(candidate); var focusNode = RangeUtils.textNodes(range)[0]; if (!focusNode) { while (candidate.childNodes.length && !dom.is(candidate.firstChild, 'br')) { candidate = candidate.firstChild; } focusNode = candidate; } if (dom.isEmpty(focusNode)) { range.setStartBefore(focusNode); } else { if (dom.emptyNode(focusNode)) { focusNode.innerHTML = '\uFEFF'; } range.setStartBefore(focusNode.firstChild || focusNode); } } }, shouldTrim: function (range) { var blocks = 'p,h1,h2,h3,h4,h5,h6'.split(','), startInBlock = dom.parentOfType(range.startContainer, blocks), endInBlock = dom.parentOfType(range.endContainer, blocks); return startInBlock && !endInBlock || !startInBlock && endInBlock; }, _blankAfter: function (node) { while (node && (dom.isMarker(node) || dom.stripBom(node.nodeValue) === '')) { node = node.nextSibling; } return !node; }, exec: function () { var range = this.getRange(), doc = RangeUtils.documentFromRange(range), parent, previous, next, emptyParagraphContent = editorNS.emptyElementContent, paragraph, marker, li, heading, rng, shouldTrim = this.shouldTrim(range); range.deleteContents(); marker = this._insertMarker(doc, range); li = dom.closestEditableOfType(marker, ['li']); heading = dom.closestEditableOfType(marker, 'h1,h2,h3,h4,h5,h6'.split(',')); if (li) { if (dom.emptyNode(li)) { paragraph = dom.create(doc, 'p'); if (li.nextSibling) { rng = range.cloneRange(); rng.selectNode(li); RangeUtils.split(rng, li.parentNode); } dom.insertAfter(paragraph, li.parentNode); dom.remove(li.parentNode.childNodes.length == 1 ? li.parentNode : li); paragraph.innerHTML = emptyParagraphContent; next = paragraph; } } else if (heading && this._blankAfter(marker)) { paragraph = dom.create(doc, 'p'); dom.insertAfter(paragraph, heading); paragraph.innerHTML = emptyParagraphContent; dom.remove(marker); next = paragraph; } if (!next) { if (!(li || heading)) { new BlockFormatter([{ tags: ['p'] }]).apply([marker]); } range.selectNode(marker); parent = dom.parentOfType(marker, [li ? 'li' : heading ? dom.name(heading) : 'p']); RangeUtils.split(range, parent, shouldTrim); previous = parent.previousSibling; if (dom.is(previous, 'li') && previous.firstChild && !dom.is(previous.firstChild, 'br')) { previous = previous.firstChild; } next = parent.nextSibling; this.clean(previous); this.clean(next, { links: true }); if (dom.is(next, 'li') && next.firstChild && !dom.is(next.firstChild, 'br')) { next = next.firstChild; } dom.remove(parent); normalize(previous); } normalize(next); this._moveFocus(range, next); range.collapse(true); dom.scrollTo(next); RangeUtils.selectRange(range); }, clean: function (node, options) { var root = node; if (node.firstChild && dom.is(node.firstChild, 'br')) { dom.remove(node.firstChild); } if (dom.isDataNode(node) && !node.nodeValue) { node = node.parentNode; } if (node) { var siblings = false; while (node.firstChild && node.firstChild.nodeType == 1) { siblings = siblings || dom.significantNodes(node.childNodes).length > 1; node = node.firstChild; } if (!dom.isEmpty(node) && /^\s*$/.test(node.innerHTML) && !siblings) { $(root).find('.k-br').remove(); node.innerHTML = editorNS.emptyElementContent; } if (options && options.links) { while (node != root) { if (dom.is(node, 'a') && dom.emptyNode(node)) { dom.unwrap(node); break; } node = node.parentNode; } } } } }); var NewLineCommand = Command.extend({ init: function (options) { this.options = options; Command.fn.init.call(this, options); }, exec: function () { var range = this.getRange(); var br = dom.create(RangeUtils.documentFromRange(range), 'br'); var filler; var browser = kendo.support.browser; var oldIE = browser.msie && browser.version < 11; range.deleteContents(); range.insertNode(br); normalize(br.parentNode); if (!oldIE && (!br.nextSibling || dom.isWhitespace(br.nextSibling))) { filler = br.cloneNode(true); filler.className = 'k-br'; dom.insertAfter(filler, br); } range.setStartAfter(br); range.collapse(true); dom.scrollTo(br.nextSibling || br); RangeUtils.selectRange(range); } }); extend(editorNS, { ParagraphCommand: ParagraphCommand, NewLineCommand: NewLineCommand }); registerTool('insertLineBreak', new Tool({ key: 13, shift: true, command: NewLineCommand })); registerTool('insertParagraph', new Tool({ key: 13, command: ParagraphCommand })); }(window.kendo.jQuery)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/lists', ['editor/linebreak'], f); }(function () { (function ($) { var kendo = window.kendo, Class = kendo.Class, extend = $.extend, Editor = kendo.ui.editor, dom = Editor.Dom, RangeUtils = Editor.RangeUtils, EditorUtils = Editor.EditorUtils, Command = Editor.Command, ToolTemplate = Editor.ToolTemplate, FormatTool = Editor.FormatTool, BlockFormatFinder = Editor.BlockFormatFinder, textNodes = RangeUtils.textNodes, registerTool = Editor.EditorUtils.registerTool; var ListFormatFinder = BlockFormatFinder.extend({ init: function (tag) { this.tag = tag; var tags = this.tags = [ tag == 'ul' ? 'ol' : 'ul', tag ]; BlockFormatFinder.fn.init.call(this, [{ tags: tags }]); }, isFormatted: function (nodes) { var formatNodes = []; var formatNode, i; for (i = 0; i < nodes.length; i++) { formatNode = this.findFormat(nodes[i]); if (formatNode && dom.name(formatNode) == this.tag) { formatNodes.push(formatNode); } } if (formatNodes.length < 1) { return false; } if (formatNodes.length != nodes.length) { return false; } for (i = 0; i < formatNodes.length; i++) { if (formatNodes[i].parentNode != formatNode.parentNode) { break; } if (formatNodes[i] != formatNode) { return false; } } return true; }, findSuitable: function (nodes) { var candidate = this.findFormat(nodes[0]); if (candidate && dom.name(candidate) == this.tag) { return candidate; } return null; } }); var ListFormatter = Class.extend({ init: function (tag, unwrapTag) { var that = this; that.finder = new ListFormatFinder(tag); that.tag = tag; that.unwrapTag = unwrapTag; }, isList: function (node) { var name = dom.name(node); return name == 'ul' || name == 'ol' || name == 'dl'; }, wrap: function (list, nodes) { var li = dom.create(list.ownerDocument, 'li'), i, node; for (i = 0; i < nodes.length; i++) { node = nodes[i]; if (dom.is(node, 'li')) { list.appendChild(node); continue; } if (this.isList(node)) { while (node.firstChild) { list.appendChild(node.firstChild); } continue; } if (dom.is(node, 'td')) { while (node.firstChild) { li.appendChild(node.firstChild); } list.appendChild(li); node.appendChild(list); list = list.cloneNode(false); li = li.cloneNode(false); continue; } li.appendChild(node); if (dom.isBlock(node)) { list.appendChild(li); dom.unwrap(node); li = li.cloneNode(false); } } if (li.firstChild) { list.appendChild(li); } }, containsAny: function (parent, nodes) { for (var i = 0; i < nodes.length; i++) { if (dom.isAncestorOrSelf(parent, nodes[i])) { return true; } } return false; }, suitable: function (candidate, nodes) { if (candidate.className == 'k-marker') { var sibling = candidate.nextSibling; if (sibling && dom.isBlock(sibling)) { return false; } sibling = candidate.previousSibling; if (sibling && dom.isBlock(sibling)) { return false; } } return this.containsAny(candidate, nodes) || dom.isInline(candidate) || candidate.nodeType == 3; }, _parentLists: function (node) { var editable = dom.closestEditable(node); return $(node).parentsUntil(editable, 'ul,ol'); }, split: function (range) { var nodes = textNodes(range); var start, end, parents; if (nodes.length) { start = dom.parentOfType(nodes[0], ['li']); end = dom.parentOfType(nodes[nodes.length - 1], ['li']); range.setStartBefore(start); range.setEndAfter(end); for (var i = 0, l = nodes.length; i < l; i++) { var formatNode = this.finder.findFormat(nodes[i]); if (formatNode) { parents = this._parentLists(formatNode); if (parents.length) { RangeUtils.split(range, parents.last()[0], true); } else { RangeUtils.split(range, formatNode, true); } } } } }, merge: function (tag, formatNode) { var prev = formatNode.previousSibling, next; while (prev && (prev.className == 'k-marker' || prev.nodeType == 3 && dom.isWhitespace(prev))) { prev = prev.previousSibling; } if (prev && dom.name(prev) == tag) { while (formatNode.firstChild) { prev.appendChild(formatNode.firstChild); } dom.remove(formatNode); formatNode = prev; } next = formatNode.nextSibling; while (next && (next.className == 'k-marker' || next.nodeType == 3 && dom.isWhitespace(next))) { next = next.nextSibling; } if (next && dom.name(next) == tag) { while (formatNode.lastChild) { next.insertBefore(formatNode.lastChild, next.firstChild); } dom.remove(formatNode); } }, breakable: function (node) { return node != node.ownerDocument.body && !/table|tbody|tr|td/.test(dom.name(node)) && !node.attributes.contentEditable; }, applyOnSection: function (section, nodes) { var tag = this.tag; var commonAncestor = dom.closestSplittableParent(nodes); var ancestors = []; var formatNode = this.finder.findSuitable(nodes); if (!formatNode) { formatNode = new ListFormatFinder(tag == 'ul' ? 'ol' : 'ul').findSuitable(nodes); } var childNodes; if (/table|tbody/.test(dom.name(commonAncestor))) { childNodes = $.map(nodes, function (node) { return dom.parentOfType(node, ['td']); }); } else { childNodes = dom.significantChildNodes(commonAncestor); if ($.grep(childNodes, dom.isBlock).length) { childNodes = $.grep(childNodes, $.proxy(function (node) { return this.containsAny(node, nodes); }, this)); } if (!childNodes.length) { childNodes = nodes; } } function pushAncestor() { ancestors.push(this); } for (var i = 0; i < childNodes.length; i++) { var child = childNodes[i]; var suitable = (!formatNode || !dom.isAncestorOrSelf(formatNode, child)) && this.suitable(child, nodes); if (!suitable) { continue; } if (formatNode && this.isList(child)) { $.each(child.childNodes, pushAncestor); dom.remove(child); } else { ancestors.push(child); } } if (ancestors.length == childNodes.length && this.breakable(commonAncestor)) { ancestors = [commonAncestor]; } if (!formatNode) { formatNode = dom.create(commonAncestor.ownerDocument, tag); dom.insertBefore(formatNode, ancestors[0]); } this.wrap(formatNode, ancestors); if (!dom.is(formatNode, tag)) { dom.changeTag(formatNode, tag); } this.merge(tag, formatNode); }, apply: function (nodes) { var i = 0, sections = [], lastSection, lastNodes, section; do { section = dom.closestEditable(nodes[i], [ 'td', 'body' ]); if (!lastSection || section != lastSection) { if (lastSection) { sections.push({ section: lastSection, nodes: lastNodes }); } lastNodes = [nodes[i]]; lastSection = section; } else { lastNodes.push(nodes[i]); } i++; } while (i < nodes.length); sections.push({ section: lastSection, nodes: lastNodes }); for (i = 0; i < sections.length; i++) { this.applyOnSection(sections[i].section, sections[i].nodes); } }, unwrap: function (ul) { var fragment = ul.ownerDocument.createDocumentFragment(), unwrapTag = this.unwrapTag, parents, li, p, child; for (li = ul.firstChild; li; li = li.nextSibling) { p = dom.create(ul.ownerDocument, unwrapTag || 'p'); while (li.firstChild) { child = li.firstChild; if (dom.isBlock(child)) { if (p.firstChild) { fragment.appendChild(p); p = dom.create(ul.ownerDocument, unwrapTag || 'p'); } fragment.appendChild(child); } else { p.appendChild(child); } } if (p.firstChild) { fragment.appendChild(p); } } parents = this._parentLists(ul); if (parents[0]) { dom.insertAfter(fragment, parents.last()[0]); parents.last().remove(); } else { dom.insertAfter(fragment, ul); } dom.remove(ul); }, remove: function (nodes) { var formatNode; for (var i = 0, l = nodes.length; i < l; i++) { formatNode = this.finder.findFormat(nodes[i]); if (formatNode) { this.unwrap(formatNode); } } }, toggle: function (range) { var that = this, nodes = textNodes(range), ancestor = range.commonAncestorContainer; if (!nodes.length) { range.selectNodeContents(ancestor); nodes = textNodes(range); if (!nodes.length) { var text = ancestor.ownerDocument.createTextNode(''); range.startContainer.appendChild(text); nodes = [text]; range.selectNode(text.parentNode); } } if (that.finder.isFormatted(nodes)) { that.split(range); that.remove(nodes); } else { that.apply(nodes); } } }); var ListCommand = Command.extend({ init: function (options) { options.formatter = new ListFormatter(options.tag); Command.fn.init.call(this, options); } }); var ListTool = FormatTool.extend({ init: function (options) { this.options = options; FormatTool.fn.init.call(this, extend(options, { finder: new ListFormatFinder(options.tag) })); }, command: function (commandArguments) { return new ListCommand(extend(commandArguments, { tag: this.options.tag })); } }); extend(Editor, { ListFormatFinder: ListFormatFinder, ListFormatter: ListFormatter, ListCommand: ListCommand, ListTool: ListTool }); registerTool('insertUnorderedList', new ListTool({ tag: 'ul', template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Insert unordered list' }) })); registerTool('insertOrderedList', new ListTool({ tag: 'ol', template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Insert ordered list' }) })); }(window.kendo.jQuery)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/link', ['editor/lists'], f); }(function () { (function ($, undefined) { var kendo = window.kendo, Class = kendo.Class, extend = $.extend, proxy = $.proxy, Editor = kendo.ui.editor, dom = Editor.Dom, RangeUtils = Editor.RangeUtils, EditorUtils = Editor.EditorUtils, Command = Editor.Command, Tool = Editor.Tool, ToolTemplate = Editor.ToolTemplate, InlineFormatter = Editor.InlineFormatter, InlineFormatFinder = Editor.InlineFormatFinder, textNodes = RangeUtils.textNodes, registerTool = Editor.EditorUtils.registerTool; var LinkFormatFinder = Class.extend({ findSuitable: function (sourceNode) { return dom.parentOfType(sourceNode, ['a']); } }); var LinkFormatter = Class.extend({ init: function () { this.finder = new LinkFormatFinder(); }, apply: function (range, attributes) { var nodes = textNodes(range); var markers, doc, formatter, a, parent; if (attributes.innerHTML) { doc = RangeUtils.documentFromRange(range); markers = RangeUtils.getMarkers(range); range.deleteContents(); a = dom.create(doc, 'a', attributes); range.insertNode(a); parent = a.parentNode; if (dom.name(parent) == 'a') { dom.insertAfter(a, parent); } if (dom.emptyNode(parent)) { dom.remove(parent); } var ref = a; for (var i = 0; i < markers.length; i++) { dom.insertAfter(markers[i], ref); ref = markers[i]; } if (markers.length) { dom.insertBefore(doc.createTextNode('\uFEFF'), markers[1]); dom.insertAfter(doc.createTextNode('\uFEFF'), markers[1]); range.setStartBefore(markers[0]); range.setEndAfter(markers[markers.length - 1]); } } else { formatter = new InlineFormatter([{ tags: ['a'] }], attributes); formatter.finder = this.finder; formatter.apply(nodes); } } }); var UnlinkCommand = Command.extend({ init: function (options) { options.formatter = { toggle: function (range) { new InlineFormatter([{ tags: ['a'] }]).remove(textNodes(range)); } }; this.options = options; Command.fn.init.call(this, options); } }); var LinkCommand = Command.extend({ init: function (options) { this.options = options; Command.fn.init.call(this, options); this.formatter = new LinkFormatter(); if (!options.url) { this.attributes = null; this.async = true; } else { this.exec = function () { this.formatter.apply(options.range, { href: options.url, innerHTML: options.text || options.url, target: options.target }); }; } }, _dialogTemplate: function () { return kendo.template('
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
')({ messages: this.editor.options.messages }); }, exec: function () { var messages = this.editor.options.messages; this._initialText = ''; this._range = this.lockRange(true); var nodes = textNodes(this._range); var a = nodes.length ? this.formatter.finder.findSuitable(nodes[0]) : null; var img = nodes.length && dom.name(nodes[0]) == 'img'; var dialog = this.createDialog(this._dialogTemplate(), { title: messages.createLink, close: proxy(this._close, this), visible: false }); if (a) { this._range.selectNodeContents(a); nodes = textNodes(this._range); } this._initialText = this.linkText(nodes); dialog.find('.k-dialog-insert').click(proxy(this._apply, this)).end().find('.k-dialog-close').click(proxy(this._close, this)).end().find('.k-edit-field input').keydown(proxy(this._keydown, this)).end().find('#k-editor-link-url').val(this.linkUrl(a)).end().find('#k-editor-link-text').val(this._initialText).end().find('#k-editor-link-title').val(a ? a.title : '').end().find('#k-editor-link-target').attr('checked', a ? a.target == '_blank' : false).end().find('.k-editor-link-text-row').toggle(!img); this._dialog = dialog.data('kendoWindow').center().open(); $('#k-editor-link-url', dialog).focus().select(); }, _keydown: function (e) { var keys = kendo.keys; if (e.keyCode == keys.ENTER) { this._apply(e); } else if (e.keyCode == keys.ESC) { this._close(e); } }, _apply: function (e) { var element = this._dialog.element; var href = $('#k-editor-link-url', element).val(); var title, text, target; var textInput = $('#k-editor-link-text', element); if (href && href != 'http://') { if (href.indexOf('@') > 0 && !/^(\w+:)|(\/\/)/i.test(href)) { href = 'mailto:' + href; } this.attributes = { href: href }; title = $('#k-editor-link-title', element).val(); if (title) { this.attributes.title = title; } if (textInput.is(':visible')) { text = textInput.val(); if (!text && !this._initialText) { this.attributes.innerHTML = href; } else if (text && text !== this._initialText) { this.attributes.innerHTML = dom.stripBom(text); } } target = $('#k-editor-link-target', element).is(':checked'); this.attributes.target = target ? '_blank' : null; this.formatter.apply(this._range, this.attributes); } this._close(e); if (this.change) { this.change(); } }, _close: function (e) { e.preventDefault(); this._dialog.destroy(); dom.windowFromDocument(RangeUtils.documentFromRange(this._range)).focus(); this.releaseRange(this._range); }, linkUrl: function (anchor) { if (anchor) { return anchor.getAttribute('href', 2); } return 'http://'; }, linkText: function (nodes) { var text = ''; var i; for (i = 0; i < nodes.length; i++) { text += nodes[i].nodeValue; } return dom.stripBom(text || ''); }, redo: function () { var range = this.lockRange(true); this.formatter.apply(range, this.attributes); this.releaseRange(range); } }); var UnlinkTool = Tool.extend({ init: function (options) { this.options = options; this.finder = new InlineFormatFinder([{ tags: ['a'] }]); Tool.fn.init.call(this, $.extend(options, { command: UnlinkCommand })); }, initialize: function (ui, options) { Tool.fn.initialize.call(this, ui, options); ui.addClass('k-state-disabled'); }, update: function (ui, nodes) { ui.toggleClass('k-state-disabled', !this.finder.isFormatted(nodes)).removeClass('k-state-hover'); } }); extend(kendo.ui.editor, { LinkFormatFinder: LinkFormatFinder, LinkFormatter: LinkFormatter, UnlinkCommand: UnlinkCommand, LinkCommand: LinkCommand, UnlinkTool: UnlinkTool }); registerTool('createLink', new Tool({ key: 'K', ctrl: true, command: LinkCommand, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Create Link' }) })); registerTool('unlink', new UnlinkTool({ key: 'K', ctrl: true, shift: true, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Remove Link' }) })); }(window.kendo.jQuery)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/file', [ 'kendo.filebrowser', 'editor/link' ], f); }(function () { (function ($, undefined) { var kendo = window.kendo, extend = $.extend, Editor = kendo.ui.editor, EditorUtils = Editor.EditorUtils, dom = Editor.Dom, registerTool = EditorUtils.registerTool, ToolTemplate = Editor.ToolTemplate, RangeUtils = Editor.RangeUtils, Command = Editor.Command, LinkFormatter = Editor.LinkFormatter, textNodes = RangeUtils.textNodes, keys = kendo.keys, KEDITORFILEURL = '#k-editor-file-url', KEDITORFILETITLE = '#k-editor-file-title'; var FileCommand = Command.extend({ init: function (options) { var that = this; Command.fn.init.call(that, options); that.formatter = new LinkFormatter(); that.async = true; that.attributes = {}; }, insertFile: function (file, range) { var attributes = this.attributes; var doc = RangeUtils.documentFromRange(range); if (attributes.href && attributes.href != 'http://') { if (!file) { file = dom.create(doc, 'a', { href: attributes.href }); file.innerHTML = attributes.innerHTML; range.deleteContents(); range.insertNode(file); if (!file.nextSibling) { dom.insertAfter(doc.createTextNode('\uFEFF'), file); } range.setStartAfter(file); range.setEndAfter(file); RangeUtils.selectRange(range); return true; } else { dom.attr(file, attributes); } } return false; }, _dialogTemplate: function (showBrowser) { return kendo.template('
' + '# if (showBrowser) { #' + '
' + '# } #' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '' + '
' + '
')({ messages: this.editor.options.messages, showBrowser: showBrowser }); }, redo: function () { var that = this, range = that.lockRange(); this.formatter.apply(range, this.attributes); that.releaseRange(range); }, exec: function () { var that = this, range = that.lockRange(), nodes = textNodes(range), applied = false, file = nodes.length ? this.formatter.finder.findSuitable(nodes[0]) : null, dialog, options = that.editor.options, messages = options.messages, fileBrowser = options.fileBrowser, showBrowser = !!(kendo.ui.FileBrowser && fileBrowser && fileBrowser.transport && fileBrowser.transport.read !== undefined), dialogOptions = { title: messages.insertFile, visible: false, resizable: showBrowser }; function apply(e) { var element = dialog.element, href = element.find(KEDITORFILEURL).val().replace(/ /g, '%20'), innerHTML = element.find(KEDITORFILETITLE).val(); that.attributes = { href: href, innerHTML: innerHTML !== '' ? innerHTML : href }; applied = that.insertFile(file, range); close(e); if (that.change) { that.change(); } } function close(e) { e.preventDefault(); dialog.destroy(); dom.windowFromDocument(RangeUtils.documentFromRange(range)).focus(); if (!applied) { that.releaseRange(range); } } function keyDown(e) { if (e.keyCode == keys.ENTER) { apply(e); } else if (e.keyCode == keys.ESC) { close(e); } } dialogOptions.close = close; if (showBrowser) { dialogOptions.width = 750; } dialog = this.createDialog(that._dialogTemplate(showBrowser), dialogOptions).toggleClass('k-filebrowser-dialog', showBrowser).find('.k-dialog-insert').click(apply).end().find('.k-dialog-close').click(close).end().find('.k-edit-field input').keydown(keyDown).end().find(KEDITORFILEURL).val(file ? file.getAttribute('href', 2) : 'http://').end().find(KEDITORFILETITLE).val(file ? file.title : '').end().data('kendoWindow'); if (showBrowser) { that._fileBrowser = new kendo.ui.FileBrowser(dialog.element.find('.k-filebrowser'), extend({}, fileBrowser, { change: function () { dialog.element.find(KEDITORFILEURL).val(this.value()); }, apply: apply })); } dialog.center().open(); dialog.element.find(KEDITORFILEURL).focus().select(); } }); kendo.ui.editor.FileCommand = FileCommand; registerTool('insertFile', new Editor.Tool({ command: FileCommand, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Insert File' }) })); }(window.kendo.jQuery)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/image', [ 'kendo.imagebrowser', 'editor/link' ], f); }(function () { (function ($, undefined) { var kendo = window.kendo, extend = $.extend, Editor = kendo.ui.editor, EditorUtils = Editor.EditorUtils, dom = Editor.Dom, registerTool = EditorUtils.registerTool, ToolTemplate = Editor.ToolTemplate, RangeUtils = Editor.RangeUtils, Command = Editor.Command, keys = kendo.keys, KEDITORIMAGEURL = '#k-editor-image-url', KEDITORIMAGETITLE = '#k-editor-image-title', KEDITORIMAGEWIDTH = '#k-editor-image-width', KEDITORIMAGEHEIGHT = '#k-editor-image-height'; var ImageCommand = Command.extend({ init: function (options) { var that = this; Command.fn.init.call(that, options); that.async = true; that.attributes = {}; }, insertImage: function (img, range) { var attributes = this.attributes; var doc = RangeUtils.documentFromRange(range); if (attributes.src && attributes.src != 'http://') { var removeIEAttributes = function () { setTimeout(function () { if (!attributes.width) { img.removeAttribute('width'); } if (!attributes.height) { img.removeAttribute('height'); } img.removeAttribute('complete'); }); }; if (!img) { img = dom.create(doc, 'img', attributes); img.onload = img.onerror = removeIEAttributes; range.deleteContents(); range.insertNode(img); if (!img.nextSibling) { dom.insertAfter(doc.createTextNode('\uFEFF'), img); } removeIEAttributes(); range.setStartAfter(img); range.setEndAfter(img); RangeUtils.selectRange(range); return true; } else { img.onload = img.onerror = removeIEAttributes; dom.attr(img, attributes); removeIEAttributes(); } } return false; }, _dialogTemplate: function (showBrowser) { return kendo.template('
' + '# if (showBrowser) { #' + '
' + '# } #' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '' + '
' + '
')({ messages: this.editor.options.messages, showBrowser: showBrowser }); }, redo: function () { var that = this, range = that.lockRange(); if (!that.insertImage(RangeUtils.image(range), range)) { that.releaseRange(range); } }, exec: function () { var that = this, range = that.lockRange(), applied = false, img = RangeUtils.image(range), imageWidth = img && img.getAttribute('width') || '', imageHeight = img && img.getAttribute('height') || '', dialog, options = that.editor.options, messages = options.messages, imageBrowser = options.imageBrowser, showBrowser = !!(kendo.ui.ImageBrowser && imageBrowser && imageBrowser.transport && imageBrowser.transport.read !== undefined), dialogOptions = { title: messages.insertImage, visible: false, resizable: showBrowser }; function apply(e) { var element = dialog.element, w = parseInt(element.find(KEDITORIMAGEWIDTH).val(), 10), h = parseInt(element.find(KEDITORIMAGEHEIGHT).val(), 10); that.attributes = { src: element.find(KEDITORIMAGEURL).val().replace(/ /g, '%20'), alt: element.find(KEDITORIMAGETITLE).val() }; that.attributes.width = null; that.attributes.height = null; if (!isNaN(w) && w > 0) { that.attributes.width = w; } if (!isNaN(h) && h > 0) { that.attributes.height = h; } applied = that.insertImage(img, range); close(e); if (that.change) { that.change(); } } function close(e) { e.preventDefault(); dialog.destroy(); dom.windowFromDocument(RangeUtils.documentFromRange(range)).focus(); if (!applied) { that.releaseRange(range); } } function keyDown(e) { if (e.keyCode == keys.ENTER) { apply(e); } else if (e.keyCode == keys.ESC) { close(e); } } dialogOptions.close = close; if (showBrowser) { dialogOptions.width = 750; } dialog = this.createDialog(that._dialogTemplate(showBrowser), dialogOptions).toggleClass('k-filebrowser-dialog', showBrowser).find('.k-dialog-insert').click(apply).end().find('.k-dialog-close').click(close).end().find('.k-edit-field input').keydown(keyDown).end().find(KEDITORIMAGEURL).val(img ? img.getAttribute('src', 2) : 'http://').end().find(KEDITORIMAGETITLE).val(img ? img.alt : '').end().find(KEDITORIMAGEWIDTH).val(imageWidth).end().find(KEDITORIMAGEHEIGHT).val(imageHeight).end().data('kendoWindow'); if (showBrowser) { this._imageBrowser = new kendo.ui.ImageBrowser(dialog.element.find('.k-imagebrowser'), extend({}, imageBrowser, { change: function () { dialog.element.find(KEDITORIMAGEURL).val(this.value()); }, apply: apply })); } dialog.center().open(); dialog.element.find(KEDITORIMAGEURL).focus().select(); } }); kendo.ui.editor.ImageCommand = ImageCommand; registerTool('insertImage', new Editor.Tool({ command: ImageCommand, template: new ToolTemplate({ template: EditorUtils.buttonTemplate, title: 'Insert Image' }) })); }(window.kendo.jQuery)); }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); })); (function (f, define) { define('editor/components', ['editor/image'], f); }(function () { (function ($, undefined) { var kendo = window.kendo, DropDownList = kendo.ui.DropDownList, dom = kendo.ui.editor.Dom; var SelectBox = DropDownList.extend({ init: function (element, options) { var that = this; DropDownList.fn.init.call(that, element, options); if (kendo.support.mobileOS.ios) { this._initSelectOverlay(); this.bind('dataBound', $.proxy(this._initSelectOverlay, this)); } that.text(that.options.title); that.bind('open', function () { if (that.options.autoSize) { var list = that.list, listWidth; list.css({ whiteSpace: 'nowrap', width: 'auto' }); listWidth = list.width(); if (listWidth) { listWidth += 20; } else { listWidth = that._listWidth; } list.css('width', listWidth + kendo.support.scrollbar()); that._listWidth = listWidth; } }); }, options: { name: 'SelectBox', index: -1 }, _initSelectOverlay: function () { var selectBox = this; var value = selectBox.value(); var view = this.dataSource.view(); var item; var html = ''; var encode = kendo.htmlEncode; for (var i = 0; i < view.length; i++) { item = view[i]; html += '