PageRenderTime 64ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/jquery.mobile.splitview.js

https://bitbucket.org/webcred/brizinga
JavaScript | 624 lines | 435 code | 71 blank | 118 comment | 123 complexity | f5fd13e975ed9b5bd496aba32a022ccd MD5 | raw file
  1. // TODO: reinstate replaceBackBtn - to include the case where people actually really want the back btn
  2. (function($,window,undefined){
  3. $( window.document ).bind('mobileinit', function(){
  4. //some class for css to detect touchscreens
  5. if($.support.touch){
  6. $('html').addClass('touch');
  7. }
  8. var $query = $.mobile.media('screen and (min-width: 480px)') && ($.mobile.media('(-webkit-max-device-pixel-ratio: 1.2)') || $.mobile.media('(max--moz-device-pixel-ratio: 1.2)'));
  9. $.support.splitview = ($query || ($.mobile.browser.ie && $(this).width() >= 480)) && $.mobile.ajaxEnabled;
  10. if ($.support.splitview) {
  11. $('html').addClass('splitview');
  12. //on window.ready() execution:
  13. $(function() {
  14. $(document).unbind('.toolbar');
  15. $('.ui-page').die('.toolbar');
  16. $('div:jqmData(role="panel")').addClass('ui-mobile-viewport ui-panel');
  17. var firstPageMain=$('div:jqmData(id="main") > div:jqmData(role="page"):first');
  18. if( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ){
  19. var $container=$('div:jqmData(id="main")');
  20. $.mobile.firstPage = firstPageMain;
  21. $.mobile.changePage(firstPageMain, {transition:'none', changeHash:false, pageContainer:$container});
  22. $.mobile.activePage=undefined;
  23. } //no need to trigger a hashchange here cause the other page is handled by core.
  24. // setup the layout for splitview and jquerymobile will handle first page init
  25. $(window).trigger('orientationchange');
  26. setTimeout(function(){
  27. $.mobile.firstPage = firstPageMain;
  28. }, 100)
  29. }); //end window.ready()
  30. //----------------------------------------------------------------------------------
  31. //Main event bindings: click, form submits, hashchange and orientationchange/resize(popover)
  32. //----------------------------------------------------------------------------------
  33. //existing base tag?
  34. var $window = $( window ),
  35. $html = $( 'html' ),
  36. $head = $( 'head' ),
  37. $base = $head.children( "base" ),
  38. //tuck away the original document URL minus any fragment.
  39. documentUrl = $.mobile.path.parseUrl( location.href ),
  40. //if the document has an embedded base tag, documentBase is set to its
  41. //initial value. If a base tag does not exist, then we default to the documentUrl.
  42. documentBase = $base.length ? $.mobile.path.parseUrl( $.mobile.path.makeUrlAbsolute( $base.attr( "href" ), documentUrl.href ) ) : documentUrl;
  43. function findClosestLink(ele)
  44. {
  45. while (ele){
  46. if (ele.nodeName.toLowerCase() == "a"){
  47. break;
  48. }
  49. ele = ele.parentNode;
  50. }
  51. return ele;
  52. }
  53. // The base URL for any given element depends on the page it resides in.
  54. function getClosestBaseUrl( ele )
  55. {
  56. // Find the closest page and extract out its url.
  57. var url = $( ele ).closest( ".ui-page" ).jqmData( "url" ),
  58. base = documentBase.hrefNoHash;
  59. if ( !url || !$.mobile.path.isPath( url ) ) {
  60. url = base;
  61. }
  62. return $.mobile.path.makeUrlAbsolute( url, base);
  63. }
  64. //simply set the active page's minimum height to screen height, depending on orientation
  65. function getScreenHeight(){
  66. var orientation = jQuery.event.special.orientationchange.orientation(),
  67. port = orientation === "portrait",
  68. winMin = port ? 480 : 320,
  69. screenHeight = port ? screen.availHeight : screen.availWidth,
  70. winHeight = Math.max( winMin, $( window ).height() ),
  71. pageMin = Math.min( screenHeight, winHeight );
  72. return pageMin;
  73. }
  74. function newResetActivePageHeight(){
  75. var page=$( "." + $.mobile.activePageClass );
  76. page.each(function(){
  77. if($(this).closest(".panel-popover").length != 1){
  78. $(this).css("min-height", getScreenHeight());
  79. }
  80. else {
  81. $(this).css("min-height", "100%")
  82. }
  83. });
  84. }
  85. //override _registerInternalEvents to bind to new methods below
  86. $.mobile._registerInternalEvents = function(){
  87. //DONE: bind form submit with this plugin
  88. $("form").live('submit', function(event){
  89. var $this = $( this );
  90. if( !$.mobile.ajaxEnabled ||
  91. $this.is( ":jqmData(ajax='false')" ) ){ return; }
  92. var type = $this.attr("method"),
  93. target = $this.attr("target"),
  94. url = $this.attr( "action" ),
  95. $currPanel=$this.parents('div:jqmData(role="panel")'),
  96. $currPanelActivePage=$currPanel.children('div.'+$.mobile.activePageClass);
  97. // If no action is specified, browsers default to using the
  98. // URL of the document containing the form. Since we dynamically
  99. // pull in pages from external documents, the form should submit
  100. // to the URL for the source document of the page containing
  101. // the form.
  102. if ( !url ) {
  103. // Get the @data-url for the page containing the form.
  104. url = getClosestBaseUrl( $this );
  105. if ( url === documentBase.hrefNoHash ) {
  106. // The url we got back matches the document base,
  107. // which means the page must be an internal/embedded page,
  108. // so default to using the actual document url as a browser
  109. // would.
  110. url = documentUrl.hrefNoSearch;
  111. }
  112. }
  113. url = $.mobile.path.makeUrlAbsolute( url, getClosestBaseUrl($this) );
  114. //external submits use regular HTTP
  115. if( $.mobile.path.isExternal( url ) || target ) {
  116. return;
  117. }
  118. //temporarily put this here- eventually shud just set it immediately instead of an interim var.
  119. $.mobile.activePage=$currPanelActivePage;
  120. // $.mobile.pageContainer=$currPanel;
  121. $.mobile.changePage(
  122. url,
  123. {
  124. type: type && type.length && type.toLowerCase() || "get",
  125. data: $this.serialize(),
  126. transition: $this.jqmData("transition"),
  127. direction: $this.jqmData("direction"),
  128. reloadPage: true,
  129. pageContainer:$currPanel
  130. }
  131. );
  132. event.preventDefault();
  133. });
  134. //add active state on vclick
  135. $( document ).bind( "vclick", function( event ) {
  136. var link = findClosestLink( event.target );
  137. if ( link ) {
  138. if ( $.mobile.path.parseUrl( link.getAttribute( "href" ) || "#" ).hash !== "#" ) {
  139. $( link ).closest( ".ui-btn" ).not( ".ui-disabled" ).addClass( $.mobile.activeBtnClass );
  140. $( "." + $.mobile.activePageClass + " .ui-btn" ).not( link ).blur();
  141. }
  142. }
  143. });
  144. //DONE: link click event binding for changePage
  145. //click routing - direct to HTTP or Ajax, accordingly
  146. $(document).bind( "click", function(event) {
  147. var link = findClosestLink(event.target);
  148. if (!link){
  149. return;
  150. }
  151. var $link = $(link),
  152. //remove active link class if external (then it won't be there if you come back)
  153. httpCleanup = function(){
  154. window.setTimeout( function() { removeActiveLinkClass( true ); }, 200 );
  155. };
  156. //if there's a data-rel=back attr, go back in history
  157. if( $link.is( ":jqmData(rel='back')" ) ) {
  158. window.history.back();
  159. return false;
  160. }
  161. //if ajax is disabled, exit early
  162. if( !$.mobile.ajaxEnabled ){
  163. httpCleanup();
  164. //use default click handling
  165. return;
  166. }
  167. var baseUrl = getClosestBaseUrl( $link ),
  168. //get href, if defined, otherwise fall to null #
  169. href = $.mobile.path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );
  170. // XXX_jblas: Ideally links to application pages should be specified as
  171. // an url to the application document with a hash that is either
  172. // the site relative path or id to the page. But some of the
  173. // internal code that dynamically generates sub-pages for nested
  174. // lists and select dialogs, just write a hash in the link they
  175. // create. This means the actual URL path is based on whatever
  176. // the current value of the base tag is at the time this code
  177. // is called. For now we are just assuming that any url with a
  178. // hash in it is an application page reference.
  179. if ( href.search( "#" ) != -1 ) {
  180. href = href.replace( /[^#]*#/, "" );
  181. if ( !href ) {
  182. //link was an empty hash meant purely
  183. //for interaction, so we ignore it.
  184. event.preventDefault();
  185. return;
  186. } else if ( $.mobile.path.isPath( href ) ) {
  187. //we have apath so make it the href we want to load.
  188. href = $.mobile.path.makeUrlAbsolute( href, baseUrl );
  189. } else {
  190. //we have a simple id so use the documentUrl as its base.
  191. href = $.mobile.path.makeUrlAbsolute( "#" + href, documentUrl.hrefNoHash );
  192. }
  193. }
  194. // Should we handle this link, or let the browser deal with it?
  195. var useDefaultUrlHandling = $link.is( "[rel='external']" ) || $link.is( ":jqmData(ajax='false')" ) || $link.is( "[target]" ),
  196. // Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
  197. // requests if the document doing the request was loaded via the file:// protocol.
  198. // This is usually to allow the application to "phone home" and fetch app specific
  199. // data. We normally let the browser handle external/cross-domain urls, but if the
  200. // allowCrossDomainPages option is true, we will allow cross-domain http/https
  201. // requests to go through our page loading logic.
  202. isCrossDomainPageLoad = ( $.mobile.allowCrossDomainPages && documentUrl.protocol === "file:" && href.search( /^https?:/ ) != -1 ),
  203. //check for protocol or rel and its not an embedded page
  204. //TODO overlap in logic from isExternal, rel=external check should be
  205. // moved into more comprehensive isExternalLink
  206. isExternal = useDefaultUrlHandling || ( $.mobile.path.isExternal( href ) && !isCrossDomainPageLoad ),
  207. isRefresh=$link.jqmData('refresh'),
  208. $targetPanel=$link.jqmData('panel'),
  209. $targetContainer=$('div:jqmData(id="'+$targetPanel+'")'),
  210. $targetPanelActivePage=$targetContainer.children('div.'+$.mobile.activePageClass),
  211. $currPanel=$link.parents('div:jqmData(role="panel")'),
  212. //not sure we need this. if you want the container of the element that triggered this event, $currPanel
  213. $currContainer=$.mobile.pageContainer,
  214. $currPanelActivePage=$currPanel.children('div.'+$.mobile.activePageClass),
  215. url=$.mobile.path.stripHash($link.attr("href")),
  216. from = null;
  217. //still need this hack apparently:
  218. $('.ui-btn.'+$.mobile.activeBtnClass).removeClass($.mobile.activeBtnClass);
  219. $activeClickedLink = $link.closest( ".ui-btn" ).addClass($.mobile.activeBtnClass);
  220. if( isExternal ) {
  221. httpCleanup();
  222. //use default click handling
  223. return;
  224. }
  225. //use ajax
  226. var transitionVal = $link.jqmData( "transition" ),
  227. direction = $link.jqmData("direction"),
  228. reverseVal = (direction && direction === "reverse") ||
  229. // deprecated - remove by 1.0
  230. $link.jqmData( "back" ),
  231. //this may need to be more specific as we use data-rel more
  232. role = $link.attr( "data-" + $.mobile.ns + "rel" ) || undefined,
  233. hash = $currPanel.jqmData('hash');
  234. //if link refers to an already active panel, stop default action and return
  235. if ($targetPanelActivePage.attr('data-url') == url || $currPanelActivePage.attr('data-url') == url) {
  236. if (isRefresh) { //then changePage below because it's a pageRefresh request
  237. $.mobile.changePage(href, {fromPage:from, transition:'fade', reverse:reverseVal, changeHash:false, pageContainer:$targetContainer, reloadPage:isRefresh});
  238. }
  239. else { //else preventDefault and return
  240. event.preventDefault();
  241. return;
  242. }
  243. }
  244. //if link refers to a page on another panel, changePage on that panel
  245. else if ($targetPanel && $targetPanel!=$link.parents('div:jqmData(role="panel")')) {
  246. var from=$targetPanelActivePage;
  247. $.mobile.pageContainer=$targetContainer;
  248. $.mobile.changePage(href, {fromPage:from, transition:transitionVal, reverse:reverseVal, pageContainer:$targetContainer});
  249. }
  250. //if link refers to a page inside the same panel, changePage on that panel
  251. else {
  252. var from=$currPanelActivePage;
  253. $.mobile.pageContainer=$currPanel;
  254. var hashChange= (hash == 'false' || hash == 'crumbs')? false : true;
  255. $.mobile.changePage(href, {fromPage:from, transition:transitionVal, reverse:reverseVal, changeHash:hashChange, pageContainer:$currPanel});
  256. //active page must always point to the active page in main - for history purposes.
  257. $.mobile.activePage=$('div:jqmData(id="main") > div.'+$.mobile.activePageClass);
  258. }
  259. event.preventDefault();
  260. });
  261. //prefetch pages when anchors with data-prefetch are encountered
  262. //TODO: insert pageContainer in here!
  263. $( ".ui-page" ).live( "pageshow.prefetch", function(){
  264. var urls = [],
  265. $thisPageContainer = $(this).parents('div:jqmData(role="panel")');
  266. $( this ).find( "a:jqmData(prefetch)" ).each(function(){
  267. var url = $( this ).attr( "href" ),
  268. panel = $(this).jqmData('panel'),
  269. container = panel.length? $('div:jqmData(id="'+panel+'")') : $thisPageContainer;
  270. if ( url && $.inArray( url, urls ) === -1 ) {
  271. urls.push( url );
  272. $.mobile.loadPage( url, {pageContainer: container} );
  273. }
  274. });
  275. });
  276. //DONE: bind hashchange with this plugin
  277. //hashchanges are defined only for the main panel - other panels should not support hashchanges to avoid ambiguity
  278. $.mobile._handleHashChange = function( hash ) {
  279. var to = $.mobile.path.stripHash( hash ),
  280. transition = $.mobile.urlHistory.stack.length === 0 ? "none" : undefined,
  281. $mainPanel=$('div:jqmData(id="main")'),
  282. $mainPanelFirstPage=$mainPanel.children('div:jqmData(role="page"):first'),
  283. $mainPanelActivePage=$mainPanel.children('div.ui-page-active'),
  284. $menuPanel=$('div:jqmData(id="menu")'),
  285. $menuPanelFirstPage=$menuPanel.children('div:jqmData(role="page"):first'),
  286. $menuPanelActivePage=$menuPanel.children('div.ui-page-active'),
  287. //FIX: temp var for dialogHashKey
  288. dialogHashKey = "&ui-state=dialog",
  289. // default options for the changPage calls made after examining the current state
  290. // of the page and the hash
  291. changePageOptions = {
  292. transition: transition,
  293. changeHash: false,
  294. fromHashChange: true,
  295. pageContainer: $mainPanel
  296. };
  297. if( !$.mobile.hashListeningEnabled || $.mobile.urlHistory.ignoreNextHashChange ){
  298. $.mobile.urlHistory.ignoreNextHashChange = false;
  299. return;
  300. }
  301. // special case for dialogs
  302. if( $.mobile.urlHistory.stack.length > 1 && to.indexOf( dialogHashKey ) > -1 ) {
  303. // If current active page is not a dialog skip the dialog and continue
  304. // in the same direction
  305. if(!$.mobile.activePage.is( ".ui-dialog" )) {
  306. //determine if we're heading forward or backward and continue accordingly past
  307. //the current dialog
  308. $.mobile.urlHistory.directHashChange({
  309. currentUrl: to,
  310. isBack: function() { window.history.back(); },
  311. isForward: function() { window.history.forward(); }
  312. });
  313. // prevent changepage
  314. return;
  315. } else {
  316. // var setTo = function() { to = $.mobile.urlHistory.getActive().pageUrl; };
  317. // if the current active page is a dialog and we're navigating
  318. // to a dialog use the dialog objected saved in the stack
  319. // urlHistory.directHashChange({ currentUrl: to, isBack: setTo, isForward: setTo });
  320. urlHistory.directHashChange({
  321. currentUrl: to,
  322. // regardless of the direction of the history change
  323. // do the following
  324. either: function( isBack ) {
  325. var active = $.mobile.urlHistory.getActive();
  326. to = active.pageUrl;
  327. // make sure to set the role, transition and reversal
  328. // as most of this is lost by the domCache cleaning
  329. $.extend( changePageOptions, {
  330. role: active.role,
  331. transition: active.transition,
  332. reverse: isBack
  333. });
  334. }
  335. });
  336. }
  337. }
  338. //if to is defined, load it
  339. if ( to ){
  340. to = ( typeof to === "string" && !$.mobile.path.isPath( to ) ) ? ( $.mobile.path.makeUrlAbsolute( '#' + to, documentBase ) ) : to;
  341. //if this is initial deep-linked page setup, then changePage sidemenu as well
  342. if (!$('div.ui-page-active').length) {
  343. $menuPanelFirstPage='#'+$menuPanelFirstPage.attr('id');
  344. $.mobile.changePage($menuPanelFirstPage, {transition:'none', reverse:true, changeHash:false, fromHashChange:false, pageContainer:$menuPanel});
  345. $.mobile.activePage=undefined;
  346. }
  347. $.mobile.activePage=$mainPanelActivePage.length? $mainPanelActivePage : undefined;
  348. $.mobile.changePage(to, changePageOptions );
  349. } else {
  350. //there's no hash, go to the first page in the main panel.
  351. $.mobile.activePage=$mainPanelActivePage? $mainPanelActivePage : undefined;
  352. $.mobile.changePage( $mainPanelFirstPage, changePageOptions );
  353. }
  354. };
  355. //hashchange event handler
  356. $(window).bind( "hashchange", function( e, triggered ) {
  357. $.mobile._handleHashChange( location.hash );
  358. });
  359. //set page min-heights to be device specific
  360. $( document ).bind( "pageshow.resetPageHeight", newResetActivePageHeight );
  361. $( window ).bind( "throttledresize.resetPageHeight", newResetActivePageHeight );
  362. }; //end _registerInternalEvents
  363. //DONE: bind orientationchange and resize - the popover
  364. _orientationHandler = function(event){
  365. var $menu=$('div:jqmData(id="menu")'),
  366. $main=$('div:jqmData(id="main")'),
  367. $mainHeader=$main.find('div.'+$.mobile.activePageClass+'> div:jqmData(role="header")'),
  368. $window=$(window);
  369. function popoverBtn(header) {
  370. if(!header.children('.popover-btn').length){
  371. if(header.children('a.ui-btn-left').length){
  372. header.children('a.ui-btn-left').replaceWith('<a class="popover-btn">Menu</a>');
  373. header.children('a.popover-btn').addClass('ui-btn-left').buttonMarkup();
  374. }
  375. else{
  376. header.prepend('<a class="popover-btn">Menu</a>');
  377. header.children('a.popover-btn').addClass('ui-btn-left').buttonMarkup()
  378. }
  379. }
  380. }
  381. function replaceBackBtn(header) {
  382. if($.mobile.urlHistory.stack.length > 1 && !header.children('a:jqmData(rel="back")').length && header.jqmData('backbtn')!=false){
  383. header.prepend("<a href='#' class='ui-btn-left' data-"+ $.mobile.ns +"rel='back' data-"+ $.mobile.ns +"icon='arrow-l'>Back</a>" );
  384. header.children('a:jqmData(rel="back")').buttonMarkup();
  385. }
  386. };
  387. function popover(){
  388. $menu.addClass('panel-popover')
  389. .removeClass('ui-panel-left')
  390. .css({'width':'25%', 'min-width':'250px', 'display':'', 'overflow-x':'visible'});
  391. if(!$menu.children('.popover_triangle').length){
  392. $menu.prepend('<div class="popover_triangle"></div>');
  393. }
  394. $menu.children('.' + $.activePageClass).css('min-height', '100%');
  395. $main.removeClass('ui-panel-right')
  396. .css('width', '');
  397. popoverBtn($mainHeader);
  398. $main.undelegate('div:jqmData(role="page")', 'pagebeforeshow.splitview');
  399. $main.delegate('div:jqmData(role="page")','pagebeforeshow.popover', function(){
  400. var $thisHeader=$(this).children('div:jqmData(role="header")');
  401. popoverBtn($thisHeader);
  402. });
  403. // TODO: unbind resetActivePageHeight for popover pages
  404. };
  405. function splitView(){
  406. $menu.removeClass('panel-popover')
  407. .addClass('ui-panel-left')
  408. .css({'width':'25%', 'min-width':'250px', 'display':''});
  409. $menu.children('.popover_triangle').remove();
  410. $main.addClass('ui-panel-right')
  411. .width(function(){
  412. return $(window).width()-$('div:jqmData(id="menu")').width();
  413. });
  414. $mainHeader.children('.popover-btn').remove();
  415. // replaceBackBtn($mainHeader);
  416. $main.undelegate('div:jqmData(role="page")', 'pagebeforeshow.popover');
  417. $main.delegate('div:jqmData(role="page")', 'pagebeforeshow.splitview', function(){
  418. var $thisHeader=$(this).children('div:jqmData(role="header")');
  419. $thisHeader.children('.popover-btn').remove();
  420. // replaceBackBtn($thisHeader);
  421. });
  422. }
  423. if(event.orientation){
  424. if(event.orientation == 'portrait'){
  425. popover();
  426. }
  427. else if(event.orientation == 'landscape') {
  428. splitView();
  429. }
  430. }
  431. else if($window.width() < 768 && $window.width() > 480){
  432. popover();
  433. }
  434. else if($window.width() > 768){
  435. splitView();
  436. }
  437. };
  438. $(window).bind('orientationchange', _orientationHandler);
  439. $(window).bind('throttledresize', _orientationHandler);
  440. //popover button click handler - from http://www.cagintranet.com/archive/create-an-ipad-like-dropdown-popover/
  441. $('.popover-btn').live('click', function(e){
  442. e.preventDefault();
  443. $('.panel-popover').fadeToggle('fast');
  444. if ($('.popover-btn').hasClass($.mobile.activeBtnClass)) {
  445. $('.popover-btn').removeClass($.mobile.activeBtnClass);
  446. } else {
  447. $('.popover-btn').addClass($.mobile.activeBtnClass);
  448. }
  449. });
  450. $('body').live('click', function(event) {
  451. if (!$(event.target).closest('.panel-popover').length && !$(event.target).closest('.popover-btn').length) {
  452. $(".panel-popover").stop(true, true).hide();
  453. $('.popover-btn').removeClass($.mobile.activeBtnClass);
  454. };
  455. });
  456. //----------------------------------------------------------------------------------
  457. //Other event bindings: scrollview, crumbs, data-context and content height adjustments
  458. //----------------------------------------------------------------------------------
  459. //DONE: pageshow binding for scrollview - now using IScroll4! hell yeah!
  460. $('div:jqmData(role="page")').live('pagebeforeshow.scroll', function(event, ui){
  461. if ($.support.touch && !$.support.touchOverflow) {
  462. var $page = $(this),
  463. $scrollArea = $page.find('div:jqmData(role="content")');
  464. $scrAreaChildren = $scrollArea.children();
  465. if ($scrAreaChildren.length > 1) {
  466. $scrAreaChildren = $scrollArea.wrapInner("<div class='scrollable vertical'></div>").children();
  467. }
  468. $scrollArea.css({ 'width':'auto',
  469. 'height':'auto',
  470. 'overflow':'hidden'});
  471. //TODO: if too many pages are in the DOM that have iscroll on, this might slow down the browser significantly,
  472. //in which case we'll need to destroy() the iscroll as the page hides.
  473. $scrollArea.iscroll();
  474. }
  475. });
  476. //data-hash 'crumbs' handler
  477. //now that data-backbtn is no longer defaulting to true, lets set crumbs to create itself even when backbtn is not available
  478. $('div:jqmData(role="page")').live('pagebeforeshow.crumbs', function(event, data){
  479. var $this = $(this);
  480. if($this.jqmData('hash') == 'crumbs' || $this.parents('div:jqmData(role="panel")').data('hash') == 'crumbs'){
  481. if($this.jqmData('hash')!=false && $this.find('.ui-crumbs').length < 1){
  482. var $header=$this.find('div:jqmData(role="header")');
  483. backBtn = $this.find('a:jqmData(rel="back")');
  484. if(data.prevPage.jqmData('url') == $this.jqmData('url')){ //if it's a page refresh
  485. var prevCrumb = data.prevPage.find('.ui-crumbs');
  486. crumbify(backBtn, prevCrumb.attr('href'), prevCrumb.find('.ui-btn-text').html());
  487. }
  488. else if($.mobile.urlHistory.stack.length > 0) {
  489. var text = data.prevPage.find('div:jqmData(role="header") .ui-title').html();
  490. crumbify(backBtn, '#'+data.prevPage.jqmData('url'), text);
  491. }
  492. else if(backBtn.length && $.mobile.urlHistory.stack.length <= 1) {
  493. backBtn.remove();
  494. }
  495. }
  496. }
  497. function crumbify(button, href, text){
  498. if(!button.length) {
  499. $this.find('div:jqmData(role="header")').prepend('<a class="ui-crumbs ui-btn-left" data-icon="arrow-l"></a>');
  500. button=$header.children('.ui-crumbs').buttonMarkup();
  501. }
  502. button.removeAttr('data-rel')
  503. .jqmData('direction','reverse')
  504. .addClass('ui-crumbs')
  505. .attr('href',href);
  506. button.find('.ui-btn-text').html(text);
  507. }
  508. });
  509. //data-context handler - a page with a link that has a data-context attribute will load that page after this page loads
  510. //this still needs work - pageTransitionQueue messes everything up.
  511. $('div:jqmData(role="panel")').live('pagechange.context', function(){
  512. var $this=$(this),
  513. $currPanelActivePage = $this.children('.' + $.mobile.activePageClass),
  514. panelContextSelector = $this.jqmData('context'),
  515. pageContextSelector = $currPanelActivePage.jqmData('context'),
  516. contextSelector= pageContextSelector ? pageContextSelector : panelContextSelector;
  517. //if you pass a hash into data-context, you need to specify panel, url and a boolean value for refresh
  518. if($.type(contextSelector) === 'object') {
  519. var $targetContainer=$('div:jqmData(id="'+contextSelector.panel+'")'),
  520. $targetPanelActivePage=$targetContainer.children('div.'+$.mobile.activePageClass),
  521. isRefresh = contextSelector.refresh === undefined ? false : contextSelector.refresh;
  522. if(($targetPanelActivePage.jqmData('url') == contextSelector.url && contextSelector.refresh)||(!contextSelector.refresh && $targetPanelActivePage.jqmData('url') != contextSelector.url)){
  523. $.mobile.changePage(contextSelector.url, options={transition:'fade', changeHash:false, pageContainer:$targetContainer, reloadPage:isRefresh});
  524. }
  525. }
  526. else if(contextSelector && $currPanelActivePage.find(contextSelector).length){
  527. $currPanelActivePage.find(contextSelector).trigger('click');
  528. }
  529. });
  530. //this measures the height of header and footer and sets content to the appropriate height so
  531. // that no content is concealed behind header and footer
  532. $('div:jqmData(role="page")').live('pageshow.contentHeight', function(){
  533. var $this=$(this),
  534. $header=$this.children(':jqmData(role="header")'),
  535. $footer=$this.children(':jqmData(role="footer")'),
  536. thisHeaderHeight=$header.css('display') == 'none' ? 0 : $header.outerHeight(),
  537. thisFooterHeight=$footer.css('display') == 'none' ? 0 : $footer.outerHeight();
  538. // $this.children(':jqmData(role="content")').css({'top':thisHeaderHeight, 'bottom':thisFooterHeight});
  539. })
  540. //this allows panels to change their widths upon changepage - useful for pages that need a different width than the ones provided.
  541. // $('div:jqmData(role="page")').live('')
  542. }
  543. else {
  544. //removes all panels so the page behaves like a single panel jqm
  545. $(function(){
  546. $('div:jqmData(role="panel")').each(function(){
  547. var $this = $(this);
  548. $this.replaceWith($this.html());
  549. })
  550. });
  551. }
  552. });
  553. })(jQuery,window);