A basic guitar tablature editor written in JavaScript
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
TablatureJS/tablaturejs.html

656 lines
18 KiB

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<!-- vim: set lbr sbr=@___ encoding=utf-8 columns=80 lines=999: -->
<!--
TODO:
* work with insert/delete
* add repeat symbol (:)
CHANGELOG:
v0.1.0 - 2010/12/20
* Implemented import
v0.0.9 - 2010/05/11
* Implemented export
v0.0.8 - 2010/01/14
* Implemented mouse click
v0.0.7 - 2010/01/11
* Improved deletion when placed on a bar
* Major refactoring
* Automatically deletion of trailing empty staves
* Added copy/paste feature
v0.0.6 - 2009/10/16
* Added quick help
v0.0.5 - 2009/09/25
* Basic styling
v0.0.4 - 2009/09/24
* Possibility to add new staves
* Moving from staff to staff with keys
v0.0.3 - 2009/09/23
* Moving current cell with keys
* Adding speed
v0.0.2 - 2009/09/22
* Current cell display
v0.0.1 - 2009/09/21
* Basic staff display
-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>TablatureJS</title>
<script type="text/javascript" src="mootools-1.2.4-core-yc.js"></script>
<script type="text/javascript">
//<![CDATA[
var Tablature = {
NUMBER_OF_LINES : 6,
WIDTH : 78,
MAX_SPEED : 64,
BORDER : new Element('strong', { text : '|' }),
LINE : new Element('span', { text : '-' }),
BAR : new Element('span', { text : '|' }),
_numberOfStaves : null,
_currentStaffNumber : null,
_currentColumnNumber : null,
_currentLineNumber : null,
_movingSpeed : null,
_mousePosition : null,
_copiedColumn : ['-', '-', '-', '-', '-', '-'],
initialise: function() {
Tablature._numberOfStaves = 0;
Tablature._addStaff();
Tablature._currentColumnNumber = 0;
Tablature._currentLineNumber = 0;
Tablature._currentStaffNumber = 0;
Tablature._setMovingSpeed(1);
Tablature._displayCursor();
Tablature.hideExport();
Tablature.hideImport();
$('tab').addEvent('click', Tablature._onClick);
$('tab').addEvent('mouseover', Tablature._onMouseOver);
$('export').addEvent('click', Tablature.export);
$('import').addEvent('click', Tablature.showImport);
$('close-export').addEvent('click', Tablature.hideExport);
$('close-import').addEvent('click', Tablature.hideImport);
$('save-import').addEvent('click', Tablature.import);
},
changeSpeed: function(increaseOrDecrease) {
switch(increaseOrDecrease) {
case 'increase':
Tablature._setMovingSpeed( Tablature._movingSpeed * 2 );
break;
case 'decrease':
Tablature._setMovingSpeed( Tablature._movingSpeed / 2 );
break;
;
}
},
clear: function() {
for ( var staff = Tablature._numberOfStaves ; staff > 0 ; staff-- ) {
Tablature._getStaff(staff-1).destroy();
Tablature._numberOfStaves--;
}
},
copyColumn: function() {
Tablature._getCurrentColumn().each( function(e,i) {
Tablature._copiedColumn[i] = e.get('text');
});
},
draw: function(key) {
Tablature._getCurrentNote().set('text', key);
},
drawBar: function() {
Tablature._getCurrentColumn().each( function(p) {
p.set('text', '|');
});
},
eraseColumn: function() {
Tablature._getCurrentColumn().each( function(p) {
p.set('text', '-');
});
},
export: function() {
var tab = '';
$('tab').getElements('div').each( function(staff) {
staff.getElements('p').each( function(line) {
tab += '|';
line.getElements('span').each( function(note) {
tab += note.get('text');
})
tab += '|';
tab += "\n";
});
tab += "\n";
});
$('export-content').value = tab;
Tablature._showExport();
},
hideExport: function() {
$('export-tab').setStyle('display','none');
},
hideImport: function() {
$('import-tab').setStyle('display','none');
},
import: function() {
var tab = $('import-content').value;
lines = tab.match(new RegExp("\\|.{"+Tablature.WIDTH+"}\\|", "g"));
var staves = [];
for ( var staff = 0 ; staff*Tablature.NUMBER_OF_LINES < lines.length ; staff += 1 ) {
staves[staff] = [];
for ( var line = 0 ; line < Tablature.NUMBER_OF_LINES ; line++ ) {
staves[staff][line] = lines[staff*Tablature.NUMBER_OF_LINES+line].match(new RegExp(".", "g"));
}
}
Tablature.clear();
for ( var staff = 0 ; staff < staves.length ; staff++ ) {
Tablature._addStaff();
Tablature._currentStaffNumber = staff;
for ( var line = 0 ; line < staves[staff].length ; line++ ) {
Tablature._currentLineNumber = line;
for ( var note = 1 ; note < staves[staff][line].length-1 ; note++ ) {
Tablature._currentColumnNumber = note-1;
Tablature.draw(staves[staff][line][note]);
}
}
}
Tablature._currentStaffNumber = 0;
Tablature._currentColumnNumber = 0;
Tablature._currentLineNumber = 0;
Tablature._displayCursor();
Tablature.hideImport();
},
move: function(direction) {
Tablature._resetCursor();
switch(direction) {
case 'right':
Tablature._currentColumnNumber = Math.min(
Tablature.WIDTH - 1,
Tablature._currentColumnNumber + Tablature._movingSpeed
)
break;
case 'left':
Tablature._currentColumnNumber = Math.max(
0,
Tablature._currentColumnNumber - Tablature._movingSpeed
)
break;
case 'down':
Tablature._currentLineNumber = Math.min(
Tablature.NUMBER_OF_LINES - 1,
Tablature._currentLineNumber + 1
)
break;
case 'up':
Tablature._currentLineNumber = Math.max(
0,
Tablature._currentLineNumber - 1
)
break;
case 'next':
Tablature._currentStaffNumber++;
if ( Tablature._currentStaffNumber == Tablature._numberOfStaves ) {
Tablature._addStaff();
}
break;
case 'previous':
if ( Tablature._currentStaffNumber == Tablature._numberOfStaves-1 ) {
Tablature._deleteStaffIfEmpty();
}
Tablature._currentStaffNumber = Math.max(
0,
Tablature._currentStaffNumber - 1
)
break;
case 'start':
Tablature._currentColumnNumber = 0;
break;
case 'end':
Tablature._currentColumnNumber = Tablature.WIDTH - 1;
break;
;
}
Tablature._displayCursor();
},
pasteColumn: function() {
Tablature._getCurrentColumn().each( function(e,i) {
e.set('text', Tablature._copiedColumn[i]);
});
},
showImport: function() {
$('import-content').value='';
$('import-tab').setStyle('display','block');
},
_addStaff: function() {
Tablature._numberOfStaves++;
var newStaff = new Element('div', {
'class': 'staff-' + Tablature._numberOfStaves
});
for ( var line = 0; line < Tablature.NUMBER_OF_LINES; line++ ) {
var newLine = new Element('p');
newLine.adopt(Tablature.BORDER.clone())
for ( var column = 0; column < Tablature.WIDTH; column++ ) {
newLine.adopt(Tablature.LINE.clone());
}
newLine.adopt(Tablature.BORDER.clone())
newStaff.adopt(newLine);
}
$('tab').adopt(newStaff);
},
_deleteStaffIfEmpty: function() {
if ( Tablature._numberOfStaves > 1 ) {
var isEmpty = Tablature._getCurrentLines().every( function(e, i) {
return e.getElements('span').every( function(n, i) {
return n.get('text') == '-';
})
})
if ( isEmpty ) {
Tablature._getCurrentStaff().destroy();
Tablature._numberOfStaves--;
}
}
},
_displayCursor: function() {
Tablature._getCurrentColumn().each( function(e, i) {
e.addClass('active');
if ( i == Tablature._currentLineNumber )
e.addClass('current');
});
$('position').set('text', '{column}/{max} ({staff}/{staves})'.substitute({
column: Tablature._currentColumnNumber + 1,
max: Tablature.WIDTH,
staff: Tablature._currentStaffNumber + 1,
staves: Tablature._numberOfStaves
}));
},
_getCurrentColumn: function() {
var lines = [];
Tablature._getCurrentLines().each( function(e, i) {
lines[i] = e.getElements('span')[Tablature._currentColumnNumber];
});
return lines;
},
_getCurrentLines: function() {
return Tablature._getCurrentStaff().getElements('p');
},
_getCurrentNote: function() {
return Tablature._getCurrentLines()[Tablature._currentLineNumber]
.getElements('span')[Tablature._currentColumnNumber];
},
_getCurrentStaff: function() {
return Tablature._getStaff(Tablature._currentStaffNumber);
},
_getStaff: function(staffNumber) {
return $('tab').getElements('div')[staffNumber];
},
_onClick: function(e) {
if ( e.target.get('tag') == 'span' ) {
Tablature._resetCursor();
var currentCell = e.target;
var currentLine = currentCell.getParent();
var currentStaff = currentLine.getParent();
var columnIndex = currentLine.getElements('span').indexOf(currentCell);
var lineIndex = currentStaff.getElements('p').indexOf(currentLine);
var staffIndex = $('tab').getElements('div').indexOf(currentStaff);
Tablature._currentStaffNumber = staffIndex;
Tablature._currentLineNumber = lineIndex;
Tablature._currentColumnNumber = columnIndex;
Tablature._displayCursor();
}
},
_onMouseOver: function(e) {
if ( e.target.get('tag') == 'span' ) {
$('tab').getElements('.selected')
.removeClass('selected');
e.target.addClass('selected');
}
},
_resetCursor: function() {
Tablature._getCurrentStaff().getElements('.active')
.removeClass('active')
.removeClass('current');
},
_showExport: function() {
$('export-tab').setStyle('display','block');
},
_setMovingSpeed: function(newSpeed) {
Tablature._movingSpeed = Math.min(
Math.ceil(newSpeed),
Tablature.MAX_SPEED
);
$('moving-speed').set('text', Tablature._movingSpeed);
}
}
var Command = {
readInput: function(e) {
//console.log( e.code + ': ' + e.key );
var recognisedEvent = true;
switch(e.key) {
case '+':
Tablature.changeSpeed('increase');
break;
case '-':
Tablature.changeSpeed('decrease');
break;
case 'right':
case 'left':
case 'up':
case 'down':
Tablature.move(e.key);
break;
case 'h':
case 'p':
case 't':
case 'b':
case '/':
case '\\':
Tablature.draw(e.key);
break;
case 'c':
Tablature.copyColumn();
break;
case 'v':
Tablature.pasteColumn();
break;
case 'e':
Tablature.export();
break;
case 'i':
Tablature.showImport();
break;
case 'space':
Tablature.move('next');
break;
case 'enter':
Tablature.drawBar();
break;
case 'esc':
Tablature.hideExport();
Tablature.hideImport();
break;
default:
switch(e.code) {
case 33: // PgUp
Tablature.move('previous');
break;
case 34: // PgDwn
Tablature.move('next');
break;
case 36: // Start
Tablature.move('start');
break;
case 35: // End
Tablature.move('end');
break;
case 48: // 0
case 49: // 1
case 50: // 2
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57: // 9
Tablature.draw(e.key);
break;
case 46: // Numpad delete
if ( Tablature._getCurrentNote().get('text') == '|' ) {
Tablature.eraseColumn();
} else {
Tablature.draw('-');
}
break;
case 42: // Numpad *
Tablature.draw('X');
break;
default:
recognisedEvent = false;
;
}
break;
;
}
if ( recognisedEvent ) {
e.preventDefault();
}
}
}
window.addEvent('domready', Tablature.initialise);
window.addEvent('keydown', Command.readInput); // don't use keypress or event.keys will be wrong !
//]]>
</script>
<style type="text/css">
/*
Syntax { display/position
; size/margin
; border
; colour
; text
}
In vim, use 'AlignCtrl l:' and 'Align { ; }'
*/
/* tags */
html, body { margin: 0; padding: 0
; font-family: Verdana,sans-serif; font-size: 11pt
}
div { margin: 20px 0 }
p { margin: 0 }
h1 { margin: 5px 0 0 0
; font-family: Georgia,fantasy; font-style: italic; font-size: 130%
; text-align: center
}
h2 { margin: 0
; font-family: Georgia,fantasy; font-style: italic; font-size: 120%
; text-align: center
}
h3 { margin: 10px 0 0
; border: 1px dotted #E3E3E3; border-width: 0 0 1px
; font-family: Georgia,fantasy; font-style: italic; font-size: 110%
; text-align: right
}
ul { margin: 0
; list-style-type: none
}
li { margin: 0; padding: 0
; border: 1px solid #E3E3E3; border-width: 1px 0 0 0
}
a { color: inherit; background-color: inherit
; border: 1px dotted black; border-width: 0 0 1px 0
; text-decoration: none }
a:focus { border-width: 0 }
/* ids */
#tools { position: fixed; top: 0;
; height: 36px; width: 100%; margin: 0; padding: 0 5px
; border: 1px solid black; border-width: 0 0 1px 0
; background-color: #FFFFE3; color: inherit
; font-size: 70%
}
#copyright { position: fixed; bottom: 0;
; height: 26px; width: 100%; margin: 0; padding: 0 5px
; border: 1px solid black; border-width: 1px 0 0 0
; background-color: #FFFFE3; color: inherit
; font-size: 60%; text-align: center
}
#tab { margin: 46px 10px 36px 10px
; cursor: pointer
}
#help { position: fixed
; right: 0px; width: 200px; padding: 5px; margin: 0 10px
; border: 1px solid black;
; background-color: #FFFFE3; color: inherit
; font-size: 70%
}
#export-tab,
#import-tab { position: absolute
; left:10px; right: 230px; margin:0; padding: 5px; height: 300px
; border: 1px solid black; background-color: #E3E3E3; color: inherit
}
#close-export,
#close-import { float: right
; font-size: 70%
}
#export-content,
#import-content { height:80% }
/* classes */
.active { background-color: #E3E3FF; color: inherit }
.current { background-color: #8888FF; color: inherit }
.selected { background-color: #E3FFE3; color: inherit }
.generic-command { font-style: italic }
/* advanced */
#tools dl { margin: 0 }
#tools dt { display: inline
; margin-left: 10px
; font-weight: bold
}
#tools dd { display: inline
; padding: 0 10px 0 5px; margin: 0 0 0 0
; border: 1px solid #E3E3E3; border-width: 0 1px 0 0
}
#help dl { margin: 0 }
#help dt { float: left
; padding: 0 5px 0 0; margin: 0
; width: 70px
; border: 1px dotted #E3E3E3; border-width: 0 1px 0 0
; font-weight: bold; text-align: right; white-space: nowrap
}
#help dd { overflow:hidden
; padding: 0 0 0 5px; margin: 0
}
</style>
</head>
<body>
<div id="tools">
<h1>TablatureJS v0.1.0 (2010/12/20)</h1>
<dl>
<dt>Speed</dt>
<dd id="moving-speed"></dd>
<dt>Position</dt>
<dd id="position"></dd>
<dt>Actions</dt>
<dd><a href="#" id="export">Export</a></dd>
<dd><a href="#" id="import">Import</a></dd>
</dl>
</div>
<div id="export-tab">
<a href="#" id="close-export">[Close]</a>
<textarea id="export-content" cols="80"></textarea>
</div>
<div id="import-tab">
<a href="#" id="close-import">[Close]</a>
<textarea id="import-content" cols="80"></textarea>
<br />
<button id="save-import">Save</button>
</div>
<div id="help">
<h2>Quick Help</h2>
<h3>Motion</h3>
<dl>
<dt class="generic-command">arrow</dt>
<dd>move around</dd>
<dt class="generic-command">mouse click</dt>
<dd>move around</dd>
<dt>page up</dt>
<dd>move to previous</dd>
<dt>page down</dt>
<dd>move to next staff</dd>
<dt>space</dt>
<dd>move to next staff</dd>
<dt>start</dt>
<dd>move to first column</dd>
<dt>end</dt>
<dd>move to last column</dd>
<dt>+</dt>
<dd>increase speed</dd>
<dt>-</dt>
<dd>decrease speed</dd>
</dl>
<h3>Edition</h3>
<dl>
<dt class="generic-command">number</dt>
<dd>input note</dd>
<dt>h</dt>
<dd>input hammer</dd>
<dt>p</dt>
<dd>input pulloff</dd>
<dt>t</dt>
<dd>input tapping</dd>
<dt>b</dt>
<dd>input bend</dd>
<dt>/</dt>
<dd>input slide up</dd>
<dt>\</dt>
<dd>input slide down</dd>
<dt>*</dt>
<dd>input mute</dd>
<dt>enter</dt>
<dd>add bar</dd>
<dt>delete</dt>
<dd>delete note</dd>
<dt>c</dt>
<dd>copy bar</dd>
<dt>v</dt>
<dd>paste bar</dd>
</dl>
<h3>Special</h3>
<dl>
<dt>e</dt>
<dd>export</dd>
<dt>i</dt>
<dd>import</dd>
</dl>
</div>
<pre id="tab"></pre>
<p id="copyright">
<em>TablatureJS</em> is a program to edit Tablatures in a web browser.<br />
<em>TablatureJS</em> is available under GPLv3 license.
You can redistribute it or modify it freely.
See <a href="http://en.wikipedia.org/wiki/GNU_General_Public_License">
this page</a> for further details.
</p>
</body>
</html>