Last active
February 8, 2018 13:38
-
-
Save d4rkie/d15ca9630c8e2bcd50ad to your computer and use it in GitHub Desktop.
MusicBrainz: Paste-A-Date! (fixed for the new Relationship Editor)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name MusicBrainz: Paste-A-Date! | |
// @description This script adds a field after the existing date fields where you can paste a date and it will try to parse it. | |
// @version 2015-01-13 | |
// @author nikki, d4rkie | |
// | |
// @grant none | |
// @include *://musicbrainz.org/* | |
// @include *://beta.musicbrainz.org/* | |
// @include *://test.musicbrainz.org/* | |
// ==/UserScript== | |
//**************************************************************************// | |
var nikkis_messy_date_extractor; | |
init_paste_a_date(); | |
document.body.addEventListener("DOMNodeInserted", paste_a_date_calmDOM, false); | |
var paste_a_date_calmDOMto; | |
function paste_a_date_calmDOM() { // sampled from JESUS2099 | |
if (paste_a_date_calmDOMto) { | |
clearTimeout(paste_a_date_calmDOMto); | |
} | |
paste_a_date_calmDOMto = setTimeout(init_paste_a_date, 500); // set to 0.5 seconds to spam less | |
} | |
function init_paste_a_date() { | |
/* Javascript sucks! */ | |
Array.prototype.unique = function () { | |
var r = new Array(); | |
o:for(var i = 0, n = this.length; i < n; i++) { | |
for(var x = 0, y = r.length; x < y; x++) { | |
if(r[x]==this[i]) | |
continue o; | |
} | |
r[r.length] = this[i]; | |
} | |
return r; | |
} | |
/* End of workaround because Javascript sucks! */ | |
nikkis_messy_date_extractor = function (str) { | |
// replace fullwidth digits | |
str = str.replace(/[0-9]/g, function(a){ return String.fromCharCode(a.charCodeAt(0)-("0".charCodeAt(0)-"0".charCodeAt(0))); }); | |
// RoC year numbering - http://en.wikipedia.org/wiki/Minguo_calendar | |
str = str.replace(/民國([0-9]{1,3})/, function(a, year){ return parseInt(year)+1911; }); | |
// Japanese eras - http://en.wikipedia.org/wiki/Japanese_era_name | |
str = str.replace(/(明治|大正|昭和|平成)元(年)/, "$1"+"1$2"); | |
str = str.replace(/(明治|M)([0-9]{1,2})/, function(a, b, year){ return parseInt(year)+1867; }); | |
str = str.replace(/(大正|T)([0-9]{1,2})/, function(a, b, year){ return parseInt(year)+1911; }); | |
str = str.replace(/(昭和|S)([0-9]{1,2})/, function(a, b, year){ return parseInt(year)+1925; }); | |
str = str.replace(/(平成|H)([0-9]{1,2})/, function(a, b, year){ return parseInt(year)+1988; }); | |
// Japanese letters for years on older releases - https://wiki.musicbrainz.org/User:Nikki/Japanese_stuff | |
var jp_years = Array(); | |
jp_years["N"] = "1984"; | |
jp_years["I"] = "1985"; | |
jp_years["H"] = "1986"; | |
jp_years["O"] = "1987"; | |
jp_years["R"] = "1988"; | |
jp_years["E"] = "1989"; | |
jp_years["C"] = "1990"; | |
jp_years["D"] = "1991"; | |
jp_years["K"] = "1992"; | |
str = str.replace(/([NIHORECDK])-([0-9]{1,2}-[0-9]{1,2})/, function(a, year, date){ return jp_years[year] + "-" + date; }); | |
// Ordinal numbers | |
str = str.replace(/\b([0-9]{1,2})(st|nd|rd|th)\b/, "$1"); | |
// Spanish months | |
str = str.replace(/ de ([a-z]+) del? /i, " $1 "); | |
var cjk = /^\W*([0-9]{2}|[0-9]{4})(?:(?:\u5E74|\uB144\W?)(0?[1-9]|1[0-2])(?:(?:\u6708|\uC6D4\W?)(0?[1-9]|[12][0-9]|3[01])(?:\u65E5|\uC77C)?)?)?\W*$/; | |
var ymd = /^\W*([0-9]{2}|[0-9]{4})(?:\W+(0?[1-9]|1[0-2])(?:\W+(0?[1-9]|[12][0-9]|3[01]))?)?\W*$/; | |
var dmy = /^\W*(?:(0?[1-9]|[12][0-9]|3[01])\W+)?(0?[1-9]|1[0-2])\W+([0-9]{2}|[0-9]{4})\W*$/; | |
var mdy = /^\W*(0?[1-9]|1[0-2])\W+(0?[1-9]|[12][0-9]|3[01])\W+((?:1[89]|20)?[0-9]{2})\W*$/; | |
var dmy_text = /^\W*(?:(0?[1-9]|[12][0-9]|3[01])\W+)?([\wÀ-ÖØ-öø-ÿ ]+)\W+([0-9]{2}|[0-9]{4})\W*$/; | |
var ymd_text = /^\W*([0-9]{2}|[0-9]{4})\W+([\wÀ-ÖØ-öø-ÿ ]+)(?:\W+(0?[1-9]|[12][0-9]|3[01]))?\W*$/; | |
var mdy_text = /^\W*([\wÀ-ÖØ-öø-ÿ]+)\W+(0?[1-9]|[12][0-9]|3[01])\W+([0-9]{2}|[0-9]{4})\W*$/; | |
var dates = Array(); | |
if (cjk.test(str)) { | |
var matches = ymd.exec(str); | |
var newdate = clean_date(matches[1], matches[2], matches[3]); | |
if (newdate) dates.push(newdate); | |
return dates; // We know there's only one match and since JS's Unicode support is lacking, continuing will cause false matches | |
} | |
if (ymd.test(str)) { | |
var matches = ymd.exec(str); | |
var newdate = clean_date(matches[1], matches[2], matches[3]); | |
if (newdate) dates.push(newdate); | |
} | |
if (dmy.test(str)) { | |
var matches = dmy.exec(str); | |
if (matches[3] > 2484) matches[3] = matches[3] - 543; // Thai years | |
var newdate = clean_date(matches[3], matches[2], matches[1]); | |
if (newdate) dates.push(newdate); | |
} | |
if (mdy.test(str)) { | |
var matches = mdy.exec(str); | |
var newdate = clean_date(matches[3], matches[1], matches[2]) | |
if (newdate) dates.push(newdate); | |
} | |
if (dmy_text.test(str)) { | |
var matches = dmy_text.exec(str); | |
var month = get_month(matches[2]); | |
var newdate = clean_date(matches[3], month, matches[1]); | |
if (newdate && month) dates.push(newdate); | |
} | |
if (ymd_text.test(str)) { | |
var matches = ymd_text.exec(str); | |
var month = get_month(matches[2]); | |
var newdate = clean_date(matches[1], month, matches[3]); | |
if (newdate && month) dates.push(newdate); | |
} | |
if (mdy_text.test(str)) { | |
var matches = mdy_text.exec(str); | |
var month = get_month(matches[1]); | |
var newdate = clean_date(matches[3], month, matches[2]); | |
if (newdate && month) dates.push(newdate); | |
} | |
return dates; | |
} | |
function clean_date(y, m, d) { | |
if (y.length == 2) y = (y > 20) ? "19"+y : "20"+y; | |
if (m && m.length == 1) m = "0"+m; | |
if (d && d.length == 1) d = "0"+d; | |
if (d == 29 && m == 2 && y%4 != 0 && y%400 != 0) return false; | |
if (d == 30 && m == 2) return false; | |
if (d == 31 && (m == 2 || m == 4 || m == 6 || m == 9 || m == 11)) return false; | |
var newdate = [ y ]; | |
if (m) newdate.push(m); | |
if (d) newdate.push(d); | |
return newdate.join("-"); | |
} | |
function get_date(input) { | |
var div = input.date_display; | |
var str = input.value; | |
var dates = nikkis_messy_date_extractor(str).sort().unique(); | |
if (str.length < 1) { | |
div.style.borderColor = 'white'; | |
div.style.backgroundColor = 'white'; | |
div.innerHTML = ""; | |
div.style.display = 'inline'; | |
} else if (dates.length == 1) { | |
set_date(input, dates[0].split('-')[0], dates[0].split('-')[1], dates[0].split('-')[2]); | |
div.style.borderColor = 'green'; | |
div.style.backgroundColor = '#CDFFBD'; | |
div.innerHTML = "✓"; | |
div.style.display = 'inline'; | |
} else if (dates.length > 1) { | |
div.style.borderColor = 'yellow'; | |
div.style.backgroundColor = '#FFEEBD'; | |
div.style.display = 'block'; | |
div.innerHTML = "multiple possibilities:"; | |
for (var j = 0; j < dates.length; j++) { | |
div.appendChild( document.createElement("br")); | |
var a = document.createElement("a"); | |
a.innerHTML = dates[j]; | |
a.style.cursor = "pointer"; | |
a.addEventListener("click", (function(i,j,k,l) { return function(){ set_date(i,j,k,l); }})(input, dates[j].split('-')[0], dates[j].split('-')[1], dates[j].split('-')[2]), false); | |
div.appendChild(a, div); | |
} | |
} else { | |
div.style.borderColor = 'red'; | |
div.style.backgroundColor = '#FFBDCD'; | |
div.innerHTML = "✗"; | |
div.style.display = 'inline'; | |
} | |
} | |
function trigger_event(name, element) { | |
var event = document.createEvent("HTMLEvents"); | |
event.initEvent(name, false, true); | |
element.dispatchEvent(event); | |
} | |
function set_date(input, year, month, day) { | |
var e = input.parentNode.getElementsByTagName("input"); | |
e[0].value = year ? year : ""; | |
trigger_event('change', e[0]); | |
e[1].value = month ? month : ""; | |
trigger_event('change', e[1]); | |
e[2].value = day ? day : ""; | |
trigger_event('change', e[2]); | |
} | |
function get_month (str) { | |
var months = Array(); | |
months["january"] = "1"; | |
months["jan"] = "1"; | |
months["janv"] = "1"; | |
months["januari"] = "1"; | |
months["janeiro"] = "1"; | |
months["januar"] = "1"; | |
months["janvier"] = "1"; | |
months["enero"] = "1"; | |
months["february"] = "2"; | |
months["feb"] = "2"; | |
months["févr"] = "2"; | |
months["februari"] = "2"; | |
months["fevereiro"] = "2"; | |
months["februar"] = "2"; | |
months["février"] = "2"; | |
months["febrero"] = "2"; | |
months["march"] = "3"; | |
months["mar"] = "3"; | |
months["mars"] = "3"; | |
months["março"] = "3"; | |
months["märz"] = "3"; | |
months["marzo"] = "3"; | |
months["marts"] = "3"; | |
months["april"] = "4"; | |
months["apr"] = "4"; | |
months["avr"] = "4"; | |
months["abril"] = "4"; | |
months["avril"] = "4"; | |
months["may"] = "5"; | |
months["mai"] = "5"; | |
months["maj"] = "5"; | |
months["maio"] = "5"; | |
months["mayo"] = "5"; | |
months["june"] = "6"; | |
months["jun"] = "6"; | |
months["juin"] = "6"; | |
months["juni"] = "6"; | |
months["junho"] = "6"; | |
months["junio"] = "6"; | |
months["july"] = "7"; | |
months["jul"] = "7"; | |
months["juil"] = "7"; | |
months["juli"] = "7"; | |
months["julho"] = "7"; | |
months["julio"] = "7"; | |
months["juillet"] = "7"; | |
months["august"] = "8"; | |
months["aug"] = "8"; | |
months["août"] = "8"; | |
months["augusti"] = "8"; | |
months["agosto"] = "8"; | |
months["september"] = "9"; | |
months["sep"] = "9"; | |
months["sept"] = "9"; | |
months["setembro"] = "9"; | |
months["septembre"] = "9"; | |
months["septiembre"] = "9"; | |
months["october"] = "10"; | |
months["oct"] = "10"; | |
months["oktober"] = "10"; | |
months["outubro"] = "10"; | |
months["octobre"] = "10"; | |
months["octubre"] = "10"; | |
months["november"] = "11"; | |
months["nov"] = "11"; | |
months["novembro"] = "11"; | |
months["novembre"] = "11"; | |
months["noviembre"] = "11"; | |
months["december"] = "12"; | |
months["dec"] = "12"; | |
months["déc"] = "12"; | |
months["dezembro"] = "12"; | |
months["dezember"] = "12"; | |
months["décembre"] = "12"; | |
months["diciembre"] = "12"; | |
// roman numerals | |
months["i"] = "1"; | |
months["ii"] = "2"; | |
months["iii"] = "3"; | |
months["iv"] = "4"; | |
months["v"] = "5"; | |
months["vi"] = "6"; | |
months["vii"] = "7"; | |
months["viii"] = "8"; | |
months["ix"] = "9"; | |
months["x"] = "10"; | |
months["xi"] = "11"; | |
months["xii"] = "12"; | |
if (months[str.toLowerCase()]) | |
return months[str.toLowerCase()]; | |
return 0; | |
} | |
$("body").on("input", "input.paste-a-date", function (event) { | |
get_date(event.target); | |
}); | |
$(".partial-date").each(function () { | |
this.style.display = "block"; | |
add_input(this); | |
}); | |
function add_input(container) { | |
container = $(container); | |
var input = {}; | |
// check if already added | |
var oldInput = $('.paste-a-date', container).first(); | |
if (oldInput.length) { | |
return oldInput[0]; | |
} | |
var input = document.createElement("input"); | |
input.setAttribute("type", "text"); | |
input.setAttribute("size", "12"); | |
input.style.marginLeft = "4px"; | |
input.style.width = "auto"; | |
input.className = "paste-a-date"; | |
var lastInput = $('input', container).last(); | |
$(input).insertAfter(lastInput); | |
input.date_display = add_display(container[0]); | |
return input; | |
} | |
function add_display(container) { | |
var div = container.appendChild(document.createElement("div")); | |
div.style.border = "1px solid white"; | |
return div; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment