Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
/*
@authors:
* [[User:The_Photographer]]
* [[User:Trougnouf]] (remove the blue backgrounds and fix signature.)
This script make easy the review process on [[Commons:Quality_images_candidates]]
It prevent edit conflicts and you can vote with a simple click (selecting the vote type in the combobox below of each image)
Please, feel free of contact to me to improve this tool. Thanks
*/
mw.loader.using("mediawiki.api.edit").done(function() {
    "use strict";

    mw.util.addCSS(
        "	#voting_bar {			" +
        "	    position: fixed;	" +
        "	    bottom: 0;			" +
        "	    width: 100%;		" +
        "		height: 40px;		" +
        "		padding: 15px;		" +
        "		border: 1px solid #a2a9b1; " +
        "		background-color: #E6E6FA; " +
        "	}   					" +
        "	#loading_ {			" +
        "      display: inline-block !important;	" +
        "      padding-left: 10px;	" +
        "      color: green;	" +
        "      font-weight: bold;	" +
        "	}   					" +
        "	#confirm_ {			" +
        "      display: inline-block !important;	" +
        "      padding-left: 10px;	" +
        "      color: red;	" +
        "	}"
    );

	var CONFIRM_BAR = 
		"<div id='voting_bar'>" +
        "	<span id='confirm_review' style='margin:auto !important' class='submit ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary ui-button-large' role='button'>" +
        "		<span class='ui-button-icon-primary ui-icon-green ui-icon ui-icon-check'>&nbsp;</span>" +
        "		<span class='ui-button-text'>Confirm reviews</span>" +
        "	</span>" +
        "	<div id='loading_'></div>" +
        "	<div id='confirm_'></div>" +
        "	<p style='padding-left: 50px;padding-right:50px;float:right;'>" +
         "	  <label for='filterNominations'>Show Only</label>" +
        "		<select style='margin: 0 !important' id='filterNominations' class='submit ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary ui-button-large'>" +
		"			<option value='Discuss'>Discuss</option>" +
		"			<option value='Promotion'>Promotion</option>" +
		"			<option value='Decline'>Decline</option>" +
		"			<option value='Review'>Reviewed</option>" +
		"			<option value='ToReview'>To Review</option>" +
		"			<option value='' selected>All</option>" +
		"		</select>" +
        "	</p>" +
        "</div>";
    var QIC_PAGE_DESTINY = "Commons:Quality_images_candidates/candidate_list";
    var NOMINATION_CONTAINER = "div.qi";
    var REVIEW_MESSAGE = "Dear wikiuser, please enter your review comment";
    var USERNAME = mw.config.get("wgUserName");
    var TITLE = mw.config.get("wgPageName");

    if (TITLE == "Commons:Quality_images_candidates") TITLE = QIC_PAGE_DESTINY;
    var api = new mw.Api();
    var opt = {
        "Nomination": {
            color: "#0000FF",
            message: "",
            type: "Nomination"
        },
        "Promotion": {
            color: "lime",
            message: "Good quality.",
            type: "Promotion"
        },
        "Decline": {
            color: "red",
            message: "Insufficient quality.",
            type: "Decline"
        },
        "Comment": {
            color: "#0000FF",
            message: "",
            type: "Comment"
        },
        "Discuss": {
            color: "#EEEE00",
            message: "I disagree.",
            type: "Discuss"
        }
    };
    var comboValues = {
        "Promotion": "Promotion",
        "Decline": "Decline",
        "Nomination": "Comment",
        "Discuss": "Discuss",
        "": "..."
    };
    var votes = [];
    var reviewCount = 0;

    function _loading(show) {
        if (show) {
            $("#confirm_").text("");
            $("#loading_").text("Sending reviews..");
        } else {
            $("#loading_").text("");
        }
    }

    function _confirmMessage() {
        if (reviewCount > 0) {
            $("#confirm_").text(reviewCount + " pending review confirmations");
        }
    }
	
	function getButtonBg(cmbVal){
		var buttonBg = null;
		if (cmbVal == "Decline")
			buttonBg = "red";
		if (cmbVal == "Promotion")
			buttonBg = "green";			
		if (cmbVal == "Discuss")		
			buttonBg = "yellow";	
		return buttonBg;
	}
	function setComboClass($cmb,className) {
		$cmb.removeClass( "ui-button-green ui-button-red ui-button-yellow" );
		if (className!==null)
			$cmb.addClass("ui-button-"+className);
	}
    function _setBgColor($cmb) {
		setComboClass($cmb, getButtonBg($cmb.val()));
	}
    function getSection(section) {
        _loading(true);
        return api.get({
                action: "query",
                prop: "revisions",
                rvprop: ["content", "timestamp"],
                titles: [TITLE],
                section: section, // Future support of section edition
                formatversion: "2",
                curtimestamp: true
            })
            .then(function(data) {
                var page, revision;
                page = data.query.pages[0];
                revision = page.revisions[0];
                return revision.content;
            });
    }

    function editSection(section, content) {
        $.ajax({
            url: mw.util.wikiScript("api"),
            data: {
                format: "json",
                action: "edit",
                title: TITLE,
                summary: "Reviewing " + reviewCount + " nomination(s) with [[User:The Photographer/QICvote.js|QICvote]]",
                text: content,
                //section: section, // Future support of section edition
                token: mw.user.tokens.get("csrfToken")
            },
            dataType: "json",
            type: "POST",
            success: function(data) {
                if (data && data.edit && data.edit.result == "Success") {
                    _loading(false);
                    votes = [];
                    $("#confirm_").text("");
                    mw.notify($("<div class=\"mw-notification-content\"><span class=\"ui-button-icon-primary ui-icon-green ui-icon ui-icon-check\" style=\"display:inline-block\"></span>&nbsp;<span style=\"font-size: 1em !important;color:green;\">Your " + (reviewCount).toString() + " review(s) were saved.</span></div>"));
                    reviewCount = 0;
                } else if (data && data.error) {
                    throw new Error("Error: API returned error code \"" + data.error.code + "\": " + data.error.info);
                } else {
                    throw new Error("Error: Unknown result from API.");
                }
            },
            error: function(xhr) {
                alert("Error: Request failed.");
            }
        });
    }

    function getSectionId(element) {
        var url = $(element).parent().parent().parent().find("h2 span a:last").attr("href");
        var results = new RegExp("[\?&]section=([^&#]*)").exec(url);
        return results[1] || 0;
    }

    function createCombo() {
        var $cmb = $("<select style='width:100%; margin:0px !important;' class='submit ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary ui-button-large' />");

        $.each(comboValues, function(key, value) {
            $cmb
                .append($("<option>", {
                        value: key
                    })
                    .text(value));
        });

        $cmb.val("");

        return $cmb;
    }

    function _getImageName(aElement) {
        var imageName = null;

        var imageNode = $(aElement).parent().find("a.image").last().attr("href").split(":");

        if (imageNode.length > 0) {
            if (imageNode[1].indexOf(".") !== -1) {
                imageName = imageNode[1];
            }
        }

        return imageName;
    }

    function _remplaceLast(str, word, newWord) {
        var n = str.lastIndexOf(word);
        str = str.slice(0, n) + str.slice(n).replace(word, newWord);
        return str;
    }

    function escapeRegExp(str) {
        return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    }

    function getEOL(newNomination) {

        return (newNomination.slice(-3) === "|}}") ? "" : "<br />";

    }

    function getVoteTemplate(type) {
        var voteTemplate = "";
        if (type == "Promotion") {
            voteTemplate = "{{s}} ";
        } else if (type == "Decline") {
            voteTemplate = "{{o}} ";
        }
        return voteTemplate;
    }

    function _getSignature() {
        // Signature function adapted from MediaWiki:QICSigs.js
        var month = ["January", "February", "March", "April", "May", "June",
            "July", "August", "September", "October", "November", "December"
        ];
        var now = new Date();

        var minute = now.getUTCMinutes();
        if (minute < 10) {
            minute = "0" + minute;
        }

        var hour = now.getUTCHours();
        if (hour < 10) {
            hour = "0" + hour;
        }
        return " --[[User:" + USERNAME + "|" + USERNAME + "]] " + hour + ":" + minute + ", " + now.getUTCDate() + " " +
            month[now.getUTCMonth()] + " " + now.getUTCFullYear() + " (UTC)";
    }

    function _addVote(content, image, type, comment) {
        var reg = escapeRegExp(image) + "(.*)\\n";
        var nomination = content.match(new RegExp(reg, "g"))[0];

        var newNomination = getNominationType(nomination, type);

        newNomination = _remplaceLast(newNomination, "}}", getEOL(newNomination) + getVoteTemplate(type) + comment + _getSignature() + "}}");

        return content.replace(nomination, newNomination);
    }

    function scapeFilenames(filesname) {
        function removeSpaces(match) {
            return match.replace(/\ /g, "_");
        }
        return filesname.replace(/File:(.*?)\|\{\{+/g, removeSpaces);
    }

    function isDiscuss(oldType, newType) {
        return ((oldType === "Promotion" && newType == "Decline") || (newType === "Promotion" && oldType == "Decline") || oldType == "Discuss");
    }

    function getNominationType(nomination, newType) {
        function setType(oldType) {
            oldType = oldType.replace("{{/", "").replace("|", "");
            if (isDiscuss(oldType, newType)) {
                newType = "Discuss";
            }
            return ("{{/" + newType + "|");
        }
        return nomination.replace(/\{\{\/(Nomination|Promotion|Decline|Discuss)\|/g, setType);
    }

    function _addVotes() {
        $.each(votes, function(section, votesSection) {
            if ((typeof votesSection !== "undefined") && (votesSection.length > 0)) {
                getSection(section - 1).then(function(content) {
                    content = scapeFilenames(content);
                    $.each(votesSection, function(i, vote) {
                        content = _addVote(content, vote.image, vote.type, vote.comment);
                    });
                    editSection(section, content);
                });
            }
        });
    }

    function _getNominationContainer(e) {
        return $(e).parent().find(NOMINATION_CONTAINER);
    }

    function _nullVote(cmb) {
        var nullVote = false;
        if ($(cmb).val() === "") {
            _getNominationContainer(cmb).find("ul li i").text("Review needed");
            _getNominationContainer(cmb).css("border-color", "#0000FF");
            $(cmb).val("");
            nullVote = true;
        }
        return nullVote;
    }

    function _getSelection(cmb) {
        var oldType = $(cmb).parent().find("div.qi ul li:nth-child(2)").children(":first").text();
        var newType = $(cmb).val();
        if (isDiscuss(oldType, newType)) {
            newType = "Discuss";
        }
        return opt[newType];
    }

    function _removePreviusVote(cmb) {
        _getNominationContainer(cmb).find("ul li > .coment").remove();
    }

    function _setBoderColorVote(cmb, newColor) {
        _getNominationContainer(cmb).css("border-color", newColor);
    }

    function getOldType(cmb) {
        _getNominationContainer(cmb).find("ul li:nth-child(2)").children(":first").text();
    }

    function _setVoteTitle(cmb, newTitle) {
        _getNominationContainer(cmb).find("ul li:nth-child(2)").children(":first").text(newTitle);
    }

    function _getCommentElement(comment) {
        return $("<li />", {
            text: comment,
            "class": "coment"
        });
    }

    function _getSignatureElement() {
        return $("<a />", {
            href: String("/wiki/User:" + USERNAME),
            text: USERNAME
        });
    }

    function _getDateElement() {
        return $("<p />", {
            text: String(new Date().toUTCString())
        });
    }

    function _filterNominations(cmb) {
    	$(".gallerybox").each(function() {
    		$(this).show();
    		console.log($(this).find(NOMINATION_CONTAINER).find("ul:first li:last b:first").text());
    		if ($(cmb).val() !=="") {
	    		if ($(this).find(NOMINATION_CONTAINER).find("ul:first li:last i").text() !== "Review needed")
	    		{
		            if ($(this).find(NOMINATION_CONTAINER).find("ul:first li:last b:first").text() !== $(cmb).val()) {
		                $(this).hide();
		            } else {
		                $(this).show();
		            }
	    		 } else if ($(cmb).val() !== "ToReview") {
	    		 	 $(this).hide();
	    		 }
    		}
        });
    }

    function _onChangeVote(cmb, section) {
        if (_nullVote(cmb)) return;

        var selection;
        var imageName;
        var comment = "";

        selection = _getSelection(cmb);

        _setVoteTitle(cmb, selection.type);
        _setBoderColorVote(cmb, selection.color);
        //_removePreviusVote(cmb);

        comment = prompt(REVIEW_MESSAGE, selection.message);
        var $comment = _getCommentElement(comment);

        var $signature = _getSignatureElement();
        var $date = _getDateElement();

        $(cmb).parent().find(NOMINATION_CONTAINER).
        find("ul").append($comment).
        append($signature).
        append($date);

        imageName = _getImageName(cmb);

        if (typeof votes[section] === "undefined") {
            votes[section] = [];
        }

        votes[section].push({
            image: decodeURIComponent(imageName),
            comment: comment,
            type: $(cmb).val()
        });

        reviewCount++;
    }

    if (TITLE == QIC_PAGE_DESTINY) {
        var section;
        var $cmb;
        $("body").append(CONFIRM_BAR);
        $("#confirm_review").on("click", function() {
            _addVotes();
        });
        $(".gallerybox").each(function() {
            $cmb = createCombo();
            $(this).append($cmb);
            section = getSectionId(this);
            $cmb.on("change", function() {
                _onChangeVote(this, section);
                _confirmMessage();
				_setBgColor($(this));
            });
        });
        
        $("#filterNominations").change(function() {
            _filterNominations(this);
            _setBgColor($(this));
        });

    }
});