jquery.booklet.1.2.0.js 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
  1. /*
  2. * jQuery Booklet Plugin
  3. * Copyright (c) 2010 W. Grauvogel (http://builtbywill.com/)
  4. *
  5. * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
  6. * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
  7. *
  8. * Version : 1.2.0
  9. *
  10. * Originally based on the work of:
  11. * 1) Charles Mangin (http://clickheredammit.com/pageflip/)
  12. */
  13. ;(function($) {
  14. $.fn.booklet = function(options){
  15. var o = $.extend({}, $.fn.booklet.defaults, options);
  16. return $(this).each(function()
  17. {
  18. var command, config, obj, id, i, target;
  19. //option type string - api call
  20. if(typeof options == 'string')
  21. {
  22. //check if booklet has been initialized
  23. if($(this).data('booklet')){
  24. command = options.toLowerCase();
  25. obj = $.fn.booklet.interfaces[$(this).data('id')];
  26. if(command == 'next'){ obj.next() }
  27. else if(command == 'prev'){ obj.prev() }
  28. }
  29. }
  30. //option type number - api call
  31. else if(typeof options == 'number')
  32. {
  33. //check if booklet has been initialized
  34. if($(this).data('booklet')){
  35. target = options;
  36. obj = $.fn.booklet.interfaces[$(this).data('id')];
  37. if(target % 2 != 0) {
  38. target-= 1;
  39. }
  40. obj.gotoPage(target);
  41. }
  42. }
  43. //else build new booklet
  44. else
  45. {
  46. config = $.extend(true, {}, o);
  47. // Determine ID (Reuse array slots if possible)
  48. id = $.fn.booklet.interfaces.length;
  49. for(i = 0; i < id; i++)
  50. {
  51. if(typeof $.fn.booklet.interfaces[i] == 'undefined'){ id = i; break; }
  52. }
  53. // Instantiate the booklet
  54. obj = new booklet($(this), config, id);
  55. // Add API references
  56. $.fn.booklet.interfaces[id] = obj;
  57. }
  58. });
  59. }
  60. function booklet(target, options, id){
  61. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. //VARS + STRUCTURE
  63. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  64. var self, opts, b, src,
  65. hash, i, j, p, diff, busy, init, rhover, lhover, h, a, playing,
  66. titles = new Array(), chapters = new Array(),
  67. pN, p0, p1, p2, p3, p4, pNwrap, p0wrap, p1wrap, p2wrap, p3wrap, p4wrap, wraps, sF, sB,
  68. p3drag, p0drag, temp, relativeX,
  69. overlaysB, overlayN, overlayP, tabs, tabN, tabP, arrows, arrowN, arrowP, next, prev, ctrlsN, ctrlsP,
  70. menu, chapter, dd, ddUL, ddH, ddLI, ddA, ddT, ddC, ddCUL, ddCH, ddCLI, ddCA, ddCT,
  71. empty = '<div class="b-page-empty" title="" rel=""></div>', blank = '<div class="b-page-blank" title="" rel=""></div>'
  72. ;
  73. busy = false;
  74. playing = false;
  75. init = false;
  76. rhover = lhover = false;
  77. self = this;
  78. self.options = options;
  79. self.id = id;
  80. self.hash = '';
  81. opts = self.options;
  82. b = target.addClass('booklet');
  83. src = b.children('.b-load');
  84. //save page titles and chapter names, add page numbers
  85. initPages();
  86. //store data for api calls
  87. b.data('booklet',true);
  88. b.data('id', id);
  89. b.data('total', src.children().length);
  90. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  91. // SETUP OPTIONS
  92. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  93. //set width + height
  94. if(!opts.width){
  95. opts.width = b.width();
  96. }else if(typeof opts.width == 'string' && opts.width.indexOf("%") != -1){
  97. opts.wPercent = true;
  98. opts.wOrig = opts.width;
  99. opts.width = (opts.width.replace('%','')/100) * parseFloat(b.parent().css('width'));
  100. }
  101. if(!opts.height){
  102. opts.height = b.height();
  103. }else if(typeof opts.height == 'string' && opts.height.indexOf("%") != -1){
  104. opts.hPercent = true;
  105. opts.hOrig = opts.height;
  106. opts.height = (opts.height.replace('%','')/100) * parseFloat(b.parent().css('height'));
  107. }
  108. b.width(opts.width);
  109. b.height(opts.height);
  110. //save page sizes and other vars
  111. opts.pWidth = opts.width/2;
  112. opts.pWidthN = '-'+(opts.pWidth)+'px';
  113. opts.pWidthH = opts.pWidth/2;
  114. opts.pHeight = opts.height;
  115. opts.pTotal = src.children().length;
  116. opts.speedH = opts.speed/2;
  117. //set startingPage
  118. if(opts.direction == 'LTR'){
  119. opts.curr = 0;
  120. }else if(opts.direction == 'RTL'){
  121. opts.curr = opts.pTotal-2;
  122. }
  123. if(!isNaN(opts.startingPage) && opts.startingPage <= opts.pTotal && opts.startingPage > 0){
  124. if((opts.startingPage % 2) != 0){opts.startingPage--};
  125. opts.curr = opts.startingPage;
  126. }
  127. //set position
  128. if(opts.closed && opts.autoCenter){
  129. if(opts.curr == 0){
  130. b.width(opts.pWidth);
  131. }else if(opts.curr >= opts.pTotal-2){
  132. b.width(opts.pWidth);
  133. }
  134. }
  135. //set booklet opts.name
  136. if(opts.name){
  137. document.title = opts.name;
  138. }else{
  139. opts.name = document.title;
  140. }
  141. //save shadow widths for anim
  142. if(opts.shadows){
  143. opts.shadowTopFwdWidth = '-'+opts.shadowTopFwdWidth+'px';
  144. opts.shadowTopBackWidth = '-'+opts.shadowTopBackWidth+'px';
  145. }
  146. //setup menu
  147. if(opts.menu){
  148. menu = $(opts.menu).addClass('b-menu');
  149. p = opts.curr;
  150. //setup page selctor
  151. if(opts.pageSelector){
  152. //add selector
  153. dd = $('<div class="b-selector b-selector-page"><span class="b-current">'+ (p+1) +' - '+ (p+2) +'</span></div>').appendTo(menu);
  154. ddUL = $('<ul></ul>').appendTo(dd).empty().css('height','auto');
  155. //loop through all pages
  156. for(i=0; i < opts.pTotal; i+=2){
  157. j = i;
  158. //nums for normal view
  159. nums = (j+1) +'-'+ (j+2);
  160. if(opts.closed){
  161. //nums for closed book
  162. j--;
  163. if(i==0){nums='1'}
  164. else if(i==opts.pTotal-2){nums=opts.pTotal-2}
  165. else {nums = (j+1) +'-'+ (j+2);}
  166. //nums for closed book with covers
  167. if(opts.covers){
  168. j--;
  169. if(i==0){nums=''}
  170. else if(i==opts.pTotal-2){nums=''}
  171. else {nums = (j+1) +'-'+ (j+2);}
  172. }
  173. }
  174. //nums for RTL direction
  175. if(opts.direction == 'RTL'){
  176. nums = (Math.abs(j - opts.pTotal)-1) +' - '+ ((Math.abs(j - opts.pTotal)));
  177. if(opts.closed){
  178. if(i==opts.pTotal-2){nums='1'}
  179. else if(i==0){nums=opts.pTotal-2}
  180. else{nums = (Math.abs(j - opts.pTotal)-3) +' - '+ ((Math.abs(j - opts.pTotal)-2));}
  181. if(opts.covers){
  182. if(i==opts.pTotal-2){nums=''}
  183. else if(i==0){nums=''}
  184. else{nums = (Math.abs(j - opts.pTotal)-5) +' - '+ ((Math.abs(j - opts.pTotal)-4));}
  185. }
  186. }
  187. dd.find('.b-current').text(nums);
  188. ddLI = $('<li><a href="#/page/'+ (i+1) +'" id="selector-page-'+i+'"><span class="b-text">'+ titles[i+1] +'</span><span class="b-num">'+ nums +'</span></a></li>').prependTo(ddUL);
  189. }else{
  190. if(i==0){dd.find('.b-current').text(nums);}
  191. ddLI = $('<li><a href="#/page/'+ (i+1) +'" id="selector-page-'+i+'"><span class="b-text">'+ titles[i] +'</span><span class="b-num">'+ nums +'</span></a></li>').appendTo(ddUL);
  192. }
  193. ddA = ddLI.find('a');
  194. if(!opts.hash){
  195. ddA.click(function(){
  196. if(opts.direction == 'RTL'){dd.find('.b-current').text($(this).find('.b-num').text());}
  197. ddT = parseInt($(this).attr('id').replace('selector-page-',''));
  198. self.gotoPage(ddT);
  199. return false;
  200. });
  201. }
  202. }
  203. //set height
  204. ddH = ddUL.height();
  205. ddUL.css({'height':0, 'padding-bottom':0});
  206. //add hover effects
  207. dd.unbind('hover').hover(function(){
  208. ddUL.stop().animate({height:ddH, paddingBottom:10}, 500);
  209. },function(){
  210. ddUL.stop().animate({height:0, paddingBottom:0}, 500);
  211. });
  212. }
  213. //setup chapter selctor
  214. if(opts.chapterSelector){
  215. chapter = chapters[opts.curr];
  216. if(chapter == ""){ chapter = chapters[opts.curr+1]; }
  217. ddC = $('<div class="b-selector b-selector-chapter"><span class="b-current">'+chapter+'</span></div>').appendTo(menu);
  218. ddCUL = $('<ul></ul>').appendTo(ddC).empty().css('height','auto');
  219. for(i=0; i < opts.pTotal; i+=1){
  220. if(chapters[i] != "" && typeof chapters[i] != "undefined"){
  221. if(opts.direction == 'RTL'){
  222. j = i;
  223. if(j % 2 != 0){j--;}
  224. ddC.find('.b-current').text(chapters[i]);
  225. ddCLI = $('<li><a href="#/page/'+ (j+1) +'" id="selector-page-'+(j)+'"><span class="b-text">'+ chapters[i] +'</span></a></li>').prependTo(ddCUL);
  226. }else{
  227. ddCLI = $('<li><a href="#/page/'+ (i+1) +'" id="selector-page-'+i+'"><span class="b-text">'+ chapters[i] +'</span></a></li>').appendTo(ddCUL);
  228. }
  229. ddCA = ddCLI.find('a');
  230. if(!opts.hash){
  231. ddCA.click(function(){
  232. if(opts.direction == 'RTL'){ddC.find('.b-current').text($(this).find('.b-text').text());}
  233. ddCT = parseInt($(this).attr('id').replace('selector-page-',''));
  234. self.gotoPage(ddCT);
  235. return false;
  236. });
  237. }
  238. }
  239. }
  240. ddCH = ddCUL.height();
  241. ddCUL.css({'height':0, 'padding-bottom':0});
  242. ddC.unbind('hover').hover(function(){
  243. ddCUL.stop().animate({height:ddCH, paddingBottom:10}, 500);
  244. },function(){
  245. ddCUL.stop().animate({height:0, paddingBottom:0}, 500);
  246. });
  247. }
  248. }
  249. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  250. // API METHODS
  251. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  252. $.extend(self,
  253. {
  254. next : function(){
  255. if(!busy){
  256. self.gotoPage(opts.curr+2);
  257. }
  258. },
  259. prev : function(){
  260. if(!busy){
  261. self.gotoPage(opts.curr-2);
  262. }
  263. },
  264. gotoPage : function(num){
  265. //moving forward (increasing number)
  266. if(num > opts.curr && num < opts.pTotal && num >= 0 && !busy){
  267. busy = true;
  268. diff = num - opts.curr;
  269. opts.curr = num;
  270. opts.before.call(self, opts);
  271. updatePager();
  272. updateCtrls();
  273. updateHash(opts.curr+1, opts);
  274. initAnim(diff, true, sF);
  275. //hide p2 as p3 moves across it
  276. if(opts.closed && opts.autoCenter && num-diff == 0){
  277. p2.stop().animate({width:0, left:opts.pWidth}, opts.speed, opts.easing);
  278. p4.stop().animate({left:opts.pWidth}, opts.speed, opts.easing);
  279. }else{
  280. p2.stop().animate({width:0}, opts.speedH, opts.easeIn);
  281. }
  282. //animate p3 from right to left (left: movement, width: reveal slide, paddingLeft: shadow underneath)
  283. //call setuppages at end of animation to reset pages
  284. //animation if dragging forward
  285. if(p3drag){
  286. p3.stop().animate({left:opts.pWidth/4, width:opts.pWidth*.75, paddingLeft: opts.shadowBtmWidth}, opts.speedH, opts.easeIn)
  287. .animate({left:0, width:opts.pWidth, paddingLeft:0}, opts.speedH);
  288. }else{
  289. p3.stop().animate({left:opts.pWidthH, width:opts.pWidthH, paddingLeft: opts.shadowBtmWidth}, opts.speedH, opts.easeIn)
  290. .animate({left:0, width:opts.pWidth, paddingLeft:0}, opts.speedH);
  291. }
  292. p3wrap.animate({left:opts.shadowBtmWidth}, opts.speedH, opts.easeIn)
  293. .animate({left:0}, opts.speedH, opts.easeOut, function(){updateAfter()});
  294. //moving backward (decreasing number)
  295. }else if(num < opts.curr && num < opts.pTotal && num >= 0 && !busy){
  296. busy = true;
  297. diff = opts.curr - num;
  298. opts.curr = num;
  299. opts.before.call(self, opts);
  300. updatePager();
  301. updateCtrls();
  302. updateHash(opts.curr+1, opts);
  303. initAnim(diff, false, sB);
  304. //animation if dragging backwards
  305. if(p0drag){
  306. //hide p1 as p0 moves across it
  307. p1.animate({left:opts.pWidth, width:0}, opts.speed, opts.easing);
  308. p1wrap.animate({left:opts.pWidthN}, opts.speed, opts.easing);
  309. //animate p0 from left to right (right: movement, width: reveal slide, paddingLeft: shadow underneath)
  310. if(opts.closed && opts.autoCenter && opts.curr == 0){
  311. p0.animate({left:opts.pWidthH, width:opts.pWidthH}, opts.speedH, opts.easeIn)
  312. .animate({left:0, width:opts.pWidth}, opts.speedH, opts.easeOut);
  313. p2.stop().animate({left:0}, opts.speed, opts.easing);
  314. }else{
  315. p0.animate({left:opts.pWidth, width:opts.pWidth}, opts.speed, opts.easing);
  316. }
  317. //animate .wrapper content with p0 to keep content right aligned throughout
  318. //call setuppages at end of animation to reset pages
  319. p0wrap.animate({right:0}, opts.speed, opts.easing, function(){updateAfter()});
  320. }else{
  321. //hide p1 as p0 moves across it
  322. p1.animate({left:opts.pWidth, width:0}, opts.speed, opts.easing);
  323. p1wrap.animate({left:opts.pWidthN}, opts.speed, opts.easing);
  324. //animate p0 from left to right (right: movement, width: reveal slide, paddingLeft: shadow underneath)
  325. if(opts.closed && opts.autoCenter && opts.curr == 0){
  326. p0.animate({left:opts.pWidthH, width:opts.pWidthH}, opts.speedH, opts.easeIn)
  327. .animate({left:0, width:opts.pWidth}, opts.speedH, opts.easeOut);
  328. p2.stop().animate({left:0}, opts.speed, opts.easing);
  329. }else{
  330. p0.animate({left:opts.pWidthH, width:opts.pWidthH}, opts.speedH, opts.easeIn)
  331. .animate({left:opts.pWidth, width:opts.pWidth}, opts.speedH, opts.easeOut);
  332. }
  333. //animate .wrapper content with p0 to keep content right aligned throughout
  334. //call setuppages at end of animation to reset pages
  335. p0wrap.animate({right:opts.shadowBtmWidth}, opts.speedH,opts. easeIn)
  336. .animate({right:0}, opts.speedH, opts.easeOut, function(){updateAfter()});
  337. }
  338. }
  339. }
  340. });
  341. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  342. // SETUP CONTROLS
  343. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  344. if(opts.manual && $.ui){
  345. opts.overlays = false;
  346. }
  347. //add prev next user defined controls
  348. if(opts.next){
  349. next = $(opts.next);
  350. next.click(function(e){e.preventDefault(); self.next();});
  351. }
  352. if(opts.prev){
  353. prev = $(opts.prev);
  354. prev.click(function(e){e.preventDefault(); self.prev();});
  355. }
  356. //add overlays
  357. if(opts.overlays){
  358. overlayP = $('<div class="b-overlay b-overlay-prev b-prev" title="Previous Page"></div>').appendTo(b);
  359. overlayN = $('<div class="b-overlay b-overlay-next b-next" title="Next Page"></div>').appendTo(b);
  360. overlaysB = b.find('.b-overlay');
  361. if ($.browser.msie) {
  362. overlaysB.css({'background':'#fff','filter':'progid:DXImageTransform.Microsoft.Alpha(opacity=0) !important'});
  363. }
  364. }
  365. //add tabs
  366. if(opts.tabs){
  367. tabP = $('<div class="b-tab b-tab-prev b-prev" title="Previous Page">Previous</div>').appendTo(b);
  368. tabN = $('<div class="b-tab b-tab-next b-next" title="Next Page">Next</div>').appendTo(b);
  369. tabs = b.find('.b-tab');
  370. if(opts.tabWidth){
  371. tabs.width(opts.tabWidth);
  372. }
  373. if(opts.tabHeight){
  374. tabs.height(opts.tabHeight);
  375. }
  376. tabs.css({'top': '-'+tabN.outerHeight()+'px'});
  377. b.css({'marginTop': tabN.outerHeight()});
  378. //update ctrls for RTL direction
  379. if(opts.direction == 'RTL'){
  380. tabN.html('Previous').attr('title','Previous Page');
  381. tabP.html('Next').attr('title','Next Page');
  382. }
  383. }else{
  384. b.css({'marginTop': 0});
  385. }
  386. //add arrows
  387. if(opts.arrows){
  388. arrowP = $('<div class="b-arrow b-arrow-prev b-prev" title="Previous Page"><div>Previous</div></div>').appendTo(b);
  389. arrowN = $('<div class="b-arrow b-arrow-next b-next" title="Next Page"><div>Next</div></div>').appendTo(b);
  390. arrows = b.find('.b-arrow');
  391. //update ctrls for RTL direction
  392. if(opts.direction == 'RTL'){
  393. arrowN.html('<div>Previous</div>').attr('title','Previous Page');
  394. arrowP.html('<div>Next</div>').attr('title','Next Page');
  395. }
  396. }
  397. //save all "b-prev" and "b-next" controls
  398. ctrlsN = b.find('.b-next');
  399. ctrlsP = b.find('.b-prev');
  400. //add click actions
  401. ctrlsN.click(function(e){e.preventDefault(); self.next();});
  402. ctrlsP.click(function(e){e.preventDefault(); self.prev();});
  403. //add page hover animations
  404. if(opts.overlays && opts.hovers){
  405. //hovers to start draggable forward
  406. ctrlsN.unbind("mouseover mouseout").bind("mouseover",function(){
  407. hoverAnimStart(true);
  408. })
  409. .bind("mouseout",function(){
  410. hoverAnimEnd(true);
  411. });
  412. //hovers to start draggable backwards
  413. ctrlsP.unbind("mouseover mouseout").bind("mouseover",function(){
  414. hoverAnimStart(false);
  415. })
  416. .bind("mouseout",function(){
  417. hoverAnimEnd(false);
  418. });
  419. }
  420. //arrow animations
  421. if(opts.arrows){
  422. if(opts.arrowsHide){
  423. if($.support.opacity){
  424. ctrlsN.hover(
  425. function(){arrowN.find('div').stop().fadeTo('fast', 1);},
  426. function(){arrowN.find('div').stop().fadeTo('fast', 0);
  427. });
  428. ctrlsP.hover(
  429. function(){arrowP.find('div').stop().fadeTo('fast', 1);},
  430. function(){arrowP.find('div').stop().fadeTo('fast', 0);
  431. });
  432. }else{
  433. ctrlsN.hover(
  434. function(){arrowN.find('div').show();},
  435. function(){arrowN.find('div').hide();
  436. });
  437. ctrlsP.hover(
  438. function(){arrowP.find('div').show();},
  439. function(){arrowP.find('div').hide();
  440. });
  441. }
  442. }else{
  443. arrowN.find('div').show();
  444. arrowP.find('div').show();
  445. }
  446. }
  447. //keyboard ctrls
  448. if(opts.keyboard){
  449. //keyboard ctrls
  450. $(document).keyup(function(event){
  451. if(event.keyCode == 37){self.prev();}
  452. else if(event.keyCode == 39){self.next();}
  453. });
  454. }
  455. //hash ctrls
  456. if(opts.hash){
  457. setupHash();
  458. clearInterval(h);
  459. h = setInterval(function(){pollHash()}, 250);
  460. }
  461. //percentage resizing
  462. if(opts.wPercent || opts.hPercent){
  463. $(window).resize(function() {
  464. resetSize();
  465. });
  466. }
  467. //auto flip book controls
  468. if(opts.auto && opts.delay){
  469. clearTimeout(a);
  470. a = setTimeout(function(){self.next();},opts.delay);
  471. playing = true;
  472. if(opts.pause){
  473. pause = $(opts.pause);
  474. pause.click(function(e){
  475. e.preventDefault();
  476. if(playing){
  477. clearTimeout(a);
  478. playing = false;
  479. }
  480. });
  481. }
  482. if(opts.play){
  483. play = $(opts.play);
  484. play.click(function(e){
  485. e.preventDefault();
  486. if(!playing){
  487. clearTimeout(a);
  488. a = setTimeout(function(){self.next();},opts.delay);
  489. playing = true;
  490. }
  491. });
  492. }
  493. }
  494. //first time setup
  495. resetPages();
  496. updateCtrls();
  497. updatePager();
  498. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  499. //General Functions
  500. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  501. function initPages(){
  502. //fix for odd number of pages
  503. if((src.children().length % 2) != 0){
  504. //if book is closed and using covers, add page before back cover, else after last page
  505. if(opts.closed && opts.covers){
  506. src.children().last().before(blank);
  507. }else{
  508. src.children().last().after(blank);
  509. }
  510. }
  511. //if closed book, add empty pages to start and end
  512. if(opts.closed){
  513. $(empty).attr({'title':opts.closedFrontTitle || "Beginning", 'rel':opts.closedFrontChapter || "Beginning of Book"}).prependTo(src);
  514. src.children().last().attr({'title':opts.closedBackTitle || "End", 'rel':opts.closedBackChapter || "End of Book"});
  515. src.append(empty);
  516. }
  517. if(opts.direction == 'LTR'){
  518. j = 0;
  519. }else{
  520. j = src.children().length;
  521. if(opts.closed){j-=2;}
  522. if(opts.covers){j-=2;}
  523. $(src.children().get().reverse()).each(function(){
  524. $(this).appendTo(src);
  525. });
  526. }
  527. //save titles and chapters
  528. src.children().each(function(i){
  529. //save chapter title
  530. if($(this).attr('rel')){
  531. chapters[i] = $(this).attr('rel');
  532. }else{
  533. chapters[i] = "";
  534. }
  535. //save page title
  536. titles[i] = $(this).attr('title');
  537. //give content the correct wrapper and page wrapper
  538. if($(this).hasClass('b-page-empty')){
  539. $(this).wrap('<div class="b-page"><div class="b-wrap"></div></div>');
  540. }else if(opts.closed && opts.covers && (i == 1 || i == src.children().length-2)){
  541. $(this).wrap('<div class="b-page"><div class="b-wrap b-page-cover"></div></div>');
  542. }else if(i % 2 != 0){
  543. $(this).wrap('<div class="b-page"><div class="b-wrap b-wrap-right"></div></div>');
  544. }else{
  545. $(this).wrap('<div class="b-page"><div class="b-wrap b-wrap-left"></div></div>');
  546. }
  547. $(this).parents('.b-page').addClass('b-page-'+i).data('page',i);
  548. //add page numbers
  549. if(opts.pageNumbers && !$(this).hasClass('b-page-empty') && (!opts.closed || (opts.closed && !opts.covers) || (opts.closed && opts.covers && i != 1 && i != src.children().length-2))){
  550. if(opts.direction == 'LTR'){j++;}
  551. $(this).parent().append('<div class="b-counter">'+(j)+'</div>');
  552. if(opts.direction == 'RTL'){j--;}
  553. }
  554. });
  555. }
  556. function resetSize(){
  557. //recalculate size for percentage values
  558. if(opts.wPercent){
  559. opts.width = (opts.wOrig.replace('%','')/100) * parseFloat(b.parent().css('width'));
  560. b.width(opts.width);
  561. opts.pWidth = opts.width/2;
  562. opts.pWidthN = '-'+(opts.pWidth)+'px';
  563. opts.pWidthH = opts.pWidth/2;
  564. }
  565. if(opts.hPercent){
  566. opts.height = (opts.hOrig.replace('%','')/100) * parseFloat(b.parent().css('height'));
  567. b.height(opts.height);
  568. opts.pHeight = opts.height;
  569. }
  570. resetCSS();
  571. }
  572. function resetCSS(){
  573. //update css
  574. b.find('.b-shadow-f, .b-shadow-b, .b-p0, .b-p3').css({'filter':'','zoom':''});
  575. if(opts.manual && $.ui){
  576. b.find('.b-page').draggable('destroy').removeClass('b-grab b-grabbing');
  577. }
  578. wraps.attr('style','');
  579. wraps.css({'left':0,'width':opts.pWidth-(opts.pagePadding*2), 'height':opts.pHeight-(opts.pagePadding*2), 'padding': opts.pagePadding});
  580. p0wrap.css({'right':0,'left':'auto'});
  581. p1.css({'left':0,'width':opts.pWidth, 'height':opts.pHeight});
  582. p2.css({'left':opts.pWidth, 'width':opts.pWidth, 'opacity':1, 'height':opts.pHeight});
  583. pN.css({'left':0, 'width':opts.pWidth, 'height':opts.pHeight});
  584. p0.css({'left':0, 'width':0, 'height':opts.pHeight});
  585. p3.stop().css({'left':opts.pWidth*2, 'width':0, 'height':opts.pHeight, paddingLeft:0});
  586. p4.css({'left':opts.pWidth, 'width':opts.pWidth, 'height':opts.pHeight});
  587. if(opts.closed && opts.autoCenter && opts.curr == 0){
  588. pN.css({'left':0});
  589. p1.css({'left':opts.pWidthN});
  590. p2.css({'left':0});
  591. p3.css({'left':opts.pWidth});
  592. p4.css({'left':0});
  593. }
  594. if(opts.closed && opts.autoCenter && (opts.curr == 0 || opts.curr >= opts.pTotal-2)){
  595. if(opts.overlays){overlaysB.width('100%');}
  596. b.width(opts.pWidth);
  597. }else{
  598. if(opts.overlays){overlaysB.width('50%');}
  599. b.width(opts.width);
  600. }
  601. }
  602. function resetPages(){
  603. //reset page order
  604. if(init){
  605. if(p1.data('page')-1 < 0){
  606. src.prepend(p2.detach());
  607. src.prepend(p1.detach());
  608. }else{
  609. b.find('.b-page-'+(p1.data('page')-1)).after(p1.detach());
  610. b.find('.b-page-'+(p2.data('page')-1)).after(p2.detach());
  611. }
  612. if(p3.data('page')-1 <= opts.pTotal){
  613. b.find('.b-page-'+(p3.data('page')-1)).after(p3.detach());
  614. b.find('.b-page-'+(p4.data('page')-1)).after(p4.detach());
  615. }
  616. if(pN.data('page')-1 >= 0){
  617. b.find('.b-page-'+(pN.data('page')-1)).after(pN.detach());
  618. b.find('.b-page-'+(p0.data('page')-1)).after(p0.detach());
  619. }else{
  620. src.prepend(pN.detach());
  621. pN.after(p0.detach());
  622. }
  623. }
  624. //reset all content
  625. b.find('.b-page').removeClass('b-pN b-p0 b-p1 b-p2 b-p3 b-p4').hide();
  626. //add page classes
  627. if(opts.curr-2 >= 0){
  628. b.find('.b-page-'+(opts.curr-2)).addClass('b-pN').show();
  629. b.find('.b-page-'+(opts.curr-1)).addClass('b-p0').show();
  630. }
  631. b.find('.b-page-'+(opts.curr)).addClass('b-p1').show();
  632. b.find('.b-page-'+(opts.curr+1)).addClass('b-p2').show();
  633. if(opts.curr+3 <= opts.pTotal){
  634. b.find('.b-page-'+(opts.curr+2)).addClass('b-p3').show();
  635. b.find('.b-page-'+(opts.curr+3)).addClass('b-p4').show();
  636. }
  637. //save structure elems to vars
  638. pN = b.find('.b-pN');
  639. p0 = b.find('.b-p0');
  640. p1 = b.find('.b-p1');
  641. p2 = b.find('.b-p2');
  642. p3 = b.find('.b-p3');
  643. p4 = b.find('.b-p4');
  644. pNwrap = b.find('.b-pN .b-wrap');
  645. p0wrap = b.find('.b-p0 .b-wrap');
  646. p1wrap = b.find('.b-p1 .b-wrap');
  647. p2wrap = b.find('.b-p2 .b-wrap');
  648. p3wrap = b.find('.b-p3 .b-wrap');
  649. p4wrap = b.find('.b-p4 .b-wrap');
  650. wraps = b.find('.b-wrap');
  651. resetCSS();
  652. //update page order for animations
  653. if(opts.curr+3 <= opts.pTotal){
  654. p3.after(p0.detach());
  655. p1.after(p4.detach());
  656. }else{
  657. p0.detach().appendTo(src);
  658. }
  659. init = true;
  660. if(opts.shadows){
  661. b.find('.b-shadow-f, .b-shadow-b').remove();
  662. sF = $('<div class="b-shadow-f"></div>').css({'right':0,'width':opts.pWidth, 'height':opts.pHeight}).appendTo(p3);
  663. sB = $('<div class="b-shadow-b"></div>').appendTo(p0).css({'left':0,'width':opts.pWidth, 'height':opts.pHeight});
  664. }
  665. //reset vars
  666. rhover = lhover = p3drag = p0drag = false;
  667. //manual page turning, check if jQuery UI is loaded
  668. if(opts.manual && $.ui){
  669. //implement draggable forward
  670. p3.draggable({
  671. axis: "x",
  672. containment: [p2.offset().left-opts.pWidthH,0,p2.offset().left+opts.pWidth-50,opts.pHeight],
  673. drag: function(event, ui) {
  674. p3drag = true;
  675. temp = ui.originalPosition.left - ui.position.left;
  676. p3.removeClass('b-grab').addClass('b-grabbing');
  677. p3.width(40+(temp/2));
  678. p3wrap.css({'left':10+(temp/8)});
  679. p2.width(opts.pWidth-p3.width()+10);
  680. if(opts.shadows){
  681. sF.css({'right':'-'+(20+temp/4)+'px'});
  682. if($.support.opacity){
  683. sF.css({'opacity':0.5*(temp/opts.pWidthH)});
  684. }else{
  685. sF.css({'right':'auto','left':0.1*p3.width()});
  686. }
  687. }
  688. },
  689. stop: function(event, ui) {
  690. hoverAnimEnd(false);
  691. var temp = ui.originalPosition.left - ui.position.left;
  692. if(temp>opts.pWidthH/4){
  693. if(opts.shadows && !$.support.opacity){
  694. sF.css({'left':'auto'});
  695. }
  696. self.next();
  697. p3.removeClass('b-grab b-grabbing');
  698. }else{
  699. p3drag = false;
  700. p3.removeClass('b-grabbing').addClass('b-grab');
  701. }
  702. }
  703. });
  704. //implement draggable backwards
  705. p0.draggable({
  706. axis: "x",
  707. containment: [p1.offset().left+10,0,p1.offset().left+opts.pWidth*.75,opts.pHeight],
  708. drag: function(event, ui) {
  709. p0drag = true;
  710. temp = ui.position.left - ui.originalPosition.left;
  711. p0.removeClass('b-grab').addClass('b-grabbing');
  712. p0.css({left:40+(temp)/1.5, width:40+(temp)});
  713. p0wrap.css({right:10+temp/4});
  714. p1.css({left:ui.position.left+20, width:opts.pWidth-ui.position.left-10});
  715. p1wrap.css({left:-1*(temp+30)});
  716. if(opts.shadows){
  717. if($.support.opacity){
  718. sB.css({'opacity':0.5*(temp/opts.pWidthH)});
  719. }else{
  720. sB.css({'left':-0.38*opts.pWidth});
  721. }
  722. }
  723. },
  724. stop: function(event, ui) {
  725. hoverAnimEnd(true);
  726. temp = ui.position.left - ui.originalPosition.left;
  727. if(temp>opts.pWidthH/4){
  728. self.prev();
  729. p0.removeClass('b-grab b-grabbing');
  730. }else{
  731. p0drag = false;
  732. p0.removeClass('b-grabbing').addClass('b-grab');
  733. }
  734. }
  735. });
  736. //mousetracking for page movement
  737. $(b).unbind('mousemove mouseout').bind('mousemove',function(e){
  738. relativeX = e.pageX - b.offset().left;
  739. if(relativeX < 50){
  740. hoverAnimStart(false);
  741. }else if(relativeX > opts.pWidth-50 && opts.curr == 0 && opts.autoCenter && opts.closed){
  742. hoverAnimStart(true);
  743. }else if(relativeX > 50 && relativeX < opts.width-50){
  744. hoverAnimEnd(false);
  745. hoverAnimEnd(true);
  746. }else if(relativeX > opts.width-50){
  747. hoverAnimStart(true);
  748. }
  749. }).bind('mouseout',function(){
  750. hoverAnimEnd(false);
  751. hoverAnimEnd(true);
  752. });
  753. }
  754. }
  755. function hoverAnimStart(inc){
  756. if(inc){
  757. if(!busy && !rhover &&!lhover && !p3drag && opts.curr+2 <= opts.pTotal-2){
  758. //animate
  759. p2.stop().animate({'width':opts.pWidth-40}, 500, opts.easing);
  760. p3.addClass('b-grab');
  761. if(opts.closed && opts.autoCenter && opts.curr == 0){
  762. p3.stop().animate({'left':opts.pWidth-50, 'width':40}, 500, opts.easing);
  763. }else{
  764. p3.stop().animate({'left':opts.width-50, 'width':40}, 500, opts.easing);
  765. }
  766. p3wrap.stop().animate({'left':10}, 500, opts.easing);
  767. if(opts.shadows && !$.support.opacity){
  768. sF.css({'right':'auto','left':'-40%'});
  769. }
  770. rhover = true;
  771. }
  772. }else{
  773. if(!busy && !lhover && !rhover && !p0drag && opts.curr-2 >= 0){
  774. //animate
  775. p1.stop().animate({left:10, width:opts.pWidth-10}, 400, opts.easing);
  776. p0.addClass('b-grab');
  777. p1wrap.stop().animate({left:"-10px"}, 400, opts.easing);
  778. p0.stop().animate({left:10, width:40}, 400, opts.easing);
  779. p0wrap.stop().animate({right:10}, 400, opts.easing);
  780. if(opts.shadows && !$.support.opacity){
  781. sB.css({'left':-0.38*opts.pWidth});
  782. }
  783. lhover = true;
  784. }
  785. }
  786. }
  787. function hoverAnimEnd(inc){
  788. if(inc){
  789. if(!busy && rhover && !p3drag && opts.curr+2 <= opts.pTotal-2){
  790. p2.stop().animate({'width':opts.pWidth}, 500, opts.easing);
  791. if(opts.closed && opts.autoCenter && opts.curr == 0){
  792. p3.stop().animate({'left':opts.pWidth, 'width':0}, 500, opts.easing);
  793. }else{
  794. p3.stop().animate({'left':opts.width, 'width':0}, 500, opts.easing);
  795. }
  796. p3wrap.stop().animate({'left':0}, 500, opts.easing);
  797. if(opts.shadows && !$.support.opacity){
  798. sF.css({'left':'auto'});
  799. }
  800. rhover = false;
  801. }
  802. }else{
  803. if(!busy && lhover && !p0drag && opts.curr-2 >= 0){
  804. p1.stop().animate({left:0, width:opts.pWidth}, 400, opts.easing);
  805. p1wrap.stop().animate({left:0}, 400, opts.easing);
  806. p0.stop().animate({left:0, width:0}, 400, opts.easing);
  807. p0wrap.stop().animate({right:0}, 400, opts.easing);
  808. lhover = false;
  809. }
  810. }
  811. }
  812. function initAnim(diff, inc, shadow){
  813. //setup content
  814. if(inc && diff > 2){
  815. b.find('.b-page-'+(p3.data('page')-1)).after(p3.detach());
  816. b.find('.b-page-'+(p4.data('page')-1)).after(p4.detach());
  817. b.find('.b-p3, .b-p4').removeClass('b-p3 b-p4').hide();
  818. b.find('.b-page-'+opts.curr).addClass('b-p3').show().stop().css({'left':opts.pWidth*2, 'width':0, 'height':opts.pHeight, paddingLeft:0});
  819. b.find('.b-page-'+(opts.curr+1)).addClass('b-p4').show().css({'left':opts.pWidth, 'width':opts.pWidth, 'height':opts.pHeight});
  820. b.find('.b-page-'+opts.curr+' .b-wrap').show().css({'width':opts.pWidth-(opts.pagePadding*2), 'height':opts.pHeight-(opts.pagePadding*2), 'padding': opts.pagePadding});
  821. b.find('.b-page-'+(opts.curr+1)+' .b-wrap').show().css({'width':opts.pWidth-(opts.pagePadding*2), 'height':opts.pHeight-(opts.pagePadding*2), 'padding': opts.pagePadding});
  822. p3 = b.find('.b-p3');
  823. p4 = b.find('.b-p4');
  824. p3wrap = b.find('.b-p3 .b-wrap');
  825. p4wrap = b.find('.b-p4 .b-wrap');
  826. if(rhover){
  827. p3.css({'left':opts.width-40, 'width':20, 'padding-left': 10});
  828. }
  829. p1.after(p4.detach());
  830. p2.after(p3.detach());
  831. if (opts.shadows) {
  832. b.find('.b-shadow-f').remove();
  833. sF = $('<div class="b-shadow-f"></div>').css({
  834. 'right': 0,
  835. 'width': opts.pWidth,
  836. 'height': opts.pHeight
  837. }).appendTo(p3);
  838. shadow = sF;
  839. }
  840. }else if(!inc && diff > 2){
  841. b.find('.b-page-'+(pN.data('page')-1)).after(pN.detach());
  842. b.find('.b-page-'+(p0.data('page')-1)).after(p0.detach());
  843. b.find('.b-pN, .b-p0').removeClass('b-pN b-p0').hide();
  844. b.find('.b-page-'+opts.curr).addClass('b-pN').show().css({'left':0, 'width':opts.pWidth, 'height':opts.pHeight});
  845. b.find('.b-page-'+(opts.curr+1)).addClass('b-p0').show().css({'left':0, 'width':0, 'height':opts.pHeight});
  846. b.find('.b-page-'+opts.curr+' .b-wrap').show().css({'width':opts.pWidth-(opts.pagePadding*2), 'height':opts.pHeight-(opts.pagePadding*2), 'padding': opts.pagePadding});
  847. b.find('.b-page-'+(opts.curr+1)+' .b-wrap').show().css({'width':opts.pWidth-(opts.pagePadding*2), 'height':opts.pHeight-(opts.pagePadding*2), 'padding': opts.pagePadding});
  848. pN = b.find('.b-pN');
  849. p0 = b.find('.b-p0');
  850. pNwrap = b.find('.b-pN .b-wrap');
  851. p0wrap = b.find('.b-p0 .b-wrap');
  852. if(lhover){
  853. p0.css({left:10, width:40});
  854. p0wrap.css({right:10});
  855. }
  856. p0.detach().appendTo(src);
  857. if (opts.shadows) {
  858. b.find('.b-shadow-b, .b-shadow-f').remove();
  859. sB = $('<div class="b-shadow-b"></div>').appendTo(p0).css({
  860. 'left': 0,
  861. 'width': opts.pWidth,
  862. 'height': opts.pHeight
  863. });
  864. shadow = sB;
  865. }
  866. }
  867. //update page visibility
  868. //if moving to start and end of book
  869. if(opts.closed){
  870. if(!inc && opts.curr == 0){
  871. pN.hide();
  872. }else if(!inc){
  873. pN.show();
  874. }
  875. if(inc && opts.curr >= opts.pTotal-2){
  876. p4.hide();
  877. }else if(inc){
  878. p4.show();
  879. }
  880. }
  881. //init shadows
  882. if(opts.shadows){
  883. //check for opacity support -> animate shadow overlay on moving slide
  884. if($.support.opacity){
  885. shadow.animate({opacity:1}, opts.speedH, opts.easeIn)
  886. .animate({opacity:0}, opts.speedH, opts.easeOut);
  887. }else{
  888. if(inc){
  889. shadow.animate({right:opts.shadowTopFwdWidth}, opts.speed, opts.easeIn);
  890. }else{
  891. shadow.animate({left:opts.shadowTopBackWidth}, opts.speed, opts.easeIn);
  892. }
  893. }
  894. }
  895. //init position anim
  896. if(opts.closed && opts.autoCenter){
  897. if(opts.curr == 0){
  898. p3.hide();
  899. p4.hide();
  900. b.animate({width:opts.pWidth}, opts.speed, opts.easing);
  901. }else if(opts.curr >= opts.pTotal-2){
  902. p0.hide();
  903. pN.hide();
  904. b.animate({width:opts.pWidth}, opts.speed, opts.easing);
  905. }else{
  906. b.animate({width:opts.width}, opts.speed, opts.easing);
  907. }
  908. }
  909. }
  910. function updateAfter(){
  911. resetPages();
  912. updatePager();
  913. updateCtrls();
  914. opts.after.call(self, opts);
  915. busy = false;
  916. //update auto play timer
  917. if(opts.auto && opts.delay){
  918. if(playing && opts.curr < opts.pTotal-2){
  919. clearTimeout(a);
  920. a = setTimeout(function(){self.next();},opts.delay);
  921. console.log("continue...");
  922. }
  923. if(opts.curr >= opts.pTotal-2){
  924. playing = false;
  925. }
  926. }
  927. }
  928. function updateCtrls(){
  929. //update ctrls, cursors and visibility
  930. if(opts.overlays || opts.tabs || opts.arrows){
  931. if($.support.opacity){
  932. if(opts.curr < opts.pTotal-2){
  933. ctrlsN.fadeIn('fast').css('cursor',opts.cursor);
  934. }else{
  935. ctrlsN.fadeOut('fast').css('cursor','default');
  936. }
  937. if(opts.curr >= 2 && opts.curr != 0){
  938. ctrlsP.fadeIn('fast').css('cursor',opts.cursor);
  939. }else{
  940. ctrlsP.fadeOut('fast').css('cursor','default');
  941. }
  942. }else{
  943. if(opts.curr < opts.pTotal-2){
  944. ctrlsN.show().css('cursor',opts.cursor);
  945. }else{
  946. ctrlsN.hide().css('cursor','default');
  947. }
  948. if(opts.curr >= 2 && opts.curr != 0){
  949. ctrlsP.show().css('cursor',opts.cursor);
  950. }else{
  951. ctrlsP.hide().css('cursor','default');
  952. }
  953. }
  954. }
  955. }
  956. function updatePager(){
  957. if(opts.pageSelector){
  958. if(opts.direction == 'RTL'){
  959. nums = (Math.abs(opts.curr - opts.pTotal)-1) +' - '+ ((Math.abs(opts.curr - opts.pTotal)));
  960. if(opts.closed){
  961. if(opts.curr==opts.pTotal-2){nums='1'}
  962. else if(opts.curr==0){nums=opts.pTotal-2}
  963. else{nums = (Math.abs(opts.curr - opts.pTotal)-2) +' - '+ ((Math.abs(opts.curr - opts.pTotal)-1));}
  964. if(opts.covers){
  965. if(opts.curr==opts.pTotal-2){nums=''}
  966. else if(opts.curr==0){nums=''}
  967. else{nums = (Math.abs(opts.curr - opts.pTotal)-3) +' - '+ ((Math.abs(opts.curr - opts.pTotal)-2));}
  968. }
  969. }
  970. $(opts.menu+' .b-selector-page .b-current').text(nums);
  971. }else{
  972. nums = (opts.curr+1) +' - '+ (opts.curr+2);
  973. if(opts.closed){
  974. if(opts.curr==0){nums='1'}
  975. else if(opts.curr==opts.pTotal-2){nums=opts.pTotal-2}
  976. else {nums = (opts.curr) +'-'+ (opts.curr+1);}
  977. if(opts.covers){
  978. if(opts.curr==0){nums=''}
  979. else if(opts.curr==opts.pTotal-2){nums=''}
  980. else {nums = (opts.curr-1) +'-'+ (opts.curr);}
  981. }
  982. }
  983. $(opts.menu+' .b-selector-page .b-current').text(nums);
  984. }
  985. }
  986. if(opts.chapterSelector){
  987. if(chapters[opts.curr]!=""){
  988. $(opts.menu+' .b-selector-chapter .b-current').text(chapters[opts.curr]);
  989. }else if(chapters[opts.curr+1]!=""){
  990. $(opts.menu+' .b-selector-chapter .b-current').text(chapters[opts.curr+1]);
  991. }
  992. if(opts.direction == 'RTL' && chapters[opts.curr+1]!=""){
  993. $(opts.menu+' .b-selector-chapter .b-current').text(chapters[opts.curr+1]);
  994. }else if(chapters[opts.curr]!=""){
  995. $(opts.menu+' .b-selector-chapter .b-current').text(chapters[opts.curr]);
  996. }
  997. }
  998. }
  999. function setupHash(){
  1000. hash = getHashNum();
  1001. if(!isNaN(hash) && hash <= opts.pTotal-1 && hash >= 0 && hash != ''){
  1002. if((hash % 2) != 0){
  1003. hash--;
  1004. }
  1005. opts.curr = hash;
  1006. }else{
  1007. updateHash(opts.curr+1, opts);
  1008. }
  1009. self.hash = hash;
  1010. }
  1011. function pollHash(){
  1012. hash = getHashNum();
  1013. //check page num
  1014. if(!isNaN(hash) && hash <= opts.pTotal-1 && hash >= 0){
  1015. if(hash != opts.curr && hash.toString()!=self.hash){
  1016. if((hash % 2) != 0){hash--};
  1017. document.title = opts.name + " - Page "+ (hash+1);
  1018. if(!busy){
  1019. self.gotoPage(hash);
  1020. self.hash = hash;
  1021. }
  1022. }
  1023. }
  1024. }
  1025. //get page number from hash tag, last element
  1026. function getHashNum(){
  1027. var hash = window.location.hash.split('/');
  1028. if(hash.length > 1){
  1029. return parseInt(hash[2])-1;
  1030. }else{
  1031. return '';
  1032. }
  1033. }
  1034. //set the hash
  1035. function updateHash(hash, opts){
  1036. if(opts.hash){
  1037. window.location.hash = "/page/" + hash;
  1038. }
  1039. }
  1040. }
  1041. //define empty array to hold API references
  1042. $.fn.booklet.interfaces = [];
  1043. //define default options
  1044. $.fn.booklet.defaults = {
  1045. name: null, // name of the booklet to display in the document title bar
  1046. width: 600, // container width
  1047. height: 400, // container height
  1048. speed: 1000, // speed of the transition between pages
  1049. direction: 'LTR', // direction of the overall content organization, default LTR, left to right, can be RTL for languages which read right to left
  1050. startingPage: 0, // index of the first page to be displayed
  1051. easing: 'easeInOutQuad', // easing method for complete transition
  1052. easeIn: 'easeInQuad', // easing method for first half of transition
  1053. easeOut: 'easeOutQuad', // easing method for second half of transition
  1054. closed: false, // start with the book "closed", will add empty pages to beginning and end of book
  1055. closedFrontTitle: null, // used with "closed", "menu" and "pageSelector", determines title of blank starting page
  1056. closedFrontChapter: null, // used with "closed", "menu" and "chapterSelector", determines chapter name of blank starting page
  1057. closedBackTitle: null, // used with "closed", "menu" and "pageSelector", determines chapter name of blank ending page
  1058. closedBackChapter: null, // used with "closed", "menu" and "chapterSelector", determines chapter name of blank ending page
  1059. covers: false, // used with "closed", makes first and last pages into covers, without page numbers (if enabled)
  1060. autoCenter: false, // used with "closed", makes book position in center of container when closed
  1061. pagePadding: 10, // padding for each page wrapper
  1062. pageNumbers: true, // display page numbers on each page
  1063. manual: true, // enables manual page turning, requires jQuery UI to function
  1064. hovers: true, // enables preview pageturn hover animation, shows a small preview of previous or next page on hover
  1065. overlays: true, // enables navigation using a page sized overlay, when enabled links inside the content will not be clickable
  1066. tabs: false, // adds tabs along the top of the pages
  1067. tabWidth: 60, // set the width of the tabs
  1068. tabHeight: 20, // set the height of the tabs
  1069. arrows: false, // adds arrows overlayed over the book edges
  1070. arrowsHide: false, // auto hides arrows when controls are not hovered
  1071. cursor: 'pointer', // cursor css setting for side bar areas
  1072. hash: false, // enables navigation using a hash string, ex: #/page/1 for page 1, will affect all booklets with 'hash' enabled
  1073. keyboard: true, // enables navigation with arrow keys (left: previous, right: next)
  1074. next: null, // selector for element to use as click trigger for next page
  1075. prev: null, // selector for element to use as click trigger for previous page
  1076. auto: false, // enables automatic navigation, requires "delay"
  1077. delay: 5000, // amount of time between automatic page flipping
  1078. pause: null, // selector for element to use as click trigger for pausing auto page flipping
  1079. play: null, // selector for element to use as click trigger for restarting auto page flipping
  1080. menu: null, // selector for element to use as the menu area, required for 'pageSelector'
  1081. pageSelector: false, // enables navigation with a dropdown menu of pages, requires 'menu'
  1082. chapterSelector: false, // enables navigation with a dropdown menu of chapters, determined by the "rel" attribute, requires 'menu'
  1083. shadows: true, // display shadows on page animations
  1084. shadowTopFwdWidth: 166, // shadow width for top forward anim
  1085. shadowTopBackWidth: 166, // shadow width for top back anim
  1086. shadowBtmWidth: 50, // shadow width for bottom shadow
  1087. before: function(){}, // callback invoked before each page turn animation
  1088. after: function(){} // callback invoked after each page turn animation
  1089. }
  1090. })(jQuery);