מדיה ויקי:Gadget-pgnviewer.js: הבדלים בין גרסאות בדף

DK
מ 85 גרסאות של הדף wikipedia:he:מדיה_ויקי:Gadget-pgnviewer.js יובאו
 
(15 גרסאות ביניים של 2 משתמשים אינן מוצגות)
שורה 23: שורה 23:
sides = ['n', 'e', 's', 'w'], // used for legends
sides = ['n', 'e', 's', 'w'], // used for legends
rowClassPrefix = 'pgn-prow-',
rowClassPrefix = 'pgn-prow-',
  fileClassPrefix = 'pgn-pfile-',
fileClassPrefix = 'pgn-pfile-',
allFilesAndColumnClasses = "01234567"
allFilesAndColumnClasses = "01234567"
.split("")
.split("")
.map(function(i) { return rowClassPrefix + i + ' ' + fileClassPrefix + i;})
.map( function( i ) { return rowClassPrefix + i + ' ' + fileClassPrefix + i; } )
.join(" "),
.join(" "),
  hiddenPiece = 'pgn-piece-hidden',
hiddenPiece = 'pgn-piece-hidden',
chessboardClass = 'pgn-board-img',
chessboardClass = 'pgn-board-img',
buttonClass = 'pgn-button',
resetGameButtonClass = 'pgn-button-tostart',
resetGameButtonClass = 'pgn-button-tostart',
ffButtonClass = 'pgn-button-toend',
ffButtonClass = 'pgn-button-toend',
שורה 43: שורה 42:
mw = window.mw,
mw = window.mw,
$ = window.$,
$ = window.$,
domParser = new DOMParser(),
mobile = mw.config.get('skin') === 'minerva';
mobile = mw.config.get('skin') === 'minerva';
שורה 54: שורה 54:
function indexOfMoveNotation(notation) {
function indexOfMoveNotation(notation) {
var match = notation.match( /(\d+)([ld])/ );
var match = notation.match( /(\d+)([ld])/ );
if (match) return parseInt( match[1] ) * 2 + ( match[2] === 'l' ? 1 : 2 );
if (match) return ( parseInt( match[1] ) - 1 ) * 2 + ( match[2] === 'l' ? 1 : 2 );
return 0;
return 0;
}
}
שורה 69: שורה 69:
return res.reverse().join('/'); // fen begins with row 8 file a - go figure...
return res.reverse().join('/'); // fen begins with row 8 file a - go figure...
}
}
 
