Skip to content

Instantly share code, notes, and snippets.

@MatthiasPortzel
Created September 8, 2017 01:43
Show Gist options
  • Save MatthiasPortzel/6f61696c7fa4ad2c0d48ebfe202702dc to your computer and use it in GitHub Desktop.
Save MatthiasPortzel/6f61696c7fa4ad2c0d48ebfe202702dc to your computer and use it in GitHub Desktop.
A bookmarklet to improve voting on Khan Academy
(function () {
//The element that we mess with
var base = document.getElementsByClassName("voting-wrap")[0];
//No voting base means we're looking at a child account program or a tutorial/offical video
if (!base) {
//Try just adding a whole new thing
var wrap = document.getElementsByClassName("buttons_vponqv");
//If we're on an offical program there will be a share button and we can add it next to that
if (wrap.length) {
wrap = wrap[0];
base = document.createElement("span");
//If we're on a child account program we need to add it above the tabs
}else {
wrap = document.getElementById("scratchpad-tabs").parentNode;
base = document.createElement("div");
base.style.textAlign = "center";
}
wrap.insertBefore(base, wrap.childNodes[0]);
base.classList.add("voting-wrap");
}else {
base = base.getElementsByClassName("discussion-meta-controls")[0].childNodes[0];
}
var attr = KAdefine.require("./javascript/scratchpads-package/scratchpad-ui.js").ScratchpadUI.scratchpad.attributes;
var cookie = KAdefine.require("./javascript/shared-package/cookies.js").readCookie("fkey");
var key = attr.key;
var id = attr.id;
var orgVotes = attr.sumVotesIncremented; //The number of votes, not including our own
var loaded = false;
//Our vote
var voteType = 0;
base.innerHTML = `
<div class="discussion-vote">
<div id="m-vote-up" class="vote-for vote-for-js vote-up" style="margin: 0 5px;"></div>
<span id="m-vote-count" style="font-size: 17px; color: rgb(33, 36, 44);">${orgVotes}</span>
<div id="m-vote-down" class="vote-for vote-for-js vote-down" style="margin: 0 5px"></div>
</div>`;
var voteUp = document.getElementById("m-vote-up");
var voteDn = document.getElementById("m-vote-down");
var mVote = function () {
if (!loaded) return;
//If we clicked the vote up button we assume we're voting it.
if (this.classList.contains("vote-up")) {
voteType = 1;
voteDn.classList.remove("voted");//Can't vote up and down
}
if (this.classList.contains("vote-down")) {
voteType = -1;
voteUp.classList.remove("voted");
}
//If we already were voted, then set our vote to neutral
if (this.classList.contains("voted")) {
voteType = 0;
}
this.classList.toggle("voted");
//Show the orignal votes, plus ours
document.getElementById("m-vote-count").innerText = orgVotes + voteType;
var req = new XMLHttpRequest();
req.addEventListener("load", function () {
if (this.status === 204) return; //204. No Content.
var res = JSON.parse(this.response);
if (res.error) {
alert("Failed with error:\n\n" + res.error);
}
});
//Send our vote
req.open("POST", `https://www.khanacademy.org/api/internal/discussions/voteentity?entity_key=${key}&vote_type=${voteType}`);
req.setRequestHeader("X-KA-FKey", cookie);
req.send();
};
voteUp.addEventListener("click", mVote);
voteDn.addEventListener("click", mVote);
//Fetch if we previously upvoted or downvoted the program
var req = new XMLHttpRequest();
req.addEventListener("load", function () {
var res = JSON.parse(this.response);
//Makes sure we have the most recent vote count
orgVotes = res.scratchpad.sumVotesIncremented;
document.getElementById("m-vote-count").innerText = orgVotes;
if (res.upVoted) {
voteType = 1;
orgVotes -= 1;
voteUp.classList.add("voted");
}
if (res.downVoted) {
voteType = -1;
orgVotes += 1;
voteDn.classList.add("voted");
}
loaded = true;
});
req.open("GET", `https://www.khanacademy.org/api/internal/show_scratchpad?scratchpad_id=${id}&projection={"upVoted":1,"downVoted":1,"scratchpad":{"sumVotesIncremented":1}}`);
req.setRequestHeader("X-KA-FKey", cookie);
req.send();
})("©Matthias")
(function(){var base=document.getElementsByClassName("voting-wrap")[0];if(!base){var wrap=document.getElementsByClassName("buttons_vponqv");if(wrap.length){wrap=wrap[0];base=document.createElement("span")}else{wrap=document.getElementById("scratchpad-tabs").parentNode;base=document.createElement("div");base.style.textAlign="center"}wrap.insertBefore(base,wrap.childNodes[0]);base.classList.add("voting-wrap")}else{base=base.getElementsByClassName("discussion-meta-controls")[0].childNodes[0]}var attr=KAdefine.require("./javascript/scratchpads-package/scratchpad-ui.js").ScratchpadUI.scratchpad.attributes;var cookie=KAdefine.require("./javascript/shared-package/cookies.js").readCookie("fkey");var key=attr.key;var id=attr.id;var orgVotes=attr.sumVotesIncremented;var loaded=false,voteType=0;base.innerHTML=`<div class="discussion-vote"><div id="m-vote-up" class="vote-for vote-for-js vote-up" style="margin: 0 5px;"></div><span id="m-vote-count" style="font-size:17px;color:rgb(33,36,44);">${orgVotes}</span><div id="m-vote-down" class="vote-for vote-for-js vote-down" style="margin: 0 5px"></div></div>`;var voteUp=document.getElementById("m-vote-up");var voteDn=document.getElementById("m-vote-down");var mVote=function(){if(!loaded)return;if(this.classList.contains("vote-up")){voteType=1;voteDn.classList.remove("voted")}if(this.classList.contains("vote-down")){voteType=-1;voteUp.classList.remove("voted")}if(this.classList.contains("voted")){voteType=0}this.classList.toggle("voted");document.getElementById("m-vote-count").innerText=orgVotes+voteType;var req=new XMLHttpRequest;req.addEventListener("load",function(){if(this.status===204)return;var res=JSON.parse(this.response);if(res.error){alert("Failed with error:\n\n"+res.error)}});req.open("POST",`https://www.khanacademy.org/api/internal/discussions/voteentity?entity_key=${key}&vote_type=${voteType}`);req.setRequestHeader("X-KA-FKey",cookie);req.send()};voteUp.addEventListener("click",mVote);voteDn.addEventListener("click",mVote);var req=new XMLHttpRequest;req.addEventListener("load",function(){var res=JSON.parse(this.response);orgVotes=res.scratchpad.sumVotesIncremented;document.getElementById("m-vote-count").innerText=orgVotes;if(res.upVoted){voteType=1;orgVotes-=1;voteUp.classList.add("voted")}if(res.downVoted){voteType=-1;orgVotes+=1;voteDn.classList.add("voted")}loaded=true});req.open("GET",`https://www.khanacademy.org/api/internal/show_scratchpad?scratchpad_id=${id}&projection={"upVoted":1,"downVoted":1,"scratchpad":{"sumVotesIncremented":1}}`);req.setRequestHeader("X-KA-FKey",cookie);req.send()})("©Matthias");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment