如何实施上下投票?

Mag*_*gic 10 javascript php post

如果你已经使用Stack Overflow一段时间,你肯定已经使用了问题和答案的上下投票功能.我注意到Stack Overflow使用<a>锚点.但我不知道如何将数据发布到服务器.我认为这是与此相关的JavaScript <a>,但我找不到它.我该如何实现它?

T.J*_*der 12

是的,涉及JavaScript.有两个部分:为投票"按钮"上的点击事件挂钩处理程序,并将数据发送到服务器.

在其他地方很好地讨论了这些事件,我不会在这里讨论.

将数据发送到服务器,您可以使用ajax.DIY方式看起来大致如此(但实际上并没有使用此代码,见下文):

var xhr = new XMLHttpRequest();
xhr.open("POST", "/path/to/server/destination");
xhr.onreadystatechange = handleStateChange;
xhr.send("id=" + encodeURIComponent(id) +
         "&user=" + encodeURIComponent(userId) +
         "&vote=up");
function handleStateChange() {
    if (xhr.readyState === 4) {
        // POST complete
        if (xhr.status === 200) {
            // POST complete and we have response, check it
            if (xhr.responseText !== "ok") { // Or whatever you want it to be
                // Report problem
            }
        } else {
            // Ajax failed, handle/report problem
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以上XMLHttpRequest部分仅适用于现代浏览器; 对于早期版本的IE而言,您必须使用fetch.看这里的例子(虽然我一直认为这是相当复杂的).

这是一个例子,说明浏览器与浏览器的不同之处.在进行丰富的Web编程时,存在很多这些小的浏览器差异(包括挂钩事件处理程序!),因此我建议使用一个良好的,良好支持的库来平滑那些并提供大量实用功能.你有很多选择:jQuery,Prototype,YUI,Closure,或其他任何一个.

以上是使用jQuery的内容:

var body = new FormData();
body.append("id", id);
body.append("user", userId);
body.append("vote", "up");
fetch("/path/to/server/destination", {
    method: "POST",
    body: body
})
.then(function(res) {
    if (!res.ok) {
        throw new Error("HTTP error " + res.status);
    }
    return res.text(); // or `res.json()` if you return JSON
})
.then(function(data) {
    if (data !== "ok") { // Or whatever
        // Report problem
    }
})
.catch(function(error) {
    // Ajax failed, handle/report problem
});
Run Code Online (Sandbox Code Playgroud)

......其他库将提供类似的帮助功能.

(这两个例子 - 无论是DIY方式还是jQuery方式 - 都没有正确处理HTTP错误,这自然是你想做的,但这会给你一个想法.)


更新:

而且只是为了好玩,这里有一个使用jQuery的完整示例(但我不是在推jQuery;你可以做一些非常相似的事情,可能就像上面提到的任何其他库一样简单;对我来说这对我来说最简单使用jQuery删除示例,因为这是我目前使用的库):

HTML:

<div class="article" data-itemid="427">
<a href="voteup"   class="vote up"  >Up</a>
<a href="votedown" class="vote down">Down</a>
<!-- ...the contents of the item... -->
</div>
Run Code Online (Sandbox Code Playgroud)

使用jQuery的JavaScript:

document.addEventListener("click", function(event) {
    // Regardless of the below, we handle the event, so "consume" it
    event.stopPropagation();
    event.preventDefault();

    // Get the anchor element
    var voteLink = event.target.closest("a.vote");
    if (!voteLink) {
        // Didn't find one, bail
        return;
    }

    // See if the vote has already been done or is in progress
    if (voteLink.classList.contains("done") || voteLink.classList.contains("inprogress")) {
        // Ignore the click, possibly tell the user why
        return;
    }

    // Get the vote type
    var voteType = voteLink.classList.contains("up") ? "up" : "down";

    // Get the item we"re voting on
    var item = voteLink.closest(".article");

    // Get its ID
    var itemId = item.getAttribute("data-itemid");

    // If we didn"t get an ID...
    if (!itemId) {
        // ...report error
        return;
    }

    // Mark "in progress" and initiate the vote; action continues
    // in our callbacks below
    voteLink.classList.add("inprogress");
    var body = new FormData();
    body.append("itemId", itemId);
    body.append("voteType", voteType);
    fetch("savevote", {
        method: "POST",
        body:   body
    })
    .then(function(res) {
        if (!res.ok) {
            throw new Error("HTTP error " + res.status);
        }
        return res.text(); // or `res.json()` if you return JSON
    })
    .then(function(data) {
        if (data === "ok") { // Or whatever
            voteLink.classList.add("done");
        } else {
            // Report an error to the user, the server couldn"t record the vote
        }
    })
    .catch(function(error) {
        // Ajax failed, handle/report problem
    })
    .finally(function() {
        // Not in progress anymore
        voteLink.classList.remove("inprogress");
    });
});
Run Code Online (Sandbox Code Playgroud)

一些说明:

  • 上面的所有代码都包含在我传递给href函数的函数中.这告诉jQuery在DOM"准备好"(更多)时运行代码.或者,只需将href标签放在标签的底部href(此处此处更多).
  • 我已经data-在链接上(StackOverflow没有),所以如果禁用JavaScript,我们可以回到我们允许用户使用表单提交或某事投票的页面.此外,链接closest由浏览器(标签目标等)专门处理,因此这对于可访问性非常有用.(要真的这样做,我可能还要把文章ID放在那里closest.)
  • 我在一个contains属性中存储我们正在投票的项目的ID .
  • 我们通过将"最近"的文章定位到单击的按钮来找到要投票的项目.jQuery的!voteLink || !this.contains(voteLink)功能与元素开始,并检查该元素,那么它的父,那么父母等,直到它找到你通过CSS选择器匹配所以投票按钮与文章相关的围堵.被投票的文章包含投票按钮.
  • 我正在使用POST,因为调用会更改服务器状态,因此GET不合适
  • ajax帖子的回调是闭包(注意它们是如何被定义 !voteLink,我XMLHttpRequest在其中使用,即使它是变量fetch).闭包并不复杂,但有一些事情重要的是要了解它们,我试图在那篇链接文章中解决这些问题.
  • 我正在使用jQuery的href功能,这是一种进行事件委托的机制.这样,我可以动态地添加项目以对页面进行投票,而不用担心将处理程序连接到他们的投票按钮.