/* Redactor v9.0 beta 2 Updated: February 13, 2013 http://redactorjs.com/ Copyright (c) 2009-2013, Imperavi Inc. License: http://imperavi.com/redactor/license/ Usage: $('#content').redactor(); */ var rwindow, rdocument; if (typeof RELANG === 'undefined') { var RELANG = {}; } var RLANG = { html: 'HTML', video: 'Insert Video', image: 'Insert Image', table: 'Table', link: 'Link', link_insert: 'Insert link', unlink: 'Unlink', formatting: 'Formatting', paragraph: 'Paragraph', quote: 'Quote', code: 'Code', header1: 'Header 1', header2: 'Header 2', header3: 'Header 3', header4: 'Header 4', bold: 'Bold', italic: 'Italic', fontcolor: 'Font Color', backcolor: 'Back Color', unorderedlist: 'Unordered List', orderedlist: 'Ordered List', outdent: 'Outdent', indent: 'Indent', cancel: 'Cancel', insert: 'Insert', save: 'Save', _delete: 'Delete', insert_table: 'Insert Table', insert_row_above: 'Add Row Above', insert_row_below: 'Add Row Below', insert_column_left: 'Add Column Left', insert_column_right: 'Add Column Right', delete_column: 'Delete Column', delete_row: 'Delete Row', delete_table: 'Delete Table', rows: 'Rows', columns: 'Columns', add_head: 'Add Head', delete_head: 'Delete Head', title: 'Title', image_position: 'Position', none: 'None', left: 'Left', right: 'Right', image_web_link: 'Image Web Link', text: 'Text', mailto: 'Email', web: 'URL', video_html_code: 'Video Embed Code', file: 'Insert File', upload: 'Upload', download: 'Download', choose: 'Choose', or_choose: 'Or choose', drop_file_here: 'Drop file here', align_left: 'Align text to the left', align_center: 'Center text', align_right: 'Align text to the right', align_justify: 'Justify text', horizontalrule: 'Insert Horizontal Rule', deleted: 'Deleted', anchor: 'Anchor', link_new_tab: 'Open link in new tab', underline: 'Underline', alignment: 'Alignment', filename: 'Name (optional)' }; 'use strict'; (function($){ // Plugin $.fn.redactor = function(options) { var val = []; var args = Array.prototype.slice.call(arguments, 1); if (typeof options === 'string') { this.each(function() { var instance = $.data(this, 'redactor'); if (typeof instance !== 'undefined') { var arr = options.split('.'); var func = arr.length == 1 ? instance[options] : instance[arr[0]][arr[1]]; if ($.isFunction(func)) { var methodVal = func.call(instance, args); if (methodVal !== undefined && methodVal !== instance) { val.push(methodVal); } } } }); } else { this.each(function() { if (!$.data(this, 'redactor')) { $.data(this, 'redactor', new Redactor(this, options)); } }); } if (val.length == 0) { return this; } else if (val.length == 1) { return val[0]; } else { return val; } }; // Initialization var Redactor = function(el, options) { this.$element = this.$el = $(el); // Lang if (typeof options !== 'undefined' && typeof options.lang !== 'undefined' && typeof RELANG[options.lang] !== 'undefined') { RLANG = $.extend({}, RLANG, RELANG[options.lang]); } // Options this.opts = $.extend({ iframe: false, fullpage: false, css: false, // url lang: 'en', direction: 'ltr', // ltr or rtl callback: false, // function keyupCallback: false, // function keydownCallback: false, // function execCommandCallback: false, // function syncBeforeCallback: false, // function syncAfterCallback: false, // function focus: false, tabindex: false, autoresize: true, minHeight: false, plugins: false, // array air: false, airButtons: ['formatting', '|', 'bold', 'italic', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'fontcolor', 'backcolor'], mobile: true, wym: false, cleanup: true, source: true, shortcuts: true, visual: true, placeholder: false, linebreaks: false, paragraphy: true, convertDivs: false, convertLinks: true, formattingPre: false, autosave: false, // false or url autosaveCallback: false, // function interval: 60, // seconds fixed: false, fixedTop: 0, // pixels fixedBox: false, toolbarExternal: false, // ID selector linkAnchor: false, linkEmail: false, imageGetJson: false, // url (ex. /folder/images.json ) or false imageUpload: false, // url imageUploadCallback: false, // function imageUploadErrorCallback: false, // function imageDeleteCallback: false, // function fileUpload: false, // url fileUploadCallback: false, // function fileUploadErrorCallback: false, // function uploadCrossDomain: false, uploadFields: false, observeImages: true, overlay: true, // modal overlay allowedTags: false, deniedTags: false, clearTags: ['script', 'html', 'head', 'title', 'link', 'body', 'style', 'meta', 'applet'], boldTag: 'strong', italicTag: 'em', buttonsCustom: {}, buttonsAdd: [], buttons: ['html', '|', 'formatting', '|', 'bold', 'italic', 'deleted', 'underline', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'image', 'video', 'file', 'table', 'link', '|', 'fontcolor', 'backcolor', '|', 'alignment', '|', 'horizontalrule'], // 'underline', 'alignleft', 'aligncenter', 'alignright', 'justify' formattingTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4'], activeButtons: ['deleted', 'italic', 'bold', 'underline', 'unorderedlist', 'orderedlist', 'table'], // 'alignleft', 'aligncenter', 'alignright', 'justify' activeButtonsStates: { b: 'bold', strong: 'bold', i: 'italic', em: 'italic', del: 'deleted', strike: 'deleted', ul: 'unorderedlist', ol: 'orderedlist', u: 'underline', table: 'table' }, colors: [ '#ffffff', '#000000', '#eeece1', '#1f497d', '#4f81bd', '#c0504d', '#9bbb59', '#8064a2', '#4bacc6', '#f79646', '#ffff00', '#f2f2f2', '#7f7f7f', '#ddd9c3', '#c6d9f0', '#dbe5f1', '#f2dcdb', '#ebf1dd', '#e5e0ec', '#dbeef3', '#fdeada', '#fff2ca', '#d8d8d8', '#595959', '#c4bd97', '#8db3e2', '#b8cce4', '#e5b9b7', '#d7e3bc', '#ccc1d9', '#b7dde8', '#fbd5b5', '#ffe694', '#bfbfbf', '#3f3f3f', '#938953', '#548dd4', '#95b3d7', '#d99694', '#c3d69b', '#b2a2c7', '#b7dde8', '#fac08f', '#f2c314', '#a5a5a5', '#262626', '#494429', '#17365d', '#366092', '#953734', '#76923c', '#5f497a', '#92cddc', '#e36c09', '#c09100', '#7f7f7f', '#0c0c0c', '#1d1b10', '#0f243e', '#244061', '#632423', '#4f6128', '#3f3151', '#31859b', '#974806', '#7f6000'], // private textareamode: false, buffer: false, emptyHtml: '
', invisibleSpace: '', alignmentTags: ['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'P', 'TD', 'DIV', 'BLOCKQUOTE'], // modal windows container modal_file: String() + '' + text + '
'); if (text != '') { var node2 = $('' + this.opts.invisibleSpace + '
'); $(element).replaceWith(node1); node1.after(node2); this.selection.start.call(this, node2); } else { $(element).replaceWith(node1); this.selection.end.call(this, node1); } this.sync(); return false; } else if ($(element).closest('h1, h2, h3, h4, h5, h6, ol, ul, li, p, td', this.$editor[0]).size() == 0 && !this.utils.browser.call(this, 'mozilla')) { // Inserting br on Enter e.preventDefault(); this.format.insertLineBreak.call(this); return false; } else { // Native line break for blocks elements h1, h2, h3, h4, h5, h6, ol, ul, li, p, td setTimeout($.proxy(this.format.newLine, this), 1); } } else if (key === 13 && (e.ctrlKey || e.shiftKey)) // Shift+Enter or Ctrl+Enter { this.buffer.set.call(this); e.preventDefault(); this.format.insertLineBreak.call(this); } // SHORCTCUTS if (ctrl) { if (key == 65) { this.selectall = true; } else if (key != 91 && key != 17) { this.selectall = false; } this.shortcuts.set.call(this, e, key); } // Tab if (key === 9 && this.opts.shortcuts) { e.preventDefault(); if (pre === true && !e.shiftKey) { this.buffer.set.call(this); this.insert.nodeAtCaret.call(this, document.createTextNode('\t')); this.sync(); return false; } else { if (!e.shiftKey) { this.indenting.indent.call(this); return false; } else { this.indenting.outdent.call(this); return false; } } } }, this)); this.$editor.on('keyup.redactor', $.proxy(function(e) { var key = e.which; // convert links if (this.opts.convertLinks && key === 13) { this.$editor.linkify(); } // callback as you type if (typeof this.opts.keyupCallback === 'function') { this.opts.keyupCallback(this, e); } // if empty if (this.opts.linebreaks === false && (key === 8 || key === 46)) { return this.format.empty.call(this, e); } this.sync(); }, this)); // autosave if (this.opts.autosave !== false) { this.autosave(); } // observers setTimeout($.proxy(this.observe.start, this), 1); // FF fix if (this.utils.browser.call(this, 'mozilla')) { try { this.document.execCommand('enableObjectResizing', false, false); this.document.execCommand('enableInlineTableEditing', false, false); } catch (e) {} } // focus if (this.opts.focus) { setTimeout($.proxy(this.focus.set, this), 100); } // fixed if (this.opts.fixed) { this.observe.scroll.call(this); $(document).scroll($.proxy(this.observe.scroll, this)); } // code mode if (this.opts.visual === false) { setTimeout($.proxy(function() { this.opts.visual = true; this.toggle(); }, this), 200); } // callback if (typeof this.opts.callback === 'function') { this.opts.callback(this); } if (this.opts.toolbar !== false) { this.$toolbar.find('a').attr('tabindex', '-1'); } }, // SHORTCUTS shortcuts: { set: function(e, key) { if (key === 90) { if (this.opts.buffer.length != 0) { e.preventDefault(); this.buffer.get.call(this); } else if (e.shiftKey) { if (this.opts.rebuffer.length != 0) { e.preventDefault(); this.buffer.redo.call(this); } else this.shortcuts.load.call(this, e, 'redo'); // Ctrl + Shift + z } else this.shortcuts.load.call(this, e, 'undo'); // Ctrl + z } if (this.opts.shortcuts) { if (key === 77) this.shortcuts.load.call(this, e, 'removeFormat'); // Ctrl + m else if (key === 66) this.shortcuts.load.call(this, e, 'bold'); // Ctrl + b else if (key === 73) this.shortcuts.load.call(this, e, 'italic'); // Ctrl + i else if (key === 74) this.shortcuts.load.call(this, e, 'insertunorderedlist'); // Ctrl + j else if (key === 75) this.shortcuts.load.call(this, e, 'insertorderedlist'); // Ctrl + k else if (key === 76) this.shortcuts.load.call(this, e, 'superscript'); // Ctrl + l else if (key === 72) this.shortcuts.load.call(this, e, 'subscript'); // Ctrl + h } }, load: function(e, cmd) { e.preventDefault(); this.exec.command.call(this, cmd, false); } }, // BUILD build: { start: function() { // content this.content = ''; // container this.$box = $(''); // air box if (this.opts.air) { this.$air = $(''); } // mobile if (this.utils.oldIE.call(this) || (this.opts.mobile === false && this.utils.isMobile.call(this) === true)) { if (this.$el.get(0).tagName === 'TEXTAREA') { this.$box.insertAfter(this.$el).append(this.$el); } else { this.$editor = this.$el; this.$el = $('').css('height', this.height).val($.trim(this.$editor.html())); this.$editor.hide(); this.$box.insertAfter(this.$editor).append(this.$el); } return true; } // build if (this.opts.iframe) { this.iframe.start.call(this); } else if (this.$el.get(0).tagName === 'TEXTAREA') { this.opts.textrareamode = true; this.build.textarea.call(this); } else { this.build.element.call(this); } if (!this.opts.iframe) { this.build.options.call(this); this.afterBuild.call(this); } }, textarea: function() { this.$editor = $(''); this.build.addClasses.call(this, this.$editor); this.content = $.trim(this.$el.val()); this.$el.attr('dir', this.opts.direction); this.$box.insertAfter(this.$el).append(this.$editor).append(this.$el); this.build.enable.call(this); }, element: function() { this.$editor = this.$el; this.$el = $('').attr('dir', this.opts.direction).css('height', this.height); this.content = $.trim(this.$editor.html()); this.$box.insertAfter(this.$editor).append(this.$editor).append(this.$el); this.build.enable.call(this); }, addClasses: function(el) { var classlist = this.$el.get(0).className.split(/\s+/); $.each(classlist, function(i,s) { el.addClass('redactor_' + s); }); }, enable: function() { this.$editor.addClass('redactor_editor').attr('contenteditable', true).attr('dir', this.opts.direction); this.$el.hide(); this.build.clean.call(this); this.placeholder.start.call(this); this.code.set.call(this, this.content, false); }, options: function() { var $el = this.$editor; if (this.opts.iframe) $el = this.$frame; if (this.opts.tabindex) $el.attr('tabindex', this.opts.tabindex); if (this.opts.minHeight) $el.css('min-height', this.opts.minHeight + 'px'); if (this.opts.wym) this.$editor.addClass('redactor_editor_wym'); if (!this.opts.autoresize) $el.css('height', this.height); }, clean: function(html) { if (typeof html === 'undefined') html = this.content; html = this.clean.savePreCode.call(this, html); if (!this.opts.fullpage) html = this.clean.stripTags.call(this, html, false); if (this.opts.paragraphy) html = this.clean.paragraphy.call(this, html); if (this.opts.linebreaks) html = html.replace(/\n/g, '