Skip to content

Instantly share code, notes, and snippets.

@pblocz
Last active December 11, 2019 21:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pblocz/43dc185975386ab5eedf to your computer and use it in GitHub Desktop.
Save pblocz/43dc185975386ab5eedf to your computer and use it in GitHub Desktop.
Tampermonkey script to find UCM ELP Sakai forums posts ranking, use from *forums* tab, or else it won't work
/*! ELPRank.user.js v1.3 | (c) 2014 Pablo Cabeza
* license: http://opensource.org/licenses/mit-license.php
*/
// ==UserScript==
// @name ELPRank
// @namespace https://gist.github.com/43dc185975386ab5eedf
// @version 1.3
// @description To find UCM ELP Sakai forum posts ranking, use from *forums* tab, or else it won't work
// @author Pablo Cabeza
// @include https://cv3.sim.ucm.es/portal/site/*
// @grant GM_getResourceText
// @grant GM_getResourceURL
// @grant GM_addStyle
// @require http://code.jquery.com/jquery-latest.js
// @require http://cdn.datatables.net/1.10.4/js/jquery.dataTables.min.js
// @resource ScriptCSS https://gist.github.com/PCabeza/43dc185975386ab5eedf/raw/ELPRank.user.js.css
// @updateURL https://gist.github.com/PCabeza/43dc185975386ab5eedf/raw/ELPRank.user.js
// @downloadURL https://gist.github.com/PCabeza/43dc185975386ab5eedf/raw/ELPRank.user.js
// ==/UserScript==
window.CVUTILS = (function(win) {
// Fetch css styles while loading the script
var scriptstyle = GM_getResourceText("ScriptCSS");
var datatablescss_url = "https://cdn.datatables.net/1.10.4/css/jquery.dataTables.css"
// Extra elements added to the page to make it work
var button = $('<div id="special-button"><div class="inner">π</div></div>');
var container = $('<div id="special-container"><div class="special-table-wrapper"><table class="display"><thead><tr><th>Posición</th><th>Nombre</th><th>Mensajes</th></thead></tr><tbody></tbody></table></div></div>');
// Regex to extract the content of the body of a web page html
var body_regex = /<body[^>]*>([\s\S]*)<\/body>/;
var baseurl, listurl; // urls extracted from sakai forum frame
var peoples=[], headers, nameidx, numidx;
/**
This function retrieves the paginated user list from listurl,
extracts (user names,number of messages) in forum and iterates
until all user data is fetched, it then calls callback with
that data.
The data is stored in the form of [name,number] in peoples
variables.
*/
function listUsers(callback,page) {
page = page*1 || 0;
var url=listurl + (page ? "/"+(page*30) : "") + ".page";
console.log("Calling: ",url);
var call = $.ajax ( {
type: 'GET',
url: url,
async: true,
success: function (responseText) {
var content = body_regex.exec(call.responseText)[1];
// Use this auxiliary node to parse html
var output = $('<output>').append($.parseHTML(content))
// Get all rows form the table that contains user data
var trs = $('table.forumline',output).last().find('tr');
// Just update indices the first time
if(!page) {
headers = trs.first().find('th').map(function(idx,el) {
return $(el).text().trim().toLowerCase();
}).toArray();
nameidx = $.inArray("nombre",headers);
numidx = $.inArray("mensajes",headers);
}
// Append to people the parsed information from users
Array.prototype.push.apply(peoples,trs.slice(1).map(
function(idx,tr) {
return [$(tr).find('td').map(
function(idx,el) {
return $(el).text().trim().toLowerCase();
})
.filter(
function(idx){
return (idx == nameidx) || (idx==numidx);
}
).toArray()
];
}));
// Find if this page is the last
var final = output.find("table a").filter(
function(idx) {
return $(this).text().trim().toLowerCase() == "siguiente";
}
).length == 0;
if(final) callback(peoples);
else listUsers(callback,page+1);
}
});
}
/**
Append extra html elements and prepare events
*/
function prepareHTML() {
// Add extra styles
GM_addStyle(scriptstyle);
$('head').append(
$('<link rel="stylesheet">').attr('href',datatablescss_url)
);
$('body').append(button);
var populateTable = false; // To prevent populating table twice
button.click(function() {
// Guard against double clicking the button while loading
if(button.hasClass('loading')) return;
// Add class for proccessing
button.addClass('loading');
var call = function(p){
// Prepare and sort user data
// $.grep() prevents empty results
people = $.map(
$.grep(p,function(v,i) { return v.length == 2; }),
function(v,i) {
return [[v[0],parseInt(v[1])]];
}).sort(function(a,b){ return a[1]-b[1]; });
// Print nice table into the console
console.table(people.reverse());
// Populate table using DataTables api
if(!populateTable)
$.each(people,function(i,v) {
v.splice(0,0,"#"+(i+1)); // insert position to v
container.find('table').dataTable().api().row.add(v); // add row
});
populateTable=true;
// Draw table and show it
container.find('table').dataTable().api().draw();
container.show();
$('body').addClass('modal-open');
// Remove class after processing
button.removeClass('loading');
};
// Just call listUsers when there is no data
if(!peoples.length) listUsers(call);
else call(peoples);
});
$('body').append(container);
container.hide();
// Modal-like hide the table
container.click(function(){
container.hide();
$('body').removeClass('modal-open');
});
container.find('> *').click(function(e){e.stopPropagation();});
// Initialize DataTable in container
container.find('table').DataTable({"order": [[ 2, "desc" ]]});
// Find target url for forums
baseurl=$('iframe').attr('src').replace(/\?.*/,'');
listurl= baseurl + "/user/list";
}
$(document).ready(function(){
prepareHTML();
});
return {
button: button,
container: container,
listUsers: listUsers,
listurl: listurl,
};
})(window);
/*! ELPRank.user.js v1.3 | (c) 2014 Pablo Cabeza
* license: http://opensource.org/licenses/mit-license.php
*/
body.modal-open {
overflow: hidden;
}
#special-button{
border-radius: 100%;
bottom: 30px;
left: 30px;
position: fixed;
width: 46px;
height: 46px;
display: table;
border: solid rgb(118, 118, 118);
padding: 4px;
transition: padding 0.1s, left 0.1s, bottom 0.1s, background-image 0.2s;
}
#special-button:hover {
cursor: pointer;
}
#special-button:active, #special-button:focus {
padding: 2px;
bottom: 32px;
left: 32px;
}
#special-button.loading .inner{
background-image: url(https://upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif);
background-repeat: no-repeat;
background-position: 7px 8px;
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
max-width: 45px;
}
#special-button .inner {
border-radius: 100%;
display: table-cell;
text-align: center;
vertical-align: middle;
font-size: 40px;
color: solid rgb(118, 118, 118);
background-color: rgb(203, 203, 203);
}
#special-container {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.317647);
position: fixed;
left: 0px;
top: 0px;
padding-top: 50px;
}
#special-container > * {
max-width: 800px;
width: 80%;
margin: 0px auto;
background-color: white;
padding: 30px;
max-height: 60%;
overflow: auto;
border-radius: 5px;
box-shadow: 1px 1px 10px rgba(56, 56, 56, 0.86);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment