diff --git a/src/applications/ponder/view/PonderVotableView.php b/src/applications/ponder/view/PonderVotableView.php
index d4fb401b5c..0f1b10ddf6 100644
--- a/src/applications/ponder/view/PonderVotableView.php
+++ b/src/applications/ponder/view/PonderVotableView.php
@@ -47,23 +47,60 @@ final class PonderVotableView extends AphrontView {
require_celerity_resource('ponder-vote-css');
require_celerity_resource('javelin-behavior-ponder-votebox');
- Javelin::initBehavior(
- 'ponder-votebox',
+ Javelin::initBehavior('ponder-votebox', array());
+
+ $uri = id(new PhutilURI($this->uri))->alter('phid', $this->phid);
+
+ $up = javelin_render_tag(
+ 'a',
array(
- 'nodeid' => $this->phid,
- 'vote' => $this->vote,
- 'count' => $this->count,
- 'uri' => $this->uri
- ));
+ 'href' => (string)$uri,
+ 'sigil' => 'upvote',
+ 'mustcapture' => true,
+ 'class' => ($this->vote > 0) ? 'ponder-vote-active' : null,
+ ),
+ "\xE2\x96\xB2");
- $content =
- '
'.
- '
-
'.
- $this->renderChildren().
- '
';
+ $down = javelin_render_tag(
+ 'a',
+ array(
+ 'href' => (string)$uri,
+ 'sigil' => 'downvote',
+ 'mustcapture' => true,
+ 'class' => ($this->vote < 0) ? 'ponder-vote-active' : null,
+ ),
+ "\xE2\x96\xBC");
- return $content;
+ $count = javelin_render_tag(
+ 'div',
+ array(
+ 'class' => 'ponder-vote-count',
+ 'sigil' => 'ponder-vote-count',
+ ),
+ phutil_escape_html($this->count));
+
+ return javelin_render_tag(
+ 'div',
+ array(
+ 'class' => 'ponder-votable',
+ 'sigil' => 'ponder-votable',
+ 'meta' => array(
+ 'count' => (int)$this->count,
+ 'vote' => (int)$this->vote,
+ ),
+ ),
+ javelin_render_tag(
+ 'div',
+ array(
+ 'class' => 'ponder-votebox',
+ ),
+ $up.$count.$down).
+ phutil_render_tag(
+ 'div',
+ array(
+ 'class' => 'ponder-votebox-content',
+ ),
+ $this->renderChildren()));
}
}
diff --git a/webroot/rsrc/css/application/ponder/vote.css b/webroot/rsrc/css/application/ponder/vote.css
index 9e6e0e428d..31b8ac9f71 100644
--- a/webroot/rsrc/css/application/ponder/vote.css
+++ b/webroot/rsrc/css/application/ponder/vote.css
@@ -2,17 +2,45 @@
* @provides ponder-vote-css
*/
-
-
-.ponder-votable .phabricator-transaction-view {
- margin : 0;
- padding : 0;
+.ponder-votebox {
+ text-align: center;
}
-.ponder-votable .phabricator-transaction-detail {
- min-height : 90px;
+.ponder-votebox a {
+ font-size: 20px;
+ line-height: 20px;
+ display: block;
+
+ text-decoration: none;
+ color: #999999;
+ font-weight: normal;
+
+ /* Our default fonts have weirdly different up/down arrow sizes. */
+ font-family: Arial;
}
+.ponder-votebox a:hover {
+ color: #606060;
+}
+
+.ponder-votebox a.ponder-vote-active {
+ color: #3b5998;
+}
+
+.ponder-votebox a.ponder-vote-active:hover {
+ color: #a1bbe5;
+}
+
+.ponder-vote-count {
+ color: #888888;
+ font-size: 14px;
+ line-height: 14px;
+ font-weight: bold;
+}
+
+
+
+
.ponder-votebox {
float : left;
width : 32px;
@@ -21,57 +49,11 @@
margin-left : 10px;
}
-.ponder-upbutton {
- border : none;
- padding : 0;
+.ponder-votable .phabricator-transaction-view {
margin : 0;
- width : 32px;
- height : 13px;
-}
-
-.ponder-downbutton {
- border : none;
padding : 0;
- margin : 0;
- width : 32px;
- height : 13px;
}
-.ponder-votecount {
- width : 32px;
- height : 22pt;
- padding : 0;
- margin : 0;
- overflow : visible;
- text-align : center;
- font-size : 15pt;
-}
-
-.ponder-upbutton:hover {
- cursor : pointer;
-}
-
-.ponder-downbutton:hover {
- cursor : pointer;
-}
-
-.ponder-votable-bottom {
- clear : both;
-}
-
-.ponder-upbutton {
- background : url(/rsrc/image/application/ponder/upvote.png) 0 -13px no-repeat;
-}
-
-.ponder-upbutton.ponder-vote-up {
- background : url(/rsrc/image/application/ponder/upvote.png) 0 0 no-repeat;
-}
-
-.ponder-downbutton {
- background : url(/rsrc/image/application/ponder/downvote.png)
- 0 -13px no-repeat;
-}
-
-.ponder-downbutton.ponder-vote-down {
- background : url(/rsrc/image/application/ponder/downvote.png) 0 0 no-repeat;
+.ponder-votable .phabricator-transaction-detail {
+ min-height : 90px;
}
diff --git a/webroot/rsrc/image/application/ponder/downvote.png b/webroot/rsrc/image/application/ponder/downvote.png
deleted file mode 100644
index 7272a6645c..0000000000
Binary files a/webroot/rsrc/image/application/ponder/downvote.png and /dev/null differ
diff --git a/webroot/rsrc/image/application/ponder/upvote.png b/webroot/rsrc/image/application/ponder/upvote.png
deleted file mode 100644
index cb543a2141..0000000000
Binary files a/webroot/rsrc/image/application/ponder/upvote.png and /dev/null differ
diff --git a/webroot/rsrc/js/application/ponder/behavior-votebox.js b/webroot/rsrc/js/application/ponder/behavior-votebox.js
index 3871d30b40..15c3197484 100644
--- a/webroot/rsrc/js/application/ponder/behavior-votebox.js
+++ b/webroot/rsrc/js/application/ponder/behavior-votebox.js
@@ -3,74 +3,53 @@
* @requires javelin-behavior
* javelin-dom
* javelin-util
- * phabricator-shaped-request
+ * javelin-stratcom
+ * javelin-request
*/
JX.behavior('ponder-votebox', function(config) {
- var node = JX.$(config.nodeid);
- var vote = config.vote;
- var count = config.count | 0;
- var targetURI = config.targetURI;
+ function handle_vote(e, vote) {
+ e.kill();
- var upnode, countnode, downnode;
+ var root = e.getNode('ponder-votable');
+ var data = e.getNodeData('ponder-votable');
- // this defines the behavior of the up/downvote
- // buttons, e.g. clicking 'up' transitions from
- // an 'up' vote to a 'none' vote
- var votecycle = {
- "1" : { up : "0", down : "-1" },
- "0" : { up : "1", down : "-1" },
- "-1" : { up : "1", down : "0" }
- };
+ if (data.vote != vote) {
+ data.vote = vote;
+ data.count += vote;
+ } else {
+ // User is undoing their vote.
+ data.vote = 0;
+ data.count -= vote;
+ }
- var voteclass = {
- "0" : "ponder-vote-none",
- "-1" : "ponder-vote-down",
- "1" : "ponder-vote-up"
- };
+ var upv = JX.DOM.find(root, 'a', 'upvote');
+ JX.DOM.alterClass(upv, 'ponder-vote-active', (data.vote > 0));
- function decorate() {
- upnode = JX.$N('div');
- countnode = JX.$N('div');
- downnode = JX.$N('div');
- node.appendChild(upnode);
- node.appendChild(countnode);
- node.appendChild(downnode);
- JX.DOM.alterClass(upnode, "ponder-upbutton " + voteclass[vote], true);
- JX.DOM.alterClass(downnode, "ponder-downbutton " + voteclass[vote], true);
- JX.DOM.alterClass(countnode, "ponder-votecount", true);
+ var downv = JX.DOM.find(root, 'a', 'downvote');
+ JX.DOM.alterClass(downv, 'ponder-vote-active', (data.vote < 0))
+
+ JX.DOM.setContent(
+ JX.DOM.find(root, 'div', 'ponder-vote-count'),
+ data.count);
+
+ new JX.Request(e.getTarget().href, JX.bag)
+ .setData({vote: data.vote})
+ .send()
}
- function update_state() {
- upnode.className = "ponder-upbutton " + voteclass[vote];
- downnode.className = "ponder-downbutton " + voteclass[vote];
- JX.DOM.setContent(countnode, JX.$H(count.toString()));
- }
+ JX.Stratcom.listen(
+ 'click',
+ 'downvote',
+ function(e) {
+ handle_vote(e, -1);
+ });
- function getdata() {
- return { phid : config.nodeid, vote : vote };
- }
-
- var request = new JX.PhabricatorShapedRequest(config.uri, JX.id, getdata);
- var trigger = JX.bind(request, request.trigger);
-
- function handle_upvote(e) {
- count += votecycle[vote].up - vote;
- vote = votecycle[vote].up;
- trigger();
- update_state();
- }
-
- function handle_downvote(e) {
- count += votecycle[vote].down - vote;
- vote = votecycle[vote].down;
- trigger();
- update_state();
- }
-
- decorate();
- update_state();
- JX.DOM.listen(upnode, 'click', null, handle_upvote);
- JX.DOM.listen(downnode, 'click', null, handle_downvote);
+ JX.Stratcom.listen(
+ 'click',
+ 'upvote',
+ function(e) {
+ handle_vote(e, 1);
+ });
});