$.fn.ImperaviLanguages = { ru : { html : 'Код', // Styles dropdown menu styles : { name : 'Стили', paragraph : 'Параграф', quote : 'Цитата', code : 'Код', h2 : 'Заголовок 2', h3 : 'Заголовок 3', h4 : 'Заголовок 4', h5 : 'Заголовок 5', h6 : 'Заголовок 6', }, // Formatting dropdown menu format : { name : 'Формат', bold : 'Полужирный', italic : 'Наклонный', sup : 'Надстрочный', sub : 'Надстрочный', strike : 'Зачеркнутый', remove : 'Очистить форматирование' }, // Lists dropdown menu lists : { name : 'Списки', unordered : 'Обычный список', ordered : 'Нумерованный список', outdent : 'Уменьшить отступ', indent : 'Увеличить отступ' }, // Working with images image : { name : 'Изображение', download : 'Скачать изображение', text : 'Текст', mailto : 'Эл. почта', web : 'URL', title : 'Подсказка', buttons : { save : 'Сохранить', cancel : 'Отменить', insert : 'Вставить', remove : 'Удалить' }, align : { name : 'Обтекание текстом', none : 'нет', left : 'слева', right : 'справа' } }, // Insert and format tables table : { name : 'Таблица', insert : 'Вставить таблицу', remove : 'Удалить таблицу', row: { name : 'Строки', above : 'Добавить строку сверху', below : 'Добавить строку снизу', remove : 'Удалить строку' }, column : { name : 'Столбцы', left : 'Добавить столбец слева', right : 'Добавить столбец справа', remove : 'Удалить столбец', }, header : { add : 'Добавить заголовок', remove : 'Удалить заголовок' } }, // Insert video from youtube etc video : { name : 'Видео', code : 'Код видео ролика' }, // Insert or remove hyperlink to a file file : { name : 'Файл', upload : 'Загрузить', download : 'Скачать', choose : 'Выбрать', or_choose : 'Или выберите', drop : 'Перетащите файл сюда' }, // Insert or remove hyperlink link : { name : 'Ссылка', insert : 'Вставить ссылку ...', remove : 'Удалить ссылку' } } } ; $.fn.ImperaviToolbarDefault = { html : true, // Styles dropdown menu // TODO: User styles here. Move all to format section from here styles : { paragraph : true, quote : true, code : true, h2 : true, h3 : true, h4 : true, h5 : true, h6 : true }, // Formatting dropdown menu format : { bold : true, italic : true, sup : true, sub : true, strike : true, remove : true }, // Lists dropdown menu lists : { unordered : true, ordered : true, outdent : true, indent : true }, // Working with images image : true, // Insert and format tables table : { insert : true, remove : true, header: { add : true, remove : true }, row: { above : true, below : true, remove : true }, column: { left : true, right : true, remove : true } }, // Insert video from youtube etc video : true, // Insert or remove hyperlink to a file file: true, // Insert or remove hyperlink link : { insert : true, remove : true } } ; (function( $ ) { $.fn.ImperaviActionDelegator = function(o) { this.initialize() } $.fn.ImperaviActionDelegator.prototype = { initialize: function() {}, delegateButtonClick: function(button, iframe) { switch (button.attr('rel')) { case 'indent': case 'outdent': alert('yay!') break; case 'video': new $.fn.ImperaviPluginVideo break; } } } })(jQuery); (function( $ ) { $.fn.ImperaviPluginVideo = function(o) { this.initialize(o) } $.fn.ImperaviPluginVideo.prototype = { initialize: function(o) { this.o = o this.dialog = new $.fn.ImperaviDialog({ title : 'Insert video', width : 600, height : 300, onOkay : function() { alert(this.el.find('textarea').val()) this.hide() } }) this.dialog.show() this.dialog.el.addClass('imperavi-plugin-video') this.build() }, build: function() { var textarea = $(document.createElement('textarea')) this.dialog.setContent(textarea) } } })(jQuery); // TODO: add custom events // - onShow // - onClose // - onBuilt // - onContentLoaded // - onOkay // - onCancel (function( $ ) { $.fn.ImperaviDialog = function(o) { var o = $.extend({ onOkay : function() { this.hide() }, onCancel : function() { this.hide() } }, o) this.initialize(o) } $.fn.ImperaviDialog.prototype = { el : null, o : null, overlay : null, initialize: function(o) { // Retrieve user options passed to imperavi this.o = $.extend($.fn.ImperaviOptions().options.dialog, o) }, build: function() { // Build dialog just once if (this.el) return; // Create overlay this.overlay = new $.fn.ImperaviOverlay() // Dialog window this.el = $(document.createElement('div')) .attr('id', 'imperavi-dialog') .appendTo($('body')); // Close button this.closeBtn = $(document.createElement('a')) .attr('href', 'javascript:;') .html('×') .attr('id', 'imperavi-dialog-close') .appendTo(this.el); // Dialog title this.title = $(document.createElement('h1')) .attr('id', 'imperavi-dialog-title') .appendTo(this.el); // Dialog content this.article = $(document.createElement('article')) .attr('id', 'imperavi-dialog-content') .appendTo(this.el); // Buttons panel this.buttons = $(document.createElement('div')) .attr('id', 'imperavi-dialog-buttons') .appendTo(this.el); this.okay_button = this.addButton('Okay', 'okay') .click($.proxy(function(){ this.o.onOkay.call(this) }, this)) this.cancel_button = this.addButton('Cancel', 'cancel') .click($.proxy(function(){ this.o.onCancel.call(this) }, this)) // Set default size this.setSize(this.o.width, this.o.height) // Set default title this.setTitle(this.o.title) }, addButton: function(caption, name) { return $(document.createElement('a')) .attr('id', 'imperavi-dialog-' + name) .attr('href', 'javascript:;') .html(caption) .appendTo(this.buttons); }, addEvents: function() { $(document).keyup($.proxy(this.close, this)) this.closeBtn.click($.proxy(this.close, this)) this.overlay.el.click($.proxy(this.close, this)) }, removeEvents: function() { $(document).unbind('keyup', $.proxy(this.close, this)) this.closeBtn.unbind('click', $.proxy(this.close, this)) this.overlay.el.unbind('click', $.proxy(this.close, this)) }, setSize: function(width, height) { this.el.css({ width : width+ 'px', height : height + 'px', marginTop : '-' + height / 2 + 'px', marginLeft : '-' + width / 2 + 'px' }).fadeIn('fast'); }, setTitle: function(title) { this.title.html(title) }, setContent: function(content) { this.article.html(content) }, // TODO Load content via ajax loadContent: function(url) { this.setContent('') }, cleanUp: function() { this.removeEvents() this.setContent('') this.setTitle('') }, show: function() { this.build() this.overlay.show() this.el.show() this.addEvents() }, hide: function() { this.el.hide() this.overlay.hide() this.cleanUp() }, close: function(e) { if (e.keyCode == 27 || e.type == 'click') this.hide() } } })(jQuery); (function( $ ) { $.fn.ImperaviOverlay = function(o) { this.initialize(o) } $.fn.ImperaviOverlay.prototype = { el : null, initialize: function(o) { this.o = o }, build: function() { if (this.el) return; this.el = $(document.createElement('div')) .attr('id', 'imperavi-overlay') .appendTo($('body')); }, show: function() { this.build() this.el.show() }, hide: function() { this.el.hide() } } })(jQuery); (function( $ ) { $.fn.ImperaviIframe = function(textarea, o) { this.initialize(textarea, o) } $.fn.ImperaviIframe.prototype = { textarea : null, wrapper : null, el : null, initialize: function(textarea, o) { this.textarea = textarea this.o = o this.textarea.hide(); this.build() this.populate() this.enable(true) }, // Build Iframe object and stuff build: function() { this.wrapper = $(document.createElement('div')) .addClass('imperavi') .insertAfter(this.textarea) this.el = $(document.createElement('iframe')) .appendTo(this.wrapper) .css({ width : this.textarea.outerWidth(), height : this.textarea.outerHeight() }) }, populate: function() { html = '' html += '' //html += '' //html += '' html += '' + this.textarea.val() html += '' this.doc().open(); this.doc().write(html); this.doc().close(); }, enableObjects: function() { if (!$.browser.mozilla) return; //this.doc().execCommand('styleWithCSS', false, false) //this.doc().execCommand('enableObjectResizing', false, false) //this.doc().execCommand('enableInlineTableEditing', false, false) }, observe: function() { }, enable: function(status) { // Located here for Chrome support this.doc().designMode = status ? 'on' : 'off'; this.el.load($.proxy(function() { this.enableObjects(); this.observe(); }, this)); }, doc: function() { return this.el.get(0).contentDocument || this.el.get(0).contentWindow.document } } })(jQuery); (function( $ ) { $.fn.ImperaviIframeResizer = function(iframe, o) { this.initialize(iframe, o) } $.fn.ImperaviIframeResizer.prototype = { iframe : null, el : null, initialize: function(iframe, o) { this.iframe = iframe this.o = o this.build() }, build: function() { this.el = $(document.createElement('div')) .addClass('imperavi-resizer') .insertAfter(this.iframe.el) this.el.append($(document.createElement('div'))) } } })(jQuery); (function( $ ) { $.fn.ImperaviToolbar = function(iframe, o) { var o = $.extend({ onButtonClick : function(button) {}, }, o) this.initialize(iframe, o) } $.fn.ImperaviToolbar.prototype = { iframe : null, el : null, initialize: function(iframe, o) { this.iframe = iframe this.o = o this.x = $.fn.ImperaviToolbarDefault // TODO make it pretty this.l = $.fn.ImperaviLanguages.ru // TODO make it pretty this.build() }, // Build Toolbar object build: function() { this.el = $(document.createElement('ul')) .insertBefore(this.iframe.el); $.each(this.x, $.proxy(function(key, value) { // Buttons with dropdown if (typeof value == 'object') { this.el.append(this.addDropdown(key, value)) } else if (typeof value == 'boolean' && value == true) { var title = typeof this.l[key] == 'object' ? this.l[key].name : this.l[key] this.el.append(this.addButton(key, title, null)) } }, this)); }, addButton: function(name, title, caption) { var li = $(document.createElement('li')).addClass('button-' + name) var a = $(document.createElement('a')) .attr('href', 'javascript:;') .attr('rel', name) .attr('title', title) .appendTo(li) // This executes a custom callback on button click .click($.proxy(function(){ this.o.onButtonClick.call(this, a) }, this)) var span = $(document.createElement('span')) .html(caption) .appendTo(a); return li.append(a) }, addDropdown: function(name, items) { var button = this.addButton(name, this.l[name].name, null) var ul = $(document.createElement('ul')) button.addClass('has-dropdown') // Add dropdown items $.each(items, $.proxy(function(key, value) { if (typeof value == 'object') { var separator = true $.each(value, $.proxy(function(key2, value2) { if (value2 == true) { var item = this.addButton(key2, null, this.l[name][key][key2]) if (separator) item.addClass('separator') ul.append(item) separator = false } }, this)); } else if (typeof value == 'boolean' && value == true) { ul.append( this.addButton(key, null, this.l[name][key]) ) } }, this)); return button.append(ul) } } })(jQuery); (function( $ ) { $.fn.imperavi = function(o) { // Editor options var o = $.extend({ language : 'ru', // TODO replace with $.fn.ImperaviLanguage resizer : $.fn.ImperaviIframeResizer, dialog : $.fn.ImperaviDialog, overlay : $.fn.ImperaviOverlay, iframe : $.fn.ImperaviIframe, toolbar : $.fn.ImperaviToolbar, delegator : $.fn.ImperaviActionDelegator, options : { dialog : { title : 'Default title', width : 500, height : 300 } } }, o) // Global options $.fn.ImperaviOptions = function() { return o } // Main object $.fn.Imperavi = function(el) { this.initialize(el) } $.fn.Imperavi.prototype = { textarea : null, iframe : null, toolbar : null, resizer : null, delegator : null, // Initialize imperavi initialize: function(el) { this.textarea = $(el) this.build() this.autosave() }, build: function() { // Delegate action to another object this.delegator = new o.delegator // Create iframe this.iframe = new o.iframe(this.textarea, o) // Create editor resizer this.resizer = new o.resizer(this.iframe, o) // Create toolbar this.toolbar = new o.toolbar(this.iframe, { onButtonClick : $.proxy(function(button) { this.delegator.delegateButtonClick(button, this.iframe) }, this) }) }, autosave: function() { // TODO: implement } } // Apply imperavi for each selected element return this.each(function() { new $.fn.Imperavi(this) }) } })(jQuery);