var ips = (function($){ function init(){ // Hide menus $(".acp-menu").hide(); // Set up modal $("#modal").css( { height: ( $(window).height() - parseInt( $("#header").height() ) ) } ); $(window).resize( function(e){ $("#modal").css( { height: ( $(window).height() - parseInt( $("#header").height() ) ) } ); }); } return { init: init }; })(jQuery); jQ(document).ready(function() { ips.init(); jQ("#app_menu").ipsMultiMenu(); sidebar.init(); livesearch.init(); }); // ************************************ // // Extend jQuery with custom methods // // ************************************ // jQ.undefined = function( obj ){ return typeof obj === "undefined"; }; // ************************************ // // Basic IPS plugins // // ************************************ // var livesearch = {}, sidebar = {}; (function($){ sidebar = function($){ // Properties // Private Methods var init = function(){ $("#toggle_sidebar").click( function(e){ e.preventDefault(); if( $("#page_body").hasClass("open_menu") ) { $("#toggle_sidebar").fadeOut(); $("#section_navigation").fadeOut('slow', function(){ $("#main_content").animate( { marginLeft: 0 }, function(){ $("#page_body").removeClass("open_menu").addClass("close_menu"); $("#toggle_sidebar").fadeIn(); $( window ).trigger('resize'); // Some of our components use window size, so fire this now ipb.Cookie.set("acp_sidebar", "closed", 1); }); }); } else { $("#toggle_sidebar").fadeOut(); $("#main_content").animate( { marginLeft: 195 }, function(){ $("#section_navigation").hide().fadeIn( 'slow', function(){ $("#page_body").removeClass("close_menu").addClass("open_menu"); $("#toggle_sidebar").slideDown(); $( window ).trigger('resize'); // Some of our components use window size, so fire this now ipb.Cookie.set("acp_sidebar", "open", 1); } ); } ); } return false; } ); }; // Public methods return { init: init } }($); livesearch = function($){ // Options object var options = { showDelay: 400, hideDelay: 800, minChars: 3, lastPress: 0 }; // Properties var $elem = {}, $results = {}, $modal = {}, defaultText = '', lastValue = '', timeouts = {}, documentClickHandler = false, cache = {}, self = this; // Templates var templates = { wrap: "", item: "
  • [name]
  • ", none: "

    " + ipb.lang['livesearchnoresults'] + "

    ", locations: { members: "
  • [name]
    [extra]
  • ", forums: "
  • [name]
    [extra]
  • ", nexus: "
  • [name]
  • " } }; // Private methods var init = function(){ $elem = $("#acpSearchKeyword"); $results = $("#live_search_results"); $modal = $("#modal"); defaultText = $elem.val(); $elem.focus( handleFocus ).blur( handleBlur ).attr("autocomplete", "off"); $elem.bind( 'keydown', function() { options.lastPress = new Date().getTime(); } ); // Attach live event to sections that are NOT disabled and NOT active; make Overview active if ( ipb.vars['app_url'].substring( ipb.vars['app_url'].length - 10, ipb.vars['app_url'].length - 5 ) == 'nexus' ) { $("#ls_sections li:not(.disabled):not(.active)", $results).live('click', switchResultsTab).siblings("#ls_nexus").addClass('active'); $("#ls_results > div", $results).hide().siblings("#ls_nexus_panel").show(); $(".count", $results).hide(); } else { $("#ls_sections li:not(.disabled):not(.active)", $results).live('click', switchResultsTab).siblings("#ls_overview").addClass('active'); $("#ls_results > div", $results).hide().siblings("#ls_overview_panel").show(); $(".count", $results).hide(); } }, runSearch = function(){ // Keep it going timeouts['show'] = setTimeout( runSearch, options.showDelay ); var curVal = $elem.val(); var timeNow = new Date().getTime(); if ( options.lastPress && timeNow && ( ( timeNow - options.lastPress ) < 800 ) ) { return; } if( curVal.length < options.minChars ){ hideResultsPanel(); documentClick(false); return; } showResultsPanel(); // Display the modal and results panel documentClick(true); // Set the document click event if( curVal == lastValue ){ return; } // If it's the same as last time, skip fetchResults( curVal ); // Grab the results and process lastValue = curVal; // Update last value to be current value }, fetchResults = function( curVal ){ Debug.write( '--' + curVal ); if( cache[ curVal ] ){ Debug.write("Loading from cache"); parseResults( cache[ curVal ] ); } else { $('#acp_loading').show(); $.ajax( { url: ipb.vars['app_url'].replace( /&/g, '&' ) + "app=core&module=ajax§ion=livesearch&do=search&secure_key=" + ipb.vars['md5_hash'], type: 'POST', data: { 'search_term': curVal }, success: function(data){ if( data['error'] ) { alert( data['error'] ); if( data["__session__expired__log__out__"] ){ window.location.reload(); } } else { cache[ curVal ] = data; parseResults( data ); } $('#acp_loading').hide(); }, error: function(){ alert( ipb.lang['session_timed_out'] ); window.location.reload(); } }); } }, parseResults = function( data ){ if( $.undefined( data ) ){ //Debug.error( "Invalid JSON" ); return; } // Disable all sections to start with $("#ls_sections li").not("#ls_marketplace").addClass("disabled").find(".count").hide(); // If there are per-group settings, add to settings tab if( !$.undefined( data['groupLangs'] ) && data['groupLangs'] ) { var _langs = new Array(); _langs['name'] = ipb.lang['group_settings_match']; _langs['url'] = ipb.vars['base_url'] + 'app=members&module=groups'; data['settings'].unshift( _langs ); } var total = 0; $.each( data, function( location, results ){ if( $.isArray( results ) && results.size() ) { var size = results.size(); var html = ''; // Any special template to use? _template = ( !$.undefined( templates.locations[ location ] ) ) ? templates.locations[ location ] : templates.item; // Update results panel $.each( results, function( k, v ){ html += _template.replace("[name]", v['name']).replace("[url]", v['url']).replace("[img]", v['img']).replace("[extra]", v['extra']); total++; }); // Build wrapper html = templates.wrap.replace("[items]", html); $("#ls_" + location + "_panel").html( html ); // Make members a double-column if( location == 'members' ){ $("#ls_" + location + "_panel").find("li:even").addClass("even").end().find("li:odd").addClass("odd"); } // Update section list count $("#ls_" + location ).removeClass("disabled").find(".count").html( size ).fadeIn('fast'); } else { $("#ls_" + location + "_panel").html(''); //templates.none } }); if( total ){ $("#ls_no_results").hide(); } else { $("#ls_no_results").show(); } }, switchResultsTab = function( e ){ // Switch highlighted tab $(e.target).addClass("active").siblings("li").not(e.target).removeClass("active"); $("#ls_results > div", $results) .not( "#" + e.target.id + "_panel" ).fadeOut() .siblings( "#" + e.target.id + "_panel" ).fadeIn(); }, handleDocumentClick = function(e){ if( $(e.target).closest("#live_search_results, #header").size() == 0 ) { clearTimeout( timeouts['show'] ); documentClick( false ); hideResultsPanel(); } }, documentClick = function( type ){ if( type == true ){ // If the user clicks elsewhere in the document, cancel search if( !documentClickHandler ){ $("body").bind( "click.livesearch", handleDocumentClick ); documentClickHandler = true; } } else { if( documentClickHandler ){ $("body").unbind( "click.livesearch" ); documentClickHandler = false; } } }, showResultsPanel = function(){ $modal.not(":visible").fadeIn('fast'); $results.not(":visible").fadeIn('slow'); }, hideResultsPanel = function(){ $modal.fadeOut('slow'); $results.fadeOut('fast'); }, handleFocus = function(e){ Debug.write("focus!"); if( $elem.hasClass("inactive") ){ $elem.val('').removeClass('inactive'); } clearTimeout( timeouts['show'] ); timeouts['show'] = setTimeout( runSearch, options.showDelay ); }, handleBlur = function(e){ if( $elem.val() == '' ){ clearTimeout( timeouts['show'] ); $elem.val( defaultText ).addClass('inactive'); } }; // Public methods return { init: init } }(jQuery); /****************************************/ /* Wizard bar (step by step) */ /****************************************/ $.fn.ipsWizard = function(options) { var $$ = $(this); var defaults = { nextSelector: "#next", prevSelector: "#prev", wrapSelector: "#ipsSteps_wrapper", finishSelector: "#finish", allowJumping: false, allowGoBack: false }, options = $.extend( defaults, options ); var setJumps = function( elem ){ $$.find("li").removeClass("clickable"); if( options['allowJumping'] ){ $$.find("li").not(".steps_disabled, .steps_active").addClass("clickable"); } if( options['allowGoBack'] ){ $$.find("li.steps_active").prevAll().not(".steps_disabled").addClass("clickable"); } // Show/hide Next/Prev/Finish if( $$.find("li:last").hasClass("steps_active") ){ $( options['nextSelector'] ).hide(); $( options['prevSelector'] + "," + options['finishSelector'] ).show(); } else if( $$.find("li:first").hasClass("steps_active") ) { $( options['nextSelector'] ).show(); $( options['finishSelector'] + "," + options['prevSelector'] ).hide(); } else { $( options['nextSelector'] + "," + options['prevSelector'] ).show() $( options['finishSelector'] ).hide(); } }, nextItem = function(e){ // Find active item and get next item var next = $$.find("li.steps_active").nextAll(":not(.steps_disabled)")[0]; if( $.undefined( next ) ){ return; } showItem( next.id ); }, prevItem = function(e){ var prev = $$.find("li.steps_active").prevAll(":not(.steps_disabled)")[0]; if( $.undefined( prev ) ){ return; } showItem( prev.id ); }, clickStep = function(e){ showItem( $(e.target).closest('li')[0].id ); }, backToTop = function(e){ $('html,body').animate( {'scrollTop': ( $(options['wrapSelector']).offset().top - 80 ) } ); }, focusFirst = function(activeID){ try { $('#'+activeID+'_content :input:first').focus(); } catch(err){ Debug.write( err ); } }, showItem = function( id ){ if( id === false ){ return false; } // Find active var activeID = $$.find("li.steps_active:first")[0].id; if( activeID == id ){ return; } var oldH = $('#'+activeID+'_content').height(); var newH = $('#'+id+'_content').height(); // Set up some CSS $( options['wrapSelector'] ).height( oldH ); $('#'+activeID+'_content').addClass("step_content_animating"); $('#'+id+'_content').addClass("step_content_animating"); // Switch item $( "#" + activeID + '_content' ).fadeOut('slow', function(){ $( options['wrapSelector'] ).animate( { height: newH }, 'fast', function(){ $( "#" + id + '_content' ).fadeIn('slow', function(){ $( options['wrapSelector'] ).css("height", "auto"); $('#'+activeID+'_content').removeClass("step_content_animating"); $('#'+id+'_content').removeClass("step_content_animating"); }); }); }); // Update step bar $("#"+id).siblings() .removeClass("steps_active") .removeClass("steps_done") .end() .addClass("steps_active") .prevAll(":not(.steps_active") .addClass("steps_done"); backToTop(); focusFirst( activeID ); setJumps(); }; return this.each(function(){ if( $.undefined( options['currentStep'] ) ){ } if( !options['allowJumping'] && !options['allowGoBack'] ){ $( options['prevSelector'] ).remove(); } // Set initial clickable status setJumps(); // Set event handler $(".clickable", this).live('click', clickStep); $( options['nextSelector'] ).click( nextItem ); $( options['prevSelector'] ).click( prevItem ); }); }; /****************************************/ /* Multi-level drop down menu */ /****************************************/ $.fn.ipsMultiMenu = function(options) { var defaults = { speed: 'fast' }, options = $.extend( defaults, options), arrow = $("»"), timeouts = {}; var mOver = function(e){ if( $(this).data('timeout') ){ clearTimeout( this.data('timeout') ); $(this).data('timeout', false); } var w = ($(this).outerWidth() - 5), children = $(this).children('ul:first'), docSize = $(window).width(); if( !$(this).parent("ul").hasClass('root') ){ children.css('left', w).css('top', -20); // jQuery can't get offset from hidden elements, so show, measure, then hide. children.show(); var childW = children.outerWidth(); var realLeft = children.offset().left + childW + 5; children.hide(); if( realLeft >= docSize ){ children.css('left', 5 - childW ); } } // Check if it's too far off the screen //children.fadeIn( options.speed ); $(this).children('ul:first').show(); //var _this = this; //setTimeout( function(){ $(_this).children('ul:first').show() }, 150 ); }, mOut = function(e){ //$(this).children('ul:first').fadeOut( options.speed ); var _this = this; var timeout = setTimeout( function(){ $(_this).children('ul:first').hide() }, 250 ); this.data('timeout', timeout); }; return this.each(function(){ // Hide all UL $(this).addClass('root'); $("ul", this).hide(); $("li:has(ul)", this).hover(mOver, mOut).not('.root > li').addClass('has_sub').children("a,span").append(arrow.clone()); }); }; /****************************************/ /* Sortable */ /* Piggybacks on jQuery ui sortable, */ /* but sets up some IPS defaults for it */ /****************************************/ $.fn.ipsSortable = function(type, options) { var defaults = { 'table': { handle: 'td .draghandle', items: 'tr.isDraggable', opacity: 0.6, axis: 'y', revert: true, forceHelperSize: true, helper: 'clone', sendType: 'get', pluralize: true }, 'multidimensional': { handle: '.draghandle', items: 'div.isDraggable', opacity: 0.6, axis: 'y', revert: true, forceHelperSize: true, helper: 'clone', sendType: 'get', pluralize: true }, 'list': { // todo }, 'custom': { } //todo }; return this.each(function(){ var x = ( $.undefined( defaults[type] ) ) ? defaults['custom'] : defaults[type]; var o = $.extend( x, options ); // If there's no function defined already, and a URL is specified, set up // an ajax call if( $.undefined( o['update'] ) && !$.undefined( o['url'] ) ) { o['update'] = function( e, ui ) { if ( ! Object.isUndefined( o['callBackUrlProcess'] ) ) { o['url'] = o['callBackUrlProcess']( o['url'] ); } var serial = $(this).sortable("serialize", ( o['serializeOptions'] || {} ) ); $.ajax( { url: o['url'].replace( /&/g, '&' ), type: o['sendType'], data: serial, processData: false, success: function(data){ if( data['error'] ) { alert( data['error'] ); if( data["__session__expired__log__out__"] ){ window.location.reload(); } } else { Debug.write("Sortable update successfully posted"); } }, error: function(){ alert( ipb.lang['session_timed_out'] ); window.location.reload(); } }); } } $( this ).sortable( o ); }); }; /****************************************/ /* Tab bar */ /****************************************/ $.fn.ipsTabBar = function(options) { var defaults = { tabWrap: "#tabContent", scrollStep: 130 }, options = $.extend( defaults, options ), getTabID = function(tab){ return tab.replace("tab_", ""); }, switchTab = function(e){ var $container = $(this).parent("ul"); var curID = getTabID( $container.find("li.active")[0].id ); var newID = getTabID( this.id ); if( $(this).hasClass("active") ){ return; } // Switch highlighted tab $(this).addClass("active") .siblings("li") .not(this) .removeClass("active"); // Animate tab content $("#tab_" + curID + "_content").fadeOut(); $( options['tabWrap'] ).animate(); $("#tab_" + newID + "_content").fadeIn(); }, scrollTabs = function(e){ var tar = $(e.target); var ul = tar.siblings("ul"); // For both scrollers, check the maximum distance we can scroll // before we get to the end of the bar. Use that distance if it's // less than options.scrollStep. if( $(tar).hasClass('tab_right') ) { var l = parseInt( $(ul).css('left') ) || 0; var w = $(ul).width(); var wrap = $(ul).parent(".ipsTabBar").width(); var diff = ( l + w ) - wrap; var move = ( diff > options.scrollStep ) ? options.scrollStep : diff; $( ul ).animate({ left: "-=" + move}, function(){ checkTabToggle( tar.parent(".ipsTabBar") ); }); } else if( $(tar).hasClass('tab_left') ) { var l = parseInt( $(ul).css('left') ) || 0; var move = ( (l*-1) > options.scrollStep ) ? options.scrollStep : (l*-1); $( ul ).animate({ left: "+=" + move}, function(){ checkTabToggle( tar.parent(".ipsTabBar") ); }); } }, checkTabToggle = function( $this ){ var ul = $("ul", $this), w = ul.outerWidth(), left = parseInt( ul.css('left') ) || 0, pos = parseInt( $($this).css('left') ) || 0, wrap = $($this).width(); if( ( left + w ) > wrap ){ $($this).addClass("with_right").find(".tab_right").fadeIn('fast'); } else { $($this).removeClass("with_right").find(".tab_right").fadeOut('fast'); } if( left < 0 ){ $($this).addClass("with_left").find(".tab_left").fadeIn('fast'); } else { $($this).removeClass("with_left").find(".tab_left").fadeOut('fast'); } }; return this.each(function(){ // Hide the scrollers & set event $(".tab_left,.tab_right", this).hide().mousedown( scrollTabs ); var tabSetup = function( tab, id ){ $(tab).addClass('active'); $( options['tabWrap'] + " > div").not("#tab_" + id + "_content").hide(); // Hide all except active //$( options['tabWrap'] ).height( $("#tab_" + id + "_content").innerHeight() ); // Set tab wrap height to active pane height } // Which default tab? if( $.undefined( options['defaultTab'] ) ){ tabSetup( $("li:first", this), getTabID( $("li:first", this).attr('id') ) ); } else { tabSetup( "#" + options['defaultTab'], getTabID( options['defaultTab'] ) ); } // Event for tab switching $('li', this).click( switchTab ); var $this = this; // Initial check for showing toggles checkTabToggle( $this ); // Check on window resize too $(window).resize( function(){ checkTabToggle( $this ); }); }); }; }(jQuery));