-
Notifications
You must be signed in to change notification settings - Fork 0
/
jquery.jqpuzzle.min.js
executable file
·8 lines (8 loc) · 15.4 KB
/
jquery.jqpuzzle.min.js
1
2
3
4
5
6
7
8
/*
* jqPuzzle - Sliding Puzzles with jQuery
* Version 1.02
*
* Copyright (c) 2008 Ralf Stoltze, http://www.2meter3.de/jqPuzzle/
* Dual-licensed under the MIT and GPL licenses.
*/
(function($){$.fn.jqPuzzle=function(settings,texts){var defaults={rows:4,cols:4,hole:16,shuffle:false,numbers:true,language:'en',control:{shufflePieces:true,confirmShuffle:true,toggleOriginal:true,toggleNumbers:true,counter:true,timer:true,pauseTimer:false},success:{fadeOriginal:true,callback:undefined,callbackTimeout:300},animation:{shuffleRounds:3,shuffleSpeed:800,slidingSpeed:200,fadeOriginalSpeed:600},style:{gridSize:2,overlap:true,backgroundOpacity:0.1}};var i18n={en:{shuffleLabel:'Shuffle',toggleOriginalLabel:'Original',toggleNumbersLabel:'Numbers',confirmShuffleMessage:'Do you really want to shuffle?',movesLabel:'moves',secondsLabel:'seconds'},fr:{shuffleLabel:'Mélanger',toggleOriginalLabel:'Original',toggleNumbersLabel:'Nombres',confirmShuffleMessage:'Veux-tu vraiment mélanger?',movesLabel:'mouvements',secondsLabel:'secondes'},de:{shuffleLabel:'Mischen',toggleOriginalLabel:'Original',toggleNumbersLabel:'Nummern',confirmShuffleMessage:'Willst du wirklich mischen?',movesLabel:'Züge',secondsLabel:'Sekunden'},pt:{shuffleLabel:'Embaralhar',toggleOriginalLabel:'Original',toggleNumbersLabel:'Numeros',confirmShuffleMessage:'Tem certeza que deseja reembralhar?',movesLabel:'movimentos',secondsLabel:'segundos'}};if(settings&&!settings.hole&&(settings.rows||settings.cols)){settings.hole=(settings.rows||defaults.rows)*(settings.cols||defaults.cols)}settings=$.extend(true,{},defaults,settings);texts=$.extend((i18n[settings.language]||i18n[defaults.language]),texts);var rows=settings.rows,cols=settings.cols,hole=settings.hole;var control=settings.control,success=settings.success,animation=settings.animation,style=settings.style;if(rows<3||rows>9)rows=defaults.rows;if(cols<3||cols>9)cols=defaults.rows;if((hole>(rows*cols))||(hole<1))hole=rows*cols;hole--;if(animation.slidingSpeed<1)animation.slidingSpeed=1;if(animation.shuffleSpeed<1)animation.shuffleSpeed=1;if(animation.fadeOriginalSpeed<1)animation.fadeOriginalSpeed=1;if(animation.shuffleRounds<1)animation.shuffleRounds=1;var checkSolution=function($pieces){for(var i=0;i<$pieces.length;i++){var pieceIndex=(i<hole)?i:i+1;if($pieces.eq(i).attr('current')!=pieceIndex)return false}return true};var checkOrder=function(numbersArray){var product=1;for(var i=1;i<=(rows*cols-1);i++){for(var j=(i+1);j<=(rows*cols);j++){product*=((numbersArray[i-1]-numbersArray[j-1])/(i-j))}}return Math.round(product)==1};var getLinearPosition=function(row,col){return parseInt(row)*cols+parseInt(col)};var getMatrixPosition=function(index){return{row:(Math.floor(index/cols)),col:(index%cols)}};var getBorderWidth=function($element){var property=$element.css('border-left-width');if($element.css('border-left-style')!='none'){switch(property){case'thin':return 2;case'medium':return 4;case'thick':return 6;default:return parseInt(property)||0}}return 0};var Timer=function(interval,callback){var startTime;var startPauseTime;var totalPause=0;var timeout;var run=function(){update(new Date().getTime());timeout=setTimeout(run,interval)};var update=function(now){callback(now-totalPause-startTime)};this.start=function(){if(startTime)return false;startTime=new Date().getTime();run()};this.stop=function(){if(!startTime)return false;clearTimeout(timeout);var now=new Date().getTime();if(startPauseTime)totalPause+=now-startPauseTime;update(now);startTime=startPauseTime=undefined;totalPause=0};this.pause=function(){if(!startTime||startPauseTime)return false;clearTimeout(timeout);startPauseTime=new Date().getTime()};this.resume=function(){if(!startPauseTime)return false;totalPause+=new Date().getTime()-startPauseTime;startPauseTime=undefined;run()}};return this.filter('img').each(function(){var $srcImg=$(this);var lock=false;var moves=0;var seconds=0;var solved;var shuffled=settings.shuffle;var timer;var currHole=hole;var $dummyPiece=$('<div/>').addClass('jqp-piece');var $dummyWrapper=$('<div/>').addClass('jqp-wrapper').append($dummyPiece);var $dummyGui=$('<div/>').attr('class',$srcImg.attr('class')||'').addClass('jqPuzzle').append($dummyWrapper);$srcImg.replaceWith($dummyGui);$dummyGui.attr('id',$srcImg.attr('id')||'');var computedStyles={gui:{border:getBorderWidth($dummyGui),padding:{left:parseInt($dummyGui.css('padding-left'))||0,right:parseInt($dummyGui.css('padding-right'))||0,top:parseInt($dummyGui.css('padding-top'))||0,bottom:parseInt($dummyGui.css('padding-bottom'))||0}},wrapper:{border:getBorderWidth($dummyWrapper),padding:parseInt($dummyWrapper.css('padding-left'))||0},piece:{border:getBorderWidth($dummyPiece)}};$dummyGui.removeAttr('id');$dummyGui.replaceWith($srcImg);$srcImg.one('load',function(){var overlap=(style.gridSize===0&&style.overlap);var coveredWidth=cols*(2*computedStyles.piece.border)+(cols-1)*style.gridSize;var coveredHeight=rows*(2*computedStyles.piece.border)+(rows-1)*style.gridSize;if(overlap){coveredWidth-=(cols-1)*computedStyles.piece.border;coveredHeight-=(rows-1)*computedStyles.piece.border}$srcImg.css({width:'auto',height:'auto',visibility:'visible'});var width=Math.floor(($srcImg.width()-coveredWidth)/cols);var height=Math.floor(($srcImg.height()-coveredHeight)/rows);if(width<30||height<30)return false;var fullWidth=cols*width+coveredWidth;var fullHeight=rows*height+coveredHeight;var imgSrc=$srcImg.attr('src');var totalPieceWidth=width+2*computedStyles.piece.border+style.gridSize;var totalPieceHeight=height+2*computedStyles.piece.border+style.gridSize;var boxModelHack={piece:$.boxModel?0:2*computedStyles.piece.border,wrapper:$.boxModel?0:2*(computedStyles.wrapper.border+computedStyles.wrapper.padding),gui:{width:$.boxModel?0:2*computedStyles.gui.border+computedStyles.gui.padding.left+computedStyles.gui.padding.right,height:$.boxModel?0:2*computedStyles.gui.border+computedStyles.gui.padding.top+computedStyles.gui.padding.bottom}};var getOffset=function(row,col){var offset={left:computedStyles.wrapper.padding+col*totalPieceWidth,top:computedStyles.wrapper.padding+row*totalPieceHeight};if(overlap){offset.left-=col*computedStyles.piece.border;offset.top-=row*computedStyles.piece.border}return offset};var shuffle=function(rounds,speed){if(speed){if($shuffleButton.is('.jqp-disabled'))return false;if(lock)return false;if(control.confirmShuffle&&(moves>0)&&!window.confirm(texts.confirmShuffleMessage))return false;lock=true;if(solved){$gui.removeClass('jqp-solved');$background.fadeTo(animation.fadeOriginalSpeed,style.backgroundOpacity,function(){$background.remove().prependTo($wrapper);$buttons.removeClass('jqp-disabled')})}}if(timer)timer.stop();solved=false;shuffled=true;moves=0;seconds=0;if($display)$display.removeClass('jqp-disabled');if($counter)$counter.val(moves);if($timer)$timer.val(seconds);var shuffles=[];var i=0;while(i<rounds){var choices=[];for(var j=0;j<rows*cols;j++){choices[j]=j}choices.splice(hole,1);shuffles[i]=[];for(var j=0;j<rows*cols;j++){if(j==hole){shuffles[i][j]=hole;continue}var randomIndex=Math.floor(Math.random()*choices.length);shuffles[i][j]=choices[randomIndex];choices.splice(randomIndex,1)}if(((i+1)<rounds)||checkOrder(shuffles[i]))i++}var animCounter=0;for(var i=0;i<rounds;i++){var lastRound=((i+1)==rounds);for(var j=0;j<shuffles[i].length;j++){if(j==hole){if(lastRound)currHole=hole;continue}var pieceIndex=shuffles[i][j];if(pieceIndex>hole)pieceIndex-=1;var $piece=$pieces.eq(pieceIndex);var target=getMatrixPosition(j);var offset=getOffset(target.row,target.col);if(lastRound)$piece.attr('current',j.toString());if(speed===undefined){$piece.css({left:offset.left,top:offset.top})}else{$piece.animate({left:offset.left,top:offset.top},speed,null,function(){animCounter++;if(animCounter==animation.shuffleRounds*(rows*cols-1)){lock=false;animCounter=0}})}}}};var $wrapper=$('<div/>').addClass('jqp-wrapper').css({width:fullWidth+boxModelHack.wrapper,height:fullHeight+boxModelHack.wrapper,borderWidth:computedStyles.wrapper.border,padding:computedStyles.wrapper.padding,margin:0,position:'relative',overflow:'hidden',display:'block',visibility:'inherit'});var $protoPiece=$('<div/>').addClass('jqp-piece').css({width:width+boxModelHack.piece,height:height+boxModelHack.piece,backgroundImage:'url('+imgSrc+')',borderWidth:computedStyles.piece.border,margin:0,padding:0,position:'absolute',overflow:'hidden',display:'block',visibility:'inherit',cursor:'default'}).append($('<span/>'));var $pieces=$([]);for(var i=0;i<rows;i++){for(var j=0;j<cols;j++){var index=getLinearPosition(i,j);if(index==hole)continue;var offset=getOffset(i,j);var bgLeft=-1*(j*totalPieceWidth+computedStyles.piece.border);var bgTop=-1*(i*totalPieceHeight+computedStyles.piece.border);if(overlap){bgLeft+=j*computedStyles.piece.border;bgTop+=i*computedStyles.piece.border}$pieces=$pieces.add($protoPiece.clone().css({left:offset.left,top:offset.top,backgroundPosition:(bgLeft+'px '+bgTop+'px')}).attr('current',String(index)).appendTo($wrapper).children().text(index+1).end())}}if(settings.shuffle)shuffle(1);var $background=$('<div/>').css({width:fullWidth,height:fullHeight,left:computedStyles.wrapper.padding,top:computedStyles.wrapper.padding,backgroundImage:'url('+imgSrc+')',borderWidth:0,margin:0,padding:0,position:'absolute',opacity:style.backgroundOpacity}).prependTo($wrapper);var $controls=$('<div/>').addClass('jqp-controls').css({visibility:'inherit',display:'block',position:'static'});var $shuffleButton,$originalButton,$numbersButton;var $protoButton=$('<a/>').css('cursor','default');if(control.shufflePieces){$shuffleButton=$protoButton.clone().text(texts.shuffleLabel).appendTo($controls)}if(control.toggleOriginal){$originalButton=$protoButton.clone().text(texts.toggleOriginalLabel).appendTo($controls)}if(control.toggleNumbers){$numbersButton=$protoButton.clone().text(texts.toggleNumbersLabel).appendTo($controls);if(settings.numbers)$numbersButton.addClass('jqp-toggle')}var $buttons=$controls.children();var $display,$counter,$timer;if(control.counter||control.timer){$display=$('<span/>').css('cursor','default').appendTo($controls);var $protoField=$('<input/>').val(0).css({width:'5ex',cursor:'default'}).attr('readonly','readonly');if(control.counter)$counter=$protoField.clone().appendTo($display).after(texts.movesLabel+' ');if(control.timer)$timer=$protoField.clone().appendTo($display).after(texts.secondsLabel);if(!settings.shuffle)$display.addClass('jqp-disabled')}var $credits=$('<a/>').text('jqPuzzle').attr('href','http://www.2meter3.de/jqPuzzle/').css({'float':'right',fontFamily:'Verdana, Arial, Helvetica, sans-serif',fontSize:'9px',lineHeight:'12px',textDecoration:'none',color:'#FFFFFF',backgroundColor:'#777777',backgroundImage:'none',borderBottom:'1px dotted #FFFFFF',padding:'1px 3px 2px',marginRight:computedStyles.wrapper.border,position:'static',display:'inline',visibility:'inherit'});var $panel=$('<div/>').css({width:fullWidth+2*(computedStyles.wrapper.padding+computedStyles.wrapper.border),position:'absolute',display:'block',visibility:'inherit',margin:'0px',padding:'0px',backgroundColor:'transparent'}).append($credits).append($controls);var $gui=$('<div/>').attr('class',$srcImg.attr('class')||'').addClass('jqPuzzle').css({width:fullWidth+2*(computedStyles.wrapper.padding+computedStyles.wrapper.border)+boxModelHack.gui.width,height:fullHeight+2*(computedStyles.wrapper.padding+computedStyles.wrapper.border)+boxModelHack.gui.height,textAlign:'left',overflow:'hidden',display:'block'}).append($wrapper).append($panel);$srcImg.replaceWith($gui);var id=$srcImg.attr('id');if(id)$gui.attr('id',id);if(!settings.numbers)$pieces.children().hide();if($display)$display.children('input').val(0);var guiHeight=$gui.height();var panelHeight=$panel.height();$gui.height($gui.height()+$panel.height());if($.browser.msie)$gui[0].onselectstart=function(){return false};else $gui.mousedown(function(){return false});$buttons.mousedown(function(){if(!$(this).is('.jqp-disabled'))$(this).addClass('jqp-down')});$buttons.mouseout(function(){$(this).removeClass('jqp-down')});$buttons.mouseup(function(){$(this).removeClass('jqp-down')});$pieces.click(function(){if(lock)return false;if(solved)return false;lock=true;var $piece=$(this);var current=$piece.attr('current');var source=getMatrixPosition(current);var dest=getMatrixPosition(currHole);if(Math.abs(source.row-dest.row)+Math.abs(source.col-dest.col)!=1){lock=false;return false}var offset=getOffset(dest.row,dest.col);$piece.attr('current',String(currHole));currHole=current;if(shuffled)moves++;if($counter)$counter.val(moves);if(moves==1){if(!timer)timer=new Timer(333,function(ms){seconds=Math.floor(ms/1000);if($timer)$timer.val(seconds)});timer.start()}$piece.animate({left:offset.left,top:offset.top},animation.slidingSpeed,null,function(){if(shuffled){solved=checkSolution($pieces);if(solved){if(timer)timer.stop();shuffled=false;$gui.addClass('jqp-solved');window.setTimeout(finishGame,100)}else lock=false}else lock=false})});if(control.shufflePieces)$shuffleButton.click(function(){shuffle(animation.shuffleRounds,animation.shuffleSpeed)});if(control.toggleOriginal)$originalButton.click(function(){if($originalButton.is('.jqp-disabled'))return false;if(lock)return false;lock=true;if($originalButton.is('.jqp-toggle')){if(control.shufflePieces)$shuffleButton.removeClass('jqp-disabled');if(control.toggleNumbers)$numbersButton.removeClass('jqp-disabled');$originalButton.removeClass('jqp-toggle');$background.fadeTo(animation.fadeOriginalSpeed,style.backgroundOpacity,function(){$(this).prependTo($wrapper);if(control.pauseTimer&&timer)timer.resume();lock=false})}else{if(control.shufflePieces)$shuffleButton.addClass('jqp-disabled');if(control.toggleNumbers)$numbersButton.addClass('jqp-disabled');$originalButton.addClass('jqp-toggle');if(control.pauseTimer&&timer)timer.pause();$background.appendTo($wrapper).fadeTo(animation.fadeOriginalSpeed,1,function(){lock=false})}return false});if(control.toggleNumbers)$numbersButton.click(function(){if($numbersButton.is('.jqp-disabled'))return false;if($numbersButton.is('.jqp-toggle')){$numbersButton.removeClass('jqp-toggle');$pieces.children().hide()}else{$numbersButton.addClass('jqp-toggle');$pieces.children().show()}});var finishGame=function(){if(success.fadeOriginal){if(control.toggleOriginal)$originalButton.addClass('jqp-disabled');if(control.toggleNumbers)$numbersButton.addClass('jqp-disabled');$background.appendTo($wrapper).fadeTo(animation.fadeOriginalSpeed,1.0,function(){lock=false;solutionCallback()})}else{lock=false;solutionCallback()}};var solutionCallback=function(){if($.isFunction(success.callback)){setTimeout(function(){success.callback({moves:moves,seconds:seconds})},success.callbackTimeout)}}});var interval=setInterval(function(){if($srcImg[0].complete){clearInterval(interval);$srcImg.trigger('load')}},333)}).end()};$(document).ready(function(){$('img.jqPuzzle').each(function(){var microFormat=/\bjqp(-[a-z]{2})?-r(\d)-c(\d)(-h(\d+))?(-s(\d+))?(-[A-Z]+)?\b/;var match=microFormat.exec(this.className);var settings;if(match){settings={rows:parseInt(match[2]),cols:parseInt(match[3]),hole:parseInt(match[5])||null,shuffle:match[8]&&match[8].indexOf('S')!=-1,numbers:match[8]?match[8].indexOf('N')==-1:true,language:match[1]&&match[1].substring(1)};if(match[7]){settings.animation={};settings.animation.shuffleRounds=parseInt(match[7])}if(match[8]&&match[8].search(/[ABCDE]/)!=-1){settings.control={};settings.control.shufflePieces=match[8].indexOf('A')==-1;settings.control.toggleOriginal=match[8].indexOf('B')==-1;settings.control.toggleNumbers=match[8].indexOf('C')==-1;settings.control.counter=match[8].indexOf('D')==-1;settings.control.timer=match[8].indexOf('E')==-1}}$(this).jqPuzzle(settings)})})})(jQuery);