function Button( className, action, stateful) {
// Classes
function Button( className, action, stateful ) {
var button = this;
var button = this;
$.extend( button, {
$.extend( button, {
שורה 84: שורה 85:
if ( ( !stateful || state != oldState ) && typeof( action ) == 'function' )
if ( ( !stateful || state != oldState ) && typeof( action ) == 'function' )
action( state );
action( state );
},
setVisible: function( visible ) {
this.elem.toggle( !! visible );
},
},
elem: $( '<div>' )
elem: $( '<div>' )
שורה 104: שורה 108:
showDetails:false,
showDetails:false,
timer: null,
timer: null,
autoPlayDelay: 750,
// actions
faster: function() {  
faster: function() {  
gameSet.autoPlayDelay -= 500;  
gameSet.autoPlayDelay -= 500;  
שורה 113: שורה 119:
gameSet.reportDelay();  
gameSet.reportDelay();  
},
},
flipButton: new Button( flipBoardButtonClass, function( state ) {
gameSet.doFlip( state );
}, true ),
slowerButton:  new Button( slowerButtonClass, function() { gameSet.slower(); } ),
autoPlayButton: new Button( playButtonClass, function( state ) { gameSet.toggleAutoPlay( state ); }, true ),
fasterButton:  new Button( fasterButtonClass, function() { gameSet.faster(); } ),
commentsToggleButton: new Button( ccButtonClass, function( state ) { gameSet.hideComments( state ) }, true ),
autoPlayDelay: 750,
reportDelay: function() {
reportDelay: function() {
gameSet.toggleAutoPlay(); // no param means keep state, but use new delay
gameSet.toggleAutoPlay(); // no param means keep state, but use new delay
שורה 130: שורה 128:
},
},
// 6 is half letter size (assuming font-size 0.875em)
// 6 is half letter size (assuming font-size 0.875em)
top: function(row, l) { return (((this.flipButton.state ? row : (7 - row)) + (l ? 0.3 : 0)) * this.blockSize + (l? boardPadding-6: boardPadding)) + 'px'; },
top: function(row, l) { return (((this.isFlipped ? row : (7 - row)) + (l ? 0.3 : 0)) * this.blockSize + (l? boardPadding-6: boardPadding)) + 'px'; },
left: function(file, l) { return (((this.flipButton.state ? 7 - file : file) + (l ? 0.5 : 0)) * this.blockSize + (l? boardPadding-6: boardPadding)) + 'px'; },
left: function(file, l) { return (((this.isFlipped ? 7 - file : file) + (l ? 0.5 : 0)) * this.blockSize + (l? boardPadding-6: boardPadding)) + 'px'; },
legendLocation: function(side, num) {
legendLocation: function(side, num) {
var n = 0.5 + num;
switch (side) {  
switch (side) {  
case 'n':
case 'n': return {top: 0, left: this.left(num, true)};
return {top: 0, left: this.left(num, true)};
case 'e': return {top: this.top(num, true), left: this.blockSize * 8 + boardPadding + 5};
case 'e':
case 's': return {top: this.blockSize * 8 + 20, left: this.left(num, true)};
return {top: this.top(num, true), left: this.blockSize * 8 + boardPadding + 5};
case 'w': return {top: this.top(num, true), left: 5};
case 's':
return {top: this.blockSize * 8 + 20, left: this.left(num, true)};
case 'w':
return {top: this.top(num, true), left: 5};
}
}
},
},
שורה 155: שורה 148:
game.analyzePgn();
game.analyzePgn();
this.currentGame = game;
this.currentGame = game;
this.ccButton.setVisible( game.hasComments() );
game.show();
game.show();
}
}
שורה 162: שורה 156:
this.fenDiv.text( boardToFen(board) );
this.fenDiv.text( boardToFen(board) );
},
},
drawIfNeedRefresh: function(again) {
drawIfNeedRefresh: function() {
if (this.currentGame)
if (this.currentGame)
this.currentGame.drawBoard();
this.currentGame.drawBoard();
שורה 186: שורה 180:
this.wrapperDiv.toggleClass( 'pgn-comments-hidden', state );
this.wrapperDiv.toggleClass( 'pgn-comments-hidden', state );
},
},
isFlipped: false,
doFlip: function( state ) {
doFlip: function( state ) {
this.isFlipped = state;
this.changeAppearance();
this.changeAppearance();
},
},
playing: false,
toggleAutoPlay: function( state ) {
toggleAutoPlay: function( state ) {
clearInterval(this.timer);
clearInterval(this.timer);
if (state == undefined) state = gameSet.autoPlayButton.state;
if (state == undefined) state = this.playing;
this.playing = state;
if ( state ) {
if ( state ) {
this.currentGame.wrapAround();
this.currentGame.wrapAround();
שורה 203: שורה 201:
}
}
   
   
function transitionstart() {
$(this).addClass('moving');
}
function transitionend() {
$(this).removeClass('moving');
}
function ChessPiece(type, color, game) {
function ChessPiece(type, color, game) {
this.game = game;
this.game = game;
שורה 217: שורה 207:
this.avatar = $('<div>')
this.avatar = $('<div>')
.addClass('pgn-chessPiece pgn-ptype-color-' + type + color)
.addClass('pgn-chessPiece pgn-ptype-color-' + type + color)
.on('transitionstart', transitionstart)
.on('transitionstart', function(){ $(this).addClass('moving'); } ) //supposedly elevates z-index
.on('transitionend', transitionend);
.on('transitionend', function(){ $(this).removeClass('moving'); } );
var piece = this;
$.extend( piece, {
appear: function(file, row) {
if (game.gs.isFlipped) {
file = 7 - file;
row = 7 - row;
}
this.avatar
.removeClass(hiddenPiece)
.removeClass(allFilesAndColumnClasses)  // remove them all
.addClass(rowClassPrefix + row) //
.addClass(fileClassPrefix + file);
},
disappear: function() { return this.avatar.addClass( hiddenPiece ); },
setSquare: function( file, row ) {
this.file = file;
this.row = row;
this.onBoard = true;
},
capture: function( file, row ) {
if (this.type == 'p' && !this.game.pieceAt(file, row))  // en passant
this.game.clearPieceAt(file, this.row);
else
this.game.clearPieceAt(file, row);
this.move(file, row);
},
move: function(file, row) {
// with chess960 castling, we sometimes have to test.
if ( this.game.pieceAt( this.file, this.row ) == this )
this.game.clearSquare(this.file, this.row);
this.game.pieceAt(file, row, this); // place it on the board)
},
pawnDirection: function() { return this.color == WHITE ? 1 : -1; },
toString: function() { return this.type + this.color; },
fen: function() { return this.color == WHITE ? this.type.toUpperCase() : this.type; },
pawnStart: function() { return this.color == WHITE ? 1 : 6; },
remove: function() { this.onBoard = false; },
canMoveTo: function(file, row, capture) {
if (!this.onBoard)
return false;
var rd = Math.abs(this.row - row), fd = Math.abs(this.file - file);
switch(this.type) {
case 'n':
return rd * fd == 2; // how nice that 2 is prime: its only factors are 2 and 1....
case 'p':
var dir = this.pawnDirection();
return (
((this.row == this.pawnStart() && row ==  this.row + dir * 2 && !fd && this.game.roadIsClear(this.file, file, this.row, row) && !capture)
|| (this.row + dir == row && fd == !!capture))); // advance 1, and either stay in file and no capture, or move exactly one
case 'k':
return (rd | fd) == 1; // we'll accept 1 and 1 or 1 and 0.
case 'q':
return (rd - fd) * rd * fd == 0 && this.game.roadIsClear(this.file, file, this.row, row); // same row, same file or same diagonal.
case 'r':
return rd * fd == 0 && this.game.roadIsClear(this.file, file, this.row, row);
case 'b':
return rd == fd && this.game.roadIsClear(this.file, file, this.row, row);
}
}, // function canMoveTo
matches: function(oldFile, oldRow, isCapture, file, row) {
if (typeof oldFile == 'number' && oldFile != this.file)
return false;
if (typeof oldRow  == 'number' && oldRow != this.row)
return false;
return this.canMoveTo(file, row, isCapture);
}
} ); // extend
}
}
   
   
ChessPiece.prototype.appear = function(file, row) {
if (this.game.gs.flipButton.state) {
file = 7 - file;
row = 7 - row;
}
this.avatar
.removeClass(hiddenPiece)
.removeClass(allFilesAndColumnClasses)  // remove them all
.addClass(rowClassPrefix + row) //
.addClass(fileClassPrefix + file);
};
ChessPiece.prototype.disappear = function() {
return this.avatar
.addClass(hiddenPiece);
};
ChessPiece.prototype.setSquare = function(file, row) {
this.file = file;
this.row = row;
this.onBoard = true;
};
ChessPiece.prototype.capture = function(file, row) {
if (this.type == 'p' && !this.game.pieceAt(file, row))  // en passant
this.game.clearPieceAt(file, this.row);
else
this.game.clearPieceAt(file, row);
this.move(file, row);
};
ChessPiece.prototype.move = function(file, row) {
        if ( this.game.pieceAt( this.file, this.row ) == this ) // with chess960 castling, we sometimes have to test.
  this.game.clearSquare(this.file, this.row);
this.game.pieceAt(file, row, this); // place it on the board)
};
ChessPiece.prototype.pawnDirection = function() { return this.color == WHITE ? 1 : -1; };
ChessPiece.prototype.toString = function(fen) { return this.type + this.color; };
ChessPiece.prototype.fen = function() { return this.color == WHITE ? this.type.toUpperCase() : this.type; };
ChessPiece.prototype.pawnStart = function() { return this.color == WHITE ? 1 : 6; };
ChessPiece.prototype.remove = function() { this.onBoard = false; };
ChessPiece.prototype.canMoveTo = function(file, row, capture) {
if (!this.onBoard)
return false;
var rd = Math.abs(this.row - row), fd = Math.abs(this.file - file);
switch(this.type) {
case 'n':
return rd * fd == 2; // how nice that 2 is prime: its only factors are 2 and 1....
case 'p':
var dir = this.pawnDirection();
return (
((this.row == this.pawnStart() && row ==  this.row + dir * 2 && !fd && this.game.roadIsClear(this.file, file, this.row, row) && !capture)
|| (this.row + dir == row && fd == !!capture))); // advance 1, and either stay in file and no capture, or move exactly one
case 'k':
return (rd | fd) == 1; // we'll accept 1 and 1 or 1 and 0.
case 'q':
return (rd - fd) * rd * fd == 0 && this.game.roadIsClear(this.file, file, this.row, row); // same row, same file or same diagonal.
case 'r':
return rd * fd == 0 && this.game.roadIsClear(this.file, file, this.row, row);
case 'b':
return rd == fd && this.game.roadIsClear(this.file, file, this.row, row);
}
};
ChessPiece.prototype.matches = function(oldFile, oldRow, isCapture, file, row) {
if (typeof oldFile == 'number' && oldFile != this.file)
return false;
if (typeof oldRow  == 'number' && oldRow != this.row)
return false;
return this.canMoveTo(file, row, isCapture);
};
   
   
function Game(gameSet) {
function Game(gameSet) {
שורה 342: שורה 322:
if (trow) {
if (trow) {
try {
try {
notation = notation.replace(/[12345678]/g, function(c) { return trowrow[c] || c; } );
notation = notation.replace(/[12345678]/g, function(c) { return trow[c] || c; } );
} catch (e) {
} catch (e) {
mw.log('bad config.translate.row');
mw.log('bad config.translate.row');
שורה 355: שורה 335:
var desc = $.extend({}, this.descriptions),
var desc = $.extend({}, this.descriptions),
rtl = desc['Direction'] == 'rtl',
rtl = desc['Direction'] == 'rtl',
num = '',
gs = this.gs;
gs = this.gs;
   
   
שורה 366: שורה 345:
.empty()
.empty()
.css( { direction: rtl ? 'rtl' : 'ltr', textAlign: rtl ? 'right' : 'left' } );
.css( { direction: rtl ? 'rtl' : 'ltr', textAlign: rtl ? 'right' : 'left' } );
$.each(desc, function(key, val) { gs.descriptionsDiv.append(key + ': ' + val + '<br />'); });
$.each(desc, function(key, val) {  
var line = mw.html.escape(key + ': ' + val)  + '<br />';
gs.descriptionsDiv.append(line);  
} );
   
   
// setup pgn section
// setup pgn section
שורה 438: שורה 420:
if (0 <= m && m < this.boards.length) {
if (0 <= m && m < this.boards.length) {
this.drawBoard(m);
this.drawBoard(m);
} else this.gs.setAutoPlayButton(false);
} else this.gs.autoPlayButton.setState(false);
}
}
   
   
שורה 563: שורה 545:
}
}
Game.prototype.addComment = function(str) {
Game.prototype.addComment = function(str) {
if ( ! str ) return;
if ( ! str ) return;
this.notations.push( $( '<p>' )
this.notations.push( $( '<p>' )
שורה 570: שורה 552:
);
);
}
}
 
Game.prototype.addDescription = function(description) {
Game.prototype.addDescription = function(description) {
description = $.trim(description);
description = $.trim(description);
שורה 578: שורה 560:
}
}
   
   
Game.prototype.description = function(pgn) {
Game.prototype.description = function() {
var d = this.descriptions,
var d = this.descriptions,
round = d['Round'] ? ' (' + d['Round'] + ')' : '',
event = d['Event'] || d['אירוע'],
s = d['Name']  
round =  d['Round'] ||  d['סיבוב'],
|| d['שם']  
white = d['White'] || d['לבן'],
|| ( (d['Event'] || d['אירוע'] || '') + ': ' + (d['White'] || d['לבן'] || '') + ' - ' + (d['Black'] || d['שחור'] || '') + round);
black = d['Black'] || d['שחור'],
return s;
name = d['Name'] || d['שם'];
return name
|| ( event ? event + ': ' : '')
+ (white ? white : '')
+ (white || black ? ' – ' : '')
+ (black ? black : '')
+ (round ? ' (' + round + ')' : '');
}
}
 
Game.prototype.preAnalyzePgn = function(pgn) {
Game.prototype.preAnalyzePgn = function(pgn) {
function tryMatch(regex) {
function tryMatch(regex) {
שורה 621: שורה 609:
if (rmatch) {
if (rmatch) {
removeHead(rmatch[0]);
removeHead(rmatch[0]);
moveNum = rmatch[1] || moveNum;;
moveNum = rmatch[1] || moveNum;
}
}
return rmatch && rmatch[0];
return rmatch && rmatch[0];
שורה 690: שורה 678:
}
}
}
}
}  
}
function selectGame() {
var gameSet = $(this).data('gameSet');
Game.prototype.hasComments = function() {
gameSet.selectGame(this.value);
var hasComment = function( n ){ return n.hasClass( 'pgn-comment' ); };
return !! this.notations.filter( hasComment ).length;
}
}


שורה 704: שורה 693:
fenId = 'pgn-fen-' + id,
fenId = 'pgn-fen-' + id,
controlsDiv,
controlsDiv,
gotoend = new Button( ffButtonClass,  
createBotton = function( className, param, todraw ) {
function() {  
return new Button( className,  
gameSet.stopAutoPlay();
function() {
gameSet.currentGame.drawBoard( -1 );  
gameSet.stopAutoPlay();
} ),
if ( todraw ) gameSet.currentGame.drawBoard( param )
forward = new Button( advanceButtonClass,  
else gameSet.currentGame.advance( param );
function() {
} )
gameSet.stopAutoPlay();
},
gameSet.currentGame.advance( 1 );  
gotoend = createBotton( ffButtonClass, -1, true ),
forward = createBotton( advanceButtonClass,  1 ),
} ),
backstep = createBotton( retreatButtonClass, -1 ),
backstep = new Button( retreatButtonClass,  
gotostart = createBotton( resetGameButtonClass, 0, true ),
function() {  
flip = new Button( flipBoardButtonClass, function( state ){ gameSet.doFlip( state ); }, true ),
gameSet.stopAutoPlay();
slower = new Button( slowerButtonClass, function(){ gameSet.slower(); } ),
gameSet.currentGame.advance( -1 );  
faster = new Button( fasterButtonClass, function(){ gameSet.faster(); } ),
} ),
autoplay = new Button( playButtonClass, function( state ){ gameSet.toggleAutoPlay( state ); }, true ),
gotostart = new Button( resetGameButtonClass,  
commentsToggle = new Button( ccButtonClass, function( state ){ gameSet.hideComments( state ); }, true ),
function() {  
gameSet.stopAutoPlay();
gameSet.currentGame.drawBoard( 0 );
} ),
collapsibleDiv = $( '<div>' ), // residue. to be renamed or remove
tabnames = $.extend( {
tabnames = $.extend( {
notation: 'Game Notation',
notation: 'Game Notation',
שורה 731: שורה 715:
fen: 'FEN' },  
fen: 'FEN' },  
config.tab_names );
config.tab_names );
 
gameSet.autoPlayButton = autoplay;
gameSet.ccButton = commentsToggle
gameSet.descriptionsDiv = $('<div>', {'class': 'pgn-descriptions', id: infoId })
gameSet.descriptionsDiv = $('<div>', {'class': 'pgn-descriptions', id: infoId })
gameSet.fixedDelay = 'delay' in config;
gameSet.fixedDelay = 'delay' in config;
שורה 757: שורה 742:
.tabs();
.tabs();
}
}
var buttons = gameSet.fixedDelay
? [gotostart, backstep, autoplay, forward, gotoend, flip, commentsToggle]
: [gotostart, backstep, slower, autoplay, faster, forward, gotoend, flip, commentsToggle]
controlsDiv = $('<div>', {'class': 'pgn-controls'})
controlsDiv = $('<div>', {'class': 'pgn-controls'})
.css({textAlign: 'center'})
.css( { textAlign: 'center' } ) // todo: move to css
.append(gotostart.elem)
.append( buttons.map( function(x){ return x.elem; } ) );
.append(backstep.elem);
if ( ! gameSet.fixedDelay ) controlsDiv.append( gameSet.slowerButton.elem );
controlsDiv.append(gameSet.autoPlayButton.elem);
if ( ! gameSet.fixedDelay ) controlsDiv.append( gameSet.fasterButton.elem );
controlsDiv
.append(forward.elem)
.append(gotoend.elem)
.append(gameSet.flipButton.elem)
.append(gameSet.commentsToggleButton.elem)
;


