1/*-------------------------------------------------------------------- 2Scripts for creating and manipulating custom menus based on standard <ul> markup 3Version: 3.0, 03.31.2009 4 5By: Maggie Costello Wachs ([email protected]) and Scott Jehl ([email protected]) 6 http://www.filamentgroup.com 7 * reference articles: http://www.filamentgroup.com/lab/jquery_ipod_style_drilldown_menu/ 8 9Copyright (c) 2009 Filament Group 10Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses. 11--------------------------------------------------------------------*/ 12 13 14var allUIMenus = []; 15 16$.fn.menu = function(options){ 17 var caller = this; 18 var options = options; 19 var m = new Menu(caller, options); 20 allUIMenus.push(m); 21 22 $(this) 23 .mousedown(function(){ 24 if (!m.menuOpen) { m.showLoading(); }; 25 }) 26 .click(function(){ 27 if (m.menuOpen == false) { m.showMenu(); } 28 else { m.kill(); }; 29 return false; 30 }); 31}; 32 33function Menu(caller, options){ 34 var menu = this; 35 var caller = $(caller);
36 var container = $('<div class="fg-menu-container ui-widget ui-widget-content ui-corner-all">'+options.content+'</div>'); 37 38 this.menuOpen = false; 39 this.menuExists = false; 40 41 var options = jQuery.extend({ 42 content: null, 43 width: 180, // width of menu container, must be set or passed in to calculate widths of child menus 44 maxHeight: 180, // max height of menu (if a drilldown: height does not include breadcrumb) 45 positionOpts: { 46 posX: 'left', 47 posY: 'bottom', 48 offsetX: 0, 49 offsetY: 0, 50 directionH: 'right', 51 directionV: 'down', 52 detectH: true, // do horizontal collision detection 53 detectV: true, // do vertical collision detection 54 linkToFront: false 55 }, 56 showSpeed: 200, // show/hide speed in milliseconds 57 callerOnState: 'ui-state-active', // class to change the appearance of the link/button when the menu is showing 58 loadingState: 'ui-state-loading', // class added to the link/button while the menu is created 59 linkHover: 'ui-state-hover', // class for menu option hover state 60 linkHoverSecondary: 'li-hover', // alternate class, may be used for multi-level menus 61 // ----- multi-level menu defaults ----- 62 crossSpeed: 200, // cross-fade speed for multi-level menus 63 crumbDefaultText: 'Choose an option:', 64 backLink: true, // in the ipod-style menu: instead of breadcrumbs, show only a 'back' link 65 backLinkText: 'Back', 66 flyOut: false, // multi-level menus are ipod-style by default; this parameter overrides to make a flyout instead 67 flyOutOnState: 'ui-state-default', 68 nextMenuLink: 'ui-icon-triangle-1-e', // class to style the link (specifically, a span within the link) used in the multi-level menu to show the next level 69 topLinkText: 'All', 70 nextCrumbLink: 'ui-icon-carat-1-e' 71 }, options); 72 73 var killAllMenus = function(){ 74 $.each(allUIMenus, function(i){ 75 if (allUIMenus[i].menuOpen) { allUIMenus[i].kill(); }; 76 }); 77 }; 78 79 this.kill = function(){ 80 caller 81 .removeClass(options.loadingState) 82 .removeClass('fg-menu-open') 83 .removeClass(options.callerOnState); 84 container.find('li').removeClass(options.linkHoverSecondary).find('a').removeClass(options.linkHover); 85 if (options.flyOutOnState) { container.find('li a').removeClass(options.flyOutOnState); }; 86 if (options.callerOnState) { caller.removeClass(options.callerOnState); }; 87 if (container.is('.fg-menu-ipod')) { menu.resetDrilldownMenu(); }; 88 if (container.is('.fg-menu-flyout')) { menu.resetFlyoutMenu(); }; 89 container.parent().hide(); 90 menu.menuOpen = false; 91 $(document).unbind('click', killAllMenus); 92 $(document).unbind('keydown'); 93 }; 94 95 this.showLoading = function(){ 96 caller.addClass(options.loadingState); 97 }; 98 99 this.showMenu = function(){ 100 killAllMenus(); 101 if (!menu.menuExists) { menu.create() }; 102 caller 103 .addClass('fg-menu-open') 104 .addClass(options.callerOnState); 105 container.parent().show().click(function(){ menu.kill(); return false; }); 106 container.hide().slideDown(options.showSpeed).find('.fg-menu:eq(0)'); 107 menu.menuOpen = true; 108 caller.removeClass(options.loadingState); 109 $(document).click(killAllMenus); 110 111 // assign key events 112 $(document).keydown(function(event){ 113 var e; 114 if (event.which !="") { e = event.which; } 115 else if (event.charCode != "") { e = event.charCode; } 116 else if (event.keyCode != "") { e = event.keyCode; } 117 118 var menuType = ($(event.target).parents('div').is('.fg-menu-flyout')) ? 'flyout' : 'ipod' ; 119 120 switch(e) { 121 case 37: // left arrow 122 if (menuType == 'flyout') { 123 $(event.target).trigger('mouseout'); 124 if ($('.'+options.flyOutOnState).size() > 0) { $('.'+options.flyOutOnState).trigger('mouseover'); }; 125 }; 126 127 if (menuType == 'ipod') { 128 $(event.target).trigger('mouseout'); 129 if ($('.fg-menu-footer').find('a').size() > 0) { $('.fg-menu-footer').find('a').trigger('click'); }; 130 if ($('.fg-menu-header').find('a').size() > 0) { $('.fg-menu-current-crumb').prev().find('a').trigger('click'); }; 131 if ($('.fg-menu-current').prev().is('.fg-menu-indicator')) { 132 $('.fg-menu-current').prev().trigger('mouseover'); 133 }; 134 }; 135 return false;
136 break; 137 138 case 38: // up arrow 139 if ($(event.target).is('.' + options.linkHover)) { 140 var prevLink = $(event.target).parent().prev().find('a:eq(0)'); 141 if (prevLink.size() > 0) { 142 $(event.target).trigger('mouseout'); 143 prevLink.trigger('mouseover'); 144 }; 145 } 146 else { container.find('a:eq(0)').trigger('mouseover'); } 147 return false; 148 break; 149 150 case 39: // right arrow 151 if ($(event.target).is('.fg-menu-indicator')) { 152 if (menuType == 'flyout') { 153 $(event.target).next().find('a:eq(0)').trigger('mouseover'); 154 } 155 else if (menuType == 'ipod') { 156 $(event.target).trigger('click'); 157 setTimeout(function(){ 158 $(event.target).next().find('a:eq(0)').trigger('mouseover'); 159 }, options.crossSpeed); 160 }; 161 }; 162 return false; 163 break; 164 165 case 40: // down arrow 166 if ($(event.target).is('.' + options.linkHover)) { 167 var nextLink = $(event.target).parent().next().find('a:eq(0)'); 168 if (nextLink.size() > 0) { 169 $(event.target).trigger('mouseout'); 170 nextLink.trigger('mouseover'); 171 }; 172 } 173 else { container.find('a:eq(0)').trigger('mouseover'); } 174 return false; 175 break; 176 177 case 27: // escape 178 killAllMenus(); 179 break; 180 181 case 13: // enter 182 if ($(event.target).is('.fg-menu-indicator') && menuType == 'ipod') { 183 $(event.target).trigger('click'); 184 setTimeout(function(){ 185 $(event.target).next().find('a:eq(0)').trigger('mouseover'); 186 }, options.crossSpeed); 187 }; 188 break; 189 }; 190 }); 191 }; 192 193 this.create = function(){ 194 container.css({ width: options.width }).appendTo('body').find('ul:first').not('.fg-menu-breadcrumb').addClass('fg-menu'); 195 container.find('ul, li a').addClass('ui-corner-all'); 196 197 // aria roles & attributes 198 container.find('ul').attr('role', 'menu').eq(0).attr('aria-activedescendant','active-menuitem').attr('aria-labelledby', caller.attr('id')); 199 container.find('li').attr('role', 'menuitem'); 200 container.find('li:has(ul)').attr('aria-haspopup', 'true').find('ul').attr('aria-expanded', 'false'); 201 container.find('a').attr('tabindex', '-1'); 202 203 // when there are multiple levels of hierarchy, create flyout or drilldown menu 204 if (container.find('ul').size() > 1) { 205 if (options.flyOut) { menu.flyout(container, options); } 206 else { menu.drilldown(container, options); } 207 } 208 else { 209 container.find('a').click(function(){ 210 menu.chooseItem(this); 211 return false; 212 }); 213 }; 214 215 if (options.linkHover) { 216 var allLinks = container.find('.fg-menu li a'); 217 allLinks.hover( 218 function(){ 219 var menuitem = $(this); 220 $('.'+options.linkHover).removeClass(options.linkHover).blur().parent().removeAttr('id'); 221 $(this).addClass(options.linkHover).focus().parent().attr('id','active-menuitem'); 222 }, 223 function(){ 224 $(this).removeClass(options.linkHover).blur().parent().removeAttr('id'); 225 } 226 ); 227 }; 228 229 if (options.linkHoverSecondary) { 230 container.find('.fg-menu li').hover( 231 function(){ 232 $(this).siblings('li').removeClass(options.linkHoverSecondary); 233 if (options.flyOutOnState) { $(this).siblings('li').find('a').removeClass(options.flyOutOnState); } 234 $(this).addClass(options.linkHoverSecondary); 235 }, 236 function(){ $(this).removeClass(options.linkHoverSecondary); } 237 ); 238 }; 239 240 menu.setPosition(container, caller, options); 241 menu.menuExists = true; 242 }; 243 244 this.chooseItem = function(item){ 245 menu.kill(); 246 247 248 //Welche Aktion soll durchgeführt werden? (aktion*tabelle*id) 249 //aRel[0] -> aktion | aRel[1] -> tabelle | aRel[2] -> id 250 var cRel = $(item).attr("rel"); 251 var aRel = cRel.split("*"); 252 console.log(aRel); 253 254 if(aRel[0] == 'check') 255 { 256 jConfirm('Wollen Sie diese Klage wirklich freistellen und somit der Ãffentlichkeit zugänglich machen?', 'Klage freistellen', function(r) 257 { 258 259 if(r) 260 { 261 //Eingabe überprüfen & in Datenbank schreiben 262 jQuery.ajax({ 263 type: "POST", 264 url: "ajax.settings.php", 265 data: {action:aRel[0], table : aRel[1], id : aRel[2] }, 266 dataType: "html" 267 }).done(function( data ) { 268 //Fehlermeldung ausgeben, falls nicht erfolgreich 269 if(data == 0) 270 { 271 $("#status") 272 .addClass("message_red") 273 .html("Fehler beim Freistellen der Klage!") 274 .fadeIn('fast') 275 .delay(3000) 276 .fadeOut('slow'); 277 } 278 else 279 { 280 jAlert('Die Klage wurde erfolgreich freigestellt!'); 281 window.location.reload(); 282 283 } 284 285 }); 286 287 } 288 289 290 }); 291 292 } 293 else if (aRel[0] == 'del') 294 { 295 jConfirm('Wollen Sie diese Klage wirklich UNWIEDERRUFLICH löschen?', 'Klage löschen', function(r) 296 { 297 298 if(r) 299 { 300 //Eingabe überprüfen & in Datenbank schreiben 301 jQuery.ajax({ 302 type: "POST", 303 url: "ajax.settings.php", 304 data: {action:aRel[0], table : aRel[1], id : aRel[2], date:aRel[3] }, 305 dataType: "html" 306 }).done(function( data ) { 307 //Fehlermeldung ausgeben, falls nicht erfolgreich 308 if(data == 0) 309 { 310 $("#status") 311 .addClass("message_red") 312 .html("Fehler beim Löschen der Klage!") 313 .fadeIn('fast') 314 .delay(3000) 315 .fadeOut('slow'); 316 } 317 else 318 { 319 //Alert(data); 320 jAlert('Die Klage wurde erfolgreich gelöscht!'); 321 window.location.reload(); 322 323 } 324 325 }); 326 327 } 328 329 }); 330 } 331 else if (aRel[0] == 'copy') 332 { 333 jConfirm('Wollen Sie diese Klage wirklich kopieren?', 'Klage kopieren', function(r) 334 { 335 336 if(r) 337 { 338 //Eingabe überprüfen & in Datenbank schreiben 339 jQuery.ajax({ 340 type: "POST", 341 url: "ajax.settings.php", 342 data: {action:aRel[0], table : aRel[1], id : aRel[2] }, 343 dataType: "html" 344 }).done(function( data ) { 345 //Fehlermeldung ausgeben, falls nicht erfolgreich 346 if(data == 0) 347 { 348 $("#status") 349 .addClass("message_red") 350 .html("Fehler beim Kopieren der Klage!") 351 .fadeIn('fast') 352 .delay(3000) 353 .fadeOut('slow'); 354 } 355 else 356 { 357 jAlert('Die Klage wurde erfolgreich kopiert!'); 358 window.location.reload(); 359 360 } 361 362 }); 363 364 } 365 366 }); 367 } 368 else if (aRel[0] == 'order') 369 { 370 371 /*jPrompt('Reihenfolge-Nr:', '0', 'Reihenfolge ändern', function(r) { 372 if( r ) alert('You entered ' + r); 373 });*/ 374 375 jAlert('Die Reihenfolge wird durch das abgedruckte Datum festgelegt!<br/> Um die Reihenfolge zu ändern, mutieren Sie das entsprechende Datum <br/><b>in absteigender Reihenfolge</b>.', 'Reihenfolge ändern'); 376 377 } 378 else if (aRel[0] == 'lock') 379 { 380 jConfirm('Wollen Sie diese Klage wirklich SPERREN und somit der Ãffentlichkeit nicht mehr zugänglich machen?', 'Klage sperren', function(r) 381 { 382 383 if(r) 384 { 385 //Eingabe überprüfen & in Datenbank schreiben 386 jQuery.ajax({ 387 type: "POST", 388 url: "ajax.settings.php", 389 data: {action:aRel[0], table : aRel[1], id : aRel[2] }, 390 dataType: "html" 391 }).done(function( data ) { 392 //Fehlermeldung ausgeben, falls nicht erfolgreich 393 if(data == 0) 394 { 395 $("#status") 396 .addClass("message_red") 397 .html("Fehler beim Sperren der Klage!") 398 .fadeIn('fast') 399 .delay(3000) 400 .fadeOut('slow'); 401 } 402 else 403 { 404 jAlert('Die Klage wurde erfolgreich gesperrt!'); 405 window.location.reload(); 406 407 } 408 409 }); 410 411 } 412 413 414 415 }); 416 417 } 418 else if (aRel[0] == 'edit') 419 { 420 //Eingabe überprüfen & in Datenbank schreiben 421 jQuery.ajax({ 422 type: "POST", 423 url: "ajax.settings.php", 424 data: {action:aRel[0], table : aRel[1], id : aRel[2] }, 425 dataType: "html" 426 }).done(function( data ) { 427 //Fehlermeldung ausgeben, falls nicht erfolgreich 428 if(data == 0) 429 { 430 $("#status") 431 .addClass("message_red") 432 .html("Fehler beim Bearbeiten des Elementes!") 433 .fadeIn('fast') 434 .delay(3000) 435 .fadeOut('slow'); 436 } 437 else 438 { 439 //jAlert('Die Klage wurde erfolgreich angepasst!'); 440 window.location.reload(); 441 442 } 443 }); 444 } 445 else if (aRel[0] == 'setVimeoId') 446 { 447 bootbox.prompt("Gib die Vimeo-ID ein!", function(result){ 448 var retVal = true; 449 var tempResult = $.trim(result); 450 451 if(tempResult.length > 0) 452 { 453 if(!isNaN(parseInt(tempResult))) 454 { 455 $.ajax({ 456 type: "POST", 457 url: "ajax.settings.php", 458 data: { action:"setVimeoId", 459 json:Helper.Encoding.JSON.Encode({ 460 vidId: aRel[1], 461 vimeoId: parseInt(tempResult) 462 }) 463 }, 464 success: function(data){ 465 if(!(1*data)){ 466 bootbox.alert('<span style="color:red;font-weight:bold">Leider konnte die Vimeo-ID nicht gespeichert werden. Versuche es erneut!</span>'); 467 } 468 } 469 }) 470 }else{ 471 bootbox.alert('<span style="color:red;font-weight:bold">
471Das ist leider keine ID. Versuche es nocheinmals!</span>'); 472 retVal = false; 473 } 474 } 475 return retVal; 476 }); 477 } 478 else if (aRel[0] == 'setYouTubeId') 479 { 480 bootbox.prompt("Gib den YouTube Kurzlink zu dieser Kla.TV Sendung ein!", function(result){ 481 var retVal = true; 482 var tempResult = $.trim(result); 483 if(tempResult.length > 0) 484 { 485 $.ajax({ 486 type: "POST", 487 url: "ajax.settings.php", 488 data: { action:"setYouTubeId", 489 json:Helper.Encoding.JSON.Encode({ 490 vidId: aRel[1], 491 youTubeShortLink: tempResult 492 }) 493 }, 494 success: function(data){ 495 if(!(1*data)){ 496 bootbox.alert('<span style="color:red;font-weight:bold">
496Diese Eingabe ist leider kein YouTube Link. Versuche es nocheinmal!</span>'); 497 retVal = false; 498 } 499 else{ 500 bootbox.alert('<span style="color:green;font-weight:bold">Super. Diese Eingabe ist ein YouTube Link. Vielen Dank für deine Mithilfe!</span>'); 501 } 502 } 503 504 }) 505 } 506 return retVal; 507 }); 508 } 509 510 511 //$('#menuSelection').text($(item).text()); 512 513 //Seite neu laden, damit neue Einträge sichtbar werden 514 //window.location.reload(); 515 }; 516}; 517 518 519Menu.prototype.flyout = function(container, options) { 520 var menu = this; 521 522 this.resetFlyoutMenu = function(){ 523 var allLists = container.find('ul ul'); 524 allLists.removeClass('ui-widget-content').hide(); 525 }; 526 527 container.addClass('fg-menu-flyout').find('li:has(ul)').each(function(){ 528 var linkWidth = container.width(); 529 var showTimer, hideTimer; 530 var allSubLists = $(this).find('ul'); 531 532 allSubLists.css({ left: linkWidth, width: linkWidth }).hide(); 533 534 $(this).find('a:eq(0)').addClass('fg-menu-indicator').html('<span>' + $(this).find('a:eq(0)').text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>').hover( 535 function(){ 536 clearTimeout(hideTimer); 537 var subList = $(this).next(); 538 if (!fitVertical(subList, $(this).offset().top)) { subList.css({ top: 'auto', bottom: 0 }); }; 539 if (!fitHorizontal(subList, $(this).offset().left + 100)) { subList.css({ left: 'auto', right: linkWidth, 'z-index': 999 }); }; 540 showTimer = setTimeout(function(){ 541 subList.addClass('ui-widget-content').show(options.showSpeed).attr('aria-expanded', 'true'); 542 }, 300); 543 }, 544 function(){ 545 clearTimeout(showTimer); 546 var subList = $(this).next(); 547 hideTimer = setTimeout(function(){ 548 subList.removeClass('ui-widget-content').hide(options.showSpeed).attr('aria-expanded', 'false'); 549 }, 400); 550 } 551 ); 552 553 $(this).find('ul a').hover( 554 function(){ 555 clearTimeout(hideTimer); 556 if ($(this).parents('ul').prev().is('a.fg-menu-indicator')) { 557 $(this).parents('ul').prev().addClass(options.flyOutOnState); 558 } 559 }, 560 function(){ 561 hideTimer = setTimeout(function(){ 562 allSubLists.hide(options.showSpeed); 563 container.find(options.flyOutOnState).removeClass(options.flyOutOnState); 564 }, 500); 565 } 566 ); 567 }); 568 569 container.find('a').click(function(){ 570 menu.chooseItem(this); 571 return false; 572 }); 573}; 574 575 576Menu.prototype.drilldown = function(container, options) { 577 var menu = this; 578 var topList = container.find('.fg-menu'); 579 var breadcrumb = $('<ul class="fg-menu-breadcrumb ui-widget-header ui-corner-all ui-helper-clearfix"></ul>'); 580 var crumbDefaultHeader = $('<li class="fg-menu-breadcrumb-text">'+options.crumbDefaultText+'</li>'); 581 var firstCrumbText = (options.backLink) ? options.backLinkText : options.topLinkText; 582 var firstCrumbClass = (options.backLink) ? 'fg-menu-prev-list' : 'fg-menu-all-lists'; 583 var firstCrumbLinkClass = (options.backLink) ? 'ui-state-default ui-corner-all' : ''; 584 var firstCrumbIcon = (options.backLink) ? '<span class="ui-icon ui-icon-triangle-1-w"></span>' : ''; 585 var firstCrumb = $('<li class="'+firstCrumbClass+'"><a href="#" class="'+firstCrumbLinkClass+'">'+firstCrumbIcon+firstCrumbText+'</a></li>'); 586 587 container.addClass('fg-menu-ipod'); 588 589 if (options.backLink) { breadcrumb.addClass('fg-menu-footer').appendTo(container).hide(); } 590 else { breadcrumb.addClass('fg-menu-header').prependTo(container); }; 591 breadcrumb.append(crumbDefaultHeader); 592 593 var checkMenuHeight = function(el){ 594 if (el.height() > options.maxHeight) { el.addClass('fg-menu-scroll') }; 595 el.css({ height: options.maxHeight }); 596 }; 597 598 var resetChildMenu = function(el){ el.removeClass('fg-menu-scroll').removeClass('fg-menu-current').height('auto'); }; 599 600 this.resetDrilldownMenu = function(){ 601 $('.fg-menu-current').removeClass('fg-menu-current'); 602 topList.animate({ left: 0 }, options.crossSpeed, function(){ 603 $(this).find('ul').each(function(){ 604 $(this).hide(); 605 resetChildMenu($(this)); 606 });
607 topList.addClass('fg-menu-current'); 608 }); 609 $('.fg-menu-all-lists').find('span').remove(); 610 breadcrumb.empty().append(crumbDefaultHeader); 611 $('.fg-menu-footer').empty().hide(); 612 checkMenuHeight(topList); 613 }; 614 615 topList 616 .addClass('fg-menu-content fg-menu-current ui-widget-content ui-helper-clearfix') 617 .css({ width: container.width() }) 618 .find('ul') 619 .css({ width: container.width(), left: container.width() }) 620 .addClass('ui-widget-content') 621 .hide(); 622 checkMenuHeight(topList); 623 624 topList.find('a').each(function(){ 625 // if the link opens a child menu: 626 if ($(this).next().is('ul')) { 627 $(this) 628 .addClass('fg-menu-indicator') 629 .each(function(){ $(this).html('<span>' + $(this).text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>'); }) 630 .click(function(){ // ----- show the next menu 631 var nextList = $(this).next(); 632 var parentUl = $(this).parents('ul:eq(0)'); 633 var parentLeft = (parentUl.is('.fg-menu-content')) ? 0 : parseFloat(topList.css('left')); 634 var nextLeftVal = Math.round(parentLeft - parseFloat(container.width())); 635 var footer = $('.fg-menu-footer'); 636 637 // show next menu 638 resetChildMenu(parentUl); 639 checkMenuHeight(nextList); 640 topList.animate({ left: nextLeftVal }, options.crossSpeed); 641 nextList.show().addClass('fg-menu-current').attr('aria-expanded', 'true'); 642 643 var setPrevMenu = function(backlink){ 644 var b = backlink; 645 var c = $('.fg-menu-current'); 646 var prevList = c.parents('ul:eq(0)'); 647 c.hide().attr('aria-expanded', 'false'); 648 resetChildMenu(c); 649 checkMenuHeight(prevList); 650 prevList.addClass('fg-menu-current').attr('aria-expanded', 'true'); 651 if (prevList.hasClass('fg-menu-content')) { b.remove(); footer.hide(); }; 652 }; 653 654 // initialize "back" link 655 if (options.backLink) { 656 if (footer.find('a').size() == 0) { 657 footer.show(); 658 $('<a href="#"><span class="ui-icon ui-icon-triangle-1-w"></span> <span>Back</span></a>') 659 .appendTo(footer) 660 .click(function(){ // ----- show the previous menu 661 var b = $(this); 662 var prevLeftVal = parseFloat(topList.css('left')) + container.width(); 663 topList.animate({ left: prevLeftVal }, options.crossSpeed, function(){ 664 setPrevMenu(b); 665 }); 666 return false; 667 }); 668 } 669 } 670 // or initialize top breadcrumb 671 else { 672 if (breadcrumb.find('li').size() == 1){ 673 breadcrumb.empty().append(firstCrumb); 674 firstCrumb.find('a').click(function(){ 675 menu.resetDrilldownMenu(); 676 return false; 677 }); 678 } 679 $('.fg-menu-current-crumb').removeClass('fg-menu-current-crumb'); 680 var crumbText = $(this).find('span:eq(0)').text(); 681 var newCrumb = $('<li class="fg-menu-current-crumb"><a href="javascript://" class="fg-menu-crumb">'+crumbText+'</a></li>'); 682 newCrumb 683 .appendTo(breadcrumb) 684 .find('a').click(function(){ 685 if ($(this).parent().is('.fg-menu-current-crumb')){ 686 menu.chooseItem(this); 687 } 688 else { 689 var newLeftVal = - ($('.fg-menu-current').parents('ul').size() - 1) * 180; 690 topList.animate({ left: newLeftVal }, options.crossSpeed, function(){ 691 setPrevMenu(); 692 }); 693 694 // make this the current crumb, delete all breadcrumbs after this one, and navigate to the relevant menu 695 $(this).parent().addClass('fg-menu-current-crumb').find('span').remove(); 696 $(this).parent().nextAll().remove(); 697 }; 698 return false; 699 }); 700 newCrumb.prev().append(' <span class="ui-icon '+options.nextCrumbLink+'"></span>'); 701 }; 702 return false; 703 }); 704 } 705 // if the link is a leaf node (doesn't open a child menu) 706 else { 707 $(this).click(function(){ 708 menu.chooseItem(this); 709 return false; 710 }); 711 }; 712 }); 713}; 714 715 716/* Menu.prototype.setPosition parameters (defaults noted with *): 717 referrer = the link (or other element) used to show the overlaid object 718 settings = can override the defaults: 719 - posX/Y: where the top left corner of the object should be positioned in relation to its referrer. 720 X: left*, center, right 721 Y: top, center, bottom* 722 - offsetX/Y: the number of pixels to be offset from the x or y position. Can be a positive or negative number. 723 - directionH/V: where the entire menu should appear in relation to its referrer. 724 Horizontal: left*, right 725 Vertical: up, down* 726 - detectH/V: detect the viewport horizontally / vertically 727 - linkToFront: copy the menu link and place it on top of the menu (visual effect to make it look like it overlaps the object) */ 728 729Menu.prototype.setPosition = function(widget, caller, options) { 730 var el = widget; 731 var referrer = caller; 732 var dims = { 733 refX: referrer.offset().left, 734 refY: referrer.offset().top, 735 refW: referrer.getTotalWidth(), 736 refH: referrer.getTotalHeight() 737 }; 738 var options = options; 739 var xVal, yVal; 740
741 var helper = $('<div class="positionHelper"></div>'); 742 helper.css({ position: 'absolute', left: dims.refX, top: dims.refY, width: dims.refW, height: dims.refH }); 743 el.wrap(helper); 744 745 // get X pos 746 switch(options.positionOpts.posX) { 747 case 'left': xVal = 0; 748 break; 749 case 'center': xVal = dims.refW / 2; 750 break; 751 case 'right': xVal = dims.refW; 752 break; 753 }; 754 755 // get Y pos 756 switch(options.positionOpts.posY) { 757 case 'top': yVal = 0; 758 break; 759 case 'center': yVal = dims.refH / 2; 760 break; 761 case 'bottom': yVal = dims.refH; 762 break; 763 }; 764 765 // add the offsets (zero by default) 766 xVal += options.positionOpts.offsetX; 767 yVal += options.positionOpts.offsetY; 768 769 // position the object vertically 770 if (options.positionOpts.directionV == 'up') { 771 el.css({ top: 'auto', bottom: yVal }); 772 if (options.positionOpts.detectV && !fitVertical(el)) { 773 el.css({ bottom: 'auto', top: yVal }); 774 } 775 } 776 else { 777 el.css({ bottom: 'auto', top: yVal }); 778 if (options.positionOpts.detectV && !fitVertical(el)) { 779 el.css({ top: 'auto', bottom: yVal }); 780 } 781 }; 782 783 // and horizontally 784 if (options.positionOpts.directionH == 'left') { 785 el.css({ left: 'auto', right: xVal }); 786 if (options.positionOpts.detectH && !fitHorizontal(el)) { 787 el.css({ right: 'auto', left: xVal }); 788 } 789 } 790 else { 791 el.css({ right: 'auto', left: xVal }); 792 if (options.positionOpts.detectH && !fitHorizontal(el)) { 793 el.css({ left: 'auto', right: xVal }); 794 } 795 }; 796 797 // if specified, clone the referring element and position it so that it appears on top of the menu 798 if (options.positionOpts.linkToFront) { 799 referrer.clone().addClass('linkClone').css({ 800 position: 'absolute', 801 top: 0, 802 right: 'auto', 803 bottom: 'auto', 804 left: 0, 805 width: referrer.width(), 806 height: referrer.height() 807 }).insertAfter(el); 808 }; 809}; 810 811 812/* Utilities to sort and find viewport dimensions */ 813 814function sortBigToSmall(a, b) { return b - a; }; 815 816jQuery.fn.getTotalWidth = function(){ 817 return $(this).width() + parseInt($(this).css('paddingRight')) + parseInt($(this).css('paddingLeft')) + parseInt($(this).css('borderRightWidth')) + parseInt($(this).css('borderLeftWidth')); 818}; 819 820jQuery.fn.getTotalHeight = function(){ 821 return $(this).height() + parseInt($(this).css('paddingTop')) + parseInt($(this).css('paddingBottom')) + parseInt($(this).css('borderTopWidth')) + parseInt($(this).css('borderBottomWidth')); 822}; 823 824function getScrollTop(){ 825 return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; 826}; 827 828function getScrollLeft(){ 829 return self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft; 830}; 831 832function getWindowHeight(){ 833 var de = document.documentElement; 834 return self.innerHeight || (de && de.clientHeight) || document.body.clientHeight; 835}; 836 837function getWindowWidth(){ 838 var de = document.documentElement; 839 return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth; 840}; 841 842/* Utilities to test whether an element will fit in the viewport 843 Parameters: 844 el = element to position, required 845 leftOffset / topOffset = optional parameter if the offset cannot be calculated (i.e., if the object is in the DOM but is set to display: 'none') */ 846 847function fitHorizontal(el, leftOffset){ 848 var leftVal = parseInt(leftOffset) || $(el).offset().left; 849 return (leftVal + $(el).width() <= getWindowWidth() + getScrollLeft() && leftVal - getScrollLeft() >= 0); 850}; 851 852function fitVertical(el, topOffset){ 853 var topVal = parseInt(topOffset) || $(el).offset().top; 854 return (topVal + $(el).height() <= getWindowHeight() + getScrollTop() && topVal - getScrollTop() >= 0); 855}; 856 857/*-------------------------------------------------------------------- 858 * javascript method: "pxToEm" 859 * by: 860 Scott Jehl ([email protected]) 861 Maggie Wachs ([email protected]) 862 http://www.filamentgroup.com 863 * 864 * Copyright (c) 2008 Filament Group 865 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses. 866 * 867 * Description: Extends the native Number and String objects with pxToEm method. pxToEm converts a pixel value to ems depending on inherited font size. 868 * Article: http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/ 869 * Demo: http://www.filamentgroup.com/examples/pxToEm/ 870 * 871 * Options: 872 scope: string or jQuery selector for font-size scoping 873 reverse: Boolean, true reverses the conversion to em-px 874 * Dependencies: jQuery library 875 * Usage Example: myPixelValue.pxToEm(); or myPixelValue.pxToEm({'scope':'#navigation', reverse: true}); 876 * 877 * Version: 2.0, 08.01.2008 878 * Changelog: 879 * 08.02.2007 initial Version 1.0 880 * 08.01.2008 - fixed font-size calculation for IE 881--------------------------------------------------------------------*/ 882 883Number.prototype.pxToEm = String.prototype.pxToEm = function(settings){ 884 //set defaults 885 settings = jQuery.extend({ 886 scope: 'body', 887 reverse: false 888 }, settings); 889 890 var pxVal = (this == '') ? 0 : parseFloat(this); 891 var scopeVal; 892 var getWindowWidth = function(){ 893 var de = document.documentElement; 894 return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth; 895 }; 896 897 /* When a percentage-based font-size is set on the body, IE returns that percent of the window width as the font-size. 898 For example, if the body font-size is 62.5% and the window width is 1000px, IE will return 625px as the font-size. 899 When this happens, we calculate the correct body font-size (%) and multiply it by 16 (the standard browser font size) 900 to get an accurate em value. */ 901 902 if (settings.scope == 'body' && $.browser.msie && (parseFloat($('body').css('font-size')) / getW
902indowWidth()).toFixed(1) > 0.0) { 903 var calcFontSize = function(){ 904 return (parseFloat($('body').css('font-size'))/getWindowWidth()).toFixed(3) * 16; 905 }; 906 scopeVal = calcFontSize(); 907 } 908 else { scopeVal = parseFloat(jQuery(settings.scope).css("font-size")); }; 909 910 var result = (settings.reverse == true) ? (pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em'; 911 return result; 912}; 913
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.