1602 lines
42 KiB
JavaScript
1602 lines
42 KiB
JavaScript
// ************************************ //
|
|
// jQuery ACP Functions //
|
|
// ************************************ //
|
|
|
|
/**
|
|
* IPS namespace
|
|
*/
|
|
var ips = {};
|
|
|
|
!function($, window, document, _undefined)
|
|
{
|
|
$.extend(ips,
|
|
{
|
|
/**
|
|
* Binds all registered functions to elements within the DOM
|
|
*/
|
|
init: function()
|
|
{
|
|
Debug.write('Initialising ips jQuery object');
|
|
|
|
/* Hide menus */
|
|
$(".acp-menu").hide();
|
|
|
|
/* Set up the modal */
|
|
$("#modal").css( { height: ( $(window).height() - parseInt( $("#header").height() ) ) } );
|
|
|
|
$(window).resize( function(e)
|
|
{
|
|
$("#modal").css( { height: ( $(window).height() - parseInt( $("#header").height() ) ) } );
|
|
} );
|
|
|
|
/* Bindings */
|
|
if ( $('#edit_tabs').length )
|
|
{
|
|
$('#edit_tabs').on( 'click', function(e) {
|
|
window.location = ips.acpUrl + '&app=core&module=mycp§ion=tabs';
|
|
} );
|
|
}
|
|
|
|
Debug.write("All jQueried up in here");
|
|
},
|
|
|
|
/**
|
|
* POSTs and always expects JSON
|
|
*
|
|
* @param string url to GET
|
|
* @param object hash to POST
|
|
* @param function Method to run
|
|
* @param object Options
|
|
*
|
|
* @return XMLHttpRequest
|
|
*/
|
|
ajax: function( url, data, success, options )
|
|
{
|
|
url = url.replace( /&/g, '&' );
|
|
|
|
var ajaxOptions = $.extend(true,
|
|
{
|
|
data: data,
|
|
url: url,
|
|
success: function( data, textStatus, jqXHR )
|
|
{
|
|
success( data, textStatus, jqXHR );
|
|
|
|
},
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
error: function(xhr, textStatus, errorThrown)
|
|
{
|
|
try
|
|
{
|
|
/* If its JSON, run it anyway */
|
|
success.call(null, $.parseJSON(xhr.responseText), textStatus);
|
|
}
|
|
catch (e)
|
|
{
|
|
/* Throw error */
|
|
console.error( xhr.responseText );
|
|
}
|
|
},
|
|
timeout: 30000
|
|
}, options);
|
|
|
|
return $.ajax(ajaxOptions);
|
|
},
|
|
|
|
/**
|
|
* Loads CSS
|
|
* @param url
|
|
*/
|
|
loadCss: function( url )
|
|
{
|
|
if ( url )
|
|
{
|
|
$('<link rel="stylesheet" type="text/css" media="screen,print" href="' + url + '" />').appendTo( $('head') );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Loads JS
|
|
* @param url
|
|
*/
|
|
loadJs: function( url )
|
|
{
|
|
if ( url && ( this.loadedJs.indexOf( url ) == -1 ) )
|
|
{
|
|
$('<script/>', { src: url, type: 'text/javascript' } ).appendTo('head');
|
|
|
|
this.loadedJs.push( url );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get url param by name
|
|
*/
|
|
getQueryStringParamByName: function( name )
|
|
{
|
|
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
|
|
var regexS = "[\\?&]" + name + "=([^&#]*)";
|
|
var regex = new RegExp(regexS);
|
|
var results = regex.exec(window.location.search);
|
|
|
|
if ( results == null )
|
|
{
|
|
return "";
|
|
}
|
|
else
|
|
{
|
|
return decodeURIComponent( results[1].replace(/\+/g, " ") );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* User object
|
|
*/
|
|
member: {},
|
|
|
|
/**
|
|
* Url
|
|
*/
|
|
publicUrl: '',
|
|
|
|
/**
|
|
* Public image URL
|
|
*/
|
|
publicImageUrl: '',
|
|
|
|
/**
|
|
* ACP Image URL
|
|
*/
|
|
acpImageUrl: '',
|
|
|
|
/**
|
|
* Root URL
|
|
*/
|
|
rootUrl: '',
|
|
|
|
/**
|
|
* Public URL
|
|
*/
|
|
publicUrl: '',
|
|
|
|
/**
|
|
* ACP URL
|
|
*/
|
|
acpUrl: '',
|
|
|
|
/**
|
|
* Loaded JS
|
|
*/
|
|
loadedJs: [],
|
|
|
|
/**
|
|
* St value
|
|
*/
|
|
stVal: 0,
|
|
|
|
/**
|
|
* Bookmarks JSON
|
|
*/
|
|
bookmarksJSON: {},
|
|
|
|
/**
|
|
* Others
|
|
*/
|
|
formToken: '',
|
|
_popUpId: 0,
|
|
GLOBALS: {}
|
|
|
|
} );
|
|
|
|
/* Is JSON */
|
|
$.isJson = function(str)
|
|
{
|
|
if ($.trim(str) == '') return false;
|
|
str = str.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
|
|
return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
|
|
},
|
|
|
|
/* stripTags */
|
|
$.stripTags = function(input, allowed)
|
|
{
|
|
allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
|
|
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
|
|
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
|
|
|
return input.replace(commentsAndPhpTags, '').replace( tags, function ($0, $1)
|
|
{
|
|
return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
|
|
} );
|
|
};
|
|
|
|
/**
|
|
* Use jQuery to initialize the system
|
|
*/
|
|
$(document).ready( ips.init );
|
|
|
|
}(jQuery, this, document);
|
|
|
|
|
|
/**
|
|
* Bookmark JS
|
|
*/
|
|
!function($, window, document, _undefined)
|
|
{
|
|
ips.Bookmarks = {};
|
|
|
|
/**
|
|
* Handle CKEditor
|
|
*/
|
|
ips.Bookmarks = function() { this.__construct(); };
|
|
ips.Bookmarks.prototype =
|
|
{
|
|
/**
|
|
* Construct object
|
|
*/
|
|
__construct: function()
|
|
{
|
|
this._buildBookmarkList();
|
|
|
|
$('#bookmarks_button').show();
|
|
|
|
$(document).on( 'click', '._closeIt', $.proxy( function(e)
|
|
{
|
|
ips.GLOBALS['bookPop'].hide();
|
|
return false;
|
|
}, this ) );
|
|
|
|
$('#bookmarks_button').on( 'click', $.proxy( function(e)
|
|
{
|
|
return this.addBookmark(e);
|
|
}, this ) );
|
|
|
|
$('#bookmarks_items').on( 'click', '#manageBookmark', $.proxy( function(e)
|
|
{
|
|
return this.manageBookmarks(e);
|
|
}, this ) );
|
|
|
|
$('#bookmarks_items').on( 'click', '#addBookmark', $.proxy( function(e)
|
|
{
|
|
return this.addBookmark(e);
|
|
}, this ) );
|
|
|
|
$('#bookmarks_items').on( 'click', '[data-url]', $.proxy( function(e)
|
|
{
|
|
return this.clickBookmark(e);
|
|
}, this ) );
|
|
|
|
/* Manage */
|
|
$(document).on( 'click', 'input[data-cboxid]', $.proxy( function(e)
|
|
{
|
|
var cbox = $(e.target);
|
|
|
|
$('input[data-cboxid]').each( function( idx )
|
|
{
|
|
if ( $(this).attr('data-cboxid') != $(cbox).attr('data-cboxid') )
|
|
{
|
|
$(this).removeAttr('checked');
|
|
}
|
|
} );
|
|
}, this ) );
|
|
|
|
|
|
$(document).on( 'click', 'img[data-deleteid]', $.proxy( function(e)
|
|
{
|
|
this.removeBookmark(e);
|
|
}, this ) );
|
|
|
|
$(document).on( 'click', '#saveBookmarksManage', $.proxy( function(e)
|
|
{
|
|
this.saveBookmarks(e);
|
|
}, this ) );
|
|
},
|
|
|
|
/**
|
|
* Bookmark clicked
|
|
*/
|
|
saveBookmarks: function(e)
|
|
{
|
|
var names = {};
|
|
var home = 0;
|
|
|
|
$('input[data-inputname]').each( function(idx)
|
|
{
|
|
var id = parseInt( $(this).attr('data-inputname') );
|
|
names[id] = $(this).val();
|
|
} );
|
|
|
|
if ( $('input[data-cboxid]:checked') )
|
|
{
|
|
home = $('input[data-cboxid]:checked').val();
|
|
}
|
|
|
|
var url = ips.acpUrl + 'secure_key=' + ips.formToken + '&app=core&module=ajax§ion=bookmarks&do=save&' + $("#sortable").sortable('serialize');
|
|
var data = { home: home,
|
|
names: names };
|
|
|
|
ips.ajax( url, data, $.proxy( function( json )
|
|
{
|
|
if ( json.status == 'ok' )
|
|
{
|
|
ips.GLOBALS['bookManagePop'].hide();
|
|
|
|
/* Update JSON */
|
|
ips.bookmarksJSON = json.json;
|
|
|
|
this._buildBookmarkList();
|
|
}
|
|
else
|
|
{
|
|
if ( json.msg )
|
|
{
|
|
alert( json.msg );
|
|
}
|
|
}
|
|
}, this ) );
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Bookmark clicked
|
|
*/
|
|
removeBookmark: function(e)
|
|
{
|
|
var elem = $(e.target);
|
|
var id = $(elem).attr('data-deleteid');
|
|
|
|
var url = ips.acpUrl + 'secure_key=' + ips.formToken + '&app=core&module=ajax§ion=bookmarks&do=delete';
|
|
var data = { id: id };
|
|
|
|
if ( confirm( ipb.lang['ok_to_delete'] ) )
|
|
{
|
|
ips.ajax( url, data, $.proxy( function( json )
|
|
{
|
|
if ( json.status == 'ok' )
|
|
{
|
|
/* Remove row */
|
|
$('li[data-rowid=' + id + ']').fadeOut();
|
|
|
|
/* Update JSON */
|
|
ips.bookmarksJSON = json.json;
|
|
|
|
this._buildBookmarkList();
|
|
}
|
|
else
|
|
{
|
|
if ( json.msg )
|
|
{
|
|
alert( json.msg );
|
|
}
|
|
}
|
|
}, this ) );
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Bookmark clicked
|
|
*/
|
|
clickBookmark: function(e)
|
|
{
|
|
var elem = $(e.target).closest('[data-url]');
|
|
var url = elem.attr('data-url');
|
|
var ok = true;
|
|
|
|
/* Check for partially completed values */
|
|
// @link http://community.invisionpower.com/resources/bugs.html/_/ip-board/bookmark-prompt-to-leave-page-r39989
|
|
// Only checking for bookmarks makes the functionality relatively useless and causes confusion
|
|
/*$.each( $('body').find('input[type=text]'), function( idx )
|
|
{
|
|
if ( ! $(this).hasClass('inactive') && $(this).val().length )
|
|
{
|
|
ok = false;
|
|
|
|
return false;
|
|
}
|
|
} );
|
|
|
|
$.each( $('body').find('textarea'), function( idx )
|
|
{
|
|
if ( $(this).val().length )
|
|
{
|
|
ok = false;
|
|
|
|
return false;
|
|
}
|
|
} );*/
|
|
|
|
if ( ok !== true )
|
|
{
|
|
if ( ! confirm( ipb.lang['go_bookmark_warn'] ) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
window.location.href = ips.acpUrl + '&' + url;
|
|
},
|
|
|
|
/**
|
|
* Manage bookmarks
|
|
*/
|
|
manageBookmarks: function(e)
|
|
{
|
|
if ( typeof( ips.GLOBALS['bookManagePop'] ) != 'undefined' )
|
|
{
|
|
ips.GLOBALS['bookManagePop'].kill();
|
|
}
|
|
|
|
var url = ips.acpUrl + 'secure_key=' + ips.formToken + '&app=core&module=ajax§ion=bookmarks&do=managePane';
|
|
|
|
/* Show modal (eew Prototype)*/
|
|
ips.GLOBALS['bookManagePop'] = new ipb.Popup( 'bookManagePop', { type: 'modal',
|
|
ajaxURL: url,
|
|
hideAtStart: false,
|
|
modal: true,
|
|
w: '800px',
|
|
h: 450} );
|
|
|
|
$('#bookpPop_popup').off( 'click', '.realbutton' );
|
|
|
|
$('#bookpPop_popup').on( 'click', '.realbutton', $.proxy( function(e)
|
|
{
|
|
return this.doAddBookmark(e);
|
|
}, this ) );
|
|
|
|
return false;
|
|
},
|
|
|
|
|
|
/**
|
|
* Add a bookmark dialog
|
|
*/
|
|
addBookmark: function(e)
|
|
{
|
|
if ( typeof( ips.GLOBALS['bookPop'] ) != 'undefined' )
|
|
{
|
|
ips.GLOBALS['bookPop'].kill();
|
|
}
|
|
|
|
var _title = $('title').html();
|
|
var _can = $('body').attr('data-bookmarkable');
|
|
var _has = $('body').attr('data-bookmarked');
|
|
|
|
/* Got a url? */
|
|
var _url = this._getUrl();
|
|
|
|
/* Prep data */
|
|
_data = { 'title': _title };
|
|
|
|
/* Show modal (eew Prototype)*/
|
|
ips.GLOBALS['bookPop'] = new ipb.Popup( 'bookpPop', { type: 'modal',
|
|
initial: ipb.templates['acp_bookmark_add'].evaluate( _data ),
|
|
hideAtStart: false,
|
|
modal: true,
|
|
w: '600px',
|
|
h: 250} );
|
|
/* Test */
|
|
if ( _has == 'true' )
|
|
{
|
|
$('#bmcontent').html( ipb.lang['already_bookmark'] );
|
|
$('#bmcontent').append( $('<a/>', { 'class': 'mini_button _closeIt', href: '#' } ).html( ipb.lang['close_bookmark'] ) );
|
|
}
|
|
else if ( _can != 'true' )
|
|
{
|
|
$('#bmcontent').html( ipb.lang['cannot_bookmark'] );
|
|
}
|
|
|
|
$('#bookpPop_popup').off( 'click', '.realbutton' );
|
|
|
|
$('#bookpPop_popup').on( 'click', '.realbutton', $.proxy( function(e)
|
|
{
|
|
return this.doAddBookmark(e);
|
|
}, this ) );
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Add the actual bookmark itself
|
|
*/
|
|
doAddBookmark: function(e)
|
|
{
|
|
var url = ips.acpUrl + 'secure_key=' + ips.formToken + '&app=core&module=ajax§ion=bookmarks&do=add';
|
|
var data = { title: $('input[name=bookmarkTitle]').val(),
|
|
home : ( $('input[name=homePage]').attr('checked') == 'checked' ) ? 1 : 0,
|
|
url: this._getUrl() };
|
|
|
|
ips.ajax( url, data, $.proxy( function( json )
|
|
{
|
|
if ( json.status == 'ok' )
|
|
{
|
|
ips.GLOBALS['bookPop'].hide();
|
|
|
|
/* Update JSON */
|
|
ips.bookmarksJSON = json.json;
|
|
|
|
this._buildBookmarkList();
|
|
}
|
|
else
|
|
{
|
|
if ( json.msg )
|
|
{
|
|
$('#bmcontent').html( json.msg );
|
|
}
|
|
}
|
|
}, this ) );
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Get the current URL
|
|
*/
|
|
_getUrl: function()
|
|
{
|
|
if ( $('body').attr('data-bookmarkurl').length > 0 )
|
|
{
|
|
return $('body').attr('data-bookmarkurl');
|
|
}
|
|
|
|
return window.location.toString().replace( /^(.+?)adsess=([\d\w]{32})(&|&)(.*)/, '$4' );
|
|
},
|
|
|
|
/**
|
|
* Build up the bookmarks list
|
|
*/
|
|
_buildBookmarkList: function()
|
|
{
|
|
$('#bookmarks_items').html('');
|
|
|
|
if ( typeof( ips.bookmarksJSON ) != 'undefined' )
|
|
{
|
|
$.each( ips.bookmarksJSON, function( idx )
|
|
{
|
|
$('<a/>', { href: '#', 'data-url': this.url } ).html( this.title ).appendTo( $('<li/>').appendTo( $('#bookmarks_items') ) );
|
|
} );
|
|
}
|
|
|
|
$('<li/>', { style: 'text-align: center; min-width:200px', id: 'bookmarkAddRow' } ).appendTo( $('#bookmarks_items') );
|
|
|
|
|
|
$('<a/>', { id: 'addBookmark', 'class': 'mini_button secondary', style: 'margin: 5px 0px' } ).html( ipb.lang['add_bookmark'] ).appendTo('#bookmarkAddRow');
|
|
$('<a/>', { id: 'manageBookmark', 'class': 'mini_button secondary' } ).html( ipb.lang['manage_bookmark'] ).appendTo('#bookmarkAddRow');
|
|
|
|
}
|
|
}
|
|
|
|
$(document).ready( function() { ipb.Bookmarks = new ips.Bookmarks(); } );
|
|
|
|
}(jQuery, this, document);
|
|
|
|
|
|
jQ(document).ready(function() {
|
|
//ips.init();
|
|
jQ("#app_menu").ipsMultiMenu( { keyboardTrigger: 77 } );
|
|
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: "<ul>[items]</ul>",
|
|
item: "<li><a href='[url]'><strong>[name]</strong></a></li>",
|
|
none: "<p class='ls_none'>" + ipb.lang['livesearchnoresults'] + "</p>",
|
|
locations: {
|
|
members: "<li><a href='[url]'><img src='[img]' class='photo left' /> <strong>[name]</strong></a><br /><span class='desctext'>[extra]</span></li>",
|
|
forums: "<li><a href='[url]'><strong>[name]</strong></a><br /><span class='desctext'>[extra]</span></li>",
|
|
nexus: "<li><img src='[img]' style='height: 16px; width: 16px; border: 0px' /> <a href='[url]'><strong>[name]</strong></a></li>"
|
|
}
|
|
};
|
|
|
|
// 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 );
|
|
|
|
/* trim() is not chainable, throws error in IE8
|
|
@link http://stackoverflow.com/questions/3439316/ie8-and-jquerys-trim */
|
|
var curVal = $.trim( $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);
|
|
|
|
/****************************************/
|
|
/* Changes checkboxes into button toggles */
|
|
/****************************************/
|
|
$.fn.ipsToggler = function(options) {
|
|
var $$ = $(this);
|
|
|
|
//----------------------------------------------
|
|
// Prepares this checkbox
|
|
//----------------------------------------------
|
|
var setup = function( elem ){
|
|
var newElem = $('<span/>')
|
|
.attr('id', elem.id + '_toggler')
|
|
.addClass( options.baseClass )
|
|
.html('<span>Toggle</span>')
|
|
.data('original', elem );
|
|
|
|
if( elem.checked ){
|
|
newElem
|
|
.addClass( options.on.cssClass )
|
|
.attr('title', options.on.title );
|
|
} else {
|
|
newElem
|
|
.addClass( options.off.cssClass )
|
|
.attr('title', options.off.title );
|
|
}
|
|
|
|
$( elem )
|
|
.hide()
|
|
.before( newElem );
|
|
|
|
$( newElem )
|
|
.click( function(e){
|
|
if( $( this ).hasClass('on') ){
|
|
$( elem ).removeAttr('checked');
|
|
$( this )
|
|
.removeClass('on')
|
|
.addClass('off')
|
|
.attr('title', options.off.title);
|
|
} else {
|
|
$( elem ).attr('checked', 'checked');
|
|
$( this )
|
|
.removeClass('off')
|
|
.addClass('on')
|
|
.attr('title', options.off.title);
|
|
}
|
|
});
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Event handler for the new toggle element
|
|
//----------------------------------------------
|
|
toggle = function(e){
|
|
|
|
};
|
|
|
|
return this.each(function(){
|
|
setup( this );
|
|
});
|
|
};
|
|
|
|
/****************************************/
|
|
/* 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, with */
|
|
/* keyboard navigation */
|
|
/****************************************/
|
|
$.fn.ipsMultiMenu = function(options) {
|
|
var defaults = {
|
|
useHoverIntent: true,
|
|
},
|
|
options = $.extend( defaults, options ),
|
|
arrow = $("<span class='menu_arrow'>»</span>"),
|
|
timeouts = {};
|
|
|
|
// Private methods
|
|
//----------------------------------------------
|
|
// Mouse enter event
|
|
//----------------------------------------------
|
|
var mOver = function(e){
|
|
clearTimeout( timeouts['menu'] );
|
|
|
|
if( !$(this).parent("ul").hasClass('root') && $(this).children('ul').length ){
|
|
positionSubmenu( $(this) );
|
|
}
|
|
|
|
// Hide any submenus belonging to siblings, then show the submenu for this item
|
|
$(this).children('ul:first').fadeIn('fast').end().siblings().find('ul').fadeOut('fast');
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Mouse leave event
|
|
//----------------------------------------------
|
|
mOut = function(e){
|
|
var self = this;
|
|
timeouts['menu'] = setTimeout(
|
|
function(){
|
|
$(self).children('ul:first').fadeOut('fast');
|
|
}, 800
|
|
);
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Positions a menu according to its parent
|
|
//----------------------------------------------
|
|
positionSubmenu = function( menu ){
|
|
var w = ( $(menu).outerWidth() - 5 ),
|
|
children = $(menu).children('ul:first'),
|
|
docSize = $(window).width(),
|
|
docHeight = $(window).height();
|
|
|
|
children.css('left', w).css('top', -5);
|
|
|
|
// jQuery can't get offset from hidden elements, so show, measure, then hide.
|
|
children.show();
|
|
var childW = children.outerWidth();
|
|
var childH = children.outerHeight();
|
|
var realLeft = children.offset().left + childW + 5;
|
|
var realBottom = children.offset().top + childH + 5;
|
|
var realTop = children.offset().top + 5;
|
|
children.hide();
|
|
|
|
if( realLeft >= docSize ){
|
|
children.css('left', 5 - childW );
|
|
}
|
|
|
|
// 37916: Try to show the menu going up if it will go off the bottom of the screen, but
|
|
// only if that won't make it go off the top of the screen
|
|
if( realBottom >= docHeight ){
|
|
if( realTop - childH > 0 )
|
|
{
|
|
children.css('top', 35 - childH );
|
|
}
|
|
}
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Main entry point for keydown event
|
|
//----------------------------------------------
|
|
kPress = function( e, menu ){
|
|
e.preventDefault();
|
|
|
|
var active = findActiveItem( menu );
|
|
|
|
switch( e.keyCode ){
|
|
case 37: // Left
|
|
return move.left( $(active) );
|
|
break;
|
|
case 39: // Right
|
|
return move.right( $(active) );
|
|
break;
|
|
case 38: // Up
|
|
return move.up( $(active) );
|
|
break;
|
|
case 40: // Down
|
|
return move.down( $(active) );
|
|
break;
|
|
case 32: // Space
|
|
case 13: // Enter
|
|
return move.select( $(active) );
|
|
break;
|
|
}
|
|
},
|
|
|
|
move = {
|
|
//----------------------------------------------
|
|
// Handles selecting an item
|
|
//----------------------------------------------
|
|
select: function( active )
|
|
{
|
|
if( active.children('a').length ){
|
|
window.location = active.children('a:first').attr('href');
|
|
}
|
|
else if( active.children('ul') ){
|
|
window.location = active.children('ul').find('a:first').attr('href');
|
|
}
|
|
return false;
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Handles LEFT key
|
|
//----------------------------------------------
|
|
left: function( active ){
|
|
|
|
// If we're in a sub menu, pressing left should close the sub menu
|
|
if( !active.parent('ul').is('.root') && !active.parent('ul').is('.root > li > ul') ){
|
|
active
|
|
.parent('ul')
|
|
.find('.current')
|
|
.removeClass('current')
|
|
.end()
|
|
.hide();
|
|
}
|
|
// If we're in an app menu, and there's a previous app, we'll show that one
|
|
else if( active.parent('ul').is('.root > li > ul') && active.parent('ul').parent('li').prev().length ) {
|
|
active
|
|
.children('ul')
|
|
.hide()
|
|
.end()
|
|
.removeClass('current')
|
|
.prev()
|
|
.addClass('current')
|
|
.children('ul:first')
|
|
.show();
|
|
|
|
}
|
|
return false;
|
|
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Handles RIGHT key
|
|
//----------------------------------------------
|
|
right: function( active ){
|
|
|
|
// If what we have highlighed has a sub menu, show that submenu
|
|
if( !active.parent().is('.root') && active.has('ul:hidden').length ){
|
|
positionSubmenu( active );
|
|
active.children('ul').show().find('li:first').addClass('current');
|
|
}
|
|
else {
|
|
// If we've got something highlighted, and it's in a root app menu, we
|
|
// close the menu and show the next root app menu instead
|
|
if( active.parent('ul').is('.root > li > ul') && active.parent('ul').parent('li').next().length ){
|
|
active
|
|
.parent('ul')
|
|
.find('.current')
|
|
.removeClass('current')
|
|
.hide()
|
|
.end()
|
|
.hide()
|
|
.parent('li')
|
|
.removeClass('current')
|
|
.next()
|
|
.addClass('current')
|
|
.children('ul:first')
|
|
.show();
|
|
}
|
|
// If no menu is open but a root app menu is highlighted,
|
|
// we'll show the next root app
|
|
else if( active.parent('ul').is('.root') && active.next().length ){
|
|
active
|
|
.children('ul')
|
|
.hide()
|
|
.end()
|
|
.removeClass('current')
|
|
.next()
|
|
.addClass('current')
|
|
.children('ul:first')
|
|
.show();
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Handles UP key
|
|
//----------------------------------------------
|
|
up: function( active ){
|
|
// Go up an item, if we can
|
|
if( active.prev().length ){
|
|
active.removeClass('current').prev().addClass('current');
|
|
} else {
|
|
// If not, and this is a root app menu, hide the menu and
|
|
// make the root item active
|
|
if( active.parent().is('.root > li > ul') ){
|
|
active
|
|
.removeClass('current')
|
|
.parent()
|
|
.hide();
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Handles DOWN key
|
|
//----------------------------------------------
|
|
down: function( active ){
|
|
// If this is a root app menu...
|
|
if( active.is('.root > li') ){
|
|
// ...check whether the menu is already shown, and select the first li
|
|
if( active.children('ul:first').is(':visible') ){
|
|
active.find('ul:first > li:first').addClass('current');
|
|
} else {
|
|
// ...if it isn't visible, show it
|
|
active.find('>ul').show();
|
|
}
|
|
} else {
|
|
if( active.next().length ){
|
|
active.removeClass('current').next().addClass('current');
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Finds the deepest currently active menu item
|
|
//----------------------------------------------
|
|
findActiveItem = function( menu ){
|
|
return $('.current:visible', menu).last();
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Hover event to highlight an item
|
|
//----------------------------------------------
|
|
highlight = function( e ){
|
|
$(this)
|
|
.addClass('current')
|
|
.siblings()
|
|
.removeClass('current')
|
|
.parents('li')
|
|
.addClass('current')
|
|
.siblings()
|
|
.find('li')
|
|
.removeClass('current');
|
|
},
|
|
|
|
//----------------------------------------------
|
|
// Unhighlights an item
|
|
//----------------------------------------------
|
|
unhighlight = function( e ){
|
|
$(this).removeClass('current');
|
|
};
|
|
|
|
//----------------------------------------------
|
|
// Main item loop
|
|
//----------------------------------------------
|
|
return this.each( function(elem){
|
|
var self = this;
|
|
|
|
$(self).addClass('root');
|
|
$("ul", self).hide();
|
|
|
|
$("li", self).hover( highlight, unhighlight );
|
|
|
|
$("li", self)[ ( $.fn.hoverIntent && options.useHoverIntent ) ? 'hoverIntent' : 'hover' ]( mOver, mOut )
|
|
.filter(':has(ul)')
|
|
.not('.root > li')
|
|
.addClass('has_sub')
|
|
.children("a,span")
|
|
.append( arrow.clone() );
|
|
|
|
// Prepare event for keyboard navigation
|
|
$(document).keydown( function(e){
|
|
if( options.keyboardTrigger ){
|
|
// If the user presses the trigger key & ctrl & alt
|
|
if( e.keyCode == options.keyboardTrigger && e.ctrlKey && e.altKey ){
|
|
// Show the first menu if nothing is open
|
|
if( !$('.current', self).length ){
|
|
$('.root > li:first')
|
|
.addClass('current')
|
|
.children('ul:first')
|
|
.show()
|
|
.children('li:first')
|
|
.addClass('current');
|
|
}
|
|
// or close everything if something was open
|
|
else {
|
|
$( self )
|
|
.find('.current')
|
|
.removeClass('current')
|
|
.end()
|
|
.find('ul')
|
|
.hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle navigational keypresses
|
|
if( $('.current', self).length ){
|
|
kPress( e, self );
|
|
}
|
|
});
|
|
})
|
|
};
|
|
|
|
/****************************************/
|
|
/* 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");
|
|
}
|
|
|
|
if ( ! Object.isUndefined( o['postUpdateProcess'] ) )
|
|
{
|
|
o['postUpdateProcess']( data );
|
|
}
|
|
},
|
|
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();*/
|
|
|
|
$("#tab_" + curID + "_content").hide();
|
|
$( options['tabWrap'] ).animate();
|
|
$("#tab_" + newID + "_content").show();
|
|
},
|
|
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));
|
|
|
|
/**
|
|
* hoverIntent r6 // 2011.02.26 // jQuery 1.5.1+
|
|
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
|
|
*
|
|
* @param f onMouseOver function || An object with configuration options
|
|
* @param g onMouseOut function || Nothing (use configuration options object)
|
|
* @author Brian Cherne brian(at)cherne(dot)net
|
|
*/
|
|
(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev])}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev])};var handleHover=function(e){var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t)}if(e.type=="mouseenter"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob)},cfg.timeout)}}};return this.bind('mouseenter',handleHover).bind('mouseleave',handleHover)}})(jQuery);
|