Personal website message page (written by jQuery at the front end, written by php at the backend), jquerymysql

Source: Internet
Author: User

Personal website message page (written by jQuery at the front end, written by php at the backend), jquerymysql

First, you can see the effect on the personal website's message page: message board.

The front end uses jQuery for ease of writing and php for simple reading and writing of MySQL databases in the background.

Database Design and Implementation

The database creates a table: comments. The structure is as follows:

All comments (including comments, replies, and message boards) are written in the same table. The field belong is used for different comment areas.

In the same comment area, if parent is 0, it indicates the comment, and if parent is a value, it indicates the reply of the comment. The thought is not complicated.

Note: CSS is not mentioned here. You can customize it based on your own needs. Now you can encapsulate it:

Set Function

We set a function based on our own needs. First, my website does not implement the message reminder and instant messaging function. Therefore, the webmaster or user will not be prompted for comments and replies, it will only have an effect on the message area, so we only need to simply implement the following functions:

1. display the comment list

2. can submit comments

3. Reply

Comments

We encapsulate the comment function into a class and create different comment Areas Through instantiation, so it is not difficult to think of it,

During instantiation, the input parameters may include the id of the comment area, the php address for obtaining the comment, and the php address for submitting the comment.

So we can guess that the code for instantiating the comment area may be:

