사용자:IRTC1015/IPLabeller.js

참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다. 구글 크롬, 파이어폭스, 마이크로소프트 엣지, 사파리: ⇧ Shift 키를 누른 채 "새로 고침" 버튼을 클릭하십시오. 더 자세한 정보를 보려면 위키백과:캐시 무시하기 항목을 참고하십시오.

/***
 * IPLabeller
 * 
 * IP 사용자에 영구적인 레이블 및 배경색 부여
 * 
 * 원본: [[:en:User:Cumbril/IPLabeller]]
 * 
 * 설정용 변수:
 *	window.colorCodes: object, 기본값 대신 사용할 색상을 설정
 ***/

mw.loader.load('//ko.wikipedia.org/w/index.php?title=' +
	'User:IRTC1015/IPLabeller.css&action=raw&ctype=text/css', 'text/css');

// allow user to override colorCodes in common.js, make sure property '4' stays empty
if (!window.colorCodes) {
	var colorCodes = {
		1:"#ffcccc",	// red
		2:"#ffee99",	// yellow
		3:"#ccff66",	// green
		4:""			// white (must be empty)
	};
} else {
	colorCodes['4'] = "";
}

var messages = {
	errNoStorage: '저장소를 사용할 수 없습니다. 다음 사항을 확인 바랍니다.\n' +
					'a) 브라우저에서 영구 저장소가 지원되지 않음\n' +
					'b) 저장소가 비활성화됨\n' +
					'c) 저장소가 가득 참',
	formAddLabel: '+',
	formAddTitle: '레이블 추가',
	formChange  : '변경',
	formLabel   : '레이블',
	formColor   : '색상',
	errMissingIP: '오류: IP가 없습니다',
	lblDeleted  : '레이블 제거됨',
	lblMissing  : '레이블 없음',
	lblChanged  : '레이블 변경됨',
	lblAdded    : '레이블 추가됨',
	errAction   : '오류: 알 수 없는 동작'			
};

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 nothing
		throw new Error( messages.errNoStorage );
	} else {
		// 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.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) {
		$(".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 code
		var ip = $(this).text();
		var linkText = messages.formAddLabel;
		var linkTitle = messages.formAddTitle;
		
		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 = $('<span class="ip-label-container"></span>').html('<a href="#" class="ip-label-link" data-ip="' + ip + '" title="' + linkTitle + '">' + 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).data('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 function
		showError( popUpDiv, messages.errMissingIP );
	}

	// the key for storage is IP address
	var ip = formObj.ip_address;

	// check if the key already exists in storage to set up flag for later use
	
	var 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 entry
			deleteData( ip );
			if (keyExists) {
				fb_msg = messages.lblDeleted;
				isOK = true;
			} else {
				fb_msg = messages.lblMissing;
				isOK = false;
			}
			showMessage (popUpDiv, fb_msg, isOK);
		} else {
			// the form has data to save
			if ( isEmpty (formObj.color) ) 
			{ 
				formObj.color = 4;
			}
			var newLabel = {
				label:$.trim(formObj.label),
				color:formObj.color
			};
			setData( ip, newLabel );
			if (keyExists) {
				fb_msg = messages.lblChanged;
				isOK = true;		
			} else {
				fb_msg = messages.lblAdded;
				isOK = true;
			}
			showMessage (popUpDiv, fb_msg, isOK);
		}
	} else if ( formObj.action == "del" ) {
		// delete was clicked, do delete
		deleteData ( ip );
		if (keyExists) {
			fb_msg = messages.lblDeleted;
			isOK = true;		
		} else {
			fb_msg = messages.lblMissing;
			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 exit
	throw 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 message
	var 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;
    });
}