Merging in creating/editing links via popup
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Mon, 24 Mar 2014 09:22:02 +0000 (10:22 +0100)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Mon, 24 Mar 2014 09:22:02 +0000 (10:22 +0100)
18 files changed:
src/editor/modules/data/data.js
src/editor/modules/data/data.less [deleted file]
src/editor/modules/data/dialog.html [deleted file]
src/editor/modules/data/dialog.js [deleted file]
src/editor/modules/data/dialog.less [deleted file]
src/editor/modules/data/templates/checkbox.html [deleted file]
src/editor/modules/data/templates/input.html [deleted file]
src/editor/modules/data/templates/select.html [deleted file]
src/editor/modules/data/templates/textarea.html [deleted file]
src/editor/modules/documentCanvas/commands.js
src/editor/styles/main.less
src/editor/views/dialog/dialog.html [new file with mode: 0644]
src/editor/views/dialog/dialog.js [new file with mode: 0644]
src/editor/views/dialog/dialog.less [new file with mode: 0644]
src/editor/views/dialog/templates/checkbox.html [new file with mode: 0644]
src/editor/views/dialog/templates/input.html [new file with mode: 0644]
src/editor/views/dialog/templates/select.html [new file with mode: 0644]
src/editor/views/dialog/templates/textarea.html [new file with mode: 0644]

