First, on the personal site of the message page, you can see the effect: Message board
There's also an effect chart here.
In order to save the front end, use jquery to write, backstage use PHP simple read and write MySQL database. database design and implementation ideas
The database creates a table: comments, structure as follows:
All comments (including article comment reply, message board) are written in the same table, different comment areas with field belong distinguish
In the same comment area, the parent is 0 for comments, parent for a certain value of the comments expressed as the reply, the idea is not complicated.
Note, here does not speak CSS, everyone according to their needs customization, now start Packaging: set the function
We have to set the function according to their own needs, first of all, my website does not realize message reminders, instant Messaging functions, so comments reply will not prompt webmaster or users, will only have effect on the message area, so we simply realize the following functions:
Show Comments List
Ability to submit comments
Reply to comment class
We encapsulate the functionality of the comments into a class that can be instantiated to create different comment areas, so it's not hard to think
When instantiated, we need to pass in parameters that might include the ID of the comment area, the PHP address for the comment, and the PHP address for submitting the comment.
So we can assume that the code for the instantiated comment area might be:
var ocmt = new Comment ({
Parent: $ (' #box '), //You want to put this comment on the page which element
id:0,
getcmturl: './php/ Getcomment.php ',
setcmturl: './php/comment.php '
})
Of course, I'm defining a static method on the comment class.
Comment.allocate ({
Parent: $ (' #box '),
id:0,
getcmturl: './php/getcomment.php ',
setcmturl: './php/ comment.php '
})
It's a different place, just the initialization. Constructors
function Comment (options) {
this.belong = options.id;
This.getcmturl = Options.getcmturl;
This.setcmturl = Options.setcmturl;
This.lists = [];
This.keys = {};
This.offset = 5;
}
var fn = Comment.prototype;
Comment.allocate = function (options) {
var ocmt = new Comment (options);
if (Ocmt.belong = = undefined | |!ocmt.getcmturl | |!ocmt.setcmturl) {return
null;
};
Ocmt.init (options);
return OCMT;
};
Inside the variables and methods we slowly explain, if you do not define a allocate method, then you can write:
function Comment (options) {
this.belong = options.id;
This.getcmturl = Options.getcmturl;
This.setcmturl = Options.setcmturl;
This.lists = [];
This.keys = {};
This.offset = 5;
if (This.belong = = undefined | |!this.getcmturl | |!this.setcmturl) {return
null;
};
This.init (Options)
}
var fn = Comment.prototype;
Variable first, like I write the function first, and then need to add the property variable to go back to add, we just need to see the constructor finally executed:
This.init (Options)
The name can be seen as the initialization function. init function
Fn.init = function (options) {
//Initialize node
this.initnode (options);
Putting the contents into the container
this.parent.html (this.body);
Initialize event
this.initevent ();
Get list
this.getlist ();
};
fn for Comment.prototype, only say once, the following is no longer said.
Initialization is to have 4 jobs to do, from the code annotation can be seen, now a explain initnode function
The primary initialization node or cache Dom can be seen from the name
Fn.initnode = function (options) {//init wrapper box if (!!
options.parent) {this.parent = Options.parent[0].nodetype = 1? Options.parent: $ (' # ' + options.parent);
};
if (!this.parent) {this.parent = $ (' div ');
$ (' body '). Append (this.parent);
}//init Content This.body = (function () {var strhtml = ' <div class= ' m-comment ' > ' + "<div class=" Cmt-form "> ' + ' <textarea class=" Cmt-text "placeholder=" welcome suggestions, Ask questions and learn together.
"></textarea> ' + ' <button class=" U-button u-login-btn "> Submit comments </button> ' +
' </div> ' + ' <div class= ' cmt-content ' > ' + ' <div class= ' u-loading1 ' ></div> ' + ' <div class= ' NO-CMT ' > Not yet
Comments </div> ' + ' <ul class= ' cmt-list ' ></ul> ' + ' <div class= ' f-clear ' > ' + ' <div class= ' Pager-box ' &G
T;</div> ' + ' </div> ' + ' </div> ' +
' </div> ';
return $ (strhtml);
})();
init other node This.text = This.body.find ('. Cmt-text ')-eq (0);
THIS.CMTBTN = This.body.find ('. U-button '). EQ (0);
THIS.NOCMT = This.body.find ('. NO-CMT '). EQ (0);
This.cmtlist = This.body.find ('. Cmt-list '). EQ (0);
this.loading = This.body.find ('. u-loading1 '). EQ (0);
This.pagerbox = This.body.find ('. Pager-box '). EQ (0); };
In the code we can see that:
This.parent: The container node is saved
This.body: The HTML of the comment area is saved
This.text: Preserving the TEXTAREA elements of the commentary
THIS.CMTBTN: Save the Submit button
THIS.NOCMT: Save a text reminder when there is no comment
This.cmtlist: The container for the list is saved
This.loading: Save a loading GIF picture when loading a list
This.pagerbox: Pager Container When paging is required
JS is not difficult, are some jquery method to put the content into the container
This.parent.html (This.body)
This is nothing to say, very simple, at this time our comment component should be displayed on the page, but now does not load the comment list, also cannot comment, the following first load comment list getlist function
The first is to initialize the list, empty it, display the loaded GIF, hide the warning words without comments, and prepare to initiate the AJAX request.
The idea is to use PHP to all the comments in the comment area down, in front of the finishing, Ajax request for:
Fn.resetlist = function () {
this.loading.css (' Display ', ' block ')
this.noCmt.css (' Display ', ' none ');
This.cmtList.html (");
Fn.getlist = function () {var self = this;
This.resetlist ();
$.ajax ({url:self.getCmtUrl, type: ' Get ', DataType: ' JSON ', data: {Id:self.belong},
Success:function (data) {if (!data) {alert (' Get comment list failed ');
Return! 1;
};
Organize comments list self.initlist (data);
Self.loading.css (' Display ', ' none '); Show Comments List if (self.lists.length = 0) {//No comment self.noCmt.css (' Display ', ' block
');
}else{//Set Page separator var total = Math.ceil (Self.lists.length/self.offset); Self.pager = new Pager ({index:1, total:total, parent:self.
Pagerbox[0], onchange:self.doChangePage.bind (self), label:{
Prev: ' < ', Next: ' > ' }
});
}, Error:function () {alert (' Get comment list failed ');
}
}); };
Get form, and then the transfer ID passed, and the resulting data wanted to be an array of lists.
PHP content does not speak, the following post the SQL statement:
$id = $_get[' id '];
$query = "SELECT * from comments where belong= $id order by Time";
...
$str = ' [';
foreach ($result as $key => $value) {
$id = $value [' id '];
$username = $value [' username '];
$time = $value [' time '];
$content = $value [' content '];
$parent = $value [' parent '];
$str. = <<<end
{
"id": "{$id}",
"parent": "{$parent}",
"username": "{$username. '",
' time ': ' {$time} ',
' content ': ' {$content} ',
' response ': []
} end
;
}
$str = substr ($str, 0,-1);
$str. = '] ';
Echo $str;
Get a JSON string, jquery Ajax can turn it into JSON data, and get the following data:
If the load succeeds, then we get a bunch of data, we are now in the success callback function, the data needs to be sorted in order to display, because now all comments are back to the same level. initlist function
Fn.initlist = function (data) {
this.lists = []; Save Comment List
This.keys = {}; Save Comment ID and index corresponding table
var index = 0;
Traversal processing for
(var i = 0, len = data.length i < len; i++) {
var t = data[i],
id = t[' id '];
if (t[' parent '] = = 0) {
This.keys[id] = index++;
This.lists.push (t);
} else{
var parentid = t[' parent ',
parentindex = This.keys[parentid];
this.lists[parentindex][' response '].push (t);}};
My train of thought is: This.lists put are comments (parent 0 message), through the traversal of the data, if the parent is 0, push into this.lists; otherwise, the parent is not 0 means that this is a reply, find the corresponding comments, the reply to push into the comments of the RESP In Onse.
But there is a problem, because the ID is growing, there may be some comments are deleted, so ID and index does not necessarily match, so with This.keys save ID and index of the corresponding relationship.
Traversing all of the data can be done, and all of the this.lists, and then the rest of the thing is to turn the data into HTML and put it in the page.
Show Comments List
if (self.lists.length = 0) {
//No comment
self.noCmt.css (' Display ', ' block ');
} else{
//Set page separator
var total = Math.ceil (self.lists.length/self.offset);
Self.pager = new Pager ({
index:1,
total:total,
parent:self.pagerbox[0],
onchange: Self.doChangePage.bind (self),
label:{
prev: ' < ',
Next: ' > '
}}
This is part of the callback function that was just ajax,success, which is when the data is sorted, and if the data is empty, then "no comment is displayed".
Otherwise, set the pager, the pager I used directly before the package, if interested can look at my previous blog:
Object-oriented: pager encapsulation
In short, it's going to go through the onchange function, the default number of pages is 1, stored in the parameter Obj.index
Fn.dochangepage = function (obj) {
this.showlist (obj.index);
};
showlist function
Fn.showlist = (function () {/* generates a comment String */function Oneli (_obj) {var str1 = ';
Processing reply for (var i = 0, len = _obj.response.length i < len; i++) {var t = _obj.response[i];
T.content = T.content.replace (/\<\;/g, ' < ');
T.content = T.content.replace (/\>\;/g, ' > '); str1 + = ' <li class= ' f-clear ' ><table><tbody><tr><td> ' + ' <span class= ' user Name ' > ' + t.username + ':</span></td><td> ' + ' <span class= ' child-content ' > ' + t
. Content + ' </span></td></tr></tbody></table> ' + ' </li> '}
Process comment var headimg = ';
if (_obj.username = = "Kang") {headimg = ' kang_head.jpg ';
}else{var index = Math.floor (Math.random () * 6) + 1; headimg = ' head ' + index + '. jpg '} _obj.content = _oBj.content.replace (/\<\;/g, ' < ');
_obj.content = _obj.content.replace (/\>\;/g, ' > '); var str2 = ' <li class= ' f-clear ' > ' + ' <div class= ' head g-col-1 ' > ' + ' ' + ' </div> ' + ' <div class=" content g-col-19 "> ' + ' <div class= ' f-clear ' > ' + ' <span class= ' username f-float-left ' > ' + _obj.username + ' </span> ' + ' <span class= ' time F-float-left ' > ' + _obj.time + ' </span> ' + ' </ Div> ' + ' <span class= "parent-content" > ' + _obj.content + ' </span> ' + ' <ul class = "Child-comment" > ' + str1 + ' </ul> ' + ' </div> ' + ' <div class= ' Respone-box g-col- 2 F-float-right "> ' + ' <a href=" javascript:void (0); "class=" f-show response "data-id=" ' + _obj.id + ' "" ;
[Reply]</a> ' + ' </div> ' + ' </li> ';
return str2;
};
return function (page) {var len = this.lists.length, end = Len-(page-1) * This.offset, Start = End-this.offset < 0?
0:end-this.offset, current = This.lists.slice (start, end);
var cmtlist = '; for (var i = current.length-1 i >= 0; i--) {var t = current[i], index = this.keys[t[' id ']
];
current[i][' index '] = index;
Cmtlist + = Oneli (t);
} this.cmtList.html (Cmtlist);
}; })();
The argument for this function is page, which is the number of pages, we intercept the this.lists data based on the number of pages, and then iterate through the generated HTML.
HTML templates I'm connected by strings, and I'm looking at people's preferences.
After the build this.cmtList.html (cmtlist), so that the list is displayed, the effect of the beginning of the picture.
The functionality that is needed now is commented back, and the Init function is left with only the last initevent initevent function
Fn.initevent = function () {
//submit button click
this.cmtBtn.on (' click ', This.addCmt.bind (this, this.cmtbtn, This.text, 0 ));
Click Reply, click Cancel Reply, click the Submit Comment button in reply
this.cmtList.on (' click ', This.doClickResponse.bind (this));
The screenshot above comes from my personal website, when we click Reply, we want to have a place to write the reply, can submit, can cancel, because these elements are added later, so we will host the behavior to the comment list this element.
The comment event function is submitted below. ADDCMT function
FN.ADDCMT = function (_btn, _text, _parent) {//Prevent multiple clicks if (_btn.attr (' data-disabled ') = = ' true ') {return!
1;
//Process Submit blank var value = _text.val (). Replace (/^\s+|\s+$/g, ');
Value = Value.replace (/[\r\n]/g, ' <br > ');
if (!value) {alert (' content cannot be empty ');
Return! 1;
//No click on _btn.attr (' data-disabled ', ' true ');
_btn.html (' comments submitted ... ');
Submit processing var self = this, email, username;
Username = $.cookie (' user ');
if (!username) {username = ' visitor ';
email = $.cookie (' email ');
if (!email) {email = ' default@163.com ';
var now = new Date (); $.ajax ({type: ' Get ', DataType: ' json ', URL:THIS.SETCMTURL, data: {belong:s Elf.belong, Parent: _parent, Email:email, Username:username, Content:va Lue}, Success:function (_data) {//Unblock click _btn.attr (' Data-disabled ', ');
_btn.html (' submit comments ');
if (!_data) {alert (' comment failed, please comment again ');
Return! 1;
} if (_data[' result '] = = 1) {//Comment success alert (' comment success '); var id = _data[' id ', time = now.getfullyear () + '-' + (Now.getmonth () + 1) + '-' + now.getdate () + '
' + now.gethours () + ': ' + now.getminutes () + ': ' + now.getseconds ();
if (_parent = = 0) {var index = self.lists.length;
if (!self.pager) {//Set pager self.noCmt.css (' Display ', ' none ');
var total = Math.ceil (Self.lists.length/self.offset);
Self.pager = new Pager ({index:1, total:total, Paren