From 899f1b29e729501bea2ac2e3b32927a3220e57f8 Mon Sep 17 00:00:00 2001 From: Alexandre Date: Thu, 2 Oct 2014 13:59:13 -0300 Subject: [PATCH 1/2] Start comments reply (#17), add template for forms, basic styling for replies and tests coverage --- component.json | 1 + css/base.less | 4 +- css/styles.css | 12 ++-- css/themes/default.less | 13 ++++ js/main.js | 9 +++ js/section.js | 61 ++++++++++++++++-- package.json | 8 ++- release/side-comments.css | 12 ++-- release/side-comments.js | 77 ++++++++++++++++++++--- release/side-comments.min.css | 2 +- release/side-comments.min.js | 2 +- release/themes/default-theme.css | 26 ++++---- release/themes/default-theme.min.css | 2 +- support/test_data.js | 19 +++++- templates/comment.html | 24 +++++++- templates/form.html | 13 ++++ templates/section.html | 19 +----- test/test_main.js | 92 ++++++++++++++++++++++------ 18 files changed, 314 insertions(+), 82 deletions(-) create mode 100644 templates/form.html diff --git a/component.json b/component.json index 745fb83..22afac3 100644 --- a/component.json +++ b/component.json @@ -13,6 +13,7 @@ "main": "js/main.js", "templates": [ "templates/section.html", + "templates/form.html", "templates/comment.html" ] } \ No newline at end of file diff --git a/css/base.less b/css/base.less index c9df53e..60ff2a0 100644 --- a/css/base.less +++ b/css/base.less @@ -66,7 +66,7 @@ display: none; } - .comment-form { + .comment-form, .reply-form { display: none; } @@ -104,7 +104,7 @@ display: block; } - .comment-form { + .comment-form, .reply-form { overflow: hidden; &.active { diff --git a/css/styles.css b/css/styles.css index 12ec298..f70cc4e 100644 --- a/css/styles.css +++ b/css/styles.css @@ -29,9 +29,8 @@ height: 100%; } .side-comment * { - -webkit-box-sizing: border-box; -moz-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; } .side-comment .hide { display: none; @@ -70,7 +69,8 @@ .side-comment.has-comments .add-comment.hide { display: none; } -.side-comment.has-comments .comment-form { +.side-comment.has-comments .comment-form, +.side-comment.has-comments .reply-form { display: none; } .side-comment .comments-wrapper { @@ -102,10 +102,12 @@ .side-comment .add-comment.active { display: block; } -.side-comment .comment-form { +.side-comment .comment-form, +.side-comment .reply-form { overflow: hidden; } -.side-comment .comment-form.active { +.side-comment .comment-form.active, +.side-comment .reply-form.active { display: block; } .side-comment.active .comments-wrapper { diff --git a/css/themes/default.less b/css/themes/default.less index 16b86ff..cc61468 100644 --- a/css/themes/default.less +++ b/css/themes/default.less @@ -85,6 +85,12 @@ margin-top: -1px; } + .reply-form { + &:extend(.comment-form); + padding-left: 42px; + padding-top: 10px; + } + .comment, .comment-box { font-size: 14px; line-height: 18px; @@ -211,6 +217,13 @@ padding: 0 5px; } } + + .replies { + + .author-name { + width: @comments-wrapper-width - ( (@avatar-width + 10) * 2); + } + } } @comments-wrapper-width: 200px; diff --git a/js/main.js b/js/main.js index e89af26..b32f21d 100644 --- a/js/main.js +++ b/js/main.js @@ -129,6 +129,15 @@ SideComments.prototype.insertComment = function( comment ) { section.insertComment(comment); }; +/** + * Inserts the given comment into the right section as a reply. + * @param {Object} comment A comment to be inserted. + */ +SideComments.prototype.replyComment = function( comment ) { + var section = _.find(this.sections, { id: comment.sectionId}); + section.insertComment(comment); +}; + /** * Removes the given comment from the right section. * @param sectionId The ID of the section where the comment exists. diff --git a/js/section.js b/js/section.js index bb19a1a..682d3bd 100644 --- a/js/section.js +++ b/js/section.js @@ -1,6 +1,7 @@ var _ = require('./vendor/lodash-custom.js'); var Template = require('../templates/section.html'); var CommentTemplate = require('../templates/comment.html'); +var FormTemplate = require('../templates/form.html'); var mobileCheck = require('./helpers/mobile-check.js'); var $ = jQuery; @@ -21,6 +22,7 @@ function Section( eventPipe, $el, currentUser, comments ) { this.$el.on(this.clickEventName, '.side-comment .marker', _.bind(this.markerClick, this)); this.$el.on(this.clickEventName, '.side-comment .add-comment', _.bind(this.addCommentClick, this)); + this.$el.on(this.clickEventName, '.side-comment .reply-comment', _.bind(this.replyCommentClick, this)); this.$el.on(this.clickEventName, '.side-comment .post', _.bind(this.postCommentClick, this)); this.$el.on(this.clickEventName, '.side-comment .cancel', _.bind(this.cancelCommentClick, this)); this.$el.on(this.clickEventName, '.side-comment .delete', _.bind(this.deleteCommentClick, this)); @@ -54,6 +56,7 @@ Section.prototype.addCommentClick = function( event ) { */ Section.prototype.showCommentForm = function() { if (this.comments.length > 0) { + this.hideCommentForm(); this.$el.find('.add-comment').addClass('hide'); this.$el.find('.comment-form').addClass('active'); } @@ -61,13 +64,40 @@ Section.prototype.showCommentForm = function() { this.focusCommentBox(); }; +/** + * Callback for the reply button click event. + * @param {Object} event The event object. + */ +Section.prototype.replyCommentClick = function( event ) { + event.preventDefault(); + if (this.currentUser) { + this.showReplyForm(event.currentTarget); + } else { + this.eventPipe.emit('addCommentAttempted'); + } +}; + +/** + * Show the reply form for this section. + */ +Section.prototype.showReplyForm = function( replyButton ) { + if (this.comments.length > 0) { + this.hideCommentForm(); + this.$el.find(replyButton).addClass('hide'); + $form = $(_.find($.makeArray(this.$el.find('.reply-form')), function (el) {return el.dataset.parent === replyButton.dataset.comment})); + $form.addClass('active'); + } + + this.focusCommentBox(); +}; + /** * Hides the comment form for this section. */ Section.prototype.hideCommentForm = function() { if (this.comments.length > 0) { - this.$el.find('.add-comment').removeClass('hide'); - this.$el.find('.comment-form').removeClass('active'); + this.$el.find('a[class*="-comment"]').removeClass('hide'); + this.$el.find('div[class*="-form"]').removeClass('active'); } this.$el.find('.comment-box').empty(); @@ -119,8 +149,10 @@ Section.prototype.postCommentClick = function( event ) { * Post a comment to this section. */ Section.prototype.postComment = function() { - var $commentBox = this.$el.find('.comment-box'); + var $commentForm = this.$el.find('div[class*="-form"].active'); + var $commentBox = $commentForm.find('.comment-box'); var commentBody = $commentBox.val(); + var comment = { sectionId: this.id, comment: commentBody, @@ -129,6 +161,11 @@ Section.prototype.postComment = function() { authorId: this.currentUser.id, authorUrl: this.currentUser.authorUrl || null }; + + if ( Number($commentForm.data('parent')) ) { + comment.parentId = Number($commentForm.data('parent')); + } + $commentBox.val(''); // Clear the comment. this.eventPipe.emit('commentPosted', comment); }; @@ -138,12 +175,23 @@ Section.prototype.postComment = function() { * @param {Object} comment A comment object. */ Section.prototype.insertComment = function( comment ) { - this.comments.push(comment); + var newCommentHtml = _.template(CommentTemplate, { comment: comment, - currentUser: this.currentUser + currentUser: this.currentUser, + formTemplate: FormTemplate, + self: CommentTemplate }); - this.$el.find('.comments').append(newCommentHtml); + + if ( comment.parentId !== undefined ) { + _.find(this.comments, { id: comment.parentId }).replies.push(comment); + $parent = $(_.find($.makeArray(this.$el.find('.comments > li')), function ( el ) { return el.dataset.commentId == comment.parentId })); + $parent.find('.replies').append(newCommentHtml); + } else { + this.comments.push(comment); + this.$el.find('.comments').append(newCommentHtml); + } + this.$el.find('.side-comment').addClass('has-comments'); this.updateCommentCount(); this.hideCommentForm(); @@ -247,6 +295,7 @@ Section.prototype.render = function() { commentTemplate: CommentTemplate, comments: this.comments, sectionClasses: this.sectionClasses(), + formTemplate: FormTemplate, currentUser: this.currentUser })).appendTo(this.$el); }; diff --git a/package.json b/package.json index a2413c3..4ef3ab6 100644 --- a/package.json +++ b/package.json @@ -10,5 +10,11 @@ "gulp-less": "*", "gulp-autoprefixer": "*", "gulp-rename": "*" + }, + "devDependencies": { + "gulp": "~3.8.8", + "bower": "~1.3.12", + "chai": "~1.9.2", + "mocha": "~1.21.4" } -} \ No newline at end of file +} diff --git a/release/side-comments.css b/release/side-comments.css index 12ec298..f70cc4e 100644 --- a/release/side-comments.css +++ b/release/side-comments.css @@ -29,9 +29,8 @@ height: 100%; } .side-comment * { - -webkit-box-sizing: border-box; -moz-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; } .side-comment .hide { display: none; @@ -70,7 +69,8 @@ .side-comment.has-comments .add-comment.hide { display: none; } -.side-comment.has-comments .comment-form { +.side-comment.has-comments .comment-form, +.side-comment.has-comments .reply-form { display: none; } .side-comment .comments-wrapper { @@ -102,10 +102,12 @@ .side-comment .add-comment.active { display: block; } -.side-comment .comment-form { +.side-comment .comment-form, +.side-comment .reply-form { overflow: hidden; } -.side-comment .comment-form.active { +.side-comment .comment-form.active, +.side-comment .reply-form.active { display: block; } .side-comment.active .comments-wrapper { diff --git a/release/side-comments.js b/release/side-comments.js index a189078..5e38a15 100644 --- a/release/side-comments.js +++ b/release/side-comments.js @@ -498,6 +498,15 @@ SideComments.prototype.insertComment = function( comment ) { section.insertComment(comment); }; +/** + * Inserts the given comment into the right section as a reply. + * @param {Object} comment A comment to be inserted. + */ +SideComments.prototype.replyComment = function( comment ) { + var section = _.find(this.sections, { id: comment.sectionId}); + section.insertComment(comment); +}; + /** * Removes the given comment from the right section. * @param sectionId The ID of the section where the comment exists. @@ -579,6 +588,7 @@ require.register("side-comments/js/section.js", function(exports, require, modul var _ = require('./vendor/lodash-custom.js'); var Template = require('../templates/section.html'); var CommentTemplate = require('../templates/comment.html'); +var FormTemplate = require('../templates/form.html'); var mobileCheck = require('./helpers/mobile-check.js'); var $ = jQuery; @@ -599,6 +609,7 @@ function Section( eventPipe, $el, currentUser, comments ) { this.$el.on(this.clickEventName, '.side-comment .marker', _.bind(this.markerClick, this)); this.$el.on(this.clickEventName, '.side-comment .add-comment', _.bind(this.addCommentClick, this)); + this.$el.on(this.clickEventName, '.side-comment .reply-comment', _.bind(this.replyCommentClick, this)); this.$el.on(this.clickEventName, '.side-comment .post', _.bind(this.postCommentClick, this)); this.$el.on(this.clickEventName, '.side-comment .cancel', _.bind(this.cancelCommentClick, this)); this.$el.on(this.clickEventName, '.side-comment .delete', _.bind(this.deleteCommentClick, this)); @@ -632,6 +643,7 @@ Section.prototype.addCommentClick = function( event ) { */ Section.prototype.showCommentForm = function() { if (this.comments.length > 0) { + this.hideCommentForm(); this.$el.find('.add-comment').addClass('hide'); this.$el.find('.comment-form').addClass('active'); } @@ -639,13 +651,40 @@ Section.prototype.showCommentForm = function() { this.focusCommentBox(); }; +/** + * Callback for the reply button click event. + * @param {Object} event The event object. + */ +Section.prototype.replyCommentClick = function( event ) { + event.preventDefault(); + if (this.currentUser) { + this.showReplyForm(event.currentTarget); + } else { + this.eventPipe.emit('addCommentAttempted'); + } +}; + +/** + * Show the reply form for this section. + */ +Section.prototype.showReplyForm = function( replyButton ) { + if (this.comments.length > 0) { + this.hideCommentForm(); + this.$el.find(replyButton).addClass('hide'); + $form = $(_.find($.makeArray(this.$el.find('.reply-form')), function (el) {return el.dataset.parent === replyButton.dataset.comment})); + $form.addClass('active'); + } + + this.focusCommentBox(); +}; + /** * Hides the comment form for this section. */ Section.prototype.hideCommentForm = function() { if (this.comments.length > 0) { - this.$el.find('.add-comment').removeClass('hide'); - this.$el.find('.comment-form').removeClass('active'); + this.$el.find('a[class*="-comment"]').removeClass('hide'); + this.$el.find('div[class*="-form"]').removeClass('active'); } this.$el.find('.comment-box').empty(); @@ -697,8 +736,10 @@ Section.prototype.postCommentClick = function( event ) { * Post a comment to this section. */ Section.prototype.postComment = function() { - var $commentBox = this.$el.find('.comment-box'); + var $commentForm = this.$el.find('div[class*="-form"].active'); + var $commentBox = $commentForm.find('.comment-box'); var commentBody = $commentBox.val(); + var comment = { sectionId: this.id, comment: commentBody, @@ -707,6 +748,11 @@ Section.prototype.postComment = function() { authorId: this.currentUser.id, authorUrl: this.currentUser.authorUrl || null }; + + if ( Number($commentForm.data('parent')) ) { + comment.parentId = Number($commentForm.data('parent')); + } + $commentBox.val(''); // Clear the comment. this.eventPipe.emit('commentPosted', comment); }; @@ -716,12 +762,23 @@ Section.prototype.postComment = function() { * @param {Object} comment A comment object. */ Section.prototype.insertComment = function( comment ) { - this.comments.push(comment); + var newCommentHtml = _.template(CommentTemplate, { comment: comment, - currentUser: this.currentUser + currentUser: this.currentUser, + formTemplate: FormTemplate, + self: CommentTemplate }); - this.$el.find('.comments').append(newCommentHtml); + + if ( comment.parentId !== undefined ) { + _.find(this.comments, { id: comment.parentId }).replies.push(comment); + $parent = $(_.find($.makeArray(this.$el.find('.comments > li')), function ( el ) { return el.dataset.commentId == comment.parentId })); + $parent.find('.replies').append(newCommentHtml); + } else { + this.comments.push(comment); + this.$el.find('.comments').append(newCommentHtml); + } + this.$el.find('.side-comment').addClass('has-comments'); this.updateCommentCount(); this.hideCommentForm(); @@ -825,6 +882,7 @@ Section.prototype.render = function() { commentTemplate: CommentTemplate, comments: this.comments, sectionClasses: this.sectionClasses(), + formTemplate: FormTemplate, currentUser: this.currentUser })).appendTo(this.$el); }; @@ -3240,10 +3298,13 @@ module.exports = function() { }); require.register("side-comments/templates/section.html", function(exports, require, module){ -module.exports = '
\n \n <%= comments.length %>\n \n \n
\n
    \n <% _.each(comments, function( comment ){ %>\n <%= _.template(commentTemplate, { comment: comment, currentUser: currentUser }) %>\n <% }) %>\n
\n \n Leave a comment\n \n <% if (currentUser){ %>\n
\n
\n \n
\n

\n <%= currentUser.name %>\n

\n \n
\n Post\n Cancel\n
\n
\n <% } %>\n
\n
'; +module.exports = '
\n \n <%= comments.length %>\n \n \n
\n
    \n <% _.each(comments, function( comment ){ %>\n <%= _.template(commentTemplate, { comment: comment, currentUser: currentUser, formTemplate: formTemplate, self: commentTemplate }) %>\n <% }) %>\n
\n \n Leave a comment\n <% if (currentUser) { %>\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'comment-form\', commentId: null }) %>\n <% } %>\n
\n
'; +}); +require.register("side-comments/templates/form.html", function(exports, require, module){ +module.exports = '
\n
\n \n
\n

\n <%= currentUser.name %>\n

\n \n
\n Post\n Cancel\n
\n
'; }); require.register("side-comments/templates/comment.html", function(exports, require, module){ -module.exports = '
  • \n
    \n \n
    \n <% if (comment.authorUrl) { %>\n \n <%= comment.authorName %>\n \n <% } else { %>\n

    \n <%= comment.authorName %>\n

    \n <% } %>\n

    \n <%= comment.comment %>\n

    \n <% if (currentUser && comment.authorId === currentUser.id){ %>\n Delete\n <% } %>\n
  • '; +module.exports = '
  • \n
    \n \n
    \n <% if (comment.authorUrl) { %>\n \n <%= comment.authorName %>\n \n <% } else { %>\n

    \n <%= comment.authorName %>\n

    \n <% } %>\n

    \n <%= comment.comment %>\n

    \n\n <% if ( comment.parentId === undefined ) { %>\n \n \n\n <% if (currentUser){ %>\n Reply\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'reply-form\', commentId: comment.id })%>\n <% if (comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n <% } %>\n\n <% } %>\n\n <% if (currentUser && comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n\n
  • '; }); require.alias("component-emitter/index.js", "side-comments/deps/emitter/index.js"); require.alias("component-emitter/index.js", "emitter/index.js"); diff --git a/release/side-comments.min.css b/release/side-comments.min.css index fdd6ce1..80b006b 100644 --- a/release/side-comments.min.css +++ b/release/side-comments.min.css @@ -1 +1 @@ -@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@keyframes fadein{from{opacity:0}to{opacity:1}}.commentable-section{position:relative}.commentable-section:hover .side-comment .marker{display:block}.side-comment{position:absolute;top:0;right:0;width:20px;min-height:100%;height:100%}.side-comment *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.side-comment .hide{display:none}.side-comment .marker{display:none;position:absolute;top:0;right:0;cursor:pointer}.side-comment .marker span{display:none}.side-comment.active .marker,.side-comment.has-comments .marker,.side-comment.has-comments ul.comments{display:block}.side-comment .add-comment{display:none}.side-comment.has-comments .add-comment,.side-comment.no-current-user .add-comment{display:block}.side-comment.no-current-user .add-comment{margin-top:20px}.side-comment.has-comments .marker:before{content:""}.side-comment.has-comments .marker span{display:block}.side-comment.has-comments .add-comment.hide,.side-comment.has-comments .comment-form{display:none}.side-comment .comments-wrapper{display:none;position:absolute;top:0;left:40px}.side-comment .comments{list-style:none;padding:0;margin:0;display:none;width:100%}.side-comment .comments li{width:100%;overflow:hidden}.side-comment .actions,.side-comment .comment,.side-comment .comment-box{margin:0}.side-comment .actions,.side-comment .delete{margin-left:42px}.side-comment .add-comment.active{display:block}.side-comment .comment-form{overflow:hidden}.side-comment .comment-form.active,.side-comment.active .comments-wrapper{display:block}@media (max-width:768px){body{-webkit-overflow-scrolling:touch;overflow-x:hidden}} \ No newline at end of file +@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@keyframes fadein{from{opacity:0}to{opacity:1}}.commentable-section{position:relative}.commentable-section:hover .side-comment .marker{display:block}.side-comment{position:absolute;top:0;right:0;width:20px;min-height:100%;height:100%}.side-comment *{-moz-box-sizing:border-box;box-sizing:border-box}.side-comment .hide{display:none}.side-comment .marker{display:none;position:absolute;top:0;right:0;cursor:pointer}.side-comment .marker span{display:none}.side-comment.active .marker,.side-comment.has-comments .marker,.side-comment.has-comments ul.comments{display:block}.side-comment .add-comment{display:none}.side-comment.has-comments .add-comment,.side-comment.no-current-user .add-comment{display:block}.side-comment.no-current-user .add-comment{margin-top:20px}.side-comment.has-comments .marker:before{content:""}.side-comment.has-comments .marker span{display:block}.side-comment.has-comments .add-comment.hide,.side-comment.has-comments .comment-form,.side-comment.has-comments .reply-form{display:none}.side-comment .comments-wrapper{display:none;position:absolute;top:0;left:40px}.side-comment .comments{list-style:none;padding:0;margin:0;display:none;width:100%}.side-comment .comments li{width:100%;overflow:hidden}.side-comment .actions,.side-comment .comment,.side-comment .comment-box{margin:0}.side-comment .actions,.side-comment .delete{margin-left:42px}.side-comment .add-comment.active{display:block}.side-comment .comment-form,.side-comment .reply-form{overflow:hidden}.side-comment .comment-form.active,.side-comment .reply-form.active,.side-comment.active .comments-wrapper{display:block}@media (max-width:768px){body{-webkit-overflow-scrolling:touch;overflow-x:hidden}} \ No newline at end of file diff --git a/release/side-comments.min.js b/release/side-comments.min.js index 1ad1231..773a96a 100644 --- a/release/side-comments.min.js +++ b/release/side-comments.min.js @@ -1 +1 @@ -function require(e,t,n){var r=require.resolve(e);if(null==r){n=n||e,t=t||"root";var o=new Error('Failed to require "'+n+'" from "'+t+'"');throw o.path=n,o.parent=t,o.require=!0,o}var i=require.modules[r];if(!i._resolving&&!i.exports){var s={};s.exports={},s.client=s.component=!0,i._resolving=!0,i.call(this,s.exports,require.relative(r),s),delete i._resolving,i.exports=s.exports}return i.exports}require.modules={},require.aliases={},require.resolve=function(e){"/"===e.charAt(0)&&(e=e.slice(1));for(var t=[e,e+".js",e+".json",e+"/index.js",e+"/index.json"],n=0;nr;++r)n[r].apply(this,t)}return this},r.prototype.listeners=function(e){return this._callbacks=this._callbacks||{},this._callbacks[e]||[]},r.prototype.hasListeners=function(e){return!!this.listeners(e).length}}),require.register("side-comments/js/main.js",function(e,t,n){function r(e,t,n){this.$el=a(e),this.$body=a("body"),this.eventPipe=new s,this.currentUser=o.clone(t)||null,this.existingComments=o.cloneDeep(n)||[],this.sections=[],this.activeSection=null,this.eventPipe.on("showComments",o.bind(this.showComments,this)),this.eventPipe.on("hideComments",o.bind(this.hideComments,this)),this.eventPipe.on("sectionSelected",o.bind(this.sectionSelected,this)),this.eventPipe.on("sectionDeselected",o.bind(this.sectionDeselected,this)),this.eventPipe.on("commentPosted",o.bind(this.commentPosted,this)),this.eventPipe.on("commentDeleted",o.bind(this.commentDeleted,this)),this.eventPipe.on("addCommentAttempted",o.bind(this.addCommentAttempted,this)),this.$body.on("click",o.bind(this.bodyClick,this)),this.initialize(this.existingComments)}var o=t("./vendor/lodash-custom.js"),i=t("./section.js"),s=t("emitter"),a=jQuery;s(r.prototype),r.prototype.initialize=function(){o.each(this.$el.find(".commentable-section"),function(e){var t=a(e),n=t.data("section-id").toString(),r=o.find(this.existingComments,{sectionId:n});this.sections.push(new i(this.eventPipe,t,this.currentUser,r))},this)},r.prototype.showComments=function(){this.$el.addClass("side-comments-open")},r.prototype.hideComments=function(){this.activeSection&&(this.activeSection.deselect(),this.activeSection=null),this.$el.removeClass("side-comments-open")},r.prototype.sectionSelected=function(e){this.showComments(),this.activeSection&&this.activeSection.deselect(),this.activeSection=e},r.prototype.sectionDeselected=function(){this.hideComments(),this.activeSection=null},r.prototype.commentPosted=function(e){this.emit("commentPosted",e)},r.prototype.commentDeleted=function(e){this.emit("commentDeleted",e)},r.prototype.addCommentAttempted=function(){this.emit("addCommentAttempted")},r.prototype.insertComment=function(e){var t=o.find(this.sections,{id:e.sectionId});t.insertComment(e)},r.prototype.removeComment=function(e,t){var n=o.find(this.sections,{id:e});n.removeComment(t)},r.prototype.deleteComment=function(e,t){var n=o.find(this.sections,{id:e});n.deleteComment(t)},r.prototype.commentsAreVisible=function(){return this.$el.hasClass("side-comments-open")},r.prototype.bodyClick=function(e){var t=a(e.target);t.closest(".side-comment").length<1&&t.closest("body").length>0&&(this.activeSection&&this.activeSection.deselect(),this.hideComments())},r.prototype.setCurrentUser=function(e){this.hideComments(),this.currentUser=e,o.each(this.sections,o.bind(function(e){e.currentUser=this.currentUser,e.render()},this))},r.prototype.removeCurrentUser=function(){this.setCurrentUser(null)},r.prototype.destroy=function(){this.hideComments(),this.$el.off()},n.exports=r}),require.register("side-comments/js/section.js",function(e,t,n){function r(e,t,n,r){this.eventPipe=e,this.$el=t,this.comments=r?r.comments:[],this.currentUser=n||null,this.clickEventName=a()?"touchstart":"click",this.id=t.data("section-id"),this.$el.on(this.clickEventName,".side-comment .marker",o.bind(this.markerClick,this)),this.$el.on(this.clickEventName,".side-comment .add-comment",o.bind(this.addCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .post",o.bind(this.postCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .cancel",o.bind(this.cancelCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .delete",o.bind(this.deleteCommentClick,this)),this.render()}var o=t("./vendor/lodash-custom.js"),i=t("../templates/section.html"),s=t("../templates/comment.html"),a=t("./helpers/mobile-check.js"),c=jQuery;r.prototype.markerClick=function(e){e.preventDefault(),this.select()},r.prototype.addCommentClick=function(e){e.preventDefault(),this.currentUser?this.showCommentForm():this.eventPipe.emit("addCommentAttempted")},r.prototype.showCommentForm=function(){this.comments.length>0&&(this.$el.find(".add-comment").addClass("hide"),this.$el.find(".comment-form").addClass("active")),this.focusCommentBox()},r.prototype.hideCommentForm=function(){this.comments.length>0&&(this.$el.find(".add-comment").removeClass("hide"),this.$el.find(".comment-form").removeClass("active")),this.$el.find(".comment-box").empty()},r.prototype.focusCommentBox=function(){setTimeout(o.bind(function(){this.$el.find(".comment-box").get(0).focus()},this),300)},r.prototype.cancelCommentClick=function(e){e.preventDefault(),this.cancelComment()},r.prototype.cancelComment=function(){this.comments.length>0?this.hideCommentForm():(this.deselect(),this.eventPipe.emit("hideComments"))},r.prototype.postCommentClick=function(e){e.preventDefault(),this.postComment()},r.prototype.postComment=function(){var e=this.$el.find(".comment-box"),t=e.val(),n={sectionId:this.id,comment:t,authorAvatarUrl:this.currentUser.avatarUrl,authorName:this.currentUser.name,authorId:this.currentUser.id,authorUrl:this.currentUser.authorUrl||null};e.val(""),this.eventPipe.emit("commentPosted",n)},r.prototype.insertComment=function(e){this.comments.push(e);var t=o.template(s,{comment:e,currentUser:this.currentUser});this.$el.find(".comments").append(t),this.$el.find(".side-comment").addClass("has-comments"),this.updateCommentCount(),this.hideCommentForm()},r.prototype.updateCommentCount=function(){this.$el.find(".marker span").text(this.comments.length)},r.prototype.deleteCommentClick=function(e){e.preventDefault();var t=c(e.target).closest("li").data("comment-id");window.confirm("Are you sure you want to delete this comment?")&&this.deleteComment(t)},r.prototype.deleteComment=function(e){var t=o.find(this.comments,{id:e});t.sectionId=this.id,this.eventPipe.emit("commentDeleted",t)},r.prototype.removeComment=function(e){this.comments=o.reject(this.comments,{id:e}),this.$el.find('.side-comment .comments li[data-comment-id="'+e+'"]').remove(),this.updateCommentCount(),this.comments.length<1&&this.$el.find(".side-comment").removeClass("has-comments")},r.prototype.select=function(){this.isSelected()?(this.deselect(),this.eventPipe.emit("sectionDeselected",this)):(this.$el.find(".side-comment").addClass("active"),0===this.comments.length&&this.currentUser&&this.focusCommentBox(),this.eventPipe.emit("sectionSelected",this))},r.prototype.deselect=function(){this.$el.find(".side-comment").removeClass("active"),this.hideCommentForm()},r.prototype.isSelected=function(){return this.$el.find(".side-comment").hasClass("active")},r.prototype.sectionClasses=function(){var e="";return this.comments.length>0&&(e+=" has-comments"),this.currentUser||(e+=" no-current-user"),e},r.prototype.render=function(){this.$el.find(".side-comment").remove(),c(o.template(i,{commentTemplate:s,comments:this.comments,sectionClasses:this.sectionClasses(),currentUser:this.currentUser})).appendTo(this.$el)},r.prototype.destroy=function(){this.$el.off()},n.exports=r}),require.register("side-comments/js/vendor/lodash-custom.js",function(e,t,n){(function(){function t(e){return"\\"+ht[e]}function r(){return z.pop()||[]}function o(e){return"function"!=typeof e.toString&&"string"==typeof(e+"")}function i(e){e.length=0,z.lengtho?0:o);++r-1:void 0});return a.pop(),c.pop(),k&&(i(a),i(c)),l}function f(e,t,n,r,o,i){var a=1&t,l=2&t,u=4&t,m=16&t,h=32&t;if(!l&&!x(e))throw new TypeError;m&&!n.length&&(t&=-17,m=n=!1),h&&!r.length&&(t&=-33,h=r=!1);var d=e&&e.__bindData__;if(d&&d!==!0)return d=s(d),d[2]&&(d[2]=s(d[2])),d[3]&&(d[3]=s(d[3])),!a||1&d[1]||(d[4]=o),!a&&1&d[1]&&(t|=8),!u||4&d[1]||(d[5]=i),m&&St.apply(d[2]||(d[2]=[]),n),h&&Et.apply(d[3]||(d[3]=[]),r),d[1]|=t,f.apply(null,d);var g=1==t||17===t?c:p;return g([e,t,n,r,o,i])}function d(){mt.shadowedProps=X,mt.array=mt.bottom=mt.loop=mt.top="",mt.init="iterable",mt.useHas=!0;for(var e,t=0;e=arguments[t];t++)for(var n in e)mt[n]=e[n];var r=mt.args;mt.firstArg=/^[^,]+/.exec(r)[0];var o=Function("baseCreateCallback, errorClass, errorProto, hasOwnProperty, indicatorObject, isArguments, isArray, isString, keys, objectProto, objectTypes, nonEnumProps, stringClass, stringProto, toString","return function("+r+") {\n"+Nt(mt)+"\n}");return o(m,rt,Ct,Pt,F,b,Ft,_,mt.keys,kt,pt,Lt,ct,xt,wt)}function g(e){return Vt[e]}function v(e){return"function"==typeof e&&_t.test(e)}function b(e){return e&&"object"==typeof e&&"number"==typeof e.length&&wt.call(e)==Z||!1}function y(e,t,n,r){return"boolean"!=typeof t&&null!=t&&(r=n,n=t,t=!1),l(e,t,"function"==typeof n&&m(n,r,1))}function C(e,t,n){return l(e,!0,"function"==typeof t&&m(t,n,1))}function x(e){return"function"==typeof e}function w(e){return!(!e||!pt[typeof e])}function _(e){return"string"==typeof e||e&&"object"==typeof e&&wt.call(e)==ct||!1}function j(e){for(var t=-1,n=Rt(e),r=n.length,o=Array(r);++t2?f(e,17,s(arguments,2),null,t):f(e,1,null,null,t)}function A(e,t,n){var r=typeof e;if(null==e||"function"==r)return m(e,t,n);if("object"!=r)return L(e);var o=Rt(e),i=o[0],s=e[i];return 1!=o.length||s!==s||w(s)?function(t){for(var n=o.length,r=!1;n--&&(r=h(t[o[n]],e[o[n]],null,!0)););return r}:function(e){var t=e[i];return s===t&&(0!==s||1/s==1/t)}}function U(e){return null==e?"":String(e).replace(Wt,g)}function O(e){return e}function D(){}function L(e){return function(t){return t[e]}}function I(e,n,r){var o=a.templateSettings;e=String(e||""),r=Kt({},r,o);var i,s=Kt({},r.imports,o.imports),c=Rt(s),l=j(s),u=0,m=r.interpolate||J,p="__p += '",h=RegExp((r.escape||J).source+"|"+m.source+"|"+(m===G?Q:J).source+"|"+(r.evaluate||J).source+"|$","g");e.replace(h,function(n,r,o,s,a,c){return o||(o=s),p+=e.slice(u,c).replace(M,t),r&&(p+="' +\n__e("+r+") +\n'"),a&&(i=!0,p+="';\n"+a+";\n__p += '"),o&&(p+="' +\n((__t = ("+o+")) == null ? '' : __t) +\n'"),u=c+n.length,n}),p+="';\n";var f=r.variable,d=f;d||(f="obj",p="with ("+f+") {\n"+p+"\n}\n"),p=(i?p.replace(R,""):p).replace(H,"$1").replace(B,"$1;"),p="function("+f+") {\n"+(d?"":f+" || ("+f+" = {});\n")+"var __t, __p = '', __e = _.escape"+(i?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+p+"return __p\n}";var g="\n/*\n//# sourceURL="+(r.sourceURL||"/lodash/template/source["+Y++ +"]")+"\n*/";try{var v=Function(c,"return "+p+g).apply(N,l)}catch(b){throw b.source=p,b}return n?v(n):(v.source=p,v)}var N,z=[],F={},T=40,R=/\b__p \+= '';/g,H=/\b(__p \+=) '' \+/g,B=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Q=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,V=/\w*$/,W=/^\s*function[ \n\r\t]+\w/,G=/<%=([\s\S]+?)%>/g,J=/($^)/,K=/\bthis\b/,M=/['\n\r\t\u2028\u2029\\]/g,X=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Y=0,Z="[object Arguments]",et="[object Array]",tt="[object Boolean]",nt="[object Date]",rt="[object Error]",ot="[object Function]",it="[object Number]",st="[object Object]",at="[object RegExp]",ct="[object String]",lt={};lt[ot]=!1,lt[Z]=lt[et]=lt[tt]=lt[nt]=lt[it]=lt[st]=lt[at]=lt[ct]=!0;var ut={configurable:!1,enumerable:!1,value:null,writable:!1},mt={args:"",array:null,bottom:"",firstArg:"",init:"",keys:null,loop:"",shadowedProps:null,support:null,top:"",useHas:!1},pt={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},ht={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},ft=pt[typeof window]&&window||this,dt=pt[typeof e]&&e&&!e.nodeType&&e,gt=pt[typeof n]&&n&&!n.nodeType&&n,vt=gt&>.exports===dt&&dt,bt=pt[typeof global]&&global;!bt||bt.global!==bt&&bt.window!==bt||(ft=bt);var yt=[],Ct=Error.prototype,kt=Object.prototype,xt=String.prototype,wt=kt.toString,_t=RegExp("^"+String(wt).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),jt=Function.prototype.toString,Pt=kt.hasOwnProperty,St=yt.push,$t=kt.propertyIsEnumerable,Et=yt.unshift,qt=function(){try{var e={},t=v(t=Object.defineProperty)&&t,n=t(e,e,e)&&t}catch(r){}return n}(),At=v(At=Object.create)&&At,Ut=v(Ut=Array.isArray)&&Ut,Ot=v(Ot=Object.keys)&&Ot,Dt={};Dt[et]=Array,Dt[tt]=Boolean,Dt[nt]=Date,Dt[ot]=Function,Dt[st]=Object,Dt[it]=Number,Dt[at]=RegExp,Dt[ct]=String;var Lt={};Lt[et]=Lt[nt]=Lt[it]={constructor:!0,toLocaleString:!0,toString:!0,valueOf:!0},Lt[tt]=Lt[ct]={constructor:!0,toString:!0,valueOf:!0},Lt[rt]=Lt[ot]=Lt[at]={constructor:!0,toString:!0},Lt[st]={constructor:!0},function(){for(var e=X.length;e--;){var t=X[e];for(var n in Lt)Pt.call(Lt,n)&&!Pt.call(Lt[n],t)&&(Lt[n][t]=!1)}}();var It=a.support={};!function(){var e=function(){this.x=1},t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments);It.argsClass=wt.call(arguments)==Z,It.argsObject=arguments.constructor==Object&&!(arguments instanceof Array),It.enumErrorProps=$t.call(Ct,"message")||$t.call(Ct,"name"),It.enumPrototypes=$t.call(e,"prototype"),It.funcDecomp=!v(ft.WinRTError)&&K.test(function(){return this}),It.funcNames="string"==typeof Function.name,It.nonEnumArgs=0!=r,It.nonEnumShadows=!/valueOf/.test(n),It.spliceObjects=(yt.splice.call(t,0,1),!t[0]),It.unindexedChars="x"[0]+Object("x")[0]!="xx";try{It.nodeClass=!(wt.call(document)==st&&!({toString:0}+""))}catch(o){It.nodeClass=!0}}(1),a.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:G,variable:"",imports:{_:a}};var Nt=function(e){var t="var index, iterable = "+e.firstArg+", result = "+e.init+";\nif (!iterable) return result;\n"+e.top+";";e.array?(t+="\nvar length = iterable.length; index = -1;\nif ("+e.array+") { ",It.unindexedChars&&(t+="\n if (isString(iterable)) {\n iterable = iterable.split('')\n } "),t+="\n while (++index < length) {\n "+e.loop+";\n }\n}\nelse { "):It.nonEnumArgs&&(t+="\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += '';\n "+e.loop+";\n }\n } else { "),It.enumPrototypes&&(t+="\n var skipProto = typeof iterable == 'function';\n "),It.enumErrorProps&&(t+="\n var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n ");var n=[];if(It.enumPrototypes&&n.push('!(skipProto && index == "prototype")'),It.enumErrorProps&&n.push('!(skipErrorProps && (index == "message" || index == "name"))'),e.useHas&&e.keys)t+="\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] && keys(iterable),\n length = ownProps ? ownProps.length : 0;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n",n.length&&(t+=" if ("+n.join(" && ")+") {\n "),t+=e.loop+"; ",n.length&&(t+="\n }"),t+="\n } ";else if(t+="\n for (index in iterable) {\n",e.useHas&&n.push("hasOwnProperty.call(iterable, index)"),n.length&&(t+=" if ("+n.join(" && ")+") {\n "),t+=e.loop+"; ",n.length&&(t+="\n }"),t+="\n } ",It.nonEnumShadows){for(t+="\n\n if (iterable !== objectProto) {\n var ctor = iterable.constructor,\n isProto = iterable === (ctor && ctor.prototype),\n className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n nonEnum = nonEnumProps[className];\n ",k=0;7>k;k++)t+="\n index = '"+e.shadowedProps[k]+"';\n if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))",e.useHas||(t+=" || (!nonEnum[index] && iterable[index] !== objectProto[index])"),t+=") {\n "+e.loop+";\n } ";t+="\n } "}return(e.array||It.nonEnumArgs)&&(t+="\n}"),t+=e.bottom+";\nreturn result"};At||(u=function(){function e(){}return function(t){if(w(t)){e.prototype=t;var n=new e;e.prototype=null}return n||ft.Object()}}());var zt=qt?function(e,t){ut.value=t,qt(e,"__bindData__",ut)}:D;It.argsClass||(b=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&Pt.call(e,"callee")&&!$t.call(e,"callee")||!1});var Ft=Ut||function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&wt.call(e)==et||!1},Tt=d({args:"object",init:"[]",top:"if (!(objectTypes[typeof object])) return result",loop:"result.push(index)"}),Rt=Ot?function(e){return w(e)?It.enumPrototypes&&"function"==typeof e||It.nonEnumArgs&&e.length&&b(e)?Tt(e):Ot(e):[]}:Tt,Ht={args:"collection, callback, thisArg",top:"callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",array:"typeof length == 'number'",keys:Rt,loop:"if (callback(iterable[index], index, collection) === false) return result"},Bt={args:"object, source, guard",top:"var args = arguments,\n argsIndex = 0,\n argsLength = typeof guard == 'number' ? 2 : args.length;\nwhile (++argsIndex < argsLength) {\n iterable = args[argsIndex];\n if (iterable && objectTypes[typeof iterable]) {",keys:Rt,loop:"if (typeof result[index] == 'undefined') result[index] = iterable[index]",bottom:" }\n}"},Qt={top:"if (!objectTypes[typeof iterable]) return result;\n"+Ht.top,array:!1},Vt={"&":"&","<":"<",">":">",'"':""","'":"'"},Wt=RegExp("["+Rt(Vt).join("")+"]","g"),Gt=d(Ht),Jt=d(Bt,{top:Bt.top.replace(";",";\nif (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n callback = args[--argsLength];\n}"),loop:"result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]"}),Kt=d(Bt),Mt=d(Ht,Qt,{useHas:!1}),Xt=d(Ht,Qt);x(/x/)&&(x=function(e){return"function"==typeof e&&wt.call(e)==ot}),a.assign=Jt,a.bind=q,a.createCallback=A,a.defaults=Kt,a.filter=P,a.forEach=$,a.forIn=Mt,a.forOwn=Xt,a.keys=Rt,a.property=L,a.reject=E,a.values=j,a.each=$,a.extend=Jt,a.select=P,a.clone=y,a.cloneDeep=C,a.escape=U,a.find=S,a.identity=O,a.isArguments=b,a.isArray=Ft,a.isFunction=x,a.isObject=w,a.isString=_,a.noop=D,a.template=I,a.detect=S,a.findWhere=S,a.VERSION="2.4.1",dt&>&&(vt?(gt.exports=a)._=a:dt._=a)}).call(this)}),require.register("side-comments/js/helpers/mobile-check.js",function(e,t,n){n.exports=function(){var e=!1;return function(t){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|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(t)||/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(t.substr(0,4)))&&(e=!0)}(navigator.userAgent||navigator.vendor||window.opera),e}}),require.register("side-comments/templates/section.html",function(e,t,n){n.exports='
    \n \n <%= comments.length %>\n \n \n
    \n
      \n <% _.each(comments, function( comment ){ %>\n <%= _.template(commentTemplate, { comment: comment, currentUser: currentUser }) %>\n <% }) %>\n
    \n \n Leave a comment\n \n <% if (currentUser){ %>\n
    \n
    \n \n
    \n

    \n <%= currentUser.name %>\n

    \n \n
    \n Post\n Cancel\n
    \n
    \n <% } %>\n
    \n
    '}),require.register("side-comments/templates/comment.html",function(e,t,n){n.exports='
  • \n
    \n \n
    \n <% if (comment.authorUrl) { %>\n \n <%= comment.authorName %>\n \n <% } else { %>\n

    \n <%= comment.authorName %>\n

    \n <% } %>\n

    \n <%= comment.comment %>\n

    \n <% if (currentUser && comment.authorId === currentUser.id){ %>\n Delete\n <% } %>\n
  • '}),require.alias("component-emitter/index.js","side-comments/deps/emitter/index.js"),require.alias("component-emitter/index.js","emitter/index.js"),require.alias("side-comments/js/main.js","side-comments/index.js"); \ No newline at end of file +function require(e,t,n){var r=require.resolve(e);if(null==r){n=n||e,t=t||"root";var o=new Error('Failed to require "'+n+'" from "'+t+'"');throw o.path=n,o.parent=t,o.require=!0,o}var i=require.modules[r];if(!i._resolving&&!i.exports){var s={};s.exports={},s.client=s.component=!0,i._resolving=!0,i.call(this,s.exports,require.relative(r),s),delete i._resolving,i.exports=s.exports}return i.exports}require.modules={},require.aliases={},require.resolve=function(e){"/"===e.charAt(0)&&(e=e.slice(1));for(var t=[e,e+".js",e+".json",e+"/index.js",e+"/index.json"],n=0;nr;++r)n[r].apply(this,t)}return this},r.prototype.listeners=function(e){return this._callbacks=this._callbacks||{},this._callbacks[e]||[]},r.prototype.hasListeners=function(e){return!!this.listeners(e).length}}),require.register("side-comments/js/main.js",function(e,t,n){function r(e,t,n){this.$el=a(e),this.$body=a("body"),this.eventPipe=new s,this.currentUser=o.clone(t)||null,this.existingComments=o.cloneDeep(n)||[],this.sections=[],this.activeSection=null,this.eventPipe.on("showComments",o.bind(this.showComments,this)),this.eventPipe.on("hideComments",o.bind(this.hideComments,this)),this.eventPipe.on("sectionSelected",o.bind(this.sectionSelected,this)),this.eventPipe.on("sectionDeselected",o.bind(this.sectionDeselected,this)),this.eventPipe.on("commentPosted",o.bind(this.commentPosted,this)),this.eventPipe.on("commentDeleted",o.bind(this.commentDeleted,this)),this.eventPipe.on("addCommentAttempted",o.bind(this.addCommentAttempted,this)),this.$body.on("click",o.bind(this.bodyClick,this)),this.initialize(this.existingComments)}var o=t("./vendor/lodash-custom.js"),i=t("./section.js"),s=t("emitter"),a=jQuery;s(r.prototype),r.prototype.initialize=function(){o.each(this.$el.find(".commentable-section"),function(e){var t=a(e),n=t.data("section-id").toString(),r=o.find(this.existingComments,{sectionId:n});this.sections.push(new i(this.eventPipe,t,this.currentUser,r))},this)},r.prototype.showComments=function(){this.$el.addClass("side-comments-open")},r.prototype.hideComments=function(){this.activeSection&&(this.activeSection.deselect(),this.activeSection=null),this.$el.removeClass("side-comments-open")},r.prototype.sectionSelected=function(e){this.showComments(),this.activeSection&&this.activeSection.deselect(),this.activeSection=e},r.prototype.sectionDeselected=function(){this.hideComments(),this.activeSection=null},r.prototype.commentPosted=function(e){this.emit("commentPosted",e)},r.prototype.commentDeleted=function(e){this.emit("commentDeleted",e)},r.prototype.addCommentAttempted=function(){this.emit("addCommentAttempted")},r.prototype.insertComment=function(e){var t=o.find(this.sections,{id:e.sectionId});t.insertComment(e)},r.prototype.replyComment=function(e){var t=o.find(this.sections,{id:e.sectionId});t.insertComment(e)},r.prototype.removeComment=function(e,t){var n=o.find(this.sections,{id:e});n.removeComment(t)},r.prototype.deleteComment=function(e,t){var n=o.find(this.sections,{id:e});n.deleteComment(t)},r.prototype.commentsAreVisible=function(){return this.$el.hasClass("side-comments-open")},r.prototype.bodyClick=function(e){var t=a(e.target);t.closest(".side-comment").length<1&&t.closest("body").length>0&&(this.activeSection&&this.activeSection.deselect(),this.hideComments())},r.prototype.setCurrentUser=function(e){this.hideComments(),this.currentUser=e,o.each(this.sections,o.bind(function(e){e.currentUser=this.currentUser,e.render()},this))},r.prototype.removeCurrentUser=function(){this.setCurrentUser(null)},r.prototype.destroy=function(){this.hideComments(),this.$el.off()},n.exports=r}),require.register("side-comments/js/section.js",function(e,t,n){function r(e,t,n,r){this.eventPipe=e,this.$el=t,this.comments=r?r.comments:[],this.currentUser=n||null,this.clickEventName=c()?"touchstart":"click",this.id=t.data("section-id"),this.$el.on(this.clickEventName,".side-comment .marker",o.bind(this.markerClick,this)),this.$el.on(this.clickEventName,".side-comment .add-comment",o.bind(this.addCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .reply-comment",o.bind(this.replyCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .post",o.bind(this.postCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .cancel",o.bind(this.cancelCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .delete",o.bind(this.deleteCommentClick,this)),this.render()}var o=t("./vendor/lodash-custom.js"),i=t("../templates/section.html"),s=t("../templates/comment.html"),a=t("../templates/form.html"),c=t("./helpers/mobile-check.js"),l=jQuery;r.prototype.markerClick=function(e){e.preventDefault(),this.select()},r.prototype.addCommentClick=function(e){e.preventDefault(),this.currentUser?this.showCommentForm():this.eventPipe.emit("addCommentAttempted")},r.prototype.showCommentForm=function(){this.comments.length>0&&(this.hideCommentForm(),this.$el.find(".add-comment").addClass("hide"),this.$el.find(".comment-form").addClass("active")),this.focusCommentBox()},r.prototype.replyCommentClick=function(e){e.preventDefault(),this.currentUser?this.showReplyForm(e.currentTarget):this.eventPipe.emit("addCommentAttempted")},r.prototype.showReplyForm=function(e){this.comments.length>0&&(this.hideCommentForm(),this.$el.find(e).addClass("hide"),$form=l(o.find(l.makeArray(this.$el.find(".reply-form")),function(t){return t.dataset.parent===e.dataset.comment})),$form.addClass("active")),this.focusCommentBox()},r.prototype.hideCommentForm=function(){this.comments.length>0&&(this.$el.find('a[class*="-comment"]').removeClass("hide"),this.$el.find('div[class*="-form"]').removeClass("active")),this.$el.find(".comment-box").empty()},r.prototype.focusCommentBox=function(){setTimeout(o.bind(function(){this.$el.find(".comment-box").get(0).focus()},this),300)},r.prototype.cancelCommentClick=function(e){e.preventDefault(),this.cancelComment()},r.prototype.cancelComment=function(){this.comments.length>0?this.hideCommentForm():(this.deselect(),this.eventPipe.emit("hideComments"))},r.prototype.postCommentClick=function(e){e.preventDefault(),this.postComment()},r.prototype.postComment=function(){var e=this.$el.find('div[class*="-form"].active'),t=e.find(".comment-box"),n=t.val(),r={sectionId:this.id,comment:n,authorAvatarUrl:this.currentUser.avatarUrl,authorName:this.currentUser.name,authorId:this.currentUser.id,authorUrl:this.currentUser.authorUrl||null};Number(e.data("parent"))&&(r.parentId=Number(e.data("parent"))),t.val(""),this.eventPipe.emit("commentPosted",r)},r.prototype.insertComment=function(e){var t=o.template(s,{comment:e,currentUser:this.currentUser,formTemplate:a,self:s});void 0!==e.parentId?(o.find(this.comments,{id:e.parentId}).replies.push(e),$parent=l(o.find(l.makeArray(this.$el.find(".comments > li")),function(t){return t.dataset.commentId==e.parentId})),$parent.find(".replies").append(t)):(this.comments.push(e),this.$el.find(".comments").append(t)),this.$el.find(".side-comment").addClass("has-comments"),this.updateCommentCount(),this.hideCommentForm()},r.prototype.updateCommentCount=function(){this.$el.find(".marker span").text(this.comments.length)},r.prototype.deleteCommentClick=function(e){e.preventDefault();var t=l(e.target).closest("li").data("comment-id");window.confirm("Are you sure you want to delete this comment?")&&this.deleteComment(t)},r.prototype.deleteComment=function(e){var t=o.find(this.comments,{id:e});t.sectionId=this.id,this.eventPipe.emit("commentDeleted",t)},r.prototype.removeComment=function(e){this.comments=o.reject(this.comments,{id:e}),this.$el.find('.side-comment .comments li[data-comment-id="'+e+'"]').remove(),this.updateCommentCount(),this.comments.length<1&&this.$el.find(".side-comment").removeClass("has-comments")},r.prototype.select=function(){this.isSelected()?(this.deselect(),this.eventPipe.emit("sectionDeselected",this)):(this.$el.find(".side-comment").addClass("active"),0===this.comments.length&&this.currentUser&&this.focusCommentBox(),this.eventPipe.emit("sectionSelected",this))},r.prototype.deselect=function(){this.$el.find(".side-comment").removeClass("active"),this.hideCommentForm()},r.prototype.isSelected=function(){return this.$el.find(".side-comment").hasClass("active")},r.prototype.sectionClasses=function(){var e="";return this.comments.length>0&&(e+=" has-comments"),this.currentUser||(e+=" no-current-user"),e},r.prototype.render=function(){this.$el.find(".side-comment").remove(),l(o.template(i,{commentTemplate:s,comments:this.comments,sectionClasses:this.sectionClasses(),formTemplate:a,currentUser:this.currentUser})).appendTo(this.$el)},r.prototype.destroy=function(){this.$el.off()},n.exports=r}),require.register("side-comments/js/vendor/lodash-custom.js",function(e,t,n){(function(){function t(e){return"\\"+ht[e]}function r(){return N.pop()||[]}function o(e){return"function"!=typeof e.toString&&"string"==typeof(e+"")}function i(e){e.length=0,N.lengtho?0:o);++r-1:void 0});return a.pop(),c.pop(),k&&(i(a),i(c)),l}function f(e,t,n,r,o,i){var a=1&t,l=2&t,m=4&t,u=16&t,h=32&t;if(!l&&!x(e))throw new TypeError;u&&!n.length&&(t&=-17,u=n=!1),h&&!r.length&&(t&=-33,h=r=!1);var d=e&&e.__bindData__;if(d&&d!==!0)return d=s(d),d[2]&&(d[2]=s(d[2])),d[3]&&(d[3]=s(d[3])),!a||1&d[1]||(d[4]=o),!a&&1&d[1]&&(t|=8),!m||4&d[1]||(d[5]=i),u&&$t.apply(d[2]||(d[2]=[]),n),h&&Ut.apply(d[3]||(d[3]=[]),r),d[1]|=t,f.apply(null,d);var v=1==t||17===t?c:p;return v([e,t,n,r,o,i])}function d(){ut.shadowedProps=X,ut.array=ut.bottom=ut.loop=ut.top="",ut.init="iterable",ut.useHas=!0;for(var e,t=0;e=arguments[t];t++)for(var n in e)ut[n]=e[n];var r=ut.args;ut.firstArg=/^[^,]+/.exec(r)[0];var o=Function("baseCreateCallback, errorClass, errorProto, hasOwnProperty, indicatorObject, isArguments, isArray, isString, keys, objectProto, objectTypes, nonEnumProps, stringClass, stringProto, toString","return function("+r+") {\n"+Lt(ut)+"\n}");return o(u,rt,Ct,Pt,F,y,Ft,_,ut.keys,kt,pt,Dt,ct,xt,wt)}function v(e){return Vt[e]}function g(e){return"function"==typeof e&&_t.test(e)}function y(e){return e&&"object"==typeof e&&"number"==typeof e.length&&wt.call(e)==Z||!1}function b(e,t,n,r){return"boolean"!=typeof t&&null!=t&&(r=n,n=t,t=!1),l(e,t,"function"==typeof n&&u(n,r,1))}function C(e,t,n){return l(e,!0,"function"==typeof t&&u(t,n,1))}function x(e){return"function"==typeof e}function w(e){return!(!e||!pt[typeof e])}function _(e){return"string"==typeof e||e&&"object"==typeof e&&wt.call(e)==ct||!1}function j(e){for(var t=-1,n=Rt(e),r=n.length,o=Array(r);++t2?f(e,17,s(arguments,2),null,t):f(e,1,null,null,t)}function E(e,t,n){var r=typeof e;if(null==e||"function"==r)return u(e,t,n);if("object"!=r)return D(e);var o=Rt(e),i=o[0],s=e[i];return 1!=o.length||s!==s||w(s)?function(t){for(var n=o.length,r=!1;n--&&(r=h(t[o[n]],e[o[n]],null,!0)););return r}:function(e){var t=e[i];return s===t&&(0!==s||1/s==1/t)}}function q(e){return null==e?"":String(e).replace(Wt,v)}function O(e){return e}function I(){}function D(e){return function(t){return t[e]}}function T(e,n,r){var o=a.templateSettings;e=String(e||""),r=Kt({},r,o);var i,s=Kt({},r.imports,o.imports),c=Rt(s),l=j(s),m=0,u=r.interpolate||J,p="__p += '",h=RegExp((r.escape||J).source+"|"+u.source+"|"+(u===G?Q:J).source+"|"+(r.evaluate||J).source+"|$","g");e.replace(h,function(n,r,o,s,a,c){return o||(o=s),p+=e.slice(m,c).replace(M,t),r&&(p+="' +\n__e("+r+") +\n'"),a&&(i=!0,p+="';\n"+a+";\n__p += '"),o&&(p+="' +\n((__t = ("+o+")) == null ? '' : __t) +\n'"),m=c+n.length,n}),p+="';\n";var f=r.variable,d=f;d||(f="obj",p="with ("+f+") {\n"+p+"\n}\n"),p=(i?p.replace(R,""):p).replace(B,"$1").replace(H,"$1;"),p="function("+f+") {\n"+(d?"":f+" || ("+f+" = {});\n")+"var __t, __p = '', __e = _.escape"+(i?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+p+"return __p\n}";var v="\n/*\n//# sourceURL="+(r.sourceURL||"/lodash/template/source["+Y++ +"]")+"\n*/";try{var g=Function(c,"return "+p+v).apply(L,l)}catch(y){throw y.source=p,y}return n?g(n):(g.source=p,g)}var L,N=[],F={},z=40,R=/\b__p \+= '';/g,B=/\b(__p \+=) '' \+/g,H=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Q=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,V=/\w*$/,W=/^\s*function[ \n\r\t]+\w/,G=/<%=([\s\S]+?)%>/g,J=/($^)/,K=/\bthis\b/,M=/['\n\r\t\u2028\u2029\\]/g,X=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Y=0,Z="[object Arguments]",et="[object Array]",tt="[object Boolean]",nt="[object Date]",rt="[object Error]",ot="[object Function]",it="[object Number]",st="[object Object]",at="[object RegExp]",ct="[object String]",lt={};lt[ot]=!1,lt[Z]=lt[et]=lt[tt]=lt[nt]=lt[it]=lt[st]=lt[at]=lt[ct]=!0;var mt={configurable:!1,enumerable:!1,value:null,writable:!1},ut={args:"",array:null,bottom:"",firstArg:"",init:"",keys:null,loop:"",shadowedProps:null,support:null,top:"",useHas:!1},pt={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},ht={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},ft=pt[typeof window]&&window||this,dt=pt[typeof e]&&e&&!e.nodeType&&e,vt=pt[typeof n]&&n&&!n.nodeType&&n,gt=vt&&vt.exports===dt&&dt,yt=pt[typeof global]&&global;!yt||yt.global!==yt&&yt.window!==yt||(ft=yt);var bt=[],Ct=Error.prototype,kt=Object.prototype,xt=String.prototype,wt=kt.toString,_t=RegExp("^"+String(wt).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),jt=Function.prototype.toString,Pt=kt.hasOwnProperty,$t=bt.push,St=kt.propertyIsEnumerable,Ut=bt.unshift,At=function(){try{var e={},t=g(t=Object.defineProperty)&&t,n=t(e,e,e)&&t}catch(r){}return n}(),Et=g(Et=Object.create)&&Et,qt=g(qt=Array.isArray)&&qt,Ot=g(Ot=Object.keys)&&Ot,It={};It[et]=Array,It[tt]=Boolean,It[nt]=Date,It[ot]=Function,It[st]=Object,It[it]=Number,It[at]=RegExp,It[ct]=String;var Dt={};Dt[et]=Dt[nt]=Dt[it]={constructor:!0,toLocaleString:!0,toString:!0,valueOf:!0},Dt[tt]=Dt[ct]={constructor:!0,toString:!0,valueOf:!0},Dt[rt]=Dt[ot]=Dt[at]={constructor:!0,toString:!0},Dt[st]={constructor:!0},function(){for(var e=X.length;e--;){var t=X[e];for(var n in Dt)Pt.call(Dt,n)&&!Pt.call(Dt[n],t)&&(Dt[n][t]=!1)}}();var Tt=a.support={};!function(){var e=function(){this.x=1},t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments);Tt.argsClass=wt.call(arguments)==Z,Tt.argsObject=arguments.constructor==Object&&!(arguments instanceof Array),Tt.enumErrorProps=St.call(Ct,"message")||St.call(Ct,"name"),Tt.enumPrototypes=St.call(e,"prototype"),Tt.funcDecomp=!g(ft.WinRTError)&&K.test(function(){return this}),Tt.funcNames="string"==typeof Function.name,Tt.nonEnumArgs=0!=r,Tt.nonEnumShadows=!/valueOf/.test(n),Tt.spliceObjects=(bt.splice.call(t,0,1),!t[0]),Tt.unindexedChars="x"[0]+Object("x")[0]!="xx";try{Tt.nodeClass=!(wt.call(document)==st&&!({toString:0}+""))}catch(o){Tt.nodeClass=!0}}(1),a.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:G,variable:"",imports:{_:a}};var Lt=function(e){var t="var index, iterable = "+e.firstArg+", result = "+e.init+";\nif (!iterable) return result;\n"+e.top+";";e.array?(t+="\nvar length = iterable.length; index = -1;\nif ("+e.array+") { ",Tt.unindexedChars&&(t+="\n if (isString(iterable)) {\n iterable = iterable.split('')\n } "),t+="\n while (++index < length) {\n "+e.loop+";\n }\n}\nelse { "):Tt.nonEnumArgs&&(t+="\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += '';\n "+e.loop+";\n }\n } else { "),Tt.enumPrototypes&&(t+="\n var skipProto = typeof iterable == 'function';\n "),Tt.enumErrorProps&&(t+="\n var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n ");var n=[];if(Tt.enumPrototypes&&n.push('!(skipProto && index == "prototype")'),Tt.enumErrorProps&&n.push('!(skipErrorProps && (index == "message" || index == "name"))'),e.useHas&&e.keys)t+="\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] && keys(iterable),\n length = ownProps ? ownProps.length : 0;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n",n.length&&(t+=" if ("+n.join(" && ")+") {\n "),t+=e.loop+"; ",n.length&&(t+="\n }"),t+="\n } ";else if(t+="\n for (index in iterable) {\n",e.useHas&&n.push("hasOwnProperty.call(iterable, index)"),n.length&&(t+=" if ("+n.join(" && ")+") {\n "),t+=e.loop+"; ",n.length&&(t+="\n }"),t+="\n } ",Tt.nonEnumShadows){for(t+="\n\n if (iterable !== objectProto) {\n var ctor = iterable.constructor,\n isProto = iterable === (ctor && ctor.prototype),\n className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n nonEnum = nonEnumProps[className];\n ",k=0;7>k;k++)t+="\n index = '"+e.shadowedProps[k]+"';\n if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))",e.useHas||(t+=" || (!nonEnum[index] && iterable[index] !== objectProto[index])"),t+=") {\n "+e.loop+";\n } ";t+="\n } "}return(e.array||Tt.nonEnumArgs)&&(t+="\n}"),t+=e.bottom+";\nreturn result"};Et||(m=function(){function e(){}return function(t){if(w(t)){e.prototype=t;var n=new e;e.prototype=null}return n||ft.Object()}}());var Nt=At?function(e,t){mt.value=t,At(e,"__bindData__",mt)}:I;Tt.argsClass||(y=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&Pt.call(e,"callee")&&!St.call(e,"callee")||!1});var Ft=qt||function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&wt.call(e)==et||!1},zt=d({args:"object",init:"[]",top:"if (!(objectTypes[typeof object])) return result",loop:"result.push(index)"}),Rt=Ot?function(e){return w(e)?Tt.enumPrototypes&&"function"==typeof e||Tt.nonEnumArgs&&e.length&&y(e)?zt(e):Ot(e):[]}:zt,Bt={args:"collection, callback, thisArg",top:"callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",array:"typeof length == 'number'",keys:Rt,loop:"if (callback(iterable[index], index, collection) === false) return result"},Ht={args:"object, source, guard",top:"var args = arguments,\n argsIndex = 0,\n argsLength = typeof guard == 'number' ? 2 : args.length;\nwhile (++argsIndex < argsLength) {\n iterable = args[argsIndex];\n if (iterable && objectTypes[typeof iterable]) {",keys:Rt,loop:"if (typeof result[index] == 'undefined') result[index] = iterable[index]",bottom:" }\n}"},Qt={top:"if (!objectTypes[typeof iterable]) return result;\n"+Bt.top,array:!1},Vt={"&":"&","<":"<",">":">",'"':""","'":"'"},Wt=RegExp("["+Rt(Vt).join("")+"]","g"),Gt=d(Bt),Jt=d(Ht,{top:Ht.top.replace(";",";\nif (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n callback = args[--argsLength];\n}"),loop:"result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]"}),Kt=d(Ht),Mt=d(Bt,Qt,{useHas:!1}),Xt=d(Bt,Qt);x(/x/)&&(x=function(e){return"function"==typeof e&&wt.call(e)==ot}),a.assign=Jt,a.bind=A,a.createCallback=E,a.defaults=Kt,a.filter=P,a.forEach=S,a.forIn=Mt,a.forOwn=Xt,a.keys=Rt,a.property=D,a.reject=U,a.values=j,a.each=S,a.extend=Jt,a.select=P,a.clone=b,a.cloneDeep=C,a.escape=q,a.find=$,a.identity=O,a.isArguments=y,a.isArray=Ft,a.isFunction=x,a.isObject=w,a.isString=_,a.noop=I,a.template=T,a.detect=$,a.findWhere=$,a.VERSION="2.4.1",dt&&vt&&(gt?(vt.exports=a)._=a:dt._=a)}).call(this)}),require.register("side-comments/js/helpers/mobile-check.js",function(e,t,n){n.exports=function(){var e=!1;return function(t){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|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(t)||/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(t.substr(0,4)))&&(e=!0)}(navigator.userAgent||navigator.vendor||window.opera),e}}),require.register("side-comments/templates/section.html",function(e,t,n){n.exports='
    \n \n <%= comments.length %>\n \n \n
    \n
      \n <% _.each(comments, function( comment ){ %>\n <%= _.template(commentTemplate, { comment: comment, currentUser: currentUser, formTemplate: formTemplate, self: commentTemplate }) %>\n <% }) %>\n
    \n \n Leave a comment\n <% if (currentUser) { %>\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'comment-form\', commentId: null }) %>\n <% } %>\n
    \n
    '}),require.register("side-comments/templates/form.html",function(e,t,n){n.exports='
    \n
    \n \n
    \n

    \n <%= currentUser.name %>\n

    \n \n
    \n Post\n Cancel\n
    \n
    '}),require.register("side-comments/templates/comment.html",function(e,t,n){n.exports='
  • \n
    \n \n
    \n <% if (comment.authorUrl) { %>\n \n <%= comment.authorName %>\n \n <% } else { %>\n

    \n <%= comment.authorName %>\n

    \n <% } %>\n

    \n <%= comment.comment %>\n

    \n\n <% if ( comment.parentId === undefined ) { %>\n \n
      \n <% _.each(comment.replies, function ( reply ) {%>\n <%= _.template(self, { comment: reply, currentUser: currentUser, formTemplate: formTemplate }) %>\n <% });%>\n
    \n\n <% if (currentUser){ %>\n Reply\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'reply-form\', commentId: comment.id })%>\n <% if (comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n <% } %>\n\n <% } %>\n\n <% if (currentUser && comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n\n
  • '}),require.alias("component-emitter/index.js","side-comments/deps/emitter/index.js"),require.alias("component-emitter/index.js","emitter/index.js"),require.alias("side-comments/js/main.js","side-comments/index.js"); \ No newline at end of file diff --git a/release/themes/default-theme.css b/release/themes/default-theme.css index 6f5e177..67ffa40 100644 --- a/release/themes/default-theme.css +++ b/release/themes/default-theme.css @@ -1,16 +1,15 @@ .commentable-container { -webkit-transition: all 0.22s ease; - transition: all 0.22s ease; + transition: all 0.22s ease; } .side-comments-open { -webkit-transform: translate(-220px, 0); - -ms-transform: translate(-220px, 0); - transform: translate(-220px, 0); + -ms-transform: translate(-220px, 0); + transform: translate(-220px, 0); } .commentable-section { - -webkit-box-sizing: border-box; -moz-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; padding-right: 30px; } .side-comment { @@ -64,7 +63,7 @@ } .side-comment.active .comments-wrapper { -webkit-animation: fadein 0.2s; - animation: fadein 0.2s; + animation: fadein 0.2s; } .side-comment.has-comments .comments-wrapper { top: -22px; @@ -77,6 +76,10 @@ padding: 15px 0; margin-top: -1px; } +.side-comment .reply-form { + padding-left: 42px; + padding-top: 10px; +} .side-comment .comment, .side-comment .comment-box { font-size: 14px; @@ -150,9 +153,8 @@ float: left; margin-right: 15px; letter-spacing: 0; - -webkit-box-sizing: border-box; -moz-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; } .side-comment .add-comment:hover { text-decoration: none; @@ -167,7 +169,6 @@ .side-comment .comment-box { outline: none; border: 0; - -webkit-box-shadow: none; box-shadow: none; padding: 0; } @@ -182,11 +183,14 @@ color: #B3B3B1; padding: 0 5px; } +.side-comment .replies .author-name { + width: 116px; +} @media (max-width: 768px) { .side-comments-open { -webkit-transform: translate(-220px, 0); - -ms-transform: translate(-220px, 0); - transform: translate(-220px, 0); + -ms-transform: translate(-220px, 0); + transform: translate(-220px, 0); } .side-comment .comments-wrapper { width: 200px; diff --git a/release/themes/default-theme.min.css b/release/themes/default-theme.min.css index 8434619..0f58d8f 100644 --- a/release/themes/default-theme.min.css +++ b/release/themes/default-theme.min.css @@ -1 +1 @@ -.commentable-container{-webkit-transition:all .22s ease;transition:all .22s ease}.side-comments-open{-webkit-transform:translate(-220px,0);-ms-transform:translate(-220px,0);transform:translate(-220px,0)}.commentable-section{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding-right:30px}.side-comment{padding-bottom:20px}.side-comment .marker{width:20px;height:18px;background:#DEDEDC;border-radius:2px;text-decoration:none}.side-comment .marker span,.side-comment .marker:before{content:"+";position:absolute;width:20px;height:18px;line-height:16px;font-size:14px;color:#FFF;text-align:center}.side-comment .marker span{line-height:20px;font-size:12px}.side-comment .marker:after{content:"";display:block;position:absolute;bottom:-7px;left:5px;width:0;border-width:7px 8px 0 0;border-style:solid;border-color:#DEDEDC transparent}.side-comment .marker:hover,.side-comment.active .marker{background:#4FAF62}.side-comment .marker:hover:after,.side-comment.active .marker:after{border-color:#4FAF62 transparent}.side-comment .comments-wrapper{top:-22px;width:200px;padding-bottom:120px}.side-comment.active .comments-wrapper{-webkit-animation:fadein .2s;animation:fadein .2s}.side-comment.has-comments .comments-wrapper{top:-22px}.side-comment .comment-form,.side-comment ul.comments li{border:1px solid #F2F2F0;border-left:0;border-right:0;padding:15px 0;margin-top:-1px}.side-comment .comment,.side-comment .comment-box{font-size:14px;line-height:18px}.side-comment .author-avatar{float:left;width:32px;height:32px;margin-right:10px}.side-comment .author-avatar img{width:100%;height:100%}.side-comment .right-of-avatar{float:left;width:158px}.side-comment .author-name{font-size:15px;line-height:16px;margin:0 0 2px;font-weight:700;text-decoration:none;color:#222}.side-comment a.author-name:hover{color:#444}.side-comment .action-link{color:#B3B3B1;font-size:13px;text-decoration:none}.side-comment .action-link:hover{text-decoration:none}.side-comment .action-link.post .post{color:#89C794}.side-comment .action-link.post .post:hover{color:#468c54}.side-comment .action-link.cancel:hover,.side-comment .action-link.delete:hover{color:#57AD68}.side-comment .add-comment{color:#B3B3B1;font-size:14px;line-height:22px;font-weight:300;padding:0 8px;letter-spacing:.05em;text-decoration:none;margin-top:10px}.side-comment .add-comment:before{content:"+";border:2px solid #DEDEDC;border-radius:100px;width:23px;height:23px;color:#DEDEDC;display:block;text-align:center;font-size:16px;font-weight:400;line-height:18px;float:left;margin-right:15px;letter-spacing:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.side-comment .add-comment:hover{text-decoration:none;color:#4FAF62}.side-comment .add-comment:hover:before{border-color:#4FAF62;color:#4FAF62}.side-comment .comment-box{outline:0;border:0;-webkit-box-shadow:none;box-shadow:none;padding:0}.side-comment .actions{margin-top:5px}.side-comment .actions a{float:left}.side-comment .actions .cancel:before{content:'\00B7';color:#B3B3B1;padding:0 5px}@media (max-width:768px){.side-comments-open{-webkit-transform:translate(-220px,0);-ms-transform:translate(-220px,0);transform:translate(-220px,0)}.side-comment .comments-wrapper{width:200px}.side-comment .right-of-avatar{width:158px}.side-comment .marker{display:block}} \ No newline at end of file +.commentable-container{-webkit-transition:all .22s ease;transition:all .22s ease}.side-comments-open{-webkit-transform:translate(-220px,0);-ms-transform:translate(-220px,0);transform:translate(-220px,0)}.commentable-section{-moz-box-sizing:border-box;box-sizing:border-box;padding-right:30px}.side-comment{padding-bottom:20px}.side-comment .marker{width:20px;height:18px;background:#DEDEDC;border-radius:2px;text-decoration:none}.side-comment .marker span,.side-comment .marker:before{content:"+";position:absolute;width:20px;height:18px;line-height:16px;font-size:14px;color:#FFF;text-align:center}.side-comment .marker span{line-height:20px;font-size:12px}.side-comment .marker:after{content:"";display:block;position:absolute;bottom:-7px;left:5px;width:0;border-width:7px 8px 0 0;border-style:solid;border-color:#DEDEDC transparent}.side-comment .marker:hover,.side-comment.active .marker{background:#4FAF62}.side-comment .marker:hover:after,.side-comment.active .marker:after{border-color:#4FAF62 transparent}.side-comment .comments-wrapper{top:-22px;width:200px;padding-bottom:120px}.side-comment.active .comments-wrapper{-webkit-animation:fadein .2s;animation:fadein .2s}.side-comment.has-comments .comments-wrapper{top:-22px}.side-comment .comment-form,.side-comment ul.comments li{border:1px solid #F2F2F0;border-left:0;border-right:0;padding:15px 0;margin-top:-1px}.side-comment .reply-form{padding-left:42px;padding-top:10px}.side-comment .comment,.side-comment .comment-box{font-size:14px;line-height:18px}.side-comment .author-avatar{float:left;width:32px;height:32px;margin-right:10px}.side-comment .author-avatar img{width:100%;height:100%}.side-comment .right-of-avatar{float:left;width:158px}.side-comment .author-name{font-size:15px;line-height:16px;margin:0 0 2px;font-weight:700;text-decoration:none;color:#222}.side-comment a.author-name:hover{color:#444}.side-comment .action-link{color:#B3B3B1;font-size:13px;text-decoration:none}.side-comment .action-link:hover{text-decoration:none}.side-comment .action-link.post .post{color:#89C794}.side-comment .action-link.post .post:hover{color:#468c54}.side-comment .action-link.cancel:hover,.side-comment .action-link.delete:hover{color:#57AD68}.side-comment .add-comment{color:#B3B3B1;font-size:14px;line-height:22px;font-weight:300;padding:0 8px;letter-spacing:.05em;text-decoration:none;margin-top:10px}.side-comment .add-comment:before{content:"+";border:2px solid #DEDEDC;border-radius:100px;width:23px;height:23px;color:#DEDEDC;display:block;text-align:center;font-size:16px;font-weight:400;line-height:18px;float:left;margin-right:15px;letter-spacing:0;-moz-box-sizing:border-box;box-sizing:border-box}.side-comment .add-comment:hover{text-decoration:none;color:#4FAF62}.side-comment .add-comment:hover:before{border-color:#4FAF62;color:#4FAF62}.side-comment .comment-box{outline:0;border:0;box-shadow:none;padding:0}.side-comment .actions{margin-top:5px}.side-comment .actions a{float:left}.side-comment .actions .cancel:before{content:'\00B7';color:#B3B3B1;padding:0 5px}.side-comment .replies .author-name{width:116px}@media (max-width:768px){.side-comments-open{-webkit-transform:translate(-220px,0);-ms-transform:translate(-220px,0);transform:translate(-220px,0)}.side-comment .comments-wrapper{width:200px}.side-comment .right-of-avatar{width:158px}.side-comment .marker{display:block}} \ No newline at end of file diff --git a/support/test_data.js b/support/test_data.js index ed1415c..2d196b6 100644 --- a/support/test_data.js +++ b/support/test_data.js @@ -8,14 +8,26 @@ var existingComments = [ "authorName": "Jon Sno", "authorId": 1, "authorUrl": "http://en.wikipedia.org/wiki/Kit_Harington", - "comment": "I'm Ned Stark's bastard. Related: I know nothing." + "comment": "I'm Ned Stark's bastard", + "replies": [ + { + "id" : 100, + "authorAvatarUrl": "support/images/jon_snow.png", + "authorName": "Jon Sno", + "authorId": 1, + "authorUrl": "http://en.wikipedia.org/wiki/Kit_Harington", + "comment": "P.S.: I know nothing.", + "parentId": 88 + } + ] }, { "id": 112, "authorAvatarUrl": "support/images/donald_draper.png", "authorName": "Donald Draper", "authorId": 2, - "comment": "I need a scotch." + "comment": "I need a scotch.", + "replies": [] } ] }, @@ -27,7 +39,8 @@ var existingComments = [ "authorAvatarUrl": "support/images/clay_davis.png", "authorName": "Senator Clay Davis", "authorId": 3, - "comment": "These Side Comments are incredible. Sssshhhiiiiieeeee." + "comment": "These Side Comments are incredible. Sssshhhiiiiieeeee.", + "replies": [] } ] } diff --git a/templates/comment.html b/templates/comment.html index 745ce7d..173f967 100644 --- a/templates/comment.html +++ b/templates/comment.html @@ -14,7 +14,27 @@

    <%= comment.comment %>

    - <% if (currentUser && comment.authorId === currentUser.id){ %> - Delete + + <% if ( comment.parentId === undefined ) { %> + +
      + <% _.each(comment.replies, function ( reply ) {%> + <%= _.template(self, { comment: reply, currentUser: currentUser, formTemplate: formTemplate }) %> + <% });%> +
    + + <% if (currentUser){ %> + Reply + <%= _.template(formTemplate, { currentUser: currentUser, formClass: 'reply-form', commentId: comment.id })%> + <% if (comment.authorId === currentUser.id) { %> + Delete + <% } %> + <% } %> + <% } %> + + <% if (currentUser && comment.authorId === currentUser.id) { %> + Delete + <% } %> + \ No newline at end of file diff --git a/templates/form.html b/templates/form.html new file mode 100644 index 0000000..c1c6560 --- /dev/null +++ b/templates/form.html @@ -0,0 +1,13 @@ +
    +
    + +
    +

    + <%= currentUser.name %> +

    + +
    + Post + Cancel +
    +
    \ No newline at end of file diff --git a/templates/section.html b/templates/section.html index b88216e..1d60918 100644 --- a/templates/section.html +++ b/templates/section.html @@ -6,26 +6,13 @@
      <% _.each(comments, function( comment ){ %> - <%= _.template(commentTemplate, { comment: comment, currentUser: currentUser }) %> + <%= _.template(commentTemplate, { comment: comment, currentUser: currentUser, formTemplate: formTemplate, self: commentTemplate }) %> <% }) %>
    Leave a comment - - <% if (currentUser){ %> -
    -
    - -
    -

    - <%= currentUser.name %> -

    - -
    - Post - Cancel -
    -
    + <% if (currentUser) { %> + <%= _.template(formTemplate, { currentUser: currentUser, formClass: 'comment-form', commentId: null }) %> <% } %>
    \ No newline at end of file diff --git a/test/test_main.js b/test/test_main.js index 8653a43..f9edbaa 100644 --- a/test/test_main.js +++ b/test/test_main.js @@ -16,7 +16,8 @@ var newTestComment = { authorId: 1, authorAvatarUrl: "support/images/user/png", authorName: "New Test Commenter", - comment: "This is a test comment." + comment: "This is a test comment.", + replies: [] }; function check( done, f ) { @@ -34,9 +35,11 @@ function setSections() { $section3 = $('.side-comment').eq(2); } -function testCommentForSection( sectionNumber ) { +function testCommentForSection( sectionNumber, replyFor ) { var comment = _.clone(newTestComment); comment.sectionId = sectionNumber; + if ( replyFor ) + comment.parentId = replyFor; return comment; } @@ -109,16 +112,6 @@ describe("SideComments", function() { expect(sideComments.commentsAreVisible()).to.be.true; }); - it("should toggle the display of the comments when a marker is clicked", function() { - $('.side-comment').first().find('.marker').trigger('click'); - expect(sideComments.commentsAreVisible()).to.be.true; - }); - - it("should toggle the display of the comments when a marker is clicked", function() { - $('.side-comment').first().find('.marker').trigger('click'); - expect(sideComments.commentsAreVisible()).to.be.true; - }); - it("should make comments visible when a marker is clicked", function() { $('.side-comment').first().find('.marker').trigger('click'); expect(sideComments.commentsAreVisible()).to.be.true; @@ -177,7 +170,7 @@ describe("SideComments", function() { }); it("should render comment markup correctly", function(){ - expect($section1.find('.comments li').first().find('.author-name').text().trim()).to.equal('Jon Sno'); + expect($section1.find('.comments > li').first().children('.author-name').text().trim()).to.equal('Jon Sno'); }); it("should display the right number of comments in the markers for each sections", function(){ @@ -187,9 +180,9 @@ describe("SideComments", function() { }); it("should display the right number of comments in the list for each sections", function(){ - expect($section1.find('.comments li')).to.have.length.of(2); - expect($section2.find('.comments li')).to.have.length.of(0); - expect($section3.find('.comments li')).to.have.length.of(1); + expect($section1.find('.comments > li')).to.have.length.of(2); + expect($section2.find('.comments > li')).to.have.length.of(0); + expect($section3.find('.comments > li')).to.have.length.of(1); }); it("should show the add button when there is one or more comments", function(){ @@ -234,6 +227,34 @@ describe("SideComments", function() { expect(sideComments.commentsAreVisible()).to.be.false; }); + it("should assign the reply form to the correct comment", function () { + expect($section1.find('.comments > li').first().find('.reply-form').data('parent')).to.equal($section1.find('.comments > li').first().data('comment-id')); + }); + + it("should hide the previous reply form when clicking to reply another comment", function () { + $section1.find('.marker').trigger('click'); + $section1.find('.comments > li').first().find('.reply-comment').trigger('click'); + var $form1 = $section1.find('.reply-form.active'); + + $section1.find('.comments > li').last().find('.reply-comment').trigger('click'); + + expect($form1.is(":visible")).to.be.false; + }); + + it("should hide the add comments form when clicking to reply a comment", function () { + $section1.find('.marker').trigger('click'); + $section1.find('.add-comment').trigger('click'); + + $section1.find('.comments > li').first().find('.reply-comment').trigger('click'); + expect($section1.find('.comment-form').is(':visible')).to.be.false + }); + + it("should display the reply form when the reply button is clicked in a comment", function () { + $section1.find('.marker').trigger('click'); + $section1.find('.comments > li').first().find('.reply-comment').trigger('click'); + expect($section1.find('.comments > li').first().find('.reply-form').is(':visible')).to.be.true; + }); + it("should not have a link for comments that do not have a authorUrl", function(){ $section1.find('.marker').trigger('click'); var $authorName = $section1.find('.author-name').eq(2); @@ -278,7 +299,7 @@ describe("SideComments", function() { it("should update a non-empty section's comment list after adding", function(){ sideComments.insertComment(testCommentForSection(1)); - expect($section1.find('.comments li')).to.have.length.of(3); + expect($section1.find('.comments > li')).to.have.length.of(3); }); it("should update a non-empty section's comment count after adding", function(){ @@ -288,7 +309,7 @@ describe("SideComments", function() { it("should update an empty section's comment list after adding", function(){ sideComments.insertComment(testCommentForSection(2)); - expect($section2.find('.comments li')).to.have.length.of(1); + expect($section2.find('.comments > li')).to.have.length.of(1); }); it("should update an empty section's comment count after adding", function(){ @@ -306,12 +327,43 @@ describe("SideComments", function() { $section1.find('.add-comment').trigger('click'); $section1.find('.comment-box').val('Test Comment'); $section1.find('.action-link.post').trigger('click'); - var $lastCommentAuthor = $section1.find('.comments li').last().find('.author-name'); + var $lastCommentAuthor = $section1.find('.comments > li').last().find('.author-name'); expect($lastCommentAuthor.attr('href')).to.eq(currentUser.authorUrl); }); + + describe("Comment is a reply", function () { + + it("should emit an event when a reply is posted", function ( done ) { + this.timeout(0); + var eventFired = false; + + setTimeout( function () { + check( done, function() { + expect(eventFired).to.be.true; + } ) + }, 500); + + sideComments.on('commentPosted', function( comment ) { + eventFired = true; + }); + + $section1.find('.marker').trigger('click'); + $section1.find('.comments > li').first().find('.reply-comment').trigger('click'); + $section1.find('.comments > li').first().find('.comment-box').html(newTestComment.comment); + $section1.find('.comments > li').first().find('.action-link.post').trigger('click'); + }); + + it("should update a non-empty reply list after adding", function(){ + sideComments.insertComment(testCommentForSection(1, 88)); + expect($section1.find('.comments > li').first().find('.replies li')).to.have.length.of(2); + }); + + }); + }); + describe("Comment Deleting", function(){ beforeEach(function( done ) { @@ -344,7 +396,7 @@ describe("SideComments", function() { it("should update a section's comment list after deleting", function(){ sideComments.removeComment(1, 88); - expect($section1.find('.comments li')).to.have.length.of(1); + expect($section1.find('.comments > li')).to.have.length.of(1); }); it("should remove a section's comment count after deleting if it's the last comment", function(){ From 79031d3ad22c37f6d9324c156af8cdc0f2c89f0a Mon Sep 17 00:00:00 2001 From: Alexandre Date: Fri, 3 Oct 2014 01:36:25 -0300 Subject: [PATCH 2/2] Finish implementing comments reply (#17), including test coverage and basic styling --- css/themes/default.less | 8 ++- js/main.js | 10 +-- js/section.js | 83 +++++++++++++++++------ release/side-comments.js | 95 +++++++++++++++++++-------- release/side-comments.min.js | 2 +- release/themes/default-theme.css | 7 +- release/themes/default-theme.min.css | 2 +- support/images/cattelyn_stark.png | Bin 0 -> 14078 bytes support/test_data.js | 20 ++++++ templates/comment.html | 12 ++-- test/test_main.js | 85 ++++++++++++++++++++++-- 11 files changed, 258 insertions(+), 66 deletions(-) create mode 100644 support/images/cattelyn_stark.png diff --git a/css/themes/default.less b/css/themes/default.less index cc61468..08a7a78 100644 --- a/css/themes/default.less +++ b/css/themes/default.less @@ -220,9 +220,15 @@ .replies { - .author-name { + .right-of-avatar { width: @comments-wrapper-width - ( (@avatar-width + 10) * 2); } + + .delete { + display: inline-block; + float: left; + margin: 0; + } } } diff --git a/js/main.js b/js/main.js index b32f21d..6a64747 100644 --- a/js/main.js +++ b/js/main.js @@ -142,20 +142,22 @@ SideComments.prototype.replyComment = function( comment ) { * Removes the given comment from the right section. * @param sectionId The ID of the section where the comment exists. * @param commentId The ID of the comment to be removed. + * @param parentId The ID of the parent comment of the reply to be removed. Optional */ -SideComments.prototype.removeComment = function( sectionId, commentId ) { +SideComments.prototype.removeComment = function( sectionId, commentId, parentId ) { var section = _.find(this.sections, { id: sectionId }); - section.removeComment(commentId); + section.removeComment(commentId, parentId); }; /** * Delete the comment specified by the given sectionID and commentID. * @param sectionId The section the comment belongs to. * @param commentId The comment's ID + * @param parentId The parent comment's ID. Optional */ -SideComments.prototype.deleteComment = function( sectionId, commentId ) { +SideComments.prototype.deleteComment = function( sectionId, commentId, parentId ) { var section = _.find(this.sections, { id: sectionId }); - section.deleteComment(commentId); + section.deleteComment(commentId, parentId); }; /** diff --git a/js/section.js b/js/section.js index 682d3bd..2ffe127 100644 --- a/js/section.js +++ b/js/section.js @@ -149,18 +149,23 @@ Section.prototype.postCommentClick = function( event ) { * Post a comment to this section. */ Section.prototype.postComment = function() { - var $commentForm = this.$el.find('div[class*="-form"].active'); - var $commentBox = $commentForm.find('.comment-box'); - var commentBody = $commentBox.val(); - - var comment = { - sectionId: this.id, - comment: commentBody, - authorAvatarUrl: this.currentUser.avatarUrl, - authorName: this.currentUser.name, - authorId: this.currentUser.id, - authorUrl: this.currentUser.authorUrl || null - }; + if ( this.$el.find('.comments > li').length > 0 ){ + var $commentForm = this.$el.find('div[class*="-form"].active'); + } else { + var $commentForm = this.$el.find('div[class*="-form"]'); + } + + var $commentBox = $commentForm.find('.comment-box'), + commentBody = $commentBox.val(), + comment = { + sectionId: this.id, + comment: commentBody, + authorAvatarUrl: this.currentUser.avatarUrl, + authorName: this.currentUser.name, + authorId: this.currentUser.id, + authorUrl: this.currentUser.authorUrl || null, + replies: [] + }; if ( Number($commentForm.data('parent')) ) { comment.parentId = Number($commentForm.data('parent')); @@ -210,35 +215,71 @@ Section.prototype.updateCommentCount = function() { */ Section.prototype.deleteCommentClick = function( event ) { event.preventDefault(); - var commentId = $(event.target).closest('li').data('comment-id'); + var commentId = $(event.target).closest('li').data('comment-id'), + parentId = $(event.target).data('parent-id'); if (window.confirm("Are you sure you want to delete this comment?")) { - this.deleteComment(commentId); + this.deleteComment(commentId, parentId); } }; /** * Finds the comment and emits an event with the comment to be deleted. + * @param commentId ID of the comment to be deleted + * @param parentId ID of the parent comment of the reply to be deleted. Optional */ -Section.prototype.deleteComment = function( commentId ) { - var comment = _.find(this.comments, { id: commentId }); +Section.prototype.deleteComment = function( commentId, parentId ) { + if ( parentId != null ) { + var parent = _.find(this.comments, { id: parentId }), + comment = _.find(parent.replies, { id: commentId }); + } else { + var comment = _.find(this.comments, { id: commentId }); + } + comment.sectionId = this.id; this.eventPipe.emit('commentDeleted', comment); }; /** * Removes the comment from the list of comments and the comment array. - * @param commentId The ID of the comment to be removed from this section. + * @param commentId ID of the comment to be removed from this section + * @param parentId ID of the parent comment of the reply to be removed from this section. Optional */ -Section.prototype.removeComment = function( commentId ) { - this.comments = _.reject(this.comments, { id: commentId }); - this.$el.find('.side-comment .comments li[data-comment-id="'+commentId+'"]').remove(); - this.updateCommentCount(); +Section.prototype.removeComment = function( commentId, parentId ) { + + if ( parentId != null ) { + var comment = _.find(this.comments, { id: parentId }); + comment.replies = _.reject( comment.replies, { id: commentId }); + this.$el.find('.side-comment .comments > li[data-comment-id="'+parentId+'"] .replies li[data-comment-id="'+commentId+'"]').remove(); + } else { + var comment = _.find(this.comments, { id: commentId }); + + if ( comment.replies.length > 0 ) { + this.replaceCommentWithReplies( comment ); + } else { + this.comments = _.reject(this.comments, { id: commentId }); + this.$el.find('.side-comment .comments li[data-comment-id="'+commentId+'"]').remove(); + this.updateCommentCount(); + } + } + if (this.comments.length < 1) { this.$el.find('.side-comment').removeClass('has-comments'); } }; +/** + * Replace a comment with replies + * + * +*/ +Section.prototype.replaceCommentWithReplies = function ( comment ) { + var $commentEl = this.$el.find('.side-comment .comments > li[data-comment-id="'+ comment.id +'"] > .comment'); + + comment.deleted = true; + $commentEl.html('Comment deleted by the author'); +} + /** * Mark this section as selected. Delsect if this section is already selected. */ diff --git a/release/side-comments.js b/release/side-comments.js index 5e38a15..9658261 100644 --- a/release/side-comments.js +++ b/release/side-comments.js @@ -511,20 +511,22 @@ SideComments.prototype.replyComment = function( comment ) { * Removes the given comment from the right section. * @param sectionId The ID of the section where the comment exists. * @param commentId The ID of the comment to be removed. + * @param parentId The ID of the parent comment of the reply to be removed. Optional */ -SideComments.prototype.removeComment = function( sectionId, commentId ) { +SideComments.prototype.removeComment = function( sectionId, commentId, parentId ) { var section = _.find(this.sections, { id: sectionId }); - section.removeComment(commentId); + section.removeComment(commentId, parentId); }; /** * Delete the comment specified by the given sectionID and commentID. * @param sectionId The section the comment belongs to. * @param commentId The comment's ID + * @param parentId The parent comment's ID. Optional */ -SideComments.prototype.deleteComment = function( sectionId, commentId ) { +SideComments.prototype.deleteComment = function( sectionId, commentId, parentId ) { var section = _.find(this.sections, { id: sectionId }); - section.deleteComment(commentId); + section.deleteComment(commentId, parentId); }; /** @@ -736,18 +738,23 @@ Section.prototype.postCommentClick = function( event ) { * Post a comment to this section. */ Section.prototype.postComment = function() { - var $commentForm = this.$el.find('div[class*="-form"].active'); - var $commentBox = $commentForm.find('.comment-box'); - var commentBody = $commentBox.val(); - - var comment = { - sectionId: this.id, - comment: commentBody, - authorAvatarUrl: this.currentUser.avatarUrl, - authorName: this.currentUser.name, - authorId: this.currentUser.id, - authorUrl: this.currentUser.authorUrl || null - }; + if ( this.$el.find('.comments > li').length > 0 ){ + var $commentForm = this.$el.find('div[class*="-form"].active'); + } else { + var $commentForm = this.$el.find('div[class*="-form"]'); + } + + var $commentBox = $commentForm.find('.comment-box'), + commentBody = $commentBox.val(), + comment = { + sectionId: this.id, + comment: commentBody, + authorAvatarUrl: this.currentUser.avatarUrl, + authorName: this.currentUser.name, + authorId: this.currentUser.id, + authorUrl: this.currentUser.authorUrl || null, + replies: [] + }; if ( Number($commentForm.data('parent')) ) { comment.parentId = Number($commentForm.data('parent')); @@ -797,35 +804,71 @@ Section.prototype.updateCommentCount = function() { */ Section.prototype.deleteCommentClick = function( event ) { event.preventDefault(); - var commentId = $(event.target).closest('li').data('comment-id'); + var commentId = $(event.target).closest('li').data('comment-id'), + parentId = $(event.target).data('parent-id'); if (window.confirm("Are you sure you want to delete this comment?")) { - this.deleteComment(commentId); + this.deleteComment(commentId, parentId); } }; /** * Finds the comment and emits an event with the comment to be deleted. + * @param commentId ID of the comment to be deleted + * @param parentId ID of the parent comment of the reply to be deleted. Optional */ -Section.prototype.deleteComment = function( commentId ) { - var comment = _.find(this.comments, { id: commentId }); +Section.prototype.deleteComment = function( commentId, parentId ) { + if ( parentId != null ) { + var parent = _.find(this.comments, { id: parentId }), + comment = _.find(parent.replies, { id: commentId }); + } else { + var comment = _.find(this.comments, { id: commentId }); + } + comment.sectionId = this.id; this.eventPipe.emit('commentDeleted', comment); }; /** * Removes the comment from the list of comments and the comment array. - * @param commentId The ID of the comment to be removed from this section. + * @param commentId ID of the comment to be removed from this section + * @param parentId ID of the parent comment of the reply to be removed from this section. Optional */ -Section.prototype.removeComment = function( commentId ) { - this.comments = _.reject(this.comments, { id: commentId }); - this.$el.find('.side-comment .comments li[data-comment-id="'+commentId+'"]').remove(); - this.updateCommentCount(); +Section.prototype.removeComment = function( commentId, parentId ) { + + if ( parentId != null ) { + var comment = _.find(this.comments, { id: parentId }); + comment.replies = _.reject( comment.replies, { id: commentId }); + this.$el.find('.side-comment .comments > li[data-comment-id="'+parentId+'"] .replies li[data-comment-id="'+commentId+'"]').remove(); + } else { + var comment = _.find(this.comments, { id: commentId }); + + if ( comment.replies.length > 0 ) { + this.replaceCommentWithReplies( comment ); + } else { + this.comments = _.reject(this.comments, { id: commentId }); + this.$el.find('.side-comment .comments li[data-comment-id="'+commentId+'"]').remove(); + this.updateCommentCount(); + } + } + if (this.comments.length < 1) { this.$el.find('.side-comment').removeClass('has-comments'); } }; +/** + * Replace a comment with replies + * + * +*/ +Section.prototype.replaceCommentWithReplies = function ( comment ) { + var $commentEl = this.$el.find('.side-comment .comments > li[data-comment-id="'+ comment.id +'"] > .comment'); + + comment.deleted = true; + $commentEl.html('Comment deleted by the author'); +} + /** * Mark this section as selected. Delsect if this section is already selected. */ @@ -3304,7 +3347,7 @@ require.register("side-comments/templates/form.html", function(exports, require, module.exports = '
    \n
    \n \n
    \n

    \n <%= currentUser.name %>\n

    \n \n
    \n Post\n Cancel\n
    \n
    '; }); require.register("side-comments/templates/comment.html", function(exports, require, module){ -module.exports = '
  • \n
    \n \n
    \n <% if (comment.authorUrl) { %>\n \n <%= comment.authorName %>\n \n <% } else { %>\n

    \n <%= comment.authorName %>\n

    \n <% } %>\n

    \n <%= comment.comment %>\n

    \n\n <% if ( comment.parentId === undefined ) { %>\n \n
      \n <% _.each(comment.replies, function ( reply ) {%>\n <%= _.template(self, { comment: reply, currentUser: currentUser, formTemplate: formTemplate }) %>\n <% });%>\n
    \n\n <% if (currentUser){ %>\n Reply\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'reply-form\', commentId: comment.id })%>\n <% if (comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n <% } %>\n\n <% } %>\n\n <% if (currentUser && comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n\n
  • '; +module.exports = '
  • \n
    \n \n
    \n <% if (comment.authorUrl) { %>\n \n <%= comment.authorName %>\n \n <% } else { %>\n

    \n <%= comment.authorName %>\n

    \n <% } %>\n

    \n <%= (comment.deleted != null && comment.deleted) ? "Comment deleted by the author" : comment.comment %>\n

    \n\n <% if ( comment.parentId == null ) { %>\n \n
      \n <% _.each(comment.replies, function ( reply ) {%>\n <%= _.template(self, { comment: reply, currentUser: currentUser, formTemplate: formTemplate }) %>\n <% });%>\n
    \n\n <% if (currentUser){ %>\n Reply\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'reply-form\', commentId: comment.id })%>\n <% if (comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n <% } %>\n\n <% } else { %>\n\n <% if (currentUser && comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n\n <% } %>\n\n
  • '; }); require.alias("component-emitter/index.js", "side-comments/deps/emitter/index.js"); require.alias("component-emitter/index.js", "emitter/index.js"); diff --git a/release/side-comments.min.js b/release/side-comments.min.js index 773a96a..8f2c9f9 100644 --- a/release/side-comments.min.js +++ b/release/side-comments.min.js @@ -1 +1 @@ -function require(e,t,n){var r=require.resolve(e);if(null==r){n=n||e,t=t||"root";var o=new Error('Failed to require "'+n+'" from "'+t+'"');throw o.path=n,o.parent=t,o.require=!0,o}var i=require.modules[r];if(!i._resolving&&!i.exports){var s={};s.exports={},s.client=s.component=!0,i._resolving=!0,i.call(this,s.exports,require.relative(r),s),delete i._resolving,i.exports=s.exports}return i.exports}require.modules={},require.aliases={},require.resolve=function(e){"/"===e.charAt(0)&&(e=e.slice(1));for(var t=[e,e+".js",e+".json",e+"/index.js",e+"/index.json"],n=0;nr;++r)n[r].apply(this,t)}return this},r.prototype.listeners=function(e){return this._callbacks=this._callbacks||{},this._callbacks[e]||[]},r.prototype.hasListeners=function(e){return!!this.listeners(e).length}}),require.register("side-comments/js/main.js",function(e,t,n){function r(e,t,n){this.$el=a(e),this.$body=a("body"),this.eventPipe=new s,this.currentUser=o.clone(t)||null,this.existingComments=o.cloneDeep(n)||[],this.sections=[],this.activeSection=null,this.eventPipe.on("showComments",o.bind(this.showComments,this)),this.eventPipe.on("hideComments",o.bind(this.hideComments,this)),this.eventPipe.on("sectionSelected",o.bind(this.sectionSelected,this)),this.eventPipe.on("sectionDeselected",o.bind(this.sectionDeselected,this)),this.eventPipe.on("commentPosted",o.bind(this.commentPosted,this)),this.eventPipe.on("commentDeleted",o.bind(this.commentDeleted,this)),this.eventPipe.on("addCommentAttempted",o.bind(this.addCommentAttempted,this)),this.$body.on("click",o.bind(this.bodyClick,this)),this.initialize(this.existingComments)}var o=t("./vendor/lodash-custom.js"),i=t("./section.js"),s=t("emitter"),a=jQuery;s(r.prototype),r.prototype.initialize=function(){o.each(this.$el.find(".commentable-section"),function(e){var t=a(e),n=t.data("section-id").toString(),r=o.find(this.existingComments,{sectionId:n});this.sections.push(new i(this.eventPipe,t,this.currentUser,r))},this)},r.prototype.showComments=function(){this.$el.addClass("side-comments-open")},r.prototype.hideComments=function(){this.activeSection&&(this.activeSection.deselect(),this.activeSection=null),this.$el.removeClass("side-comments-open")},r.prototype.sectionSelected=function(e){this.showComments(),this.activeSection&&this.activeSection.deselect(),this.activeSection=e},r.prototype.sectionDeselected=function(){this.hideComments(),this.activeSection=null},r.prototype.commentPosted=function(e){this.emit("commentPosted",e)},r.prototype.commentDeleted=function(e){this.emit("commentDeleted",e)},r.prototype.addCommentAttempted=function(){this.emit("addCommentAttempted")},r.prototype.insertComment=function(e){var t=o.find(this.sections,{id:e.sectionId});t.insertComment(e)},r.prototype.replyComment=function(e){var t=o.find(this.sections,{id:e.sectionId});t.insertComment(e)},r.prototype.removeComment=function(e,t){var n=o.find(this.sections,{id:e});n.removeComment(t)},r.prototype.deleteComment=function(e,t){var n=o.find(this.sections,{id:e});n.deleteComment(t)},r.prototype.commentsAreVisible=function(){return this.$el.hasClass("side-comments-open")},r.prototype.bodyClick=function(e){var t=a(e.target);t.closest(".side-comment").length<1&&t.closest("body").length>0&&(this.activeSection&&this.activeSection.deselect(),this.hideComments())},r.prototype.setCurrentUser=function(e){this.hideComments(),this.currentUser=e,o.each(this.sections,o.bind(function(e){e.currentUser=this.currentUser,e.render()},this))},r.prototype.removeCurrentUser=function(){this.setCurrentUser(null)},r.prototype.destroy=function(){this.hideComments(),this.$el.off()},n.exports=r}),require.register("side-comments/js/section.js",function(e,t,n){function r(e,t,n,r){this.eventPipe=e,this.$el=t,this.comments=r?r.comments:[],this.currentUser=n||null,this.clickEventName=c()?"touchstart":"click",this.id=t.data("section-id"),this.$el.on(this.clickEventName,".side-comment .marker",o.bind(this.markerClick,this)),this.$el.on(this.clickEventName,".side-comment .add-comment",o.bind(this.addCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .reply-comment",o.bind(this.replyCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .post",o.bind(this.postCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .cancel",o.bind(this.cancelCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .delete",o.bind(this.deleteCommentClick,this)),this.render()}var o=t("./vendor/lodash-custom.js"),i=t("../templates/section.html"),s=t("../templates/comment.html"),a=t("../templates/form.html"),c=t("./helpers/mobile-check.js"),l=jQuery;r.prototype.markerClick=function(e){e.preventDefault(),this.select()},r.prototype.addCommentClick=function(e){e.preventDefault(),this.currentUser?this.showCommentForm():this.eventPipe.emit("addCommentAttempted")},r.prototype.showCommentForm=function(){this.comments.length>0&&(this.hideCommentForm(),this.$el.find(".add-comment").addClass("hide"),this.$el.find(".comment-form").addClass("active")),this.focusCommentBox()},r.prototype.replyCommentClick=function(e){e.preventDefault(),this.currentUser?this.showReplyForm(e.currentTarget):this.eventPipe.emit("addCommentAttempted")},r.prototype.showReplyForm=function(e){this.comments.length>0&&(this.hideCommentForm(),this.$el.find(e).addClass("hide"),$form=l(o.find(l.makeArray(this.$el.find(".reply-form")),function(t){return t.dataset.parent===e.dataset.comment})),$form.addClass("active")),this.focusCommentBox()},r.prototype.hideCommentForm=function(){this.comments.length>0&&(this.$el.find('a[class*="-comment"]').removeClass("hide"),this.$el.find('div[class*="-form"]').removeClass("active")),this.$el.find(".comment-box").empty()},r.prototype.focusCommentBox=function(){setTimeout(o.bind(function(){this.$el.find(".comment-box").get(0).focus()},this),300)},r.prototype.cancelCommentClick=function(e){e.preventDefault(),this.cancelComment()},r.prototype.cancelComment=function(){this.comments.length>0?this.hideCommentForm():(this.deselect(),this.eventPipe.emit("hideComments"))},r.prototype.postCommentClick=function(e){e.preventDefault(),this.postComment()},r.prototype.postComment=function(){var e=this.$el.find('div[class*="-form"].active'),t=e.find(".comment-box"),n=t.val(),r={sectionId:this.id,comment:n,authorAvatarUrl:this.currentUser.avatarUrl,authorName:this.currentUser.name,authorId:this.currentUser.id,authorUrl:this.currentUser.authorUrl||null};Number(e.data("parent"))&&(r.parentId=Number(e.data("parent"))),t.val(""),this.eventPipe.emit("commentPosted",r)},r.prototype.insertComment=function(e){var t=o.template(s,{comment:e,currentUser:this.currentUser,formTemplate:a,self:s});void 0!==e.parentId?(o.find(this.comments,{id:e.parentId}).replies.push(e),$parent=l(o.find(l.makeArray(this.$el.find(".comments > li")),function(t){return t.dataset.commentId==e.parentId})),$parent.find(".replies").append(t)):(this.comments.push(e),this.$el.find(".comments").append(t)),this.$el.find(".side-comment").addClass("has-comments"),this.updateCommentCount(),this.hideCommentForm()},r.prototype.updateCommentCount=function(){this.$el.find(".marker span").text(this.comments.length)},r.prototype.deleteCommentClick=function(e){e.preventDefault();var t=l(e.target).closest("li").data("comment-id");window.confirm("Are you sure you want to delete this comment?")&&this.deleteComment(t)},r.prototype.deleteComment=function(e){var t=o.find(this.comments,{id:e});t.sectionId=this.id,this.eventPipe.emit("commentDeleted",t)},r.prototype.removeComment=function(e){this.comments=o.reject(this.comments,{id:e}),this.$el.find('.side-comment .comments li[data-comment-id="'+e+'"]').remove(),this.updateCommentCount(),this.comments.length<1&&this.$el.find(".side-comment").removeClass("has-comments")},r.prototype.select=function(){this.isSelected()?(this.deselect(),this.eventPipe.emit("sectionDeselected",this)):(this.$el.find(".side-comment").addClass("active"),0===this.comments.length&&this.currentUser&&this.focusCommentBox(),this.eventPipe.emit("sectionSelected",this))},r.prototype.deselect=function(){this.$el.find(".side-comment").removeClass("active"),this.hideCommentForm()},r.prototype.isSelected=function(){return this.$el.find(".side-comment").hasClass("active")},r.prototype.sectionClasses=function(){var e="";return this.comments.length>0&&(e+=" has-comments"),this.currentUser||(e+=" no-current-user"),e},r.prototype.render=function(){this.$el.find(".side-comment").remove(),l(o.template(i,{commentTemplate:s,comments:this.comments,sectionClasses:this.sectionClasses(),formTemplate:a,currentUser:this.currentUser})).appendTo(this.$el)},r.prototype.destroy=function(){this.$el.off()},n.exports=r}),require.register("side-comments/js/vendor/lodash-custom.js",function(e,t,n){(function(){function t(e){return"\\"+ht[e]}function r(){return N.pop()||[]}function o(e){return"function"!=typeof e.toString&&"string"==typeof(e+"")}function i(e){e.length=0,N.lengtho?0:o);++r-1:void 0});return a.pop(),c.pop(),k&&(i(a),i(c)),l}function f(e,t,n,r,o,i){var a=1&t,l=2&t,m=4&t,u=16&t,h=32&t;if(!l&&!x(e))throw new TypeError;u&&!n.length&&(t&=-17,u=n=!1),h&&!r.length&&(t&=-33,h=r=!1);var d=e&&e.__bindData__;if(d&&d!==!0)return d=s(d),d[2]&&(d[2]=s(d[2])),d[3]&&(d[3]=s(d[3])),!a||1&d[1]||(d[4]=o),!a&&1&d[1]&&(t|=8),!m||4&d[1]||(d[5]=i),u&&$t.apply(d[2]||(d[2]=[]),n),h&&Ut.apply(d[3]||(d[3]=[]),r),d[1]|=t,f.apply(null,d);var v=1==t||17===t?c:p;return v([e,t,n,r,o,i])}function d(){ut.shadowedProps=X,ut.array=ut.bottom=ut.loop=ut.top="",ut.init="iterable",ut.useHas=!0;for(var e,t=0;e=arguments[t];t++)for(var n in e)ut[n]=e[n];var r=ut.args;ut.firstArg=/^[^,]+/.exec(r)[0];var o=Function("baseCreateCallback, errorClass, errorProto, hasOwnProperty, indicatorObject, isArguments, isArray, isString, keys, objectProto, objectTypes, nonEnumProps, stringClass, stringProto, toString","return function("+r+") {\n"+Lt(ut)+"\n}");return o(u,rt,Ct,Pt,F,y,Ft,_,ut.keys,kt,pt,Dt,ct,xt,wt)}function v(e){return Vt[e]}function g(e){return"function"==typeof e&&_t.test(e)}function y(e){return e&&"object"==typeof e&&"number"==typeof e.length&&wt.call(e)==Z||!1}function b(e,t,n,r){return"boolean"!=typeof t&&null!=t&&(r=n,n=t,t=!1),l(e,t,"function"==typeof n&&u(n,r,1))}function C(e,t,n){return l(e,!0,"function"==typeof t&&u(t,n,1))}function x(e){return"function"==typeof e}function w(e){return!(!e||!pt[typeof e])}function _(e){return"string"==typeof e||e&&"object"==typeof e&&wt.call(e)==ct||!1}function j(e){for(var t=-1,n=Rt(e),r=n.length,o=Array(r);++t2?f(e,17,s(arguments,2),null,t):f(e,1,null,null,t)}function E(e,t,n){var r=typeof e;if(null==e||"function"==r)return u(e,t,n);if("object"!=r)return D(e);var o=Rt(e),i=o[0],s=e[i];return 1!=o.length||s!==s||w(s)?function(t){for(var n=o.length,r=!1;n--&&(r=h(t[o[n]],e[o[n]],null,!0)););return r}:function(e){var t=e[i];return s===t&&(0!==s||1/s==1/t)}}function q(e){return null==e?"":String(e).replace(Wt,v)}function O(e){return e}function I(){}function D(e){return function(t){return t[e]}}function T(e,n,r){var o=a.templateSettings;e=String(e||""),r=Kt({},r,o);var i,s=Kt({},r.imports,o.imports),c=Rt(s),l=j(s),m=0,u=r.interpolate||J,p="__p += '",h=RegExp((r.escape||J).source+"|"+u.source+"|"+(u===G?Q:J).source+"|"+(r.evaluate||J).source+"|$","g");e.replace(h,function(n,r,o,s,a,c){return o||(o=s),p+=e.slice(m,c).replace(M,t),r&&(p+="' +\n__e("+r+") +\n'"),a&&(i=!0,p+="';\n"+a+";\n__p += '"),o&&(p+="' +\n((__t = ("+o+")) == null ? '' : __t) +\n'"),m=c+n.length,n}),p+="';\n";var f=r.variable,d=f;d||(f="obj",p="with ("+f+") {\n"+p+"\n}\n"),p=(i?p.replace(R,""):p).replace(B,"$1").replace(H,"$1;"),p="function("+f+") {\n"+(d?"":f+" || ("+f+" = {});\n")+"var __t, __p = '', __e = _.escape"+(i?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+p+"return __p\n}";var v="\n/*\n//# sourceURL="+(r.sourceURL||"/lodash/template/source["+Y++ +"]")+"\n*/";try{var g=Function(c,"return "+p+v).apply(L,l)}catch(y){throw y.source=p,y}return n?g(n):(g.source=p,g)}var L,N=[],F={},z=40,R=/\b__p \+= '';/g,B=/\b(__p \+=) '' \+/g,H=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Q=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,V=/\w*$/,W=/^\s*function[ \n\r\t]+\w/,G=/<%=([\s\S]+?)%>/g,J=/($^)/,K=/\bthis\b/,M=/['\n\r\t\u2028\u2029\\]/g,X=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Y=0,Z="[object Arguments]",et="[object Array]",tt="[object Boolean]",nt="[object Date]",rt="[object Error]",ot="[object Function]",it="[object Number]",st="[object Object]",at="[object RegExp]",ct="[object String]",lt={};lt[ot]=!1,lt[Z]=lt[et]=lt[tt]=lt[nt]=lt[it]=lt[st]=lt[at]=lt[ct]=!0;var mt={configurable:!1,enumerable:!1,value:null,writable:!1},ut={args:"",array:null,bottom:"",firstArg:"",init:"",keys:null,loop:"",shadowedProps:null,support:null,top:"",useHas:!1},pt={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},ht={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},ft=pt[typeof window]&&window||this,dt=pt[typeof e]&&e&&!e.nodeType&&e,vt=pt[typeof n]&&n&&!n.nodeType&&n,gt=vt&&vt.exports===dt&&dt,yt=pt[typeof global]&&global;!yt||yt.global!==yt&&yt.window!==yt||(ft=yt);var bt=[],Ct=Error.prototype,kt=Object.prototype,xt=String.prototype,wt=kt.toString,_t=RegExp("^"+String(wt).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),jt=Function.prototype.toString,Pt=kt.hasOwnProperty,$t=bt.push,St=kt.propertyIsEnumerable,Ut=bt.unshift,At=function(){try{var e={},t=g(t=Object.defineProperty)&&t,n=t(e,e,e)&&t}catch(r){}return n}(),Et=g(Et=Object.create)&&Et,qt=g(qt=Array.isArray)&&qt,Ot=g(Ot=Object.keys)&&Ot,It={};It[et]=Array,It[tt]=Boolean,It[nt]=Date,It[ot]=Function,It[st]=Object,It[it]=Number,It[at]=RegExp,It[ct]=String;var Dt={};Dt[et]=Dt[nt]=Dt[it]={constructor:!0,toLocaleString:!0,toString:!0,valueOf:!0},Dt[tt]=Dt[ct]={constructor:!0,toString:!0,valueOf:!0},Dt[rt]=Dt[ot]=Dt[at]={constructor:!0,toString:!0},Dt[st]={constructor:!0},function(){for(var e=X.length;e--;){var t=X[e];for(var n in Dt)Pt.call(Dt,n)&&!Pt.call(Dt[n],t)&&(Dt[n][t]=!1)}}();var Tt=a.support={};!function(){var e=function(){this.x=1},t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments);Tt.argsClass=wt.call(arguments)==Z,Tt.argsObject=arguments.constructor==Object&&!(arguments instanceof Array),Tt.enumErrorProps=St.call(Ct,"message")||St.call(Ct,"name"),Tt.enumPrototypes=St.call(e,"prototype"),Tt.funcDecomp=!g(ft.WinRTError)&&K.test(function(){return this}),Tt.funcNames="string"==typeof Function.name,Tt.nonEnumArgs=0!=r,Tt.nonEnumShadows=!/valueOf/.test(n),Tt.spliceObjects=(bt.splice.call(t,0,1),!t[0]),Tt.unindexedChars="x"[0]+Object("x")[0]!="xx";try{Tt.nodeClass=!(wt.call(document)==st&&!({toString:0}+""))}catch(o){Tt.nodeClass=!0}}(1),a.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:G,variable:"",imports:{_:a}};var Lt=function(e){var t="var index, iterable = "+e.firstArg+", result = "+e.init+";\nif (!iterable) return result;\n"+e.top+";";e.array?(t+="\nvar length = iterable.length; index = -1;\nif ("+e.array+") { ",Tt.unindexedChars&&(t+="\n if (isString(iterable)) {\n iterable = iterable.split('')\n } "),t+="\n while (++index < length) {\n "+e.loop+";\n }\n}\nelse { "):Tt.nonEnumArgs&&(t+="\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += '';\n "+e.loop+";\n }\n } else { "),Tt.enumPrototypes&&(t+="\n var skipProto = typeof iterable == 'function';\n "),Tt.enumErrorProps&&(t+="\n var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n ");var n=[];if(Tt.enumPrototypes&&n.push('!(skipProto && index == "prototype")'),Tt.enumErrorProps&&n.push('!(skipErrorProps && (index == "message" || index == "name"))'),e.useHas&&e.keys)t+="\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] && keys(iterable),\n length = ownProps ? ownProps.length : 0;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n",n.length&&(t+=" if ("+n.join(" && ")+") {\n "),t+=e.loop+"; ",n.length&&(t+="\n }"),t+="\n } ";else if(t+="\n for (index in iterable) {\n",e.useHas&&n.push("hasOwnProperty.call(iterable, index)"),n.length&&(t+=" if ("+n.join(" && ")+") {\n "),t+=e.loop+"; ",n.length&&(t+="\n }"),t+="\n } ",Tt.nonEnumShadows){for(t+="\n\n if (iterable !== objectProto) {\n var ctor = iterable.constructor,\n isProto = iterable === (ctor && ctor.prototype),\n className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n nonEnum = nonEnumProps[className];\n ",k=0;7>k;k++)t+="\n index = '"+e.shadowedProps[k]+"';\n if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))",e.useHas||(t+=" || (!nonEnum[index] && iterable[index] !== objectProto[index])"),t+=") {\n "+e.loop+";\n } ";t+="\n } "}return(e.array||Tt.nonEnumArgs)&&(t+="\n}"),t+=e.bottom+";\nreturn result"};Et||(m=function(){function e(){}return function(t){if(w(t)){e.prototype=t;var n=new e;e.prototype=null}return n||ft.Object()}}());var Nt=At?function(e,t){mt.value=t,At(e,"__bindData__",mt)}:I;Tt.argsClass||(y=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&Pt.call(e,"callee")&&!St.call(e,"callee")||!1});var Ft=qt||function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&wt.call(e)==et||!1},zt=d({args:"object",init:"[]",top:"if (!(objectTypes[typeof object])) return result",loop:"result.push(index)"}),Rt=Ot?function(e){return w(e)?Tt.enumPrototypes&&"function"==typeof e||Tt.nonEnumArgs&&e.length&&y(e)?zt(e):Ot(e):[]}:zt,Bt={args:"collection, callback, thisArg",top:"callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",array:"typeof length == 'number'",keys:Rt,loop:"if (callback(iterable[index], index, collection) === false) return result"},Ht={args:"object, source, guard",top:"var args = arguments,\n argsIndex = 0,\n argsLength = typeof guard == 'number' ? 2 : args.length;\nwhile (++argsIndex < argsLength) {\n iterable = args[argsIndex];\n if (iterable && objectTypes[typeof iterable]) {",keys:Rt,loop:"if (typeof result[index] == 'undefined') result[index] = iterable[index]",bottom:" }\n}"},Qt={top:"if (!objectTypes[typeof iterable]) return result;\n"+Bt.top,array:!1},Vt={"&":"&","<":"<",">":">",'"':""","'":"'"},Wt=RegExp("["+Rt(Vt).join("")+"]","g"),Gt=d(Bt),Jt=d(Ht,{top:Ht.top.replace(";",";\nif (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n callback = args[--argsLength];\n}"),loop:"result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]"}),Kt=d(Ht),Mt=d(Bt,Qt,{useHas:!1}),Xt=d(Bt,Qt);x(/x/)&&(x=function(e){return"function"==typeof e&&wt.call(e)==ot}),a.assign=Jt,a.bind=A,a.createCallback=E,a.defaults=Kt,a.filter=P,a.forEach=S,a.forIn=Mt,a.forOwn=Xt,a.keys=Rt,a.property=D,a.reject=U,a.values=j,a.each=S,a.extend=Jt,a.select=P,a.clone=b,a.cloneDeep=C,a.escape=q,a.find=$,a.identity=O,a.isArguments=y,a.isArray=Ft,a.isFunction=x,a.isObject=w,a.isString=_,a.noop=I,a.template=T,a.detect=$,a.findWhere=$,a.VERSION="2.4.1",dt&&vt&&(gt?(vt.exports=a)._=a:dt._=a)}).call(this)}),require.register("side-comments/js/helpers/mobile-check.js",function(e,t,n){n.exports=function(){var e=!1;return function(t){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|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(t)||/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(t.substr(0,4)))&&(e=!0)}(navigator.userAgent||navigator.vendor||window.opera),e}}),require.register("side-comments/templates/section.html",function(e,t,n){n.exports='
    \n \n <%= comments.length %>\n \n \n
    \n
      \n <% _.each(comments, function( comment ){ %>\n <%= _.template(commentTemplate, { comment: comment, currentUser: currentUser, formTemplate: formTemplate, self: commentTemplate }) %>\n <% }) %>\n
    \n \n Leave a comment\n <% if (currentUser) { %>\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'comment-form\', commentId: null }) %>\n <% } %>\n
    \n
    '}),require.register("side-comments/templates/form.html",function(e,t,n){n.exports='
    \n
    \n \n
    \n

    \n <%= currentUser.name %>\n

    \n \n
    \n Post\n Cancel\n
    \n
    '}),require.register("side-comments/templates/comment.html",function(e,t,n){n.exports='
  • \n
    \n \n
    \n <% if (comment.authorUrl) { %>\n \n <%= comment.authorName %>\n \n <% } else { %>\n

    \n <%= comment.authorName %>\n

    \n <% } %>\n

    \n <%= comment.comment %>\n

    \n\n <% if ( comment.parentId === undefined ) { %>\n \n
      \n <% _.each(comment.replies, function ( reply ) {%>\n <%= _.template(self, { comment: reply, currentUser: currentUser, formTemplate: formTemplate }) %>\n <% });%>\n
    \n\n <% if (currentUser){ %>\n Reply\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'reply-form\', commentId: comment.id })%>\n <% if (comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n <% } %>\n\n <% } %>\n\n <% if (currentUser && comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n\n
  • '}),require.alias("component-emitter/index.js","side-comments/deps/emitter/index.js"),require.alias("component-emitter/index.js","emitter/index.js"),require.alias("side-comments/js/main.js","side-comments/index.js"); \ No newline at end of file +function require(e,t,n){var r=require.resolve(e);if(null==r){n=n||e,t=t||"root";var o=new Error('Failed to require "'+n+'" from "'+t+'"');throw o.path=n,o.parent=t,o.require=!0,o}var i=require.modules[r];if(!i._resolving&&!i.exports){var s={};s.exports={},s.client=s.component=!0,i._resolving=!0,i.call(this,s.exports,require.relative(r),s),delete i._resolving,i.exports=s.exports}return i.exports}require.modules={},require.aliases={},require.resolve=function(e){"/"===e.charAt(0)&&(e=e.slice(1));for(var t=[e,e+".js",e+".json",e+"/index.js",e+"/index.json"],n=0;nr;++r)n[r].apply(this,t)}return this},r.prototype.listeners=function(e){return this._callbacks=this._callbacks||{},this._callbacks[e]||[]},r.prototype.hasListeners=function(e){return!!this.listeners(e).length}}),require.register("side-comments/js/main.js",function(e,t,n){function r(e,t,n){this.$el=a(e),this.$body=a("body"),this.eventPipe=new s,this.currentUser=o.clone(t)||null,this.existingComments=o.cloneDeep(n)||[],this.sections=[],this.activeSection=null,this.eventPipe.on("showComments",o.bind(this.showComments,this)),this.eventPipe.on("hideComments",o.bind(this.hideComments,this)),this.eventPipe.on("sectionSelected",o.bind(this.sectionSelected,this)),this.eventPipe.on("sectionDeselected",o.bind(this.sectionDeselected,this)),this.eventPipe.on("commentPosted",o.bind(this.commentPosted,this)),this.eventPipe.on("commentDeleted",o.bind(this.commentDeleted,this)),this.eventPipe.on("addCommentAttempted",o.bind(this.addCommentAttempted,this)),this.$body.on("click",o.bind(this.bodyClick,this)),this.initialize(this.existingComments)}var o=t("./vendor/lodash-custom.js"),i=t("./section.js"),s=t("emitter"),a=jQuery;s(r.prototype),r.prototype.initialize=function(){o.each(this.$el.find(".commentable-section"),function(e){var t=a(e),n=t.data("section-id").toString(),r=o.find(this.existingComments,{sectionId:n});this.sections.push(new i(this.eventPipe,t,this.currentUser,r))},this)},r.prototype.showComments=function(){this.$el.addClass("side-comments-open")},r.prototype.hideComments=function(){this.activeSection&&(this.activeSection.deselect(),this.activeSection=null),this.$el.removeClass("side-comments-open")},r.prototype.sectionSelected=function(e){this.showComments(),this.activeSection&&this.activeSection.deselect(),this.activeSection=e},r.prototype.sectionDeselected=function(){this.hideComments(),this.activeSection=null},r.prototype.commentPosted=function(e){this.emit("commentPosted",e)},r.prototype.commentDeleted=function(e){this.emit("commentDeleted",e)},r.prototype.addCommentAttempted=function(){this.emit("addCommentAttempted")},r.prototype.insertComment=function(e){var t=o.find(this.sections,{id:e.sectionId});t.insertComment(e)},r.prototype.replyComment=function(e){var t=o.find(this.sections,{id:e.sectionId});t.insertComment(e)},r.prototype.removeComment=function(e,t,n){var r=o.find(this.sections,{id:e});r.removeComment(t,n)},r.prototype.deleteComment=function(e,t,n){var r=o.find(this.sections,{id:e});r.deleteComment(t,n)},r.prototype.commentsAreVisible=function(){return this.$el.hasClass("side-comments-open")},r.prototype.bodyClick=function(e){var t=a(e.target);t.closest(".side-comment").length<1&&t.closest("body").length>0&&(this.activeSection&&this.activeSection.deselect(),this.hideComments())},r.prototype.setCurrentUser=function(e){this.hideComments(),this.currentUser=e,o.each(this.sections,o.bind(function(e){e.currentUser=this.currentUser,e.render()},this))},r.prototype.removeCurrentUser=function(){this.setCurrentUser(null)},r.prototype.destroy=function(){this.hideComments(),this.$el.off()},n.exports=r}),require.register("side-comments/js/section.js",function(e,t,n){function r(e,t,n,r){this.eventPipe=e,this.$el=t,this.comments=r?r.comments:[],this.currentUser=n||null,this.clickEventName=c()?"touchstart":"click",this.id=t.data("section-id"),this.$el.on(this.clickEventName,".side-comment .marker",o.bind(this.markerClick,this)),this.$el.on(this.clickEventName,".side-comment .add-comment",o.bind(this.addCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .reply-comment",o.bind(this.replyCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .post",o.bind(this.postCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .cancel",o.bind(this.cancelCommentClick,this)),this.$el.on(this.clickEventName,".side-comment .delete",o.bind(this.deleteCommentClick,this)),this.render()}var o=t("./vendor/lodash-custom.js"),i=t("../templates/section.html"),s=t("../templates/comment.html"),a=t("../templates/form.html"),c=t("./helpers/mobile-check.js"),l=jQuery;r.prototype.markerClick=function(e){e.preventDefault(),this.select()},r.prototype.addCommentClick=function(e){e.preventDefault(),this.currentUser?this.showCommentForm():this.eventPipe.emit("addCommentAttempted")},r.prototype.showCommentForm=function(){this.comments.length>0&&(this.hideCommentForm(),this.$el.find(".add-comment").addClass("hide"),this.$el.find(".comment-form").addClass("active")),this.focusCommentBox()},r.prototype.replyCommentClick=function(e){e.preventDefault(),this.currentUser?this.showReplyForm(e.currentTarget):this.eventPipe.emit("addCommentAttempted")},r.prototype.showReplyForm=function(e){this.comments.length>0&&(this.hideCommentForm(),this.$el.find(e).addClass("hide"),$form=l(o.find(l.makeArray(this.$el.find(".reply-form")),function(t){return t.dataset.parent===e.dataset.comment})),$form.addClass("active")),this.focusCommentBox()},r.prototype.hideCommentForm=function(){this.comments.length>0&&(this.$el.find('a[class*="-comment"]').removeClass("hide"),this.$el.find('div[class*="-form"]').removeClass("active")),this.$el.find(".comment-box").empty()},r.prototype.focusCommentBox=function(){setTimeout(o.bind(function(){this.$el.find(".comment-box").get(0).focus()},this),300)},r.prototype.cancelCommentClick=function(e){e.preventDefault(),this.cancelComment()},r.prototype.cancelComment=function(){this.comments.length>0?this.hideCommentForm():(this.deselect(),this.eventPipe.emit("hideComments"))},r.prototype.postCommentClick=function(e){e.preventDefault(),this.postComment()},r.prototype.postComment=function(){if(this.$el.find(".comments > li").length>0)var e=this.$el.find('div[class*="-form"].active');else var e=this.$el.find('div[class*="-form"]');var t=e.find(".comment-box"),n=t.val(),r={sectionId:this.id,comment:n,authorAvatarUrl:this.currentUser.avatarUrl,authorName:this.currentUser.name,authorId:this.currentUser.id,authorUrl:this.currentUser.authorUrl||null,replies:[]};Number(e.data("parent"))&&(r.parentId=Number(e.data("parent"))),t.val(""),this.eventPipe.emit("commentPosted",r)},r.prototype.insertComment=function(e){var t=o.template(s,{comment:e,currentUser:this.currentUser,formTemplate:a,self:s});void 0!==e.parentId?(o.find(this.comments,{id:e.parentId}).replies.push(e),$parent=l(o.find(l.makeArray(this.$el.find(".comments > li")),function(t){return t.dataset.commentId==e.parentId})),$parent.find(".replies").append(t)):(this.comments.push(e),this.$el.find(".comments").append(t)),this.$el.find(".side-comment").addClass("has-comments"),this.updateCommentCount(),this.hideCommentForm()},r.prototype.updateCommentCount=function(){this.$el.find(".marker span").text(this.comments.length)},r.prototype.deleteCommentClick=function(e){e.preventDefault();var t=l(e.target).closest("li").data("comment-id"),n=l(e.target).data("parent-id");window.confirm("Are you sure you want to delete this comment?")&&this.deleteComment(t,n)},r.prototype.deleteComment=function(e,t){if(null!=t)var n=o.find(this.comments,{id:t}),r=o.find(n.replies,{id:e});else var r=o.find(this.comments,{id:e});r.sectionId=this.id,this.eventPipe.emit("commentDeleted",r)},r.prototype.removeComment=function(e,t){if(null!=t){var n=o.find(this.comments,{id:t});n.replies=o.reject(n.replies,{id:e}),this.$el.find('.side-comment .comments > li[data-comment-id="'+t+'"] .replies li[data-comment-id="'+e+'"]').remove()}else{var n=o.find(this.comments,{id:e});n.replies.length>0?this.replaceCommentWithReplies(n):(this.comments=o.reject(this.comments,{id:e}),this.$el.find('.side-comment .comments li[data-comment-id="'+e+'"]').remove(),this.updateCommentCount())}this.comments.length<1&&this.$el.find(".side-comment").removeClass("has-comments")},r.prototype.replaceCommentWithReplies=function(e){var t=this.$el.find('.side-comment .comments > li[data-comment-id="'+e.id+'"] > .comment');e.deleted=!0,t.html("Comment deleted by the author")},r.prototype.select=function(){this.isSelected()?(this.deselect(),this.eventPipe.emit("sectionDeselected",this)):(this.$el.find(".side-comment").addClass("active"),0===this.comments.length&&this.currentUser&&this.focusCommentBox(),this.eventPipe.emit("sectionSelected",this))},r.prototype.deselect=function(){this.$el.find(".side-comment").removeClass("active"),this.hideCommentForm()},r.prototype.isSelected=function(){return this.$el.find(".side-comment").hasClass("active")},r.prototype.sectionClasses=function(){var e="";return this.comments.length>0&&(e+=" has-comments"),this.currentUser||(e+=" no-current-user"),e},r.prototype.render=function(){this.$el.find(".side-comment").remove(),l(o.template(i,{commentTemplate:s,comments:this.comments,sectionClasses:this.sectionClasses(),formTemplate:a,currentUser:this.currentUser})).appendTo(this.$el)},r.prototype.destroy=function(){this.$el.off()},n.exports=r}),require.register("side-comments/js/vendor/lodash-custom.js",function(e,t,n){(function(){function t(e){return"\\"+ht[e]}function r(){return N.pop()||[]}function o(e){return"function"!=typeof e.toString&&"string"==typeof(e+"")}function i(e){e.length=0,N.lengtho?0:o);++r-1:void 0});return a.pop(),c.pop(),k&&(i(a),i(c)),l}function d(e,t,n,r,o,i){var a=1&t,l=2&t,m=4&t,u=16&t,h=32&t;if(!l&&!x(e))throw new TypeError;u&&!n.length&&(t&=-17,u=n=!1),h&&!r.length&&(t&=-33,h=r=!1);var f=e&&e.__bindData__;if(f&&f!==!0)return f=s(f),f[2]&&(f[2]=s(f[2])),f[3]&&(f[3]=s(f[3])),!a||1&f[1]||(f[4]=o),!a&&1&f[1]&&(t|=8),!m||4&f[1]||(f[5]=i),u&&$t.apply(f[2]||(f[2]=[]),n),h&&Ut.apply(f[3]||(f[3]=[]),r),f[1]|=t,d.apply(null,f);var v=1==t||17===t?c:p;return v([e,t,n,r,o,i])}function f(){ut.shadowedProps=X,ut.array=ut.bottom=ut.loop=ut.top="",ut.init="iterable",ut.useHas=!0;for(var e,t=0;e=arguments[t];t++)for(var n in e)ut[n]=e[n];var r=ut.args;ut.firstArg=/^[^,]+/.exec(r)[0];var o=Function("baseCreateCallback, errorClass, errorProto, hasOwnProperty, indicatorObject, isArguments, isArray, isString, keys, objectProto, objectTypes, nonEnumProps, stringClass, stringProto, toString","return function("+r+") {\n"+Lt(ut)+"\n}");return o(u,rt,Ct,Pt,F,y,Ft,_,ut.keys,kt,pt,Dt,ct,xt,wt)}function v(e){return Qt[e]}function g(e){return"function"==typeof e&&_t.test(e)}function y(e){return e&&"object"==typeof e&&"number"==typeof e.length&&wt.call(e)==Z||!1}function b(e,t,n,r){return"boolean"!=typeof t&&null!=t&&(r=n,n=t,t=!1),l(e,t,"function"==typeof n&&u(n,r,1))}function C(e,t,n){return l(e,!0,"function"==typeof t&&u(t,n,1))}function x(e){return"function"==typeof e}function w(e){return!(!e||!pt[typeof e])}function _(e){return"string"==typeof e||e&&"object"==typeof e&&wt.call(e)==ct||!1}function j(e){for(var t=-1,n=Rt(e),r=n.length,o=Array(r);++t2?d(e,17,s(arguments,2),null,t):d(e,1,null,null,t)}function E(e,t,n){var r=typeof e;if(null==e||"function"==r)return u(e,t,n);if("object"!=r)return D(e);var o=Rt(e),i=o[0],s=e[i];return 1!=o.length||s!==s||w(s)?function(t){for(var n=o.length,r=!1;n--&&(r=h(t[o[n]],e[o[n]],null,!0)););return r}:function(e){var t=e[i];return s===t&&(0!==s||1/s==1/t)}}function q(e){return null==e?"":String(e).replace(Vt,v)}function O(e){return e}function I(){}function D(e){return function(t){return t[e]}}function T(e,n,r){var o=a.templateSettings;e=String(e||""),r=Kt({},r,o);var i,s=Kt({},r.imports,o.imports),c=Rt(s),l=j(s),m=0,u=r.interpolate||J,p="__p += '",h=RegExp((r.escape||J).source+"|"+u.source+"|"+(u===G?W:J).source+"|"+(r.evaluate||J).source+"|$","g");e.replace(h,function(n,r,o,s,a,c){return o||(o=s),p+=e.slice(m,c).replace(M,t),r&&(p+="' +\n__e("+r+") +\n'"),a&&(i=!0,p+="';\n"+a+";\n__p += '"),o&&(p+="' +\n((__t = ("+o+")) == null ? '' : __t) +\n'"),m=c+n.length,n}),p+="';\n";var d=r.variable,f=d;f||(d="obj",p="with ("+d+") {\n"+p+"\n}\n"),p=(i?p.replace(R,""):p).replace(B,"$1").replace(H,"$1;"),p="function("+d+") {\n"+(f?"":d+" || ("+d+" = {});\n")+"var __t, __p = '', __e = _.escape"+(i?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+p+"return __p\n}";var v="\n/*\n//# sourceURL="+(r.sourceURL||"/lodash/template/source["+Y++ +"]")+"\n*/";try{var g=Function(c,"return "+p+v).apply(L,l)}catch(y){throw y.source=p,y}return n?g(n):(g.source=p,g)}var L,N=[],F={},z=40,R=/\b__p \+= '';/g,B=/\b(__p \+=) '' \+/g,H=/(__e\(.*?\)|\b__t\)) \+\n'';/g,W=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Q=/\w*$/,V=/^\s*function[ \n\r\t]+\w/,G=/<%=([\s\S]+?)%>/g,J=/($^)/,K=/\bthis\b/,M=/['\n\r\t\u2028\u2029\\]/g,X=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Y=0,Z="[object Arguments]",et="[object Array]",tt="[object Boolean]",nt="[object Date]",rt="[object Error]",ot="[object Function]",it="[object Number]",st="[object Object]",at="[object RegExp]",ct="[object String]",lt={};lt[ot]=!1,lt[Z]=lt[et]=lt[tt]=lt[nt]=lt[it]=lt[st]=lt[at]=lt[ct]=!0;var mt={configurable:!1,enumerable:!1,value:null,writable:!1},ut={args:"",array:null,bottom:"",firstArg:"",init:"",keys:null,loop:"",shadowedProps:null,support:null,top:"",useHas:!1},pt={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},ht={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},dt=pt[typeof window]&&window||this,ft=pt[typeof e]&&e&&!e.nodeType&&e,vt=pt[typeof n]&&n&&!n.nodeType&&n,gt=vt&&vt.exports===ft&&ft,yt=pt[typeof global]&&global;!yt||yt.global!==yt&&yt.window!==yt||(dt=yt);var bt=[],Ct=Error.prototype,kt=Object.prototype,xt=String.prototype,wt=kt.toString,_t=RegExp("^"+String(wt).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),jt=Function.prototype.toString,Pt=kt.hasOwnProperty,$t=bt.push,St=kt.propertyIsEnumerable,Ut=bt.unshift,At=function(){try{var e={},t=g(t=Object.defineProperty)&&t,n=t(e,e,e)&&t}catch(r){}return n}(),Et=g(Et=Object.create)&&Et,qt=g(qt=Array.isArray)&&qt,Ot=g(Ot=Object.keys)&&Ot,It={};It[et]=Array,It[tt]=Boolean,It[nt]=Date,It[ot]=Function,It[st]=Object,It[it]=Number,It[at]=RegExp,It[ct]=String;var Dt={};Dt[et]=Dt[nt]=Dt[it]={constructor:!0,toLocaleString:!0,toString:!0,valueOf:!0},Dt[tt]=Dt[ct]={constructor:!0,toString:!0,valueOf:!0},Dt[rt]=Dt[ot]=Dt[at]={constructor:!0,toString:!0},Dt[st]={constructor:!0},function(){for(var e=X.length;e--;){var t=X[e];for(var n in Dt)Pt.call(Dt,n)&&!Pt.call(Dt[n],t)&&(Dt[n][t]=!1)}}();var Tt=a.support={};!function(){var e=function(){this.x=1},t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments);Tt.argsClass=wt.call(arguments)==Z,Tt.argsObject=arguments.constructor==Object&&!(arguments instanceof Array),Tt.enumErrorProps=St.call(Ct,"message")||St.call(Ct,"name"),Tt.enumPrototypes=St.call(e,"prototype"),Tt.funcDecomp=!g(dt.WinRTError)&&K.test(function(){return this}),Tt.funcNames="string"==typeof Function.name,Tt.nonEnumArgs=0!=r,Tt.nonEnumShadows=!/valueOf/.test(n),Tt.spliceObjects=(bt.splice.call(t,0,1),!t[0]),Tt.unindexedChars="x"[0]+Object("x")[0]!="xx";try{Tt.nodeClass=!(wt.call(document)==st&&!({toString:0}+""))}catch(o){Tt.nodeClass=!0}}(1),a.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:G,variable:"",imports:{_:a}};var Lt=function(e){var t="var index, iterable = "+e.firstArg+", result = "+e.init+";\nif (!iterable) return result;\n"+e.top+";";e.array?(t+="\nvar length = iterable.length; index = -1;\nif ("+e.array+") { ",Tt.unindexedChars&&(t+="\n if (isString(iterable)) {\n iterable = iterable.split('')\n } "),t+="\n while (++index < length) {\n "+e.loop+";\n }\n}\nelse { "):Tt.nonEnumArgs&&(t+="\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += '';\n "+e.loop+";\n }\n } else { "),Tt.enumPrototypes&&(t+="\n var skipProto = typeof iterable == 'function';\n "),Tt.enumErrorProps&&(t+="\n var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n ");var n=[];if(Tt.enumPrototypes&&n.push('!(skipProto && index == "prototype")'),Tt.enumErrorProps&&n.push('!(skipErrorProps && (index == "message" || index == "name"))'),e.useHas&&e.keys)t+="\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] && keys(iterable),\n length = ownProps ? ownProps.length : 0;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n",n.length&&(t+=" if ("+n.join(" && ")+") {\n "),t+=e.loop+"; ",n.length&&(t+="\n }"),t+="\n } ";else if(t+="\n for (index in iterable) {\n",e.useHas&&n.push("hasOwnProperty.call(iterable, index)"),n.length&&(t+=" if ("+n.join(" && ")+") {\n "),t+=e.loop+"; ",n.length&&(t+="\n }"),t+="\n } ",Tt.nonEnumShadows){for(t+="\n\n if (iterable !== objectProto) {\n var ctor = iterable.constructor,\n isProto = iterable === (ctor && ctor.prototype),\n className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n nonEnum = nonEnumProps[className];\n ",k=0;7>k;k++)t+="\n index = '"+e.shadowedProps[k]+"';\n if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))",e.useHas||(t+=" || (!nonEnum[index] && iterable[index] !== objectProto[index])"),t+=") {\n "+e.loop+";\n } ";t+="\n } "}return(e.array||Tt.nonEnumArgs)&&(t+="\n}"),t+=e.bottom+";\nreturn result"};Et||(m=function(){function e(){}return function(t){if(w(t)){e.prototype=t;var n=new e;e.prototype=null}return n||dt.Object()}}());var Nt=At?function(e,t){mt.value=t,At(e,"__bindData__",mt)}:I;Tt.argsClass||(y=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&Pt.call(e,"callee")&&!St.call(e,"callee")||!1});var Ft=qt||function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&wt.call(e)==et||!1},zt=f({args:"object",init:"[]",top:"if (!(objectTypes[typeof object])) return result",loop:"result.push(index)"}),Rt=Ot?function(e){return w(e)?Tt.enumPrototypes&&"function"==typeof e||Tt.nonEnumArgs&&e.length&&y(e)?zt(e):Ot(e):[]}:zt,Bt={args:"collection, callback, thisArg",top:"callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",array:"typeof length == 'number'",keys:Rt,loop:"if (callback(iterable[index], index, collection) === false) return result"},Ht={args:"object, source, guard",top:"var args = arguments,\n argsIndex = 0,\n argsLength = typeof guard == 'number' ? 2 : args.length;\nwhile (++argsIndex < argsLength) {\n iterable = args[argsIndex];\n if (iterable && objectTypes[typeof iterable]) {",keys:Rt,loop:"if (typeof result[index] == 'undefined') result[index] = iterable[index]",bottom:" }\n}"},Wt={top:"if (!objectTypes[typeof iterable]) return result;\n"+Bt.top,array:!1},Qt={"&":"&","<":"<",">":">",'"':""","'":"'"},Vt=RegExp("["+Rt(Qt).join("")+"]","g"),Gt=f(Bt),Jt=f(Ht,{top:Ht.top.replace(";",";\nif (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n callback = args[--argsLength];\n}"),loop:"result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]"}),Kt=f(Ht),Mt=f(Bt,Wt,{useHas:!1}),Xt=f(Bt,Wt);x(/x/)&&(x=function(e){return"function"==typeof e&&wt.call(e)==ot}),a.assign=Jt,a.bind=A,a.createCallback=E,a.defaults=Kt,a.filter=P,a.forEach=S,a.forIn=Mt,a.forOwn=Xt,a.keys=Rt,a.property=D,a.reject=U,a.values=j,a.each=S,a.extend=Jt,a.select=P,a.clone=b,a.cloneDeep=C,a.escape=q,a.find=$,a.identity=O,a.isArguments=y,a.isArray=Ft,a.isFunction=x,a.isObject=w,a.isString=_,a.noop=I,a.template=T,a.detect=$,a.findWhere=$,a.VERSION="2.4.1",ft&&vt&&(gt?(vt.exports=a)._=a:ft._=a)}).call(this)}),require.register("side-comments/js/helpers/mobile-check.js",function(e,t,n){n.exports=function(){var e=!1;return function(t){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|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(t)||/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(t.substr(0,4)))&&(e=!0)}(navigator.userAgent||navigator.vendor||window.opera),e}}),require.register("side-comments/templates/section.html",function(e,t,n){n.exports='
    \n \n <%= comments.length %>\n \n \n
    \n
      \n <% _.each(comments, function( comment ){ %>\n <%= _.template(commentTemplate, { comment: comment, currentUser: currentUser, formTemplate: formTemplate, self: commentTemplate }) %>\n <% }) %>\n
    \n \n Leave a comment\n <% if (currentUser) { %>\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'comment-form\', commentId: null }) %>\n <% } %>\n
    \n
    '}),require.register("side-comments/templates/form.html",function(e,t,n){n.exports='
    \n
    \n \n
    \n

    \n <%= currentUser.name %>\n

    \n \n
    \n Post\n Cancel\n
    \n
    '}),require.register("side-comments/templates/comment.html",function(e,t,n){n.exports='
  • \n
    \n \n
    \n <% if (comment.authorUrl) { %>\n \n <%= comment.authorName %>\n \n <% } else { %>\n

    \n <%= comment.authorName %>\n

    \n <% } %>\n

    \n <%= (comment.deleted != null && comment.deleted) ? "Comment deleted by the author" : comment.comment %>\n

    \n\n <% if ( comment.parentId == null ) { %>\n \n
      \n <% _.each(comment.replies, function ( reply ) {%>\n <%= _.template(self, { comment: reply, currentUser: currentUser, formTemplate: formTemplate }) %>\n <% });%>\n
    \n\n <% if (currentUser){ %>\n Reply\n <%= _.template(formTemplate, { currentUser: currentUser, formClass: \'reply-form\', commentId: comment.id })%>\n <% if (comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n <% } %>\n\n <% } else { %>\n\n <% if (currentUser && comment.authorId === currentUser.id) { %>\n Delete\n <% } %>\n\n <% } %>\n\n
  • '}),require.alias("component-emitter/index.js","side-comments/deps/emitter/index.js"),require.alias("component-emitter/index.js","emitter/index.js"),require.alias("side-comments/js/main.js","side-comments/index.js"); \ No newline at end of file diff --git a/release/themes/default-theme.css b/release/themes/default-theme.css index 67ffa40..4a466d1 100644 --- a/release/themes/default-theme.css +++ b/release/themes/default-theme.css @@ -183,9 +183,14 @@ color: #B3B3B1; padding: 0 5px; } -.side-comment .replies .author-name { +.side-comment .replies .right-of-avatar { width: 116px; } +.side-comment .replies .delete { + display: inline-block; + float: left; + margin: 0; +} @media (max-width: 768px) { .side-comments-open { -webkit-transform: translate(-220px, 0); diff --git a/release/themes/default-theme.min.css b/release/themes/default-theme.min.css index 0f58d8f..146a400 100644 --- a/release/themes/default-theme.min.css +++ b/release/themes/default-theme.min.css @@ -1 +1 @@ -.commentable-container{-webkit-transition:all .22s ease;transition:all .22s ease}.side-comments-open{-webkit-transform:translate(-220px,0);-ms-transform:translate(-220px,0);transform:translate(-220px,0)}.commentable-section{-moz-box-sizing:border-box;box-sizing:border-box;padding-right:30px}.side-comment{padding-bottom:20px}.side-comment .marker{width:20px;height:18px;background:#DEDEDC;border-radius:2px;text-decoration:none}.side-comment .marker span,.side-comment .marker:before{content:"+";position:absolute;width:20px;height:18px;line-height:16px;font-size:14px;color:#FFF;text-align:center}.side-comment .marker span{line-height:20px;font-size:12px}.side-comment .marker:after{content:"";display:block;position:absolute;bottom:-7px;left:5px;width:0;border-width:7px 8px 0 0;border-style:solid;border-color:#DEDEDC transparent}.side-comment .marker:hover,.side-comment.active .marker{background:#4FAF62}.side-comment .marker:hover:after,.side-comment.active .marker:after{border-color:#4FAF62 transparent}.side-comment .comments-wrapper{top:-22px;width:200px;padding-bottom:120px}.side-comment.active .comments-wrapper{-webkit-animation:fadein .2s;animation:fadein .2s}.side-comment.has-comments .comments-wrapper{top:-22px}.side-comment .comment-form,.side-comment ul.comments li{border:1px solid #F2F2F0;border-left:0;border-right:0;padding:15px 0;margin-top:-1px}.side-comment .reply-form{padding-left:42px;padding-top:10px}.side-comment .comment,.side-comment .comment-box{font-size:14px;line-height:18px}.side-comment .author-avatar{float:left;width:32px;height:32px;margin-right:10px}.side-comment .author-avatar img{width:100%;height:100%}.side-comment .right-of-avatar{float:left;width:158px}.side-comment .author-name{font-size:15px;line-height:16px;margin:0 0 2px;font-weight:700;text-decoration:none;color:#222}.side-comment a.author-name:hover{color:#444}.side-comment .action-link{color:#B3B3B1;font-size:13px;text-decoration:none}.side-comment .action-link:hover{text-decoration:none}.side-comment .action-link.post .post{color:#89C794}.side-comment .action-link.post .post:hover{color:#468c54}.side-comment .action-link.cancel:hover,.side-comment .action-link.delete:hover{color:#57AD68}.side-comment .add-comment{color:#B3B3B1;font-size:14px;line-height:22px;font-weight:300;padding:0 8px;letter-spacing:.05em;text-decoration:none;margin-top:10px}.side-comment .add-comment:before{content:"+";border:2px solid #DEDEDC;border-radius:100px;width:23px;height:23px;color:#DEDEDC;display:block;text-align:center;font-size:16px;font-weight:400;line-height:18px;float:left;margin-right:15px;letter-spacing:0;-moz-box-sizing:border-box;box-sizing:border-box}.side-comment .add-comment:hover{text-decoration:none;color:#4FAF62}.side-comment .add-comment:hover:before{border-color:#4FAF62;color:#4FAF62}.side-comment .comment-box{outline:0;border:0;box-shadow:none;padding:0}.side-comment .actions{margin-top:5px}.side-comment .actions a{float:left}.side-comment .actions .cancel:before{content:'\00B7';color:#B3B3B1;padding:0 5px}.side-comment .replies .author-name{width:116px}@media (max-width:768px){.side-comments-open{-webkit-transform:translate(-220px,0);-ms-transform:translate(-220px,0);transform:translate(-220px,0)}.side-comment .comments-wrapper{width:200px}.side-comment .right-of-avatar{width:158px}.side-comment .marker{display:block}} \ No newline at end of file +.commentable-container{-webkit-transition:all .22s ease;transition:all .22s ease}.side-comments-open{-webkit-transform:translate(-220px,0);-ms-transform:translate(-220px,0);transform:translate(-220px,0)}.commentable-section{-moz-box-sizing:border-box;box-sizing:border-box;padding-right:30px}.side-comment{padding-bottom:20px}.side-comment .marker{width:20px;height:18px;background:#DEDEDC;border-radius:2px;text-decoration:none}.side-comment .marker span,.side-comment .marker:before{content:"+";position:absolute;width:20px;height:18px;line-height:16px;font-size:14px;color:#FFF;text-align:center}.side-comment .marker span{line-height:20px;font-size:12px}.side-comment .marker:after{content:"";display:block;position:absolute;bottom:-7px;left:5px;width:0;border-width:7px 8px 0 0;border-style:solid;border-color:#DEDEDC transparent}.side-comment .marker:hover,.side-comment.active .marker{background:#4FAF62}.side-comment .marker:hover:after,.side-comment.active .marker:after{border-color:#4FAF62 transparent}.side-comment .comments-wrapper{top:-22px;width:200px;padding-bottom:120px}.side-comment.active .comments-wrapper{-webkit-animation:fadein .2s;animation:fadein .2s}.side-comment.has-comments .comments-wrapper{top:-22px}.side-comment .comment-form,.side-comment ul.comments li{border:1px solid #F2F2F0;border-left:0;border-right:0;padding:15px 0;margin-top:-1px}.side-comment .reply-form{padding-left:42px;padding-top:10px}.side-comment .comment,.side-comment .comment-box{font-size:14px;line-height:18px}.side-comment .author-avatar{float:left;width:32px;height:32px;margin-right:10px}.side-comment .author-avatar img{width:100%;height:100%}.side-comment .right-of-avatar{float:left;width:158px}.side-comment .author-name{font-size:15px;line-height:16px;margin:0 0 2px;font-weight:700;text-decoration:none;color:#222}.side-comment a.author-name:hover{color:#444}.side-comment .action-link{color:#B3B3B1;font-size:13px;text-decoration:none}.side-comment .action-link:hover{text-decoration:none}.side-comment .action-link.post .post{color:#89C794}.side-comment .action-link.post .post:hover{color:#468c54}.side-comment .action-link.cancel:hover,.side-comment .action-link.delete:hover{color:#57AD68}.side-comment .add-comment{color:#B3B3B1;font-size:14px;line-height:22px;font-weight:300;padding:0 8px;letter-spacing:.05em;text-decoration:none;margin-top:10px}.side-comment .add-comment:before{content:"+";border:2px solid #DEDEDC;border-radius:100px;width:23px;height:23px;color:#DEDEDC;display:block;text-align:center;font-size:16px;font-weight:400;line-height:18px;float:left;margin-right:15px;letter-spacing:0;-moz-box-sizing:border-box;box-sizing:border-box}.side-comment .add-comment:hover{text-decoration:none;color:#4FAF62}.side-comment .add-comment:hover:before{border-color:#4FAF62;color:#4FAF62}.side-comment .comment-box{outline:0;border:0;box-shadow:none;padding:0}.side-comment .actions{margin-top:5px}.side-comment .actions a{float:left}.side-comment .actions .cancel:before{content:'\00B7';color:#B3B3B1;padding:0 5px}.side-comment .replies .right-of-avatar{width:116px}.side-comment .replies .delete{display:inline-block;float:left;margin:0}@media (max-width:768px){.side-comments-open{-webkit-transform:translate(-220px,0);-ms-transform:translate(-220px,0);transform:translate(-220px,0)}.side-comment .comments-wrapper{width:200px}.side-comment .right-of-avatar{width:158px}.side-comment .marker{display:block}} \ No newline at end of file diff --git a/support/images/cattelyn_stark.png b/support/images/cattelyn_stark.png new file mode 100644 index 0000000000000000000000000000000000000000..0e2e26a929e40e5a7ea637ebbc10f1c70a18c4a2 GIT binary patch literal 14078 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 literal 0 HcmV?d00001 diff --git a/support/test_data.js b/support/test_data.js index 2d196b6..a9bd314 100644 --- a/support/test_data.js +++ b/support/test_data.js @@ -21,6 +21,26 @@ var existingComments = [ } ] }, + { + "id": 79, + "authorAvatarUrl": "support/images/jon_snow.png", + "authorName": "Jon Sno", + "authorId": 1, + "authorUrl": "http://en.wikipedia.org/wiki/Kit_Harington", + "comment": "Again, I AM Ned Stark's bastard", + "deleted" : true, + "replies": [ + { + "id": 894, + "authorAvatarUrl": "support/images/cattelyn_stark.png", + "authorName": "Catellyn Stark", + "authorId": 5, + "authorUrl": "http://pt.wikipedia.org/wiki/Michelle_Fairley", + "comment": "Booooh!", + "parentId": 79 + } + ] + }, { "id": 112, "authorAvatarUrl": "support/images/donald_draper.png", diff --git a/templates/comment.html b/templates/comment.html index 173f967..7c3db5a 100644 --- a/templates/comment.html +++ b/templates/comment.html @@ -12,10 +12,10 @@

    <% } %>

    - <%= comment.comment %> + <%= (comment.deleted != null && comment.deleted) ? "Comment deleted by the author" : comment.comment %>

    - <% if ( comment.parentId === undefined ) { %> + <% if ( comment.parentId == null ) { %>
      <% _.each(comment.replies, function ( reply ) {%> @@ -31,10 +31,12 @@ <% } %> <% } %> - <% } %> + <% } else { %> + + <% if (currentUser && comment.authorId === currentUser.id) { %> + Delete + <% } %> - <% if (currentUser && comment.authorId === currentUser.id) { %> - Delete <% } %> \ No newline at end of file diff --git a/test/test_main.js b/test/test_main.js index f9edbaa..05edad6 100644 --- a/test/test_main.js +++ b/test/test_main.js @@ -297,7 +297,7 @@ describe("SideComments", function() { $section1.find('.action-link.post').trigger('click'); }); - it("should update a non-empty section's comment list after adding", function(){ + it("should update a non-empty section's comment list length after adding", function(){ sideComments.insertComment(testCommentForSection(1)); expect($section1.find('.comments > li')).to.have.length.of(3); }); @@ -307,7 +307,7 @@ describe("SideComments", function() { expect($section1.find('.marker span').text().trim()).to.equal("3"); }); - it("should update an empty section's comment list after adding", function(){ + it("should update an empty section's comment list length after adding", function(){ sideComments.insertComment(testCommentForSection(2)); expect($section2.find('.comments > li')).to.have.length.of(1); }); @@ -332,6 +332,22 @@ describe("SideComments", function() { expect($lastCommentAuthor.attr('href')).to.eq(currentUser.authorUrl); }); + it("should be inserted with a comment body", function () { + sideComments.on('commentPosted', function ( comment ) { + comment.id = 123; + sideComments.insertComment(comment); + }); + + var commentBody = 'Test comment'; + + $section2.find('.marker').trigger('click'); + $section2.find('.add-comment').trigger('.click'); + $section2.find('.comment-box').val(commentBody); + $section2.find('.action-link.post').trigger('click'); + + expect($section2.find('.comments > li').last().find('.comment').text().trim()).to.equal(commentBody) + }); + describe("Comment is a reply", function () { it("should emit an event when a reply is posted", function ( done ) { @@ -351,14 +367,38 @@ describe("SideComments", function() { $section1.find('.marker').trigger('click'); $section1.find('.comments > li').first().find('.reply-comment').trigger('click'); $section1.find('.comments > li').first().find('.comment-box').html(newTestComment.comment); - $section1.find('.comments > li').first().find('.action-link.post').trigger('click'); + $section1.find('.comments > li').first().find('.reply-form .post').trigger('click'); }); - it("should update a non-empty reply list after adding", function(){ + it("should update a non-empty reply list length after adding", function(){ sideComments.insertComment(testCommentForSection(1, 88)); expect($section1.find('.comments > li').first().find('.replies li')).to.have.length.of(2); }); + it("should update an empty reply list length after adding", function () { + sideComments.insertComment(testCommentForSection(3, 66)); + expect($section3.find('.comments > li').first().find('.replies li')).to.have.length.of(1); + }); + + it("should update an empty reply list of a new comment", function () { + sideComments.insertComment(testCommentForSection(2)); + sideComments.insertComment(testCommentForSection(2, 278)); + expect($section2.find('.comments > li').first().find('.replies li')).to.have.length.of(1); + }); + + it("should belong to the current user", function () { + sideComments.on('commentPosted', function( comment ) { + comment.id = 3335; + sideComments.insertComment(comment); + }); + + $section1.find('.comments > li').first().find('.reply-comment').trigger('click'); + $section1.find('.comments > li').first().find('.comment-box').html(newTestComment.comment); + $section1.find('.comments > li').first().find('.reply-form .action-link.post').trigger('click'); + + expect($section1.find('.comments > li').first().find('.replies li').last().find('.author-name').text().trim()).to.equal(currentUser.name); + }); + }); }); @@ -390,12 +430,12 @@ describe("SideComments", function() { }); it("should update a section's comment count after removing", function(){ - sideComments.removeComment(1, 88); + sideComments.removeComment(1, 112); expect($section1.find('.marker span').text().trim()).to.equal("1"); }); it("should update a section's comment list after deleting", function(){ - sideComments.removeComment(1, 88); + sideComments.removeComment(1, 112); expect($section1.find('.comments > li')).to.have.length.of(1); }); @@ -409,6 +449,39 @@ describe("SideComments", function() { $section3.find('.marker').trigger('click'); expect($section3.find('.comment-form').is(':visible')).to.be.true; }); + + it("should only update a comment's body when the deleted comment has replies", function () { + sideComments.removeComment(1, 88); + var comment = $section1.find('.comments > li').first().find('.comment').first().text(); + expect(comment).to.equal("Comment deleted by the author"); + }); + + describe("Comment is a reply", function () { + + it("should emit an event when a comment is deleted", function( done ){ + this.timeout(0); + var eventFired = false; + + setTimeout( function () { + check( done, function() { + expect(eventFired).to.be.true; + } ) + }, 500); + + sideComments.on('commentDeleted', function( comment ) { + eventFired = true; + }); + + sideComments.sections[0].deleteComment(100, 88); + }); + + it("should update a comment replies list after deleting", function () { + sideComments.removeComment(1, 100, 88); + expect($section1.find('.comments > li').first().find('.replies li')).to.have.length.of(0) + }); + + }); + }); describe("No Current User", function(){