Var oCmt = new Comment ({parent: $ ('# box'), // id: 0, getCmtUrl :'. /php/getcomment. php ', setCmtUrl :'. /php/comment. php '})

Of course, I define a static method on the Comment class.

Comment.allocate({ parent: $('#box'), id: 0, getCmtUrl: './php/getcomment.php', setCmtUrl: './php/comment.php'})

Similar, but the initialization is different.

Constructor

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;};

We will explain the variables and Methods. If you do not define an allocate method, you can write it as follows:

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;

Let's not talk about the variable first. For example, I write the function first, and then add the attribute variable. We only need to see that the constructor has finally executed:

This. init (options)

The name indicates the initialization function.

Init Function

Fn. init = function (options) {// initialize node this. initNode (options); // put the content into the container this.parent.html (this. body); // initialization event this. initEvent (); // obtain the list this. getList ();};

Fn is Comment. prototype, which is only once.

There are four tasks to do during initialization. From the code comments, we can see that one by one

InitNode Function

It can be seen from the name that the main initialization node or cache dom

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 and 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"> no comment </div> '+' <ul class = "cmt-list"> </ul> '+' <div class = "f-clear"> '+' <div class = "pager-box"> </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: saves the html of the comment area.
This. text: saves the textarea element of the comment.
This. cmtBtn: The submit button is saved.
This. noCmt: saves text reminders when no comments exist.
This. cmtList: the container that saves the list
This. loading: stores the loading GIF image when the list is loaded.
This. pagerBox: The page sharer container when paging is required

There are no difficulties in js. They are all jQuery methods.

Put the content in the container

This.parent.html (this. body)

There is nothing to talk about. It is very simple. At this time, our comment component should be displayed on the page, but the comment list is not loaded now, and no comment can be made. Next we will first talk about loading the comment list.

GetList Function

First, initialize the list, clear the list, display the loaded gif image, hide the words without comments, and initiate an ajax request when you are ready.

The idea is to use php to get all the messages in the comment area and sort them at the front end. The ajax request is:

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', ype: 'json', data: {id: self. belong}, success: function (data) {if (! Data) {alert ('failed to get the comment list'); return! 1 ;}; // sort out the Comments list self. initList (data); self.loading.css ('display', 'None'); // display the comment list if (self. lists. length = 0) {// No comments for self.noCmt.css ('display', 'block');} else {// set the page splitter 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 ('failed to get the comment list ');}});};

Get form, and then transfer the id to the past. The expected data is a list array.

Php content is not mentioned. The following is an 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;

The json string is obtained. jQuery ajax can convert it into json data. The obtained data is as follows:

If the load is successful, we get a bunch of data. Now we are in the success callback function, and the data needs to be sorted before it can be displayed, because all comments and replies now belong to the same layer.

InitList Function

Fn. initList = function (data) {this. lists = []; // Save the comment list this. keys ={}; // Save the comment id and index corresponding to the table var index = 0; // traverse 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 idea is: this. lists puts comments (messages with parent 0). The retrieved data is traversed. If parent is 0, the request is pushed to this. lists; otherwise, if parent is not 0, it indicates that this is a reply. Then, find the corresponding comment and push the reply to the response of the comment.

However, there is another problem because the id is constantly increasing and some comments may be deleted, so the id and index do not necessarily match, so this. keys stores the correspondence between id and index.

After traversal, all the data can be organized and all the data is stored in this. lists. The rest is to turn the data into html and put it into the page.

// Display the comment list if (self. lists. length = 0) {// No comments for self.noCmt.css ('display', 'block');} else {// set the page splitter 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 of ajax and success just now. If the data is empty after data is sorted, the system displays "no comments for the moment ".

Otherwise, set the page splitter. I directly used the previously encapsulated page splitter. If you are interested, please refer to my previous articles:

Object-oriented: Page splitter Encapsulation

Simply put, the onchange function will be executed once. The default page number is 1, which is saved in the obj. index parameter.

fn.doChangePage = function (obj) { this.showList(obj.index);};

ShowList Function

Fn. showList = (function () {/* generate a comment string */function oneLi (_ obj) {var str1 = ''; // process the response 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 = "username">' + t. username + ': </span> </td> <td>' + '<span class = "child-co Ntent "> '+ t. content + '</span> </td> </tr> </tbody> </table>' + '</li>'} // process comments 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 parameter of this function is page, which is the number of pages. we extract the data of this. lists based on the number of pages, and then traverse and generate html.

Html templates are connected with strings, depending on your preferences.

After generation, this.cmtList.html (cmtList) is displayed.

Now, you still need to comment and reply to the function, and the init function only has the last initEvent.

InitEvent Function

Fn. initEvent = function () {// click this. cmtBtn. on ('click', this. addCmt. bind (this, this. cmtBtn, this. text, 0); // click "reply", click "cancel reply", and click "submit comment" in "reply. cmtList. on ('click', this. doClickResponse. bind (this ));};

The above is from my personal website. When we click "reply", we hope to have a place to write a reply, submit it, and cancel it. As these elements are added later, therefore, we host the behavior to the comment list element.

Next, we will submit the comment event function.

AddCmt Function

Fn. addCmt = function (_ btn, _ text, _ parent) {// prevent multiple clicks if (_ btn. attr ('data-disabled ') = 'true') {return! 1;} // blank var value = _ text. val (). replace (/^ \ s + | \ s + $/g, ''); value = value. replace (/[\ r \ n]/g, '<br>'); if (! Value) {alert ('content cannot be blank '); return! 1;} // do not click _ btn. attr ('data-disabled ', 'true'); _btn.html ('comments are being submitted... '); // submit for processing var self = this, email, username; username = $. cookie ('user'); if (! Username) {username = 'tourists';} email = $. cookie ('email '); if (! Email) {email = 'default @ 163.com ';} var now = new Date (); $. ajax ({type: 'get', dataType: 'json', url: this. setCmtUrl, data: {belong: self. belong, parent: _ parent, email: email, username: username, content: value}, success: function (_ data) {// unban click _ btn. attr ('data-disabled ', ''); _btn.html ('submit comments'); if (! _ Data) {alert ('comments failed, please Recomment '); return! 1;} if (_ data ['result'] = 1) {// alert ('comment successfully'); 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 the page splitter self.noCmt.css ('display', 'None'); 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: '>'});} self. keys [id] = index; self. lists. push ({"id": id, "username": username, "time": time, "content": value, "response": []}); self. showList (1); self. pager. _ $ setIndex (1);} else {var index = self. keys [_ parent], page = self. pager. _ index; self. lists [index] ['response']. push ({"id": id, "username": username, "time": time, "content": value}); self. showList (page);} self. text. val ('');} else {alert ('comment failed, Recomment ') ;}}, error: function () {alert ('comment failed, recomment '); // unban click _ btn. attr ('data-disabled ', ''); _btn.html ('submit comments ');}});}

There are three parameters: _ btn, _ text, _ parent. The reason why these three parameters are required is that the same function can be used only after comments or replies, so that they do not need to be written separately.

After clicking it, it is common to prevent multiple submissions. check whether there are username, email, and other user information in the cookie. If there is no such information, use the identity of the visitor. Then, process the content and remove the blank content, change \ n to <br>, and initiate an ajax request after verification.

Put the new comment in this. lists, and then execute this. showList (1) to refresh the display.

The SQL statement is as follows:

$ Parent = $ _ GET ['parent']; $ belong = $ _ GET ['belong']; $ content = htmlentities ($ _ GET ['content']); $ username = $ _ GET ['username']; $ email = $ _ GET ['email ']; $ query = "insert into comments (parent, belong, content, time, username, email) value ($ parent, $ belong, '$ content', NOW (),' $ username', '$ email') "; doClickResponse function fn. doClickResponse = function (_ event) {var target = Response (_event.tar get); var id = target. attr ('data- Id'); if (target. hasClass ('response') & target. attr ('data-disabled ')! = 'True') {// click to reply var oDiv = document. createElement ('div '); oDiv. className = 'cmt-form'; oDiv. innerHTML = '<textarea class = "cmt-text" placeholder = "welcome to the suggestion, ask questions, and learn together! "> </Textarea> '+' <button class =" u-button resBtn "data-id =" '+ id +' "> submit comments </button> '+' <a href = "javascript: void (0); "class =" cancel "> [cancel reply] </a> '; target. parent (). parent (). append (oDiv); oDiv = null; target. attr ('data-disabled ', 'true');} else if (target. hasClass ('cancel') {// click cancel to reply to var ppNode = target. parent (). parent (), oRes = ppNode. find ('. response '). eq (0); target. parent (). remove (); oRes. attr (' Data-disabled ', '');} else if (target. hasClass ('resbtn ') {// click to comment on var oText = target. parent (). find ('. cmt-text '). eq (0), parent = target. attr ('data-id'); this. addCmt (target, oText, parent);} else {// return in other cases! 1 ;}};

Determine which button is clicked based on target. class.

If you click "reply" to generate html, put it behind this comment

Var oDiv = document. createElement ('div '); oDiv. className = 'cmt-form'; oDiv. innerHTML = '<textarea class = "cmt-text" placeholder = "welcome to the suggestion, ask questions, and learn together! "> </Textarea> '+' <button class =" u-button resBtn "data-id =" '+ id +' "> submit comments </button> '+' <a href = "javascript: void (0); "class =" cancel "> [cancel reply] </a> '; target. parent (). parent (). append (oDiv); oDiv = null; target. attr ('data-disabled ', 'true'); // prevents repeated html generation

Click Cancel to remove the generated one.

Var ppNode = target. parent (). parent (), oRes = ppNode. find ('. response '). eq (0); target. parent (). remove (); oRes. attr ('data-disabled ', ''); // you can click the reply button again.

Click Submit to obtain the obtained element and directly call the addCmt function.

var oText = target.parent().find('.cmt-text').eq(0), parent = target.attr('data-id');this.addCmt(target, oText, parent);

Note: When the html file is generated by the parent, I saved it to the data-id of the submit button.

All of these functions have been implemented, and we hope to be inspired by your learning experience.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.