1/** 2* 3* @author: Cargo 4* 5**/ 6var intransition = 7 soundDependenciesCalled = 8 start_sound = 9 this_play = 10 mouse_down = 11 tool_over = 12 timer = 13 lastT = 14 viewport_threshold = false, 15 cycleTimeout = new Array(), 16 cyclePause = new Array(), 17 cycleComplete = new Array(); 18 19///////////////////////////////////////////////////////////////////////////////////////////////// 20 21if (typeof (Cargo) === "undefined") { 22 Cargo = {}; 23 // Legacy 24 //CARGO = Cargo; 25} 26 27// To use for global variables Cargo.Config.get('dispatch_url') 28Cargo.Config = { 29 'CARGO_URL' : (/cargocollective.com/.test(document.location.host) || /persona.co/.test(document.location.host)) ? document.location.host : 'cargocollective.com', 30 'Print_Url' : '', 31 'Admin_Print_Url' : '', 32 'dispatch_url' : 'dispatch.php', 33 'dispatch_prefix' : 'dispatch/', 34 'project_single' : '/entry-detail.php', 35 'custom_thumbsize_path' : '/dispatch/user/saveCustomThumbPosition', 36 'css_inspector_position' : '/dispatch/user/saveCssInspectorPosition', 37 'drag_drop_options' : '/dispatch/user/saveDragDropOptions', 38 'get_drag_drop_options' : '/dispatch/user/getDragDropOptions', 39 'save_edit_frame' : '/dispatch/admin/saveEditContent_', 40 'save_syntax_color' : '/dispatch/admin/toggleSyntaxColor', 41 'MAX_COMMENT_IMAGES' : 10, 42 'CDN_CONTAINER_TEMPLATE' : '//payload.cargocollective.com/', 43 'website_title' : $("meta[name='cargo_title']").attr("content"), 44 'fourOfour' : '/dispatch/user/user404', 45 'loading_animation' : '<img src="/_gfx/loadingAnim.gif">', 46 47 get : function(key, def) { 48 return this[key] ? this[key] : def; 49 }, 50 51 GetDesign : function() { 52 return $("#design").val(); 53 }, 54 55 GetTemplate : function() { 56 return $("#template").val(); 57 }, 58 59 GetCurrentPageType : function() { 60 var type = $(".entry").attr("page_type"); 61 return (typeof type == "undefined") ? "none" : type; 62 }, 63 64 GetCurrentPage : function() { 65 return $("#current_page").val(); 66 }, 67 68 GetTotalPages : function() { 69 return $("#total_pages").val(); 70 }, 71 72 GetPageLimit : function() { 73 return $("#page_limit").val(); 74 }, 75 76 isIE : function() { 77 return (/MSIE (\d+\.\d+);/.test(navigator.userAgent)); 78 }, 79 80 isMobile : function() { 81 return (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)); 82 }, 83 84 isIE8 : function() { 85 var rv = -1; // Return value assumes failure. 86 if (this.isIE()) { 87 var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); 88 if (re.exec(navigator.userAgent) != null) rv = parseFloat( RegExp.$1 ); 89 } 90 91 return (rv < 9 && rv > 0) ? true : false; 92 }, 93 94 isOldIE : function() { 95 var rv = -1; // Return value assumes failure. 96 if (this.isIE()) { 97 var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); 98 if (re.exec(navigator.userAgent) != null) rv = parseFloat( RegExp.$1 ); 99 } 100 101 return (rv <= 9 && rv > 0) ? true : false; 102 }, 103 104 SetCookieUrl : function(url) { 105 $.cookie('curl', url, {path: '/'}); 106 }, 107 108 GetCookieUrl : function() { 109 return $.cookie('curl'); 110 }, 111 112 SetCookieUid : function(uid) { 113 $.cookie('cuid', uid, {path: '/'}); 114 }, 115 116 GetCookieUid : function() { 117 return $.cookie('cuid'); 118 }, 119 120 GetUid : function() { 121 return $('#uid').val(); 122 }, 123 124 /** 125 * Returns the width of the scrollbars 126 * Useful for checking for Lion webkit 127 * via http://www.fleegix.org/articles/2006-05-30-getting-the-scrollbar-width-in-pixels 128 */ 129 GetScrollBarWidth : function() { 130 var scr = null; 131 var inn = null; 132 var wNoScroll = 0; 133 var wScroll = 0; 134 135 // Outer scrolling div 136 scr = document.createElement('div'); 137 scr.style.position = 'absolute'; 138 scr.style.top = '-1000px'; 139 scr.style.left = '-1000px'; 140 scr.style.width = '100px'; 141 scr.style.height = '50px'; 142 // Start with no scrollbar 143 scr.style.overflow = 'hidden'; 144 145 // Inner content div 146 inn = document.createElement('div'); 147 inn.style.width = '100%'; 148 inn.style.height = '200px'; 149 150 // Put the inner div in the scrolling div 151 scr.appendChild(inn); 152 // Append the scrolling div to the doc 153 document.body.appendChild(scr); 154
155 // Width of the inner div sans scrollbar 156 wNoScroll = inn.offsetWidth; 157 // Add the scrollbar 158 scr.style.overflow = 'auto'; 159 // Width of the inner div width scrollbar 160 wScroll = inn.offsetWidth; 161 162 // Remove the scrolling div from the doc 163 document.body.removeChild( 164 document.body.lastChild); 165 166 // Pixel width of the scroller 167 return (wNoScroll - wScroll); 168 } 169 170}; // end config 171 172/** 173 * Make a safe logging method 174 */ 175Cargo.log = function(args) { 176 if (typeof console == 'undefined' || !window.console) { 177 return; 178 } 179 console.log(args); 180}; 181 182 183/** 184 * Location based lookups 185 * eg. getting direct links, current domain, etc 186 */ 187/* !Cargo.Location */ 188Cargo.Location = { 189 GetDomain : function(no_trailing_slash) { 190 var domain = document.location.protocol + "//" + location.hostname; 191 return (!no_trailing_slash) ? domain+"/" : domain; 192 }, 193 194 GetCargoUrl : function() { 195 var url = ($("#url").val() == "") ? $('#follow_url').val() : $("#url").val(); 196 return url; 197 }, 198 199 GetDomainOrUrl : function() { 200 if( this.IsCustomDomain() ) { 201 return this.GetCargoUrl(); 202 } else { 203 var url = location.pathname.split("/")[1]; 204 return (url == "gallery" || url == "selections") ? null : url; 205 } 206 }, 207 208 GetNetworkId : function() { 209 return ($("#nid").length > 0) ? $("#nid").val() : false; 210 }, 211 212 GetDirectLink : function( pid ) { 213 return $("directlink#dl_"+pid).attr("link"); 214 // this.MakeDirectLink( location.pathname.replace( this.GetBaseUrl()+"/", "") ); 215 }, 216 217 // Use this to get absolute paths 218 GetPathAbs : function( path_rel ) { 219 return this.GetDomain() + path_rel; 220 }, 221 222 /* 223 * Pass a url path in and create a direct link 224 */ 225 MakeDirectLink : function( purl ) { 226 var direct_link = this.GetDomain( true ); 227 228 if( !this.IsCustomDomain() ) { 229 direct_link += this.GetBaseUrl(); 230 } 231 232 if( purl ) { 233 return direct_link + "/" + purl; 234 } else { 235 return direct_link; 236 } 237 }, 238 239 /* 240 * Helper method to retrieve the base URL 241 * Useful for domain vs cargo URL 242 * Allows a modifier value to be given 243 * e.g. "following" for [cargourl]/following 244 */ 245 GetBaseUrl : function(modifier) { 246 modifier = (modifier) ? "/" + modifier : ""; 247 248 if( location.hostname.indexOf( Cargo.Config.get('CARGO_URL') ) >= 0 ) { 249 var return_url = "/" + Cargo.Location.GetCargoUrl() + modifier; 250 if( $("#follow_sort").length > 0 && $("#follow_sort").val() != "" ) { 251 /* 252 * Because of following cookie memory, sometimes this URL could simply be /following 253 * even if the sort is "all". Test for this case by sniffing the location.pathname 254 */ 255 var filter = "/"+$("#follow_sort").val()+"/"; 256 if( location.pathname.indexOf( filter ) >= 0 && modifier == "following") { 257 return_url += "/"+$("#follow_sort").val(); 258 } 259 260 } 261 return return_url; 262 263 } else { 264 return modifier; 265 } 266 }, 267 268 IsFollowing : function() { 269 return ($('#follow_url').val() || $("#follow_type").length > 0) ? true : false; 270 }, 271 272 IsUserImageGallery : function() { 273 return ( location.pathname.indexOf("/images") >= 0 ) ? true : false; 274 }, 275 276 IsHomepageGallery : function() { 277 return ( location.pathname.indexOf("/gallery") >= 0 ) ? true : false; 278 }, 279 280 IsUserSelections : function() { 281 return ( location.pathname.indexOf("/selections") >= 0 ) ? true : false; 282 }, 283 284 IsCustomDomain : function() { 285 return ( location.hostname.indexOf( Cargo.Config.get('CARGO_URL') ) < 0 ) ? true : false; 286 }, 287 288 IsUserFilter : function() { 289 if( location.pathname.indexOf("filter/") >= 0 && $(".view_tag_info").length > 0 ) { 290 return true; 291 } else { 292 return false; 293 } 294 }, 295 296 GetUserFilter : function() { 297 if( this.IsUserFilter() ) { 298 return location.pathname.split("filter/")[1].split("/")[0]; 299 } else { 300 return ""; 301 } 302 }, 303 304 IsSoloLink : function() { 305 return ($("#is_solo").length > 0 && $("#is_solo").val() == "true") ? true : false; 306 }, 307 308 IsDirectLink : function() { 309 return ($("#is_direct").length > 0 && $("#is_direct").val() == "true") ? true : false; 310 }, 311 312 IsEditingProject : function() { 313 return !!( this.IsInAdmin() && this.IsDirectLink() ); 314 }, 315 316 IsStartProject : function() { 317 if( 318 $("#start_page").length > 0 && 319 $("#start_page").val() != "none" && 320 $("#current_open").val() == "none" && 321 !Cargo.Location.IsUserFilter() && 322 $("#entry_"+$("#start_page").val()).length > 0 323 ) { 324 return true; 325 326 } else { 327 return false; 328 } 329 }, 330 331 GetStartProjectPid : function() { 332 if( 333 $("#start_page").length > 0 && 334 $("#start_page").val() != "none" 335 ) { 336 return $("#start_page").val(); 337 } else { 338 return false; 339 } 340 }, 341 342 IsInAdmin : function() { 343 return ( location.pathname.indexOf("/adminedit") >= 0 ) ? true : false; 344 }, 345 346 IsFeedIndex : function() { 347 return ($(".index_view").length > 0) ? true : false; 348 }, 349 350 IsSearch : function() { 351 return ($('#search_form_results').length > 0) ? true : false; 352 }, 353 354 IsTraceMarks : function() { 355 return ($('tracemark_data').length > 0) ? true : false; 356 }, 357 358 IsNetwork : function() { 359 return ($('#nid').length > 0 && $("#template").val() == "network") ? true : false; 360 }, 361 362 IsNetworkMemberList : function() { 363 return ($('memberlist').length > 0) ? true : false; 364 }, 365 366 IsInFrame : function() { 367 return (window.self !== window.top); 368 } 369} 370 371// Helper class for getting dispatch urls 372/* !Cargo.Dispatcher */ 373Cargo.Dispatcher = { 374 // Path should be 'c/a' 375 GetUrl : function(path, g) { 376 if(typeof(g) == 'array' && g.length > 0) { 377 path += '/' + g.split('/'); 378 } 379 return Cargo.Location.GetDomain() + Cargo.Config.get('dispatch_prefix') + path; 380 } 381}; 382 383 384 385/** 386 * Ajax methods 387 * Standardixed ways to handle ajax 388 */ 389/* !Cargo.Ajax */ 390Cargo.Ajax = { 391 _is_init : false, 392 393 Init : function() { 394 if(Cargo.Ajax._is_init == false) { 395 Cargo.Ajax._is_init = true; 396 397 $(".ajax_post_form").live("keypress", function(e) { 398 if (e.keyCode == 13) { 399 $(".ajax_post", this).trigger("click"); 400 return false; 401 } 402 }); 403 404 $(".ajax_post").live("click", function(elem) { 405 var container_selector = $(this).parents(".ajax_post_container"); 406 var parent_form = $('form', container_selector); 407 var params = parent_form.serialize(), 408 route = parent_form.attr("action"), 409 identifier = parent_form.find('input[name="identifier"]').val(); 410 411 /* Trigger a before handler */ 412 var handler_event_name = Cargo.Ajax.GetBeforeHandlerName(identifier); 413 $(document).trigger(handler_event_name, [container_selector]); 414 415 $.post(route, params, function(data) { 416 var response_data = $.parseJSON(data); 417 /* Trigger a complete handler */ 418 var handler_event_name = Cargo.Ajax.GetCompleteHandlerName(identifier); 419 $(document).trigger(handler_event_name, [container_selector, response_data]); 420 }); 421 422 return false; 423 }); 424 425 /* Ajax event handlers. custom-defined per ajax type */ 426 Cargo.Ajax.BindBeforeHandler("promote_form", function(event, container_selector) { 427 $(container_selector) 428 .find('.ajax_post').hide(); 429 $(container_selector) 430 .append('<div class="ajax_loading">'+Cargo.Config.loading_animation+'</div>'); 431 Cargo.ReplaceLoadingAnims(); 432 }); 433 434 Cargo.Ajax.BindCompleteHandler("promote_form", function(event, container_selector, response_data) { 435 if(response_data.error.length == 0) { 436 $(container_selector) 437 .find('.ajax_loading') 438 .remove(); 439 $(container_selector) 440 .find('.ajax_post') 441 .show() 442 .text(response_data.jdata.ajax_post_val); 443 $(container_selector) 444 .find('input[name="action_type"]') 445 .val(response_data.jdata.action_type_val); 446 } 447 }); 448 449 /* handlers for password form */ 450 Cargo.Ajax.BindBeforeHandler("password_form", function(event, container_selector) { 451 $("#password_protected_title").hide(); 452 $(container_selector) 453 .find('.ajax_post').hide(); 454 $('#ErrorMessage') 455 .html('<span class="ajax_loading2">'+Cargo.Config.loading_animation+'</span>'); 456 }); 457 Cargo.Ajax.BindCompleteHandler("password_form", function(event, container_selector, response_data) { 458 $(container_selector) 459 .find('.ajax_loading2') 460 .remove(); 461 $(container_selector) 462 .find('.ajax_post') 463 .show(); 464 if(response_data.error.length == 0) { 465 document.location.href = $(container_selector) 466 .find('input[name="TargetUrl"]') 467 .val(); 468 } else { 469 $("#ErrorMessage").html(response_data.jdata.ErrorMessage); 470 // Hack for password protection 471 $("#password_protected_title").hide(); 472 $(container_selector) 473 .find('input[name="user_password"]') 474 .val(''); 475 } 476 }); 477 478 } 479 480 }, 481 482 GetBeforeHandlerName : function(identifier) { 483 return 'ajax_' + identifier + '_before_handler'; 484 }, 485 486 GetCompleteHandlerName : function(identifier) { 487 return 'ajax_' + identifier + '_complete_handler'; 488 }, 489 490 BindBeforeHandler : function(identifier, func_closure) { 491 $(document).bind( Cargo.Ajax.GetBeforeHandlerName(identifier), func_closure ); 492 }, 493 494 BindCompleteHandler : function(identifier, func_closure) { 495 $(document).bind( Cargo.Ajax.GetCompleteHandlerName(identifier), func_closure ); 496 } 497 498}; 499 500/* !Cargo.GetContainerDomainByPid */ 501Cargo.GetContainerDomainByPid = function(pid) { 502 // this code used to replace %s in the template by the partition number 503 // left in, in case this function is being used out-of-tree 504 return Cargo.Config.get('CDN_CONTAINER_TEMPLATE'); 505}; 506 507/** 508 * Standardized auto pagination 509 * Usage 510 * 511 * Cargo.AutoPagination.Init( { 512 * "ajax_route" : "tracemark/loadTracemarks", 513 * "more_load_handle" : "#moreload", 514 * "height_selector" : function() { return Tracemark.GetShortestColumn(); } 515 * }); 516 */ 517/* !Cargo.AutoPagination */ 518Cargo.AutoPagination = { 519 Data : { 520 "should_paginate" : true, 521 "is_updating" : false, // are we currently waiting on ajax? 522 "within_bounds" : false, // within the bounds of paginating? 523 "preload_distance" : 1500, // Distance before the end of the page to fire 524 "page" : 0, // Page count 525 "more_load_handle" : "#moreload", // Handler to show the loading message / attach new page 526 "ajax_route" : "", // Route for the ajax 527 "is_ajax" : true, // Is this cycle ajax loaded? 528 "height_selector" : 'document', // Can be dynamic: function() { return getSelector(); }
529 "limit" : 80, // If we are using offset, and not page, use this value 530 "offset" : 0 // If we are not using page, then use offset based on page 531 }, 532 /* 533 * Initialize by setting defaults and binding the scroll event 534 */ 535 Init : function( settings ) { 536 this.Data.should_paginate = true; 537 538 // Make sure we are not in the middle of an update before re-init 539 if(this.Data.is_updating) { 540 setTimeout(function() { 541 Cargo.AutoPagination.Init(settings); 542 }, 100); 543 } else { 544 // Loop through the default settings and set them 545 for(key in settings) { 546 this.Data[key] = settings[key]; 547 } 548 549 // Bind the scroll 550 $(window).bind("scroll", function(event) { 551 Cargo.AutoPagination.CheckPageHeight(event); 552 }); 553 } 554 555 }, 556 557 558 End : function() { 559 this.Data.should_paginate = false; 560 this.Data.is_updating = false; 561 $(document).trigger("paginationDone"); 562 }, 563 564 /* 565 * Checks if we are within bounds of paginating 566 */ 567 CheckPageHeight : function() { 568 if (this.Data.should_paginate === false) { 569 return; 570 } 571 572 // Check to see if the selector is a function or a string 573 var selector = (typeof this.Data.height_selector == "function") ? this.Data.height_selector() : this.Data.height_selector; 574 575 var window_scroll = $(window).scrollTop()+$(window).height(); 576 var document_size = $(selector).height()-this.Data.preload_distance; 577 578 this.Data.within_bounds = ( window_scroll >= document_size ) ? true : false; 579 580 if (this.Data.within_bounds && !this.Data.is_updating) { 581 this.Paginate(); 582 } 583 584 }, 585 586 /* 587 * Paginates 588 */ 589 Paginate : function() { 590 this.Data.is_updating = true; 591 $(this.Data.more_load_handle).show(); // Show the handler 592 Cargo.ReplaceLoadingAnims($(this.Data.more_load_handle).find('img')); 593 this.Data.page++; // up the page count 594 595 this.Data.offset = this.Data.page * this.Data.limit; 596 $.post( 597 Cargo.Dispatcher.GetUrl(this.Data.ajax_route), 598 Cargo.AutoPagination.Data, 599 function(data) { Cargo.AutoPagination.PaginateCallback(data) } 600 ); 601 602 $(document).trigger("paginationStart", [ (this.Data.page) ]); 603 }, 604 605 /** 606 * Pagination callback varibale 607 */ 608 PaginateCallback : function(dataObj) { 609 var jdata = $.parseJSON(dataObj); 610 611 $(this.Data.more_load_handle).hide(); 612 613 // Prevent further pagination attempts 614 if ((typeof jdata.jdata.end_pagination !== 'undefined') && (jdata.jdata.end_pagination === true)) { 615 this.End(); 616 } 617 618 if(jdata.error != "" || jdata.html == "") { 619 // This is probably a blank value 620 // Do nothing, stop paginating 621 622 } else { 623 $(this.Data.more_load_handle).before( jdata.html ); 624 this.Data.is_updating = false; 625 } 626 627 628 $(document).trigger("paginationComplete", [ (this.Data.page+1) ]); 629 630 } 631} 632 633 // A lazy loader of sorts 634Cargo.loaded_scripts = []; 635 636Cargo.require_once = function(url) { 637 url = url.toLowerCase(); 638 // Check if its in our array 639 if(jQuery.inArray(url, this.loaded_scripts) >= 0) { 640 return; 641 } 642 // Check if its in the head (ie not loaded with this script) 643 var already_loaded = false; 644 $('script').each(function() { 645 var src = $(this).attr('src'); 646 if(src) { 647 src = src.toLowerCase(); 648 if(src.search(url) >= 0) { 649 Cargo.loaded_scripts.push(url); 650 already_loaded = true; 651 return false; 652 } 653 } 654 }); 655 // load it 656 if(already_loaded == false) { 657 addScript(url); 658 this.loaded_scripts.push(url); 659 } 660 return; 661} 662 663 664/** 665 * Cargo javascript router 666 * Has a list of routes 667 * Loads data based on route 668 */ 669/* !Cargo.Router */ 670Cargo.Router = { 671 /** 672 * Routes for sites 673 * Each route requires a regex 674 * The regex will assume the base URL has 675 * been stripped (do not include Cargo/url) 676 * The result must be formatted like a value set 677 * these values will be set using eval() 678 * they are separated by lines for legibility using \ 679 * Additionally, a conditional must be met 680 * Because routes often look the same, 681 * we must meet a conditional to prove the page 682 * - A value of true means no conditional (true will always pass) 683 * Finally, the action is set on what to do 684 * Options include "home", "close" and "load" 685 * Cargo.History.HomePopstate() // user/network/following landing page 686 * Cargo.History.ClosePopstate() // close any open projects. Similar to home
687 * Projects.LoadProject() // load any project or page 688 */ 689 /* !Routes */ 690 "Routes" : { 691 /* 692 * Network 693 */ 694 "network_filter_project" : { 695 "regex" : "^\/filter\/([^\/]*)\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)$", 696 "result" : ' Projects.Data.network_filter="$1"; \ 697 Projects.Data.user_url="$2"; \ 698 Projects.Data.purl="$3"; \ 699 Projects.Data.network_url=$("#url").val();', 700 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 701 "action" : "Projects.LoadProject();" 702 // /filter/sound/richard/13278 703 }, 704 705 "network_filter_page" : { 706 "regex" : "^\/filter\/([^\/]*)\/([a-zA-Z0-9._-]+)$", 707 "result" : ' Projects.Data.network_filter="$1"; \ 708 Projects.Data.purl="$2"; \ 709 Projects.Data.user_url=$("#url").val(); \ 710 Projects.Data.network_url=$("#url").val();', 711 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 712 "action" : "Projects.LoadProject();" 713 // /filter/sound/About-this-project 714 }, 715 716 "network_filter" : { 717 "regex" : "^\/filter\/([^\/]*)$", 718 "result" : 'Projects.Data.network_filter="$1";', 719 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 720 "action" : "Cargo.History.ClosePopstate();" 721 // /filter/sound 722 }, 723 724 "network_sort_project" : { 725 "regex" : "^\/display\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)$", 726 "result" : ' Projects.Data.network_sort="$1"; \ 727 Projects.Data.user_url="$2"; \ 728 Projects.Data.purl="$3"; \ 729 Projects.Data.network_url=$("#url").val();', 730 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 731 "action" : "Projects.LoadProject();" 732 // /display/mycomments/richard/Untitled-project 733 }, 734 735 "network_sort_page" : { 736 "regex" : "^\/display\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)$", 737 "result" : ' Projects.Data.network_sort="$1"; \ 738 Projects.Data.purl="$2"; \ 739 Projects.Data.user_url=$("#url").val(); \ 740 Projects.Data.network_url=$("#url").val();', 741 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 742 "action" : "Projects.LoadProject();" 743 // /display/mycomments/About-this-project 744 }, 745 746 "network_sort" : { 747 "regex" : "^\/display\/([a-zA-Z0-9._-]+)$", 748 "result" : ' Projects.Data.network_sort="$1"; \ 749 Projects.Data.network_url=$("#url").val();', 750 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 751 "action" : "Cargo.History.ClosePopstate();" 752 // /display/mycomments 753 }, 754 755 "network_adminedit" : { 756 "regex" : "\/adminedit$", 757 "result" : "", 758 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 759 "action" : "" 760 // /adminedit 761 }, 762 763 "network_project" : { 764 "regex" : "^\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)$", 765 "result" : ' Projects.Data.user_url="$1"; \ 766 Projects.Data.purl="$2"; \ 767 Projects.Data.network_url=$("#url").val();', 768 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 769 "action" : "Projects.LoadProject();" 770 // /richard/Photo-Koto 771 }, 772 773 "network_page" : { 774 "regex" : "^\/([a-zA-Z0-9._-]+)$", 775 "result" : ' Projects.Data.purl="$1"; \ 776 Projects.Data.nurl=$("#url").val(); \ 777 Projects.Data.network_url=$("#url").val();', 778 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 779 "action" : "Projects.LoadProject();" 780 // /About-this-project 781 }, 782 783 "network_home" : { 784 "regex" : "", 785 "result" : 'Projects.Data.network_url=$("#url").val();', 786 "conditional" : '$("#nuid").length > 0 && $("#follow_sort").length <= 0', 787 "action" : "Cargo.History.HomePopstate();" 788 // / 789 }, 790 791 /* 792 * Following 793 */ 794 "following_project_comments" : { 795 "regex" : "^\/following\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)\/comments$", 796 "result" : ' Projects.Data.user_url="$1"; \ 797 Projects.Data.purl="$2"; \ 798 Projects.Data.attr="comments";', 799 "conditional" : '$("#follow_sort").length > 0',
800 "action" : "Projects.LoadProject();" 801 //following/Tapisteries-recentes/comments 802 }, 803 804 "following_sort_project_comments" : { 805 "regex" : "^\/following\/([a-zA-Z]+)\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)\/comments$", 806 "result" : ' Projects.Data.follow_sort="$1"; \ 807 Projects.Data.user_url="$2"; \ 808 Projects.Data.purl="$3"; \ 809 Projects.Data.attr="comments";', 810 "conditional" : '$("#follow_sort").length > 0', 811 "action" : "Projects.LoadProject();" 812 //following/postswithcomments/mondiran/Tapisteries-recentes/comments 813 }, 814 815 "following_sort_project" : { 816 "regex" : "^\/following\/([a-zA-Z]+)\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)$", 817 "result" : ' Projects.Data.follow_sort="$1"; \ 818 Projects.Data.user_url="$2"; \ 819 Projects.Data.purl="$3";', 820 "conditional" : '$("#follow_sort").length > 0', 821 "action" : "Projects.LoadProject();" 822 // /following/postswithcomments/mondrian/Self-portrait 823 }, 824 825 "following_project" : { 826 "regex" : "^\/following\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)$", 827 "result" : ' Projects.Data.user_url="$1"; \ 828 Projects.Data.purl="$2";', 829 "conditional" : '$("#follow_sort").length > 0', 830 "action" : "Projects.LoadProject();" 831 // /following/mondrian/Self-portrait 832 }, 833 834 "following_sort" : { 835 "regex" : "^\/following\/([a-zA-Z0-9._-]+)$", 836 "result" : 'Projects.Data.follow_sort="$1";', 837 "conditional" : '$("#follow_sort").length > 0', 838 "action" : "Cargo.History.ClosePopstate();" 839 // /following/postswithcomments 840 }, 841 842 843 "following" : { 844 "regex" : "^\/following$", 845 "result" : "", 846 "conditional" : '$("#follow_sort").length > 0', 847 "action" : "Cargo.History.HomePopstate();" 848 // /following 849 }, 850 851 /* 852 * User 853 */ 854 "user_filter_project" : { 855 "regex" : "^\/filter\/([^\/]*)\/([a-zA-Z0-9._-]+)$", 856 "result" : ' Projects.Data.user_filter="$1"; \ 857 Projects.Data.purl="$2";', 858 "conditional" : '$("#url").length > 0', 859 "action" : "Projects.LoadProject();" 860 // /filter/oil-on-canvas/Sidney-Janis-Gallery 861 }, 862 863 "user_filter" : { 864 "regex" : "^\/filter\/([^\/]*)$", 865 "result" : 'Projects.Data.user_filter="$1";', 866 "conditional" : '$("#url").length > 0', 867 "action" : "Cargo.History.ClosePopstate();" 868 // /filter/oil-on-canvas 869 }, 870 871 "user_preview" : { 872 "regex" : "\/preview\/(html|css)$", 873 "result" : '', 874 "conditional" : '$("#url").length > 0', 875 "action" : "Cargo.History.HomePopstate();" 876 // /preview/html 877 }, 878 879 "sc_user_adminedit" : { 880 "regex" : "^\/([a-zA-Z0-9._-]+)\/adminedit$", 881 "result" : 'Projects.Data.purl="$1";', 882 "conditional" : '($("#url").length > 0 && $("#template").val() == "spacecollective")', 883 "action" : "Projects.LoadProject();" 884 // /adminedit (only for SpaceCollective designs) 885 }, 886 887 "user_adminedit" : { 888 "regex" : "\/adminedit$", 889 "result" : "", 890 "conditional" : '$("#url").length > 0', 891 "action" : "" 892 // /adminedit 893 }, 894 895 "user_project" : { 896 "regex" : "^\/([a-zA-Z0-9._-]+)$", 897 "result" : 'Projects.Data.purl="$1";', 898 "conditional" : '$("#url").length > 0', 899 "action" : "Projects.LoadProject();" 900 // /Tapisteries-recentes 901 }, 902 903 "user_solo" : { 904 "regex" : "^(.*)\/solo$", 905 "result" : "", 906 "conditional" : '$("#url").length > 0', 907 "action" : "false" 908 // /Tapisteries-recentes/solo 909 // Do nothing, php has already done it's job 910 }, 911 912 "user_home" : { 913 "regex" : "", 914 "result" : "", 915 "conditional" : '$("#url").length > 0', 916 "action" : "Cargo.History.HomePopstate();" 917 // / 918 } 919 }, 920 921 /** 922 * Take in a route from History.RunRoute 923 * Strip the route of it's base URL 924 * Loop through the routes list to find a match 925 * Load the data based on route 926 * Return; 927 */ 928 LoadRoute : function( route ) { 929 // Remove the base URL from the route 930 route = route.replace( new RegExp( Cargo.Location.GetBaseUrl(), "i" ), ""); 931 932 for(key in this.Routes) { 933 // Evaluate the conditional to make sure it matches 934 if( eval(this.Routes[key]["conditional"]) ) { 935 var expression = new RegExp( this.Routes[key]["regex"] ); 936 937 // Test the expression to see if we have a match 938 if( expression.test(route) ) { 939 // Match found, set the result and return 940 var result = route.replace(expression, this.Routes[key]["result"]); 941 942 /* If there are still slashes in the result, 943 * we've either failed to find a route, 944 * or we've found a false positive */ 945 if(result.indexOf("/") >= 0 && result.length > 1 && key != "network_home") { 946 //Projects.Render404(); 947 /* 948 if( window.console && window.Cargo.log ) { 949 Cargo.log("404 â Route: "+route+" â result: "+result+" â action: "+this.Routes[key]["action"]+" â key: "+key); 950 } 951 */ 952 // Cargo.log("Found dead route"); 953 return; 954 955 } else if(result.length > 1 || key == "network_home") { 956 // Strip a slash if there is one 957 result = result.replace('/', ''); 958 try { 959 $.globalEval( result ); 960 961 } catch(err) { 962 /* 963 if( window.console && window.Cargo.log ) { 964 Cargo.log("Error loading route: "+err); 965 } 966 */ 967 } 968 } 969 970 break; 971 } 972 } 973 } 974 975 // Cargo.log("Route: "+route+" -- Found route: "+key+" -- Action: "+this.Routes[key]["action"]); 976 977 // Perform the action 978 $.globalEval( this.Routes[key]["action"] ); 979 980 } 981}; // End Router 982 983/** 984 * Create an object for getting and setting history 985 */ 986/* !Cargo.History */ 987Cargo.History = { 988 989 "LastPayload" : "", 990 991 "FirstLoad" : true, 992 993 // If there is a hash link pasted in, this is the pid 994 "HashPID" : "", 995 996 /* Return a class based on the key 997 * Example: key = Photography-project 998 * returns: jQuery object of the clicked <a> tag 999 * 1000 * @author: Cargo 1001 */ 1002 Get : function(key) { 1003 if(key) { 1004 return this[key.toLowerCase()] ? this[key.toLowerCase()] : false; 1005 } 1006 }, 1007 1008 /* 1009 * Set a single property 1010 */ 1011 Set : function(key, value) { 1012 this[key.toLowerCase()] = value; 1013 }, 1014 1015 /* 1016 * Returns a pid based on a purl 1017 * Used in history 1018 * Example: key = My-Project-1 1019 * Returns: 12345 1020 */ 1021 GetPidFromPurl : function(purl) { 1022 var link_Obj = Cargo.History.Get(purl), 1023 // Strip out the Cargo/url 1024 purl = purl.replace(/\/\S*\//g,''), 1025 // Could be pid, check if it is numeric 1026 pid_return = (/^\d+$/.test(purl)) ? purl : false, 1027 pid = (link_Obj) ? $(link_Obj).attr("id").replace("p","") : pid_return; 1028 1029 /* 1030 * If the pid was not found in any link on the page 1031 * BUT the pid was found in an incoming hash, use that 1032 */ 1033 if(pid === false && Cargo.History.HashPID != "") { 1034 pid = Cargo.History.HashPID; 1035 Cargo.History.HashPID = ""; 1036 } 1037 1038 // Set the global pid 1039 Projects.Data.pid = pid; 1040 }, 1041 1042 /* 1043 * Returns a purl based on the pid 1044 * Used in next / prev project 1045 * Example: pid = 12345 1046 * Return: My-Project-1 1047 */ 1048 GetPurlFromPid : function(pid) { 1049 for(key in this) { 1050 if(typeof this[key] != "function" && key != "LastPayload" && key != "FirstLoad" &&
1050key != "HashPID") { 1051 var thispid = $(this[key]).attr("id").replace("p",""); 1052 if(thispid == pid) { 1053 return key.toLowerCase(); 1054 } 1055 } 1056 } 1057 1058 // If we made it this far, then we need to paginate 1059 if( typeof getMoreHistory == "function" ) { 1060 getMoreHistory(); 1061 } 1062 1063 // No purl was found, let's build one 1064 return Cargo.Location.GetBaseUrl() + "/" + pid; 1065 }, 1066 1067 /** 1068 * Creates a URL to be inserted into the history link 1069 * Checks for filters 1070 */ 1071 MakeLink : function(base_href, this_item) { 1072 var href = "", 1073 hash = ""; 1074 1075 // Following 1076 if( Cargo.Location.IsFollowing() ) { 1077 // Strip the base out of the following 1078 base_href = base_href.replace( Cargo.Location.GetBaseUrl("following"), ""); 1079 1080 // Check the base URL, remove the filter (because the following may not have the filter) 1081 var base_follow_url = Cargo.Location.GetBaseUrl(); 1082 base_follow_url = base_follow_url.replace(this.GetFollowingFilter(), ""); 1083 1084 // Rebuild a clean link 1085 href = hash = base_follow_url + "/following" + this.GetFollowingFilter() + base_href; 1086 1087 if ( !Cargo.History.SupportSlashHistory() ) { 1088 // With old browsers, just push the project name 1089 hash = stripLeadingSlash( base_href ); 1090 } 1091 1092 1093 // User 1094 } else { 1095 // Strip the Cargo/url out 1096 base_href = base_href.replace( new RegExp( Cargo.Location.GetBaseUrl(), "i" ), ""); 1097 1098 // Strip the custom domain out 1099 base_href = base_href.replace( Cargo.Location.GetDomain(), "/"); 1100 1101 // Check if there is a network filter, if so use that. Otherwise, use user filter 1102 var filter = ( this.GetNetworkSorting() ) ? this.GetNetworkSorting() : this.GetUserFilter(); 1103 1104 // If the filter is already in the link, the link is already made 1105 if( base_href.indexOf(filter) >= 0 ) { 1106 href = hash = Cargo.Location.GetBaseUrl() + base_href; 1107 } else { 1108 // Rebuild the entire path 1109 href = hash = Cargo.Location.GetBaseUrl() + filter + base_href; 1110 } 1111 1112 if ( !Cargo.History.SupportSlashHistory() ) { 1113 // With old browsers, just push the project name 1114 hash = stripLeadingSlash( base_href ); 1115 1116 } 1117 } 1118 1119 /* 1120 * If a jQuery object for "this_item" exists: 1121 * Set the value of the link. Change the href and add the "hash" data 1122 */ 1123 if(this_item) { 1124 $(this_item).attr("href", href).data("hash", hash); 1125 1126 /* 1127 * If this is not passed, return the hash value 1128 */ 1129 } else { 1130 return hash; 1131 } 1132 }, 1133 1134 /** 1135 * Checks if there is a filter on following pages 1136 */ 1137 IsFollowingFilter : function(url) { 1138 if(url) { 1139 url = url.replace(Cargo.Location.GetBaseUrl("following"), "").split("/").splice(1); 1140 return (url.length >= 2) ? false : true; 1141 } 1142 }, 1143 1144 /** 1145 * Checks if there is a filter on following pages 1146 */ 1147 GetFollowingFilter : function() { 1148 var filter = "/"+$("#follow_sort").val(); 1149 // If the filter is in the URL path (sometimes it is not due to following memory) 1150 return ( location.pathname.indexOf(filter) > 0 ) ? filter : ""; 1151 1152 }, 1153 1154 /** 1155 * Returns the network's filter 1156 */ 1157 GetNetworkFilter : function() { 1158 var pathname = location.pathname 1159 .replace(Cargo.Location.GetBaseUrl(), "") 1160 .split("/") 1161 .splice(1); 1162 if( 1163 pathname.length >= 2 && 1164 pathname[0] == "filter" && 1165 $("#nuid").length > 0 1166 ) { 1167 return "/" + pathname[0] + "/" + pathname[1]; 1168 1169 } else { 1170 return ""; 1171 } 1172 }, 1173 1174 /** 1175 * Check if this is a network or not 1176 * returns true || false 1177 */ 1178 IsNetwork : function() { 1179 return ($("#nuid").length > 0) ? true : false; 1180 }, 1181 1182 1183 /** 1184 * Returns the network's sorting display 1185 */ 1186 GetNetworkSorting : function() { 1187 var pathname = location.pathname 1188 .replace(Cargo.Location.GetBaseUrl(), "") 1189 .split("/") 1190 .splice(1); 1191 if( 1192 pathname.length >= 2 && 1193 pathname[0] == "display" && 1194 $("#nuid").length > 0 1195 ) { 1196 return "/" + pathname[0] + "/" + pathname[1]; 1197 1198 } else { 1199 return ""; 1200 } 1201 }, 1202 1203 /** 1204 * Returns the user filter 1205 */ 1206 GetUserFilter : function() { 1207 var pathname = location.pathname 1208 .replace(Cargo.Location.GetBaseUrl(), "") 1209 .split("/") 1210 .splice(1); 1211 if(pathname.length >= 2 && pathname[0] == "filter") { 1212 return "/" + pathname[0] + "/" + pathname[1]; 1213 1214 } else { 1215 return ""; 1216 } 1217 }, 1218 1219 1220 /* 1221 * Checks if this browser supports HTML5 history pushing 1222 * Returns true || false 1223 */ 1224 SupportSlashHistory : function() { 1225 //return false; 1226 return !!(window.history && (typeof window.history.pushState != "undefined")); 1227 }, 1228 1229 1230 /* 1231 * Pushes a location into history 1232 * Conditional on browser support 1233 * Can be manually called, or is bound to the click 1234 * e.g. next/prev links 1235 */ 1236 Load : function(url, title) { 1237 //Cargo.log("URL: "+url); 1238 1239 if ( Cargo.History.SupportSlashHistory() ) { 1240 if( url.indexOf("index.php") < 0 ) { 1241 // Don't load a php file 1242 window.history.pushState({}, title, url); 1243 // Run this route
1244 Cargo.History.RunRoute(url); 1245 } 1246 1247 } else { 1248 // Does not support slash history 1249 $.history.load( url ); 1250 } 1251 1252 1253 }, 1254 1255 /* 1256 * Unloads the last history item 1257 * Useful when closing a project 1258 * or when you've reached the end of your history 1259 * Set's the "unloading" var to prevent start page re-open 1260 */ 1261 Unload : function(title) { 1262 // Prevent start re-open 1263 Projects.Data.unloading = true; 1264 1265 if ( Cargo.History.SupportSlashHistory() ) { 1266 // For custom domains, load a / as index 1267 if( Cargo.Location.IsCustomDomain() ) { 1268 this.Load( this.MakeLink("/") ); 1269 1270 } else { 1271 this.Load( this.MakeLink("") ); 1272 } 1273 1274 1275 } else { 1276 $.history.load( "#" ); 1277 } 1278 1279 this.SetLastPayload(""); 1280 1281 // Set the title 1282 Cargo.History.SetWindowTitle(true); 1283 }, 1284 1285 /* 1286 * Set the last loaded URL 1287 */ 1288 SetLastPayload : function(url) { 1289 this.LastPayload = url; 1290 }, 1291 1292 /* 1293 * Check the last laoded URL 1294 */ 1295 CheckLastPayload : function(url) { 1296 return !!(this.LastPayload != url); 1297 }, 1298 1299 1300 /** 1301 * Get the uri based on the location 1302 * Determines what the URL to load will be 1303 * This method is called by the RunRoute function 1304 */ 1305 GetUriFromLocation : function() { 1306 var url = location.pathname; 1307 1308 // Slash link 1309 if( Cargo.History.SupportSlashHistory() ) { 1310 // Sanitize the trailing slash 1311 return stripTrailingSlash( url ); 1312 1313 1314 // hash link 1315 } else if( location.hash != "" && !Cargo.History.SupportSlashHistory() ) { 1316 var split_link = location.hash.split("/"); 1317 1318 // Check if there is a pid in this string (old URL) 1319 if(parseInt( split_link[0].replace("#","") ) ) { 1320 // This URL looks like: #1234/Title 1321 url = "/"+split_link[1]; 1322 1323 } else { 1324 url = location.hash; 1325 } 1326 1327 return url; 1328 } 1329 }, 1330 1331 /* 1332 * This function runs the route that was found by the router 1333 * This is only for HTML5 history, RunRouteHash is for old browsers 1334 */ 1335 RunRoute : function(route) { 1336 // If we made it here with a hash in the URL, redirect to the slash URL 1337 if(location.hash != "" && Cargo.History.SupportSlashHistory() ) { 1338 // Redirect the hash link to slash link 1339 this.HashToSlash(); 1340 return false; 1341 } 1342 1343 // Take the incoming route and remove the trailing slash 1344 route = stripTrailingSlash( route ); 1345 1346 /* 1347 * Check last payload, don't allow a double load 1348 */ 1349 if(this.CheckLastPayload( route ) === false) { 1350 // Scroll to the top 1351 Projects.Helper.ScrollToTop(); 1352 return; 1353 } 1354 1355 /* 1356 * If no route is passed, it could be a direct link 1357 * Figure out what that link is 1358 */ 1359 if(!route) { 1360 route = this.GetUriFromLocation(); 1361 } 1362 1363 // Remember the latest URL to prevent double loads 1364 this.SetLastPayload( route ); 1365 1366 // Get the PID for this project project 1367 Cargo.History.GetPidFromPurl( route ); 1368 1369 /* 1370 * Make sure we're not on homepage and there is a start project open 1371 * Compare the base URL to the path in the location bar 1372 * If that is home + there is something already loaded, don't load this route 1373 * Also checks if there is a project already open, to prevent double opens 1374 */ 1375 if( 1376 ( ( location.pathname == Cargo.Location.GetBaseUrl() || location.pathname == "/" ) && 1377 $("#start_page").length > 0 && $("#start_page").val() != "none" && 1378 $("#entry_"+$("#start_page").val()).length > 0 ) 1379 || 1380 ( (location.pathname == Cargo.Location.GetBaseUrl() || location.pathname == "/" ) && 1381 Cargo.Config.GetTemplate() == "spacecollective" && this.FirstLoad 1382 && ($("#start_page").length == 0 || $("#start_page").val() == "none") 1383 ) 1384 || 1385 $("#entry_"+Projects.Data.pid).length > 0 1386 || 1387 route.indexOf("index.php") >= 0 1388 ) { 1389 1390 // Do nothing 1391 1392 } else { 1393 // Load from the Router 1394 Cargo.Router.LoadRoute( route ); 1395 } 1396 1397 // Make sure this posts back 1398 if(this.notify) this.notify( route ); 1399 1400 1401 this.FirstLoad = false; 1402 1403 }, 1404 1405 1406 /* 1407 * This method is not using the router 1408 * It grabs the #hash value and figures out where to go from there 1409 */ 1410 RunRouteHash : function(url, firstload) { 1411 url = stripTrailingSlash( url ); 1412 1413 // Don't allow homestate 1414 if(url && (url == "#" || url == "") ) { 1415 return; 1416 } 1417 1418 /* 1419 * Check last payload, don't allow a double load 1420 */ 1421 if(this.CheckLastPayload(url) === false) { 1422 return; 1423 } 1424 1425 /* 1426 * If no URL is passed, it could be a direct link 1427 * Figure out what that link is 1428 */ 1429 if(!url) { 1430 url = this.GetUriFromLocation(); 1431 // If no URL to load, hault 1432 if( !url ) { 1433 // If this is a new browser, stop here. We're done 1434 if( Cargo.History.SupportSlashHistory() ) { 1435 return; 1436 1437 // Otherwise, this is the homepage of the old browser 1438 } else { 1439 this.HomePopstate(); 1440 } 1441 } 1442 } 1443 1444 // Remember the latest URL to prevent double loads 1445 this.SetLastPayload(url); 1446 1447 // Set the PID for this project project 1448 Cargo.History.GetPidFromPurl(url); 1449 1450 1451 // Network, split the input and go from there 1452 if( Cargo.History.IsNetwork && url && url.split("/").length >= 2 ) { 1453 var uri = url.split("/"); 1454 Projects.Data.user_url = uri[0]; 1455 Projects.Data.purl = uri[1]; 1456 Projects.Data.network_url = $("#url").val(); 1457 } 1458 // Not a network, get data like normal 1459 else if( url && Projects.Data.user_url == "" || Projects.Data.purl == "" ) { 1460 Projects.Data.user_url = $("#url").val(); 1461 Projects.Data.purl = url; 1462 1463 } 1464 // Navigated home, check for start project 1465 else if( !url && Cargo.Location.GetStartProjectPid() ) { 1466 Projects.Data.pid = Cargo.Location.GetStartProjectPid(); 1467 } 1468 1469 if(Projects.Data.pid) { 1470 // Check to see if the project is already loaded 1471 if( $("#entry_"+Projects.Data.pid).length > 0 ) { 1472 /* 1473 * If content is already loaded, just do the cleanup 1474 */ 1475 Projects.TriggerPreloadHelpers( Projects.Data.pid ); 1476 // If this project is not already open, open it 1477 if( $("#entry_"+Projects.Data.pid).length > 0 ) { 1478 Projects.TriggerPostloadHelpers(); 1479 1480 // Changing the page may have dumped our content :( 1481 // Reload in this case 1482 } else { 1483 Projects.AjaxLoadByPid(); 1484 } 1485 1486 } else { 1487 Projects.AjaxLoadByPid(); 1488 1489 } 1490 1491 } else if( 1492 !Projects.Data.pid && 1493 Cargo.Location.IsFollowing() && 1494 Cargo.Location.GetBaseUrl("following") != url 1495 ) { 1496 /* 1497 * This is the following page, the pasted link may not 1498 * exist yet. Verify that it is not a filter link first 1499 * If it is not, load by purl 1500 */ 1501 if( !this.IsFollowingFilter(url) ) { 1502 Projects.AjaxLoadByPurl(); 1503 1504 } 1505 1506 } else if(Cargo.Location.GetBaseUrl() == url || url == "#") { 1507 /* 1508 * Navigated back to home 1509 */ 1510 this.HomePopstate(); 1511 1512 1513 } else if( !Projects.Data.pid && Cargo.History.GetNetworkSorting() ) { 1514 /* 1515 * Network sorting filter page 1516 * This is like home 1517 */ 1518 this.HomePopstate(); 1519 1520 } else if( !Projects.Data.pid && !Cargo.Location.IsFollowing() ) { 1521 /* 1522 * This is a direct link with no pid on a user page 1523 * Could be a project that is turned off 1524 * May not exist, but try to load it anyway 1525 */ 1526 Projects.AjaxLoadByPurl(); 1527 } 1528 1529 if(this.notify) this.notify(url); 1530 1531 }, 1532 1533 /** 1534 * When the popstate is the homepage 1535 * Chooses whether to load the start project 1536 * or close the open project 1537 */ 1538 HomePopstate : function() { 1539 /* 1540 * Safari reads the init load as a pop state 1541 * Check for start page, don't close the start page 1542 * If no start page, then close the project, we're back home 1543 */ 1544 if( 1545 $("#start_page").length > 0 && 1546 $("#start_page").val() != "none" && 1547 Projects.Data.unloading === false && 1548 Cargo.History.SupportSlashHistory() 1549 ) { 1550 Projects.Data.is_start_page = true; 1551 Projects.Data.pid = $("#start_page").val(); 1552 1553 /* 1554 * SpaceCollective double loads start pages, this hack fixes that 1555 */ 1556 if($("#item_"+Projects.Data.pid).length > 0) { 1557 if( $("#item_"+Projects.Data.pid).hasClass("project_feed_full") === false ) { 1558 Projects.AjaxLoadByPid( Projects.Data.pid ); 1559 } 1560 } else { 1561 Projects.AjaxLoadByPid( Projects.Data.pid ); 1562 $(document).trigger("startProjectLoaded"); 1563 } 1564 1565 } else { 1566 this.ClosePopstate(); 1567 } 1568 }, 1569 1570 /** 1571 * This is fired on either a back button pop (from HomePopstate) 1572 * or from the router when we hit a "landing"
1573 * page of /filter, or network/sort 1574 */ 1575 ClosePopstate : function() { 1576 Projects.CloseProject(true); 1577 1578 // For network 1579 $(".project_feed_thumb").removeClass("selected"); 1580 $("#prev_open, #current_open").val("none"); 1581 1582 // Global value to stop double load 1583 Projects.Data.unloading = false; 1584 1585 // Set the title back 1586 Cargo.History.SetWindowTitle(true); 1587 1588 }, 1589 1590 /** 1591 * Convert a hash link to a slash link 1592 * At the end of this, we fire the history load event 1593 */ 1594 HashToSlash : function() { 1595 var uri = this.SanitizeURI(), 1596 path = stripTrailingSlash( location.pathname ); 1597 1598 uri = path + uri.replace("#/", "/").replace("#", "/"); 1599 1600 // Custom domains will have an additional slash, get rid of those 1601 uri = uri.replace("//", "/"); 1602 1603 // Send them on their way 1604 Cargo.History.Load( uri ); 1605 }, 1606 1607 /** 1608 * Sanitize the incoming URI by removing any PID 1609 */ 1610 SanitizeURI : function() { 1611 var url = "", 1612 hash_to_parts = location.hash 1613 .replace("#/", "/") 1614 .replace("#/", "/") 1615 .replace("#", "/") 1616 .split("/") 1617 .splice(1); 1618 1619 // If the last char is a slash, remove it 1620 url = stripTrailingSlash( url ); 1621 1622 // If the first part of the hash array is a pid, remove it 1623 if(hash_to_parts.length >= 2 && parseInt(hash_to_parts[0]) > 0) { 1624 // Set the hashpid for use later 1625 Cargo.History.HashPID = hash_to_parts[0]; 1626 1627 for(var i=1; i<hash_to_parts.length; i++) { 1628 url += "/" + hash_to_parts[i]; 1629 } 1630 1631 } else { 1632 url += location.hash; 1633 } 1634 1635 return url; 1636 }, 1637 1638 1639 /* 1640 * Starts the HTML5 history plugin 1641 */ 1642 StartHistory : function(notify) { 1643 /* 1644 * Check for a hash 1645 * Coming in from an old hash link 1646 */ 1647 if( location.hash && Cargo.History.SupportSlashHistory() ) { 1648 // Only update for new browsers 1649 Cargo.History.RunRoute(); 1650 1651 } else if ( !Cargo.History.SupportSlashHistory() ) { 1652 // This browser does not support HTML5 history 1653 $.history.init(function(url) { 1654 /* 1655 * Check to see if there is a pid coming in 1656 * If so, reload with just the sanitized url 1657 */ 1658 if( 1659 url != Cargo.History.SanitizeURI() && 1660 "#"+url != Cargo.History.SanitizeURI() 1661 ) { 1662 Cargo.History.Load( Cargo.History.SanitizeURI() ); 1663 1664 } else { 1665 // Load this url 1666 Cargo.History.RunRouteHash( stripLeadingSlash( url ) ); 1667 } 1668 }); 1669 1670 /* 1671 * Fire some Cargo events 1672 */ 1673 this.InitEvents(); 1674 1675 } else { 1676 // This browser is compliant 1677 1678 // Create a callback 1679 this.notify = notify; 1680 1681 // Run the router 1682 Cargo.History.RunRoute(); 1683 1684 /* 1685 * Check for incoming links 1686 * If there is a pasted / direct link 1687 * Make sure it's 1688 * - not the homestate 1689 * - not following homestate 1690 * - not network filter state 1691 * - not a network display/sort 1692 * - not user filter state 1693 */ 1694 var pathname = location.pathname.toLowerCase(); 1695 var baseurl = Cargo.Location.GetBaseUrl().toLowerCase(); 1696 if( 1697 pathname != baseurl && 1698 pathname.indexOf(baseurl + "/preview/") < 0 && 1699 pathname != Cargo.Location.GetBaseUrl("following") && 1700 pathname != baseurl + Cargo.History.GetNetworkFilter().toLowerCase() && 1701 pathname != baseurl + Cargo.History.GetNetworkSorting().toLowerCase() && 1702 pathname != baseurl + Cargo.History.GetUserFilter().toLowerCase() && 1703 pathname != baseurl + Cargo.History.GetUserFilter().toLowerCase() + "/" && 1704 !Cargo.Location.IsInAdmin() && 1705 pathname != "/" && 1706 pathname != baseurl+"/" && 1707 pathname != "/index.php" && 1708 !Cargo.Location.IsNetworkMemberList() 1709 ) { 1710 // Give 1 ms timeout to prevent this event firing before document.ready 1711 setTimeout(function() { 1712 $(document).trigger("projectLoadComplete", [ false ]); 1713 }, 1); 1714 1715 1716 } 1717 1718 /* 1719 * Fire some Cargo events 1720 */ 1721 this.InitEvents(); 1722 1723 // Used to detect initial (useless) popstate 1724 var popped = ('state' in window.history), 1725 initialURL = location.href; 1726 1727 /* 1728 * Bind for the back/forward button 1729 * by listening to the pop state 1730 * Timer to avoid Chrome's load issue 1731 */ 1732 setTimeout(function() { 1733 Cargo.History.BindEvent("popstate", function() { 1734 1735 // Ignore inital popstate that webkit fires on page load 1736 var initialPop = !popped && location.href == initialURL; 1737 popped = true; 1738 1739 if ( initialPop ) { 1740 return; 1741 } 1742 1743 /* 1744 * Check to see if a legacy link was loaded in 1745 * This may have been because of a user's custom nav 1746 */ 1747 if( location.hash ) {
1748 Cargo.History.RunRoute(); 1749 1750 } else { 1751 Cargo.History.RunRoute(location.pathname, true); 1752 } 1753 1754 }, false); 1755 }, 1); 1756 } 1757 1758 }, 1759 1760 /** 1761 * Create a handler for event binding 1762 * This is in place because IE uses a different binder then 1763 * the rest of the browsers, naturally. 1764 */ 1765 BindEvent : function(event_name, event_function) { 1766 if (window.addEventListener){ 1767 window.addEventListener(event_name, event_function, false); 1768 } else if (window.attachEvent){ 1769 window.attachEvent(event_name, event_function); 1770 } 1771 1772 }, 1773 1774 1775 /* 1776 * Takes all links with the rel= tag and binds them to the history 1777 * Processes the hash or slash out of the href 1778 * @var pre_path : string; used as modifier e.g. "following" || "[network url]" 1779 * @var page : string; used when paginating and binding only one page at a time 1780 */ 1781 BindLinks : function(pre_path, page, single) { 1782 // If this is a new page, use the page to load history 1783 if(page && page > 0) { 1784 var history_links = "#page_" + page + " a[rel='history']" 1785 1786 } else if(single) { 1787 // Used when adding just a single element as the history eg: SpaceCollective 1788 var history_links = single; 1789 1790 } else { 1791 // Just use all history elements 1792 var history_links = "a[rel='history']"; 1793 } 1794 1795 $(history_links).unbind("click").die("click").each(function() { 1796 // Make the links 1797 Cargo.History.MakeLink( $(this).attr("href"), $(this) ); 1798 1799 // Set the value for lookup later 1800 Cargo.History.Set( $(this).data("hash"), $(this) ); 1801 1802 }).click(function(e) { 1803 // If control+click or middle click, open new tab 1804 if(e.metaKey || e.which == 2) { 1805 window.open( $(this).attr("href") ); 1806 } else { 1807 Cargo.History.Load( $(this).data("hash") ); 1808 } 1809 1810 return false; 1811 }); 1812 }, 1813 1814 /* 1815 * For ajax history, set the title of the page 1816 */ 1817 SetWindowTitle : function(is_unload) { 1818 if(!is_unload) { 1819 if(Projects.Data.project_title) { 1820 document.title = Projects.Data.project_title + " - " + Cargo.Config.website_title; 1821 } 1822 1823 } else { 1824 document.title = Cargo.Config.website_title; 1825 } 1826 }, 1827 1828 /* 1829 * Initialize the history plugin 1830 * If HTML5 pushState is available, this will take preference 1831 * Do not load this on search results, or permalink pages 1832 * var "pre_path" = string; e.g. "following" || "network" 1833 */ 1834 Init : function(pre_path, page, single) { 1835 if( 1836 $(".search_results").length == 0 && 1837 ($("#maincontainer").length > 0 || $("#items_container").length > 0) 1838 ) { 1839 // Bind all the links found on the page 1840 Cargo.History.BindLinks(pre_path, page, single); 1841 1842 if( !single && (!page || page <= 1) ) { 1843 // Start the history 1844 Cargo.History.StartHistory(function(url) { }); 1845 } 1846 1847 } 1848 }, 1849 1850 /** 1851 * Initialize the history for designs that use auto pagination 1852 * eg. tesla, apollo, limelight 1853 * Binds only new links to the page 1854 * Just a wrapper for init 1855 */ 1856 InitPagination : function(page) { 1857 this.Init(false, page, false); 1858 }, 1859 1860 /** 1861 * First some initial events 1862 * This will tell the homestate if there are direct links, start pages etc 1863 * Abstracted for use with old + new history 1864 */ 1865 InitEvents : function() { 1866 // If this is a editing a project 1867 if( Cargo.Location.IsEditingProject() ) { 1868 $(document).trigger("editProjectLoaded", [ location.pathname ]); 1869 } 1870 // If this is a solo link 1871 else if( Cargo.Location.IsSoloLink() ) { 1872 $(document).trigger("soloLinkLoaded", [ location.pathname ]); 1873 } 1874 // If a direct link is loaded 1875 else if( Cargo.Location.IsDirectLink() ) { 1876 // Fire the event for direct link 1877 $(document).trigger("directLinkLoaded", [ location.pathname ]); 1878 } 1879 // Fire the direct link loaded event for admin and solo 1880 else if( Cargo.Location.IsEditingProject() || Cargo.Location.IsSoloLink() ) { 1881 // Fire the event for direct link 1882 $(document).trigger("directLinkLoaded", [ location.pathname ]); 1883 } 1884 // If a start project is loaded on page load, fire an event 1885 else if( Cargo.Location.IsStartProject() ) { 1886 $(document).trigger("startProjectLoaded"); 1887 1888 } 1889 1890 1891 }, 1892 1893 /** 1894 * Initialize the following-list and followed-list history 1895 * Uses the hash method only 1896 */ 1897 InitFollowlist : function() { 1898 $.history.init(changeFollowPage); 1899 $("a[rel='history']").live("click", function(){ 1900 var hash = this.href; 1901 hash = hash.replace(/^.*#/, ''); 1902 $.history.load(hash); 1903 return false; 1904 }); 1905 } 1906 1907}; // END History 1908 1909 1910/* !Cargo.Analytics */ 1911Cargo.Analytics = { 1912 Config: { 1913 id: 'UA-1837333-7', 1914 name: '__cargo_analytics', 1915 }, 1916 1917 enabled: true, 1918 1919 Init: function() { 1920 1921 if(typeof _use_google_analytics !== 'undefined') { 1922 this.enabled = _use_google_analytics === 1; 1923 } 1924 1925 if (Cargo.Location.IsCustomDomain()) { 1926 this.Config.custom_url = '/' + document.location.host; 1927 } 1928 1929 if(this.enabled) { 1930 1931 // Include analytics.js 1932 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 1933 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 1934 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 1935 })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); 1936 1937 // Create Google Analytics tracker, send initial pageview 1938 ga('create', this.Config.id, 'auto', {'name': this.Config.name, 'cookieName': this.Config.name}); 1939 1940 this.pageview(false); 1941 1942 } 1943 1944 // Send pageviews on project load 1945 $(document).bind("projectLoadComplete", function(e, pid) { 1946 if (! Cargo.Location.IsDirectLink() && ! Cargo.Location.IsStartProject()) { 1947 Cargo.Analytics.pageview(true); 1948 } 1949 }); 1950 }, 1951 1952 pageview: function(send_to_all_trackers, url) 1953 { 1954 if (typeof url !== 'undefined' && ! send_to_all_trackers) { 1955 if(this.enabled) { 1956 ga(this.Config.name + '.send', 'pageview', { 1957 'page': url, 1958 'dimension3': 'Cargo 1' 1959 }); 1960 } 1961 return; 1962 } 1963 1964 var tracker = this.Config.name, 1965 pathname = document.location.pathname.replace(/\/$/, ''); 1966 1967 if(this.enabled) { 1968 if (typeof this.Config.custom_url !== 'undefined') { 1969 ga(this.Config.name + '.send', 'pageview', { 1970 'page': this.Config.custom_url + pathname, 1971 'dimension3': 'Cargo 1' 1972 }); 1973 } else { 1974 ga(this.Config.name + '.send', 'pageview', { 1975 'dimension3': 'Cargo 1' 1976 }); 1977 } 1978 } 1979 1980 // Send data for any other trackers 1981 if (typeof ga == 'function' && send_to_all_trackers) { 1982 ga(function() { 1983 ga.getAll().map(function(g) { 1984 var t = g.get('name'); 1985 if (t != tracker) {
1986 ga(t + '.send', 'pageview'); 1987 } 1988 }); 1989 }); 1990 1991 // Push data to legacy trackers 1992 if (typeof _gaq !== 'undefined') { 1993 _gaq.push(['_trackPageview', pathname]); 1994 } 1995 } 1996 } 1997}; 1998 1999Cargo.EU_cookie_notification = function() { 2000 if($('head meta[name="en_cookie_notification"]').length > 0) { 2001 if(!localStorage.getItem('eu_cookie_notification')) { 2002 var class_name = $('head meta[name="en_cookie_notification"]').attr('position'), 2003 content = $('head meta[name="en_cookie_notification"]').attr('description'), 2004 link = $('head meta[name="en_cookie_notification"]').attr('policy_link'); 2005 content = content.replace('[policy_link]', '<a href="'+link+'" target="_blank">').replace('[/policy_link]','</a>'); 2006 2007 $('body').prepend('<div id="eu_cookie_notification" class="'+class_name+'">'+content+'</div>'); 2008 2009 $("#eu_cookie_notification").click(function(e) { 2010 if($(e.target).is('a')){ 2011 return true; 2012 } 2013 2014 $(this).remove(); 2015 localStorage.setItem('eu_cookie_notification', 'true'); 2016 }); 2017 } 2018 } 2019}; 2020 2021 2022///////////////////////////////////////////////////////////////////////////////////////////////// 2023/** 2024 * Projects class 2025 * 2026 * 2027 * @todo: description 2028 */ 2029/* !Projects */ 2030var Projects = { 2031 2032 "Data" : { 2033 "is_start_page" : false, // If opening project is a start project 2034 "unloading" : false, // If a project is unloading 2035 "pid" : "", // The current pid 2036 2037 "purl" : "", // purl when parsing the URL 2038 "follow_sort" : "", // follow sort value when parsing the URL (postswithcomments) 2039 "network_sort" : "", // network sort value when parsing the URL (mine) 2040 "user_url" : "", // The user URL when parsing the URL 2041 "network_url" : "", // The newtwork URL when parsing the URL 2042 "user_filter" : "", // The filter on a user page 2043 "network_filter": "", // The filter on a network 2044 "attr" : "", // attribute of the URL (like comments) when parsing 2045 "do_scroll" : true, // scroll to the top of the page after load, or not 2046 2047 "slideheight" : "", // Returned from Ajax opening 2048 "slidecount" : "", // Returned from Ajax opening 2049 "content" : "", // The full content returned from Ajax 2050 "project_title" : "", // Title of the project, returned from Ajax 2051 "CloseObj" : "" // a jQuery object of the close button clicked 2052 }, 2053 2054 2055 /** 2056 * Determines which type of project load 2057 * Always attempt to load from PID first 2058 */ 2059 LoadProject : function() { 2060 if( Projects.Data.pid !== false ) { 2061 Projects.AjaxLoadByPid(); 2062 2063 } else { 2064 Projects.AjaxLoadByPurl(); 2065 } 2066 }, 2067 2068 /** 2069 * Ajax load a project via the pid 2070 */ 2071 AjaxLoadByPid : function( pid ) { 2072 2073 if(pid) { 2074 // Set the PID 2075 this.Data.pid = pid; 2076 } 2077 2078 /* 2079 * Check to see if there is a custom ajax load 2080 * If so, use that 2081 */ 2082 if (typeof Projects.CustomAjaxLoadByPid == "function") { 2083 Projects.CustomAjaxLoadByPid( this.Data.pid ); 2084 return; 2085 } 2086 2087 2088 if( this.Data.user_url == "" ) { 2089 this.Data.user_url = $("#url").val(); 2090 2091 } 2092 2093 // Assume we are going to load the project using ajax 2094 this.FireAjax = true; 2095 2096 // If everything is ok, we have a PID to load, fire away 2097 if( Projects.FireAjax === true && this.Data.pid && this.Data.pid != "none" ) { 2098 // Load all of the helpers at once 2099 Projects.TriggerPreloadHelpers(); 2100 2101 var data = { 2102 pid : this.Data.pid, 2103 url : this.Data.user_url, 2104 nurl : this.Data.network_url, 2105 is_following : Cargo.Location.IsFollowing(), 2106 design : $("#design").val(), 2107 template : $("#template").val()/*, 2108 viewtype : $("#viewtype").val() 2109 */ 2110 }, 2111 2112 path = Cargo.Location.GetDomain() + 2113 $("#templatepath").val() + 2114 Cargo.Config.get('project_single'); 2115 2116 2117 $.post( path, data, function(dataObj) { 2118 if(dataObj !== "") { 2119 Projects.WriteProject(dataObj); 2120 2121 } else { 2122 // If a failed load happens, close this load 2123 Projects.CloseProject(); 2124 } 2125 }); 2126 2127 } else { 2128 // Hide the spinner
2129 Projects.Helper.HideSpinners(); 2130 } 2131 2132 }, 2133 2134 /** 2135 * Ajax load a project via the purl 2136 */ 2137 AjaxLoadByPurl : function() { 2138 // If no url is defined, define it 2139 if( this.Data.user_url == "" ) { 2140 this.Data.user_url = $("#url").val(); 2141 } 2142 2143 // Make sure we have something to look for 2144 if( this.Data.purl ) { 2145 2146 var data = { 2147 purl : this.Data.purl, 2148 url : this.Data.user_url, 2149 nurl : this.Data.network_url, 2150 is_following : Cargo.Location.IsFollowing() 2151 }, 2152 2153 path = Cargo.Location.GetDomain() + 2154 $("#templatepath").val() + 2155 Cargo.Config.get('project_single'); 2156 2157 $.post( path, data, function(dataObj) { 2158 if(dataObj !== "") { 2159 // Write the project 2160 Projects.WriteProject(dataObj); 2161 2162 // Set the current vals 2163 $("#prev_open").val( $("#current_open").val() ); 2164 $("#current_open").val(Projects.Data.pid); 2165 2166 } else { 2167 // If a failed load happens, close this load 2168 Projects.CloseProject(); 2169 } 2170 }); 2171 2172 2173 } 2174 }, 2175 2176 /** 2177 * Write the return data from the ajax loaded post 2178 * Prints the project into a container 2179 * Does a little housekeeping and garbage collecting 2180 */ 2181 WriteProject : function(data) { 2182 // Gather data 2183 this.Helper.ProcessData(data); 2184 2185 if(this.Data.pid === false || this.Data.pid === null) { 2186 /* 2187 * Failed load, don't continue 2188 * Trigger post load helpers 2189 */ 2190 Projects.TriggerPostloadHelpers(); 2191 2192 // Render a 404 2193 //Projects.Render404(); 2194 2195 } else if( 2196 $("#entry_"+this.Data.pid).length > 0 && 2197 ! $("#item_"+this.Data.pid).hasClass("project_feed_full") 2198 ) { 2199 /* 2200 * Content was loaded, but it is already on the page 2201 * Trigger post load helpers 2202 */ 2203 Projects.TriggerPostloadHelpers(); 2204 2205 } else { 2206 /* 2207 * Print the content 2208 */ 2209 2210 // Unload any audio on the page 2211 unloadAudio(); 2212 2213 // Check for a custom write project 2214 if (typeof Projects.CustomWriteProject == "function") { 2215 Projects.CustomWriteProject(data); 2216 return; 2217 2218 // If this is an SC project use a different method 2219 } else if( $("#template").val() == "spacecollective") { 2220 this.WriteProjectSC(); 2221 return; 2222 2223 // If this is a homepage project 2224 } else if($("#pRow"+this.Data.pid).length > 0) { 2225 this.WriteProjectHome(); 2226 return; 2227 } 2228 2229 // Figure out which container to load into 2230 var container = Projects.Helper.GetContainer(); 2231 2232 // Print the project to the container 2233 $(container).html( this.Data.content ); 2234 2235 // Trigger post load helpers 2236 Projects.TriggerPostloadHelpers(); 2237 2238 if(this.Data.attr == "comments") { 2239 // Scroll to the comments 2240 // Anchor to 1/3 screen 2241 anchorTo('comment_post_'+this.Data.pid, Math.ceil($(window).height()/1.5), true); 2242 this.Data.attr = ""; // Reset after use 2243 2244 } else if( this.Data.do_scroll) { 2245 // Scroll to the top of the page 2246 Projects.Helper.ScrollToTop(); 2247 } 2248 2249 } // end if content is correct 2250 2251 }, 2252 2253 /** 2254 * There is such a large difference between Escher and SC 2255 * this method is called by the WriteProject method 2256 */ 2257 WriteProjectSC : function() { 2258 // Assume we can print this project 2259 this.PrintProject = true; 2260 2261 // Unload any audio on the page 2262 unloadAudio(); 2263 2264 // Figure out which container to load into 2265 container = Projects.Helper.GetContainer(); 2266 2267 // Make interventions before content is printed 2268 Projects.Helper.PostloadSC_pre_content(); 2269 2270 // Print the project to the container 2271 if(this.PrintProject === true) { 2272 $(container).html( this.Data.content ); 2273 } 2274 2275 // Make interventions after content is printed 2276 Projects.Helper.PostloadSC_post_content(); 2277 2278 // Hide the spinner 2279 Projects.Helper.HideSpinners(); 2280 2281 // Set the title 2282 Cargo.History.SetWindowTitle(); 2283 2284 }, 2285 2286 WriteProjectHome : function() { 2287 $("#pRow"+this.Data.pid).attr("class", "content_container_open").html( this.Data.content ); 2288 Projects.Slideshow.CheckForSlideshow(); 2289 Projects.Video.CheckForVideo(); 2290 }, 2291 2292 /** 2293 * Fires all of the helper methods 2294 * Useful when needing to update highlights 2295 * without ajax loading a project 2296 */ 2297 TriggerPreloadHelpers : function(pid) { 2298 // Set this if it is incoming 2299 if(pid) this.Data.pid = pid; 2300 2301 // Fire the Cargo events 2302 Projects.Helper.TriggerPreloadCargoEvents(); 2303 2304 // Show the spinner 2305 Projects.Helper.ShowSpinners(); 2306 2307 // Remove any old highlights 2308 Projects.Helper.RemoveNavHighlight(); 2309 2310 // Set the navigation highlight 2311 if( !Projects.Data.is_start_page ) { 2312 Projects.Helper.SetNavHighlight(); 2313 } 2314 2315 // Set the current page 2316 Projects.Helper.SetCurrentPages(); 2317 2318 // Intervention for the SpaceCollective design(s) 2319 Projects.Helper.PreloadInterventionSC(); 2320 2321 // Stop any slideshow cycles 2322 Projects.Helper.KillSlideshows(); 2323 2324 // Remove detail_preload 2325 $( Projects.Helper.GetContainer() ).removeClass("detail_preload"); 2326 2327 // Remove the fullscreen 2328 if( $("#freshbox").length > 0) { 2329 $(".entry").FreshBox().Close(); 2330 $(".entry").FreshBox().CloseFullscreen(); 2331 } 2332 2333 // Video 2334 // Projects.Video.CheckForVideo(); 2335 }, 2336 2337 /** 2338 * Fires all the helper methods 2339 * For after the project is returned from AJAX 2340 */ 2341 TriggerPostloadHelpers : function() { 2342 // Set the title 2343 Cargo.History.SetWindowTitle(); 2344 2345 // Hide the spinner
2346 Projects.Helper.HideSpinners(); 2347 2348 // Remove the thumb highlight 2349 Projects.Helper.RemoveThumbHighlight(); 2350 2351 // Remove any old highlights 2352 Projects.Helper.RemoveNavHighlight(); 2353 2354 // Set the highlight for the project thumb 2355 if( !Projects.Data.is_start_page ) { 2356 Projects.Helper.SetThumbHighlight(); 2357 Projects.Helper.SetNavHighlight(); 2358 } 2359 2360 // Set the current page 2361 Projects.Helper.SetCurrentPages(); 2362 2363 // Any user options set that need to happen 2364 Projects.Helper.UserOptionActions(); 2365 2366 // Unhide the container 2367 var container = Projects.Helper.GetContainer(); 2368 $(container).show(); 2369 2370 // Fire the Cargo events 2371 Projects.Helper.TriggerPostloadCargoEvents(); 2372 2373 // Reset the start page data 2374 if( Projects.Data.is_start_page ) { 2375 $(".project_index").remove(); 2376 Projects.Data.is_start_page = false; 2377 } 2378 2379 // Video 2380 // Projects.Video.CheckForVideo(); 2381 }, 2382 2383 /** 2384 * Close a single project 2385 * Unloads all of the content and set the view state back to normal 2386 */ 2387 CloseProject : function(no_history) { 2388 var pid = $("#current_open").val(); 2389 2390 // This is a hack for the SC design. Should be converted, but for now leaving it 2391 if($("#template").val() == "spacecollective") { 2392 closeFeedPr(pid,false,'list'); 2393 $(document).trigger("projectCloseComplete", [pid, $("#maincontainer")]); 2394 Cargo.History.Unload(); 2395 return; 2396 } 2397 2398 // Unload any audio on the page 2399 unloadAudio(); 2400 2401 // Check for a custom write project 2402 if (typeof Projects.CustomCloseProject == "function") { 2403 Projects.CustomCloseProject(pid, no_history); 2404 return; 2405 2406 } else { 2407 // Fire some Cargo events 2408 $(document).trigger("projectClose", [ $("#maincontainer") ] ); 2409 $(document).trigger("projectIndex", [ pid ]); 2410 2411 // Unload the content 2412 $("#maincontainer").html("").css("display", "none").removeClass("detail_preload"); 2413 2414 // Unload the history 2415 if(!no_history) { 2416 Cargo.History.Unload(); 2417 } 2418 2419 if (jQuery.browser.safari && this.Data.do_scroll ) window.scrollTo(0,0); 2420 2421 $(document).trigger("projectCloseUnload", [pid, $("#maincontainer")]); 2422 2423 $('#pr_contain_item_'+pid).attr("class", ""); 2424 2425 if($("#o_thumb_nav").val() == "yes") { 2426 $("#page_"+$("#current_page").val()).css("display","block"); 2427 2428 } 2429 2430 $(".project_thumb, .project_feed_thumb").removeClass("active").removeClass("selected"); 2431 $(".nav_active").removeClass("nav_active"); 2432 2433 $(document).trigger("projectCloseComplete", [pid, $("#maincontainer")]); 2434 2435 if( this.Data.do_scroll && !$.browser.safari ) { 2436 // Scroll back to the top 2437 Projects.Helper.ScrollToTop(); 2438 } 2439 } 2440 }, 2441 2442 /* 2443 * Shows the next project 2444 * This is fired from the event "showNextProject" 2445 * Non-feed based designs only 2446 */ 2447 ShowNextProject : function() { 2448 // Set the default of the next spot to be the first spot 2449 var next = 0; 2450 2451 // Make sure the SC/Network designs are not mid load (prevents rapid fire next project) 2452 if( 2453 $("#load_"+Projects.Data.pid).css("display") == "block" && 2454 ($("#template").val() == "spacecollective" || $("#template").val() == "network") 2455 ) { 2456 return; 2457 2458 // There is a pre-defined pid, load the next 2459 } else if(Projects.Data.pid || $("#start_page").length > 0) { 2460 var cur = Projects.Data.pid ? Projects.Data.pid : $("#start_page").val(); 2461 var spot = array_search(cur, pr_list); 2462 2463 if(spot !== false && spot < pr_list.length-1) { 2464 // Next = next 2465 next = parseInt(spot)+1; 2466 } 2467 2468 } 2469 2470 // Get the purl and load it 2471 var next_purl = Cargo.History.GetPurlFromPid(pr_list[next]); 2472 Cargo.History.Load( next_purl ); 2473 2474 }, 2475 2476 /* 2477 * Shows the previous project 2478 * This is fired from the event "showPrevProject" 2479 * Non-feed based designs only 2480 */ 2481 ShowPreviousProject : function() { 2482 // Set the default of the next spot to be the last spot 2483 var next = pr_list.length-1; 2484 2485 // Make sure the SC/Network designs are not mid load (prevents rapid fire next project) 2486 if( 2487 $("#load_"+Projects.Data.pid).css("display") == "block" && 2488 ($("#template").val() == "spacecollective" || $("#template").val() == "network") 2489 ) { 2490 return; 2491 2492 // There is a pre-defined pid, load the prev 2493 } else if(Projects.Data.pid) { 2494 var spot = array_search(Projects.Data.pid, pr_list); 2495 2496 if(spot != 0) { 2497 // Make sure we're not at the start 2498 next = parseInt(spot)-1; 2499 } 2500 2501 } 2502 2503 // Get the purl and load it 2504 var next_purl = Cargo.History.GetPurlFromPid(pr_list[next]); 2505 Cargo.History.Load( next_purl ); 2506 2507 2508 }, 2509 2510 /* 2511 * Shows a random project 2512 * This is fired from the even "showRandomProject" 2513 * Non-feed based designs only 2514 */ 2515 ShowRandomProject : function() { 2516 // Set a default for the next spot 2517 var next = Math.floor(Math.random()*pr_list.length); 2518 2519 // If there is a project open, make sure this is not that project 2520 if(Projects.Data.pid) { 2521 var cur = array_search(Projects.Data.pid, pr_list); 2522 if(cur == next) { 2523 // Randomize again 2524 next = Math.floor(Math.random()*pr_list.length); 2525 } 2526 } 2527 2528 var next_purl = Cargo.History.GetPurlFromPid(pr_list[next]); 2529 2530 // If no URL is found, then pass the PID instead 2531 if(next_purl == undefined) { 2532 next_purl = pr_list[next]; 2533 } 2534 Cargo.History.Load( next_purl ); 2535 }, 2536 2537 /* 2538 * Shows the next project 2539 * This is fired from the event "showNextProject" 2540 * Feed based designs only 2541 */ 2542 ShowNextFeedProject : function() { 2543 var move_speed = 250; 2544 var padding = viewport_threshold; 2545 var current = $(".entry:in-viewport").attr("id"); 2546 2547 // If we don't have a current post and we've scrolled, then we are still moving 2548 if(!current && $(window).scrollTop() > 20) { 2549 return false; 2550 } 2551 2552 var next_post = (!current) ? "#"+$(".entry:first").nextAll(".entry").attr("id") : "#"+$("#"+current).nextAll(".entry").attr("id"); 2553 2554 if (next_post != "#undefined") { 2555 var next_offset = $(next_post).offset().top-padding; 2556 2557 clearTimeout(timer); 2558 window.scrollTo(0, (next_offset-padding)); 2559 doscroll(next_offset,$(window).scrollTop(),0); 2560
2561 //$.scrollTo(next_post, move_speed, {offset: {top:-padding}}); 2562 var within_bounds = (($(window).scrollTop()+$(window).height()) >= ($("body").height()-1500)) ? true : false; 2563 if(next_post == "#"+$(".entry:last").prevAll(".entry").attr("id") && !within_bounds) getMoreHistory(); 2564 } 2565 }, 2566 2567 /* 2568 * Shows the previous project 2569 * This is fired from the event "showPrevProject" 2570 * Feed based designs only 2571 */ 2572 ShowPreviousFeedProject : function() { 2573 var move_speed = 250; 2574 var padding = viewport_threshold; 2575 var current = "#"+$(".entry:in-viewport").attr("id"); 2576 2577 if (current != "#undefined") { 2578 if($(window).scrollTop() > $(current).offset().top) { 2579 if(current != "#"+$(".entry:last").attr("id")) current = "#"+$(current).nextAll(".entry").attr("id"); 2580 else current = "."+$(current).next().attr("class"); 2581 2582 if(current == ".") current = "#new_page_content"; 2583 } 2584 2585 var prev_post = ($(current).prevAll(".entry").length <= 0) ? "body" : "#"+$(current).prevAll(".entry").attr("id"); 2586 var prev_offset = $(prev_post).offset().top; 2587 2588 clearTimeout(timer); 2589 window.scrollTo(0, prev_offset); 2590 doscroll((prev_offset-padding),$(window).scrollTop(),0); 2591 //$.scrollTo(prev_post, move_speed, {offset: {top:-padding}}); 2592 2593 } 2594 }, 2595 2596 /** 2597 * Error handler for write project 2598 * This gets triggered by Projects.Helper.ProcessData 2599 * If there is an error found, this fires 2600 */ 2601 ErrorHandler : function() { 2602 if(this.Data.redirect_url != "" ) { 2603 document.location.href = this.Data.redirect_url; 2604 } 2605 }, 2606 2607 /** 2608 * Render a 404 page 2609 * First ajax load the user 404 page 2610 * Then replace the entire content with the result 2611 */ 2612 Render404 : function() { 2613 2614 Cargo.log("Not found: 404"); 2615 2616 /* Commented out until problems stop 2617 var data = { 2618 "url" : Cargo.Location.GetCargoUrl(), 2619 "uri" : Cargo.Location.GetCargoUrl() 2620 }; 2621 2622 $.ajax( { 2623 type : "POST", 2624 url : Cargo.Config.get("fourOfour") + "/" + Cargo.Location.GetCargoUrl() + "/" + Cargo.Location.GetCargoUrl(), 2625 data : data, 2626 2627 // Use the error type, because 404 renders "not found" headers 2628 error : function(xhr, textStatus, errorThrown) { 2629 // Remove the user's stylesheet 2630 $("#user_stylesheet").remove(); 2631 2632 // Replace the body content with 404 page 2633 $("body").css("background-color","#0000ad").html(xhr.responseText); 2634 } 2635 }); 2636 */ 2637 2638 } 2639 2640}; // end Projects 2641 2642/** 2643 * Helper methods for projects 2644 * Includes setting navigation, current pages, etc 2645 * Accepts the pid value of the project being opened 2646 */ 2647/* !Projects.Helper */ 2648Projects.Helper = { 2649 2650 /** 2651 * Process the ajax return data 2652 */ 2653 ProcessData : function(data) { 2654 try { 2655 // Verify this is proper JSON 2656 var jdata = $.parseJSON(data); 2657 Projects.Data.pid = jdata.pid, 2658 Projects.Data.slideheight = jdata.slideheight, 2659 Projects.Data.slidecount = jdata.slidecount, 2660 Projects.Data.content = jdata.content; 2661 Projects.Data.project_title = jdata.title; 2662 Projects.Data.project_title = jdata.title; 2663 Projects.Data.error = jdata.error; 2664 Projects.Data.redirect_url = jdata.redirect_url; 2665 2666 } catch (e) { 2667 // Invalid JSON 2668 Projects.Data.slideheight = 0, 2669 Projects.Data.slidecount = 0, 2670 Projects.Data.content = data; 2671 Projects.Data.project_title = ""; 2672 return false; 2673 } 2674 2675 if(Projects.Data.error && Projects.Data.error.length > 0) { 2676 Projects.ErrorHandler(); 2677 return false; 2678 } 2679 2680 }, 2681 2682 /** 2683 * Set the current page, prev page, and spot 2684 * Then check pagination and go to that page if needed 2685 */ 2686 SetCurrentPages : function() { 2687 // Set previous and current 2688 $("#prev_open").val( $("#current_open").val() ); 2689 $("#current_open").val(Projects.Data.pid); 2690 2691 // Find and set what spot we are (for next/prev) 2692 if( typeof pid_list != "undefined" ) { 2693 var this_spot = pid_list.indexOf(Projects.Data.pid); 2694 this_spot = (!this_spot) ? -1 : this_spot; 2695 $("#this_spot").val(this_spot); 2696 } 2697 2698 var thispage = $("#item_"+Projects.Data.pid).attr("page"), 2699 limit = $("#limit").val(), 2700 cur = $("#current_page").val(); 2701 2702 // Check to see if we need to go to a new page 2703 if(thispage && thispage != 0) { 2704 if(thispage != cur) { 2705 // Go to the new page 2706 changePage(thispage,limit); 2707 $("#this_spot").val( $("#item_"+Projects.Data.pid).attr("spot") ); 2708 } 2709 } 2710 2711 //} 2712 }, 2713 2714 /** 2715 * Intervention for the SC design 2716 * Sets a flag to not open, if need be 2717 */ 2718 PreloadInterventionSC : function() { 2719 // If this is SpaceCollective and not a network 2720 if($('#items_container').length > 0 && $("#templatepath").val().indexOf("network") === 0) { 2721 // If this is the same project that is already open, don't re-open 2722 if( Projects.Data.pid == $("#prev_open").val() ) { 2723 Projects.FireAjax = false; 2724 } 2725 2726 // Store this project in a var to re-use on close 2727 } else { 2728 $("#moduleholder_c").val( $("#moduleholder_o").val() ); 2729 $("#moduleholder_o").val( $("#item_"+Projects.Data.pid).html() ); 2730 $("#modulenumber").val( $("#prev_open").val() ); 2731 } 2732 2733 }, 2734 2735 /**
2736 * Intervention for the SC design after ajax load 2737 * This fires before the content is printed 2738 */ 2739 PostloadSC_pre_content : function() { 2740 2741 var this_item = $("#item_"+Projects.Data.pid); 2742 2743 // Same project and it's already open, don't print 2744 if( Projects.Data.pid == $("#prev_open").val() && $(this_item).attr("class") == "project_feed_full") { 2745 Projects.PrintProject = false; 2746 2747 } else { 2748 $(this_item) 2749 .attr("onmouseover", "") 2750 .attr("onmouseout", "") 2751 .attr("class", "project_feed_full"); 2752 2753 if( Cargo.Config.isIE() ) { 2754 // Adds the rounded corners to IE 2755 $(this_item).addClass("ie"); 2756 } 2757 2758 // Adds rounded corners to everyone else 2759 try { DD_roundies.addRule(".project_feed_full", 5, true); } catch(err) { } 2760 2761 // If there was a project already open, close it 2762 if( $("#moduleholder_c").val() != "none" && $("#modulenumber").val() != $(this_item).attr("name")) { 2763 printClosed( $("#modulenumber").val(), $("#moduleholder_c").val(), true); 2764 // Dump the values 2765 $("#modulenumber").val("none"); 2766 $("#moduleholder_c").val("none"); 2767 } 2768 } 2769 }, 2770 2771 /** 2772 * Intervention for the SC design after ajax 2773 * This fires after the content is printed 2774 */ 2775 PostloadSC_post_content : function() { 2776 2777 // disable scroll restore 2778 if ('scrollRestoration' in history) { 2779 history.scrollRestoration = 'manual'; 2780 } 2781 2782 // Reshuffle the cards 2783 shiftPosition(); 2784 2785 // Reset the start page data 2786 Projects.Data.is_start_page = false; 2787 2788 // Add a spacer and hide the container 2789 $('#item_'+Projects.Data.pid+" #body_container").before( 2790 '<div style="height:'+ $('#item_'+Projects.Data.pid).height() +'px" id="cardspacer"> </div>' 2791 ).css("display","none"); 2792 2793 // For fixed headers, set a differnt top pad 2794 var toppad = 60; 2795 if($(".header_img").css("position") == "fixed") { 2796 toppad = $(".header_img").height(); 2797 } 2798 2799 // Hide the project header if in the admin edit view 2800 if(Cargo.Location.IsInAdmin()) { 2801 $(".project_header").remove(); 2802 } 2803 2804 // If this is not a start project, scroll to the top 2805 if( $('#startpage').val() == 'none' || $('#startpage').val() != Projects.Data.pid ) { 2806 2807 var window_top_height = toppad + getMass(".header_img", "height") + getMass(".nav_container.horizontal", "height"); 2808 2809 // If there is not already a defined way to handle this 2810 if( 2811 $('#item_'+Projects.Data.pid).offset() && 2812 ( 2813 ( $('#item_'+Projects.Data.pid).offset().top < window_top_height && 2814 $(window).scrollTop() > 10 ) || 2815 $('#item_'+Projects.Data.pid).offset().top > window_top_height 2816 ) 2817 ) { 2818 2819 $.scrollTo( 2820 { top:($('#item_'+Projects.Data.pid).offset().top-toppad), left:0}, 2821 450, 2822 { onAfter:function(){ 2823 $('#cardspacer').remove(); 2824 $('#item_'+Projects.Data.pid+" #body_container").fadeIn(); 2825 $('#item_'+Projects.Data.pid).addClass("open"); 2826 shiftPosition(); 2827 } 2828 }); 2829 2830 } else { 2831 2832 $('#cardspacer').remove(); 2833 $('#item_'+Projects.Data.pid+" #body_container").fadeIn(); 2834 $('#item_'+Projects.Data.pid).addClass("open"); 2835 2836 } 2837 2838 // This is a start project, fade it in 2839 } else { 2840 $('#cardspacer').remove(); 2841 $('#item_'+Projects.Data.pid+" #body_container").fadeIn(); 2842 } 2843 2844 $('#startpage').val('none'); 2845 $(document).trigger("SCprojectLoadComplete", [ Projects.Data.pid ]); 2846 2847 // Fire the Cargo events 2848 Projects.Helper.TriggerPostloadCargoEvents(); 2849 }, 2850 2851 /** 2852 * Show the loading spinners 2853 */ 2854 ShowSpinners : function() { 2855 $("#load_"+Projects.Data.pid) 2856 .css("visibility", "visible") 2857 .show(); 2858 2859 if( $("#template").val() != "spacecollective") { 2860 $("#nav_loadspin") 2861 .css("visibility", "visible") 2862 .show(); 2863 } 2864 }, 2865 2866 /** 2867 * Hide the loading spinners 2868 */ 2869 HideSpinners : function() { 2870 $("#load_"+Projects.Data.pid+", #nav_loadspin").hide(); 2871 }, 2872 2873 /** 2874 * Highlights the nav item 2875 */ 2876 SetNavHighlight : function() { 2877 $("#menu_"+Projects.Data.pid).addClass("nav_active"); 2878 }, 2879 2880 /** 2881 * Removes highlight from the nav 2882 */ 2883 RemoveNavHighlight : function() { 2884 $(".nav_active").removeClass("nav_active"); 2885 }, 2886 2887 /** 2888 * Highlights the open thumbnail 2889 */ 2890 SetThumbHighlight : function() { 2891 $("#item_"+Projects.Data.pid).addClass("active"); 2892 2893 }, 2894 2895 /** 2896 * Removes the old highlight 2897 */ 2898 RemoveThumbHighlight : function() { 2899 $(".project_thumb.active").removeClass("active"); 2900 }, 2901 2902 /** 2903 * Triggers any preload events 2904 */ 2905 TriggerPreloadCargoEvents : function() { 2906 $(document).trigger("projectLoadStart", [ Projects.Data.pid, window.location.pathname.split("/") ]); 2907 }, 2908 2909 /** 2910 * Triggers any post write project events 2911 */ 2912 TriggerPostloadCargoEvents : function() { 2913 $(document).trigger("projectReady", [ { 2914 "pid" : Projects.Data.pid, 2915 "slideheight" : Projects.Data.slideheight 2916 } ]); 2917 2918 $(document).trigger("projectLoadComplete", [ Projects.Data.pid ]); 2919 }, 2920 2921 /** 2922 * Determines which container to use 2923 * returns the container 2924 */ 2925 GetContainer : function() { 2926 // Escher based 2927 if( $('#maincontainer').length > 0 ) { 2928 return $('#maincontainer'); 2929 2930 // SpaceCollective based 2931 } else if( $('#items_container').length > 0 ) { 2932 return $('#item_'+Projects.Data.pid); 2933 2934 // Homepage 2935 } else { 2936 return $("pRow"+Projects.Data.pid); 2937 } 2938 2939 }, 2940 2941 /** 2942 * Any user options that happen after loading a project 2943 * For instance, hiding of thumbnails 2944 */ 2945 UserOptionActions : function() { 2946 // Hide the thumbnails 2947 if($("#o_thumb_nav").val() == "yes") { 2948 $("#page_"+$("#current_page").val()).css("display","none"); 2949 2950 } 2951 }, 2952 2953 /** 2954 * Scroll to the top of the page 2955 */ 2956 ScrollToTop : function() { 2957 // Don't do this for SC 2958 if($("#items_container").length === 0 && $("#no_scroll").length === 0) { 2959 // If we are further then 50 from the top, jump to 50 2960 if(getScrollHeight() > 50) { 2961 window.scrollTo(0, 50); 2962 } 2963 // Smooth scroll the rest of the way 2964 doscroll(0,getScrollHeight(),0); 2965 } 2966 2967 }, 2968 2969 /** 2970 * Kill slideshow cycles 2971 * @todo move to slideshow class (when available) 2972 */ 2973 KillSlideshows : function() { 2974 // kill slideshow cycles 2975 for(i=0;i<20;i++) { 2976 clearTimeout(cycleTimeout[i]); 2977 } 2978 cycleTimeout = []; 2979 cyclePause = []; 2980 cycleComplete = []; 2981 } 2982 2983}; // end Helpers 2984 2985 2986 2987 2988///////////////////////////////////////////////////////////////////////////////////////////////// 2989/* !Projects.Slideshow */ 2990Projects.Slideshow = { 2991 /* 2992 * Set a bunch of vars that will be used with each method 2993 */ 2994 "Data" : { 2995 "do_placeholder" : false, // Use placeholder content, or activate the slideshow 2996 "thumbs_height" : [ ], // The total height of each thumbnail container 2997 "slideheight_largest": [ ], // The height of this slideshow 2998 "slidewidth_largest" : [ ], // The width of this slideshow 2999 "slideheight_first" : [ ], // The height of this slideshow 3000 "slidewidth_first" : [ ] // The width of this slideshow 3001 }, 3002 3003 // Hold the config values 3004 "Config" : { }, 3005 3006 /* 3007 * Sets the variables to be used later 3008 */ 3009 SetData : function() { 3010 var template = Cargo.Config.GetTemplate(); 3011 var design = Cargo.Config.GetDesign();
3012 if( template && design ) { 3013 this.Data.isSC = template.indexOf("spacecollective") >= 0 ? true : false; 3014 this.Data.isOz = design.indexOf("ozfeed") >= 0 ? true : false; 3015 this.Data.isTesla = design.indexOf("tesla") >= 0 ? true : false; 3016 this.Data.isRunyon = design.indexOf("runyon") >= 0 ? true : false; 3017 this.Data.isWarhol = design.indexOf("warhol") >= 0 ? true : false; 3018 // Josh commented this out on 12-7-5 because we are not sure why this is in place 3019 this.Data.isMontessori = false; //design.indexOf("montessori") >= 0 ? true : false; 3020 } 3021 3022 if( 3023 this.Data.isSC || 3024 this.Data.isOz || 3025 this.Data.isTesla || 3026 this.Data.isMontessori || 3027 this.Data.isRunyon 3028 ) { 3029 this.Data.oneFail = true; 3030 } 3031 3032 // Reset the slideshow values 3033 this.Data.slidewidth_largest = [ ]; 3034 this.Data.slideheight_largest = [ ]; 3035 this.Data.slidewidth_first = [ ]; 3036 this.Data.slideheight_first = [ ]; 3037 3038 }, 3039 3040 LoadConfig : function() { 3041 var slideconfig = $("slideconfig"); 3042 this.Config.thumb_position = slideconfig.attr("thumb_position"); 3043 this.Config.has_thumbs = slideconfig.attr("has_thumbs"); 3044 this.Config.nav_position = slideconfig.attr("nav_position"); 3045 this.Config.count_style = slideconfig.attr("count_style"); 3046 this.Config.has_count = slideconfig.attr("has_count"); 3047 this.Config.text_next = slideconfig.attr("text_next"); 3048 this.Config.text_slash = slideconfig.attr("text_slash"); 3049 this.Config.text_prev = slideconfig.attr("text_prev"); 3050 this.Config.has_textnav = slideconfig.attr("has_textnav"); 3051 this.Config.auto_delay = slideconfig.attr("auto_delay"); 3052 this.Config.is_autoplay = slideconfig.attr("is_autoplay"); 3053 this.Config.transition = slideconfig.attr("transition"); 3054 3055 this.Config.delay = this.Config.transition == "none" ? 10 : 400; 3056 3057 if(this.Config.is_autoplay == "yes") { 3058 this.Config.timeout = parseFloat(this.Config.auto_delay)*1000; 3059 } else { 3060 this.Config.timeout = 0; 3061 } 3062 3063 if(this.Config.transition == "none") { 3064 this.Config.transition_speed = 1; 3065 this.Config.transition = "fade"; 3066 } else { 3067 this.Config.transition_speed = '2000'; 3068 } 3069 3070 this.Config.first = true; 3071 this.Config.nextSlide; 3072 }, 3073 3074 /* 3075 * Will sniff the page for slideshows 3076 * Loop through each and create them 3077 */ 3078 CheckForSlideshow : function( ) { 3079 var slide_list = []; 3080 $(".slideshow_wrapper").each(function() { 3081 var new_slide = $(this).attr("class").replace(/slideshow_wrapper/g,"").replace(/_/g,"").replace(/ /,""); 3082 3083 if(!in_array(new_slide,slide_list)) { 3084 Projects.Slideshow.StartSlideshow( new_slide ); 3085 slide_list.push(new_slide); 3086 } 3087 }); 3088 }, 3089 3090 3091 /* 3092 * Start the slideshow instance 3093 * This is an exact replica of the old slideshow method 3094 * @todo: remove all refs to legacy function 3095 */ 3096 StartSlideshow : function( pid ) { 3097 // Set the default vars 3098 this.SetData(); 3099 3100 // Load the config file 3101 this.LoadConfig(); 3102 3103 var this_selector = $(".slideshow_wrapper_"+pid).parent(".slideshow_component"); 3104 3105 var has_caption = false; 3106 3107 var self = this; 3108 3109 $(this_selector).each(function(i) { 3110 // First height/width 3111 self.Data.slideheight_first[i] = $("img:first", this).height(); 3112 self.Data.slidewidth_first[i] = $("img:first", this).width(); 3113 3114 // The w/h values might be 0, so grab from the attr 3115 self.Data.slideheight_first[i] = (self.Data.slideheight_first[i] == 0) ? $("img:first", this).attr("height") : self.Data.slideheight_first[i]; 3116 self.Data.slidewidth_first[i] = (self.Data.slidewidth_first[i] == 0) ? $("img:first", this).attr("width") : self.Data.slidewidth_first[i]; 3117 3118 // Tell this element that we've go this covered 3119 $(this).attr("rel", "started").attr("id", "slideshow_component_"+pid+"_"+i); 3120 3121 // For inner loop use 3122 var Data = Projects.Slideshow.Data; 3123 var Config = Projects.Slideshow.Config; 3124 3125 // Add an id with unique sequential 3126 $(".slideshow_wrapper_"+pid, this).attr({ 3127 "id" : "slideshow_wrapper_"+pid+"_"+i, 3128 "class" : "slideshow_wrapper" 3129 }); 3130 $(".slideshow_container_"+pid, this).attr({ 3131 "id" : "slideshow_container_"+pid+"_"+i, 3132 "class" : "slideshow_container" 3133 }); 3134 $(".slideshow_count_"+pid, this).attr({ 3135 "id" : "slideshow_count_"+pid+"_"+i, 3136 "class" : "slideshow_count" 3137 }); 3138 $(".slideclick_"+pid, this).attr({ 3139 "id" : "slideclick_"+pid+"_"+i, 3140 "class" : "slideclick" 3141 }); 3142 $(".slideshow_caption_"+pid, this).attr({ 3143 "id" : "slideshow_caption_"+pid+"_"+i, 3144 "class" : "slideshow_caption" 3145 }); 3146 $(".slideshow_nav_"+pid, this) 3147 .attr("id", "slideshow_nav_"+pid+"_"+i) 3148 .removeClass("slideshow_nav_"+pid); 3149 3150 $(".slide_prev_"+pid, this).attr("id", "prev_"+pid+"_"+i); 3151 $(".slide_next_"+pid, this).attr("id", "next_"+pid+"_"+i); 3152 3153 // Loop through each image, get the widest and tallest 3154 $(".slideshow_container img", this).each(function(n) { 3155 var this_w = ($(this).width() > $(this).get(0).getAttribute("width")) ? $(this).width() : $(this).get(0).getAttribute("width"), 3156 this_h = ($(this).height() > $(this).get(0).getAttribute("height")) ? $(this).height() : $(this).get(0).getAttribute("height"); 3157 3158 3159 this_w = parseInt(this_w); 3160 this_h = parseInt(this_h); 3161 3162 if(this_w > Data.slidewidth_largest[i] || !Data.slidewidth_largest[i]) { 3163 Data.slidewidth_largest[i] = this_w; 3164 } 3165 3166 // Get the highest if we're on a special design 3167 if(this_h > Data.slideheight_largest[i] || !Data.slideheight_largest[i]) { 3168 Data.slideheight_largest[i] = this_h; 3169 } 3170 3171 // Check for caption 3172 if( !has_caption && $(this).attr("caption") && $(this).attr("caption") != "") { 3173 has_caption = true; 3174 } 3175 3176 3177 }); 3178 3179 // Set the first width 3180 $(".slideshow_wrapper", this).width( Data.slidewidth_largest[i] ); 3181 3182 // Set the default width of the container on certain designs 3183 if(Data.oneFail) { 3184 $(".slideshow_wrapper", this).height( Data.slideheight_largest[i] ); 3185 $(".slideshow_container", this).height( Data.slideheight_largest[i] ); 3186 Data.slideheight_first[i] = Data.slideheight_largest[i]; 3187 } else { 3188 //$(".slideshow_wrapper", this).height( Data.slideheight_first[i] ); 3189 $(".slideshow_container", this).height( Data.slideheight_first[i] ); 3190 } 3191 3192 3193 3194 // If the slide w > 560, set the caption with to be 560 3195 var caption_w = (Data.slidewidth_largest[i] > 560) ? 560 : Data.slidewidth_largest[i]; 3196 $('.slideshow_caption', this).css("width",caption_w+"px"); 3197 3198 // Remove additional breaks 3199 $('.slideshow_container br', this).each(function() { $(this).remove(); }); 3200 3201 // If there is no captions, remove the caption container 3202 if( !has_caption ) { 3203 $(".slideshow_caption", this).remove(); 3204 } 3205 3206 3207 3208 /* 3209 * Check and set thumbails 3210 */ 3211 Projects.Slideshow.SetThumbs(pid, i, Data.slidewidth_largest[i]); 3212 3213 3214 // Get the count of images 3215 var img_count = $(".slideshow_container img", this).length; 3216 3217 // Set the count 3218 if(Config.count_style == "parenth" && img_count > 0) { 3219 var count_nav = '(1 of '+img_count+')'; 3220 3221 } else if(Config.count_style == "no_parenth" && img_count > 0) { 3222 var count_nav = '1 of '+img_count; 3223 } 3224 3225 // Show the count 3226 $("#slideshow_count_"+pid+"_"+i, this).html(count_nav); 3227 3228 3229 /* 3230 * Instantiate this slideshow 3231 */ 3232 if( Projects.Slideshow.Data.do_placeholder ) { 3233 Projects.Slideshow.SetPlaceholder(pid, i); 3234 3235 } else { 3236 Projects.Slideshow.InitSingleSlideshow(pid, i); 3237 } 3238 3239 3240 }); 3241 3242 3243 if(typeof shiftPadding == "function") { 3244 shiftPadding(); 3245 } 3246 }, 3247 3248 /* 3249 * First checks, then sets the thumbnails if there are any 3250 */ 3251 SetThumbs : function(pid, i, slidewidth) { 3252 /* If there are slideshow thumbs 3253 */ 3254 if(this.Config.has_thumbs == "yes") { 3255 // The position is on top 3256 if( this.Config.thumb_position == "top" ) { 3257 3258 $('#slideshow_wrapper_'+pid+'_'+i) 3259 .before('<ul class="slideshow_thumbs" id="slideshow_thumbs_'+pid+'_'+i+'">'); 3260 3261 // Position is below 3262 } else if( this.Config.thumb_position == "bottom" ) { 3263 // If there is a nav below 3264 if( this.Config.nav_position == "bottom" && this.Config.has_nav == "yes" ) { 3265 $('#slideshow_nav_'+pid+'_'+i) 3266 .before('<ul class="slideshow_thumbs" id="slideshow_thumbs_'+pid+'_'+i+'">') 3267 .css("clear","both"); 3268 3269 // Default, attach it to the bottom of the wrapper 3270 } else { 3271 $('#slideshow_wrapper_'+pid+'_'+i) 3272 .after('<ul class="slideshow_thumbs" id="slideshow_thumbs_'+pid+'_'+i+'">'); 3273 } 3274 } 3275 3276 // Restrict the width 3277 $('#slideshow_thumbs_'+pid+'_'+i).css("width",slidewidth+"px"); 3278 3279 // Add the thumbs into the container, only for live 3280 if( !Projects.Slideshow.Data.do_placeholder ) { 3281 var t_hold = $('#slideshow_container_'+pid+'_'+i).html(); 3282 $('#slideshow_thumbs_'+pid+'_'+i).html( t_hold ); 3283 } 3284 3285 // Remove the width and height attributes 3286 $('#slideshow_thumbs_'+pid+'_'+i+' img') 3287 .removeAttr("width") 3288 .removeAttr("height") 3289 .wrap('<li class="slideshow_thumb"><a href="#">'); 3290 } 3291 }, 3292 3293 /* 3294 * Instantiates one instance of the slideshow 3295 * Can be used standalone, or with the Start slideshow method 3296 */ 3297 InitSingleSlideshow : function(pid, i) { 3298 3299 // First, empty the contents of the thumbnails 3300 $('#slideshow_thumbs_'+pid+'_'+i).empty(); 3301 3302 $('#slideshow_container_'+pid+'_'+i).cycle({ 3303 fx: Projects.Slideshow.Config.transition, 3304 pager: '#slideshow_thumbs_'+pid+'_'+i, 3305 height: Projects.Slideshow.Data.slideheight_first[i], 3306 width: Projects.Slideshow.Data.slidewidth_largest[i], 3307 next: '#next_'+pid+'_'+i, 3308 prev: '#prev_'+pid+'_'+i, 3309 contain: '#slideclick_'+pid+'_'+i, 3310 timeout: Projects.Slideshow.Config.timeout, 3311 speed: Projects.Slideshow.Config.transition_speed, 3312 this_i: i, 3313
3314 // callback fn that adjusts the slideshow's height 3315 before: function(currSlideElement, nextSlideElement, options, forwardFlag){ 3316 var sh = ($(this).get(0).getAttribute("height")) ? $(this).get(0).getAttribute("height") : $(this).height(); 3317 sh = parseInt(sh); 3318 3319 var sw = ($(this).get(0).getAttribute("width")) ? $(this).get(0).getAttribute("width") : $(this).width(); 3320 sw = parseInt(sw); 3321 3322 if( 3323 sh > 0 && 3324 !Projects.Slideshow.Data.isSC && 3325 !Projects.Slideshow.Data.isOz && 3326 !Projects.Slideshow.Data.isRunyon && 3327 !Projects.Slideshow.Data.isWarhol 3328 ) { 3329 if(Projects.Slideshow.Config.transition == "scrollRight") { 3330 $(this).parent().animate({ height: sh, width: sw }, Projects.Slideshow.Config.delay); 3331 $(this).siblings().css("z-index",0); 3332 $(this).css("z-index",($(this).index()+1)) 3333 } else { 3334 $(this).parent().animate({ height: sh }, Projects.Slideshow.Config.delay); 3335 } 3336 3337 } 3338 3339 $(document).trigger("slideshowTransitionStart", [nextSlideElement]); 3340 }, 3341 3342 after: function(currSlideElement, nextSlideElement, options, forwardFlag) { 3343 if(parseInt(nextSlideElement) >= 0) { 3344 nextSlide = $("#"+$(currSlideElement).parent().attr("id")+" img:nth-child("+parseInt(nextSlideElement)+")"); 3345 } else { 3346 nextSlide = nextSlideElement; 3347 } 3348 3349 $(document).trigger("slideshowTransitionFinish", [nextSlide]); 3350 }, 3351 3352 // callback fn that creates a thumbnail to use as pager anchor 3353 pagerAnchorBuilder: function(idx, slide) { 3354 return '<li class="slideshow_thumb"><a href="#"><img src="' + slide.src + '" /></a></li>'; 3355 } 3356 3357 }); 3358 3359 // Get the thumbnail height (used in the placeholder) 3360 this.GetThumbnailHeight(pid, i); 3361 3362 // Update the complete state of this 3363 $(document).trigger("slideshowLoadComplete", [ $('#slideshow_container_'+pid+'_'+i) ]); 3364 }, 3365 3366 /* 3367 * Set's the slideshow to display placeholder content 3368 * by showing only the first image in the slideshow 3369 */ 3370 SetPlaceholder : function(pid, i) { 3371 // Dump all of the image except for the first one 3372 $("#slideshow_container_"+pid+"_"+i+" img:first ~img").remove(); 3373 3374 // Make a position for the container and give it a height 3375 $("#slideshow_container_"+pid+"_"+i).css({ 3376 "position" : "relative", 3377 "height" : $("#slideshow_container_"+pid+"_"+i+" img:first").height() 3378 }); 3379 3380 // Fake the thumbs by adding in holders 3381 for(var n in this.Data.thumbs_height[i]) { 3382 var img = '<img src="/_gfx/spacer.gif" height="'+ 3383 this.Data.thumbs_height[i][n].h+'" width="'+ 3384 this.Data.thumbs_height[i][n].w+'" />'; 3385 3386 var fake_thumb = '<li class="slideshow_thumb fake"><a href="#">'+img+'</a></li>'; 3387 $("#slideshow_thumbs_"+pid+"_"+i).append(fake_thumb); 3388 } 3389 3390 $("#slideshow_thumbs_"+pid+"_"+i).css("clear", "both"); 3391 }, 3392 3393 /* 3394 * Destroys all slideshow sessions by removeing them and re-adding them 3395 * This is used by the inspector 3396 */ 3397 DestroyAll : function() { 3398 $(".slideshow_component").each(function() { 3399 // Remove and re-add everything 3400 $(this).after('<div class="slideshow_component" id="'+$(this).attr("id")+'">'+$(this).html()+'</div>').remove(); 3401 }); 3402 3403 }, 3404 3405 /* 3406 * Re-checks the page for slideshows 3407 * This is used when reactivating them after inspector closes 3408 * The assumption is they have already been activated once 3409 */ 3410 ReCheckAndInit : function() { 3411 // Get rid of all the plugin control 3412 this.DestroyAll(); 3413 3414 $(".slideshow_component").each(function() { 3415 var id = $(".slideshow_wrapper", this).attr("id").replace("slideshow_wrapper_", ""), 3416 pid = id.split("_")[0], 3417 i = id.split("_")[1]; 3418 3419 // Remove the slide thumbs, they will be re-added 3420 $(".slideshow_thumbs", this) 3421 .after('<ul class="slideshow_thumbs" id="slideshow_thumbs_'+pid+'_'+i+'">') 3422 .remove(); 3423 3424 // Re-init the slides 3425 Projects.Slideshow.InitSingleSlideshow(pid, i); 3426 3427 }); 3428 3429 }, 3430 3431 /** 3432 * Get the thumbnail container height 3433 * Store the value 3434 * To do this, we add a clear:both div, grab height, then remove 3435 */ 3436 GetThumbnailHeight : function(pid, i) { 3437 var size_array = [ ]; 3438 3439 $("#slideshow_container_"+pid+"_"+i+" img").each(function(index) { 3440 var h = parseInt($(".slideshow_thumb img").css("height")); 3441 var og_w = $(this).attr("width"); 3442 var og_h = $(this).attr("height"); 3443 size_array[ index ] = getScaleSize(og_w, og_h, h); 3444 }); 3445 3446 this.Data.thumbs_height[i] = size_array; 3447 3448 } 3449 3450} 3451///////////////////////////////////////////////////////////////////////////////////////////////// 3452// Leaving this stub in for legacy purposes 3453// @todo: remove all refs to legacy function 3454// @todo: utilize the "CheckForSlideshows" method 3455function startSlideshow(pid) { 3456 Projects.Slideshow.StartSlideshow( pid ); 3457} 3458 3459 3460/*! 3461 * The "reverse fallback" -- Flash object and HTML5 video tags are both housed 3462 * within a div.video_component. The CheckForVideo() method determines who gets 3463 * to stay, in essence, and removes the unused tags. 3464 */ 3465/* !Projects.Video */ 3466Projects.Video = { 3467 Config: { 3468 DEBUG: false, 3469 dependencies: [ 3470 '/_css/mediaplayer.css', 3471 '/_js/jquery-ui-1.8.18.custom.min.js', 3472 '/_js/cargo.video.package.js' 3473 ], 3474 volume_default: 0.75, 3475 volume: 1, 3476 muted: false 3477 }, 3478 3479/** 3480 * DEBUG 3481 * 3482 * Controlled by Config.DEBUG, MightForceHTML5() and IsForcingHTML5() modify, 3483 * dependent upon the presence of the cargo.video.forcedHTML5 cookie, the 3484 * behavior of DetectPlugin() and DestroyFallbackTags() - always displaying 3485 * the video elements. 3486 * 3487 * ForceHTML5() controls the cargo.video.forcedHTML5 cookie and enables video 3488 * elements accordingly. 3489 */ 3490 MightForceHTML5: function() { 3491 return this.Config.DEBUG; 3492 }, 3493
3494 IsForcingHTML5: function() { 3495 if (this.Config.is_forcing_HTML5 !== undefined) 3496 return this.Config.is_forcing_HTML5; 3497 3498 var forcing_HTML5 = $.cookie('cargo.video.forcedHTML5') || false; 3499 if (forcing_HTML5) 3500 this.Config.has_flash_plugin = false; 3501 3502 this.Config.is_forcing_HTML5 = forcing_HTML5; 3503 return forcing_HTML5; 3504 }, 3505 3506 ForceHTML5: function() { 3507 var should_force_HTML5 = $.cookie('cargo.video.forcedHTML5') || false; 3508 this.Config.force_HTML5 = ! should_force_HTML5; 3509 if (this.Config.force_HTML5) { 3510 $.cookie('cargo.video.forcedHTML5', true, {expires: 30, path: '/'}); 3511 this.Config.has_flash_plugin = false; 3512 this.CheckForVideo(); 3513 } else { 3514 $.cookie('cargo.video.forcedHTML5', null, {path: '/'}); 3515 window.location.reload(); 3516 } 3517 }, 3518 3519/** 3520 * Primary method, determines if there are videos present and, if so, if there 3521 * is a need to "reverse fallback" to an HTML5 player. Upon fallback, loads the 3522 * related CSS and javascript should they not already exist, calling back to 3523 * itself recursively, rearranging and removing Flash and HTML5 elements, and 3524 * finally applying the HTML5 player controls. 3525 * 3526 * @param video_js_has_loaded Boolean, true on recursive call after load of external CSS and javascript files 3527 */ 3528 CheckForVideo: function(video_js_has_loaded) { 3529 if (!this.DetectVideos()) 3530 return; 3531 3532 if (this.DetectPlugin()) { 3533 this.DestroyFallbackTags(); 3534 return; 3535 } 3536 3537 // Load video-related javascript here, but only once 3538 if (this.Config.has_video_js === undefined) { 3539 if (video_js_has_loaded) { 3540 this.Config.has_video_js = true; 3541 } else { 3542 if (this.Config.is_loading_video_js !== undefined) 3543 return; 3544 3545 this.Config.is_loading_video_js = true; 3546 3547 // Actual loading of external dependencies 3548 $.loadFiles(this.Config.dependencies).done(function() { 3549 Projects.Video.CheckForVideo(true); 3550 }); 3551 3552 return; 3553 } 3554 } 3555 3556 // Culling of the object tags, displaying of the video tags 3557 $('.video_component').each(function() { 3558 $(this).children('object').remove(); 3559 3560 var video_tag = $(this).children('.video_tag'); 3561 var player = video_tag.children(); 3562 video_tag.css({ 3563 display: 'inline-block', 3564 width: player.attr('data-video-width'), 3565 height: player.attr('data-video-height') 3566 }); 3567 3568 // Apply jMediaelement controls after javascript has loaded 3569 if (Projects.Video.Config.has_video_js) 3570 Projects.Video.ConfigureMediaPlayer(player); 3571 }); 3572 }, 3573 3574/** 3575 * Application of jMediaelement controls to video tags 3576 */ 3577 ConfigureMediaPlayer: function(player) { 3578 // Don't call video player methods more than once 3579 if (player.attr('data-video-configured') !== undefined) 3580 return; 3581 3582 player.attr('data-video-configured', 'true'); 3583 3584 // Grab volume settings from cookies or defaults 3585 this.Config.volume = $.cookie('cargo.video.volume') || this.Config.volume_default; 3586 this.Config.muted = ($.cookie('cargo.video.muted')) ? true : false; 3587 3588 // Apply jMediaelement controls, custom volume logic 3589 player.jmeInit().jmeProp('controlbar', true); 3590 player.children('video').each(function(index, video) { 3591 $(video).bind('volumechange', function() { 3592 var control = $('.mute-unmute'); 3593 var volume = Number($(this).jmeValue('volume')); 3594 var muted = $(this).jmeValue('muted'); 3595 3596 if (volume > 0.66) { 3597 control.removeClass('volume-medium volume-low').addClass('volume-high'); 3598 } else if (volume <= 0.66 && volume > 0.33) { 3599 control.removeClass('volume-high volume-low state-mute state-unmute').addClass('volume-medium'); 3600 } else if (volume <= 0.33 && volume > 0.01) { 3601 control.removeClass('volume-high volume-medium state-mute state-unmute').addClass('volume-low'); 3602 } else { 3603 control.removeClass('volume-high volume-medium volume-low').addClass('state-unmute'); 3604 } 3605 3606 if (muted) { 3607 control.addClass('state-unmute'); 3608 $.cookie('cargo.video.muted', true, {expires: 30, path: '/'}); 3609 } else { 3610 $.cookie('cargo.video.muted', null, {path: '/'}); 3611 } 3612 3613 $.cookie('cargo.video.volume', volume, {expires: 30, path: '/'}); 3614 }); 3615 3616 video.volume = Projects.Video.Config.volume; 3617 video.muted = Projects.Video.Config.muted; 3618 }); 3619 }, 3620 3621/** 3622 * Determine if the browser supports and has the Flash plugin installed 3623 * 3624 * @return Boolean, whether detected 3625 */ 3626 DetectPlugin: function() { 3627 // Only check for Flash once 3628 if (this.Config.has_flash_plugin !== undefined) 3629 return this.Config.has_flash_plugin; 3630 3631 // During debug, always report a lack of Flash 3632 if (this.MightForceHTML5()) { 3633 if (this.IsForcingHTML5()) 3634 return false; 3635 } 3636 3637 var flash_was_detected = false; 3638 if (typeof navigator.plugins != 'undefined' && typeof navigator.plugins['Shockwave Flash'] == 'object') { 3639 var d = navigator.plugins['Shockwave Flash'].description; 3640 if (d && !(typeof navigator.mimeTypes != 'undefined' && navigator.mimeTypes['application/x-shockwave-flash'] && !navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin)) 3641 flash_was_detected = true; 3642 } else if (typeof window.ActiveXObject != 'undefined') { 3643 try { 3644 if ((new ActiveXObject('ShockwaveFlash.ShockwaveFlash'))) 3645 flash_was_detected = true; 3646 } catch(e) {} 3647 } 3648 3649 this.Config.has_flash_plugin = flash_was_detected; 3650 return flash_was_detected; 3651 }, 3652 3653/** 3654 * Get a count of the div.video_component elements, confirm if there is more 3655 * than one present 3656 * 3657 * @return Boolean, true if one or more 3658 */ 3659 DetectVideos: function() { 3660 return ($('.video_component').length > 0); 3661 }, 3662 3663/** 3664 * Remove the video tag parent div, even though it is not displayed, just to be 3665 * extra, extra safe 3666 */ 3667 DestroyFallbackTags: function() { 3668 // During debug, do not remove the video tags 3669 if (this.MightForceHTML5()) 3670 return; 3671 3672 if (this.Config.was_destroyed !== undefined) 3673 return; 3674 3675 this.Config.was_destroyed = true; 3676 $('.video_component .video_tag').each(function(index, value) { 3677 $(this).remove(); 3678 }); 3679 } 3680} 3681/*- 3682 * End Projects.Video 3683 */ 3684 3685 Cargo.ReplaceLoadingAnims = function(specificSelection) { 3686 3687 $(".retinaSpinner").each(function() { 3688 if (window.devicePixelRatio > 1 ){ 3689 $(this).addClass('rotating'); 3690 } 3691 }); 3692 3693 if(!Cargo.Config.isOldIE()){
3694 var spinnerEl = $('<div></div>'); 3695 3696 for(var i = 0; i < 8; i++){ 3697 spinnerEl.append( 3698 '<div style="position: absolute; top: -2px;">' + 3699 '<div class="spinner_circle part' + (i + 1) + '" style="-webkit-transform: rotate(' + (i * 45) +'deg) translate(6px, 0px); transform: rotate(' + (i * 45) +'deg) translate(6px, 0px);"></div>' + 3700 '</div>'); 3701 } 3702 3703 if(typeof specificSelection == "undefined"){ 3704 $('img[src$="/loadingAnim.gif"]').each(function(){ 3705 replace(this); 3706 }); 3707 } else { 3708 specificSelection.each(function(){ 3709 replace(this); 3710 }); 3711 } 3712 } 3713 3714 function replace(self){ 3715 var thisSpinner = spinnerEl.clone(); 3716 3717 thisSpinner.attr('class', 'retinaSpinner ' + $(self).attr('class')); 3718 thisSpinner.attr('id', $(self).attr('id')); 3719 thisSpinner.attr('style', $(self).attr('style')); 3720 3721 if (window.devicePixelRatio > 1 ){ 3722 thisSpinner.addClass('rotating'); 3723 } 3724 3725 // replace the old GIF 3726 $(self).replaceWith(thisSpinner); 3727 } 3728 } 3729 3730 3731///////////////////////////////////////////////////////////////////////////////////////////////// 3732/** 3733 * Social media class 3734 * 3735 * This is the main social media function 3736 * It will init the rest of the application 3737 * 3738 * Cargo.IncludeSocialMedia( { 3739 * element : ".project_footer", 3740 * show_count : true, 3741 * 3742 * facebook : true, 3743 * twitter : true, 3744 * stumbleupon : false, 3745 * pintrest : true 3746 * } ); 3747 * 3748 * 3749 * .social_media { 3750 * margin: 30px 0 100px 0; height: 20px; 3751 * } 3752 * 3753 */ 3754/* !Cargo.IncludeSocialMedia */ 3755Cargo.IncludeSocialMedia = function( dataObj ) { 3756 // Loop through each to set the default options 3757 $.each(dataObj, function(key, value) { 3758 Cargo.SocialMedia.SetDefaults(key, value); 3759 }); 3760 3761 // Set the project open/ready states 3762 $(document).ready(function() { Cargo.SocialMedia.Init(); }); 3763 3764 // Cover the bases on the events that fire 3765 $(document).bind("projectLoadComplete", function(e, pid) { Cargo.SocialMedia.Init(); }); 3766 $(document).bind("directLinkLoaded", function(e, path) { Cargo.SocialMedia.Init(); }); 3767 $(document).bind("startProjectLoaded", function(e) { Cargo.SocialMedia.Init(); }); 3768 $(document).bind("paginationComplete", function(e) { Cargo.SocialMedia.Init(); }); 3769 3770}; 3771 3772 3773/** 3774 * This is the main social media app 3775 * It will contain the various services 3776 * NOTE: 3777 * The var "Services" sits at the bottom of this method 3778 * this defines each socail network and their dependencies 3779 * it must sit at the bottom, not the top 3780 */ 3781/* !Cargo.SocialMedia */ 3782Cargo.SocialMedia = { 3783 3784 /* 3785 * Pre-define the services and their respective scripts that need loading 3786 */ 3787 "Services" : { 3788 "facebook" : { 3789 "script" : false, // script url for inclusion at write time 3790 "inuse" : false // if this is in use or not, always default false 3791 }, 3792 3793 "twitter" : { 3794 "script" : "http://platform.twitter.com/widgets.js", 3795 "inuse" : false 3796 }, 3797 3798 "pinterest" : { 3799 "script" : false, 3800 "inuse" : false 3801 }, 3802 3803 "googleplus" : { 3804 "script" : "https://apis.google.com/js/plusone.js", 3805 "inuse" : false 3806 }, 3807 3808 "stumbleupon": { 3809 "script" : "http://platform.stumbleupon.com/1/widgets.js", 3810 "inuse" : false 3811 }, 3812 3813 "reddit" : { 3814 "script" : "http://www.reddit.com/buttonlite.js?i=5", 3815 "inuse" : false 3816 } 3817 3818 3819 }, 3820 3821 "Options" : { 3822 "element" : ".project_footer", // The selector element to bind the html to 3823 "show_count" : false, // Show the "like" count or not 3824 "twitter_username" : false // Twitter username for @reply 3825 }, 3826 3827 "OutputHTML" : "", // The HTML that will be printed to the element 3828 3829 3830 3831 /* 3832 * Set the defaults of the socail media elements 3833 */ 3834 SetDefaults : function( which, value ) { 3835 if(which == "element" || which == "show_count" || which == "twitter_username") { 3836 this.Options[which] = value; 3837 } else { 3838 // set the "inuse" value for the default 3839 this.Services[which].inuse = value; 3840 } 3841 }, 3842 3843 /* 3844 * Initialize the services 3845 */ 3846 Init : function() { 3847 // Reset the output values 3848 this.OutputHTML = ""; 3849 3850 // Create the HTML 3851 this.CreateHTML(); 3852 3853 // Write the HTML 3854 this.WriteHTML(); 3855 }, 3856 3857 /* 3858 * Gets a project title 3859 */ 3860 AddHTML : function( html ) { 3861 this.OutputHTML += html; 3862 }, 3863 3864 /* 3865 * Takes the HTML that was created by the methods below 3866 * Replaces the stubs with real content 3867 * Stubs are for direct link / encoded direct link / title 3868 * Input is a PID of the element we are binding 3869 * If no PID is passed, it will default to site link / html title 3870 */ 3871 GetFormattedHTML : function( pid ) { 3872 var final_output = this.OutputHTML; 3873 3874 // Direct link 3875 final_output = final_output.replace(/CARGO_DIRECT_LINK/g, this.GetDirectSocialLink( pid ) ); 3876 3877 // Encoded direct link 3878 final_output = final_output.replace(/CARGO_ENCODED_DIRECT_LINK/g, encodeURIComponent(this.GetDirectSocialLink( pid ) ) ); 3879 3880 // Title 3881 final_output = final_output.replace(/CARGO_PROJECT_TITLE/g, this.GetSocialProjectTitle( pid ) ); 3882 3883 // Return the results 3884 return final_output; 3885 }, 3886 3887 /* 3888 * Write the buttons to the choosen element 3889 */ 3890 WriteHTML : function() { 3891 3892 // Attach the content to the choosen element/selector 3893 $(this.Options.element) 3894 .each(function() { 3895 // Add to reclusive elements. Make them social, but skip ones that already are social. 3896 if($(this).data("has_social") !== true) { 3897 $(this) 3898 .append('<div class="social_media">' + Cargo.SocialMedia.GetFormattedHTML( Cargo.SocialMedia.GetNearestPid( $(this) ) ) + '</div>') 3899 .data("has_social", true); 3900 } 3901 });
3902 3903 3904 // Loop one more time, this time include scripts 3905 $.each(this.Services, function(service, options) { 3906 if( options.inuse === true && options.script !== false ) { 3907 // Remove any old scripts 3908 $("script#"+service).remove(); 3909 3910 // Add the new script 3911 addScript( options.script, service ); 3912 } 3913 }); 3914 3915 }, 3916 3917 /* 3918 * Helper method gets a project title 3919 */ 3920 GetSocialProjectTitle : function( pid ) { 3921 // Feed 3922 if( Cargo.Config.GetTemplate().indexOf("feed") >= 0 ) { 3923 return $("#entry_"+pid+" .project_title").text(); 3924 3925 } else { 3926 return $(".project_title").text(); 3927 } 3928 3929 }, 3930 3931 /* 3932 * Helper method gets a direct link 3933 */ 3934 GetDirectSocialLink : function( pid ) { 3935 return Cargo.Location.GetDirectLink( pid ); 3936 }, 3937 3938 /* 3939 * Quick and dirty. 3940 * Finds the pid of the most active element 3941 * On feed design, that is probably it's parent. Find the entry 3942 */ 3943 GetNearestPid : function( this_elem ) { 3944 if( Cargo.Config.GetTemplate().indexOf("feed") >= 0 ) { 3945 if( $(this_elem).prevAll(".entry:first").length > 0) { 3946 return $(this_elem).prevAll(".entry:first").attr("id").replace("entry_", ""); 3947 } else if($(this_elem).parents(".entry:first").length > 0) { 3948 return $(this_elem).parents(".entry:first").attr("id").replace("entry_", ""); 3949 } else { 3950 return $(this_elem).parent().attr("id").replace("entry_", ""); 3951 } 3952 } else { 3953 return $("#current_open").val(); 3954 } 3955 }, 3956 3957 /* 3958 * Create the final output HTML by adding individual services 3959 */ 3960 CreateHTML : function() { 3961 // Loop through and add each to the selector 3962 for (var service in this.Services) { 3963 // Facebook 3964 if(service == "facebook" && this.Services[service].inuse ) { 3965 this.AddHTML( this.Facebook() ); 3966 } 3967 // Twitter 3968 else if(service == "twitter" && this.Services[service].inuse ) { 3969 this.AddHTML( this.Twitter() ); 3970 } 3971 // Pinterest 3972 else if(service == "pinterest" && this.Services[service].inuse ) { 3973 this.AddHTML( this.Pinterest() ); 3974 } 3975 // Google Plus 3976 else if(service == "googleplus" && this.Services[service].inuse ) { 3977 this.AddHTML( this.GooglePlus() ); 3978 } 3979 // StumbleUpon 3980 else if(service == "stumbleupon" && this.Services[service].inuse ) { 3981 this.AddHTML( this.StumbleUpon() ); 3982 } 3983 // Reddit 3984 else if(service == "reddit" && this.Services[service].inuse ) { 3985 this.AddHTML( this.Reddit() ); 3986 } 3987 3988 } 3989 }, 3990 3991 3992 /* 3993 * All services below here 3994 * Note, string replacements are made for the following: 3995 * CARGO_DIRECT_LINK 3996 * CARGO_ENCODED_DIRECT_LINK 3997 * CARGO_PROJECT_TITLE 3998 */ 3999 Facebook : function() { 4000 4001 // Cargo.log("Should we show comments? "+this.Options.show_count); 4002 var w = (this.Options.show_count) ? '90' : '47'; 4003 4004 return '<div class="facebook_like" style="float: left; margin-right: 8px;"><iframe src="http://www.facebook.com/plugins/like.php?href=CARGO_ENCODED_DIRECT_LINK&send=false&layout=button_count&width=50&show_faces=false&action=like&colorscheme=light&font=arial&height=21&appId=150492405019861" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:'+w+'px; height:21px;" allowTransparency="true"></iframe></div>'; 4005 4006 }, 4007 4008 Twitter : function() { 4009 4010 var output = '<div class="tweet_this" style="float: left; margin-right: 8px;"><a href="https://twitter.com/share" class="twitter-share-button"'; 4011 4012 if (this.Options.twitter_username !== false) { 4013 output += ' data-via="'+ this.Options.twitter_username +'"'; 4014 } 4015 4016 output += ' data-url="CARGO_ENCODED_DIRECT_LINK" data-text="CARGO_PROJECT_TITLE: CARGO_DIRECT_LINK" data-count="none">Tweet</a></div>'; 4017 4018 return output; 4019 4020 }, 4021 4022 Pinterest : function() { 4023 4024 $("a.pin_it_link") 4025 .live("click", function() { 4026 addScript("http://assets.pinterest.com/js/pinmarklet.js?r=" + Math.random()*99999999); 4027 return false; 4028 });
4029 4030 return '<div class="pin_it" style="float: left; margin-right: 8px;"><a href="#" class="pin_it_link" style="background: none; border: 0;"><img src="/_gfx/pinit.png" /></a></div>'; 4031 4032 }, 4033 4034 GooglePlus : function() { 4035 4036 return '<div class="google_plus" style="float: left; margin-right: 8px;"><g:plusone size="medium" annotation="none" href="CARGO_DIRECT_LINK"></g:plusone></div>'; 4037 4038 }, 4039 4040 StumbleUpon : function() { 4041 4042 return '<div class="stumbleupon" style="float: left; margin-right: 8px;"><su:badge layout="4" location ="CARGO_DIRECT_LINK"></su:badge></div>'; 4043 4044 }, 4045 4046 Reddit : function() { 4047 4048 return '<div class="reddit" style="float: left; margin-right: 8px;"><a href="http://www.reddit.com/submit?url=CARGO_ENCODED_DIRECT_LINK" target="_blank"><img src="http://www.reddit.com/static/spreddit5.gif" alt="submit to reddit" border="0" /></a></div>'; 4049 4050 } 4051 4052 4053}; // End SocialMedia 4054 4055 4056/*! 4057 * Usage: 4058 * $.loadFiles('/this.js', '/that.js', '/other.js').done(function(data) { 4059 * console.log('Multiple files have finished loading.'); 4060 * }).fail(function(xhr, text_status) { 4061 * console.log('One of the files could not be loaded.'); 4062 * }); 4063 */ 4064/* !jQuery loadFiles Plugin */ 4065(function($) { 4066/** 4067 * Constructor for Filer class; creates Deferred object in order to provide 4068 * jQuery done() and fail() event handling and initializes files array to track 4069 * and hold constructs created by trackFileState(). 4070 */ 4071 var Filer = function(files_to_load) { 4072 this.init(); 4073 this.addFilesFromConstructor(files_to_load); 4074 4075 return this; 4076 }; $.extend(Filer.prototype, { 4077 init: function(files_to_load) { 4078 this.Data = { 4079 files: [], 4080 done_callback: null, 4081 fail_callback: null 4082 }; 4083 }, 4084 4085/** 4086 * Traverses the arguments passed by the constructor, recursively so should one 4087 * an array, passing files individually to the addFile method. 4088 * 4089 * @param files Mixed 4090 */ 4091 addFilesFromConstructor: function(files) { 4092 $.each(files, $.proxy(function(index, value) { 4093 if ($.isArray(value)) { 4094 this.addFilesFromConstructor(value); 4095 } else { 4096 this.addFile(this.Data.files.length, value); 4097 } 4098 }, this)); 4099 }, 4100 4101/** 4102 * Creates jQuery $.ajax options object and events, performs $.ajax load, and 4103 * sends XHR reference to trackFileState() method. 4104 * 4105 * @param index Number, order the file reference is to be placed within the files array 4106 * @param value Object or String, object for jQuery $.ajax call or string path to file URL 4107 */ 4108 addFile: function(index, value) { 4109 var base = (typeof value === 'object') ? value : {url: value}; 4110 var options = $.extend(base, { 4111 cache: true, 4112 dataType: this.dataTypeForFile(base.url), 4113 success: $.proxy(function(data, text_status, xhr) { 4114 this.handleFileLoad(index, data); 4115 }, this), 4116 error: $.proxy(function(xhr, text_status, error_thrown) { 4117 this.handleFileError(index, xhr, text_status); 4118 }, this) 4119 }); 4120 4121 this.trackFileState(index, value, $.ajax(options)); 4122 }, 4123 4124/** 4125 * @param url String, file URL 4126 * @return String, dataType for $.ajax options object 4127 */ 4128 dataTypeForFile: function(url) { 4129 return /\.js$/.test(url) ? 'script' : 'text'; 4130 }, 4131 4132/** 4133 * Places file information into files array for load and error event handling. 4134 * 4135 * @param index Number, order the file reference is to be placed within the files array 4136 * @param url String, file URL 4137 * @param xhr Object, returned by jQuery $.ajax() 4138 */ 4139 trackFileState: function(index, url, xhr) { 4140 this.Data.files[index] = { 4141 complete: false, 4142 index: index, 4143 url: url, 4144 xhr: xhr 4145 }; 4146 }, 4147 4148/** 4149 * Called by $.ajax done event, forwards done message to the Filer done handler 4150 * in the event all files have completed. Handles special case for CSS files, 4151 * injecting their content in to the document head. 4152 * 4153 * @param index Number 4154 * @param data Mixed 4155 */ 4156 handleFileLoad: function(index, data) { 4157 // A jQuery 1.4.2 bug has $.ajax success firing on $.ajax abort() - don't handle files mistakenly called by this 4158 // See http://bugs.jquery.com/ticket/6060 and https://github.com/jquery/jquery/commit/ba9e0fc177841bd74cc5ea4e52f09cd87d747bf5 4159 if (this.has_exited_on_error !== undefined) 4160 return; 4161 4162 this.Data.files[index].complete = true; 4163 4164 // Manually add CSS to the document head 4165 if (/\.css$/.test(this.Data.files[index].url)) 4166 $('head').append('<style>' + data + '</style>'); 4167 4168 var completed = 0; 4169 $.each(this.Data.files, function(index, file) { 4170 if (file.complete) 4171 completed++; 4172 }); 4173 4174 if (this.Data.files.length == completed) 4175 this.complete(data); 4176 }, 4177 4178/** 4179 * Called by $.ajax fail event, forwards fail message to the Filer fail handler 4180 * and aborts any remaining $.ajax loads. 4181 */ 4182 handleFileError: function(index, xhr, text_status) { 4183 this.error(xhr, text_status); 4184 4185 this.Data.files[index].complete = true; 4186 $.each(this.Data.files, function(index, file) { 4187 if ( ! file.complete) 4188 file.xhr.abort(); 4189 }); 4190 }, 4191 4192/** 4193 * Sends message to Deferred object that all file loads were successful. 4194 */ 4195 complete: function(data) { 4196 if ($.isFunction(this.Data.done_callback)) 4197 this.Data.done_callback.apply(this, [data]); 4198 }, 4199 4200/** 4201 * Sends message to Deferred object that one or more file loads could not be 4202 * completed. Prevents itself from sending such message more than once. 4203 */ 4204 error: function(xhr, text_status) { 4205 // $.ajax abort() results in numerous calls here, prevent such events 4206 if (this.has_exited_on_error !== undefined) 4207 return; 4208 4209 this.has_exited_on_error = true; 4210 4211 if ($.isFunction(this.Data.fail_callback)) 4212 this.Data.fail_callback.apply(this, [xhr, text_status]); 4213 }, 4214 4215 done: function(callback) { 4216 this.Data.done_callback = callback; 4217 return this; 4218 }, 4219 4220 fail: function(callback) { 4221 this.Data.fail_callback = callback; 4222 return this; 4223 } 4224 }); 4225 4226/** 4227 * @return Filer instance 4228 */ 4229 $.extend({ 4230 loadFiles: function() { 4231 return new Filer($.makeArray(arguments)); 4232 } 4233 }); 4234})(jQuery); 4235/*- 4236 * End jQuery loadFiles Plugin 4237 */ 4238 4239 4240/** 4241 * FreshBox 4242 */ 4243/* !jQuery Freshbox aka Fullscreen plugin */ 4244(function($) { 4245 4246 $.fn.FreshBox = function(options) { 4247 4248 var defaults = { 4249 fill : "fit", // How is the image resized 4250 element : "img", // What element are we targeting? 4251 parent : ".project_content" 4252 }; 4253 4254 // Update any options passed in with the defaults 4255 this.options = $.extend(defaults, options); 4256 var self = this; 4257 4258 this.Data = { 4259 overflow : null, // The overflow of body before opening the lightbox 4260 scroll_x : 0, // Starting scroll position 4261 scroll_y : 0, // Starting scroll position 4262 window_height : 0, // Window height 4263 window_width : 0, // Window width 4264 iOS : undefined, // Data store for cached UI element sizes on iOS 4265 allowZoom : true, // allow zooming into images that are bigger than the window. 4266 zoomedImage : undefined, 4267 zoomEnabled : false, 4268 zoomActive : false 4269 }; 4270 4271 /** 4272 * Override the parent element 4273 */ 4274 if (typeof freshbox_parent_element !== 'undefined') self.options.parent = freshbox_parent_element; 4275 4276 /** 4277 * Init 4278 * Sets up the click events for both fullscreen and lightbox 4279 */ 4280 this.Init = function() { 4281 4282 var element; 4283 4284 // Initialize fullscreen when clicking fullscreen button 4285 $("#fullscreen", self).die().unbind("click").click( function(e) { 4286 // If we're using a modern browser 4287 if( !self.CheckOldBrowsers() ) { 4288 self.InitFullscreen(e, $(this).parents(".entry").attr("id")); 4289 } else { 4290 self.InitLightbox(e, $(this).attr("data-mid"), $(this).parents(".entry").attr("id")); 4291 } 4292 return false; 4293 }); 4294 4295 // Only inititilize the lightbox when that display option is checked 4296 if($("fullscreen_option").attr("data") == "lightbox" ) { 4297 // Find the parent 4298 // Initialize lightbox when clicking project_content img 4299 $(self.options.parent+" "+self.options.element, self).each(function() { 4300 // If this is a Cargo uploaded image or not in an anchor tag 4301 if ( $(this).is("[src_o]") && !$(this).parent("a").length > 0 ) { 4302 4303 // Cursor style 4304 $(this).css("cursor", function() { 4305 if ($.browser.mozilla) { 4306 return '-moz-zoom-in'; 4307 } else if ($.browser.webkit) { 4308 return '-webkit-zoom-in'; 4309 } else { 4310 return 'pointer'; 4311 } 4312 });
4313 4314 // Setup 4315 $(this).die().unbind("click").click( function(e) { 4316 self.InitLightbox(e, $(this).attr("data-mid"), $(this).parents(".entry").attr("id")); 4317 return false; 4318 }); 4319 }; 4320 }); 4321 } // end if lightbox 4322 4323 }; 4324 4325 /** 4326 * Fullscreen 4327 * Opened by clicking the fulllscreen button 4328 * Opens images fullscreen via HTML5 4329 * Falls back to flash if HTML5 isn't supported 4330 */ 4331 this.InitFullscreen = function(e, element) { 4332 4333 self.Construct(); 4334 4335 // Get the active container, based on the element that was clicked 4336 4337 var active_container; 4338 if( self.options.parent !== ".project_content" ) { 4339 active_container = self.options.parent; 4340 } else { 4341 active_container = $(e.currentTarget).parents(self.options.parent); 4342 } 4343 4344 // Hide until open if not IE or iOS or an old browser 4345 if( ! Cargo.Config.isIE() && ! self.CheckIOS() || ! self.CheckOldBrowsers() ) 4346 $("#freshbox").css("visibility", "hidden"); 4347 4348 // Write the container and hide the scrollbar 4349 $("#freshbox").data("state", "fullscreen").append($("#fullscreen_src").html()); 4350 4351 // If we're in the older IE, add the related class 4352 if ($.browser.msie && $.browser.version.substr(0,1) < 9) 4353 $("#freshbox").addClass("ie"); 4354 4355 // Append all of the images in freshbar content 4356 $(self.options.element, active_container).each(function() { 4357 // If it's a Cargo uploaded image 4358 if ( $(this).is("[src_o]") ) { 4359 $(this).clone() 4360 .appendTo("#freshbox #fullscreen_imgs") 4361 .attr("style", ""); 4362 } 4363 }); 4364 4365 // Click to progress 4366 $("#freshbox").click(function() { 4367 self.NewElement("next"); 4368 return false; 4369 }); 4370 4371 // Trigger next functions 4372 self.ConfigureSlideshow(); 4373 self.OpenFullscreen(); 4374 self.Navigation(); 4375 }; 4376 4377 this.InitLightbox = function(e, mid, element) { 4378 4379 self.Construct(); 4380 4381 // Get the active container, based on the element that was clicked 4382 var active_container = $(e.currentTarget).parents(self.options.parent); 4383 4384 // Write the container and hide the scrollbar 4385 $("#freshbox").data("state", "lightbox").append($("#fullscreen_src").html()); 4386 4387 // Append all of the images in freshbar content 4388 $(self.options.element, active_container).each(function() { 4389 4390 // If it's a Cargo uploaded image 4391 if ( $(this).is("[src_o]") ) { 4392 $(this).clone() 4393 .appendTo("#freshbox #fullscreen_imgs") 4394 .attr("style", ""); 4395 } 4396 }); 4397 4398 /** 4399 * Loop through each of those images and append them to the 4400 * image container, until we match the ids with the clicked img 4401 */ 4402 var mid_match = false; 4403 4404 $("#freshbox #fullscreen_imgs img").each(function() { 4405 if( mid_match == false && $(this).attr("data-mid") != mid ) { 4406 $(this).appendTo("#freshbox #fullscreen_imgs"); 4407 } else if( mid_match == false && $(this).attr("data-mid") == mid ) { 4408 mid_match = true; 4409 } 4410 }); 4411 4412 // Click to close 4413 $("#freshbox").click(function() { 4414 self.Close(); 4415 4416 return false; 4417 }); 4418 4419 // Trigger next functions 4420 self.ConfigureSlideshow(); 4421 self.Navigation(); 4422 4423 $(document).trigger("freshboxOpen"); 4424 4425 4426 }; 4427 4428 /** 4429 * Construct 4430 * Shared between both functions 4431 */ 4432 this.Construct = function() { 4433 // Grab the overflow of body 4434 this.Data.overflow = $("body").css("overflow"); 4435 this.Data.scroll_x = $(window).scrollLeft(); 4436 this.Data.scroll_y = $(window).scrollTop(); 4437 4438 // Close previous instances 4439 self.Close(); 4440 4441 this.Data.zoomEnabled = false; 4442 this.Data.zoomActive = false; 4443 4444 if(Cargo.Config.isMobile()){ 4445 var viewport = document.querySelector("meta[name=viewport]"), 4446 zoomLevel = this.getViewportScale(); 4447 4448 if(viewport === null) { 4449 // add viewport tag 4450 var viewport = document.createElement('meta'); 4451 viewport.setAttribute('name', 'viewport'); 4452 4453 document.getElementsByTagName('head')[0].appendChild(viewport); 4454 this.Data.oldViewPortContent = ''; 4455 4456 } else { 4457 // store current content attribute value 4458 this.Data.oldViewPortContent = viewport.getAttribute('content'); 4459 } 4460 4461 viewport.setAttribute('content', 'width=device-width, initial-scale='+ zoomLevel +', minimum-scale='+ zoomLevel +', maximum-scale='+ zoomLevel); 4462 4463 } 4464 4465 4466 // Create the freshbox element 4467 $("body").append('<div id="freshbox" />'); 4468 4469 // If the body isn't already hidden, then hide it 4470 if( this.Data.overflow != "hidden" ) $("body").css("overflow", "hidden"); 4471 4472 // IE class for IE and older browsers 4473 if( Cargo.Config.isIE() || self.CheckOldBrowsers() ) $("#freshbox").addClass("ie"); 4474 4475 // Disable scaling and scrolling in iOS 4476 this.PreventIOSEvents(true); 4477 4478 $(window).resize(function() { 4479 self.Resize(); 4480 }); 4481 4482 window.onorientationchange = function() { 4483 self.Resize(); 4484 }; 4485 4486 }; 4487 4488 4489 /** 4490 * Create the slideshow and set the key commands 4491 */ 4492 this.ConfigureSlideshow = function() { 4493 /** 4494 * If there is a single image in the project, 4495 * hide the prev/next buttons. 4496 */ 4497 if( $("#freshbox img").length == 1 ) { 4498 $("#freshbox").addClass("single"); 4499 $("#fullscreen_next, #fullscreen_prev").remove(); 4500 } 4501 4502 // Configure the nav 4503 $("#fullscreen_next").click(function(e) { 4504 self.NewElement("next"); 4505 return false; 4506 }); 4507 4508 $("#fullscreen_close").click(function(e) { 4509 self.Close(); 4510 self.CloseFullscreen(); 4511 return false; 4512 }); 4513 4514 $("#fullscreen_prev").click(function(e) { 4515 self.NewElement("prev"); 4516 return false; 4517 }); 4518 4519 $("#fullscreen_zoom").click(function(e) { 4520 self.toggleZoom(); 4521 self.Data.zoomEnabled =! self.Data.zoomEnabled; 4522 return false; 4523 }); 4524 4525 /** 4526 * Keyboard nav 4527 */ 4528 4529 // Unbind previous instances 4530 shortcut.remove("Up"); 4531 shortcut.remove("Down"); 4532 shortcut.remove("Left"); 4533 shortcut.remove("Right"); 4534 // shortcut.remove("Esc"); 4535 4536 shortcut.add("Up",function() { 4537 self.NewElement("prev"); 4538 },{ 4539 'type' : 'keydown', 4540 'disable_in_input' : true, 4541 'keycode' : 38 4542 }); 4543 4544 shortcut.add("Down",function() { 4545 self.NewElement("next"); 4546 },{ 4547 'type' : 'keydown', 4548 'disable_in_input' : true, 4549 'keycode' : 36 4550 }); 4551 4552 shortcut.add("Left",function() { 4553 self.NewElement("prev"); 4554 },{ 4555 'type' : 'keydown', 4556 'disable_in_input' : true, 4557 'keycode' : 37 4558 }); 4559 4560 shortcut.add("Right",function() { 4561 self.NewElement("next"); 4562 },{ 4563 'type' : 'keydown', 4564 'disable_in_input' : true, 4565 'keycode' : 39 4566 }); 4567 4568 shortcut.add("Esc",function() { 4569 self.Close(); 4570 self.CloseFullscreen(); 4571 }, { 4572 'type' : 'keydown', 4573 'keycode' : 27 4574 }); 4575 4576 // Assign the first image as active and format 4577 self.NewElement("next"); 4578 4579 if(Cargo.Config.isMobile()){ 4580 $('.freshbox_navigation').remove(); 4581 $("#freshbox").unbind(); 4582 4583 this.Data.freshboxHammer = Hammer($('#freshbox')[0], { 4584 prevent_default: true, 4585 swipe_velocity: 0.4, 4586 tap_always: false 4587 }); 4588 4589 this.Data.freshboxHammer.on('swipeleft', function(){ 4590 self.NewElement("next"); 4591 }); 4592 4593 this.Data.freshboxHammer.on('swiperight', function(){ 4594 self.NewElement("prev"); 4595 }); 4596 4597 this.Data.freshboxHammer.on('tap', function(e){
4598 clearTimeout(self.Data.tapCloseTimeout); 4599 4600 self.Data.tapCloseTimeout = setTimeout(function(){ 4601 self.Close(); 4602 self.CloseFullscreen(); 4603 }, 250); 4604 4605 }); 4606 4607 this.Data.freshboxHammer.on('doubletap', function(e){ 4608 clearTimeout(self.Data.tapCloseTimeout); 4609 self.toggleZoom(); 4610 self.Data.zoomEnabled =! self.Data.zoomEnabled; 4611 }); 4612 4613 this.Data.freshboxHammer.on('pinchin', function(e){ 4614 clearTimeout(self.Data.tapCloseTimeout); 4615 if(self.Data.zoomActive){ 4616 self.toggleZoom(); 4617 self.Data.zoomEnabled =! self.Data.zoomEnabled; 4618 } 4619 e.gesture.stopDetect(); 4620 }); 4621 4622 this.Data.freshboxHammer.on('pinchout', function(e){ 4623 clearTimeout(self.Data.tapCloseTimeout); 4624 if(!self.Data.zoomActive){ 4625 self.toggleZoom(); 4626 self.Data.zoomEnabled =! self.Data.zoomEnabled; 4627 } 4628 e.gesture.stopDetect(); 4629 }); 4630 } 4631 4632 }; 4633 4634 /** 4635 * For slideshows, what the next element will be 4636 */ 4637 this.NewElement = function(direction) { 4638 4639 // Remove preload image and spinner 4640 $("#freshbox img.preload, #freshbox_loading").remove(); 4641 4642 // Previous 4643 if( direction == "prev") { 4644 // Prepend the active image to the begining of the container 4645 $("#freshbox img.active").removeClass("active").prependTo($("#fullscreen_imgs")); 4646 $("#fullscreen_imgs img:last").addClass("active"); 4647 4648 // Next 4649 } else { 4650 // Append the active image to the end of the container 4651 $("#freshbox img.active").removeClass("active").appendTo($("#fullscreen_imgs")); 4652 $("#fullscreen_imgs img:first").addClass("active"); 4653 }; 4654 4655 // Move the active image and preload 4656 $("#freshbox img.active").prependTo($("#freshbox")); 4657 4658 self.LoadIMG($("#freshbox img.active")); 4659 self.Resize(); 4660 4661 }; 4662 4663 this.toggleZoom = function(){ 4664 4665 function constrain(val, min, max) { 4666 return Math.min(Math.max(val, min), max); 4667 } 4668 4669 var activeImage = $('#freshbox img.active.zoomable'), 4670 transformFallback = Cargo.Config.isOldIE(), 4671 oldMaxWidth, 4672 oldMaxHeight; 4673 4674 if(activeImage.length > 0) { 4675 4676 this.Data.zoomedImage = activeImage; 4677 4678 if(activeImage.hasClass('zoomed')){ 4679 4680 activeImage.removeClass('zoomed'); 4681 4682 $('a.freshbox_nav_button#fullscreen_zoom').removeClass('active'); 4683 4684 this.clearZoomEvents(); 4685 4686 } else { 4687 4688 this.Data.oldMaxHeight = activeImage[0].style.maxHeight, 4689 this.Data.oldMaxWidth = activeImage[0].style.maxWidth; 4690 4691 activeImage.addClass('zoomed'); 4692 $('a.freshbox_nav_button#fullscreen_zoom').addClass('active'); 4693 4694 this.Data.zoomActive = true; 4695 4696 activeImage.css({ 4697 'maxWidth' : 'none', 4698 'maxHeight' : 'none', 4699 'cursor' : function(){ 4700 if ($.browser.mozilla) { 4701 return '-moz-grab'; 4702 } else if ($.browser.webkit) { 4703 return '-webkit-grab'; 4704 } else { 4705 return 'move'; 4706 } 4707 } 4708 }); 4709 4710 // make drag work outside of the browser window. 4711 if(activeImage[0].setCapture) { 4712 activeImage[0].setCapture(); 4713 } 4714 4715 var isDragging = false, 4716 imageHeight = parseInt(activeImage.attr('height_o')), 4717 imageWidth = parseInt(activeImage.attr('width_o')), 4718 windowHeight = window.innerHeight, 4719 windowWidth = window.innerWidth, 4720 offsetX = 0, 4721 offsetY = 0, 4722 maxXoffset = 9e9, 4723 maxYoffset = 9e9, 4724 dragXMultiplier = 1.0, 4725 dragYMultiplier = 1.0, 4726 dragTimeout, 4727 pageX, 4728 pageY; 4729 4730 $(window).bind('resize.freshboxZoom', function(){ 4731 windowWidth = window.innerWidth; 4732 windowHeight = window.innerHeight; 4733 4734 activeImage.css({ 4735 'marginLeft' : ((windowWidth - imageWidth) / 2) + 'px', 4736 'marginTop' : ((windowHeight - imageHeight) / 2) + 'px' 4737 }); 4738 4739 // calculate offset bounds from image center 4740 maxXoffset = constrain(((imageWidth - windowWidth) / 2), 0, 9e9); 4741 maxYoffset = constrain(((imageHeight - windowHeight) / 2), 0, 9e9); 4742 4743 // calculate drag multipliers for really big images 4744 dragXMultiplier = constrain(imageWidth / windowWidth, 1, 2); 4745 dragYMultiplier = constrain(imageHeight / windowHeight, 1, 2); 4746 });
4747 4748 $(window).trigger('resize.freshboxZoom'); 4749 4750 if(Cargo.Config.isMobile()){ 4751 4752 this.Data.zoomHammer = Hammer(activeImage[0], { 4753 tap_always: false, 4754 prevent_default: true 4755 }).on("dragstart", function(e){ 4756 if(e.gesture.touches.length > 0){ 4757 pageX = e.gesture.touches[0].pageX; 4758 pageY = e.gesture.touches[0].pageY; 4759 } 4760 }).on("drag", function(e){ 4761 if(e.gesture.touches.length > 0){ 4762 4763 if(!isNaN(pageX) && !isNaN(pageY)){ 4764 4765 offsetX -= (pageX - e.gesture.touches[0].pageX) * dragXMultiplier; 4766 offsetY -= (pageY - e.gesture.touches[0].pageY) * dragYMultiplier; 4767 4768 offsetX = constrain(offsetX, -maxXoffset, maxXoffset); 4769 offsetY = constrain(offsetY, -maxYoffset, maxYoffset); 4770 4771 activeImage.css('-webkit-transform', 'translate3d(' + offsetX + 'px, ' + offsetY + 'px, 0)'); 4772 4773 } 4774 4775 pageX = e.gesture.touches[0].pageX; 4776 pageY = e.gesture.touches[0].pageY; 4777 } 4778 4779 return false; 4780 }); 4781 4782 } else { 4783 // desktop drag behavior 4784 activeImage.bind('mousedown.freshboxZoom', function(e){ 4785 4786 // only left mouse button 4787 if(e.button === 0) { 4788 pageX = e.pageX; 4789 pageY = e.pageY; 4790 4791 dragTimeout = setTimeout(function(){ 4792 isDragging = true; 4793 4794 activeImage.css({ 4795 'cursor' : function(){ 4796 if ($.browser.mozilla) { 4797 return '-moz-grabbing'; 4798 } else if ($.browser.webkit) { 4799 return '-webkit-grabbing'; 4800 } else { 4801 return 'move'; 4802 } 4803 } 4804 }); 4805 4806 $(document).bind('mouseup.freshboxZoom', function(){ 4807 4808 clearTimeout(dragTimeout); 4809 4810 $(document).unbind('mousemove.freshboxZoom'); 4811 $(document).unbind('mouseup.freshboxZoom'); 4812 4813 if(activeImage[0].releaseCapture) { 4814 activeImage[0].releaseCapture(); 4815 } 4816 4817 // make sure the click event fires first; 4818 setTimeout(function(){ 4819 isDragging = false; 4820 }); 4821 4822 }); 4823 }, 150); 4824 4825 $(document).bind('mousemove.freshboxZoom', function(e){ 4826 4827 offsetX -= (pageX - e.pageX) * dragXMultiplier; 4828 offsetY -= (pageY - e.pageY) * dragYMultiplier; 4829 4830 offsetX = constrain(offsetX, -maxXoffset, maxXoffset); 4831 offsetY = constrain(offsetY, -maxYoffset, maxYoffset); 4832 4833 activeImage.css({ 4834 left: offsetX + 'px', 4835 top: offsetY + 'px' 4836 }); 4837 4838 pageX = e.pageX; 4839 pageY = e.pageY; 4840 4841 });
4842 } 4843 4844 return false; 4845 4846 }); 4847 4848 activeImage.bind('click.freshboxZoom', function(e){ 4849 4850 activeImage.css({ 4851 'cursor' : function(){ 4852 if ($.browser.mozilla) { 4853 return '-moz-grab'; 4854 } else if ($.browser.webkit) { 4855 return '-webkit-grab'; 4856 } else { 4857 return 'move'; 4858 } 4859 } 4860 }); 4861 4862 clearTimeout(dragTimeout); 4863 4864 if(isDragging) { 4865 return false; 4866 } 4867 }); 4868 4869 } 4870 } 4871 } 4872 }; 4873 4874 this.clearZoomEvents = function(){ 4875 $(document).unbind('mousemove.freshboxZoom'); 4876 $(document).unbind('mouseup.freshboxZoom'); 4877 4878 $(window).unbind('resize.freshboxZoom'); 4879 4880 if(this.Data.zoomedImage !== undefined) { 4881 this.Data.zoomedImage.unbind('mousedown.freshboxZoom'); 4882 this.Data.zoomedImage.unbind('click.freshboxZoom'); 4883 4884 if(this.Data.zoomedImage[0].releaseCapture) { 4885 this.Data.zoomedImage[0].releaseCapture(); 4886 } 4887 4888 if(Cargo.Config.isMobile()){ 4889 // clear Hammer events 4890 this.Data.zoomHammer.dispose(); 4891 } 4892 4893 this.Data.zoomedImage.css({ 4894 'transform' : '', 4895 '-webkit-transform' : '', 4896 'left' : '0', 4897 'top' : '0', 4898 'marginTop' : 'auto', 4899 'marginLeft' : 'auto', 4900 'maxWidth' : (this.Data.oldMaxWidth === undefined ? '100%' : this.Data.oldMaxWidth), 4901 'maxHeight' : (this.Data.oldMaxHeight === undefined ? '100%' : this.Data.oldMaxHeight), 4902 'cursor' : function(){ 4903 return 'pointer'; 4904 } 4905 }); 4906 } 4907 4908 this.Data.zoomActive = false; 4909 4910 this.Resize({ 4911 type: 'orientationchange' 4912 }); 4913 }; 4914 4915 /** 4916 * Load an image 4917 */ 4918 this.LoadIMG = function($image) { 4919 4920 var activeImage = $image[0], 4921 self = this; 4922 4923 if(activeImage === undefined) { 4924 return; 4925 } 4926 4927 var loadOriginal = parseInt(activeImage.getAttribute('width_o')) > parseInt(activeImage.getAttribute('width')); 4928 4929 activeImage.removeAttribute('style'); 4930 activeImage.setAttribute('class', 'active'); 4931 4932 $(activeImage).css({ 4933 'maxHeight' : '100%', 4934 'maxWidth' : '100%', 4935 'width' : 'auto', 4936 'height' : 'auto', 4937 'margin' : 'auto', 4938 'top' : '0', 4939 'bottom' : '0', 4940 'left' : '0', 4941 'right' : '0' 4942 }); 4943 4944 $(activeImage).css('cursor', 'pointer'); 4945 4946 $('a.freshbox_nav_button#fullscreen_zoom').hide(); 4947 4948 if( loadOriginal === true ){ 4949 4950 // there's a bigger image available. If we're on retina we want to show higher pixel 4951 // densities. If the image @ 75% is still bigger than the active image, scale it down. 4952 // 4953 var maxWidthAt75Percent = (parseInt(activeImage.getAttribute('width_o')) / 100.0) * 75; 4954 4955 if(window.devicePixelRatio >= 1.5 && maxWidthAt75Percent > parseInt(activeImage.getAttribute('width'))){ 4956 4957 if(maxWidthAt75Percent > window.innerWidth) { 4958 maxWidthAt75Percent = window.innerWidth; 4959 } 4960 4961 $(activeImage).css({ 4962 'maxWidth' : maxWidthAt75Percent + 'px' 4963 }).attr('data-restrict-width', maxWidthAt75Percent); 4964 } 4965 4966 // mark the currently active image as preloader for the original image that's gonna be loaded. 4967 activeImage.setAttribute('class', 'preload'); 4968 4969 // create new image container for the original. 4970 var originalImage = new Image(), 4971 i; 4972 4973 // clone attributes 4974 for( i = 0; i < activeImage.attributes.length; i++ ) { 4975 if(activeImage.attributes[i].name !== "src") { 4976 originalImage.setAttribute(activeImage.attributes[i].name, activeImage.attributes[i].value); 4977 } 4978 } 4979 4980 // set original source 4981 originalImage.src = activeImage.getAttribute('src_o'); 4982 4983 // mark as active 4984 originalImage.setAttribute('class', 'active'); 4985 4986 // add to DOM 4987 activeImage.parentNode.appendChild(originalImage); 4988 4989 // original is not cached, show loading anim. 4990 if(originalImage.complete === false) { 4991 4992 spinner = $("<img />").attr("src", "/_gfx/loadingAnim.gif").attr("id", "freshbox_loading").appendTo("#freshbox"); 4993 4994 // overwrite design.css for older designs to force the loader on top. 4995 if(spinner.css('zIndex') === "101") { 4996 spinner.css('zIndex', '115'); 4997 spinner.css('opacity', '0.4'); 4998 } 4999 5000 originalImage.onload = function(){ 5001 $('#freshbox_loading').remove(); 5002 5003 if(activeImage !== null && activeImage.parentNode !== null){ 5004 activeImage.parentNode.removeChild(activeImage); 5005 } 5006 5007 self.Resize(); 5008 } 5009 5010 } else { 5011 activeImage.parentNode.removeChild(activeImage); 5012 } 5013 } 5014 5015 Cargo.ReplaceLoadingAnims($("#freshbox img[src$='/loadingAnim.g
5015if']")); 5016 5017 5018 this.Resize(); 5019 5020 5021 if(this.Data.zoomEnabled === true){ 5022 this.toggleZoom(); 5023 } 5024 5025 }; 5026 5027 /** 5028 * Set the navigation 5029 */ 5030 this.Navigation = function() { 5031 var transition_time = 200, 5032 hover = false, 5033 nav_fadeout = null, 5034 nav_timeout = 650, 5035 nav_track = {}; 5036 5037 nav_fadeout = setTimeout('$(".freshbox_navigation").stop().fadeOut(200)', nav_timeout); 5038 5039 $(".freshbox_navigation").mouseenter(function() { 5040 hover = true; 5041 }); 5042 5043 $(".freshbox_navigation").mouseleave(function() { 5044 hover = false; 5045 }); 5046 5047 $("#freshbox").mousemove(function(e) { 5048 5049 // Show the project nav if you're on a project 5050 if(nav_track.x != e.clientX && nav_track.y != e.clientY) { 5051 $(".freshbox_navigation").fadeIn(transition_time); 5052 } 5053 5054 nav_track = { 5055 "x" : e.clientX, 5056 "y" : e.clientY 5057 }; 5058 5059 // If the text is visible, or if you're hovering over the top 5060 // always show the header/toolbar 5061 if (hover == true) { 5062 clearTimeout(nav_fadeout); 5063 5064 // Otherwise, fade the project nav / header out after a second or so 5065 } else { 5066 if(nav_fadeout != null) { clearTimeout(nav_fadeout) }; 5067 nav_fadeout = setTimeout('$(".freshbox_navigation").stop().fadeOut(200)', nav_timeout); 5068 } 5069 5070 }); 5071 }; 5072 5073 /** 5074 * What happens when the window is resized 5075 */ 5076 this.Resize = function(e) { 5077 5078 var preload = $('#freshbox img.preload'), 5079 active = $('#freshbox img.active'); 5080 5081 if(this.Data.allowZoom === true) { 5082 if(parseInt(active.attr('width_o')) > window.innerWidth || parseInt(active.attr('height_o')) > window.innerHeight){ 5083 active.addClass('zoomable'); 5084 $('a.freshbox_nav_button#fullscreen_zoom').show(); 5085 5086 } else { 5087 5088 if(active.hasClass('zoomable')) { 5089 5090 if(this.Data.zoomActive === true){ 5091 5092 var self = this; 5093 5094 setTimeout(function(){ 5095 self.toggleZoom(); 5096 active.removeClass('zoomable'); 5097 $('a.freshbox_nav_button#fullscreen_zoom').hide(); 5098 active.css('cursor', ''); 5099 }, 50); 5100 5101 } else { 5102 5103 active.removeClass('zoomable'); 5104 $('a.freshbox_nav_button#fullscreen_zoom').hide(); 5105 active.css('cursor', ''); 5106 5107 } 5108 } 5109 } 5110 } 5111 5112 if(this.Data.zoomActive === true){ 5113 return false; 5114 } 5115 5116 if(e !== undefined) { 5117 5118 if(e.type === "orientationchange" || e.type === "resize") { 5119 // recalculate 5120 $('#freshbox [data-restrict-width]').each(function(){ 5121 5122 var maxWidthAt75Percent = (parseInt(this.getAttribute('width_o')) / 100.0) * 75; 5123 5124 if(window.devicePixelRatio >= 1.5 && maxWidthAt75Percent > parseInt(this.getAttribute('width'))){ 5125 5126 if(maxWidthAt75Percent > window.innerWidth) { 5127 maxWidthAt75Percent = window.innerWidth; 5128 } 5129 5130 $(this).css({ 5131 'maxWidth' : maxWidthAt75Percent + 'px' 5132 }).attr('data-restrict-width', maxWidthAt75Percent); 5133 } 5134 5135 }); 5136 5137 } 5138 5139 } 5140 5141 if(preload.length > 0){ 5142 5143 var parent = preload.parent(), 5144 parent_ratio = parent.width() / parent.height(); 5145 preload_ratio = parseInt(preload.attr('width')) / parseInt(preload.attr('height')), 5146 maxWidth = preload.attr('width_o'); 5147 5148 5149 if(preload.attr('data-restrict-width') !== undefined) { 5150 maxWidth = preload.attr('data-restrict-width'); 5151 } 5152 5153 preload.css({ 5154 'maxWidth' : maxWidth + 'px', 5155 'maxHeight' : '99999px', 5156 'width' : preload_ratio > parent_ratio ? parent.width() : parent.height() * (preload_ratio) + 'px' 5157 }); 5158 } 5159 5160 }; 5161 5162 /** 5163 * Opens the site into fullscreen mode 5164 */ 5165 this.OpenFullscreen = function() { 5166 // The element we're opening 5167 var docElem = document.documentElement; 5168 5169 // Browser checks to open fullscreen 5170 if (docElem.requestFullscreen) { 5171 docElem.requestFullscreen(); 5172 } else if (docElem.mozRequestFullScreen) { 5173 docElem.mozRequestFullScreen(); 5174 } else if (docElem.webkitRequestFullScreen) { 5175 docElem.webkitRequestFullScreen(); 5176 } else if (docElem.msRequestFullscreen) { 5177 docElem.msRequestFullscreen(); 5178 } else { 5179 // Fail, except on iOS 5180 if ( ! this.CheckIOS()) 5181 return; 5182 } 5183 5184 // When we switch fullscreen states 5185 docElem.addEventListener("mozfullscreenchange",function(){ 5186 if ( ! document.webkitIsFullScreen) 5187 self.Close(); 5188 }, false); 5189 5190 docElem.addEventListener("webkitfullscreenchange",function(){ 5191 if ( ! document.webkitIsFullScreen) 5192 self.Close(); 5193 }, false); 5194 5195 // Show the freshbox 5196 if ( ! Cargo.Config.isIE()) 5197 setTimeout('$("#freshbox").css("visibility", "visible")', 100); 5198 }; 5199 5200 /** 5201 * Exits fullscreen mode from elsewhere 5202 */ 5203 this.CloseFullscreen = function() { 5204 if(document.exitFullscreen) { 5205 document.exitFullscreen(); 5206 } else if(document.mozCancelFullScreen) { 5207 document.mozCancelFullScreen(); 5208 } else if(document.webkitCancelFullScreen) { 5209 document.webkitCancelFullScreen(); 5210 } else if(document.msExitFullscreen) { 5211 document.msExitFullscreen(); 5212 } 5213 }; 5214 5215 /** 5216 * Checks the window width versus screen width when resizing 5217 * to toggle the fullscreen button and toolset 5218 */ 5219 this.CheckFullscreen = function() { 5220 if( screen.width > $(window).width() + 20 ) { 5221 self.Close(); 5222 } 5223 }; 5224 5225 /** 5226 * Can we do some more advanced stuff? True / False 5227 * Returns false if your browser is new 5228 */ 5229 this.CheckOldBrowsers = function() { 5230 // If Firefox, and version 3.6 or less 5231 if( $.browser.mozilla && $.browser.version.slice(0,3) >= 1.9 ) { 5232 return false 5233 // Check webkit, if version 3 or less 5234 } else if ( $.browser.webkit && $.browser.version.substr(0,1) >= 4 ) { 5235 return false 5236 } else { 5237 return true; 5238 } 5239 }; 5240 5241 this.CheckIOS = function() { 5242 if (navigator.userAgent.match(/i(Phone|Pod|Pad)/i)) { 5243 return true; 5244 } else { 5245 return false; 5246 } 5247 }; 5248 5249 this.GetIOSWindowSize = function() { 5250 var width = screen.width; 5251 var height = screen.height; 5252 5253 if (window.orientation !== 0) { 5254 width = screen.height; 5255 height = screen.width; 5256 } 5257 5258 if (navigator.userAgent.match(/i(Phone|Pod)/i)) { 5259 if (window.orientation === 0) { 5260 height -= 44; 5261 } else { 5262 height -= 32; 5263 } 5264 } 5265 5266 if (navigator.userAgent.match(/iPad/i)) 5267 height -= 58; 5268 5269 return { 5270 width: width, 5271 height: height 5272 }; 5273 }; 5274 5275 this.GetIOSViewportSize = function() { 5276 var windowSize = this.GetIOSWindowSize(); 5277 var scale = this.GetIOSScale(); 5278 5279 return { 5280 width: (windowSize.width * scale), 5281 height: (windowSize.height * scale) 5282 }; 5283 }; 5284 5285 this.GetIOSScale = function() { 5286 return document.body.offsetWidth / this.GetIOSWindowSize().width; 5287 }; 5288 5289 this.GetIOSZoom = function() { 5290 return document.documentElement.clientWidth / window.innerWidth; 5291 }; 5292 5293 this.PreventIOSEvents = function(restrict) { 5294 if ( ! this.CheckIOS()) 5295 return; 5296 5297 if (restrict) { 5298 $('body').live('touchmove', function(event) { 5299 event.preventDefault(); 5300 }); 5301 } else { 5302 $('body').die('touchmove'); 5303 } 5304 }; 5305 5306 this.getOrientation = function(){ 5307 var orientation = window.orientation; 5308 5309 if(orientation === undefined) { 5310 // No JavaScript orientation support. Work it out. 5311 if(document.documentElement.clientWidth > document.documentElement.clientHeight) orientation = 'landscape'; 5312 else orientation = 'portrait'; 5313 5314 } 5315 else if(orientation === 0 || orientation === 180) orientation = 'portrait'; 5316 else orientation = 'landscape'; // Assumed default, most laptop and PC screens. 5317 5318 return orientation; 5319 }; 5320 5321 this.getViewportScale = function(){ 5322 var viewportScale = undefined; 5323 5324 // Get viewport width 5325 var viewportWidth = document.documentElement.clientWidth; 5326 5327 // Abort. Screen width is greater than the viewport width (not fullscreen). 5328 if(screen.width > viewportWidth) { 5329 return; 5330 } 5331 5332 // Get the orientation corrected screen width 5333 var orientation = this.getOrientation(); 5334 var screenWidth = screen.width; 5335 5336 if(orientation === 'portrait') { 5337 // Take smaller of the two dimensions 5338 if(screen.width > screen.height) screenWidth = screen.height; 5339 5340 } 5341 else { 5342 // Take larger of the two dimensions 5343 if(screen.width < screen.height) screenWidth = screen.height; 5344 5345 } 5346 5347 // Calculate viewport scale 5348 var viewportScale = screenWidth / window.innerWidth; 5349 return viewportScale; 5350 }; 5351 5352 /** 5353 * Closes the lightbox 5354 */ 5355 this.Close = function() { 5356 5357 // Reset the overflow on body 5358 if ($("body").attr("style") && this.Data.overflow != "hidden") 5359 $("body").css("overflow", ""); 5360 5361 // Return to the scroll position if IE 5362 if ( Cargo.Config.isIE() ) { 5363 $(window).scrollTop(this.Data.scroll_y); 5364 $(window).scrollLeft(this.Data.scroll_x); 5365 } 5366 5367 // Remove the freshbox 5368 $("#freshbox").die().unbind().remove(); 5369 5370 // Reenable scaling and scrolling in iOS 5371 this.PreventIOSEvents(false); 5372 5373 shortcut.remove("Up"); 5374 shortcut.remove("Down"); 5375 shortcut.remove("Left"); 5376 shortcut.remove("Right"); 5377 5378 // reset viewport 5379 var viewport = document.querySelector("meta[name=viewport]"); 5380 5381 if(viewport !== null && this.Data.oldViewPortContent !== undefined) { 5382 viewport.setAttribute('content', this.Data.oldViewPortContent); 5383 } 5384 5385 $(document).trigger("freshboxClose"); 5386 }; 5387 5388 // Return the data, keep it chaining 5389 return this.each(function() { 5390 // Keep chaining 5391 var $this = $(this); 5392 5393 // Run it 5394 self.Init(); 5395 5396 }); 5397 5398 5399 }; 5400 5401})(jQuery); 5402/* 5403 * End freshbox plugin 5404 */ 5405 5406 5407///////////////////////////////////////////////////////////////////////////////////////////////// 5408/* !EVENT (document).ready */ 5409$(document).ready(function() { 5410 FollowingSniff(); 5411 if($("body.blog").length > 0) { 5412 Projects.Slideshow.CheckForSlideshow(); 5413 Projects.Video.CheckForVideo(); 5414 } 5415 5416 // Set the project close click 5417 $(".project_index a").live("click", function() { 5418 // Load "this" into a variable 5419 Projects.Data.CloseObj = $(this); 5420 Projects.CloseProject(); 5421 return false; 5422 });
5423 5424 // Sniff for ajax links 5425 Cargo.Ajax.Init(); 5426 5427 // Sniff for fullscreen 5428 $(".entry").FreshBox(); 5429 5430 // Sniff for inspector 5431 if(location.search.replace("?","") == "inspector") { 5432 loadInspector(); 5433 } 5434 5435 // Sniff for password, auto focus 5436 if($(".password_protected").length > 0) { 5437 $(".ajax_post_form input[name='user_password']").focus(); 5438 } 5439 5440 // 5441 Projects.Video.CheckForVideo(); 5442 5443 /* 5444 * Load the toolset and rail 5445 * @todo: Clean this up 5446 */ 5447 5448 if ( (Cargo.Location.GetCargoUrl() || Cargo.Location.IsUserImageGallery()) && !Cargo.Location.IsInFrame()) { 5449 $.getJSON("//"+Cargo.Config.get('CARGO_URL')+"/dispatch/cargosite/cargoToolset/"+Cargo.Location.GetDomainOrUrl()+"?callback=?", { is_following : Cargo.Location.IsFollowing() }, function(data) { 5450 if( data.error == "nocookie") { 5451 /* No cookie found */ 5452 return; 5453 } else { 5454 if( data.jdata.url ) { 5455 // Set the cookie URL 5456 Cargo.Config.SetCookieUrl(data.jdata.url); 5457 Cargo.Config.SetCookieUid(data.jdata.uid); 5458 5459 if(Cargo.Location.IsCustomDomain()) { 5460 $.post( 5461 "/dispatch/cargosite/cargoToolsetLocal", 5462 { token : data.jdata.token, url : data.jdata.url, muid : data.jdata.muid, cv : data.jdata.cv }, 5463 function(dataObj) { 5464 if(Cargo.InspectorLoading === true) { 5465 // Don't show this if we are inspecting 5466 return; 5467 } 5468 5469 if($("#follow_popup").length == 0) { 5470 $("body").append(dataObj.jdata.html); 5471 } else { 5472 $("#follow_popup").replaceWith(dataObj.jdata.html); 5473 if(Cargo.Location.IsFollowing()) { 5474 // Add the light class to this 5475 $("#follow_popup").attr("class", "light"); 5476 } 5477 } 5478 }, 5479 "json"); 5480 } 5481 5482 } 5483 5484 if( data.html ) { 5485 if( Cargo.Location.IsFollowing() ) { 5486 /* 5487 * Only for the following page 5488 */ 5489 $("#follow_links").html(data.html); 5490 5491 } else { 5492 $("body").prepend( data.html ); 5493 } 5494 5495 } 5496 5497 loadRail(true, data.jdata.url); 5498 } 5499 }); 5500 } 5501 5502 /* Always init the following click */ 5503 Cargo.Follow.Init(); 5504 5505 Cargo.Analytics.Init(); 5506 5507 Cargo.EU_cookie_notification(); 5508 5509}); 5510 5511///////////////////////////////////////////////////////////////////////////////////////////////// 5512 5513/** 5514 * Toggles the header into hi-res our out 5515 * Called from the admin frame 5516 */ 5517function ToggleHeaderHiRes(which, url) { 5518 if($('img[src$="/'+url+'"]').length > 0) { 5519 if(which == "2x") { 5520 $('img[src$="/'+url+'"]').width( Math.floor($('img[src$="/'+url+'"]').width() / 2) ); 5521 $('img[src$="/'+url+'"]').height( Math.floor($('img[src$="/'+url+'"]').height() / 2) ); 5522 } else { 5523 $('img[src$="/'+url+'"]').width( Math.floor($('img[src$="/'+url+'"]').width() * 2) ); 5524 $('img[src$="/'+url+'"]').height( Math.floor($('img[src$="/'+url+'"]').height() * 2) ); 5525 } 5526 } 5527} 5528/* 5529 * Load the Rail 5530 */ 5531function loadRail(show_toolset, cookie_url) { 5532 if(!cookie_url) { 5533 /* if no cookie url is passed, try and get from cookie */ 5534 cookie_url = Cargo.Config.GetCookieUrl(); 5535 } 5536 5537 $.post('/dispatch/rail/getRail', { url : Cargo.Location.GetCargoUrl(), curl : cookie_url }, function(serverData) { 5538 var data = $.parseJSON(serverData); 5539 5540 /* Write to the page */ 5541 $("body").append(data.templates.masterview_tpl); 5542 5543 /* Preload the templates and model */ 5544 Cargo.app.Rail.Templates = data.templates; 5545 Cargo.app.Rail.Model.LoadModels(data.models); 5546 5547 Cargo.Rail.Init(); 5548 if(show_toolset) { 5549 $(document).trigger("initToolset"); 5550 Cargo.app.Rail.Events.trigger("toolset:loaded"); 5551 } 5552 }); 5553} 5554 5555/* !EVENT paginationComplete */ 5556// Create callbacks for pagination 5557$(document).bind("paginationComplete", function(e) { 5558 if($("#home_container").length == 0){ 5559 $(".entry").FreshBox(); 5560 } 5561}); 5562 5563///////////////////////////////////////////////////////////////////////////////////////////////// 5564/* !EVENT directLinkLoaded */ 5565$(document).bind("directLinkLoaded", function(e, path) { 5566 // Any user options set that need to happen 5567 Projects.Helper.UserOptionActions(); 5568 5569 // Set the nav and thumb highlights 5570 Projects.Helper.SetNavHighlight(); 5571 Projects.Helper.SetThumbHighlight(); 5572 5573 // Set the current page / paginate 5574 Projects.Helper.SetCurrentPages(); 5575}); 5576
5577///////////////////////////////////////////////////////////////////////////////////////////////// 5578 5579function hideContextMenu() { 5580 $("#toolset_admin").removeClass("toolset_active"); 5581 $("#toolset_menu").hide(); 5582 5583 toolsetToggle("on"); 5584} 5585 5586///////////////////////////////////////////////////////////////////////////////////////////////// 5587 5588function showContextMenu(which) { 5589 var toolset_top = $("#toolset").css("top"); 5590 var toolset_right = $("#toolset").css("right"); 5591 $("#toolset_menu").css({"top" : toolset_top , "right" : toolset_right}); 5592 $("#toolset_admin").addClass("toolset_active"); 5593 $("#toolset_menu").show(); 5594 $("#css_inspector_trigger").live("click", function() { 5595 loadInspector(); 5596 return false; 5597 }); 5598} 5599 5600///////////////////////////////////////////////////////////////////////////////////////////////// 5601/** 5602 * This loads the inspector 5603 */ 5604function loadInspector() { 5605 5606 loadInspector3(); 5607 /* 5608 5609 if($("#inspector").length > 0) { 5610 // inspector is loaded 5611 5612 } else { 5613 var dependencies = [ 5614 "/_jsapps/inspector/codemirror-2.15/codemirror-package.js", 5615 "/_jsapps/inspector/jquery.mini.colors.js", 5616 "/_jsapps/inspector/jquery-ui-1.8.18.custom.min.js", 5617 "/_jsapps/inspector/inspector.css" 5618 ]; 5619 $.loadFiles(dependencies).done(function() { 5620 $.post(Cargo.Dispatcher.GetUrl("admin/loadInspector/" + $("#url").val()), {}, function(data) { 5621 if (data.error == "") { 5622 var jdata = $.parseJSON(data.jdata); 5623 $.loadFiles("/_jsapps/inspector/inspector-1.0.js").done(function() { 5624 // Make sure they didn't double click 5625 if( $("#inspector").length <= 0 ) { 5626 CSS.Sheet.ParseAndSet(jdata.css_data); // Load the CSS data 5627 Inspector.CustomHTML.SetData(jdata.html_data); // Load the HTML data 5628 $("body").append(data.html); // append the inspector 5629 Inspector.init(jdata.inspector_position); // Initialize 5630 } 5631 }); 5632 } else if (data.error == "Refresh") { 5633 document.location.href = document.location + "?inspector"; 5634 } else { 5635 alert("Log in to use the Inspector"); 5636 } 5637 }, "json"); 5638 }); 5639 } */ 5640} 5641///////////////////////////////////////////////////////////////////////////////////////////////// 5642 5643function loadInspector3() { 5644 5645 if(window.editor !== undefined){ 5646 return false; 5647 } 5648 5649 Cargo.Core = Cargo.Core || {}; 5650 5651 var dependencies = [ 5652 "/_jsapps/api/_cargo/_core/inspector3.js" 5653 ]; 5654 5655 $.loadFiles(dependencies).done(function() { 5656 5657 var oldjQuery = $.noConflict(true); 5658 5659 oldjQuery.loadFiles(['/_jsapps/_libs/jquery/jquery-min.js']).done(function() { 5660 5661 Cargo.Core.Inspector3.load({ 5662 onInit: function(inspector){ 5663 5664 var $ = inspector.options.coreWindow.$, 5665 Cargo = inspector.options.coreWindow.Cargo; 5666 5667 setTimeout(function(){ 5668 $(inspector.options.coreDocument).ready(function() { Cargo.app.Rail.Events.on("toolset:loaded", function() { 5669 $("#toolset, #toolset *, #toolset_menu, #toolset_menu *, #design_panel, #design_panel *").unbind(); 5670 $("#toolset_follow_pair a, #toolset_follow a").unbind(); 5671 $("#toolset").fadeTo('fast', 0.3).css('pointer-events', 'none'); 5672 }); }); 5673 5674 $("#toolset, #toolset *, #toolset_menu, #toolset_menu *, #design_panel, #design_panel *").unbind(); 5675 $("#toolset_follow_pair a, #toolset_follow a").unbind(); 5676 $("#toolset").fadeTo('fast', 0.3).css('pointer-events', 'none'); 5677 }, 500); 5678 5679 $("#toolset").fadeTo('fast', 0.3).css('pointer-events', 'none'); 5680 5681 if(inspector.options.coreWindow.hasOwnProperty('Masonry')){ 5682 if(typeof inspector.options.coreWindow.doMason === "function"){ 5683 5684 var throttledMason = _.throttle(function(){ 5685 inspector.options.coreWindow.$(inspector.options.coreDocument).trigger("contentResize"); 5686 inspector.options.coreWindow.doMason(); 5687 }, 100); 5688 5689 inspector.inspectorCore.eventManager.subscribe('style_changed', function(){ 5690 throttledMason(); 5691 }); 5692 5693 throttledMason(); 5694 } 5695 } 5696 5697 if(inspector.options.coreWindow.hasOwnProperty('shiftPosition')){ 5698 if(typeof inspector.options.coreWindow.shiftPosition === "function"){ 5699 5700 var throttledShiftPosition = _.throttle(inspector.options.coreWindow.shiftPosition, 100); 5701 5702 inspector.inspectorCore.eventManager.subscribe('style_changed', function(){ 5703 throttledShiftPosition(); 5704 });
5705 5706 throttledShiftPosition(); 5707 } 5708 } 5709 5710 function addClickBehavior(){ 5711 5712 if(Cargo.ReplaceLoadingAnims === undefined){ 5713 Cargo.Core.ReplaceLoadingAnims.init(); 5714 } else { 5715 Cargo.ReplaceLoadingAnims(); 5716 } 5717 5718 if(inspector.options.coreWindow.Design !== undefined){ 5719 if(inspector.options.coreWindow.Design.hasOwnProperty('Resize')){ 5720 setTimeout(function(){ 5721 inspector.options.coreWindow.Design.Resize(); 5722 }, 20); 5723 } 5724 } 5725 5726 $('img').unbind(); 5727 5728 $(".slideshow_component").each(function() { 5729 // Remove and re-add everything 5730 $(this).after('<div class="slideshow_component" id="'+$(this).attr("id")+'">'+$(this).html()+'</div>').remove(); 5731 }); 5732 5733 $("#mainwrapper, .project_feed_full").removeAttr("onclick").unbind("click dblclick").die("dblclick").dblclick(function(e) { 5734 if( $(this).attr("id") == "mainwrapper") { 5735 $(inspector.options.coreDocument).trigger("closeProject"); 5736 5737 } else if( $(this).attr("id") == "search_term" ) { 5738 $(this).focus(); 5739 5740 }else if( $(this).attr("href") == "#" ) { 5741 // Don't allow # to be clicked 5742 return; 5743 5744 } else if(!$(this).attr("rel") && $(this).attr("href") ){ 5745 // Follow the link 5746 var win=inspector.options.coreWindow.open($(this).attr("href"), '_blank'); 5747 win.focus(); 5748 } 5749 5750 }); 5751 5752 $("a[onclick]").each(function(){ 5753 this.setAttribute('ondblclick', this.getAttribute('onclick')); 5754 this.removeAttribute('onclick'); 5755 }); 5756 5757 $("a[rel='history']").each(function(){ 5758 $(this).unbind("click").dblclick(function(e) { 5759 Cargo.History.Load( $(this).data("hash") ); 5760 e.preventDefault(); 5761 }); 5762 }); 5763 5764 $('a:not([rel], #splash)').removeAttr("onclick").unbind('click').die('dblclick').click(function(e){ 5765 e.preventDefault(); 5766 }).live("dblclick", function() { 5767 var href = this.getAttribute('href'); 5768 5769 if(href !== '#' && href !== '' && href.indexOf('javascript:') === -1){ 5770 5771 var cargoURL = (Cargo.hasOwnProperty('Helper') ? Cargo.Helper.GetUrl() : Cargo.Config.GetCookieUrl()), 5772 customDomain = inspector.options.coreWindow.location.hostname.search(/cargocollective\.com/i) === -1, 5773 sameDomain = (this.hostname.search(/cargocollective\.com/i) !== -1 ? this.pathname.split('/')[1] === cargoURL : this.hostname === inspector.options.coreWindow.location.hostname), 5774 subLocation = this.pathname.split('/')[(customDomain ? 1 : 2)], 5775 forbiddenSubLocation = (subLocation === undefined ? false : subLocation.search(/^(following|admin|images)$/i) !== -1); 5776 5777 //console.log(cargoURL, subLocation, sameDomain, forbiddenSubLocation); 5778 5779 if(sameDomain && !forbiddenSubLocation) { 5780 inspector.options.coreDocument.location.href = this.getAttribute('href'); 5781 } else { 5782 var newTab = inspector.options.coreWindow.open(href, '_blank'); 5783 newTab.focus(); 5784 } 5785 5786 } 5787 }); 5788 5789 $(".project_next a").unbind().die().click(function(e){ 5790 e.preventDefault() 5791 }).live("dblclick", function() { 5792 $(inspector.options.coreDocument).trigger("showNextProject"); 5793 }); 5794 5795 // Close project 5796 $(".project_index a").unbind().die().click(function(e){ 5797 e.preventDefault() 5798 }).live("dblclick", function() { 5799 $(inspector.options.coreDocument).trigger("closeProject"); 5800 }); 5801 5802 // Next page (pagination) 5803 $("a.next_page").unbind().die().click(function(e){ 5804 e.preventDefault() 5805 }).live("dblclick", function() { 5806 changePage(parseInt($("#current_page").val())+1); 5807 }); 5808 5809 // Prev page (pagination); 5810 $("a.prev_page").unbind().die().click(function(e){ 5811 e.preventDefault() 5812 }).live("dblclick", function() { 5813 changePage(parseInt($("#current_page").val())-1); 5814 });
5815 5816 if( typeof inspector.options.coreWindow.customNavigationDblClick == "function") { 5817 inspector.options.coreWindow.customNavigationDblClick(); 5818 } 5819 5820 } 5821 5822 $(inspector.options.coreDocument).bind("projectLoadComplete", function(e, pid) { 5823 addClickBehavior(); 5824 }); 5825 5826 $(inspector.options.coreDocument).bind("pageChangeComplete", function(e, newpage) { 5827 addClickBehavior(); 5828 }); 5829 5830 $(inspector.options.coreDocument).bind("paginationComplete", function(e) { 5831 addClickBehavior(); 5832 }); 5833 5834 $(inspector.options.coreDocument).bind("projectIndex", function(e, pid) { 5835 addClickBehavior(); 5836 }); 5837 5838 addClickBehavior(); 5839 } 5840 }); 5841 }); 5842 }); 5843 5844} 5845///////////////////////////////////////////////////////////////////////////////////////////////// 5846 5847 5848function toolsetToggle(which) { 5849 if (which == "on") { 5850 if ($("#toolset_admin a").length > 0 && $("#toolset_admin a").attr("rel").length > 0) { 5851 $("#toolset_admin a").attr("href",$("#toolset_admin a").attr("rel")).removeAttr("rel"); 5852 } 5853 } else if (which == "off") { 5854 if ($("#toolset_admin a").length > 0 && $("#toolset_admin a").attr("href").length > 0 && tool_over && mouse_down) { 5855 $("#toolset_admin a").attr("rel",$("#toolset_admin a").attr("href")).removeAttr("href"); 5856 mouse_down = false; 5857 showContextMenu(); 5858 } 5859 } 5860} 5861 5862///////////////////////////////////////////////////////////////////////////////////////////////// 5863/* !EVENT initToolset */ 5864$(document).bind("initToolset", function(e) { 5865 if($("#toolset").length > 0) { 5866 $("#toolset_admin").mousedown(function(e) { 5867 mouse_down = true; 5868 if(e.button == 2){ 5869 showContextMenu(); 5870 } else{ 5871 setTimeout("toolsetToggle('off')", 500); 5872 } 5873 5874 }).mouseup(function() { 5875 mouse_down = false; 5876 5877 }).mouseover(function() { 5878 tool_over = true; 5879 5880 }).mouseout(function() { 5881 tool_over = false; 5882 5883 }).click(function() { 5884 if ($("#toolset_admin a").attr("href").length > 0 && tool_over) { 5885 document.location.href = $("#toolset_admin a").attr("href"); 5886 hideContextMenu(); 5887 } 5888 return false; 5889 }); 5890 5891 $("#toolset_admin").bind("contextmenu", function(e) { 5892 return false; 5893 }); 5894 5895 $(document).click(function() { 5896 if(!mouse_down && !tool_over){ 5897 hideContextMenu(); 5898 } 5899 5900 }).mouseup(function(e) { 5901 if(e.button == 2){ 5902 mouse_down = false; 5903 } 5904 setTimeout("toolsetToggle('on')", 100); 5905 }); 5906 5907 $("#toolset_menu a").bind("click mouseup mouseover", function(e) { 5908 if(e.type == "mouseover") { 5909 toolsetToggle("on"); 5910 } else { 5911 // window.location.href = $(this).attr("href"); 5912 hideContextMenu(); 5913 } 5914 }); 5915 5916 $("#toolset_admin a").click(function(e) { 5917 if(e.ctrlKey) { 5918 showContextMenu(); 5919 return false; 5920 } 5921 }); 5922 5923 $(document).bind("projectIndex", function(e, pid){ 5924 hideContextMenu(); 5925 }); 5926 5927 $("#toolset_menu a:first").addClass("toolset_first"); 5928 $("#toolset_menu a:last").addClass("toolset_last"); 5929 5930 $("#toolset_network_leave").click(function() { 5931 if(confirm("Leave this network?")) return true; 5932 else return false; 5933 }); 5934 5935 $("#toolset_network_join").click(function() { 5936 if(confirm("Join this network?")) return true; 5937 else return false; 5938 }); 5939 } 5940}); 5941 5942///////////////////////////////////////////////////////////////////////////////////////////////// 5943/* !EVENT networkFilterMenu */ 5944$(document).bind("networkFilterMenu", function(e) { 5945 var networkFilterVisible = 0; 5946 5947 $(".network_filter_menu a:first").addClass("network_filter_menu_first"); 5948 $(".network_filter_menu a:last").addClass("network_filter_menu_last"); 5949 5950 $(".show_network_menu").click(function() { 5951 networkFilterVisible = 1; 5952 $(".network_filter_menu").show(); 5953 }); 5954 5955 $(document).click(function() { 5956 if(networkFilterVisible == 1){ 5957 networkFilterVisible = 0; 5958 } else { 5959 $(".network_filter_menu").hide(); 5960 } 5961 }); 5962}); 5963///////////////////////////////////////////////////////////////////////////////////////////////// 5964function hideNetworkFilterMenu() { 5965 var networkFilterVisible = 0; 5966 $(".network_filter_menu").hide(); 5967} 5968///////////////////////////////////////////////////////////////////////////////////////////////// 5969/* !EVENT projectLoadStart */ 5970$(document).bind("projectLoadStart", function(e) { 5971 /* Close toolset menu */ 5972 hideContextMenu(); 5973 hideNetworkFilterMenu(); 5974}); 5975///////////////////////////////////////////////////////////////////////////////////////////////// 5976/* !EVENT pageReady */ 5977$(document).bind("pageReady", function(e, history_type) { 5978 if(history_type == "follow") { 5979 Cargo.History.Init("following"); 5980 } else if(history_type != "none") { 5981 Cargo.History.Init(); 5982 } 5983 $(document).trigger("projectReady", ["first"]); 5984 $(document).trigger("loadSearch"); 5985 $(document).trigger("initToolset"); 5986 $(document).trigger("networkFilterMenu"); 5987 if(history_type != "follow") { 5988 $(document).trigger("keyboardShortcuts"); 5989 } 5990}); 5991///////////////////////////////////////////////////////////////////////////////////////////////// 5992/* !EVENT keyboardShortcuts */ 5993$(document).bind("keyboardShortcuts", function(e, which) { 5994 var me = Cargo.Location.GetBaseUrl(); 5995 5996 shortcut.add("H",function() { if($(window).scrollTop() > 50) { window.scrollTo(0, 50); doscroll(0,getScrollHeight(),0);}}
5996,{ 'type':'keydown', 'disable_in_input':true, 'keycode':72 }); 5997 if(which != "feed") { 5998 shortcut.add("J",function() { $(document).trigger("showNextProject"); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':74 }); 5999 shortcut.add("K",function() { $(document).trigger("showPrevProject"); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':75 }); 6000 shortcut.add("R",function() { $(document).trigger("showRandomProject"); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':82 }); 6001 shortcut.add("X",function() { $(document).trigger("closeProject"); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':88 }); 6002 shortcut.add("I",function() { $(document).trigger("closeProject"); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':73 }); 6003 } else { 6004 shortcut.add("J",function() { $(document).trigger("showNextFeedProject"); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':74 }); 6005 shortcut.add("K",function() { $(document).trigger("showPrevFeedProject"); },{ 'type':'keydown', 'disable_in_input':true, 'keycode'
6005:75 }); 6006 shortcut.add("I",function() { top.document.location.href=me+"/index" },{ 'type':'keydown', 'disable_in_input':true, 'keycode':73 }); 6007 } 6008 6009 6010 shortcut.add("Shift+F",function() { 6011 6012 if ( ! $("body").hasClass("rail_active") ) { 6013 Cargo.app.Rail.Events.trigger("show_rail_following"); 6014 } else { 6015 Cargo.app.Rail.Events.trigger("rail:hide"); 6016 } 6017 6018 },{ 6019 'type' :'keydown', 6020 'disable_in_input' :true, 6021 'keycode' :70 6022 }); 6023 6024 shortcut.add("Esc",function() { 6025 6026 // If the freshbox isn't displayed 6027 if ( ! $("#freshbox").length > 0 ) { 6028 Cargo.app.Rail.Events.trigger("rail:hide"); 6029 } 6030 6031 },{ 6032 'type' : 'keydown', 6033 'disable_in_input' : true, 6034 'keycode' : 27 6035 }); 6036 6037 shortcut.add("Shift+G",function() { top.document.location.href=me+"/images"; },{ 'type':'keydown', 'disable_in_input':true, 'keycode':71 }); 6038 6039 /* 6040 * Personal site shortcuts 6041 */ 6042 shortcut.add("Shift+A",function() { top.document.location.href=me+"/admin"; },{ 'type':'keydown', 'disable_in_input':true, 'keycode'
6042:65 }); 6043 shortcut.add("Shift+H",function() { top.document.location.href=me+"/admin/html"; },{ 'type':'keydown', 'disable_in_input':true, 'keycode':72 }); 6044 shortcut.add("Shift+C",function() { loadInspector3(); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':67 }); 6045 shortcut.add("Shift+D",function() { top.document.location.href=me+"/admin/designs"; },{ 'type':'keydown', 'disable_in_input':true, 'keycode':68 }); 6046 shortcut.add("Shift+X",function() { top.document.location.href=me; },{ 'type':'keydown', 'disable_in_input':true, 'keycode':88 }); 6047 shortcut.add("Shift+I",function() { loadInspector(); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':73 }); 6048 shortcut.add("Shift+E",function() { if($(".editlink a").length > 0) { top.document.location.href=$(".editlink a").attr('href'); } },{ 'type':'keydown', 'disable_in_input':true, 'keycode':69 }); 6049 //shortcut.add("Ctrl+Shift+I",function() { loadInspector3(); },{ 'type':'keydown', 'disable_in_input':true, 'keycode':73 }); 6050 6051}); 6052///////////////////////////////////////////////////////////////////////////////////////////////// 6053/* !EVENT projectReady */ 6054$(document).bind("projectReady", function(e, dataObj) { 6055 checkForSound(); 6056 Projects.Slideshow.CheckForSlideshow(); 6057 Projects.Video.CheckForVideo(); 6058 // Sniff for ajax links 6059 Cargo.Ajax.Init(); 6060 // Freshbox 6061 $(".entry").FreshBox(); 6062}); 6063///////////////////////////////////////////////////////////////////////////////////////////////// 6064/* !EVENT loadSearch */ 6065$(document).bind("loadSearch", function(e) { 6066 $("#search_form_results, #search_form, #rail_search_form").submit(function(te) { 6067 $(document).trigger("doSearch", [ { 6068 "form" : $(this).attr("id"), 6069 "term" : $('#search_term', this).val() 6070 } ]); 6071 return false; 6072 }).keypress(function(e) { 6073 if( e.which == 13 ) { // enter key 6074 $(document).trigger("doSearch", [ { 6075 "form" : $(this).attr("id"), 6076 "term" : $('#search_term', this).val() 6077 } ]); 6078 } 6079 }); 6080 $("#search_form #search_term, #rail_search_form #search_term").focus(function() { 6081 if($(this).val() == $(this).attr("rel")) $(this).val(""); 6082 }).blur(function() { 6083 if($(this).val() == "") $(this).val($(this).attr("rel")); 6084 }).blur(); 6085 6086 if($("#search_form_results").length > 0) { 6087 shortcut.add("I",function() { top.document.location.href=Cargo.Location.GetBaseUrl() }
6087,{ 'type':'keydown', 'disable_in_input':true, 'keycode':73 }); 6088 } 6089}); 6090///////////////////////////////////////////////////////////////////////////////////////////////// 6091/* !EVENT doSearch */ 6092$(document).bind("doSearch", function(e, data) { 6093 var search_term = data.term; 6094 search_term.replace(" ","-"); 6095 6096 if ($("#following_header").length != 0) { 6097 if(location.host.indexOf("cargocollective.com") >= 0) { 6098 var loc = document.location.pathname.split("/"); 6099 var url = (loc[0] != "") ? loc[0] : loc[1]; 6100 var me = "//"+location.host+"/"+url; 6101 } else { 6102 var me = "//"+location.host; 6103 } 6104 document.location.href=me+"/following/search/"+search_term; 6105 6106 } else { 6107 document.location.href=Cargo.Location.GetBaseUrl()+"/search/"+search_term; 6108 } 6109}); 6110///////////////////////////////////////////////////////////////////////////////////////////////// 6111function checkForSound() { 6112 // see if there is a sound && see if soundmanager is loaded 6113 // Check for firefox 6114 6115 if(Cargo.Config.isMobile() && $(".audio_component").length > 0){ 6116 loadSoundDependencies(); 6117 } 6118 6119 $(".audio_component .play_pause").live('click', function() { 6120 var force = false; 6121 if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){ //test for Firefox/x.x or Firefox x.x (ignoring remaining digits); 6122 var ffversion=new Number(RegExp.$1); // capture x.x portion and store as a number 6123 if(ffversion < 3.6) { force = true; } 6124 } //else if($("#template").val() == "SC") { force = true; } // test for SpaceCollective 6125 6126 $(document).trigger("audioPlayPause", [$(this).attr("rel"), $(this).attr("class").replace("play_pause ", "") ]); 6127 6128 if(($(".audio_component").length > 0 || force == true) && typeof soundManager == "undefined") { 6129 $(this).removeClass("play").addClass("pause"); 6130 6131 loadSoundDependencies(); 6132 6133 start_sound = $(this).parents(".audio_component").attr("id"); 6134 this_play = $(this); 6135 } 6136 }); 6137 6138 if(($(".audio_component").length > 0 ) && $("#DroidFont").length <= 0) { 6139 // Load the external font from the google api 6140 var droidfont=document.createElement('link'); 6141 droidfont.id='DroidFont'; 6142 droidfont.setAttribute('type','text/css'); 6143 droidfont.setAttribute('rel','stylesheet'); 6144 droidfont.setAttribute('href','https://fonts.googleapis.com/css?family=Droid+Sans+Mono'); 6145 6146 var hd=document.getElementsByTagName('head')[0]; 6147 hd.appendChild(droidfont); 6148 }; 6149 $(".progress").css("display","none"); 6150 initPlayerSize(); 6151} 6152 6153function loadSoundDependencies() { 6154 // check, check, doublecheck 6155 if(!soundDependenciesCalled && typeof soundManager == "undefined"){ 6156 $.getScript('/_js/jquery-ui-1.8.18.custom.min.js', function(){ 6157 }); 6158 6159 $.getScript('/_js/soundmanager/soundmanager2-nodebug-jsmin.js', function(){ 6160 }); 6161 soundDependenciesCalled = true; 6162 } 6163} 6164 6165///////////////////////////////////////////////////////////////////////////////////////////////// 6166function initPlayerSize() { 6167 var total_players = $(".audio_component").length; 6168 var zero_count = 0; 6169 6170 $(".audio_component").each(function(){ 6171 if($(this).width() > 0) { 6172 // Setup playhead/progress width 6173 //$('.Href', this).hide(); 6174 var position = $(".position", this); 6175 var playhead = $(".playhead", this); 6176 // This makes the player correctly sized based on the .Sound width property 6177 var soundWidth = $(this).width(); 6178 var soundBordersWidth = $(".border", this).outerWidth() - $(".border", this).width(); 6179 var controlsWidth = $(".controls", this).width(soundWidth - soundBordersWidth).width(); 6180 var volumeWidth = $(".volume", this).width(); 6181 var playpauseWidth = $(".play_pause", this).width(); 6182 var spacerWidths = $(".vertical_border", this).width() * 2; 6183 $(".border", this).width(soundWidth - soundBordersWidth); 6184 $(".info", this).width(controlsWidth - volumeWidth - playpauseWidth - spacerWidths); 6185 6186 var refWidth = $(".info", this).width(); 6187 position.width(refWidth); 6188 6189 playhead 6190 .css("width", refWidth+"px") 6191 .css("left", 0); 6192 6193 var progressBordersWidth = $(".progress", this).outerWidth() - $(".progress", this).width(); 6194 $(".progress") 6195 .css("width", (refWidth - progressBordersWidth) +"px") 6196 .css("left", 0); 6197 6198 if($("#home_content").length > 0) var prog_left = "35px";
6199 else var prog_left = "0px"; 6200 6201 $(".progress_clip") 6202 .css("position", "absolute") 6203 .css("overflow", "hidden") 6204 .css("width", refWidth+"px") 6205 .css("left", prog_left); 6206 6207 $(".position") 6208 .css("left", prog_left); 6209 6210 $(".playhead_container", this) 6211 .css("position", "relative") 6212 .css("width", (playhead.outerWidth() * 2) + "px") 6213 .css("left", ((playhead.outerWidth() * -1)) + "px"); 6214 6215 $(".progress_container", this) 6216 .css("position", "absolute") 6217 .css("z-index", "-1") 6218 .css("width", (playhead.outerWidth() * 2) + "px") 6219 .css("left", ((playhead.outerWidth() * -1)) + "px"); 6220 6221 } // end width check 6222 else { 6223 zero_count++; 6224 } 6225 }); 6226 6227 if( zero_count > 0 && zero_count == total_players) { 6228 // This content is not yet loaded because the container is faded out 6229 // Pause for 1 sec, then enable 6230 setTimeout("initPlayerSize()", 500); 6231 } 6232} 6233///////////////////////////////////////////////////////////////////////////////////////////////// 6234// Loop through all sounds on the page and unload them 6235function unloadAudio() { 6236 $(".audio_component").each(function() { 6237 if(typeof soundManager == "object") { 6238 soundManager.unload( $(this).attr("id") ); 6239 } 6240 }); 6241} 6242 6243///////////////////////////////////////////////////////////////////////////////////////////////// 6244// Deprecated 6245// Wrapper for Projects class, leaving for legacy 6246function openThisPr(pid) { 6247 Projects.AjaxLoadByPid( pid ); 6248 return false; 6249} 6250///////////////////////////////////////////////////////////////////////////////////////////////// 6251/* !EVENT closeProject */ 6252$(document).bind("closeProject", function(e){ 6253 Projects.CloseProject(); 6254}); 6255///////////////////////////////////////////////////////////////////////////////////////////////// 6256/* !EVENT initNextProject */ 6257$(document).bind("initNextProject", function(e){ 6258 $(".project_next a").die("click").live("click", function() { 6259 if(pr_list.length > 1) $(document).trigger("showNextProject"); 6260 return false; 6261 }); 6262}); 6263///////////////////////////////////////////////////////////////////////////////////////////////// 6264/* !EVENT showNextProject */ 6265$(document).bind("showNextProject", function(e){ 6266 Projects.ShowNextProject(); 6267}); 6268///////////////////////////////////////////////////////////////////////////////////////////////// 6269/* !EVENT showPrevProject */ 6270$(document).bind("showPrevProject", function(e){ 6271 Projects.ShowPreviousProject(); 6272}); 6273///////////////////////////////////////////////////////////////////////////////////////////////// 6274/* !EVENT showNextFeedProject */ 6275$(document).bind("showNextFeedProject", function(e){ 6276 Projects.ShowNextFeedProject(); 6277}); 6278///////////////////////////////////////////////////////////////////////////////////////////////// 6279/* !EVENT showPrevFeedProject */ 6280$(document).bind("showPrevFeedProject", function(e){ 6281 Projects.ShowPreviousFeedProject(); 6282}); 6283///////////////////////////////////////////////////////////////////////////////////////////////// 6284/* !EVENT showRandomProject */ 6285$(document).bind("showRandomProject", function(e){ 6286 Projects.ShowRandomProject(); 6287}); 6288///////////////////////////////////////////////////////////////////////////////////////////////// 6289function makeDetailLink(title) { 6290 var url = title 6291 .replace(/^\s+|\s+$/g, "") 6292 .replace(/[_|\s]+/g, "-") 6293 .replace(/[^a-zA-Z0-9-]+/g, "") 6294 .replace(/[-]+/g, "-") 6295 .replace(/^-+|-+$/g, "") 6296 ; 6297 return url; 6298} 6299 6300///////////////////////////////////////////////////////////////////////////////////////////////// 6301/* !EVENT slideshowTransitionFinish */ 6302$(document).bind("slideshowTransitionFinish", function(e, cur){ 6303 var caption = $(cur).attr("caption"); 6304 var caption_class = $(cur).parent().parent().parent().nextAll().attr("class"); 6305 6306 if(caption !== undefined){ 6307 $(cur).parent().parent().parent().siblings('.slideshow_caption').html(caption); 6308 } 6309 else{ 6310 $(cur).parent().parent().parent().siblings('.slideshow_caption').html(""); 6311 } 6312 6313}); 6314///////////////////////////////////////////////////////////////////////////////////////////////// 6315function getThumbFile(file_name) { 6316 var ext = file_name.substr(file_name.lastIndexOf('.')); 6317 var name = file_name.substring(0, file_name.lastIndexOf('.')); 6318 return name+"_t"+ext 6319} 6320///////////////////////////////////////////////////////////////////////////////////////////////// 6321function getScaleSize(og_w, og_h, h) { 6322 if(og_h > h) { 6323 var scale_percent = og_h / h; 6324 var out_w = Math.floor(og_w / scale_percent); 6325 var out_h = h; 6326 } else { 6327 var out_w = og_w; 6328 var out_h = og_h; 6329 } 6330 6331 return { "w" : out_w, "h" : out_h }; 6332} 6333///////////////////////////////////////////////////////////////////////////////////////////////// 6334// if no_hostory == false, unload the history 6335// This is just a wrapper for the new method, kept for legacy usage 6336function closeThisPr(no_history) { 6337 Projects.CloseProject( no_history ); 6338} 6339///////////////////////////////////////////////////////////////////////////////////////////////// 6340function changePage(newpage,limit) { 6341 $(document).trigger("pageChange", [newpage]); 6342 6343 var cur = document.getElementById('current_page').value; 6344 var total_pages = document.getElementById('total_pages').value; 6345 var current_page = document.getElementById('page_'+cur); 6346 var current_nav = document.getElementById('nav_page_'+cur); 6347 var new_page = document.getElementById('page_'+newpage); 6348 var new_nav = document.getElementById('nav_page_'+newpage); 6349 var pagination = document.getElementById('pagination'); 6350 var pid = $('#current_open').val(); 6351 var design = $('#design').val(); 6352 var template = $('#template').val(); 6353 6354 6355 if(document.getElementById('pr_contain_item_'+cur)) { 6356 document.getElementById('pr_contain_item_'+cur).className = ""; 6357 } 6358 6359 // reset nav status 6360 Projects.Helper.RemoveNavHighlight(); 6361 6362 // Remove the thumb highlight 6363 Projects.Helper.RemoveThumbHighlight(); 6364 6365 6366 // dump the old nav 6367 if(current_nav) current_nav.style.display = "none"; 6368 6369 // show the new nav 6370 if(new_nav) new_nav.style.display = "block"; 6371 6372 // dump prev page thumbs 6373 if(current_page) current_page.style.display = "none"; 6374 6375 // change pagination 6376 var pagout = ""; 6377 if(newpage > 1) { 6378 if(design.indexOf("kennedy") >= 0) pagout += "← "; 6379 pagout += "<a href=\"javascript:void(0)\" onclick=\"changePage("+(parseInt(newpage)-1)+","+limit+", true)\" "; 6380 pagout += "class=\"prev_page\">Prev page</a>"; 6381 } 6382 6383 if(newpage > 1 && newpage < total_pages) { 6384 if(design.indexOf("kennedy") >= 0) { 6385 pagout += " <span>("+newpage+" of "+total_pages+")</span> "; 6386 6387 } else if(design.indexOf("amsterdam") < 0 && design.indexOf("kertesz") < 0 && design.indexOf("hegel") < 0) { 6388 pagout += "<span> / </span>"; 6389 } 6390 } 6391 6392 if(design.indexOf("amsterdam") >= 0 || design.indexOf("kertesz") >= 0 || design.indexOf("hegel") >= 0) { 6393 pagout += " <span>"+newpage+" of "+total_pages+"</span> "; 6394 } 6395 6396 if(newpage < total_pages) { 6397 pagout += "<a href=\"javascript:void(0)\" onclick=\"changePage("+(parseInt(newpage)+1)+","+limit+", true)\" "; 6398 pagout += "class=\"next_page\">Next page</a>"; 6399 if(design.indexOf("kennedy") >= 0) pagout += " →"; 6400 6401 } 6402 6403 if(design.indexOf("amsterdam") < 0 && design.indexOf("kertesz") < 0 && design.indexOf("hegel") < 0) { 6404 if(design.indexOf("kennedy") >= 0 && newpage > 1) { // do nothing 6405 } else { 6406 pagout += " <span>("+newpage+" of "+total_pages+")</span>"; 6407 } 6408 } 6409 6410 if($(".pagination").length > 0) $(".pagination").each(function() { $(this).html(pagout); }); 6411 6412 6413 // show next page thumbs 6414 if(new_page) { 6415 showNextPageThumbs( newpage ); 6416 } 6417 6418 if(document.getElementById('menu_'+pid)) { 6419 $("#menu_"+pid).addClass("nav_active"); 6420 } 6421 6422 // set new page values 6423 document.getElementById('current_page').value = newpage; 6424 curspot = cur < newpage ? (cur*limit)-1 : ((newpage-1)*limit)-1; 6425 document.getElementById('this_spot').value = curspot; 6426 6427 if(document.getElementById('items') && template.indexOf("network") < 0 && design.indexOf("amsterdam") < 0 && design.indexOf("kertesz") < 0 && design.indexOf("hegel") < 0) shiftPosition(false); 6428 6429 window.scrollTo(0,0); 6430
6431 //changeHorizNav(newpage); 6432 $(document).trigger("pageChangeComplete", [newpage]); 6433 6434} 6435 6436/** 6437 * Shows the next page of thumbs 6438 * Unhides the div, swaps the content 6439 */ 6440function showNextPageThumbs( new_page ) { 6441 $("#page_"+new_page).show(); 6442 6443 $(".project_thumb, .project_feed_thumb").each(function() { 6444 var pid = $(this).attr("name"); 6445 var thumbContainer = $("#cardthumb_"+pid); 6446 if(thumbContainer.length > 0 && thumbContainer.attr("name") != "") { 6447 //thumbContainer.innerHTML = "<img src=\""+thumbContainer.getAttribute("name")+"\" border=\"0\" />"; 6448 thisW = thumbContainer.attr("width") ? 'width="'+thumbContainer.attr("width")+'"' : ""; 6449 thisH = thumbContainer.attr("height") ? 'height="'+thumbContainer.attr("height")+'"' : ""; 6450 thisImg = thumbContainer.attr("name"); 6451 thumbContainer.html("<img src=\""+thisImg+"\" border=\"0\" "+thisW+" "+thisH+" />"); 6452 thumbContainer.attr("name",""); 6453 } 6454 }); 6455} 6456///////////////////////////////////////////////////////////////////////////////////////////////// 6457function changeHorizNav(newpage) { 6458 // move pages, pagination and following if nav is horiz 6459 if($(".nav_container").hasClass("horizontal")) { 6460 if($("#pagination").length > 0) $("#nav_page_"+newpage).append($("#pagination")); 6461 if($(".nav_follow").length > 0) $("#nav_page_"+newpage).append($(".nav_follow")); 6462 if(($(".page_link").length > 0 || $(".link_link").length > 0) && $("#sticky_page").val() != "none") { 6463 if($("#sticky_page").val() == "top") $("#nav_page_"+newpage).prepend($(".page_link")).prepend($(".link_link")); 6464 else { 6465 $("#nav_page_"+newpage).append($(".page_link")).append($(".link_link")); 6466 if($("#pagination").length > 0) $("#nav_page_"+newpage).append($("#pagination")); 6467 if($(".nav_follow").length > 0) $("#nav_page_"+newpage).append($(".nav_follow")); 6468 } 6469 } 6470 } 6471} 6472///////////////////////////////////////////////////////////////////////////////////////////////// 6473function FollowingSniff() { 6474 if($("#following_header").length > 0 || $(".follow_container.home").length > 0) { 6475 if($(".follow_container.home").length > 0) { 6476 $.loadFiles("/_js/cargo.following.package.js").done(function() { 6477 Cargo.Following.PreparePagination(); 6478 }); 6479 6480 } else { 6481 //Cargo.History.InitFollowlist(); 6482 Cargo.Following.PreparePagination(); 6483 } 6484 $(".recent_following_thumb:odd").addClass("even"); 6485 } 6486} 6487///////////////////////////////////////////////////////////////////////////////////////////////// 6488 6489Cargo.Follow = { 6490 6491 Data : { 6492 'el' : false 6493 }, 6494 6495 /** 6496 * bind all follow/unfollow links 6497 */ 6498 Init : function() { 6499 6500 $("a[rel='follow']").die('click').live('click', function() { 6501 Cargo.Follow.ShowFollowWindow($(this)); 6502 return false; 6503 }); 6504 6505 $(".follow_popup_ok").die('click').live('click', function() { 6506 Cargo.Follow.DoFollow($(this).attr('data-my_uid'), $(this).attr('data-my_cv'), $(this).attr('data-their_uid'), $(this).attr('data-type')); 6507 return false; 6508 }); 6509 6510 $(".follow_popup_cancel").die('click').live('click', function() { 6511 Cargo.Follow.Hide(); 6512 return false; 6513 }); 6514 6515 }, 6516 6517 Show : function() { 6518 Cargo.ReplaceLoadingAnims(); 6519 6520 $("#follow_popup").show(); 6521 6522 if(typeof Cargo.Home == "object") { 6523 Cargo.Home.Personal.RemoveEnterShortcut(); 6524 } 6525 6526 // Key bindings 6527 shortcut.add("return",function() { 6528 $("a.follow_popup_ok").click(); 6529 },{ 'type':'keydown', 'disable_in_input':true, 'propagate': false, 'keycode':13 }); 6530 6531 shortcut.add("esc",function() { 6532 $("a.follow_popup_cancel").click(); 6533 },{ 'type':'keydown', 'disable_in_input':true, 'propagate': false, 'keycode':27 }); 6534 }, 6535 6536 Hide : function() { 6537 6538 // Hide the element 6539 $("#follow_popup").hide(); 6540 6541 // Remove the keys 6542 shortcut.remove("return"); 6543 6544 if(typeof Cargo.Home == "object") { 6545 Cargo.Home.Personal.AddEnterShortcut(); 6546 } 6547 6548 }, 6549 6550 6551 ShowFollowWindow : function(el) { 6552 Cargo.Follow.Show(); 6553 6554 $("#follow_popup_note").html(ucFirst($(el).attr("data-type"))+" "+$(el).attr('data-displayurl')+"?"); 6555 $(".follow_popup_ok").attr({ 6556 'data-their_uid': $(el).attr("data-their_uid"), 6557 'data-my_uid' : $(el).attr("data-my_uid"), 6558 'data-my_cv' : $(el).attr("data-my_cv"), 6559 'data-type' : $(el).attr("data-type") 6560 }); 6561 Cargo.Follow.Data.el = el; 6562 6563 }, 6564 6565 DoFollow : function(my_uid, my_cv, their_uid, type) { 6566 $("#following_loadspin").show(); 6567 $.post( 6568 Cargo.Dispatcher.GetUrl("user/doFollow"), 6569 { my_uid:my_uid, my_cv:my_cv, their_uid:their_uid, type:type }, 6570 Cargo.Follow.FollowResult, 6571 "json" 6572 ); 6573 6574 }, 6575 6576 FollowResult : function(dataObj) { 6577 $("#following_loadspin").hide(); 6578 6579 if(typeof Cargo.Home == "object") { 6580 Cargo.Home.Personal.hideProjectAfterUnfollow(Cargo.Follow.Data.el); 6581 6582 } else if(Cargo.Follow.Data.el.attr("id")) { 6583 $("#follow_links").html(dataObj.html); 6584 $("#rail_follow").html(dataObj.html); 6585 6586 // update "template" 6587 if(Cargo.app.Rail.view.following) { 6588 Cargo.app.Rail.Templates.following_tpl = Cargo.app.Rail.view.following.el.innerHTML; 6589 } 6590 6591 } else { 6592 Cargo.Follow.Data.el.replaceWith(dataObj.jdata.tag_html); 6593 } 6594 6595 Cargo.Follow.Hide(); 6596 } 6597 6598
6599 6600} 6601 6602///////////////////////////////////////////////////////////////////////////////////////////////// 6603function changeFollowPage(newpage) { 6604 if(newpage) { 6605 if(newpage.indexOf("page") >= 0) var ishome = false; 6606 else var ishome = true; 6607 if(!ishome) newpage=parseInt(newpage.replace("page","")); 6608 var cur = document.getElementById('current_page').value; 6609 var limit = parseInt(document.getElementById('total_pages').value); 6610 var current_page = document.getElementById('page_'+cur); 6611 var new_page = document.getElementById('page_'+newpage); 6612 var pagination = document.getElementById('pagination'); 6613 6614 // change pagination 6615 var pagout = ""; 6616 if(!ishome) { 6617 var prevlink = "#page"+(parseInt(newpage)-1); 6618 var nextlink = "#page"+(parseInt(newpage)+1); 6619 } else { 6620 var prevlink = "javascript:void(0)\" onclick=\"changeFollowPage('"+(parseInt(newpage)-1)+"')"; 6621 var nextlink = "javascript:void(0)\" onclick=\"changeFollowPage('"+(parseInt(newpage)+1)+"')"; 6622 } 6623 if(newpage > 1) pagout += "<a href=\""+prevlink+"\" rel=\"history\">Prev page</a>"; 6624 if(newpage > 1 && newpage < limit) pagout += "<span> / </span>"; 6625 if(newpage < limit) pagout += "<a href=\""+nextlink+"\" rel=\"history\">Next page</a>"; 6626 pagout += " <span>("+newpage+" of "+limit+")</span>"; 6627 6628 if($(".follow_pagination").length > 0) $(".follow_pagination").each(function() { $(this).html(pagout); }); 6629 $("#page_"+newpage+" img").each(function(){ $(this).attr("src",$(this).attr("name")); }); 6630 6631 // show next page thumbs 6632 if(new_page) { 6633 new_page.style.display = "block"; 6634 current_page.style.display = "none"; 6635 } 6636 6637 // set new page values 6638 document.getElementById('current_page').value = newpage; 6639 6640 window.scrollTo(0,0); 6641 } 6642 6643} 6644 6645///////////////////////////////////////////////////////////////////////////////////////////////// 6646 6647///////////////////////////////////////////////////////////////////////////////////////////////// 6648 if(!Array.indexOf){ 6649 Array.prototype.indexOf = function(obj){ 6650 for(var i=0; i<this.length; i++){ 6651 if(this[i]==obj){ 6652 return i; 6653 } 6654 } 6655 return -1; 6656 } 6657 } 6658///////////////////////////////////////////////////////////////////////////////////////////////// 6659function feedAnchor(anchorLink) { 6660 url = "item_"+anchorLink; 6661 setTimeout('scrollto(url)',200); 6662} 6663///////////////////////////////////////////////////////////////////////////////////////////////// 6664function anchorTo(which,amount_above,do_move) { 6665 if(document.getElementById(which)) { 6666 if(do_move) { 6667 $.scrollTo("#"+which, 0, {offset: {top:-amount_above-50}}); 6668 $.scrollTo("#"+which, 300, {offset: {top:-amount_above}}); 6669 } else { 6670 $.scrollTo("#"+which, 0, {offset: {top:-amount_above}}); 6671 } 6672 } 6673} 6674///////////////////////////////////////////////////////////////////////////////////////////////// 6675 6676function scrollto(obj) { 6677 var t=0; 6678 var pad = 35; 6679 var strTop = document.getElementById(obj).style.top; 6680 if(strTop=="") doscroll(0,getScrollHeight(),0); 6681 else { 6682 pxPos = strTop.indexOf("px"); 6683 targetYPos = parseInt(strTop.substring(0, pxPos)) - pad; 6684 var y = getScrollHeight(); //document[getDocElName()].scrollTop; 6685 clearTimeout(timer); 6686 6687 //alert(getScrollHeight()+' / '+targetYPos+' / '+y); 6688 doscroll(targetYPos,y,t); 6689 } 6690} 6691///////////////////////////////////////////////////////////////////////////////////////////////// 6692function doscroll(targetYPos,y,t) { 6693 var speed = 6; 6694 var diff = targetYPos - y; 6695 var steps = diff/(speed*speed); 6696 t += (t+steps)/diff; 6697 newY = (t==1) ? y+diff : y + (diff * (-Math.pow(2, -20 * t/1) + 1)); 6698 if(t) window.scrollTo(0, newY); 6699 6700 if(t >= 1 || lastT == t || !t) clearTimeout(timer); 6701 else timer=setTimeout("doscroll("+targetYPos+","+y+","+t+")",1); 6702 6703 lastT = t; 6704 6705 return false; 6706} 6707///////////////////////////////////////////////////////////////////////////////////////////////// 6708function getDocElName(){ 6709 if(document.compatMode && document.compatMode == "CSS1Compat") return "documentElement"; 6710 else return "body"; 6711} 6712///////////////////////////////////////////////////////////////////////////////////////////////// 6713function handle(delta) { 6714 clearTimeout(timer); 6715} 6716///////////////////////////////////////////////////////////////////////////////////////////////// 6717function wheel(event){ 6718 var delta = 0; 6719 if (!event) event = window.event; 6720 if (event.wheelDelta) { 6721 delta = event.wheelDelta/120; 6722 if (window.opera) delta = -delta; 6723 } else if (event.detail) { 6724 delta = -event.detail/3; 6725 } 6726 if (delta) handle(delta); 6727} 6728///////////////////////////////////////////////////////////////////////////////////////////////// 6729/* Initialization code. */ 6730if (window.addEventListener) 6731 window.addEventListener('DOMMouseScroll', wheel, false); 6732window.onmousewheel = document.onmousewheel = wheel; 6733 6734 6735///////////////////////////////////////////////////////////////////////////////////////////////// 6736function di(id,name){
6737 if (document.images) document.images[id].src=eval(name+".src"); 6738} 6739///////////////////////////////////////////////////////////////////////////////////////////////// 6740function getadmin(url) { 6741 document.location.href=url+"/admin"; 6742} 6743///////////////////////////////////////////////////////////////////////////////////////////////// 6744function closeadmin(url) { 6745 parent.document.location="/"+url; 6746} 6747///////////////////////////////////////////////////////////////////////////////////////////////// 6748function cargoToolset(doshow) { 6749 if(doshow) { 6750 $("#toolset").css("display","block"); 6751 //$("#toolsetframe").remove(); // breaks safari 6752 $(document).trigger("showToolset"); 6753 } 6754} 6755///////////////////////////////////////////////////////////////////////////////////////////////// 6756function detectBrowser() { 6757 var browser=navigator.appName; 6758 var b_version=navigator.appVersion; 6759 var version=parseFloat(b_version); 6760 return browser; 6761} 6762///////////////////////////////////////////////////////////////////////////////////////////////// 6763function getScrollHeight() { 6764 var y; 6765 if (self.pageYOffset) { 6766 y = self.pageYOffset; 6767 } else if (document.documentElement && document.documentElement.scrollTop) { 6768 y = document.documentElement.scrollTop; 6769 } else if (document.body) { 6770 y = document.body.scrollTop; 6771 } 6772 return parseInt(y); 6773} 6774///////////////////////////////////////////////////////////////////////////////////////////////// 6775function getScrollWidth() { 6776 var x; 6777 if (self.pageXOffset) { 6778 x = self.pageXOffset; 6779 } else if (document.documentElement && document.documentElement.scrollLeft) { 6780 x = document.documentElement.scrollLeft; 6781 } else if (document.body) { 6782 x = document.body.scrollLeft; 6783 } 6784 return parseInt(x); 6785} 6786///////////////////////////////////////////////////////////////////////////////////////////////// 6787function truncateText(trunc,len, dir) { 6788 if (trunc.length > len) { 6789 if(dir == "normal") trunc = trunc.substring(0, len)+'...'; 6790 else if(dir == "center") trunc = trunc.substring(0, (len/2))+'âö'+trunc.substring(trunc.length, trunc.length-(len/2)); 6791 else trunc = '...'+trunc.substring(trunc.length, trunc.length-len); 6792 } 6793 return trunc; 6794} 6795///////////////////////////////////////////////////////////////////////////////////////////////// 6796function array_search(needle, haystack) { 6797 var key = ''; 6798 for (key in haystack) { 6799 if (parseInt(haystack[key]) === parseInt(needle)) { 6800 return key; 6801 } 6802 } 6803 return false; 6804} 6805///////////////////////////////////////////////////////////////////////////////////////////////// 6806function arfind(ar,value) { 6807 for(i=0;i<ar.length;i++) { 6808 if(ar[i] == value) { 6809 spot = i; 6810 break; 6811 } 6812 } 6813 return spot; 6814} 6815///////////////////////////////////////////////////////////////////////////////////////////////// 6816// Facebook comments 6817// NOTE: There is a duplicate of this function in /_jsapps/api/_cargo/functions.js 6818 function fbComments(variant, fbwidth, fbnum){ 6819 addScript("http://connect.facebook.net/en_US/all.js#xfbml=1"); 6820 var f_url = 6821 design = 6822 template = 6823 padding = ""; 6824 var margin = "30px 0 30px 0"; 6825 var element= ".project_bottom"; 6826 var colorscheme = (variant == "dark") ? "dark" : "light"; 6827 6828 fbwidth = (!fbwidth) ? 560 : fbwidth; 6829 fbnum = (!fbnum) ? 15 : fbnum; 6830 6831 $(document).ready(function() { 6832 // Define the template and design 6833 6834 design = $("input#design").val(); 6835 template = $("input#template").val(); 6836 6837 // If it's feed go for it 6838 if( Cargo.Config.GetCurrentPageType() == "project" && 6839 ($("#detailbottom").length > 0 || $("#content_container.permalink_page").length > 0 || $("#items_container.permapage").length > 0) 6840 ) { 6841 6842 // Set the current page URL 6843 // f_url = encodeURIComponent(window.location.href.replace("#","/")); 6844 f_url = window.location.href.replace("#","/"); 6845 6846 if(design == "ozfeed" || design == "ozfeed-alt") { 6847 element = ".project_content .clear:last"; 6848 } else { 6849 element = ".project_footer"; 6850 } 6851 6852 // Create the element 6853 $(element).after('<div class="fb_comments" style="width: '+fbwidth+'; margin: '+margin+'; padding: '+padding+';"><fb:comments href="'+f_url+'" width="'+fbwidth+'" num_posts="'+fbnum+'" colorscheme="'+colorscheme+'"></fb:comments></div>'); 6854 } 6855 6856 // Also add a comment count on Feed 6857 if(template == "feed") { 6858 if($("#detailbottom").length <= 0) { 6859 fbCommentCount(); 6860 $(document).bind("paginationComplete", function(e, dataObj) { 6861 fbCommentCount(); 6862 });
6863 } 6864 } 6865 }); 6866 6867 // For everything but Feed / SC 6868 $(document).bind("projectLoadComplete", function(e, pid){ 6869 fbCommentLoad(pid, variant, fbwidth, fbnum); 6870 }); 6871 6872 6873 // For everything but Feed / non-SC 6874 $(document).bind("SCprojectLoadComplete", function(e, pid){ 6875 // fbCommentLoad(pid, variant, fbwidth, fbnum); 6876 }); 6877 6878 } 6879///////////////////////////////////////////////////////////////////////////////////////////////// 6880// Facebook comment count for Feed 6881 function fbCommentCount() { 6882 $(".project_footer:not(:has(>iframe))").each(function(){ 6883 var pid = Cargo.SocialMedia.GetNearestPid( $(this) ), 6884 direct_link = Cargo.Location.GetDirectLink( pid ); 6885 6886 $(this).append('<br/><iframe class="fb_comments_iframe" src="http://www.facebook.com/plugins/comments.php?href=+'+direct_link+'&permalink=1" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:130px; height:16px; margin-top: 10px;" allowTransparency="true"></iframe> '); 6887 }); 6888 } 6889///////////////////////////////////////////////////////////////////////////////////////////////// 6890// Load FaceBook comments for non-feed designs 6891 function fbCommentLoad(pid, variant, fbwidth, fbnum) { 6892 var margin = "30px 0 30px 0"; 6893 var timeout = 500; 6894 var template = $("input#template").val(); 6895 var design = $("input#design").val(); 6896 var domain = $("input#is_domain").val(); 6897 var colorscheme = (variant == "dark") ? "dark" : "light"; 6898 var position = "before"; 6899 var element= ".project_bottom"; 6900 6901 if( !pid ) { 6902 // get the open project 6903 if( $("#current_open").length > 0 && $("#current_open").val() != "none") { 6904 pid = $("#current_open").val(); 6905 6906 } else { 6907 return false; 6908 } 6909 } 6910 6911 // If you're on a project 6912 if(array_search(pid, pr_list)){ 6913 // Load the Facebook comments script again, for whatever reason(s) 6914 $.getScript("http://connect.facebook.net/en_US/all.js#xfbml=1", function() { 6915 f_url = Cargo.Location.GetDirectLink( pid ); 6916 6917 // FB events 6918 FB.Event.subscribe('xfbml.render', function(response){ 6919 if(typeof reinitializeScrolling == 'function') { 6920 setTimeout("reinitializeScrolling(false,'main')",timeout); 6921 6922 } else if(typeof shiftPosition == 'function') { 6923 setTimeout("shiftPosition()",timeout); 6924 } 6925 6926 });
6927 FB.Event.subscribe('comment.create', function(response){ 6928 if(typeof reinitializeScrolling == 'function') { 6929 setTimeout("reinitializeScroll'ing(false,'main')",timeout); 6930 6931 } else if(typeof shiftPosition == 'function') { 6932 setTimeout("shiftPosition()",timeout); 6933 } 6934 }); 6935 FB.Event.subscribe('comment.remove', function(response){ 6936 if(typeof reinitializeScrolling == 'function') { 6937 setTimeout("reinitializeScrolling(false,'main')",timeout); 6938 6939 } else if(typeof shiftPosition == 'function') { 6940 setTimeout("shiftPosition()",timeout); 6941 } 6942 }); 6943 6944 // Design specific interventions 6945 if(template == "limelight") { 6946 margin = "0 0 30px 0"; 6947 6948 } else if(design == "kant") { 6949 margin = "30px 30px 2px 30px"; 6950 padding = "0 0 30px 0"; 6951 6952 } else if(design == "hegel") { 6953 margin = "30px auto 30px auto"; 6954 6955 } else if(design == "nietzsche") { 6956 margin = "-30px 0 50px 0"; 6957 6958 } else if(design == "kennedy" || design == "kennedy-alt") { 6959 element = ".project_footer"; 6960 position = "after"; 6961 6962 } else if(design == "landsat") { 6963 element = ".project_text"; 6964 position = "inside"; 6965 fbwidth = 480; 6966 } 6967 6968 6969 if(position == "after") { 6970 $(element).after('<div class="fb_comments" style="width: '+fbwidth+'; margin: '+margin+'; padding: '+padding+';"><fb:comments href="'+f_url+'" width="'+fbwidth+'" num_posts="'+fbnum+'" colorscheme="'+colorscheme+'"></fb:comments></div>'); 6971 } else if(position == "inside") { 6972 $(element).append('<div class="fb_comments" style="width: '+fbwidth+'; margin: '+margin+'; padding: '+padding+';"><fb:comments href="'+f_url+'" width="'+fbwidth+'" num_posts="'+fbnum+'" colorscheme="'+colorscheme+'"></fb:comments></div>'); 6973 } else { 6974 $(element).before('<div class="fb_comments" style="width: '+fbwidth+'; margin: '+margin+'; padding: '+padding+';"><fb:comments href="'+f_url+'" width="'+fbwidth+'" num_posts="'+fbnum+'" colorscheme="'+colorscheme+'"></fb:comments></div>'); 6975 } 6976 6977 // Force FB to re-parse the comments 6978 FB.XFBML.parse(); 6979 6980 }); 6981 } 6982 } 6983///////////////////////////////////////////////////////////////////////////////////////////////// 6984function addScript(script_file, id) { 6985 var scrpt=document.createElement('script'); 6986 scrpt.setAttribute('type','text/javascript'); 6987 scrpt.setAttribute('src',script_file); 6988 if( id ) scrpt.setAttribute('id',id); 6989 var hd=document.getElementsByTagName('head')[0]; 6990 hd.appendChild(scrpt); 6991} 6992///////////////////////////////////////////////////////////////////////////////////////////////// 6993function addCSS(css_file) { 6994 var scrpt=document.createElement('link'); 6995 scrpt.setAttribute('type','text/css'); 6996 scrpt.setAttribute('rel','stylesheet'); 6997 scrpt.setAttribute('href',css_file); 6998 var hd=document.getElementsByTagName('head')[0]; 6999 hd.appendChild(scrpt); 7000} 7001 7002/** 7003 * This inserts a new element into the dom 7004 * Used by the admin frame, so that we can use jQuery 7005 */ 7006function addElementIntoDOM( existing_id, new_html, which) { 7007 if(which == "before") { 7008 $("#"+existing_id).before( new_html ); 7009 } else { 7010 $("#"+existing_id).after( new_html ); 7011 } 7012} 7013/** 7014 * Deletes an element from the dom 7015 * Used by the admin frame for live preview 7016 */ 7017function deleteElementFromDOM( element_id ) { 7018 // Check if there is a br after, if so remove that too 7019 if($("#"+element_id).next().get(0).tagName.toLowerCase() == "br") { 7020 $("#"+element_id).next().remove(); 7021 } 7022 7023 $("#"+element_id).remove(); 7024} 7025 7026/** 7027 * Returns a jquery object based on the input 7028 * Used by the admin frame for live preview 7029 * Tries for class, then id, then tag 7030 * Usefull because we can return a jQuery element 7031 * to a different frame 7032 */ 7033function getElementByInput( which ) { 7034 if( $( "."+which ).length > 0 ) { 7035 return $( "."+which ); 7036 7037 } else if( $( "#"+which ).length > 0 ) { 7038 return $( "#"+which ); 7039 7040 } else if( $( which ).length > 0 ) { 7041 return $( which ); 7042 7043 } 7044} 7045 7046///////////////////////////////////////////////////////////////////////////////////////////////// 7047function stripslashes( str ) { 7048 return (str+'').replace(/\0/g, '0').replace(/\\([\\'"])/g, '$1'); 7049} 7050///////////////////////////////////////////////////////////////////////////////////////////////// 7051function addslashes (str) { 7052 return (str + '').replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0'); 7053} 7054///////////////////////////////////////////////////////////////////////////////////////////////// 7055function stripTrailingSlash( str ) { 7056 if(str && str.substr(-1) == '/' && str.length > 1) { 7057 return str.substr(0, str.length - 1); 7058 } 7059 return str; 7060} 7061///////////////////////////////////////////////////////////////////////////////////////////////// 7062function stripLeadingSlash( str ) { 7063 if(str && str.charAt(0) == '/' && str.length > 1) { 7064 return str.substr(1, str.length); 7065 } 7066 return str; 7067} 7068///////////////////////////////////////////////////////////////////////////////////////////////// 7069function in_array (needle, haystack, argStrict) { 7070 var key = '',
7071 strict = !! argStrict; 7072 7073 if (strict) { 7074 for (key in haystack) { 7075 if (haystack[key] === needle) { 7076 return true; 7077 } 7078 } 7079 } else { 7080 for (key in haystack) { 7081 if (haystack[key] == needle) { 7082 return true; 7083 } 7084 } 7085 } 7086 7087 return false; 7088} 7089///////////////////////////////////////////////////////////////////////////////////////////////// 7090function readCookie(name) { 7091 var nameEQ = name + "="; 7092 var ca = document.cookie.split(';'); 7093 for(var i=0;i < ca.length;i++) { 7094 var c = ca[i]; 7095 while (c.charAt(0)==' ') c = c.substring(1,c.length); 7096 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); 7097 } 7098 return null; 7099} 7100///////////////////////////////////////////////////////////////////////////////////////////////// 7101function setCookie(c_name,value,exdays) { 7102 var exdate=new Date(); 7103 exdate.setDate(exdate.getDate() + exdays); 7104 var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString()); 7105 document.cookie=c_name + "=" + c_value; 7106} 7107///////////////////////////////////////////////////////////////////////////////////////////////// 7108function testIE() { 7109 return Cargo.Config.isIE(); 7110} 7111///////////////////////////////////////////////////////////////////////////////////////////////// 7112function ucFirst(str) { 7113 return (str) ? str.charAt(0).toUpperCase() + str.slice(1) : str; 7114} 7115///////////////////////////////////////////////////////////////////////////////////////////////// 7116function getMacVersion() { 7117 var MacVersion = 0; 7118 if(/Mac OS X\s(\d+\_\d+)|(\d+\.\d+)/.test(navigator.userAgent)) { 7119 var MacInfo = /Mac OS X\s(\d+\.\d+)|(\d+\_\d+)/.exec(navigator.userAgent) 7120 if(MacInfo) { 7121 if(MacInfo[0].length > 5) { 7122 MacVersion = MacInfo[1]; 7123 } else { 7124 MacVersion = MacInfo[0].replace("_","."); 7125 } 7126 } 7127 }; 7128 7129 return MacVersion; 7130} 7131///////////////////////////////////////////////////////////////////////////////////////////////// 7132 7133var HiRes = window.HiRes || {}; 7134 7135HiRes.active = false; 7136 7137HiRes.Queue = { 7138 STATE_LOADING: 0, 7139 STATE_COMPLETE: 1, 7140 STATE_ERROR: -1, 7141 ID: 'hi-res-queue', 7142 FILE_EXTENSION: /(?:\.([^.]+))?$/, 7143 FILE_NAME: /(?:\/([^\/]+))?$/, 7144 element: null, 7145 7146 init: function() { 7147 $('body').append('<div id="' + this.ID + '" style="display: none;" />'); 7148 this.element = $('#' + this.ID); 7149 }, 7150 7151 search: function() { 7152 if ( $('img[data-hi-res]').length == 0 || window.devicePixelRatio < 1.5) { 7153 return; 7154 } 7155 7156 // $('[data-mid], div.thumb_image img').map(function() { 7157 $('[data-hi-res]').map(function() { 7158 // @TODO Determine means to ignore slideshow thumbnails? 7159 if (this.nodeName === 'IMG') { 7160 HiRes.Queue.push(this); 7161 } 7162 }); 7163 }, 7164 7165 push: function(img) { 7166 //var img_src = img.getAttribute('data-high-res'); 7167 var hi_res_src = img.getAttribute('data-hi-res'); 7168 var mid = $(img).data('mid'); 7169 // Hack to support thumbnails 7170 var queue_id = mid ? 'hi-res-queue-' + mid : 'hi-res-queue-' + (hi_res_src.match(this.FILE_NAME)[1]).replace(/[\W\.(_2x)]/g, ''); 7171 var queue_img = $('#' + queue_id); 7172 7173 if (queue_img.length) { 7174 switch (queue_img.attr('data-hi-res-status')) { 7175 case this.STATE_COMPLETE: 7176 return this.handleCachedImage(queue_img, img); 7177 case this.STATE_LOADING: 7178 return this.handleDuplicateImage(queue_img, img); 7179 default: 7180 return; 7181 } 7182 } else { 7183 this.element.append('<img id="' + queue_id + '" data-hi-res-status="' + this.STATE_LOADING + '">'); 7184 queue_img = $('#' + queue_id); 7185 queue_img.data('lo-res-images', [img]); 7186 queue_img.one('load', function() { 7187 HiRes.Queue.handleLoad(queue_img); 7188 }).one('error', function() { 7189 HiRes.Queue.handleError(queue_img); 7190 }).attr('src', hi_res_src); 7191 } 7192 }, 7193 7194 handleCachedImage: function(queue_img, img) { 7195 img.src = queue_img.attr('src'); 7196 }, 7197 7198 handleDuplicateImage: function(queue_img, img) { 7199 var lo_res_images = queue_img.data('lo-res-images'); 7200 lo_res_images.push(img); 7201 queue_img.data('lo-res-images', lo_res_images); 7202 }, 7203 7204 handleLoad: function(queue_img) { 7205 var hi_res_src = queue_img.attr('src'); 7206 queue_img.attr('data-hi-res-status', this.STATE_COMPLETE); 7207 queue_img.data('lo-res-images').map(function(img) { 7208 img.src = hi_res_src; 7209 }); 7210 }, 7211 7212 handleError: function(queue_img) { 7213 queue_img.attr('data-hi-res-status', this.STATE_ERROR); 7214 } 7215}; 7216 7217HiRes.Loader = { 7218 init: function() {
7219 checkPixelRatio(); 7220 7221 function checkPixelRatio() { 7222 var prevDevicePixelRatio = parseFloat($.cookie('userPixelRatio')); 7223 7224 // if(prevDevicePixelRatio != window.devicePixelRatio) { 7225 if(window.devicePixelRatio > 1.5) { 7226 enableHiRes(); 7227 } else { 7228 disableHiRes(); 7229 } 7230 // } 7231 7232 $.cookie('userPixelRatio', window.devicePixelRatio, {path: '/'}); 7233 } 7234 7235 function disableHiRes() { 7236 $.post("/dispatch/cargosite/cargoUseHiRes", { use : false }, function() {}, "json"); 7237 } 7238 7239 function enableHiRes() { 7240 $.post("/dispatch/cargosite/cargoUseHiRes", { use : true }, function() {}, "json"); 7241 7242 $(document).bind("projectLoadComplete", function(e, pid) { 7243 HiRes.Queue.search(); 7244 }); 7245 7246 $(document).bind("pageChangeComplete", function(e, newpage) { 7247 HiRes.Queue.search(); 7248 }); 7249 7250 $(document).bind("paginationComplete", function(e) { 7251 HiRes.Queue.search(); 7252 }); 7253 7254 HiRes.active = true; 7255 HiRes.Queue.init(); 7256 HiRes.Queue.search(); 7257 } 7258 7259 // listen to changes while page is loaded 7260 try { 7261 var MediaQueryList = window.matchMedia("(-webkit-min-device-pixel-ratio: 1.5)"); 7262 7263 if (typeof MediaQueryList.addListener === "function") { 7264 MediaQueryList.addListener(function(){ 7265 checkPixelRatio(); 7266 }); 7267 } 7268 } catch(err) { 7269 // matchMedia does not exist 7270 } 7271 } 7272}; 7273 7274$(function(){ 7275 HiRes.Loader.init(); 7276});
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.