////////////////////////////////////////////////////////////////////////////
// Enables user to set permanent labels and color backgrounds on accounts //
////////////////////////////////////////////////////////////////////////////
// Based on User:Cumbril's IP labeler
// This code is licensed under the CC BY-SA 3.0 License and the GFDL.
// WARNING! CODE IS TERRIBLE
importStylesheet('User:What cat?/userlabeller.css');
// encapsulate
(function(){
// allow user to override colorCodes in common.js, make sure property '4' stays empty
if (!window.colorCodes) {
window.colorCodes = {
'Red':"#FC8888", // red
'Yellow':"#ffe299", // yellow
'Green':"#99FF33", // green
'Blank':"" // white (must be empty)
};
} else {
window.colorCodes['Blank'] = "";
}
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',
errNoName: 'Error: missing username!',
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'
]);
window.userlabel = {get:getData, set:setData, del:deleteData}
// TODO: Make these obviously identifiable as callbacks (12/8/2016)
window.userlabel.changecolor = function(e) {
$('#ul-example').css({'background-color':e.target.value});
}
window.userlabel.changelabel = function(e) {
$('#ul-example-label').text(e.target.value);
}
// END TODO
window.userlabel.reload = function() {
createLinks(true);
createEvents();
}
$(document).ready(function(){
if(typeof(Storage) === "undefined") {
// if there is no local storage available, display message and do nothing
throw new Error( messages.errNoStorage );
} else {
if (typeof(localStorage['lbls']) === "undefined") { localStorage['lbls'] = "{}"; }
// define two custom methods for storing objects
Storage.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.ul-popup");
var link = $("a.mw-userlink");
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.ul-feedback");
if (!fbcontainer.is(e.target)
&& fbcontainer.has(e.target).length === 0)
{
fbcontainer.hide();
}
});
function createLinks( refresh ) {
var spacer = " ";
if (refresh) {
$("span.ul-container").remove();
$("a.mw-userlink").css("background-color","");
}
$("a.mw-userlink").each(function() {
// create link after every name; add the name into the link html code
var username = $(this).text();
var linkText = messages.formAddLabel;
var dataResult = getData( username );
var keyExists = dataResult.exists;
var dataObj = dataResult.obj;
console.log(username,dataResult);
if ( keyExists ) {
if (dataObj.label) {
linkText = dataObj.label;
} else if (dataObj.color) {
linkText = messages.formChange;
}
if (dataObj.color) {
$(this).css("background-color", dataObj.color);
}
}
var link = $("<span class='ul-container'></div>").html("<a href='#' class='ul-link' data-name='" + username + "'>"+ linkText + "</a>");
$(this).after(spacer, link);
});
}
function createEvents () {
$("a.ul-link").click(function(event) {
// if the link was clicked ...
event.preventDefault();
var name = $(this).data("name");
var data = getData( name );
// legacy variables just in case I miss one
var username = name; var dataResult = data;
var keyExists = dataResult.exists;
var dataObj = dataResult.obj;
// ... make the username bold ...
var userlink = $(this).parent().prev();
userlink.css({"font-weight": "bold"});
if(typeof(dataObj)!=="undefined"){
dlabel = dataObj.label;
dcolor = dataObj.color;
} else {
dcolor = "";
dlabel = "";
}
var Window = new Morebits.simpleWindow( 600, 400 );
Window.setScriptName("User label");
Window.setTitle("Add/edit label for "+name);
var form = new Morebits.quickForm( function(e){
if(e.target.label === "" && e.target.color === "") {deleteData(name)}
else{
setData(name,{label:e.target.label.value,color:e.target.getChecked('color')[0]});
Window.close();
createLinks(true);
createEvents();
}
} );//window.userlabel.processForm
var nameexample = form.append({type: 'div', label: "If you're seeing this, something has gone wrong", id:'ul-example-container'}); // unless you're reading the source code, then it's fine
var colorlist = form.append( { type:'field', label:'Colors' } );
colorlist.append({type: 'radio', name:'color', list: colorsToList(window.colorCodes,dcolor),
event: function( e ) {
window.userlabel.changecolor( e );
e.stopPropagation();
}
}
);
form.append({type: 'input', name:'label', label:'Label text: ', value: dlabel,
event: function( e ) {
window.userlabel.changelabel( e );
e.stopPropagation();
}
}
);
form.append( { type:'submit', label:"Set label" } );
var result = form.render();
// this is pretty much the only real way to do this seamlessly before showing the form
result.querySelector('#ul-example-container').innerHTML = $("<div id='ul-example-container'>"+
"<span id='ul-example'>"+name+"</span>"+
"<div class='ul-container'>"+
"<a href='#' id='ul-example-label' data-name='"+name+"'>"+ "Add label" + "</a>"+
"</div>"+
"</div>").html();
Window.setContent( result );
Window.display();
});
}
function colorsToList(colors,select) {
var list = [];
// awful terrible hacky for-loop; k is key, v is value, i is iterator value
for (var i=0;i<Object.keys(window.colorCodes).length;i++){var k=Object.keys(window.colorCodes)[i];var v=window.colorCodes[k];
list.push({label:k,value:v,style:'background-color:'+v,checked:(v==select)}) // the fact that this actually works is great
}
return list
}
function getData ( key ) {
var labelListObj = localStorage.getObject("lbls");
var labelObj = labelListObj[key]
var keyExists = ( (typeof labelObj === "undefined" || labelObj === null) ? false : true );
var dataObj;
if (keyExists) {
if(typeof(labelObj.label)==='undefined') {
var dataObj = {
label:labelObj.l,
color:labelObj.c
};
} else {
var dataObj = {
label:labelObj.label,
color:labelObj.color
};
}
}
return {
exists: keyExists,
obj: dataObj
};
}
function deleteData ( key ) {
var labelObj = localStorage.getObject("lbls")
delete labelObj[key];
localStorage.setObject("lbls", labelObj);
}
function setData( key, dataObj ) {
var labelObj = localStorage.getObject("lbls")
var p = { l: dataObj.label, c: dataObj.color } // the p stands for parsed
if((p.l === "" || typeof(p.l) !== "string") && (p.c === "" || typeof(p.c) !== "string")) {
deleteData(key)
}
labelObj[key] = p;
localStorage.setObject("lbls", labelObj);
}
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;
});
}
function colorsToList(colors, color) {
var list = [];
// awful terrible hacky for-loop; k is key, v is value, i is iterator value
for (var i=0;i<Object.keys(window.colorCodes).length;i++){var k=Object.keys(window.colorCodes)[i];var v=window.colorCodes[k];
list.push({label:k,value:v,style:'background-color:'+v,checked:(v===color)}) // i'm surprised this works
}
return list
}
})()