User:Kaniivel/IPLabeller.js

/////////////////////////////////////////////////////////////////////////////////////////// Enables user to set permanent labels and color backgrounds to anonymous IP accounts ///////////////////////////////////////////////////////////////////////////////////////////importStylesheet('User:Kaniivel/IPLabeller.css');// allow user to override colorCodes in common.js, make sure property '4' stays emptyif (!window.colorCodes) {var colorCodes = {1:"#FC8888",// red2:"#ffe299",// yellow3:"#99FF33",// green4:""// white (must be empty)};} else {colorCodes['4'] = "";}var messages = {errNoStorage: 'No storage available. Seems that either:\n \a) your browser does not support local storage,\n \b) local storage is turned off, or\n \c) is full.',formAddLabel: 'add label',formChange  : 'change',formLabel   : 'Label',formColor   : 'Color',errMissingIP: 'Error: missing IP address!',lblDeleted  : 'Label removed!',lblMissing  : 'Missing label!',lblChanged  : 'Label changed!',lblAdded    : 'Label added!',errAction   : 'Error: unrecognized action!'}preload([    'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Yes_check.svg/240px-Yes_check.svg.png',    'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/X_mark.svg/210px-X_mark.svg.png',    'https://upload.wikimedia.org/wikipedia/et/4/42/Ip_label_form_delete.png',    'https://upload.wikimedia.org/wikipedia/et/3/38/Ip_label_form_submit.png']);$(document).ready(function(){if( typeof(Storage) === "undefined" ) {// if there is no local storage available, display message and do nothingthrow new Error( messages.errNoStorage );} else {// define two custom methods for storing objectsStorage.prototype.setObject = function(key, value) {this.setItem(key, JSON.stringify(value));};Storage.prototype.getObject = function(key) {var value = this.getItem(key);return value && JSON.parse(value);};createLinks (false);createEvents ();}});$(document).mouseup(function (e) {var container = $("div.ip-label-popup");var link = $("a.mw-anonuserlink");if (!container.is(e.target) // if the target of the click isn't the container...&& container.has(e.target).length === 0) // ... nor a descendant of the container{container.hide();$(link).css({"font-weight": "normal"});}var fbcontainer = $("div.ip-label-feedback");if (!fbcontainer.is(e.target)&& fbcontainer.has(e.target).length === 0){fbcontainer.hide();}});function createLinks( refresh ) {var spacer = " ";if (refresh) {$("div.ip-label-container").remove();$("a.mw-anonuserlink").css("background-color","");}$("a.mw-anonuserlink").each(function() {// create link after every IP; add the IP into the link html codevar ip = $(this).text();var linkText = messages.formAddLabel;var dataResult = getData( ip );var keyExists = dataResult.keyExists;var dataObj = dataResult.dataObj;if ( keyExists ) {if (dataObj.label) {linkText = dataObj.label;} else if (dataObj.color) {linkText = messages.formChange;}if (dataObj.color) {$(this).css("background-color", colorCodes[ dataObj.color ])}}var link = $("<div class='ip-label-container'></div>").html("<a href='#' class='ip-label-link' _ip='" + ip + "'>"+ linkText + "</a>");$(this).after(spacer, link);});}function createEvents () {$("a.ip-label-link").click(function(event) {// if the link was clicked ...event.preventDefault();var ip = $(this).attr("_ip");var dataResult = getData( ip );var keyExists = dataResult.keyExists;var dataObj = dataResult.dataObj;// ... make the IP address go bold ...var iplink = $(this).parent().prev();iplink.css({"font-weight": "bold"});// ... create div with input form ...$(this).after("<div class='ip-label-popup'>" + messages.formLabel + ": <form action='' class='ip-label-popup-form'><input type='hidden' name='ip_address' value='" + ip + "'><input type='text' name='label' autocomplete='off' size='60' value='"+ ( (keyExists && dataObj.label) ? dataObj.label : "") + "' maxlength='60' class='ip-label-popup-input'><div class='ip-label-popup-bottom'>" + messages.formColor + ":<input type='radio' name='color' value=1" + (keyExists && dataObj.color == 1 ? " checked" : "") + "><div class='ip-label-popup-bottom-red'></div><input type='radio' name='color' value=2" + (keyExists && dataObj.color == 2 ? " checked" : "") + "><div class='ip-label-popup-bottom-yellow'></div><input type='radio' name='color' value=3" + (keyExists && dataObj.color == 3 ? " checked" : "") + "><div class='ip-label-popup-bottom-green'></div><input type='radio' name='color' value=4" + (keyExists && dataObj.color == 4 ? " checked" : "") + "><div class='ip-label-popup-bottom-white'></div><div class='ip-label-submit-buttons'><div class='ip-label-form-delete'></div> <div class='ip-label-form-submit'></div></div></div></form></div>");// this is the div created in the previous statement var popUpDiv = $(this).next();// set focus on input field$(popUpDiv).find("input.ip-label-popup-input").focus();// set up submit event for the form (we can have more than one way to submit the form) $(popUpDiv).find("form.ip-label-popup-form").submit(function(event) {event.preventDefault();var data = $(this).serializeArray();var formObj = {};$.each(data, function(i, val) {formObj[val.name] = val.value;});// pass container div along with the object holding form data to the processor function  processForm(popUpDiv, formObj);});// set up click event for the form + button$(popUpDiv).find(".ip-label-form-submit").on("click", function(){var form = $(this).closest("form.ip-label-popup-form");var input = $("<input>").attr("type", "hidden").attr("name", "action").val("add");$(form).append($(input));$(form).submit();iplink.css({"font-weight": "normal"});});// set up click event for the form - button$(popUpDiv).find(".ip-label-form-delete").on("click", function(){var form = $(this).closest("form.ip-label-popup-form");var input = $("<input>").attr("type", "hidden").attr("name", "action").val("del");$(form).append($(input));$(form).submit();iplink.css({"font-weight": "normal"});});});}function processForm (popUpDiv, formObj) {var fb_msg, isOK;if ( !formObj.ip_address ) {// if somehow there is no IP address, call showError functionshowError( popUpDiv, messages.errMissingIP );}// the key for storage is IP addressvar ip = formObj.ip_address;// check if the key already exists in storage to set up flag for later usevar dataResult = getData( ip );var keyExists = dataResult.keyExists;if ( formObj.action == "add" ) {if ( isBlank(formObj.label) && ( isEmpty(formObj.color) || formObj.color == 4 ) ) {// if ip label is empty or whitespace and color is undefined or white then delete the entrydeleteData( ip );if (keyExists) {var fb_msg = messages.lblDeleted;var isOK = true;} else {var fb_msg = messages.lblMissing;var isOK = false;}showMessage (popUpDiv, fb_msg, isOK);} else {// the form has data to saveif ( isEmpty (formObj.color) ) { formObj.color = 4;}var newLabel = {label:$.trim(formObj.label),color:formObj.color};setData( ip, newLabel );if (keyExists) {var fb_msg = messages.lblChanged;var isOK = true;} else {var fb_msg = messages.lblAdded;var isOK = true;}showMessage (popUpDiv, fb_msg, isOK);}} else if ( formObj.action == "del" ) {// delete was clicked, do deletedeleteData ( ip );if (keyExists) {var fb_msg = messages.lblDeleted;var isOK = true;} else {var fb_msg = messages.lblMissing;var isOK = false;}showMessage (popUpDiv, fb_msg, isOK);} else {showError( popUpDiv, messages.errAction );}popUpDiv.remove();}function showError (div, errormsg) {// show error message, destroy popup div and exitthrow new Error( errormsg );$(div).remove();}function showMessage (div, fb_msg, isOK) {// show feedback message and hide/destroy popup divs// call refresh list function afterwards$(div).hide();var img_Y = 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Yes_check.svg/240px-Yes_check.svg.png';var img_X = 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/X_mark.svg/210px-X_mark.svg.png';// create div box for the messagevar msg_div = $("<div class='ip-label-feedback'><div class='ip-label-feedback-inner'><img src='" + (isOK ? img_Y : img_X) + "'><div class='ip-label-feedback-inner-message'>" + fb_msg + "</div></div></div>");$(div).after(msg_div);msg_div.delay( 1100 ).fadeOut( 1000, function(){msg_div.remove();$(div).remove();createLinks (true);createEvents ();    });}function getData ( key ) {key = "lbl_" + key;var labelObj = localStorage.getObject( key );var keyExists = ( (typeof labelObj === undefined || labelObj === null) ? false : true );var dataObj;if (keyExists) {var dataObj = {label:labelObj.l,color:labelObj.c};}return {keyExists: keyExists,dataObj: dataObj};  }function deleteData ( key ) {key = "lbl_" + key;localStorage.removeItem( key );}function setData( key, dataObj ) {key = "lbl_" + key;var labelObject = { l: dataObj.label, c: dataObj.color };localStorage.setObject(key, labelObject);}function isBlank (str) {return (!str || /^\s*$/.test(str));}function isEmpty(str) {    return (!str || 0 === str.length);}function preload( arrayOfImages ) {    $(arrayOfImages).each(function(){        $('<img/>')[0].src = this;    });}