MediaWiki:Common.js: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
/*! | |||
* jQuery Chord Transposer plugin v1.0 | |||
* http://codegavin.com/projects/transposer | |||
* | |||
* Copyright 2010, Jesse Gavin | |||
* Dual licensed under the MIT or GPL Version 2 licenses. | |||
* http://codegavin.com/license | |||
* | |||
* Date: Sat Jun 26 21:27:00 2010 -0600 | |||
*/ | |||
(function($) { | |||
$.fn.transpose = function(options) { | |||
var opts = $.extend({}, $.fn.transpose.defaults, options); | |||
var currentKey = null; | |||
var keys = [ | |||
{ name: 'Ab', value: 0, type: 'F' }, | |||
{ name: 'A', value: 1, type: 'N' }, | |||
{ name: 'A#', value: 2, type: 'S' }, | |||
{ name: 'Bb', value: 2, type: 'F' }, | |||
{ name: 'B', value: 3, type: 'N' }, | |||
{ name: 'C', value: 4, type: 'N' }, | |||
{ name: 'C#', value: 5, type: 'S' }, | |||
{ name: 'Db', value: 5, type: 'F' }, | |||
{ name: 'D', value: 6, type: 'N' }, | |||
{ name: 'D#', value: 7, type: 'S' }, | |||
{ name: 'Eb', value: 7, type: 'F' }, | |||
{ name: 'E', value: 8, type: 'N' }, | |||
{ name: 'F', value: 9, type: 'N' }, | |||
{ name: 'F#', value: 10, type: 'S' }, | |||
{ name: 'Gb', value: 10, type: 'F' }, | |||
{ name: 'G', value: 11, type: 'N' }, | |||
{ name: 'G#', value: 0, type: 'S' } | |||
]; | |||
var getKeyByName = function (name) { | |||
if (name.charAt(name.length-1) == "m") { | |||
name = name.substring(0, name.length-1); | |||
} | |||
for (var i = 0; i < keys.length; i++) { | |||
if (name == keys[i].name) { | |||
return keys[i]; | |||
} | |||
} | |||
}; | |||
var getChordRoot = function (input) { | |||
if (input.length > 1 && (input.charAt(1) == "b" || input.charAt(1) == "#")) | |||
return input.substr(0, 2); | |||
else | |||
return input.substr(0, 1); | |||
}; | |||
var getNewKey = function (oldKey, delta, targetKey) { | |||
var keyValue = getKeyByName(oldKey).value + delta; | |||
if (keyValue > 11) { | |||
keyValue -= 12; | |||
} else if (keyValue < 0) { | |||
keyValue += 12; | |||
} | |||
var i=0; | |||
if (keyValue == 0 || keyValue == 2 || keyValue == 5 || keyValue == 7 || keyValue == 10) { | |||
// Return the Flat or Sharp Key | |||
switch(targetKey.name) { | |||
case "A": | |||
case "A#": | |||
case "B": | |||
case "C": | |||
case "C#": | |||
case "D": | |||
case "D#": | |||
case "E": | |||
case "F#": | |||
case "G": | |||
case "G#": | |||
for (;i<keys.length;i++) { | |||
if (keys[i].value == keyValue && keys[i].type == "S") { | |||
return keys[i]; | |||
} | |||
} | |||
default: | |||
for (;i<keys.length;i++) { | |||
if (keys[i].value == keyValue && keys[i].type == "F") { | |||
return keys[i]; | |||
} | |||
} | |||
} | |||
} | |||
else { | |||
// Return the Natural Key | |||
for (;i<keys.length;i++) { | |||
if (keys[i].value == keyValue) { | |||
return keys[i]; | |||
} | |||
} | |||
} | |||
}; | |||
var getChordType = function (key) { | |||
switch (key.charAt(key.length - 1)) { | |||
case "b": | |||
return "F"; | |||
case "#": | |||
return "S"; | |||
default: | |||
return "N"; | |||
} | |||
}; | |||
var getDelta = function (oldIndex, newIndex) { | |||
if (oldIndex > newIndex) | |||
return 0 - (oldIndex - newIndex); | |||
else if (oldIndex < newIndex) | |||
return 0 + (newIndex - oldIndex); | |||
else | |||
return 0; | |||
}; | |||
var transposeSong = function (target, key) { | |||
var newKey = getKeyByName(key); | |||
if (currentKey.name == newKey.name) { | |||
return; | |||
} | |||
var delta = getDelta(currentKey.value, newKey.value); | |||
$("span.c", target).each(function (i, el) { | |||
transposeChord(el, delta, newKey); | |||
}); | |||
currentKey = newKey; | |||
}; | |||
var transposeChord = function (selector, delta, targetKey) { | |||
var el = $(selector); | |||
var oldChord = el.text(); | |||
var oldChordRoot = getChordRoot(oldChord); | |||
var newChordRoot = getNewKey(oldChordRoot, delta, targetKey); | |||
var newChord = newChordRoot.name + oldChord.substr(oldChordRoot.length); | |||
el.text(newChord); | |||
var sib = el[0].nextSibling; | |||
if (sib && sib.nodeType == 3 && sib.nodeValue.length > 0 && sib.nodeValue.charAt(0) != "/") { | |||
var wsLength = getNewWhiteSpaceLength(oldChord.length, newChord.length, sib.nodeValue.length); | |||
sib.nodeValue = makeString(" ", wsLength); | |||
} | |||
}; | |||
var getNewWhiteSpaceLength = function (a, b, c) { | |||
if (a > b) | |||
return (c + (a - b)); | |||
else if (a < b) | |||
return (c - (b - a)); | |||
else | |||
return c; | |||
}; | |||
var makeString = function (s, repeat) { | |||
var o = []; | |||
for (var i = 0; i < repeat; i++) o.push(s); | |||
return o.join(""); | |||
} | |||
var isChordLine = function (input) { | |||
var tokens = input.replace(/\s+/, " ").split(" "); | |||
// Try to find tokens that aren't chords | |||
// if we find one we know that this line is not a 'chord' line. | |||
for (var i = 0; i < tokens.length; i++) { | |||
if (!$.trim(tokens[i]).length == 0 && !tokens[i].match(opts.chordRegex)) | |||
return false; | |||
} | |||
return true; | |||
}; | |||
var wrapChords = function (input) { | |||
return input.replace(opts.chordReplaceRegex, "<span class='c'>$1</span>"); | |||
}; | |||
return $(this).each(function() { | |||
var startKey = $(this).attr("data-key"); | |||
if (!startKey || $.trim(startKey) == "") { | |||
startKey = opts.key; | |||
} | |||
if (!startKey || $.trim(startKey) == "") { | |||
throw("Starting key not defined."); | |||
return this; | |||
} | |||
currentKey = getKeyByName(startKey); | |||
// Build tranpose links =========================================== | |||
var keyLinks = []; | |||
$(keys).each(function(i, key) { | |||
if (currentKey.name == key.name) | |||
keyLinks.push("<a href='#' class='selected'>" + key.name + "</a>"); | |||
else | |||
keyLinks.push("<a href='#'>" + key.name + "</a>"); | |||
}); | |||
var $this = $(this); | |||
var keysHtml = $("<div class='transpose-keys'></div>"); | |||
keysHtml.html(keyLinks.join("")); | |||
$("a", keysHtml).click(function(e) { | |||
e.preventDefault(); | |||
transposeSong($this, $(this).text()); | |||
$(".transpose-keys a").removeClass("selected"); | |||
$(this).addClass("selected"); | |||
return false; | |||
}); | |||
$(this).before(keysHtml); | |||
var output = []; | |||
var lines = $(this).text().split(/\r\n|\n/g); | |||
var line, tmp = ""; | |||
for (var i = 0; i < lines.length; i++) { | |||
line = lines[i]; | |||
if (isChordLine(line)) | |||
output.push("<span>" + wrapChords(line) + "</span>"); | |||
else | |||
output.push("<span>" + line + "</span>"); | |||
}; | |||
$(this).html(output.join("\n")); | |||
}); | |||
}; | |||
$.fn.transpose.defaults = { | |||
chordRegex: /^[A-G][b\#]?(2|4|5|6|7|9|11|13|6\/9|7\-5|7\-9|7\#5|7\#9|7\+5|7\+9|b5|#5|#9|7b5|7b9|7sus2|7sus4|add2|add4|add9|aug|dim|dim7|m\/maj7|m6|m7|m7b5|m9|m11|m13|M7|M9|M11|M13|mb5|m|sus|sus2|sus4)*(\/[A-G][b\#]*)*$/, | |||
chordReplaceRegex: /([A-G][b\#]?(2|4|5|6|7|9|11|13|6\/9|7\-5|7\-9|7\#5|7\#9|7\+5|7\+9|b5|#5|#9|7b5|7b9|7sus2|7sus4|add2|add4|add9|aug|dim|dim7|m\/maj7|m6|m7|m7b5|m9|m11|m13|maj7|maj9|maj11|maj13|M7|M9|M11|M13|mb5|m|sus|sus2|sus4)*)/g | |||
}; | |||
})(jQuery); |
Revision as of 21:31, 30 November 2023
/* Any JavaScript here will be loaded for all users on every page load. */ /*! * jQuery Chord Transposer plugin v1.0 * http://codegavin.com/projects/transposer * * Copyright 2010, Jesse Gavin * Dual licensed under the MIT or GPL Version 2 licenses. * http://codegavin.com/license * * Date: Sat Jun 26 21:27:00 2010 -0600 */ (function($) { $.fn.transpose = function(options) { var opts = $.extend({}, $.fn.transpose.defaults, options); var currentKey = null; var keys = [ { name: 'Ab', value: 0, type: 'F' }, { name: 'A', value: 1, type: 'N' }, { name: 'A#', value: 2, type: 'S' }, { name: 'Bb', value: 2, type: 'F' }, { name: 'B', value: 3, type: 'N' }, { name: 'C', value: 4, type: 'N' }, { name: 'C#', value: 5, type: 'S' }, { name: 'Db', value: 5, type: 'F' }, { name: 'D', value: 6, type: 'N' }, { name: 'D#', value: 7, type: 'S' }, { name: 'Eb', value: 7, type: 'F' }, { name: 'E', value: 8, type: 'N' }, { name: 'F', value: 9, type: 'N' }, { name: 'F#', value: 10, type: 'S' }, { name: 'Gb', value: 10, type: 'F' }, { name: 'G', value: 11, type: 'N' }, { name: 'G#', value: 0, type: 'S' } ]; var getKeyByName = function (name) { if (name.charAt(name.length-1) == "m") { name = name.substring(0, name.length-1); } for (var i = 0; i < keys.length; i++) { if (name == keys[i].name) { return keys[i]; } } }; var getChordRoot = function (input) { if (input.length > 1 && (input.charAt(1) == "b" || input.charAt(1) == "#")) return input.substr(0, 2); else return input.substr(0, 1); }; var getNewKey = function (oldKey, delta, targetKey) { var keyValue = getKeyByName(oldKey).value + delta; if (keyValue > 11) { keyValue -= 12; } else if (keyValue < 0) { keyValue += 12; } var i=0; if (keyValue == 0 || keyValue == 2 || keyValue == 5 || keyValue == 7 || keyValue == 10) { // Return the Flat or Sharp Key switch(targetKey.name) { case "A": case "A#": case "B": case "C": case "C#": case "D": case "D#": case "E": case "F#": case "G": case "G#": for (;i<keys.length;i++) { if (keys[i].value == keyValue && keys[i].type == "S") { return keys[i]; } } default: for (;i<keys.length;i++) { if (keys[i].value == keyValue && keys[i].type == "F") { return keys[i]; } } } } else { // Return the Natural Key for (;i<keys.length;i++) { if (keys[i].value == keyValue) { return keys[i]; } } } }; var getChordType = function (key) { switch (key.charAt(key.length - 1)) { case "b": return "F"; case "#": return "S"; default: return "N"; } }; var getDelta = function (oldIndex, newIndex) { if (oldIndex > newIndex) return 0 - (oldIndex - newIndex); else if (oldIndex < newIndex) return 0 + (newIndex - oldIndex); else return 0; }; var transposeSong = function (target, key) { var newKey = getKeyByName(key); if (currentKey.name == newKey.name) { return; } var delta = getDelta(currentKey.value, newKey.value); $("span.c", target).each(function (i, el) { transposeChord(el, delta, newKey); }); currentKey = newKey; }; var transposeChord = function (selector, delta, targetKey) { var el = $(selector); var oldChord = el.text(); var oldChordRoot = getChordRoot(oldChord); var newChordRoot = getNewKey(oldChordRoot, delta, targetKey); var newChord = newChordRoot.name + oldChord.substr(oldChordRoot.length); el.text(newChord); var sib = el[0].nextSibling; if (sib && sib.nodeType == 3 && sib.nodeValue.length > 0 && sib.nodeValue.charAt(0) != "/") { var wsLength = getNewWhiteSpaceLength(oldChord.length, newChord.length, sib.nodeValue.length); sib.nodeValue = makeString(" ", wsLength); } }; var getNewWhiteSpaceLength = function (a, b, c) { if (a > b) return (c + (a - b)); else if (a < b) return (c - (b - a)); else return c; }; var makeString = function (s, repeat) { var o = []; for (var i = 0; i < repeat; i++) o.push(s); return o.join(""); } var isChordLine = function (input) { var tokens = input.replace(/\s+/, " ").split(" "); // Try to find tokens that aren't chords // if we find one we know that this line is not a 'chord' line. for (var i = 0; i < tokens.length; i++) { if (!$.trim(tokens[i]).length == 0 && !tokens[i].match(opts.chordRegex)) return false; } return true; }; var wrapChords = function (input) { return input.replace(opts.chordReplaceRegex, "<span class='c'>$1</span>"); }; return $(this).each(function() { var startKey = $(this).attr("data-key"); if (!startKey || $.trim(startKey) == "") { startKey = opts.key; } if (!startKey || $.trim(startKey) == "") { throw("Starting key not defined."); return this; } currentKey = getKeyByName(startKey); // Build tranpose links =========================================== var keyLinks = []; $(keys).each(function(i, key) { if (currentKey.name == key.name) keyLinks.push("<a href='#' class='selected'>" + key.name + "</a>"); else keyLinks.push("<a href='#'>" + key.name + "</a>"); }); var $this = $(this); var keysHtml = $("<div class='transpose-keys'></div>"); keysHtml.html(keyLinks.join("")); $("a", keysHtml).click(function(e) { e.preventDefault(); transposeSong($this, $(this).text()); $(".transpose-keys a").removeClass("selected"); $(this).addClass("selected"); return false; }); $(this).before(keysHtml); var output = []; var lines = $(this).text().split(/\r\n|\n/g); var line, tmp = ""; for (var i = 0; i < lines.length; i++) { line = lines[i]; if (isChordLine(line)) output.push("<span>" + wrapChords(line) + "</span>"); else output.push("<span>" + line + "</span>"); }; $(this).html(output.join("\n")); }); }; $.fn.transpose.defaults = { chordRegex: /^[A-G][b\#]?(2|4|5|6|7|9|11|13|6\/9|7\-5|7\-9|7\#5|7\#9|7\+5|7\+9|b5|#5|#9|7b5|7b9|7sus2|7sus4|add2|add4|add9|aug|dim|dim7|m\/maj7|m6|m7|m7b5|m9|m11|m13|M7|M9|M11|M13|mb5|m|sus|sus2|sus4)*(\/[A-G][b\#]*)*$/, chordReplaceRegex: /([A-G][b\#]?(2|4|5|6|7|9|11|13|6\/9|7\-5|7\-9|7\#5|7\#9|7\+5|7\+9|b5|#5|#9|7b5|7b9|7sus2|7sus4|add2|add4|add9|aug|dim|dim7|m\/maj7|m6|m7|m7b5|m9|m11|m13|maj7|maj9|maj11|maj13|M7|M9|M11|M13|mb5|m|sus|sus2|sus4)*)/g }; })(jQuery);