gameSet.boardDiv = $('<div>')
gameSet.boardDiv = $('<div>')
שורה 805: שורה 784:
container
container
.append( selector || '' )
.append( selector || '' )
.append( collapsibleDiv
.append($('<div>')
.append(gameSet.boardDiv)
.append(gameSet.boardDiv)
.append( gameSet.tabberDiv )
.append( gameSet.tabberDiv )
.append(controlsDiv)
.append(controlsDiv)
);
);
}
}
   
   
function doIt() {
function doIt() {
$(wrapperSelector, $content).each(function( ind ) {
$(wrapperSelector).each(function( ind ) {
var
var
wrapperDiv = $(this),
wrapperDiv = $(this),
initial = wrapperDiv.text(),
initial = wrapperDiv.text(),
pgnSource = $('div.pgn-sourcegame', wrapperDiv),
pgnSource = $('div.pgn-sourcegame', wrapperDiv),
boardDiv,
selector,
selector,
gameSet = new Gameset( wrapperDiv );
gameSet = new Gameset( wrapperDiv );
try {
try {
if (pgnSource.length > 1)
if (pgnSource.length > 1)
selector = $('<select>', { 'class': 'pgn-selector' } ).data({gameSet: gameSet}).change(selectGame);
selector = $('<select>', { 'class': 'pgn-selector' } )
.change( function() { gameSet.selectGame(this.value); } );


buildBoardDiv(wrapperDiv, selector, gameSet, ind);
buildBoardDiv(wrapperDiv, selector, gameSet, ind);
שורה 859: שורה 838:
doIt();
doIt();
else
else
mw.loader.using( 'jquery.ui.tabs' ).done( doIt );
mw.loader.using( 'jquery.ui' ).done( doIt );
}
}
});
});