editor: Improved use of contenteditable for a caret support
[fnpeditor.git] / src / editor / modules / documentCanvas / canvas / comments / comments.js
index 790731f..65c80f2 100644 (file)
@@ -1,7 +1,7 @@
 define(function(require) {
     
 'use strict';
 define(function(require) {
     
 'use strict';
-/* globals Node, gettext */
+/* globals gettext */
 
 
 var $ = require('libs/jquery'),
 
 
 var $ = require('libs/jquery'),
@@ -11,7 +11,20 @@ var $ = require('libs/jquery'),
     commentTemplate = require('libs/text!./comment.html');
 
 
     commentTemplate = require('libs/text!./comment.html');
 
 
-var View = function(node, user) {
+var makeAutoResizable = function(textarea) {
+    textarea.on('input', function() {
+        resize(textarea);
+    });
+};
+
+var resize = function(textarea) {
+    if(textarea.prop('scrollHeight') > textarea.prop('clientHeight')) {
+        textarea.height(textarea.prop('scrollHeight'));
+    }
+};
+
+
+var CommentsView = function(node, user) {
     this.node = node;
     this.user = user;
     this.dom = $(_.template(commentsTemplate)());
     this.node = node;
     this.user = user;
     this.dom = $(_.template(commentsTemplate)());
@@ -22,13 +35,9 @@ var View = function(node, user) {
 
     this.textarea.on('input', function() {
         this.addButton.attr('disabled', this.textarea.val() === '');
 
     this.textarea.on('input', function() {
         this.addButton.attr('disabled', this.textarea.val() === '');
-
-        if (this.textarea.prop('scrollHeight') > this.textarea.prop('clientHeight')) {
-            this.textarea.height(this.textarea.prop('scrollHeight'));
-        }
-
-
     }.bind(this));
     }.bind(this));
+    makeAutoResizable(this.textarea);
+
     this.addButton.hide();
     this.cancelButton.hide();
     this.textarea.on('focus', function() {
     this.addButton.hide();
     this.cancelButton.hide();
     this.textarea.on('focus', function() {
@@ -82,83 +91,129 @@ var View = function(node, user) {
 
 };
 
 
 };
 
-_.extend(View.prototype, {
+_.extend(CommentsView.prototype, {
     render: function() {
         this.list.empty();
     render: function() {
         this.list.empty();
-
-        // while(this.node.getTagName() === 'span' && this.node.parent()) {
-        //     this.node = this.node.parent();
-        // }
         this.textarea.attr('placeholder', gettext('Comment'));
 
         this.node.contents()
             .filter(function(child) {
         this.textarea.attr('placeholder', gettext('Comment'));
 
         this.node.contents()
             .filter(function(child) {
-                return child.nodeType === Node.ELEMENT_NODE && child.getTagName() === 'aside' && child.getClass() === 'comment';
-                //return child.is({tag: 'aside', klass: 'comment'});
-
+                return child.is({tag: 'aside', klass: 'comment'});
             })
             .forEach(function(commentNode) {
             })
             .forEach(function(commentNode) {
-                var metaData = commentNode.getMetadata(),
-                    author, date, content;
-
-                metaData.some(function(row) {
-                    author = row.getValue();
-                    if(author) {
-                        author = author.split(' ')[0];
-                    }
-                    return true;
-                }, 'creator');
-                
-                metaData.some(function(row) {
-                    date = row.getValue();
-                    return true;
-                }, 'date');
-
-                content = commentNode.object.getText();
-
-                var commentView = $(_.template(commentTemplate)({
-                    author: author ||'?',
-                    date: date || '?',
-                    content: content || '?'
-                }));
-
-                commentView.find('.remove-btn').on('click', function() {
-                    commentNode.document.transaction(function() {
-                        commentNode.detach();
-                    }, {
-                        metadata: {
-                            description: gettext('Remove comment')
-                        }
-                    });
-                });
-
-                this.list.append(commentView);
+                var commentView = new CommentView(commentNode);
+                this.list.append(commentView.dom);
                 this.textarea.attr('placeholder', gettext('Respond') + '...');
             }.bind(this));
                 this.textarea.attr('placeholder', gettext('Respond') + '...');
             }.bind(this));
-        
     },
     onActivated: function() {
     },
     onActivated: function() {
-        //if(this.list.find('.comment').length === 0) {
             this.dom.find('.newComment').toggle(true);
             this.dom.find('.newComment').toggle(true);
-        //}
-       //this.dom.show();
-
     },
     onDeactivated: function() {
       this.dom.find('.newComment').toggle(false);
       this.addButton.hide();
       this.cancelButton.hide();
     },
     onDeactivated: function() {
       this.dom.find('.newComment').toggle(false);
       this.addButton.hide();
       this.cancelButton.hide();
-      //this.dom.hide();
-
     },
     },
+});
 
 
-    getHeight: function() {
-        return this.dom.outerHeight();
-    }
 
 
+var CommentView = function(commentNode) {
+    this.node = commentNode;
+
+    var metaData = this.node.getMetadata(),
+        author, date;
+
+    metaData.some(function(row) {
+        author = row.getValue();
+        if(author) {
+            author = author.split(' ')[0];
+        }
+        return true;
+    }, 'creator');
+    
+    metaData.some(function(row) {
+        date = row.getValue();
+        if(/[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/g.test(date)) {
+            date = date.split(':');
+            date.pop();
+            date = date.join(':');
+        }
+        return true;
+    }, 'date');
+
+    this.dom = $(_.template(commentTemplate)({
+        author: author || '',
+        date: date || '',
+        content: this.node.object.getText() || '?'
+    }));
+
+    this.contentElement = this.dom.find('.content');
+    this.editElement = this.dom.find('.edit');
+    this.deleteDialogElement = this.dom.find('.deleteDialog');
+
+    this.dom.find('.remove-btn').on('click', function() {
+        this.deleteDialogElement.show();
+    }.bind(this));
+
+    this.dom.find('.deleteDialog-confirm').on('click', function() {
+        this.node.document.transaction(function() {
+            this.node.detach();
+        }.bind(this), {
+            metadata: {
+                description: gettext('Remove comment')
+            }
+        });
+    }.bind(this));
+
+    this.dom.find('.deleteDialog-cancel').on('click', function() {
+        this.deleteDialogElement.hide();
+    }.bind(this));
+
+    this.dom.find('.edit-start-btn').on('click', function() {
+        this.startEditing();
+    }.bind(this));
+
+    this.dom.find('.edit-save-btn').on('click', function() {
+        this.saveEditing();
+    }.bind(this));
+
+    this.dom.find('.edit-cancel-btn').on('click', function() {
+        this.cancelEditing();
+    }.bind(this));
+
+    this.textarea = this.editElement.find('textarea');
+    this.textarea.on('input', function() {
+        this.dom.find('.edit-save-btn').attr('disabled', this.textarea.val() === '');
+    }.bind(this));
+    makeAutoResizable(this.textarea);
+};
+
+$.extend(CommentView.prototype, {
+    startEditing: function() {
+        this.contentElement.hide();
+        this.editElement.show();
+        this.textarea.val(this.node.object.getText());
+        resize(this.textarea);
+        this.textarea.focus();
+    },
+    saveEditing: function() {
+        var newContent = this.editElement.find('textarea').val();
+        this.node.document.transaction(function() {
+            this.node.object.setText(newContent);
+        }.bind(this), {
+            metadata: {
+                description: gettext('Edit comment')
+            }
+        });
+    },
+    cancelEditing: function() {
+        this.contentElement.show();
+        this.editElement.find('textarea').val('');
+        this.editElement.hide();
+    },
 });
 
 
 });
 
 
-return View;
+return CommentsView;
 
 });
\ No newline at end of file
 
 });
\ No newline at end of file