Note: After saving, you may have to bypass your browser's cache to see the changes. Mozilla / Firefox / Safari: hold down Shift while clicking Reload, or press Ctrl-Shift-R (Cmd-Shift-R on Apple Mac); IE: hold Ctrl while clicking Refresh, or press Ctrl-F5; Konqueror: simply click the Reload button, or press F5; Opera users may need to completely clear their cache in Tools→Preferences. — More skins

/*
Author : Svetlana Tkachenko svetlana@members.fsf.org
This file is a part of todos.js.
Licence: GPLv3+
Description: shows a todo rater for current article (and a todo for all articles) at the bottom
Version: 0.1.1
*/ 
function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index);
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB);
    };
}
function getCellValue(row, index){ return $(row).children('td').eq(index).text() }

var todoTypes = {
	'style:extlinks_not_in_body': {desc: 'External links SHOULD not be present in the article body.', diff: 0.1},
	'style:wikilinks': {desc:'Wikilinks SHOULD to be provided where appropriate.', diff: 0.2},
	'style:sources:filled': {desc:'Sources templates SHOULD be filled in correctly.', diff: 0.2},
	'style:sources:sorted': {desc:'Fresh sources SHOULD go first.', diff: 0.1},
	'content:clarified': {desc:'Article MUST not contains vague phrases which need to be clarified.', diff: 0.6},
	'content:expanded': {desc:'Article MUST not contain missing details (from the present or new sources)', diff: 0.7},
	'content:image': {desc:'Article SHOULD contain an image if needed and relevant', diff: 0.5},
	'content:fresh': {desc:'Article MUST be sufficiently fresh (this value contains a date comment)', diff: 0.9},
	'content:nobias': {desc:'Article MUST be written without bias.', diff: 0.4},
	'content:copyvio': {desc:'Article MUST be written without plagiarism.', diff: 0.5},
};

var template = {
	date: '',
	title: mw.config.get('wgTitle'),
	todos: {
		'style:extlinks_not_in_body': {num: 1, c: ''},
		'style:wikilinks': {num: 1, c: ''},
		'style:sources:filled': {num: 1, c: ''},
		'style:sources:sorted': {num: 1, c: ''},
		'content:clarified': {num: 1, c: ''},
		'content:expanded': {num: 1, c: ''},
		'content:image': {num: 1, c: ''},
		'content:fresh': {num: 1, c: ''},
		'content:nobias': {num: 1, c: ''}
	}
};

// xxx this is for debugging
//localStorage.clear();

console.log('// read todoItems from storage');
var storageName = 'Wikinews-Gryllida-toDo-LocalStorage';
var todoItems = {};
if ( localStorage.getItem(storageName)) {
	todoItems = JSON.parse(localStorage.getItem(storageName));
}

console.log('// read or create this article infos');
var articleId = mw.config.get( 'wgArticleId' );
if(!todoItems[articleId]){
	console.log('this article id does not exist');
	todoItems[articleId] = template;
}

console.log('// show this article infos on screen');
var $div = $('<div></div>', {id: 'wikinews-gryllida-todos'});
var $table = $('<table></table>', {'style': 'width:100%;', 'class': 'wikitable'});
$table.append($('<tr><th>task</th><th>status</th><th>comment</th></tr>'));
console.log(todoItems);
var keys = Object.keys(todoItems[articleId].todos);
console.log(keys);
$(keys).each(function(i){
	var key = keys[i];
	var num = todoItems[articleId]['todos'][key].num;
	var c = todoItems[articleId]['todos'][key].c;
	var $tr = $('<tr></tr>', {class: 'wikinews-gryllida-todos-tr'});
	$tr.append($('<td></td>', {text: key}));
	$tr.append($('<td></td>').append($('<input/>', {val: num})));
	$tr.append($('<td></td>',{ 'style': 'width:100%'}).append($('<input/>', {val: c, 'style': 'width:100%'})));
	$table.append($tr);
});
$div.append($table);
var $saveButton = $('<input/>', {type: 'button', val: 'Save'});
$saveButton.click(function(){
	// get new version of todoItems -- in case other articles were updated while
	// this page was open
	if ( localStorage.getItem(storageName)) {
		todoItems = JSON.parse(localStorage.getItem(storageName));
	}
	if(!todoItems[articleId]){
		console.log('this article id does not exist');
		todoItems[articleId] = template;
	}
	$('.wikinews-gryllida-todos-tr').each(function(i){
		var tr = $('.wikinews-gryllida-todos-tr')[i];
		var key = $($(tr).find('td')[0]).text();
		var num = $($(tr).find('td')[1]).find('input').val();
		var c   = $($(tr).find('td')[2]).find('input').val();
		todoItems[articleId]['todos'][key] = {};
		todoItems[articleId]['todos'][key] = {num: num, c: c};
	});
	todoItems[articleId].title = mw.config.get('wgTitle') ;
	localStorage.setItem(storageName,JSON.stringify(todoItems));
});
$div.append($saveButton);
$('#content').append($div);

var $div2 = $('<div></div>', {id: 'wikinews-gryllida-todos-all'});
var $table2 = $('<table></table>');
$table2.append($('<tr><th>article</th><th>task</th><th>status</th><th>comment</th><th>difficulty</th></tr>'));
console.log(todoItems);
var articleIds = Object.keys(todoItems);
$(articleIds).each(function(j){
	var someArticleId = articleIds[j];
	var keys = Object.keys(todoItems[someArticleId]['todos']);
	$(keys).each(function(i){
		var key = keys[i];
		var num = todoItems[someArticleId]['todos'][key].num;
		if(num !== '1'){
			var c = todoItems[someArticleId]['todos'][key].c;
			var $tr = $('<tr></tr>');
			$tr.append($('<td></td>').append($('<a></a>',{
				href: 'http://en.wikinews.org/w/index.php?curid=' + someArticleId,
				text: todoItems[someArticleId].title
			})));
			$tr.append($('<td></td>', {text: key}));
			$tr.append($('<td></td>', {text: num}));
			$tr.append($('<td></td>', {text: c}));
			$tr.append($('<td></td>', {text: todoTypes[key].diff}));
			$table2.append($tr);
		}
	});
});

// sort by difficulty
//var table = $(this).parents('table').eq(0);
var rows = $table2.find('tr:gt(0)').toArray().sort(comparer($(this).index()));
//this.asc = !this.asc;
if (!this.asc){rows = rows.reverse()}
for (var i = 0; i < rows.length; i++){$table2.append(rows[i])}
//$table2.prepend($('<tr><th>article</th><th>task</th><th>status</th><th>comment</th><th>difficulty</th></tr>'));
$table2.prop('class', 'wikitable sortable');

$div2.append($table2);
$('#content').append($div2);