$.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 hyperlink : 'Ссылка' } } ; $.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 hyperlink : 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; case 'image': new $.fn.ImperaviPluginImage break; case 'hyperlink': new $.fn.ImperaviPluginHyperlink break; case 'file': new $.fn.ImperaviPluginFile break; default: return button break; } } } })(jQuery); // Internationalization (function( $ ) { $.fn.ImperaviI18n = function(o) { var o = $.extend({ locale : 'en' }, o) this.initialize(o) } $.fn.ImperaviI18n.prototype = { o : null, locales : null, initialize: function(o) { this.o = $.extend({ locale : $.fn.ImperaviOptions().options.locale }, o) this.locales = $.fn.ImperaviLanguages[this.o.locale] }, t: function(key) { } } })(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); (function( $ ) { $.fn.ImperaviPluginImage = function(o) { this.initialize(o) } $.fn.ImperaviPluginImage.prototype = { initialize: function(o) { this.o = o this.dialog = new $.fn.ImperaviDialog({ title : 'Insert image', width : 800, height : 600, onRemove : function() { alert('fuck yeah!') this.hide() }, onOkay : function() { this.hide() } }) this.dialog.show() this.dialog.el.addClass('imperavi-plugin-image') this.build() }, build: function() { // Add 'remove' button this.removeButton = this.dialog.addButton('Remove', 'remove') this.removeButton.hide(); // Create tabs and content for tabs this.tabsArea = this.build_tabs_area() this.pickTab = this.build_tab('Pick image', this.buildPickTabContent()) .appendTo(this.tabsArea) .addClass('current') this.uploadTab = this.build_tab('Upload image', this.buildUploadTabContent()) .appendTo(this.tabsArea) this.dialog.setContent(this.tabsArea) this.switchTabs(); }, build_tabs_area: function() { var article = $(document.createElement('article')) .addClass('imperavi-tabs') return article }, build_tab: function(title, content) { var section = $(document.createElement('section')) var heading = $(document.createElement('h3')) .html(title) .addClass('imperavi-tab') .appendTo(section) var content = $(document.createElement('div')) .appendTo(section) .html(content) return section }, switchTabs: function() { var currentTab = this.pickTab this.tabsArea.on('click', '.imperavi-tab', function(e){ e.preventDefault(); if (currentTab.length) { currentTab.removeClass('current') } currentTab = $(this).closest('section').addClass('current') }) }, buildPickTabContent: function() { }, buildUploadTabContent: function() { // Create wrapper var wrapper = $(document.createElement('div')) .addClass('upload-wrapper') // Create place for thumbnail var thumbnail = $(document.createElement('figure')) .addClass('thumbnail') .appendTo(wrapper) // Choose image from disk var imageLocal = this.build_input('Choose image from disk', 'image', 'file') .appendTo(wrapper) // Image url var imageUrl = this.build_input('or specify link to image', 'image-url', 'text') .appendTo(wrapper) return wrapper }, build_input: function(title, name, type) { var wrapper = $(document.createElement('div')) .addClass('field') var label = $(document.createElement('label')) .attr('for', name) .html(title) .appendTo(wrapper) var url = $(document.createElement('input')) .attr('type', type) .attr('name', name) .attr('id', name) .appendTo(wrapper) return wrapper } } })(jQuery); (function( $ ) { $.fn.ImperaviPluginHyperlink = function(o) { this.initialize(o) } $.fn.ImperaviPluginHyperlink.prototype = { initialize: function(o) { this.o = o this.dialog = new $.fn.ImperaviDialog({ title : 'Insert hyperlink', width : 450, height : 237, onRemove : function() { alert('fuck yeah!') this.hide() }, onOkay : function() { alert('fuck') this.hide() } }) this.dialog.show() this.dialog.el.addClass('imperavi-plugin-hyperlink') this.dialog.addButton('Remove', 'remove') this.build() }, build: function() { var wrapper = $(document.createElement('div')) var url = this.build_input('Url', 'url').appendTo(wrapper) var caption = this.build_input('Title', 'title').appendTo(wrapper) this.dialog.setContent(wrapper) }, build_input: function(title, name) { var wrapper = $(document.createElement('div')) .addClass('field') var label = $(document.createElement('label')) .attr('for', name) .html(title) .appendTo(wrapper) var url = $(document.createElement('input')) .attr('type', 'text') .attr('name', name) .attr('id', name) .appendTo(wrapper) return wrapper } } })(jQuery); (function( $ ) { $.fn.ImperaviPluginFile = function(o) { this.initialize(o) } $.fn.ImperaviPluginFile.prototype = { initialize: function(o) { this.o = o this.dialog = new $.fn.ImperaviDialog({ title : 'Attach file', width : 450, height : 237, onRemove : function() { alert('fuck yeah!') this.hide() }, onOkay : function() { alert('fuck') this.hide() } }) this.dialog.show() this.dialog.el.addClass('imperavi-plugin-file') this.dialog.addButton('Remove', 'remove') this.build() }, build: function() { var wrapper = $(document.createElement('div')) var file = this.build_input('File', 'attachment').appendTo(wrapper) //var caption = this.build_input('Title', 'title').appendTo(wrapper) this.dialog.setContent(wrapper) }, build_input: function(title, name) { var wrapper = $(document.createElement('div')) .addClass('field') var label = $(document.createElement('label')) .attr('for', name) .html(title) .appendTo(wrapper) var file = $(document.createElement('input')) .attr('type', 'file') .attr('name', name) .attr('id', name) .appendTo(wrapper) return wrapper } } })(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() }, onClose : function(e) { this.close(e) }, onBuilt : function() {}, onLoad : function() {} }, 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')); this.container = $(document.createElement('div')) .attr('id', 'imperavi-dialog-container') .appendTo(this.el); // Close button this.closeBtn = $(document.createElement('a')) .attr('href', 'javascript:;') .html('×') .attr('id', 'imperavi-dialog-close') .appendTo(this.container); // Dialog title this.title = $(document.createElement('h1')) .attr('id', 'imperavi-dialog-title') .appendTo(this.container); // Dialog content this.article = $(document.createElement('article')) .attr('id', 'imperavi-dialog-content') .appendTo(this.container); // Buttons panel this.buttons_wrapper = $(document.createElement('div')) .attr('id', 'imperavi-dialog-buttons-wrapper') .appendTo(this.container); this.buttons = $(document.createElement('div')) .attr('id', 'imperavi-dialog-buttons') .appendTo(this.buttons_wrapper); this.okay_button = this.addButton('Okay', 'okay') this.cancel_button = this.addButton('Cancel', 'cancel') // Set default size this.setSize(this.o.width, this.o.height) // Set default title this.setTitle(this.o.title) this.o.onBuilt.call(this) }, addButton: function(caption, name) { var callbackName = 'on' + name.charAt(0).toUpperCase() + name.slice(1) return $(document.createElement('a')) .attr('id', 'imperavi-dialog-' + name) .attr('href', 'javascript:;') .html(caption) .click($.proxy(function(){ this.o[callbackName].call(this) }, this)) .appendTo(this.buttons); }, addEvents: function() { var onCloseCallback = $.proxy(function(e){ this.o.onClose.call(this, e) }, this) $(document).keyup(function(e) { onCloseCallback(e) }) this.closeBtn.click(function(e) { onCloseCallback(e) }) this.overlay.el.click(function(e) { onCloseCallback(e) }) }, removeEvents: function() { var onCloseCallback = $.proxy(function(e){ this.o.onClose.call(this, e) }, this) $(document).unbind('keyup', onCloseCallback) this.closeBtn.unbind('click', onCloseCallback) this.overlay.el.unbind('click', onCloseCallback) }, setSize: function(width, height) { this.el.css({ width : width + 'px', height : height + 'px', marginTop : '-' + height / 2 + 'px', marginLeft : '-' + width / 2 + 'px' }).fadeIn('fast'); this.container.css({ width : width + 'px', height : height + 'px', }) }, setTitle: function(title) { this.title.html(title) }, setContent: function(content) { this.article.html(content) }, // TODO Load content via ajax loadContent: function(url) { this.setContent('') this.o.onLoad.call(this) }, 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({ locale : '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);