Added support for multi-line comments
authorAlexander Ebert <ebert@woltlab.com>
Tue, 10 Jun 2014 20:07:08 +0000 (22:07 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 10 Jun 2014 20:07:08 +0000 (22:07 +0200)
wcfsetup/install/files/js/WCF.Comment.js
wcfsetup/install/files/js/WCF.js
wcfsetup/install/files/style/comment.less

index 60aafbaa3cd0d7354edcb6f39692206ac26e35aa..9092c85ed34937c22b514ce974388739408ec18d 100644 (file)
@@ -330,8 +330,8 @@ WCF.Comment.Handler = Class.extend({
                // create UI
                this._commentAdd = $('<li class="box32 jsCommentAdd"><span class="framed">' + this._userAvatar + '</span><div /></li>').prependTo(this._container);
                var $inputContainer = this._commentAdd.children('div');
-               var $input = $('<input type="text" placeholder="' + WCF.Language.get('wcf.comment.add') + '" maxlength="65535" class="long" />').appendTo($inputContainer);
-               $('<small>' + WCF.Language.get('wcf.comment.description') + '</small>').appendTo($inputContainer);
+               var $input = $('<textarea placeholder="' + WCF.Language.get('wcf.comment.add') + '" maxlength="65535" class="long" />').appendTo($inputContainer).flexible();
+               $('<button class="small">' + WCF.Language.get('wcf.global.button.submit') + '</button>').click($.proxy(this._save, this)).appendTo($inputContainer);
                
                $input.keyup($.proxy(this._keyUp, this));
        },
@@ -343,23 +343,14 @@ WCF.Comment.Handler = Class.extend({
         * @param       jQuery          comment
         */
        _initAddResponse: function(commentID, comment) {
-               var $placeholder = null;
-               if (!comment.data('responses') || this._loadNextResponses[commentID]) {
-                       $placeholder = $('<li class="jsCommentShowAddResponse"><a>' + WCF.Language.get('wcf.comment.button.response.add') + '</a></li>').data('commentID', commentID).click($.proxy(this._showAddResponse, this)).appendTo(this._commentButtonList[commentID]);
-               }
+               var $placeholder = $('<li class="jsCommentShowAddResponse"><a>' + WCF.Language.get('wcf.comment.button.response.add') + '</a></li>').data('commentID', commentID).click($.proxy(this._showAddResponse, this)).appendTo(this._commentButtonList[commentID]);
                
-               var $listItem = $('<div class="box32 commentResponseAdd jsCommentResponseAdd"><span class="framed">' + this._userAvatar + '</span><div /></div>');
-               if ($placeholder !== null) {
-                       $listItem.hide();
-               }
-               else {
-                       this._commentButtonList[commentID].parent().addClass('jsAddResponseActive');
-               }
+               var $listItem = $('<div class="box32 commentResponseAdd jsCommentResponseAdd"><span class="framed">' + this._userAvatar + '</span><div /></div>').hide();
                $listItem.appendTo(this._commentButtonList[commentID].parent().show());
                
                var $inputContainer = $listItem.children('div');
-               var $input = $('<input type="text" placeholder="' + WCF.Language.get('wcf.comment.response.add') + '" maxlength="65535" class="long" />').data('commentID', commentID).appendTo($inputContainer);
-               $('<small>' + WCF.Language.get('wcf.comment.description') + '</small>').appendTo($inputContainer);
+               var $input = $('<textarea placeholder="' + WCF.Language.get('wcf.comment.response.add') + '" maxlength="65535" class="long" />').data('commentID', commentID).appendTo($inputContainer).flexible();
+               $('<button class="small">' + WCF.Language.get('wcf.global.button.submit') + '</button>').click($.proxy(this._save, this)).appendTo($inputContainer);
                
                var self = this;
                $input.keyup(function(event) { self._keyUp(event, true); });
@@ -413,7 +404,7 @@ WCF.Comment.Handler = Class.extend({
                $placeholder.remove();
                
                var $responseInput = this._comments[$commentID].data('responseInput').show();
-               $responseInput.find('input').focus();
+               $responseInput.find('textarea').focus();
                
                $responseInput.parents('.commentOptionContainer').addClass('jsAddResponseActive');
        },
@@ -425,19 +416,28 @@ WCF.Comment.Handler = Class.extend({
         * @param       boolean         isResponse
         */
        _keyUp: function(event, isResponse) {
-               // ignore every key except for [Enter] and [Esc]
-               if (event.which !== 13 && event.which !== 27) {
+               if (event.which === $.ui.keyCode.ESCAPE) {
+                       // cancel input
+                       $(event.currentTarget).val('').trigger('blur', event).trigger('updateHeight');
+                       
                        return;
                }
-               
-               var $input = $(event.currentTarget);
-               
-               // cancel input
-               if (event.which === 27) {
-                       $input.val('').trigger('blur', event);
-                       return;
+               else if (event.which === $.ui.keyCode.ENTER && event.ctrlKey) {
+                       this._save(null, isResponse, $(event.currentTarget));
+                       
+                       return false;
                }
-               
+       },
+       
+       /**
+        * Saves entered comment/response.
+        * 
+        * @param       object          event
+        * @param       boolean         isResponse
+        * @param       jQuery          input
+        */
+       _save: function(event, isResponse, input) {
+               var $input = (event === null) ? input : $(event.currentTarget).prev('textarea');
                var $value = $.trim($input.val());
                
                // ignore empty comments
@@ -561,7 +561,7 @@ WCF.Comment.Handler = Class.extend({
                                        this._handleGuestDialogErrors(data.returnValues.errors);
                                }
                                else {
-                                       this._commentAdd.find('input').val('').blur();
+                                       this._commentAdd.find('textarea').val('').blur().trigger('updateHeight');
                                        $(data.returnValues.template).insertAfter(this._commentAdd).wcfFadeIn();
                                        
                                        if (!WCF.User.userID) {
@@ -576,7 +576,7 @@ WCF.Comment.Handler = Class.extend({
                                }
                                else {
                                        var $comment = this._comments[data.returnValues.commentID];
-                                       $comment.find('.jsCommentResponseAdd input').val('').blur();
+                                       $comment.find('.jsCommentResponseAdd textarea').val('').blur().trigger('updateHeight');
                                        
                                        var $responseList = $comment.find('ul.commentResponseList');
                                        if (!$responseList.length) $responseList = $('<ul class="commentResponseList" />').insertBefore($comment.find('.commentOptionContainer'));
index c0122c4b73343ecad083db432f545f4e4ecf8384..5a1fe13c0dd5b04bd06339d31e41e8a34fae8ebb 100755 (executable)
@@ -201,6 +201,17 @@ function shuffle(array) {
  **/
 (function(a){(jQuery.browser=jQuery.browser||{}).mobile=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera);
 
+/**
+ * flexibleArea.js v1.2
+ * A jQuery plugin that dynamically updates textarea's height to fit the content.
+ * http://flaviusmatis.github.com/flexibleArea.js/
+ *
+ * Copyright 2012, Flavius Matis
+ * Released under the MIT license.
+ * http://flaviusmatis.github.com/license.html
+ */
+(function(e){var t={init:function(){var t=["paddingTop","paddingRight","paddingBottom","paddingLeft","fontSize","lineHeight","fontFamily","width","fontWeight","border-top-width","border-right-width","border-bottom-width","border-left-width","-moz-box-sizing","-webkit-box-sizing","box-sizing"];return this.each(function(){function i(){for(var e=0;e<t.length;e++){r.css(t[e],n.css(t[e]))}}function c(){var e=n.val().replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/&/g,"&").replace(/\n/g,"<br/>");r.html(e+"&nbsp;");h()}function h(){var e=r.height();var t="hidden";var i=s?e+a+o:e+a;if(i>l){i=l;t="auto"}else if(i<f){i=f}if(n.height()!==i){n.css({overflow:t,height:i+"px"})}}if(this.type!=="textarea")return false;var n=e(this).css({resize:"none",overflow:"hidden"});var r=e("<div></div>").css({position:"absolute",display:"none","word-wrap":"break-word","white-space":"pre-wrap","border-style":"solid"}).appendTo(document.body);i();var s=n.css("box-sizing")=="border-box"||n.css("-moz-box-sizing")=="border-box"||n.css("-webkit-box-sizing")=="border-box";var o=parseInt(n.css("border-top-width"))+parseInt(n.css("padding-top"))+parseInt(n.css("padding-bottom"))+parseInt(n.css("border-bottom-width"));var u=parseInt(n.css("height"),10);var a=parseInt(n.css("line-height"),10)||parseInt(n.css("font-size"),10);var f=a*2>u?a*2:u;var l=parseInt(n.css("max-height"),10)>-1?parseInt(n.css("max-height"),10):Number.MAX_VALUE;n.bind("keyup change cut paste",function(){c()});e(window).bind("resize",function(){var e=parseInt(n.width(),10);if(r.width()!==e){r.css({width:e+"px"});c()}});n.bind("blur",function(){h()});n.bind("updateHeight",function(){i();c()});e(function(){c()})})}};e.fn.flexible=function(n){if(t[n]){return t[n].apply(this,Array.prototype.slice.call(arguments,1))}else if(typeof n==="object"||!n){return t.init.apply(this,arguments)}else{e.error("Method "+n+" does not exist on jQuery.flexible")}}})(jQuery)
+
 /**
  * Initialize WCF namespace
  */
index d9bd9756a79d334e26c9d11823a1ee4db36ea757..75a1cdd7d0779ea01c717cea5c09af7fda6bea6d 100644 (file)
        opacity: 1;
 }
 
-.commentList input[type='text'] {
-       + small {
-               color: @wcfDimmedColor;
-               opacity: 0;
-               
-               .transition(opacity, .1s);
-       }
+.commentList textarea {
+       /* fixes flicker when expanding */
+       line-height: 1.2em;
+       
+       /* controls textarea grow */
+       min-height: @wcfBaseFontSize;
+       max-height: @wcfBaseFontSize * 10;
        
-       &:focus + small {
-               opacity: 1;
+       + button {
+               margin-top: 3px;
        }
 }