index 42e46f8..3bb2c2c 100644 (file)
@@ -1,6 +1,6 @@
 define([
     'libs/jquery',
-    './dialog',
+    'views/dialog/dialog',
     'wlxml/wlxml',
     'wlxml/extensions/list/list',
     'fnpjs/logging/logging',
diff --git a/src/editor/modules/data/data.less b/src/editor/modules/data/data.less
deleted file mode 100644 (file)
index 2a21630..0000000
+++ /dev/null
@@ -1 +0,0 @@
-@import 'dialog.less';
\ No newline at end of file
diff --git a/src/editor/modules/data/dialog.html b/src/editor/modules/data/dialog.html
deleted file mode 100644 (file)
index 80c9fb2..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<div class="rng-dialog modal hide static">
-    <div class="modal-header">
-        <button type="button" class="close">&times;</button>
-        <h1><%= title %></h1>
-    </div>
-    <div class="modal-body">
-    </div>
-    <div class="modal-footer">
-        <a href="#" class="btn btn-info btn-mini execute-btn"><%= executeButtonText %></a>
-        <a href="#" class="btn btn-danger btn-mini cancel-btn"><%= cancelButtonText %></a>
-    </div>
-</div>
\ No newline at end of file
diff --git a/src/editor/modules/data/dialog.js b/src/editor/modules/data/dialog.js
deleted file mode 100644 (file)
index 0d4bbd4..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-define(function(require) {
-
-    /* globals gettext */
-    'use strict';
-
-    var _ = require('libs/underscore'),
-        Backbone = require('libs/backbone'),
-        dialogTemplate = require('libs/text!./dialog.html'),
-        fieldTemplates = {};
-        fieldTemplates.checkbox = require('libs/text!./templates/checkbox.html');
-        fieldTemplates.select = require('libs/text!./templates/select.html');
-        fieldTemplates.textarea = require('libs/text!./templates/textarea.html');
-        fieldTemplates.input = require('libs/text!./templates/input.html');
-
-
-
-    var DialogView = Backbone.View.extend({
-        template: _.template(dialogTemplate),
-        events: {
-            'click .execute-btn': 'onExecute',
-            'click .cancel-btn': 'onCancel',
-            'click .close': 'close'
-        },
-        initialize: function() {
-            _.bindAll(this);
-            this.actionsDisabled = false;
-        },
-        show: function() {
-            this.setElement(this.template(_.extend({
-                executeButtonText: gettext('Submit'),
-                cancelButtonText: gettext('Cancel')
-            }, this.options)));
-
-            var body = this.$('.modal-body');
-            (this.options.fields || []).forEach(function(field) {
-                var template = fieldTemplates[field.type];
-                if(!template) {
-                    throw new Error('Field type {type} not recognized.'.replace('{type}', field.type));
-                }
-                body.append(
-                    _.template(template)(_.extend({description: ''}, field))
-                );
-            });
-
-            if(this.options.text) {
-                body.append('<p>' + this.options.text + '</p>');
-            }
-
-            this.$el.modal({backdrop: 'static'});
-            this.$el.modal('show');
-            this.$('textarea').focus();
-        },
-        onExecute: function(e) {
-            e.preventDefault();
-            var view = this,
-                formData = {};
-
-            (this.options.fields || []).forEach(function(field) {
-                var widget = view.$('[name=' + field.name +']');
-                formData[field.name] = widget.val();
-            });
-
-            this.trigger('execute', {
-                formData: formData,
-                success: function() { view.actionsDisabled = false; view.close(); },
-                error: function() { view.actionsDisabled = false; view.close(); },
-            });
-        },
-        onCancel: function() {
-            this.trigger('cancel');
-            this.close();
-        },
-        close: function(e) {
-            if(e) {
-                e.preventDefault();
-            }
-            if(!this.actionsDisabled) {
-                this.$el.modal('hide');
-                this.$el.remove();
-            }
-            this.trigger('close');
-        },
-        toggleButtons: function(toggle) {
-            this.$('.btn, button').toggleClass('disabled', !toggle);
-            this.$('textarea').attr('disabled', !toggle);
-            this.actionsDisabled = !toggle;
-        }
-    });
-
-    return {
-        create: function(config) {
-            return new DialogView(config);
-        }
-    };
-
-});
\ No newline at end of file
diff --git a/src/editor/modules/data/dialog.less b/src/editor/modules/data/dialog.less
deleted file mode 100644 (file)
index 8128162..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-.rng-dialog {
-    textarea {
-        padding: 3px 3px;
-        margin: 5px auto;
-        width: 95%;
-        display: block;
-    }
-    
-    h1, label {
-        font-size: 12px;
-        line-height: 12px;
-
-    }
-    
-    h1 {
-        margin: 2px 5px;
-        font-weight: bold;
-    }
-
-    .description {
-        font-size: .8em;
-    }
-
-    width: 620px;
-}
\ No newline at end of file
diff --git a/src/editor/modules/data/templates/checkbox.html b/src/editor/modules/data/templates/checkbox.html
deleted file mode 100644 (file)
index 3c14092..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<p>
-    <div style="float: left; width:100px;"><%= label %>:</div>
-    <input type="checkbox" name="<%= name %>"/> 
-    <span class="description"><%= description %></span>
-</p>
\ No newline at end of file
diff --git a/src/editor/modules/data/templates/input.html b/src/editor/modules/data/templates/input.html
deleted file mode 100644 (file)
index f60f2f6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<p>
-    <div style="float: left; width:100px;">
-    <%= label %>:
-    </div>
-    <div>
-        <input type="input" name="<%= name %>"/>
-        <span class="description"><%= description %></span>
-    </div>
-    
-</p>
\ No newline at end of file
diff --git a/src/editor/modules/data/templates/select.html b/src/editor/modules/data/templates/select.html
deleted file mode 100644 (file)
index 4b5a1de..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<p>
-    <div style="float: left; width:100px;"><%= label %>:</div>
-    <select name="<%= name %>">
-    <% options.forEach(function(option) { %>
-        <option value="<%= option.value %>"><%= option.text %></option>
-    <% }); %>
-    </select>
-    <span class="description"><%= description %></span>
-</p>
\ No newline at end of file
diff --git a/src/editor/modules/data/templates/textarea.html b/src/editor/modules/data/templates/textarea.html
deleted file mode 100644 (file)
index 50b7c50..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<p>
-    <label><%= label %></label>
-    <textarea name="<%= name %>" rows="5"></textarea>
-    <span class="description"><%= description %></span>
-</p>
index 11a874a..55de02c 100644 (file)
@@ -1,8 +1,11 @@
 define([
-'./canvas/utils'
-], function(utils) {
+'./canvas/utils',
+'views/dialog/dialog',
+'fnpjs/datetime'
+], function(utils, Dialog, datetime) {
     
 'use strict';
+/* globals gettext */
 
 
 var gridToggled = false;
@@ -104,22 +107,21 @@ commands.register('newNodeRequested', function(canvas, params, user) {
     var cursor = canvas.getCursor(),
         selectionStart = cursor.getSelectionStart(),
         selectionEnd = cursor.getSelectionEnd(),
-        wlxmlNode, caretTo, wrapper, wrapperCanvasElement;
+        wlxmlNode, caretTo, wrapperCanvasElement;
 
-    var insertNode = function(insertion) {
+    var insertNode = function(insertion, callback) {
         var doc = canvas.wlxmlDocument,
-            node, metadata, creator, currentDate, dt;
+            node, metadata, creator, dialog;
 
-        var pad = function(number) {
-            if(number < 10) {
-                number = '0' + number;
+        var execCallback = function(node) {
+            if(callback) {
+                callback(node);
             }
-            return number;
         };
 
-        doc.startTransaction();
-        node = insertion();
-        if(node.getTagName() === 'aside' && node.getClass() === 'comment') {
+        if(params.wlxmlTag === 'aside' && params.wlxmlClass === 'comment') {
+            doc.startTransaction();
+            node = insertion();
             if(user) {
                 creator = user.name;
                 if(user.email) {
@@ -129,49 +131,71 @@ commands.register('newNodeRequested', function(canvas, params, user) {
                 creator = 'anonymous';
             }
 
-            currentDate = new Date();
-            dt = pad(currentDate.getDate()) + '-' +
-                            pad((currentDate.getMonth() + 1))  + '-' +
-                            pad(currentDate.getFullYear()) + ' ' +
-                            pad(currentDate.getHours()) + ':' +
-                            pad(currentDate.getMinutes()) + ':' +
-                            pad(currentDate.getSeconds());
-
             metadata = node.getMetadata();
             metadata.add({key: 'creator', value: creator});
-            metadata.add({key: 'date', value: dt});
+            metadata.add({key: 'date', value: datetime.currentStrfmt()});
+            doc.endTransaction();
+            execCallback(node);
+        } else if(params.wlxmlClass === 'link') {
+            dialog = Dialog.create({
+                title: gettext('Create link'),
+                executeButtonText: gettext('Apply'),
+                cancelButtonText: gettext('Cancel'),
+                fields: [
+                    {label: gettext('Link'), name: 'href', type: 'input'}
+                ]
+            });
+            dialog.on('execute', function(event) {
+                doc.startTransaction();
+                node = insertion();
+                node.setAttr('href', event.formData.href);
+                doc.endTransaction();
+                event.success();
+                execCallback(node);
+            });
+            dialog.show();
+        } else {
+            doc.startTransaction();
+            node = insertion();
+            doc.endTransaction();
+            execCallback(node);
         }
-        doc.endTransaction();
-        return node;
     };
 
-
     if(cursor.isSelecting()) {
         if(cursor.isSelectingSiblings()) {
             if(cursor.isSelectingWithinElement()) {
                 wlxmlNode = selectionStart.element.data('wlxmlNode');
                 caretTo = selectionStart.offset < selectionEnd.offset ? 'start' : 'end';
 
-                wrapper = insertNode(function() {
-                    return wlxmlNode.wrapWith({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}, start: selectionStart.offset, end: selectionEnd.offset});
-                });
-                wrapperCanvasElement = utils.findCanvasElement(wrapper);
-                canvas.setCurrentElement(wrapperCanvasElement.children()[0], {caretTo: caretTo});
+                insertNode(
+                    function() {
+                        return wlxmlNode.wrapWith({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}, start: selectionStart.offset, end: selectionEnd.offset});
+                    },
+                    function(wrapper) {
+                        wrapperCanvasElement = utils.findCanvasElement(wrapper);
+                        canvas.setCurrentElement(wrapperCanvasElement.children()[0], {caretTo: caretTo});
+                    }
+                );
             }
             else {
                 wlxmlNode = selectionStart.element.data('wlxmlNode').parent();
                 caretTo = selectionStart.element.sameNode(cursor.getSelectionAnchor().element) ? 'end' : 'start';
 
-                wrapper = insertNode(function() {
-                    return wlxmlNode.wrapText({
-                        _with: {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}},
-                        offsetStart: selectionStart.offset,
-                        offsetEnd: selectionEnd.offset,
-                        textNodeIdx: [wlxmlNode.indexOf(selectionStart.element.data('wlxmlNode')), wlxmlNode.indexOf(selectionEnd.element.data('wlxmlNode'))] //parent.childIndex(selectionEnd.element)]
-                    });
-                });
-                wrapperCanvasElement = utils.findCanvasElement(wrapper);
-                canvas.setCurrentElement(wrapperCanvasElement.children()[caretTo === 0 ? 0 : wrapperCanvasElement.children().length - 1], {caretTo: caretTo});
+                insertNode(
+                    function() {
+                        return wlxmlNode.wrapText({
+                            _with: {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}},
+                            offsetStart: selectionStart.offset,
+                            offsetEnd: selectionEnd.offset,
+                            textNodeIdx: [wlxmlNode.indexOf(selectionStart.element.data('wlxmlNode')), wlxmlNode.indexOf(selectionEnd.element.data('wlxmlNode'))] //parent.childIndex(selectionEnd.element)]
+                        });
+                    },
+                    function(wrapper) {
+                        wrapperCanvasElement = utils.findCanvasElement(wrapper);
+                        canvas.setCurrentElement(wrapperCanvasElement.children()[caretTo === 0 ? 0 : wrapperCanvasElement.children().length - 1], {caretTo: caretTo});
+                    }
+                );
             }
         } else {
             var node1 = selectionStart.element.data('wlxmlNode'),
@@ -179,32 +203,65 @@ commands.register('newNodeRequested', function(canvas, params, user) {
                 siblingParents = canvas.wlxmlDocument.getSiblingParents({node1: node1, node2: node2});
 
             if(siblingParents) {
-                insertNode(function() {
-                    return canvas.wlxmlDocument.wrapNodes({
-                        node1: siblingParents.node1,
-                        node2: siblingParents.node2,
-                        _with: {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}}
-                    });
-                });
+                insertNode(
+                    function() {
+                        return canvas.wlxmlDocument.wrapNodes({
+                            node1: siblingParents.node1,
+                            node2: siblingParents.node2,
+                            _with: {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}}
+                        });
+                    }
+                );
             }
         }
     } else if(canvas.getCurrentNodeElement()) {
         wlxmlNode = canvas.getCurrentNodeElement().data('wlxmlNode');
+
+        var linkFound = [wlxmlNode].concat(wlxmlNode.parents()).some(function(node) {
+            if(node.getClass() === 'link') {
+                var dialog = Dialog.create({
+                    title: gettext('Edit link'),
+                    executeButtonText: gettext('Apply'),
+                    cancelButtonText: gettext('Cancel'),
+                    fields: [
+                        {label: gettext('Link'), name: 'href', type: 'input', initialValue: node.getAttr('href')},
+                    ]
+                });
+                dialog.on('execute', function(event) {
+                    canvas.wlxmlDocument.startTransaction();
+                    node.setAttr('href', event.formData.href);
+                    event.success();
+                    canvas.wlxmlDocument.endTransaction();
+                });
+                dialog.show();
+                return true;
+            }
+        });
+        if(linkFound) {
+            return;
+        }
+
         if(params.ctrlKey) {
-            wrapper = insertNode(function() {
-                return wlxmlNode.wrapWith({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}});
-            });
+            insertNode(
+                function() {
+                    return wlxmlNode.wrapWith({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}});
+                },
+                function(wrapper) {
+                    canvas.setCurrentElement(utils.findCanvasElement(wrapper));
+                }
+            );
         } else {
-            wrapper = insertNode(function() {
-                var node = wlxmlNode.after({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}});
-                node.append({text:''});
-                return node;
-            });
+            insertNode(
+                function() {
+                    var node = wlxmlNode.after({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}});
+                    node.append({text:''});
+                    return node;
+                }, function(wrapper) {
+                    canvas.setCurrentElement(utils.findCanvasElement(wrapper));
+                }
+            );
         }
-        canvas.setCurrentElement(utils.findCanvasElement(wrapper));
     }
-
-
 });
 
 commands.register('footnote', function(canvas, params) {
index 2792657..82bf8d5 100644 (file)
@@ -3,7 +3,7 @@
 @import 'common.less';
 
 @import '../views/openSelect/openSelect.less';
-@import '../modules/data/data.less';
+@import '../views/dialog/dialog.less';
 @import '../modules/rng/rng.less';
 @import '../modules/documentCanvas/documentCanvas.less';
 @import '../modules/sourceEditor/sourceEditor.less';
diff --git a/src/editor/views/dialog/dialog.html b/src/editor/views/dialog/dialog.html
new file mode 100644 (file)
index 0000000..80c9fb2
--- /dev/null
@@ -0,0 +1,12 @@
+<div class="rng-dialog modal hide static">
+    <div class="modal-header">
+        <button type="button" class="close">&times;</button>
+        <h1><%= title %></h1>
+    </div>
+    <div class="modal-body">
+    </div>
+    <div class="modal-footer">
+        <a href="#" class="btn btn-info btn-mini execute-btn"><%= executeButtonText %></a>
+        <a href="#" class="btn btn-danger btn-mini cancel-btn"><%= cancelButtonText %></a>
+    </div>
+</div>
\ No newline at end of file
diff --git a/src/editor/views/dialog/dialog.js b/src/editor/views/dialog/dialog.js
new file mode 100644 (file)
index 0000000..04d8f74
--- /dev/null
@@ -0,0 +1,96 @@
+define(function(require) {
+
+    /* globals gettext */
+    'use strict';
+
+    var _ = require('libs/underscore'),
+        Backbone = require('libs/backbone'),
+        dialogTemplate = require('libs/text!./dialog.html'),
+        fieldTemplates = {};
+        fieldTemplates.checkbox = require('libs/text!./templates/checkbox.html');
+        fieldTemplates.select = require('libs/text!./templates/select.html');
+        fieldTemplates.textarea = require('libs/text!./templates/textarea.html');
+        fieldTemplates.input = require('libs/text!./templates/input.html');
+
+
+
+    var DialogView = Backbone.View.extend({
+        template: _.template(dialogTemplate),
+        events: {
+            'click .execute-btn': 'onExecute',
+            'click .cancel-btn': 'onCancel',
+            'click .close': 'close'
+        },
+        initialize: function() {
+            _.bindAll(this);
+            this.actionsDisabled = false;
+        },
+        show: function() {
+            this.setElement(this.template(_.extend({
+                executeButtonText: gettext('Submit'),
+                cancelButtonText: gettext('Cancel')
+            }, this.options)));
+
+            var body = this.$('.modal-body');
+            (this.options.fields || []).forEach(function(field) {
+                var template = fieldTemplates[field.type];
+                if(!template) {
+                    throw new Error('Field type {type} not recognized.'.replace('{type}', field.type));
+                }
+                body.append(
+                    _.template(template)(_.extend({description: '', initialValue: ''}, field))
+                );
+            });
+
+            if(this.options.text) {
+                body.append('<p>' + this.options.text + '</p>');
+            }
+
+            this.$el.modal({backdrop: 'static'});
+            this.$el.modal('show');
+            this.$('textarea, input').first().focus();
+        },
+        onExecute: function(e) {
+            e.preventDefault();
+            var view = this,
+                formData = {};
+
+            (this.options.fields || []).forEach(function(field) {
+                var widget = view.$('[name=' + field.name +']');
+                formData[field.name] = widget.val();
+            });
+
+            this.trigger('execute', {
+                formData: formData,
+                success: function() { view.actionsDisabled = false; view.close(); },
+                error: function() { view.actionsDisabled = false; view.close(); },
+            });
+        },
+        onCancel: function() {
+            this.trigger('cancel');
+            this.close();
+        },
+        close: function(e) {
+            if(e) {
+                e.preventDefault();
+            }
+            if(!this.actionsDisabled) {
+                this.$el.modal('hide');
+                this.$el.remove();
+            }
+            this.trigger('close');
+        },
+        toggleButtons: function(toggle) {
+            this.$('.btn, button').toggleClass('disabled', !toggle);
+            this.$('textarea').attr('disabled', !toggle);
+            this.actionsDisabled = !toggle;
+        }
+    });
+
+    return {
+        create: function(config) {
+            return new DialogView(config);
+        }
+    };
+
+});
\ No newline at end of file
diff --git a/src/editor/views/dialog/dialog.less b/src/editor/views/dialog/dialog.less
new file mode 100644 (file)
index 0000000..8128162
--- /dev/null
@@ -0,0 +1,25 @@
+.rng-dialog {
+    textarea {
+        padding: 3px 3px;
+        margin: 5px auto;
+        width: 95%;
+        display: block;
+    }
+    
+    h1, label {
+        font-size: 12px;
+        line-height: 12px;
+
+    }
+    
+    h1 {
+        margin: 2px 5px;
+        font-weight: bold;
+    }
+
+    .description {
+        font-size: .8em;
+    }
+
+    width: 620px;
+}
\ No newline at end of file
diff --git a/src/editor/views/dialog/templates/checkbox.html b/src/editor/views/dialog/templates/checkbox.html
new file mode 100644 (file)
index 0000000..3c14092
--- /dev/null
@@ -0,0 +1,5 @@
+<p>
+    <div style="float: left; width:100px;"><%= label %>:</div>
+    <input type="checkbox" name="<%= name %>"/> 
+    <span class="description"><%= description %></span>
+</p>
\ No newline at end of file
diff --git a/src/editor/views/dialog/templates/input.html b/src/editor/views/dialog/templates/input.html
new file mode 100644 (file)
index 0000000..1600d87
--- /dev/null
@@ -0,0 +1,10 @@
+<p>
+    <div style="float: left; width:100px;">
+    <%= label %>:
+    </div>
+    <div>
+        <input type="input" name="<%= name %>" value="<%= initialValue %>"/>
+        <span class="description"><%= description %></span>
+    </div>
+    
+</p>
\ No newline at end of file
diff --git a/src/editor/views/dialog/templates/select.html b/src/editor/views/dialog/templates/select.html
new file mode 100644 (file)
index 0000000..4b5a1de
--- /dev/null
@@ -0,0 +1,9 @@
+<p>
+    <div style="float: left; width:100px;"><%= label %>:</div>
+    <select name="<%= name %>">
+    <% options.forEach(function(option) { %>
+        <option value="<%= option.value %>"><%= option.text %></option>
+    <% }); %>
+    </select>
+    <span class="description"><%= description %></span>
+</p>
\ No newline at end of file
diff --git a/src/editor/views/dialog/templates/textarea.html b/src/editor/views/dialog/templates/textarea.html
new file mode 100644 (file)
index 0000000..839e7f4
--- /dev/null
@@ -0,0 +1,5 @@
+<p>
+    <label><%= label %></label>
+    <textarea name="<%= name %>" rows="5"><%= initialValue %></textarea>
+    <span class="description"><%= description %></span>
+</p>