diff options
| author | qsm-odoo <qsm@odoo.com> | 2017-06-07 17:45:15 +0200 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2017-08-16 10:59:39 +0200 |
| commit | 4f925af06fd3cebfcfb56eb947ab68c8a2ca4490 (patch) | |
| tree | b13bd049b6b3e7bbdfb537d19b53c95fc4025ea5 /addons/web_editor/static/src/js/widgets.js | |
| parent | f205bfcd4ddcf3f1d8676ee87ee0b29941bd6773 (diff) | |
[MOV] web_editor, website: reorganize files
Diffstat (limited to 'addons/web_editor/static/src/js/widgets.js')
| -rw-r--r-- | addons/web_editor/static/src/js/widgets.js | 1177 |
1 files changed, 0 insertions, 1177 deletions
diff --git a/addons/web_editor/static/src/js/widgets.js b/addons/web_editor/static/src/js/widgets.js deleted file mode 100644 index 3bfae6ce240..00000000000 --- a/addons/web_editor/static/src/js/widgets.js +++ /dev/null @@ -1,1177 +0,0 @@ -odoo.define('web_editor.widget', function (require) { -'use strict'; - -var core = require('web.core'); -var ajax = require('web.ajax'); -var Dialog = require('web.Dialog'); -var Widget = require('web.Widget'); -var base = require('web_editor.base'); -var rte = require('web_editor.rte'); - -var QWeb = core.qweb; -var range = $.summernote.core.range; -var dom = $.summernote.core.dom; - -var _t = core._t; - -/** - * Extend Dialog class to handle save/cancel of edition components. - */ -Dialog = Dialog.extend({ - init: function (parent, options) { - options = options || {}; - this._super(parent, _.extend({}, { - buttons: [ - {text: options.save_text || _t("Save"), classes: "btn-primary o_save_button", click: this.save}, - {text: _t("Discard"), close: true} - ] - }, options)); - - this.destroyAction = "cancel"; - - var self = this; - this.opened().then(function () { - self.$('input:first').focus(); - }); - this.on("closed", this, function () { - this.trigger(this.destroyAction, this.final_data || null); - }); - }, - save: function () { - this.destroyAction = "save"; - this.close(); - }, -}); - -/** - * alt widget. Lets users change a alt & title on a media - */ -var alt = Dialog.extend({ - template: 'web_editor.dialog.alt', - init: function (parent, options, $editable, media) { - this._super(parent, _.extend({}, { - title: _t("Change media description and tooltip") - }, options)); - this.$editable = $editable; - this.media = media; - this.alt = ($(this.media).attr('alt') || "").replace(/"/g, '"'); - this.title = ($(this.media).attr('title') || "").replace(/"/g, '"'); - }, - save: function () { - range.createFromNode(this.media).select(); - this.$editable.data('NoteHistory').recordUndo(); - var alt = this.$('#alt').val(); - var title = this.$('#title').val(); - $(this.media).attr('alt', alt ? alt.replace(/"/g, """) : null).attr('title', title ? title.replace(/"/g, """) : null); - _.defer((function () { - click_event(this.media, "mouseup"); - }).bind(this)); - return this._super.apply(this, arguments); - }, -}); - -var click_event = function (el, type) { - var evt = document.createEvent("MouseEvents"); - evt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, el); - el.dispatchEvent(evt); -}; - -/** - * MediaDialog widget. Lets users change a media, including uploading a - * new image, font awsome or video and can change a media into an other - * media - * - * options: select_images: allow the selection of more of one image - */ -var MediaDialog = Dialog.extend({ - template: 'web_editor.dialog.media', - events : _.extend({}, Dialog.prototype.events, { - 'input input#icon-search': 'search', - }), - init: function (parent, options, $editable, media) { - this._super(parent, _.extend({}, { - title: _t("Select a Media"), - }, options)); - if ($editable) { - this.$editable = $editable; - this.rte = this.$editable.rte || this.$editable.data('rte'); - } - this.options = options || {}; - this.old_media = media; - this.media = media; - this.isNewMedia = !media; - this.range = range.create(); - }, - start: function () { - var self = this; - - this.$modal.addClass('note-image-dialog'); - this.$modal.find('.modal-dialog').addClass('o_select_media_dialog'); - - this.only_images = this.options.only_images || this.options.select_images || (this.media && ($(this.media).parent().data("oe-field") === "image" || $(this.media).parent().data("oe-type") === "image")); - if (this.only_images) { - this.$('[href="#editor-media-document"], [href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden'); - } - - this.opened((function () { - if (this.media) { - if (this.media.nodeName === "IMG") { - this.$('[href="#editor-media-image"]').tab('show'); - } else if ($(this.media).is('a.o_image')) { - this.$('[href="#editor-media-document"]').tab('show'); - } else if (this.media.className.match(/(^|\s)media_iframe_video($|\s)/)) { - this.$('[href="#editor-media-video"]').tab('show'); - } else if (this.media.parentNode.className.match(/(^|\s)media_iframe_video($|\s)/)) { - this.media = this.media.parentNode; - this.$('[href="#editor-media-video"]').tab('show'); - } else if (this.media.className.match(/(^|\s)fa($|\s)/)) { - this.$('[href="#editor-media-icon"]').tab('show'); - } - } - }).bind(this)); - - this.imageDialog = new ImageDialog(this, this.media, this.options); - this.imageDialog.appendTo(this.$("#editor-media-image")); - this.documentDialog = new ImageDialog(this, this.media, _.extend({'document': true}, this.options)); - this.documentDialog.appendTo(this.$("#editor-media-document")); - if (!this.only_images) { - this.iconDialog = new fontIconsDialog(this, this.media, this.options); - this.iconDialog.appendTo(this.$("#editor-media-icon")); - this.videoDialog = new VideoDialog(this, this.media, this.options); - this.videoDialog.appendTo(this.$("#editor-media-video")); - } - - this.active = this.imageDialog; - - this.$('a[data-toggle="tab"]').on('shown.bs.tab', function (event) { - if ($(event.target).is('[href="#editor-media-image"]')) { - self.active = self.imageDialog; - self.$('li.search, li.previous, li.next').removeClass("hidden"); - } else if ($(event.target).is('[href="#editor-media-document"]')) { - self.active = self.documentDialog; - self.$('li.search, li.previous, li.next').removeClass("hidden"); - } else if ($(event.target).is('[href="#editor-media-icon"]')) { - self.active = self.iconDialog; - self.$('li.search, li.previous, li.next').removeClass("hidden"); - self.$('.nav-tabs li.previous, .nav-tabs li.next').addClass("hidden"); - } else if ($(event.target).is('[href="#editor-media-video"]')) { - self.active = self.videoDialog; - self.$('.nav-tabs li.search').addClass("hidden"); - } - }); - - return this._super.apply(this, arguments); - }, - save: function () { - if (this.options.select_images) { - this.final_data = this.active.save(); - this._super.apply(this, arguments); - return; - } - if(this.rte) { - this.range.select(); - this.rte.historyRecordUndo(this.media); - } - - var self = this; - if (self.media) { - this.media.innerHTML = ""; - if (this.active !== this.imageDialog && this.active !== this.documentDialog) { - this.imageDialog.clear(); - } - // if not mode only_images - if (this.iconDialog && this.active !== this.iconDialog) { - this.iconDialog.clear(); - } - if (this.videoDialog && this.active !== this.videoDialog) { - this.videoDialog.clear(); - } - } else { - this.media = document.createElement("img"); - this.range.insertNode(this.media, true); - this.active.media = this.media; - } - this.active.save(); - - if (this.active.add_class) { - $(this.active.media).addClass(this.active.add_class); - } - var media = this.active.media; - - this.final_data = [media, self.old_media]; - $(document.body).trigger("media-saved", this.final_data); - $(self.old_media).trigger("save", this.final_data); - - // Update editor bar after image edition (in case the image change to icon or other) - _.defer(function () { - if (!media.parentNode) return; - range.createFromNode(media).select(); - click_event(media, "mousedown"); - click_event(media, "mouseup"); - }); - - this._super.apply(this, arguments); - }, - searchTimer: null, - search: function () { - var self = this; - var needle = this.$("input#icon-search").val(); - clearTimeout(this.searchTimer); - this.searchTimer = setTimeout(function () { - self.active.search(needle || ""); - },250); - } -}); - -/** - * ImageDialog widget. Let users change an image, including uploading a - * new image in odoo or selecting the image style (if supported by - * the caller). - */ -var ImageDialog = Widget.extend({ - template: 'web_editor.dialog.image', - IMAGES_PER_ROW: 6, - IMAGES_ROWS: 2, - events: _.extend({}, Dialog.prototype.events, { - 'change .url-source': function (e) { - this.changed($(e.target)); - }, - 'click button.filepicker': function () { - var filepicker = this.$('input[type=file]'); - if (!_.isEmpty(filepicker)) { - filepicker[0].click(); - } - }, - 'click .js_disable_optimization': function () { - this.$('input[name="disable_optimization"]').val('1'); - var filepicker = this.$('button.filepicker'); - if (!_.isEmpty(filepicker)) { - filepicker[0].click(); - } - }, - 'change input[type=file]': 'file_selection', - 'submit form': 'form_submit', - 'change input.url': "change_input", - 'keyup input.url': "change_input", - 'click .existing-attachments [data-src]': 'select_existing', - 'dblclick .existing-attachments [data-src]': function () { - this.getParent().save(); - }, - 'click .o_existing_attachment_remove': 'try_remove', - 'keydown.dismiss.bs.modal': function () {}, - }), - init: function (parent, media, options) { - this._super.apply(this, arguments); - this.options = options || {}; - this.accept = this.options.accept || this.options.document ? "*/*" : "image/*"; - this.domain = this.options.domain || ['|', ['mimetype', '=', false], ['mimetype', this.options.document ? 'not in' : 'in', ['image/gif', 'image/jpe', 'image/jpeg', 'image/jpg', 'image/gif', 'image/png']]]; - this.parent = parent; - this.old_media = media; - this.media = media; - this.images = []; - this.page = 0; - }, - start: function () { - this.$preview = this.$('.preview-container').detach(); - var self = this; - var res = this._super.apply(this, arguments); - var o = {url: null, alt: null}; - - if ($(this.media).is("img")) { - o.url = this.media.getAttribute('src'); - } else if ($(this.media).is("a.o_image")) { - o.url = this.media.getAttribute('href').replace(/[?].*/, ''); - o.id = +o.url.match(/\/web\/content\/([0-9]*)/, '')[1]; - } - this.parent.$(".pager > li").click(function (e) { - if(!self.$el.is(':visible')) { - return; - } - e.preventDefault(); - var $target = $(e.currentTarget); - if ($target.hasClass('disabled')) { - return; - } - self.page += $target.hasClass('previous') ? -1 : 1; - self.display_attachments(); - }); - this.fetch_existing().then(function () { - if (o.url) { - self.set_image(_.find(self.records, function (record) { return record.url === o.url;}) || o); - } - }); - return res; - }, - push: function (attachment) { - if (this.options.select_images) { - var img = _.select(this.images, function (v) { return v.id === attachment.id; }); - if (img.length) { - this.images.splice(this.images.indexOf(img[0]),1); - } else { - this.images.push(attachment); - } - } else { - this.images = [attachment]; - } - }, - save: function () { - if (this.options.select_images) { - return this.images; - } - - var img = this.images[0]; - if (!img) { - var id = this.$(".existing-attachments [data-src]:first").data('id'); - img = _.find(this.images, function (img) { return img.id === id;}); - } - - var media; - if (!img.is_document) { - if (this.media.tagName !== "IMG" || !this.old_media) { - this.add_class = "pull-left"; - this.style = {"width": "100%"}; - } - if(this.media.tagName !== "IMG") { - media = document.createElement('img'); - $(this.media).replaceWith(media); - this.media = media; - } - this.media.setAttribute('src', img.src); - } else { - if (this.media.tagName !== "A") { - $('.note-control-selection').hide(); - media = document.createElement('a'); - $(this.media).replaceWith(media); - this.media = media; - } - this.media.setAttribute('href', '/web/content/' + img.id + '?unique=' + img.checksum + '&download=true'); - $(this.media).addClass('o_image').attr('title', img.name).attr('data-mimetype', img.mimetype); - } - - $(this.media).attr('alt', img.alt); - var style = this.style; - if (style) { $(this.media).css(style); } - - return this.media; - }, - clear: function () { - this.media.className = this.media.className.replace(/(^|\s+)((img(\s|$)|img-(?!circle|rounded|thumbnail))[^\s]*)/g, ' '); - }, - change_input: function (e) { - var $input = $(e.target); - var $button = $input.parent().find("button"); - var emptyValue = ($input.val() === ""); - $button.toggleClass("btn-default", emptyValue).toggleClass("btn-primary", !emptyValue); - }, - search: function (needle) { - var self = this; - this.fetch_existing(needle).then(function () { - self.selected_existing(); - }); - }, - set_image: function (attachment) { - this.push(attachment); - this.$('input.url').val(''); - this.search(); - this.images = []; - }, - form_submit: function (event) { - var self = this; - var $form = this.$('form[action="/web_editor/attachment/add"]'); - if (!$form.find('input[name="upload"]').val().length) { - if (this.selected_existing().size()) { - event.preventDefault(); - return false; - } - } - $form.find('.well > div').hide().last().after('<span class="fa fa-spin fa-3x fa-refresh"/>'); - - var callback = _.uniqueId('func_'); - this.$('input[name=func]').val(callback); - window[callback] = function (attachments, error) { - delete window[callback]; - $form.find('.well > span').remove(); - $form.find('.well > div').show(); - _.each(attachments, function (record) { - record.src = record.url || '/web/image/' + record.id; - record.is_document = !(/gif|jpe|jpg|png/.test(record.mimetype)); - }); - if (error || !attachments.length) { - self.file_selected(null, error || !attachments.length); - } - self.images = attachments; - for (var i=0; i<attachments.length; i++) { - self.file_selected(attachments[i], error); - } - }; - }, - file_selection: function () { - var $form = this.$('form'); - this.$el.addClass('nosave'); - $form.removeClass('has-error').find('.help-block').empty(); - this.$('button.filepicker').removeClass('btn-danger btn-success'); - $form.submit(); - }, - file_selected: function (attachment, error) { - var $button = this.$('button.filepicker'); - if (!error) { - $button.addClass('btn-success'); - this.set_image(attachment); - } else { - this.$('form').addClass('has-error').find('.help-block').text(error); - $button.addClass('btn-danger'); - } - - if (!this.options.select_images) { - this.parent.save(); // auto save and close popup - } - }, - fetch_existing: function (needle) { - var domain = [['res_model', '=', 'ir.ui.view']].concat(this.domain); - if (needle && needle.length) { - domain.push('|', ['datas_fname', 'ilike', needle], ['name', 'ilike', needle]); - } - return ajax.jsonRpc('/web/dataset/call_kw', 'call', { - model: 'ir.attachment', - method: 'search_read', - args: [], - kwargs: { - domain: domain, - fields: ['name', 'mimetype', 'checksum', 'url', 'type'], - order: 'id desc', - context: base.get_context() - } - }).then(this.proxy('fetched_existing')); - }, - fetched_existing: function (records) { - this.records = _.uniq(_.filter(records, function (r) { - return (r.type === "binary" || r.url && r.url.length > 0); - }), function (r) { - return (r.url || r.id); - }); - _.each(this.records, function (record) { - record.src = record.url || '/web/image/' + record.id; - record.is_document = !(/gif|jpe|jpg|png/.test(record.mimetype)); - }); - this.display_attachments(); - }, - display_attachments: function () { - var self = this; - var per_screen = this.IMAGES_PER_ROW * this.IMAGES_ROWS; - var from = this.page * per_screen; - var records = this.records; - - // Create rows of 3 records - var rows = _(records).chain() - .slice(from, from + per_screen) - .groupBy(function (_, index) { return Math.floor(index / self.IMAGES_PER_ROW); }) - .values() - .value(); - - this.$('.help-block').empty(); - - this.$('.existing-attachments').replaceWith(QWeb.render('web_editor.dialog.image.existing.content', {rows: rows})); - this.parent.$('.pager') - .find('li.previous a').toggleClass('disabled', (from === 0)).end() - .find('li.next a').toggleClass('disabled', (from + per_screen >= records.length)); - - this.$el.find('.o_image').each(function () { - var $div = $(this); - if (/gif|jpe|jpg|png/.test($div.data('mimetype'))) { - var $img = $('<img/>').addClass('img img-responsive').attr('src', $div.data('url') || $div.data('src')); - $div.addClass('o_webimage').append($img); - } - }); - this.selected_existing(); - }, - select_existing: function (e) { - var $img = $(e.currentTarget); - if (!this.options.select_images) { - this.$('.o_existing_attachment_cell.o_selected').removeClass("o_selected"); - $img.closest('.o_existing_attachment_cell').addClass('o_selected'); - } else { - $img.closest('.o_existing_attachment_cell').toggleClass('o_selected'); - } - var attachment = _.find(this.records, function (record) { return record.id === $img.data('id'); }); - this.push(attachment); - this.selected_existing(); - }, - selected_existing: function () { - var self = this; - var $select = this.$('.o_existing_attachment_cell [data-src]').filter(function () { - var $img = $(this); - return !!_.find(self.images, function (v) { - return (v.url === $img.data("src") || ($img.data("url") && v.url === $img.data("url")) || v.id === $img.data("id")); - }); - }); - return $select; - }, - try_remove: function (e) { - var $help_block = this.$('.help-block').empty(); - var self = this; - var $a = $(e.target); - var id = parseInt($a.data('id'), 10); - var attachment = _.findWhere(this.records, {id: id}); - var $both = $a.parent().children(); - - $both.css({borderWidth: "5px", borderColor: "#f00"}); - - return ajax.jsonRpc('/web_editor/attachment/remove', 'call', {'ids': [id]}).then(function (prevented) { - if (_.isEmpty(prevented)) { - self.records = _.without(self.records, attachment); - self.display_attachments(); - return; - } - $both.css({borderWidth: "", borderColor: ""}); - $help_block.replaceWith(QWeb.render('web_editor.dialog.image.existing.error', { - views: prevented[id] - })); - }); - }, -}); - -/* list of font icons to load by editor. The icons are displayed in the media editor and - * identified like font and image (can be colored, spinned, resized with fa classes). - * To add font, push a new object {base, parser} - * - base: class who appear on all fonts (eg: fa fa-refresh) - * - parser: regular expression used to select all font in css style sheets - */ -var fontIcons = [{'base': 'fa', 'parser': /(?=^|\s)(\.fa-[0-9a-z_-]+::?before)/i}]; - -var cacheCssSelectors = {}; -var getCssSelectors = function (filter) { - var css = []; - if (cacheCssSelectors[filter]) { - return cacheCssSelectors[filter]; - } - var sheets = document.styleSheets; - for(var i = 0; i < sheets.length; i++) { - var rules; - if (sheets[i].rules) { - rules = sheets[i].rules; - } else { - //try...catch because Firefox not able to enumerate document.styleSheets[].cssRules[] for cross-domain stylesheets. - try { - rules = sheets[i].cssRules; - } catch(e) { - console.warn("Can't read the css rules of: " + sheets[i].href, e); - continue; - } - } - if (rules) { - for(var r = 0; r < rules.length; r++) { - var selectorText = rules[r].selectorText; - if (selectorText) { - selectorText = selectorText.split(/\s*,\s*/); - var data = null; - for(var s = 0; s < selectorText.length; s++) { - var match = selectorText[s].match(filter); - if (match) { - var clean = match[1].slice(1).replace(/::?before$/, ''); - if (!data) { - data = [match[1], rules[r].cssText.replace(/(^.*\{\s*)|(\s*\}\s*$)/g, ''), clean, [clean]]; - } else { - data[0] += (", " + match[1]); - data[3].push(clean); - } - } - } - if (data) { - css.push(data); - } - } - } - } - } - return cacheCssSelectors[filter] = css; -}; -var computeFonts = _.once(function () { - _.each(fontIcons, function (data) { - data.cssData = getCssSelectors(data.parser); - data.alias = []; - data.icons = _.map(data.cssData, function (css) { - data.alias.push.apply(data.alias, css[3]); - return css[2]; - }); - }); -}); - -rte.Class.include({ - init: function () { - this._super.apply(this, arguments); - computeFonts(); - }, - onEnableEditableArea: function ($editable) { - if ($editable.data('oe-type') === "monetary") { - $editable.attr('contenteditable', false); - $editable.find('.oe_currency_value').attr('contenteditable', true); - } - if ($editable.is('[data-oe-model]') && !$editable.is('[data-oe-model="ir.ui.view"]') && !$editable.is('[data-oe-type="html"]')) { - $editable.data('layoutInfo').popover().find('.btn-group:not(.note-history)').remove(); - } - }, -}); - -/** - * FontIconsDialog widget. Lets users change a font awesome, support all - * font awesome loaded in the css files. - */ -var fontIconsDialog = Widget.extend({ - template: 'web_editor.dialog.font-icons', - events : _.extend({}, Dialog.prototype.events, { - 'click .font-icons-icon': function (e) { - e.preventDefault(); - e.stopPropagation(); - - this.$('#fa-icon').val(e.target.getAttribute('data-id')); - $(".font-icons-icon").removeClass("o_selected"); - $(e.target).addClass("o_selected"); - }, - 'dblclick .font-icons-icon': function () { - this.getParent().save(); - }, - 'keydown.dismiss.bs.modal': function () {}, - }), - - init: function (parent, media) { - this._super.apply(this, arguments); - this.parent = parent; - this.media = media; - computeFonts(); - }, - start: function () { - return this._super.apply(this, arguments).then(this.proxy('load_data')); - }, - renderElement: function () { // extract list of font (like awesome) from the cheatsheet. - this.iconsParser = fontIcons; - this.icons = _.flatten(_.map(fontIcons, function (data) { // TODO maybe useless now - return data.icons; - })); - this.alias = _.flatten(_.map(fontIcons, function (data) { - return data.alias; - })); - this._super.apply(this, arguments); - }, - search: function (needle) { - var iconsParser = this.iconsParser; - if (needle) { - iconsParser = []; - _.filter(this.iconsParser, function (data) { - var cssData = _.filter(data.cssData, function (cssData) { - return _.find(cssData[3], function (alias) { - return alias.indexOf(needle) !== -1; - }); - }); - if (cssData.length) { - iconsParser.push({ - base: data.base, - cssData: cssData - }); - } - }); - } - this.$('div.font-icons-icons').html( - QWeb.render('web_editor.dialog.font-icons.icons', {'iconsParser': iconsParser})); - }, - /** - * Removes existing FontAwesome classes on the bound element, and sets - * all the new ones if necessary. - */ - save: function () { - var self = this; - var style = this.media.attributes.style ? this.media.attributes.style.value : ''; - var classes = (this.media.className||"").split(/\s+/); - var custom_classes = /^fa(-[1-5]x|spin|rotate-(9|18|27)0|flip-(horizont|vertic)al|fw|border)?$/; - var non_fa_classes = _.reject(classes, function (cls) { - return self.getFont(cls) || custom_classes.test(cls); - }); - var final_classes = non_fa_classes.concat(this.get_fa_classes()); - if (this.media.tagName !== "SPAN") { - var media = document.createElement('span'); - $(media).data($(this.media).data()); - $(this.media).replaceWith(media); - this.media = media; - style = style.replace(/\s*width:[^;]+/, ''); - } - $(this.media).attr("class", _.compact(final_classes).join(' ')).attr("style", style); - - return this.media; - }, - /** - * return the data font object (with base, parser and icons) or null - */ - getFont: function (classNames) { - if (!(classNames instanceof Array)) { - classNames = (classNames||"").split(/\s+/); - } - var fontIcon, cssData; - for (var k=0; k<this.iconsParser.length; k++) { - fontIcon = this.iconsParser[k]; - for (var s=0; s<fontIcon.cssData.length; s++) { - cssData = fontIcon.cssData[s]; - if (_.intersection(classNames, cssData[3]).length) { - return { - 'base': fontIcon.base, - 'parser': fontIcon.parser, - 'icons': fontIcon.icons, - 'font': cssData[2] - }; - } - } - } - return null; - }, - - /** - * Looks up the various FontAwesome classes on the bound element and - * sets the corresponding template/form elements to the right state. - * If multiple classes of the same category are present on an element - * (e.g. fa-lg and fa-3x) the last one occurring will be selected, - * which may not match the visual look of the element. - */ - load_data: function () { - var classes = (this.media&&this.media.className||"").split(/\s+/); - for (var i = 0; i < classes.length; i++) { - var cls = classes[i]; - switch (cls) { - case 'fa-1x':case 'fa-2x':case 'fa-3x':case 'fa-4x':case 'fa-5x': - // size classes - this.$('#fa-size').val(cls); - continue; - case 'fa-spin': - case 'fa-rotate-90':case 'fa-rotate-180':case 'fa-rotate-270': - case 'fa-flip-horizontal':case 'fa-rotate-vertical': - this.$('#fa-rotation').val(cls); - continue; - case 'fa-fw': - continue; - case 'fa-border': - this.$('#fa-border').prop('checked', true); - continue; - case '': continue; - default: - $(".font-icons-icon").removeClass("o_selected").filter("[data-alias*=',"+cls+",']").addClass("o_selected"); - if (this.alias.indexOf(cls) !== -1) { - this.$('#fa-icon').val(cls); - } - } - } - }, - /** - * Serializes the dialog to an array of FontAwesome classes. Includes the base ``fa``. - */ - get_fa_classes: function () { - var font = this.getFont(this.$('#fa-icon').val()); - return [ - font ? font.base : 'fa', - font ? font.font : "", - this.$('#fa-size').val(), - this.$('#fa-rotation').val(), - this.$('#fa-border').prop('checked') ? 'fa-border' : '' - ]; - }, - clear: function () { - this.media.className = this.media.className.replace(/(^|\s)(fa(\s|$)|fa-[^\s]*)/g, ' '); - }, -}); - - -function createVideoNode(url, options) { - options = options || {}; - - // video url patterns(youtube, instagram, vimeo, dailymotion, youku) - var ytRegExp = /^(?:(?:https?:)?\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/; - var ytMatch = url.match(ytRegExp); - - var igRegExp = /\/\/instagram.com\/p\/(.[a-zA-Z0-9]*)/; - var igMatch = url.match(igRegExp); - - var vRegExp = /\/\/vine.co\/v\/(.[a-zA-Z0-9]*)/; - var vMatch = url.match(vRegExp); - - var vimRegExp = /\/\/(player.)?vimeo.com\/([a-z]*\/)*([0-9]{6,11})[?]?.*/; - var vimMatch = url.match(vimRegExp); - - var dmRegExp = /.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/; - var dmMatch = url.match(dmRegExp); - - var youkuRegExp = /\/\/v\.youku\.com\/v_show\/id_(\w+)\.html/; - var youkuMatch = url.match(youkuRegExp); - - var $video = $('<iframe>'); - if (ytMatch && ytMatch[1].length === 11) { - var youtubeId = ytMatch[1]; - $video = $('<iframe>', { - src: '//www.youtube.com/embed/' + youtubeId, - width: '640', - height: '360' - }); - } else if (igMatch && igMatch[0].length) { - $video = $('<iframe>', { - src: igMatch[0] + '/embed/', - width: '612', - height: '710', - scrolling: 'no', - allowtransparency: 'true' - }); - } else if (vMatch && vMatch[0].length) { - $video = $('<iframe>', { - src: vMatch[0] + '/embed/simple', - width: '600', - height: '600', - class: 'vine-embed' - }); - } else if (vimMatch && vimMatch[3].length) { - $video = $('<iframe>', { - src: '//player.vimeo.com/video/' + vimMatch[3], - width: '640', - height: '360' - }); - } else if (dmMatch && dmMatch[2].length) { - $video = $('<iframe>', { - src: '//www.dailymotion.com/embed/video/' + dmMatch[2], - width: '640', - height: '360' - }); - } else if (youkuMatch && youkuMatch[1].length) { - $video = $('<iframe>', { - height: '498', - width: '510', - src: '//player.youku.com/embed/' + youkuMatch[1] - }); - } else { - // this is not a known video link. Now what, Cat? Now what? - $video = $('<iframe>', { - width: '640', - height: '360', - src: url - }); - } - - if (options.autoplay) { - $video.attr("src", $video.attr("src") + "?autoplay=1"); - } - - $video.attr('frameborder', 0); - - return $video; -} - -/** - * VideoDialog widget. Lets users change a video, support all summernote - * video, and embled iframe - */ -var VideoDialog = Widget.extend({ - template: 'web_editor.dialog.video', - events : _.extend({}, Dialog.prototype.events, { - 'click input#urlvideo ~ button': 'get_video', - 'click input#embedvideo ~ button': 'get_embed_video', - 'change input#autoplay': 'get_video', - 'change input#urlvideo': 'change_input', - 'keyup input#urlvideo': 'change_input', - 'change input#embedvideo': 'change_input', - 'keyup input#embedvideo': 'change_input', - 'keydown.dismiss.bs.modal': function () {}, - }), - init: function (parent, media) { - this._super.apply(this, arguments); - this.parent = parent; - this.media = media; - }, - start: function () { - this.$preview = this.$('.preview-container').detach(); - this.$iframe = this.$("iframe"); - var $media = $(this.media); - if ($media.hasClass("media_iframe_video")) { - var src = $media.data('src'); - this.$("input#urlvideo").val(src); - this.$("input#autoplay").prop("checked", (src || "").indexOf("autoplay") >= 0); - this.get_video(); - } - return this._super.apply(this, arguments); - }, - change_input: function (e) { - var $input = $(e.target); - var $button = $input.parent().find("button"); - if ($input.val() === "") { - $button.addClass("btn-default").removeClass("btn-primary"); - } else { - $button.removeClass("btn-default").addClass("btn-primary"); - } - }, - get_embed_video: function (event) { - event.preventDefault(); - var embedvideo = this.$("input#embedvideo").val().match(/src=["']?([^"']+)["' ]?/); - if (embedvideo) { - this.$("input#urlvideo").val(embedvideo[1]); - this.get_video(event); - } - return false; - }, - get_video: function (event) { - if (event) event.preventDefault(); - var $video = createVideoNode(this.$("input#urlvideo").val(), {autoplay: this.$("input#autoplay").is(":checked")}); - this.$iframe.replaceWith($video); - this.$iframe = $video; - return false; - }, - save: function () { - var video_id = this.$("#video_id").val(); - if (!video_id) { - this.$("button.btn-primary").click(); - video_id = this.$("#video_id").val(); - } - var $iframe = $( - '<div class="media_iframe_video" data-src="'+this.$iframe.attr("src")+'">'+ - '<div class="css_editable_mode_display"> </div>'+ - '<div class="media_iframe_video_size" contentEditable="false"> </div>'+ - '<iframe src="'+this.$iframe.attr("src")+'" frameborder="0" allowfullscreen="allowfullscreen" contentEditable="false"></iframe>'+ - '</div>'); - $(this.media).replaceWith($iframe); - this.media = $iframe[0]; - - return this.media; - }, - clear: function () { - if (this.media.dataset.src) { - try { - delete this.media.dataset.src; - } catch(e) { - this.media.dataset.src = undefined; - } - } - this.media.className = this.media.className.replace(/(^|\s)media_iframe_video(\s|$)/g, ' '); - }, -}); - -/** - * The Link Dialog allows to customize link content and style. - */ -var LinkDialog = Dialog.extend({ - template: 'web_editor.dialog.link', - events: _.extend({}, Dialog.prototype.events, { - 'change :input.url-source': 'changed', - 'keyup :input.url': 'onkeyup', - 'keyup :input': 'preview', - 'click button.remove': 'remove_link', - 'change input#o_link_dialog_label_input': function (e) { - this.text = $(e.target).val(); - }, - 'change .link-style': function (e) { - this.preview(); - }, - }), - init: function (parent, options, editable, linkInfo) { - this._super(parent, _.extend({}, { - title: _t("Link to") - }, options || {})); - this.editable = editable; - this.data = linkInfo || {}; - - this.data.className = ""; - if (this.data.range) { - this.data.iniClassName = $(this.data.range.sc).filter("a").attr("class") || ""; - this.data.className = this.data.iniClassName.replace(/(^|\s+)btn(-[a-z0-9_-]*)?/gi, ' '); - - var is_link = this.data.range.isOnAnchor(); - var r = this.data.range; - - var sc = r.sc; - var so = r.so; - var ec = r.ec; - var eo = r.eo; - - var nodes; - if (!is_link) { - if (sc.tagName) { - sc = dom.firstChild(so ? sc.childNodes[so] : sc); - so = 0; - } else if (so !== sc.textContent.length) { - if (sc === ec) { - ec = sc = sc.splitText(so); - eo -= so; - } else { - sc = sc.splitText(so); - } - so = 0; - } - if (ec.tagName) { - ec = dom.lastChild(eo ? ec.childNodes[eo-1] : ec); - eo = ec.textContent.length; - } else if (eo !== ec.textContent.length) { - ec.splitText(eo); - } - - nodes = dom.listBetween(sc, ec); - - // browsers can't target a picture or void node - if (dom.isVoid(sc) || dom.isImg(sc)) { - so = dom.listPrev(sc).length-1; - sc = sc.parentNode; - } - if (dom.isBR(ec)) { - eo = dom.listPrev(ec).length-1; - ec = ec.parentNode; - } else if (dom.isVoid(ec) || dom.isImg(sc)) { - eo = dom.listPrev(ec).length; - ec = ec.parentNode; - } - - this.data.range = range.create(sc, so, ec, eo); - this.data.range.select(); - } else { - nodes = dom.ancestor(sc, dom.isAnchor).childNodes; - } - - if (dom.isImg(sc) && nodes.indexOf(sc) === -1) { - nodes.push(sc); - } - if (nodes.length > 1 || dom.ancestor(nodes[0], dom.isImg)) { - var text = ""; - this.data.images = []; - for (var i=0; i<nodes.length; i++) { - if (dom.ancestor(nodes[i], dom.isImg)) { - this.data.images.push(dom.ancestor(nodes[i], dom.isImg)); - text += '[IMG]'; - } else if (!is_link && i===0) { - text += nodes[i].textContent.slice(so, Infinity); - } else if (!is_link && i===nodes.length-1) { - text += nodes[i].textContent.slice(0, eo); - } else { - text += nodes[i].textContent; - } - } - this.data.text = text; - } - } - - this.data.text = this.data.text.replace(/[ \t\r\n]+/g, ' '); - }, - start: function () { - this.bind_data(); - this.$('input.url-source:eq(1)').closest('.list-group-item').addClass('active'); - this.$('#o_link_dialog_label_input').focus(); - return this._super.apply(this, arguments); - }, - get_data: function (test) { - var self = this; - var def = new $.Deferred(); - var $e = this.$('.active input.url-source'); - if (!$e.length) { - $e = this.$('input.url-source:first'); - } - var val = $e.val(); - var label = this.$('#o_link_dialog_label_input').val() || val; - - if (label && this.data.images) { - for(var i=0; i<this.data.images.length; i++) { - label = label.replace(/</, "<").replace(/>/, ">").replace(/\[IMG\]/, this.data.images[i].outerHTML); - } - } - - if (!test && (!val || !$e[0].checkValidity())) { - // FIXME: error message - $e.closest('.form-group').addClass('has-error'); - $e.focus(); - def.reject(); - } - - var style = this.$("input[name='link-style-type']:checked").val() || ''; - var size = this.$("select.link-style").val() || ''; - var classes = (this.data.className || "") + (style && style.length ? " btn " : "") + style + " " + size; - var isNewWindow = this.$('input.window-new').prop('checked'); - - if ($e.hasClass('email-address') && $e.val().indexOf("@") !== -1) { - self.get_data_buy_mail(def, $e, isNewWindow, label, classes, test); - } else { - self.get_data_buy_url(def, $e, isNewWindow, label, classes, test); - } - return def; - }, - get_data_buy_mail: function (def, $e, isNewWindow, label, classes, test) { - var val = $e.val(); - def.resolve(val.indexOf("mailto:") === 0 ? val : 'mailto:' + val, isNewWindow, label, classes); - }, - get_data_buy_url: function (def, $e, isNewWindow, label, classes, test) { - def.resolve($e.val(), isNewWindow, label, classes); - }, - save: function () { - var self = this; - var _super = this._super.bind(this); - return this.get_data().then(function (url, new_window, label, classes) { - self.data.url = url; - self.data.isNewWindow = new_window; - self.data.text = label; - self.data.className = classes.replace(/\s+/gi, ' ').replace(/^\s+|\s+$/gi, ''); - if (classes.replace(/(^|[ ])(btn-default|btn-success|btn-primary|btn-info|btn-warning|btn-danger)([ ]|$)/gi, ' ')) { - self.data.style = {'background-color': '', 'color': ''}; - } - self.final_data = self.data; - }).then(_super); - }, - bind_data: function () { - var href = this.data.url; - var new_window = this.data.isNewWindow; - var text = this.data.text; - var classes = this.data.iniClassName; - - this.$('input#o_link_dialog_label_input').val(text); - this.$('input.window-new').prop('checked', new_window); - this.$('input.link-style').prop('checked', false).first().prop("checked", true); - - if (classes) { - this.$('input.link-style, select.link-style > option').each(function () { - var $option = $(this); - if ($option.val() && classes.indexOf($option.val()) >= 0) { - if ($option.is("input")) { - $option.prop("checked", true); - } else { - $option.parent().val($option.val()); - } - } - }); - } - - if (href) { - var match = /mailto:(.+)/.exec(href); - if (match) { - this.$('input.email-address').val(match = /mailto:(.+)/.exec(href) ? match[1] : ''); - } else { - this.$('input.url').val(href); - } - } - this.preview(); - }, - changed: function (e) { - $(e.target).closest('.list-group-item') - .addClass('active') - .siblings().removeClass('active') - .addBack().removeClass('has-error'); - this.preview(); - }, - onkeyup: function (e) { - var $e = $(e.target); - var is_link = $e.val().indexOf("@") === -1; - this.$('input.window-new').closest("div").toggle(is_link); - this.preview(); - }, - preview: function () { - var $preview = this.$("#link-preview"); - this.get_data(true).then(function (url, new_window, label, classes) { - $preview.attr("target", new_window ? '_blank' : "") - .attr("href", url && url.length ? url : "#") - .html((label && label.length ? label : url)) - .attr("class", classes.replace(/pull-\w+/, '') + " o_btn_preview"); - }); - } -}); - -return { - Dialog: Dialog, - alt: alt, - MediaDialog: MediaDialog, - LinkDialog: LinkDialog, - getCssSelectors: getCssSelectors, - fontIcons: fontIcons, -}; -}); |
