youtube videos
authorJan Szejko <janek37@gmail.com>
Fri, 23 Dec 2016 08:55:27 +0000 (09:55 +0100)
committerJan Szejko <janek37@gmail.com>
Fri, 23 Dec 2016 08:55:27 +0000 (09:55 +0100)
src/editor/modules/documentCanvas/canvas/canvas.js
src/editor/plugins/core/canvasElements.js
src/editor/plugins/core/img/imgElement.js
src/editor/plugins/core/switch.js
src/editor/plugins/core/video/box.html [new file with mode: 0644]
src/editor/plugins/core/video/videoElement.js [new file with mode: 0644]

index ebede40..bbdb0d4 100644 (file)
@@ -162,6 +162,11 @@ $.extend(Canvas.prototype, Backbone.Events, {
             //return DocumentTextElement.fromHTMLElement(htmlElement, canvas);
             return $element.data('canvas-element');
         }
             //return DocumentTextElement.fromHTMLElement(htmlElement, canvas);
             return $element.data('canvas-element');
         }
+
+        /* experimental */
+        if($element.parent().data('canvas-element')) {
+            return $element.parent().data('canvas-element');
+        }
     },
 
     reloadRoot: function() {
     },
 
     reloadRoot: function() {
index ab3332e..ba72c03 100644 (file)
@@ -5,7 +5,8 @@ define(function(require) {
 var $ = require('libs/jquery'),
     genericElement = require('modules/documentCanvas/canvas/genericElement'), // TODO: This should be accessible via plugin infrastructure
     linkElement = require('./links/linkElement'),
 var $ = require('libs/jquery'),
     genericElement = require('modules/documentCanvas/canvas/genericElement'), // TODO: This should be accessible via plugin infrastructure
     linkElement = require('./links/linkElement'),
-    imgElement = require('./img/imgElement')
+    imgElement = require('./img/imgElement'),
+    videoElement = require('./video/videoElement')
     ;
 
 var widgets = {
     ;
 
 var widgets = {
@@ -116,7 +117,8 @@ return [
     {tag: 'aside', klass: 'comment', prototype: null},
     {tag: 'aside', klass: 'footnote', prototype: footnote},
     {tag: 'span', klass: 'link', prototype: linkElement},
     {tag: 'aside', klass: 'comment', prototype: null},
     {tag: 'aside', klass: 'footnote', prototype: footnote},
     {tag: 'span', klass: 'link', prototype: linkElement},
-    {tag: 'div', klass: 'img', prototype: imgElement}
+    {tag: 'div', klass: 'img', prototype: imgElement},
+    {tag: 'div', klass: 'video', prototype: videoElement}
 ];
 
 
 ];
 
 
index 0ec3ca5..be0ff24 100644 (file)
@@ -20,8 +20,8 @@ _.extend(linkElement, {
 
         var linkText = this.wlxmlNode.getAttr('src') || '',
             linkUrl = this.getUrl(linkText);
 
         var linkText = this.wlxmlNode.getAttr('src') || '',
             linkUrl = this.getUrl(linkText);
-        
-        this._container().attr('style', 'background-image: url(\'' + linkUrl + '\');');
+
+        this.refreshLink(linkUrl);
 
         this.box = $(_.template(boxTemplate)({text: linkText, url: linkUrl}));
         this.box.find('.change').on('click', this.changeLink);
 
         this.box = $(_.template(boxTemplate)({text: linkText, url: linkUrl}));
         this.box.find('.change').on('click', this.changeLink);
@@ -41,10 +41,15 @@ _.extend(linkElement, {
             link.text(event.meta.newVal);
             var linkUrl = this.getUrl(event.meta.newVal);
             link.attr('href', linkUrl);
             link.text(event.meta.newVal);
             var linkUrl = this.getUrl(event.meta.newVal);
             link.attr('href', linkUrl);
-            this._container().attr('style', 'background-image: url(\'' + linkUrl + '\');');
+            this.refreshLink(linkUrl);
         }
     },
 
         }
     },
 
+    refreshLink: function(linkUrl) {
+        this._container().text('');
+        this._container().attr('style', 'background-image: url(\'' + linkUrl + '\');');
+    },
+
     changeLink: function(e) {
         var el = this,
             //doc = this.wlxmlNode.document,
     changeLink: function(e) {
         var el = this,
             //doc = this.wlxmlNode.document,
index 88544bf..e3ec5c4 100644 (file)
@@ -68,12 +68,13 @@ var createSwitchAction = function(createParams) {
 
 var headerAction = createSwitchAction({name: 'switchToHeader', from: {tagName: 'div', klass: 'p'}, to: {tagName: 'header', klass: '', name: gettext('header')}}),
     paragraphAction = createSwitchAction({name: 'switchToParagraph', from: {tagName: 'header'}, to: {tagName: 'div', klass: 'p', name: gettext('paragraph')}}),
 
 var headerAction = createSwitchAction({name: 'switchToHeader', from: {tagName: 'div', klass: 'p'}, to: {tagName: 'header', klass: '', name: gettext('header')}}),
     paragraphAction = createSwitchAction({name: 'switchToParagraph', from: {tagName: 'header'}, to: {tagName: 'div', klass: 'p', name: gettext('paragraph')}}),
-    imageAction = createSwitchAction({name: 'switchToImage', from: {tagName: 'div'}, to: {tagName: 'div', klass: 'img', name: gettext('image')}});
+    imageAction = createSwitchAction({name: 'switchToImage', from: {tagName: 'div'}, to: {tagName: 'div', klass: 'img', name: gettext('image')}}),
+    videoAction = createSwitchAction({name: 'switchToVideo', from: {tagName: 'div'}, to: {tagName: 'div', klass: 'video', name: gettext('video')}});
 
 return {
 
 return {
-    actions: [headerAction, paragraphAction, imageAction],
+    actions: [headerAction, paragraphAction, imageAction, videoAction],
     canvasActionHandler: {
     canvasActionHandler: {
-        handles: [headerAction, paragraphAction, imageAction],
+        handles: [headerAction, paragraphAction, imageAction, videoAction]
         // handle: function(canvas, action, ret) {
         //     var params = {},
         //         f;
         // handle: function(canvas, action, ret) {
         //     var params = {},
         //         f;
diff --git a/src/editor/plugins/core/video/box.html b/src/editor/plugins/core/video/box.html
new file mode 100644 (file)
index 0000000..9294581
--- /dev/null
@@ -0,0 +1,7 @@
+<div link-box style="white-space: nowrap">
+    <a link target="blank" href="<%= url %>"><%= text %></a> <br/>--
+    <span>
+        <a class="change" href="#"><%= gettext('change') %></a>
+        <a class="delete" href="#"><%= gettext('remove') %></a>
+    </span>
+</div>
diff --git a/src/editor/plugins/core/video/videoElement.js b/src/editor/plugins/core/video/videoElement.js
new file mode 100644 (file)
index 0000000..96003d7
--- /dev/null
@@ -0,0 +1,133 @@
+define(function(require) {
+    
+'use strict';
+/* globals gettext */
+
+
+var $ = require('libs/jquery'),
+    _ = require('libs/underscore'),
+    genericElement = require('modules/documentCanvas/canvas/genericElement'),
+    Dialog = require('views/dialog/dialog'),
+    boxTemplate = require('libs/text!./box.html'),
+    attachments = require('views/attachments/attachments'),
+    linkElement = Object.create(genericElement);
+
+function youtubeParser(url) {
+    var regExp = /^.*(?:youtu.be\/|v\/|\/u\/\w\/|embed\/|\?v=|&v=|shared\?ci=)([^#&?]*).*/;
+    var match = url.match(regExp);
+    return (match && match[1].length == 11) ? match[1] : false;
+}
+
+_.extend(linkElement, {
+    init: function() {
+        genericElement.init.call(this);
+        _.bindAll(this, 'changeLink', 'deleteLink');
+
+        var linkText = this.wlxmlNode.getAttr('src') || '',
+            linkUrl = this.getUrl(linkText);
+        
+        this.refreshLink(linkUrl);
+
+        this.box = $(_.template(boxTemplate)({text: linkText, url: linkUrl}));
+        this.box.find('.change').on('click', this.changeLink);
+        this.box.find('.delete').on('click', this.deleteLink);
+        this.box.hide();
+        this.addWidget(this.box);
+    },
+    onStateChange: function(changes) {
+        genericElement.onStateChange.call(this, changes);
+        if(_.isBoolean(changes.active)) {
+            this.box.toggle(changes.active);
+        }
+    },
+    onNodeAttrChange: function(event) {
+        if(event.meta.attr === 'src') {
+            var link = this.box.find('[link]');
+            link.text(event.meta.newVal);
+            var linkUrl = this.getUrl(event.meta.newVal);
+            link.attr('href', linkUrl);
+            this.refreshLink(linkUrl);
+        }
+    },
+
+    refreshLink: function(linkUrl) {
+        this._container().find('iframe').remove();
+        var video_id = youtubeParser(linkUrl);
+        if (video_id) {
+            var video_frame = '<iframe width="480" height="270" src="//www.youtube.com/embed/' + video_id +
+                '?controls=2&amp;rel=0&amp;showinfo=0&amp;theme=light" frameborder="0" allowfullscreen></iframe>';
+            this._container().text('');
+            this._container().append($(video_frame));
+        } else {
+            this._container().text(gettext('No video'));
+        }
+    },
+
+    changeLink: function(e) {
+        var el = this,
+            dialog = Dialog.create({
+            title: gettext('Edit video url'),
+            executeButtonText: gettext('Apply'),
+            cancelButtonText: gettext('Cancel'),
+            fields: [
+                {
+                    label: gettext('YouTube link'),
+                    name: 'src',
+                    type: 'input',
+                    initialValue: el.wlxmlNode.getAttr('src'),
+                    prePasteHandler:
+                        function(text) {
+                            return this.wlxmlNode.document.getLinkForUrl(text);
+                        }.bind(this)
+                }
+            ]
+        });
+        e.preventDefault();
+        e.stopPropagation();
+
+        dialog.on('execute', function(event) {
+            el.wlxmlNode.document.transaction(function() {
+                el.wlxmlNode.setAttr('src', event.formData.src);
+                el.wlxmlNode.setAttr('videoid', youtubeParser(event.formData.src));
+                event.success();
+            }, {
+                metadata: {
+                    description: gettext('Edit video url')
+                    //fragment: doc.createFragment(doc.CaretFragment, {node: el.wlxmlNode.contents()[0], offset:offset})
+                },
+                success: function() {
+                    //el.canvas.select(doc.createFragment(doc.CaretFragment, {node: el.wlxmlNode.contents()[0], offset:offset}));
+                }
+            });
+        });
+        dialog.show();
+        $(".attachment-library", dialog.$el).on('click', function() {
+            attachments.select(function(v) {$("input", dialog.$el).val(v);});
+        });
+
+    },
+
+    deleteLink: function() {
+        var el = this;
+
+        el.wlxmlNode.document.transaction(function() {
+            el.wlxmlNode.detach();
+        }, {
+            metadata: {
+                description: gettext('Remove link')
+            }
+        });
+    },
+
+    getUrl: function(link) {
+        var pattern = /^[a-z]*:\/\//g;
+        if(!pattern.test(link) && !/^\//.test(link)) {
+            link = 'http://' + link;
+        }
+        return this.wlxmlNode.document.getUrlForLink(link);
+    }
+});
+
+return linkElement;
+
+});