// ==UserScript==
// @name Unsolved tab on PSE
// @version 0.1
// @author Lord of dark (http://stackexchange.com/users/5950528/lord-of-dark)
// @description Add "Unsolved" tab on Puzzling Stack Exchange
// @include http://puzzling.stackexchange.com/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @grant GM_xmlhttpRequest
// @namespace https://gf.qytechs.cn/users/49190
// ==/UserScript==
var unanswered = document.querySelectorAll('[id="nav-unanswered"]')[0];
var tabs = unanswered.parentNode.parentNode;
var unsolved = unanswered.cloneNode(true);
unsolved.id="nav-unsolved";
unsolved.innerHTML="Unsolved";
unsolved.setAttribute("href","/unsolved");
var li_unsolved = document.createElement('li');
li_unsolved.appendChild(unsolved);
tabs.appendChild(li_unsolved);
var unsolved_url="puzzling.stackexchange.com/unsolved"
if(content.document.location.href.indexOf(unsolved_url) > -1){
// Update page title :
document.title = "Unsolved Questions - Puzzling Stack Exchange";
// Add focus on unsolved tab, remove from other tabs
tabs_youarehere = tabs.querySelectorAll('[class="youarehere"]')
for (var i = 0; i < tabs_youarehere.length; i++) { tabs_youarehere[i].removeAttribute("class");};
unsolved.parentNode.setAttribute("class","youarehere");
//remove every thing in the blank part :
var center_html = document.getElementById("content");
center_html.innerHTML="";
// Check the type of reasearch type :
var researchType = findResearchType();
// Check the page
var page= findPage();
// Call the unanswered and copy it
GM_xmlhttpRequest({
method: "GET",
url: "http://puzzling.stackexchange.com/unanswered",
onload: function(response) {
// Add all the content from UNANSWERED
var tempDiv = document.createElement('html');
tempDiv.innerHTML = response.responseText;
var all_div = tempDiv.getElementsByTagName("div");
for (var i=0;i<all_div.length;i++){
if (all_div[i].getAttribute('id')=="content"){
var content = all_div[i].innerHTML;
center_html.innerHTML=content;
}
}
updateBodyContext(researchType);
//http://puzzling.stackexchange.com/search?page=1&q=hasaccepted%3Afalse+closed%3Afalse+duplicate%3Afalse+locked%3Afalse+hasnotice%3Afalse+answers%3A0
var urlSearch;
switch(researchType) {
case "noanswers":
urlSearch="http://puzzling.stackexchange.com/search?page="+page+"&q=hasaccepted%3Afalse+closed%3Afalse+duplicate%3Afalse+locked%3Afalse+hasnotice%3Afalse+answers%3A0"
break;
default:
urlSearch="http://puzzling.stackexchange.com/search?page="+page+"&tab="+researchType+"&q=hasaccepted%3afalse%20closed%3afalse%20duplicate%3afalse%20locked%3afalse"
}
GM_xmlhttpRequest({
method: "GET",
url: urlSearch,
onload: function(response) {
var tempDiv = document.createElement('div');
tempDiv.innerHTML = response.responseText.replace(/<script(.|\s)*?\/script>/g, '');
var nb_questions = tempDiv.getElementsByTagName("h2")[0].firstChild;
document.getElementsByClassName("summarycount al")[0].innerHTML=nb_questions.nodeValue
var questionsText = tempDiv.getElementsByClassName("search-results js-search-results")[0];
var questions_area = document.getElementById("questions");
questions_area.innerHTML= questionsText.innerHTML
document.getElementsByClassName("mod-flair").remove();
var all_answer_links = document.querySelectorAll('[data-searchsession]');
for (var i = 0; i < all_answer_links.length; i++) {
all_answer_links[i].removeAttribute("data-searchsession");
all_answer_links[i].setAttribute("class","question-hyperlink");
all_answer_links[i].innerHTML= all_answer_links[i].innerHTML.replace("Q: ","");
var wrapper = document.createElement('h3');
all_answer_links[i].parentNode.appendChild(wrapper);
wrapper.appendChild(all_answer_links[i])
}
var alluserid=""
var all_from = document.querySelectorAll('[class="started fr"]');
for (var i = 0; i < all_from.length; i++) {
var relative_time = all_from[i].getElementsByTagName('span')[0];
var a_childs= all_from[i].getElementsByTagName('a');
var user;//= '<a href="/users/0/user">user</a>'
if (a_childs.length>0){
user= a_childs[0];
} else { // if there is no <a> then the user has been deleted
user = document.createElement('a');
user.setAttribute("href","/users/0/user");
user.innerHTML='deleted user'
}
all_from[i].innerHTML= all_from[i].innerHTML.replace("asked","");
all_from[i].innerHTML= all_from[i].innerHTML.replace("by","");
var userName = user.cloneNode(true);
var userid = userName.getAttribute("href").replace("/users/","").replace(/\/.*/gi,"");
alluserid=alluserid+userid+";";
user.innerHTML='<div class="gravatar-wrapper-32"><img src="http://i.stack.imgur.com/Fe45R.png" alt="" height="32" width="32"></div>';
var gravatarDiv = document.createElement('div');
gravatarDiv.setAttribute("class","user-gravatar32");
gravatarDiv.appendChild(user);
all_from[i].innerHTML="";
all_from[i].appendChild(relative_time);
all_from[i].appendChild(gravatarDiv);
var detailsDiv = document.createElement('div');
detailsDiv.setAttribute("class","user-details");
all_from[i].appendChild(detailsDiv);
detailsDiv.appendChild(userName);
}
alluserid = alluserid.replace(/;$/,"");
var all_dates = document.querySelectorAll('[class="relativetime"]');
for (var i = 0; i < all_dates.length; i++) {
var infoDiv = document.createElement('div');
infoDiv.setAttribute("class","user-info");
all_dates[i].parentNode.appendChild(infoDiv);
var timeDiv = document.createElement('div');
timeDiv.innerHTML="asked ";
timeDiv.setAttribute("class","user-action-time");
timeDiv.appendChild(all_dates[i]);
infoDiv.appendChild(timeDiv);
infoDiv.appendChild(infoDiv.parentNode.getElementsByClassName("user-gravatar32")[0]);
infoDiv.appendChild(infoDiv.parentNode.getElementsByClassName("user-details")[0]);
//add flair
var flairDiv = document.createElement('div');
flairDiv.setAttribute("class","-flair");
infoDiv.getElementsByClassName("user-details")[0].appendChild(flairDiv);
flairDiv.innerHTML='<span class="reputation-score" title="reputation score " dir="ltr">???</span>';
}
createPageNav(page,researchType)
updateUserProfil(alluserid);
}
});
}
});
// Actions before requesting the questions, applied to context.
function updateBodyContext(researchType) {
// update the title
var title_body = document.getElementById("h-unanswered-questions");
title_body.innerHTML="Unsolved Questions";
// setcontent to empty
var questionsDiv = document.getElementById("questions");
questionsDiv.innerHTML="";
// set question count to 0$
var counter = document.getElementsByClassName('summarycount al')[0];
counter.innerHTML="?";
counter.parentNode.getElementsByTagName("span")[0].innerHTML='questions with no accepted answers';
// remove page navigation :
document.getElementsByClassName('pager fl').remove()
// Change tab links
var tabs_link = document.getElementById("tabs");
var links = tabs_link.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
links[i].setAttribute("href",links[i].getAttribute("href").replace("unanswered","unsolved"));
if (links[i].getAttribute("href").indexOf(researchType)>-1){
links[i].setAttribute("class","youarehere");
} else {
links[i].removeAttribute("class");
}
if (links[i].getAttribute("href")=="/unsolved/tagged?tab=mytags"){
links[i].innerHTML="";
}
}
}
function findPage() {
var ind1=document.location.href.indexOf("page=");
if (ind1 <1){
return "1"
}
else{
var ind2=document.location.href.indexOf("&",ind1+1);
if (ind2>4){
return document.location.href.substring(ind1+5,ind2);
} else {
return document.location.href.substring(ind1+5);
}
}
return "1"
}
function findResearchType() {
var ind1=document.location.href.indexOf("tab=");
if (ind1 <1){
return "newest"
}
else{
var ind2=document.location.href.indexOf("&",ind1+1);
if (ind2>4){
return document.location.href.substring(ind1+4,ind2);
} else {
return document.location.href.substring(ind1+4);
}
}
return "newest"
}
// Define HTTP client to get the JSON
function httpGetAsync(theUrl, callback)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
// This function update the profil (gravatar / reputation / badges)
// Use API to get this data -> API without login limited at 300 request/day
function updateUserProfil(alluserid){
//var jsonUrl ='https://api.stackexchange.com/2.2/users/'+alluserid+'?page=1&pagesize=50&order=desc&sort=reputation&site=puzzling&filter=!LnNkvq0X3NNP1zDzft3_WF';
var jsonUrl ='https://api.stackexchange.com/2.2/users/'+alluserid+'?page=1&pagesize=50&order=desc&sort=reputation&site=puzzling&filter=!LnO)*RBcCzpAXUnHZRkHoo'
httpGetAsync(jsonUrl, function(response) {
var userJson = JSON.parse(response);
var items = userJson.items;
function jsonHasId(id){
for(var i = 0; i < items.length; i++){
if (items[i].user_id==id){
return true;
}
}
return false;
}
function getImgUrl(id){
for(var i = 0; i < items.length; i++){
if (items[i].user_id==id){
return items[i].profile_image;
}
}
return "";
};
function getRepBadges(id){
for(var i = 0; i < items.length; i++){
if (items[i].user_id==id){
return [items[i].reputation,items[i].badge_counts.gold,items[i].badge_counts.silver,items[i].badge_counts.bronze,items[i].user_type=="moderator"];
}
}
return [1,0,0,0];
};
// Loop on the users to update their profil pictures
var all_gravatars = document.querySelectorAll('[class="user-gravatar32"]');
for (var i = 0; i < all_gravatars.length; i++) {
var userName=all_gravatars[i].getElementsByTagName('a')[0].getAttribute("href").replace("/users/","").replace(/\/.*/gi,"");
if(jsonHasId(userName)){
all_gravatars[i].getElementsByTagName('img')[0].setAttribute("src",getImgUrl(userName));
var flair=all_gravatars[i].nextSibling.lastChild;
var repBadges = getRepBadges(userName);
flair.innerHTML='<span class="reputation-score" title="reputation score " dir="ltr">'+repBadges[0]+'</span>';
if (repBadges[1]>0) {
flair.innerHTML+='<span title="'+repBadges[1]+' gold badges"><span class="badge1"></span><span class="badgecount">'+repBadges[1]+'</span></span>';
}
if (repBadges[2]>0) {
flair.innerHTML+='<span title="'+repBadges[2]+' silver badges"><span class="badge2"></span><span class="badgecount">'+repBadges[2]+'</span></span>';
}
flair.innerHTML+='<span title="'+repBadges[3]+' bronze badges"><span class="badge3"></span><span class="badgecount">'+repBadges[3]+'</span></span>';
// Add moderator Diamonds
if (repBadges[4]){
var mod = document.createElement('span');
mod.setAttribute('class','mod-flair');
mod.setAttribute('title',"moderator");
mod.innerHTML="♦";
flair.parentNode.insertBefore(mod,flair);
}
}
}
});
}
// Create the footer to navigate in other pages
function createPageNav(page,researchType) {
var maxPages = Math.ceil(document.getElementsByClassName('summarycount al')[0].innerHTML /50);
var pagerfl = document.createElement('div');
pagerfl.setAttribute('class','pager fl');
pagerfl.innerHTML="";
if (page > 1) { // add prev button
pagerfl.appendChild(addPage(page-1, researchType, "prev"));
}
if (page > 3) {
pagerfl.appendChild(addPage(1, researchType, "1"));
}
if (page > 4) {
pagerfl.innerHTML+='<span class="page-numbers dots">…</span>';
}
if (page > 2) {
pagerfl.appendChild(addPage(page-2, researchType, page-2));
}
if (page > 1) {
pagerfl.appendChild(addPage(page-1, researchType, page-1));
}
pagerfl.innerHTML+='<span class="page-numbers current">'+page+'</span>' // add current page number
if (page < maxPages){
pagerfl.appendChild(addPage(page-(-1), researchType, page-(-1)));
}
if (page < maxPages-1){
pagerfl.appendChild(addPage(page-(-2), researchType, page-(-2)));
}
if (page < maxPages-3){
pagerfl.innerHTML+='<span class="page-numbers dots">…</span>';
}
if (page < maxPages-2){
pagerfl.appendChild(addPage(maxPages, researchType, maxPages));
}
if (page < maxPages){
pagerfl.appendChild(addPage(page+1, researchType, "next"));
}
// add next button
var pageplus1 = page+1
document.getElementById('mainbar').appendChild(pagerfl);
}
// function to create a page number span
function addPage(page, researchType, name){
var a_page= document.createElement('a');
a_page.setAttribute("href","/unsolved?page="+page+"&tab="+researchType);
a_page.setAttribute("title","go to page "+page);
var span_page= document.createElement('span');
span_page.setAttribute("class","page-numbers "+page);
span_page.innerHTML=name;
a_page.appendChild(span_page);
a_page.innerHTML+=" ";
return a_page;
}
// Remove node list
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
for(var i = this.length - 1; i >= 0; i--) {
if(this[i] && this[i].parentElement) {
this[i].parentElement.removeChild(this[i]);
}
}
}
}