├── LICENSE.txt
├── README.md
├── css
├── images
│ ├── ui-anim_basic_16x16.gif
│ └── user_blank_picture.png
└── jquery.comment.css
├── demo
├── articles
│ └── id
│ │ └── 1
│ │ └── comments
│ │ └── list
└── index.html
└── js
├── jquery.autogrow-textarea.js
├── jquery.comment.js
└── jquery.timeago.js
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2012 Hendrayana
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [jquery-comment](http://henyana.github.io/jquery-comment)
2 |
3 | It's jquery plugin for nested Comments like the [http://disqus.com](disqus). It's using ajax request and json data as the feeds.
4 |
5 | ## Quick start
6 |
7 | Two quick start options are available:
8 |
9 | * [Download the latest release](https://github.com/henyana/jquery-comment/zipball/master).
10 | * Clone the repo: `git clone git://github.com/henyana/jquery-comment.git`.
11 |
12 | ## Documentation
13 |
14 | [http://henyana.github.io/jquery-comment](http://henyana.github.io/jquery-comment)
15 |
16 | ## Demo
17 |
18 | [http://henyana.github.io/jquery-comment/demo](http://henyana.github.io/jquery-comment/demo)
19 |
20 | ## Authors
21 |
22 | **Hendrayana**
23 |
24 | + [http://twitter.com/h3ny4n4](http://twitter.com/h3ny4n4)
25 | + [http://github.com/henyana](http://github.com/henyana)
26 |
--------------------------------------------------------------------------------
/css/images/ui-anim_basic_16x16.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/henyana/jquery-comment/d2f02ede0f1aaf834f84b5d0de1912b4d4f4b24d/css/images/ui-anim_basic_16x16.gif
--------------------------------------------------------------------------------
/css/images/user_blank_picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/henyana/jquery-comment/d2f02ede0f1aaf834f84b5d0de1912b4d4f4b24d/css/images/user_blank_picture.png
--------------------------------------------------------------------------------
/css/jquery.comment.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery Post-Comment Plugin v.1.0
3 | * created [2013-02-26 17:49 AM]
4 | * TODO: Documentation
5 | *
6 | * Copyright 2013, hendra@kunchy.com or henyana@gmail.com
7 | * http://www.abelware.com
8 | */
9 | .clear{
10 | clear: both;
11 | }
12 |
13 | .comments-display{
14 |
15 | }
16 |
17 | .comments-display .dot{
18 | padding: 0 3px;
19 | font-size: 75%;
20 | color: #CCC;
21 | line-height: 1.4;
22 | }
23 |
24 | .comments-display .in-reply-to{
25 | display:inline-table;
26 | }
27 |
28 | .comments-display .in-reply-to .ui-icon{
29 | height:12px;
30 | }
31 |
32 | .comments-display .comment-length{
33 | font-weight:bold;
34 | padding-bottom:7px;
35 | }
36 |
37 | .comments-display .posted-comments-postbox {
38 | padding-top:3px;
39 | border-bottom:2px solid #F0F0F0;
40 | }
41 |
42 | ul.posted-comments {
43 | list-style: none;
44 | margin: 0;
45 | }
46 |
47 | ul.posted-comments li {
48 | padding:10px 0 0;
49 | border-top:1px solid #F0F0F0;
50 | }
51 |
52 | .avatar img{
53 | width:28px;
54 | height:28px;
55 | }
56 |
57 | .posted-comments-postbox .avatar{
58 |
59 | }
60 |
61 | .posted-comments-postbox .form{
62 | margin-left: 10px;
63 | min-width: 85%;
64 | }
65 |
66 | .posted-comments-postbox textarea, .posted-comment-form-edit textarea{
67 | min-width:98%;
68 | }
69 |
70 | .posted-comment-container{
71 | margin-left: 10px;
72 | min-width:85%;
73 | }
74 |
75 | .posted-comment-container .posted-comment-head{
76 | font-size:7pt;
77 | }
78 |
79 | .posted-comment-container .posted-comment-head .posted-comment-author{
80 | font-weight:bold;
81 | }
82 |
83 | .posted-comment-container .posted-comment-foot{
84 | font-size:7pt;
85 | color:#F0F0F0;
86 | }
87 |
88 | ul.posted-comment-childs{
89 | list-style: none;
90 | margin-left:40px;
91 | padding-top:7px;
92 | }
93 |
94 | ul.posted-comment-childs .avatar img{
95 | width:22px;
96 | height:22px;
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/demo/articles/id/1/comments/list:
--------------------------------------------------------------------------------
1 | {
2 | "results": {
3 | "comments": [
4 | {
5 | "comment_id": "1",
6 | "parent_id": "0",
7 | "in_reply_to": null,
8 | "element_id": "134",
9 | "created_by": "1",
10 | "fullname": "Administrator admin",
11 | "picture": "../css/images/user_blank_picture.png",
12 | "posted_date": "2013-02-27 09:03:25",
13 | "text": "Test message one",
14 | "attachments": [],
15 | "childrens": [
16 | {
17 | "comment_id": "3",
18 | "parent_id": "1",
19 | "in_reply_to": "Administrator admin",
20 | "element_id": "134",
21 | "created_by": "2",
22 | "fullname": "Manager manager",
23 | "picture": "../css/images/user_blank_picture.png",
24 | "posted_date": "2013-02-27 08:48:50",
25 | "text": "Hi, reply for you",
26 | "attachments": [],
27 | "childrens": []
28 | },
29 | {
30 | "comment_id": "2",
31 | "parent_id": "1",
32 | "in_reply_to": "Administrator admin",
33 | "element_id": "134",
34 | "created_by": "1",
35 | "fullname": "Administrator admin",
36 | "picture": "../css/images/user_blank_picture.png",
37 | "posted_date": "2013-02-26 11:30:44",
38 | "text": "Test message level 2",
39 | "attachments": [],
40 | "childrens": [
41 | {
42 | "comment_id": "4",
43 | "parent_id": "2",
44 | "in_reply_to": "Administrator admin",
45 | "element_id": "134",
46 | "created_by": "2",
47 | "fullname": "Manager manager",
48 | "picture": "../css/images/user_blank_picture.png",
49 | "posted_date": "2013-02-27 08:50:05",
50 | "text": "replied as level 3",
51 | "attachments": [],
52 | "childrens": []
53 | }
54 | ]
55 | }
56 | ]
57 | }
58 | ],
59 | "total_comment": 4,
60 | "user": {
61 | "user_id": 1,
62 | "fullname": "Administrator admin",
63 | "picture": "../css/images/user_blank_picture.png",
64 | "is_logged_in": true,
65 | "is_add_allowed": true,
66 | "is_edit_allowed": true
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Jquery Comment Plugin
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | ARTICLE CONTENT HERE!
18 |
19 | list: json
20 | {
21 | "results": {
22 | "comments": [
23 | {
24 | "comment_id": "1",
25 | "parent_id": "0",
26 | "in_reply_to": null,
27 | "element_id": "134",
28 | "created_by": "1",
29 | "fullname": "Administrator admin",
30 | "picture": "../css/images/user_blank_picture.png",
31 | "posted_date": "2013-02-27 09:03:25",
32 | "text": "Test message one",
33 | "attachments": [],
34 | "childrens": [
35 | {
36 | "comment_id": "3",
37 | "parent_id": "1",
38 | "in_reply_to": "Administrator admin",
39 | "element_id": "134",
40 | "created_by": "2",
41 | "fullname": "Manager manager",
42 | "picture": "../css/images/user_blank_picture.png",
43 | "posted_date": "2013-02-27 08:48:50",
44 | "text": "Hi, reply for you",
45 | "attachments": [],
46 | "childrens": []
47 | },
48 | {
49 | "comment_id": "2",
50 | "parent_id": "1",
51 | "in_reply_to": "Administrator admin",
52 | "element_id": "134",
53 | "created_by": "1",
54 | "fullname": "Administrator admin",
55 | "picture": "../css/images/user_blank_picture.png",
56 | "posted_date": "2013-02-26 11:30:44",
57 | "text": "Test message level 2",
58 | "attachments": [],
59 | "childrens": [
60 | {
61 | "comment_id": "4",
62 | "parent_id": "2",
63 | "in_reply_to": "Administrator admin",
64 | "element_id": "134",
65 | "created_by": "2",
66 | "fullname": "Manager manager",
67 | "picture": "../css/images/user_blank_picture.png",
68 | "posted_date": "2013-02-27 08:50:05",
69 | "text": "replied as level 3",
70 | "attachments": [],
71 | "childrens": []
72 | }
73 | ]
74 | }
75 | ]
76 | }
77 | ],
78 | "total_comment": 4,
79 | "user": {
80 | "user_id": 1,
81 | "fullname": "Administrator admin",
82 | "picture": "../css/images/user_blank_picture.png",
83 | "is_logged_in": true,
84 | "is_add_allowed": true,
85 | "is_edit_allowed": true
86 | }
87 | }
88 | }
89 |
90 |
91 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
124 |
125 |
--------------------------------------------------------------------------------
/js/jquery.autogrow-textarea.js:
--------------------------------------------------------------------------------
1 |
2 | (function($)
3 | {
4 | /**
5 | * Auto-growing textareas; technique ripped from Facebook
6 | *
7 | * http://github.com/jaz303/jquery-grab-bag/tree/master/javascripts/jquery.autogrow-textarea.js
8 | */
9 | $.fn.autogrow = function(options)
10 | {
11 | return this.filter('textarea').each(function()
12 | {
13 | var self = this;
14 | var $self = $(self);
15 | var minHeight = $self.height();
16 | var noFlickerPad = $self.hasClass('autogrow-short') ? 0 : parseInt($self.css('lineHeight'));
17 |
18 | var shadow = $('').css({
19 | position: 'absolute',
20 | top: -10000,
21 | left: -10000,
22 | width: $self.width(),
23 | fontSize: $self.css('fontSize'),
24 | fontFamily: $self.css('fontFamily'),
25 | fontWeight: $self.css('fontWeight'),
26 | lineHeight: $self.css('lineHeight'),
27 | resize: 'none'
28 | }).appendTo(document.body);
29 |
30 | var update = function()
31 | {
32 | var times = function(string, number)
33 | {
34 | for (var i=0, r=''; i/g, '>')
40 | .replace(/&/g, '&')
41 | .replace(/\n$/, '
')
42 | .replace(/\n/g, '
')
43 | .replace(/ {2,}/g, function(space){ return times(' ', space.length - 1) + ' ' });
44 |
45 | shadow.css('width', $self.width());
46 | shadow.html(val);
47 | $self.css('height', Math.max(shadow.height() + noFlickerPad, minHeight));
48 | }
49 |
50 | $self.change(update).keyup(update).keydown(update);
51 | $(window).resize(update);
52 |
53 | update();
54 | });
55 | };
56 | })(jQuery);
--------------------------------------------------------------------------------
/js/jquery.comment.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery Post-Comment Plugin v.1.0
3 | * created [2013-02-26 17:49 AM]
4 | * TODO: Documentation
5 | *
6 | * Copyright 2013, hendra@kunchy.com or henyana@gmail.com
7 | * http://www.abelware.com
8 | */
9 |
10 | // Utility
11 | if ( typeof Object.create !== 'function' ) {
12 | Object.create = function( obj ) {
13 | function F() {};
14 | F.prototype = obj;
15 | return new F();
16 | };
17 | }
18 |
19 | (function($, window, document, undefined){
20 |
21 | var Comment = {
22 | init_: function( options, elem ) {
23 | var self = this;
24 |
25 | self.elem = elem;
26 | self.$elem = $( elem );
27 |
28 | self.options = $.extend( {}, $.fn.comment.options, options );
29 |
30 | self.refresh_( 1 );
31 | },
32 |
33 | buildForm_: function(comment_id, parent_id){
34 | var self = this;
35 |
36 | var form_elem = $('');
37 |
38 | if(comment_id!=null)
39 | form_elem.attr('action', self.options.url_input+'/'+comment_id);
40 | else
41 | form_elem.attr('action', self.options.url_input);
42 |
43 | form_elem.attr('method', 'post');
44 |
45 | if(parent_id!=null)
46 | {
47 | var parent_id_field = $('');
48 | parent_id_field.attr('type', 'hidden');
49 | parent_id_field.attr('name', 'parent_id');
50 | parent_id_field.val(parent_id);
51 | form_elem.append(parent_id_field);
52 | }
53 |
54 | var textarea = $('');
55 | textarea.attr('name', 'text');
56 | textarea.attr('placeHolder', 'Leave a message...');
57 | textarea.css('overflow', 'hidden');
58 | textarea.autogrow();
59 |
60 | textarea.on('keypress', function(e){
61 | e = e || event;
62 | if (e.keyCode === 13 && !e.shiftKey && $.trim(this.value).length>0) {
63 | e.preventDefault();
64 | //form_elem.submit();
65 |
66 |
67 | self.submitForm_(comment_id, form_elem.serialize());
68 | }
69 | });
70 |
71 | form_elem.append(textarea);
72 |
73 | return form_elem;
74 | },
75 |
76 | submitForm_: function(comment_id, form_data){
77 | var self = this;
78 |
79 | var url_input = self.options.url_input;
80 |
81 | if(comment_id!=null) // form edit mode
82 | url_input = self.options.url_input+'/'+comment_id;
83 |
84 | return $.ajax({
85 | url: url_input,
86 | data: form_data,
87 | type: 'post',
88 | dataType: 'json',
89 | beforeSend: function(xhr, opts){
90 |
91 | $('textarea', self.$elem).attr("disabled", true);
92 |
93 | }
94 | }).done( function(result){
95 |
96 | if(result.success!=undefined)
97 | {
98 | if(result.success===false)
99 | {
100 | // error
101 | $.each(result, function(key, val){
102 | // check error if any
103 | if(val.error!=undefined)
104 | {
105 | $show_warning_(val.error);
106 | return false;
107 | }
108 | });
109 | }
110 | else
111 | {
112 | if(comment_id!=null) // edit mode
113 | {
114 | var item = $('#posted-'+comment_id, self.$elem);
115 |
116 | var item_txt = $('.posted-comment-txt:hidden', item);
117 | item_txt.html(result.text);
118 | item_txt.toggle();
119 |
120 | var item_form_edit = $('.posted-comment-form-edit', item);
121 | item_form_edit.toggle();
122 |
123 | }
124 | else
125 | {
126 | result.fullname = self.user_info_.fullname;
127 | result.picture = self.user_info_.picture;
128 |
129 | // add new itemlist
130 | var itemlist = self.buildItemList_( result );
131 |
132 | if(result.parent_id===undefined)
133 | self.$rootlist.prepend(itemlist);
134 | else
135 | {
136 | if(result.parent_id==0)
137 | self.$rootlist.prepend(itemlist);
138 | else
139 | {
140 | var id = 'posted-comment-child-'+result.parent_id;
141 |
142 | //prepend the new comment
143 | var the_child = $('ul[id="'+id+'"]', self.$elem).prepend(itemlist);
144 |
145 | // hide the form post
146 | $('div.posted-comments-postbox:visible', the_child).hide();
147 | }
148 | }
149 |
150 | // update total comment
151 | self.total_comment++;
152 | self.$total_comment.html(self.total_comment+' '+self.options.title);
153 | }
154 |
155 | // clear and enable textarea
156 | $('textarea', self.$elem).val('');
157 | $('textarea', self.$elem).attr("disabled", false);
158 | }
159 | }
160 |
161 |
162 | });
163 | },
164 |
165 | buildPostBox_: function(parent_id){
166 | var self = this;
167 |
168 | var elem = $('');
169 | elem.addClass('posted-comments-postbox');
170 |
171 | //self.user_info_
172 | var img_elem = $('
');
173 | img_elem.attr('src', self.user_info_.picture);
174 | img_elem.attr('border', 0);
175 | img_elem.addClass('ui-corner-all');
176 | img_elem.addClass('curr-user-photo');
177 |
178 | var avatar = $('');
179 | avatar.addClass('avatar').addClass('pull-left');
180 | avatar.append(img_elem);
181 |
182 | elem.append(avatar);
183 |
184 |
185 | var form = $('');
186 | form.addClass('form').addClass('pull-left');
187 |
188 | if(self.user_info_.is_add_allowed)
189 | {
190 | // form new
191 | var form_elem = self.buildForm_(null, parent_id);
192 | form.append(form_elem);
193 | }
194 |
195 | elem.append(form);
196 |
197 | var clear = $('');
198 | clear.addClass('clear');
199 |
200 | elem.append(clear);
201 |
202 | return elem;
203 | },
204 |
205 | buildUl_: function(){
206 | var self = this;
207 |
208 | var ul_elem = $('');
209 | ul_elem.addClass('posted-comments');
210 |
211 | return ul_elem;
212 | },
213 |
214 | refresh_: function( length ) {
215 | var self = this;
216 |
217 | setTimeout(function() {
218 | self.fetch_().done(function( results ) {
219 |
220 | //console.log(results);
221 |
222 | // results['user']
223 | if(results.results.user!=undefined)
224 | self.user_info_ = results.results.user;
225 |
226 | // results['comments']
227 | if(results.results.comments!=undefined)
228 | results_ = results.results.comments;
229 | // results = self.limit_( results.results.comments, self.options.limit );
230 |
231 | // results['total_comment']
232 | if(results.results.total_comment!=undefined)
233 | self.total_comment = results.results.total_comment;
234 |
235 | self.buildList_( results_ );
236 |
237 | self.display_();
238 |
239 | if ( typeof self.options.onComplete === 'function' ) {
240 | self.options.onComplete.apply( self.elem, arguments );
241 | }
242 |
243 | if ( self.options.refresh && self.options.auto_refresh ) {
244 | self.refresh_();
245 | }
246 | });
247 | }, length || self.options.refresh );
248 | },
249 |
250 | fetch_: function() {
251 | var self = this;
252 | return $.ajax({
253 | url: self.options.url_get,
254 | dataType: 'json'
255 | });
256 | },
257 |
258 | buildList_: function( results ) {
259 | var self = this;
260 | self.comments = $.map( results, function( obj, i) {
261 | return self.buildItemList_( obj );
262 | });
263 | },
264 |
265 | buildItemList_: function( comment_info ) {
266 | var self = this;
267 |
268 | var item = $( self.options.wrapEachWith );
269 |
270 | item.attr('id', 'posted-'+comment_info.comment_id);
271 |
272 | // avatar-image
273 | var avatar = $('');
274 | avatar.addClass('avatar').addClass('pull-left');
275 |
276 | var img_elem = $('
');
277 | img_elem.attr('src', comment_info.picture);
278 | img_elem.attr('border', 0);
279 | img_elem.addClass('ui-corner-all');
280 |
281 | if(comment_info.created_by==self.user_info_.user_id)
282 | img_elem.addClass('curr-user-photo');
283 |
284 | avatar.append(img_elem);
285 |
286 | item.append(avatar);
287 |
288 | // posted-comment-container
289 | var post_container = $('');
290 | post_container.addClass('posted-comment-container').addClass('pull-left');
291 |
292 | // posted-comment-head
293 | var post_head = $('');
294 | post_head.addClass('posted-comment-head');
295 |
296 | // user-fullname
297 | var username = $('');
298 | username.addClass('posted-comment-author');
299 | username.html(comment_info.fullname);
300 |
301 | post_head.append(username);
302 |
303 | // in reply-to
304 | if(comment_info.parent_id!=0)
305 | {
306 | // in-reply-to
307 | var in_reply_to = $('');
308 | in_reply_to.addClass('in-reply-to');
309 | in_reply_to.attr('title', 'in reply-to');
310 |
311 | // arrow
312 | var arrow = $('');
313 | arrow.addClass('ui-icon');
314 | arrow.addClass('ui-icon-arrow-1-e');
315 |
316 | in_reply_to.append(arrow);
317 |
318 | post_head.append(in_reply_to);
319 |
320 | // user-fullname reply
321 | var username_reply = $('');
322 | username_reply.addClass('posted-comment-author-reply');
323 | username_reply.html(comment_info.in_reply_to);
324 |
325 | post_head.append(username_reply);
326 | }
327 |
328 | // dot
329 | var dot = $('');
330 | dot.addClass('dot');
331 | dot.html('•');
332 |
333 | post_head.append(dot);
334 |
335 | // posted time
336 | var posted_date = $('');
337 | posted_date.addClass('real-time');
338 | posted_date.attr('title', self.timeStringToABBR_(comment_info.posted_date));
339 | posted_date.html(comment_info.posted_date);
340 | posted_date.timeago();
341 |
342 | post_head.append(posted_date);
343 |
344 | post_container.append(post_head);
345 |
346 | // posted-comment-body
347 | var post_body = $('');
348 | post_body.addClass('posted-comment-body');
349 |
350 | // posted-comment-txt
351 | var post_txt = $('');
352 | post_txt.addClass('posted-comment-txt');
353 | post_txt.html(comment_info.text);
354 |
355 | post_body.append(post_txt);
356 |
357 | post_container.append(post_body);
358 |
359 | // posted-comment-foot
360 | var post_foot = $('');
361 | post_foot.addClass('posted-comment-foot');
362 |
363 | // edit
364 | if(self.user_info_.is_edit_allowed && (comment_info.created_by==self.user_info_.user_id))
365 | {
366 | // form edit
367 | var form_edit_container = $('');
368 | form_edit_container.addClass('posted-comment-form-edit');
369 | form_edit_container.hide();
370 | var form_edit_elem = self.buildForm_(comment_info.comment_id, comment_info.parent_id);
371 | form_edit_container.append(form_edit_elem);
372 |
373 | post_body.append(form_edit_container);
374 |
375 |
376 | var edit_container = $('');
377 | edit_container.addClass('post-edit');
378 |
379 | var edit = $('Edit');
380 | edit.attr('href','#');
381 | edit.attr('title','Edit');
382 |
383 | edit_container.append(edit);
384 |
385 | post_foot.append(edit_container);
386 |
387 | var dot = $('');
388 | dot.addClass('dot');
389 | dot.html('•');
390 |
391 | post_foot.append(dot);
392 |
393 | // edit events-apply
394 | edit.on('click', function(e){
395 | e.preventDefault();
396 | post_txt.toggle();
397 |
398 | form_edit_container.toggle();
399 | var textarea = $('textarea', form_edit_container);
400 | textarea.val(post_txt.html());
401 | textarea.autogrow();
402 | textarea.focus();
403 | });
404 | }
405 |
406 | // delete
407 | if(self.user_info_.is_edit_allowed && (comment_info.created_by==self.user_info_.user_id))
408 | {
409 | var delete_container = $('');
410 | delete_container.addClass('post-delete');
411 |
412 | var delete_ = $('Delete');
413 | delete_.attr('href','#');
414 | delete_.attr('title','Delete');
415 |
416 | delete_container.append(delete_);
417 |
418 | post_foot.append(delete_container);
419 |
420 | var dot = $('');
421 | dot.addClass('dot');
422 | dot.html('•');
423 |
424 | post_foot.append(dot);
425 |
426 | // delete events-apply
427 | delete_.on('click', function(e){
428 | e.preventDefault();
429 | self.buildDeleteConfirm_(comment_info.comment_id);
430 | });
431 | }
432 |
433 | // reply
434 | if(self.user_info_.is_add_allowed)
435 | {
436 | var reply_container = $('');
437 | reply_container.addClass('post-reply');
438 |
439 | var reply = $('Reply');
440 | reply.attr('href','#');
441 | reply.attr('title', 'Reply');
442 |
443 | reply_container.append(reply);
444 |
445 | post_foot.append(reply_container);
446 | }
447 |
448 | post_container.append(post_foot);
449 |
450 |
451 | item.append(post_container);
452 |
453 | var clear = $('');
454 | clear.addClass('clear');
455 |
456 | item.append(clear);
457 |
458 | var ul_child_elem = $('');
459 | ul_child_elem.addClass('posted-comment-childs');
460 | ul_child_elem.attr('id', 'posted-comment-child-'+comment_info.comment_id);
461 |
462 | // postbox reply will be toggled show/hide by reply event
463 | if(self.user_info_.is_add_allowed)
464 | {
465 | var postbox = self.buildPostBox_(comment_info.comment_id);
466 | postbox.hide();
467 | ul_child_elem.append(postbox);
468 |
469 | // reply events-apply
470 | reply.on('click', function(e){
471 | e.preventDefault();
472 | postbox.toggle();
473 | });
474 |
475 | }
476 |
477 | // check if has childrens
478 | if(comment_info.childrens.length>0)
479 | {
480 | for(var i=0;i');
498 | self.$total_comment.addClass('comment-length');
499 | }
500 |
501 | self.$total_comment.html(self.total_comment+' '+self.options.title);
502 |
503 | return self.$total_comment;
504 | },
505 |
506 | removeItemList_: function( comment_id ){
507 | var self = this;
508 |
509 | // find target
510 | var target = $('#posted-'+comment_id, self.$elem);
511 |
512 | // remove target
513 | target.remove();
514 | },
515 |
516 | display_: function() {
517 | var self = this;
518 |
519 | self.$comment_display = $('');
520 | self.$comment_display.addClass('comments-display');
521 |
522 | var tc = self.buildCountList_(self.total_comment);
523 | self.$comment_display.append(tc);
524 |
525 | // default comment post form reply
526 | var postbox = self.buildPostBox_(null);
527 | self.$comment_display.append(postbox);
528 |
529 | self.$rootlist = self.buildUl_();
530 | self.$rootlist.append(self.comments);
531 |
532 | self.$comment_display.append(self.$rootlist);
533 |
534 |
535 | if ( self.options.transition === 'none' || !self.options.transition ) {
536 | self.$elem.html( self.$comment_display );
537 | } else {
538 | self.$elem[ self.options.transition ]( 500, function() {
539 | self.$elem.html( self.$comment_display )[ self.options.transition ]( 500 );
540 | });
541 | }
542 | },
543 |
544 | timeStringToABBR_: function( time_string ) {
545 | var abbr_str = '';
546 |
547 | var split = time_string.split(' ');
548 |
549 | if(split.length==0)
550 | return abbr_str;
551 |
552 | abbr_str = split[0]+'T';
553 |
554 | if(split.length==2)
555 | abbr_str += split[1]+'Z';
556 |
557 | return abbr_str;
558 | },
559 |
560 | buildDeleteConfirm_: function( comment_id ) {
561 | var self = this;
562 |
563 | var delete_confirm = $('div[id="dialog-delete-comment-confirm"]');
564 |
565 | if(delete_confirm.length==0)
566 | {
567 | delete_confirm = $('');
568 | delete_confirm.attr('id', 'dialog-delete-comment-confirm');
569 | delete_confirm.attr('title', 'Confirmation');
570 |
571 | var p = $('');
572 |
573 | var icon_alert = $('');
574 |
575 | var message = $('Are You sure want to delete this data?');
576 |
577 | p.append(icon_alert);
578 | p.append(message);
579 | delete_confirm.append(p);
580 | delete_confirm.hide().appendTo('body');
581 | }
582 |
583 | return delete_confirm.dialog({
584 | autoOpen: true,
585 | modal: true,
586 | buttons: {
587 | Yes: function () {
588 | var form_data = { 'comment_id': comment_id };
589 |
590 | $.ajax({
591 | url: self.options.url_delete,
592 | data: form_data,
593 | type: 'post',
594 | dataType: 'json',
595 | }).done( function(result){
596 |
597 | if(result.success!=undefined)
598 | {
599 | if(result.success===false)
600 | {
601 | // error
602 | $.each(result, function(key, val){
603 | // check error if any
604 | if(val.error!=undefined)
605 | {
606 | $show_warning_(val.error);
607 | return false;
608 | }
609 | });
610 | }
611 | else
612 | {
613 | self.removeItemList_(comment_id);
614 |
615 | self.total_comment = result.total_comment;
616 |
617 | self.$total_comment.html(self.total_comment+' '+self.options.title);
618 |
619 | delete_confirm.dialog("close");
620 | }
621 | }
622 | });
623 | },
624 | No: function () {
625 | delete_confirm.dialog("close");
626 | }
627 | }
628 | });
629 | },
630 |
631 | limit_: function( obj, count ) {
632 | return obj.slice( 0, count );
633 | }
634 | };
635 |
636 | $.fn.comment = function( options ) {
637 | return this.each(function() {
638 | var comment = Object.create( Comment );
639 |
640 | comment.init_( options, this );
641 |
642 | $.data( this, 'comment', comment );
643 | });
644 | };
645 |
646 | // options
647 | $.fn.comment.options = {
648 | title: 'Notes',
649 | url_get: '#',
650 | url_input: '#',
651 | url_delete: '#',
652 | wrapEachWith: '',
653 | limit: 10,
654 | auto_refresh: true,
655 | refresh: null,
656 | onComplete: null,
657 | transition: 'fadeToggle',
658 | };
659 |
660 | })(jQuery, window, document);
661 |
--------------------------------------------------------------------------------
/js/jquery.timeago.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Timeago is a jQuery plugin that makes it easy to support automatically
3 | * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
4 | *
5 | * @name timeago
6 | * @version 1.0.2
7 | * @requires jQuery v1.2.3+
8 | * @author Ryan McGeary
9 | * @license MIT License - http://www.opensource.org/licenses/mit-license.php
10 | *
11 | * For usage and examples, visit:
12 | * http://timeago.yarp.com/
13 | *
14 | * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
15 | */
16 |
17 | (function (factory) {
18 | if (typeof define === 'function' && define.amd) {
19 | // AMD. Register as an anonymous module.
20 | define(['jquery'], factory);
21 | } else {
22 | // Browser globals
23 | factory(jQuery);
24 | }
25 | }(function ($) {
26 | $.timeago = function(timestamp) {
27 | if (timestamp instanceof Date) {
28 | return inWords(timestamp);
29 | } else if (typeof timestamp === "string") {
30 | return inWords($.timeago.parse(timestamp));
31 | } else if (typeof timestamp === "number") {
32 | return inWords(new Date(timestamp));
33 | } else {
34 | return inWords($.timeago.datetime(timestamp));
35 | }
36 | };
37 | var $t = $.timeago;
38 |
39 | $.extend($.timeago, {
40 | settings: {
41 | refreshMillis: 60000,
42 | allowFuture: false,
43 | strings: {
44 | prefixAgo: null,
45 | prefixFromNow: null,
46 | suffixAgo: "ago",
47 | suffixFromNow: "from now",
48 | seconds: "less than a minute",
49 | minute: "about a minute",
50 | minutes: "%d minutes",
51 | hour: "about an hour",
52 | hours: "about %d hours",
53 | day: "a day",
54 | days: "%d days",
55 | month: "about a month",
56 | months: "%d months",
57 | year: "about a year",
58 | years: "%d years",
59 | wordSeparator: " ",
60 | numbers: []
61 | }
62 | },
63 | inWords: function(distanceMillis) {
64 | var $l = this.settings.strings;
65 | var prefix = $l.prefixAgo;
66 | var suffix = $l.suffixAgo;
67 | if (this.settings.allowFuture) {
68 | if (distanceMillis < 0) {
69 | prefix = $l.prefixFromNow;
70 | suffix = $l.suffixFromNow;
71 | }
72 | }
73 |
74 | var seconds = Math.abs(distanceMillis) / 1000;
75 | var minutes = seconds / 60;
76 | var hours = minutes / 60;
77 | var days = hours / 24;
78 | var years = days / 365;
79 |
80 | function substitute(stringOrFunction, number) {
81 | var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
82 | var value = ($l.numbers && $l.numbers[number]) || number;
83 | return string.replace(/%d/i, value);
84 | }
85 |
86 | var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
87 | seconds < 90 && substitute($l.minute, 1) ||
88 | minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
89 | minutes < 90 && substitute($l.hour, 1) ||
90 | hours < 24 && substitute($l.hours, Math.round(hours)) ||
91 | hours < 42 && substitute($l.day, 1) ||
92 | days < 30 && substitute($l.days, Math.round(days)) ||
93 | days < 45 && substitute($l.month, 1) ||
94 | days < 365 && substitute($l.months, Math.round(days / 30)) ||
95 | years < 1.5 && substitute($l.year, 1) ||
96 | substitute($l.years, Math.round(years));
97 |
98 | var separator = $l.wordSeparator || "";
99 | if ($l.wordSeparator === undefined) { separator = " "; }
100 | return $.trim([prefix, words, suffix].join(separator));
101 | },
102 | parse: function(iso8601) {
103 | var s = $.trim(iso8601);
104 | s = s.replace(/\.\d+/,""); // remove milliseconds
105 | s = s.replace(/-/,"/").replace(/-/,"/");
106 | s = s.replace(/T/," ").replace(/Z/," UTC");
107 | s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
108 | return new Date(s);
109 | },
110 | datetime: function(elem) {
111 | var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
112 | return $t.parse(iso8601);
113 | },
114 | isTime: function(elem) {
115 | // jQuery's `is()` doesn't play well with HTML5 in IE
116 | return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
117 | }
118 | });
119 |
120 | $.fn.timeago = function() {
121 | var self = this;
122 | self.each(refresh);
123 |
124 | var $s = $t.settings;
125 | if ($s.refreshMillis > 0) {
126 | setInterval(function() { self.each(refresh); }, $s.refreshMillis);
127 | }
128 | return self;
129 | };
130 |
131 | function refresh() {
132 | var data = prepareData(this);
133 | if (!isNaN(data.datetime)) {
134 | $(this).text(inWords(data.datetime));
135 | }
136 | return this;
137 | }
138 |
139 | function prepareData(element) {
140 | element = $(element);
141 | if (!element.data("timeago")) {
142 | element.data("timeago", { datetime: $t.datetime(element) });
143 | var text = $.trim(element.text());
144 | if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
145 | element.attr("title", text);
146 | }
147 | }
148 | return element.data("timeago");
149 | }
150 |
151 | function inWords(date) {
152 | return $t.inWords(distance(date));
153 | }
154 |
155 | function distance(date) {
156 | return (new Date().getTime() - date.getTime());
157 | }
158 |
159 | // fix for IE6 suckage
160 | document.createElement("abbr");
161 | document.createElement("time");
162 | }));
163 |
--------------------------------------------------------------------------------