You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3295 lines
149 KiB
3295 lines
149 KiB
10 years ago
|
// $Id: jquery.js,v 1.12.2.3 2008/06/25 09:38:39 goba Exp $
|
||
|
|
||
|
/*
|
||
|
* jQuery 1.2.6 - New Wave Javascript
|
||
|
*
|
||
|
* Copyright (c) 2008 John Resig (jquery.com)
|
||
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||
|
* and GPL (GPL-LICENSE.txt) licenses.
|
||
|
*
|
||
|
* Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008)
|
||
|
* Rev: 5685
|
||
|
*/
|
||
|
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(H(){J w=1b.4M,3m$=1b.$;J D=1b.4M=1b.$=H(a,b){I 2B D.17.5j(a,b)};J u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/,62=/^.[^:#\\[\\.]*$/,12;D.17=D.44={5j:H(d,b){d=d||S;G(d.16){7[0]=d;7.K=1;I 7}G(1j d=="23"){J c=u.2D(d);G(c&&(c[1]||!b)){G(c[1])d=D.4h([c[1]],b);N{J a=S.61(c[3]);G(a){G(a.2v!=c[3])I D().2q(d);I D(a)}d=[]}}N I D(b).2q(d)}N G(D.1D(d))I D(S)[D.17.27?"27":"43"](d);I 7.6Y(D.2d(d))},5w:"1.2.6",8G:H(){I 7.K},K:0,3p:H(a){I a==12?D.2d(7):7[a]},2I:H(b){J a=D(b);a.5n=7;I a},6Y:H(a){7.K=0;2p.44.1p.1w(7,a);I 7},P:H(a,b){I D.P(7,a,b)},5i:H(b){J a=-1;I D.2L(b&&b.5w?b[0]:b,7)},1K:H(c,a,b){J d=c;G(c.1q==56)G(a===12)I 7[0]&&D[b||"1K"](7[0],c);N{d={};d[c]=a}I 7.P(H(i){R(c 1n d)D.1K(b?7.V:7,c,D.1i(7,d[c],b,i,c))})},1g:H(b,a){G((b==\'2h\'||b==\'1Z\')&&3d(a)<0)a=12;I 7.1K(b,a,"2a")},1r:H(b){G(1j b!="49"&&b!=U)I 7.4E().3v((7[0]&&7[0].2z||S).5F(b));J a="";D.P(b||7,H(){D.P(7.3t,H(){G(7.16!=8)a+=7.16!=1?7.76:D.17.1r([7])})});I a},5z:H(b){G(7[0])D(b,7[0].2z).5y().39(7[0]).2l(H(){J a=7;1B(a.1x)a=a.1x;I a}).3v(7);I 7},8Y:H(a){I 7.P(H(){D(7).6Q().5z(a)})},8R:H(a){I 7.P(H(){D(7).5z(a)})},3v:H(){I 7.3W(19,M,Q,H(a){G(7.16==1)7.3U(a)})},6F:H(){I 7.3W(19,M,M,H(a){G(7.16==1)7.39(a,7.1x)})},6E:H(){I 7.3W(19,Q,Q,H(a){7.1d.39(a,7)})},5q:H(){I 7.3W(19,Q,M,H(a){7.1d.39(a,7.2H)})},3l:H(){I 7.5n||D([])},2q:H(b){J c=D.2l(7,H(a){I D.2q(b,a)});I 7.2I(/[^+>] [^+>]/.11(b)||b.1h("..")>-1?D.4r(c):c)},5y:H(e){J f=7.2l(H(){G(D.14.1f&&!D.4n(7)){J a=7.6o(M),5h=S.3h("1v");5h.3U(a);I D.4h([5h.4H])[0]}N I 7.6o(M)});J d=f.2q("*").5c().P(H(){G(7[E]!=12)7[E]=U});G(e===M)7.2q("*").5c().P(H(i){G(7.16==3)I;J c=D.L(7,"3w");R(J a 1n c)R(J b 1n c[a])D.W.1e(d[i],a,c[a][b],c[a][b].L)});I f},1E:H(b){I 7.2I(D.1D(b)&&D.3C(7,H(a,i){I b.1k(a,i)})||D.3g(b,7))},4Y:H(b){G(b.1q==56)G(62.11(b))I 7.2I(D.3g(b,7,M));N b=D.3g(b,7);J a=b.K&&b[b.K-1]!==12&&!b.16;I 7.1E(H(){I a?D.2L(7,b)<0:7!=b})},1e:H(a){I 7.2I(D.4r(D.2R(7.3p(),1j a==\'23\'?D(a):D.2d(a))))},3F:H(a){I!!a&&D.3g(a,7).K>0},7T:H(a){I 7.3F("."+a)},6e:H(b){G(b==12){G(7.K){J c=7[0];G(D.Y(c,"2A")){J e=c.64,63=[],15=c.15,2V=c.O=="2A-2V";G(e<0)I U;R(J i=2V?e:0,2f=2V?e+1:15.K;i<2f;i++){J d=15[i];G(d.2W){b=D.14.1f&&!d.at.2x.an?d.1r:d.2x;G(2V)I b;63.1p(b)}}I 63}N I(7[0].2x||"").1o(/\\r/g,"")}I 12}G(b.1q==4L)b+=\'\';I 7.P(H(){G(7.16!=1)I;G(b.1q==2p&&/5O|5L/.11(7.O))7.4J=(D.2L(7.2x,b)>=0||D.2L(7.34,b)>=0);N G(D.Y(7,"2A")){J a=D.2d(b);D("9R",7).P(H(){7.2W=(D.2L(7.2x,a)>=0||D.2L(7.1r,a)>=0)});G(!a.K)7.64=-1}N 7.2x=b})},2K:H(a){I a==12?(7[0]?7[0].4H:U):7.4E().3v(a)},7b:H(a){I 7.5q(a).21()},79:H(i){I 7.3s(i,i+1)},3s:H(){I 7.2I(2p.44.3s.1w(7,19))},2l:H(b){I 7.2I(D.2l(7,H(a,i){I b.1k(a,i,a)}))},5c:H(){I 7.1e(7.5n)},L:H(d,b){J a=d.1R(".");a[1]=a[1]?"."+a[1]:"";G(b===12){J c=7.5C("9z"+a[1]+"!",[a[0]]);G(c===12&&7.K)c=D.L(7[0],d);I c===12&&a[1]?7.L(a[0]):c}N I 7.1P("9u"+a[1]+"!",[a[0],b]).P(H(){D.L(7,d,b)})},3b:H(a){I 7.P(H(){D.3b(7,a)})},3W:H(g,f,h,d){J e=7.K>1,3x;I 7.P(H(){G(!3x){3x=D.4h(g,7.2z);G(h)3x.9o()}J b=7;G(f&&D.Y(7,"1T")&&D.Y(3x[0],"4F"))b=7.3H("22")[0]||7.3U(7.2z.3h("22"));J c=D([]);D.P(3x,H(){J a=e?D(7).5y(M)[0]:7;G(D.Y(a,"1m"))c=c.1e(a);N{G(a.16==1)c=c.1e(D("1m",a).21());d.1k(b,a)}});c.P(6T)})}};D.17.5j.44=D.17;H 6T(i,a){G(a.4d)D.3Y({1a:a.4d,31:Q,1O:"1m"});N D.5u(a.1r||a.6O||a.4H||"");G(a.1d)a.1d.37(a)}H 1z(){I+2B 8J}D.1l=D.17.1l=H(){J b=19[0]||{},i=1,K=19.K,4x=Q,15;G(b.1q==8I){4x=b;b=19[1]||{};i=2}G(1j b!="49"&&1j b!="H")b={};G(K==i){b=7;--i}R(;i<K;i++)G((15=19[i])!=U)R(J c 1n 15){J a=b[c],2w=15[c];G(b===2w)6M;G(4x&&2w&&1j 2w=="49"&&!2w.16)b[c]=D.1l(4x,a||(2w.K!=U?[]:{}),2w);N G(2w!==12)b[c]=2w}I b};J E="4M"+1z(),6K=0,5r={},6G=/z-?5i|8B-?8A|1y|6B|8v-?1Z/i,3P=S.3P||{};D.1l({8u:H(a){1b.$=3m$;G(a)1b.4M=w;I D},1D:H(a){I!!a&&1j a!="23"&&!a.Y&&a.1q!=2p&&/^[\\s[]?H/.11(a+"")},4n:H(a){I a.1C&&!a.1c||a.2j&&a.2z&&!a.2z.1c},5u:H(a){a
|
||
|
|
||
|
var Drupal = Drupal || { 'settings': {}, 'behaviors': {}, 'themes': {}, 'locale': {} };
|
||
|
|
||
|
/**
|
||
|
* Set the variable that indicates if JavaScript behaviors should be applied
|
||
|
*/
|
||
|
Drupal.jsEnabled = document.getElementsByTagName && document.createElement && document.createTextNode && document.documentElement && document.getElementById;
|
||
|
|
||
|
/**
|
||
|
* Attach all registered behaviors to a page element.
|
||
|
*
|
||
|
* Behaviors are event-triggered actions that attach to page elements, enhancing
|
||
|
* default non-Javascript UIs. Behaviors are registered in the Drupal.behaviors
|
||
|
* object as follows:
|
||
|
* @code
|
||
|
* Drupal.behaviors.behaviorName = function () {
|
||
|
* ...
|
||
|
* };
|
||
|
* @endcode
|
||
|
*
|
||
|
* Drupal.attachBehaviors is added below to the jQuery ready event and so
|
||
|
* runs on initial page load. Developers implementing AHAH/AJAX in their
|
||
|
* solutions should also call this function after new page content has been
|
||
|
* loaded, feeding in an element to be processed, in order to attach all
|
||
|
* behaviors to the new content.
|
||
|
*
|
||
|
* Behaviors should use a class in the form behaviorName-processed to ensure
|
||
|
* the behavior is attached only once to a given element. (Doing so enables
|
||
|
* the reprocessing of given elements, which may be needed on occasion despite
|
||
|
* the ability to limit behavior attachment to a particular element.)
|
||
|
*
|
||
|
* @param context
|
||
|
* An element to attach behaviors to. If none is given, the document element
|
||
|
* is used.
|
||
|
*/
|
||
|
Drupal.attachBehaviors = function(context) {
|
||
|
context = context || document;
|
||
|
if (Drupal.jsEnabled) {
|
||
|
// Execute all of them.
|
||
|
jQuery.each(Drupal.behaviors, function() {
|
||
|
this(context);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Encode special characters in a plain-text string for display as HTML.
|
||
|
*/
|
||
|
Drupal.checkPlain = function(str) {
|
||
|
str = String(str);
|
||
|
var replace = { '&': '&', '"': '"', '<': '<', '>': '>' };
|
||
|
for (var character in replace) {
|
||
|
var regex = new RegExp(character, 'g');
|
||
|
str = str.replace(regex, replace[character]);
|
||
|
}
|
||
|
return str;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Translate strings to the page language or a given language.
|
||
|
*
|
||
|
* See the documentation of the server-side t() function for further details.
|
||
|
*
|
||
|
* @param str
|
||
|
* A string containing the English string to translate.
|
||
|
* @param args
|
||
|
* An object of replacements pairs to make after translation. Incidences
|
||
|
* of any key in this array are replaced with the corresponding value.
|
||
|
* Based on the first character of the key, the value is escaped and/or themed:
|
||
|
* - !variable: inserted as is
|
||
|
* - @variable: escape plain text to HTML (Drupal.checkPlain)
|
||
|
* - %variable: escape text and theme as a placeholder for user-submitted
|
||
|
* content (checkPlain + Drupal.theme('placeholder'))
|
||
|
* @return
|
||
|
* The translated string.
|
||
|
*/
|
||
|
Drupal.t = function(str, args) {
|
||
|
// Fetch the localized version of the string.
|
||
|
if (Drupal.locale.strings && Drupal.locale.strings[str]) {
|
||
|
str = Drupal.locale.strings[str];
|
||
|
}
|
||
|
|
||
|
if (args) {
|
||
|
// Transform arguments before inserting them
|
||
|
for (var key in args) {
|
||
|
switch (key.charAt(0)) {
|
||
|
// Escaped only
|
||
|
case '@':
|
||
|
args[key] = Drupal.checkPlain(args[key]);
|
||
|
break;
|
||
|
// Pass-through
|
||
|
case '!':
|
||
|
break;
|
||
|
// Escaped and placeholder
|
||
|
case '%':
|
||
|
default:
|
||
|
args[key] = Drupal.theme('placeholder', args[key]);
|
||
|
break;
|
||
|
}
|
||
|
str = str.replace(key, args[key]);
|
||
|
}
|
||
|
}
|
||
|
return str;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Format a string containing a count of items.
|
||
|
*
|
||
|
* This function ensures that the string is pluralized correctly. Since Drupal.t() is
|
||
|
* called by this function, make sure not to pass already-localized strings to it.
|
||
|
*
|
||
|
* See the documentation of the server-side format_plural() function for further details.
|
||
|
*
|
||
|
* @param count
|
||
|
* The item count to display.
|
||
|
* @param singular
|
||
|
* The string for the singular case. Please make sure it is clear this is
|
||
|
* singular, to ease translation (e.g. use "1 new comment" instead of "1 new").
|
||
|
* Do not use @count in the singular string.
|
||
|
* @param plural
|
||
|
* The string for the plural case. Please make sure it is clear this is plural,
|
||
|
* to ease translation. Use @count in place of the item count, as in "@count
|
||
|
* new comments".
|
||
|
* @param args
|
||
|
* An object of replacements pairs to make after translation. Incidences
|
||
|
* of any key in this array are replaced with the corresponding value.
|
||
|
* Based on the first character of the key, the value is escaped and/or themed:
|
||
|
* - !variable: inserted as is
|
||
|
* - @variable: escape plain text to HTML (Drupal.checkPlain)
|
||
|
* - %variable: escape text and theme as a placeholder for user-submitted
|
||
|
* content (checkPlain + Drupal.theme('placeholder'))
|
||
|
* Note that you do not need to include @count in this array.
|
||
|
* This replacement is done automatically for the plural case.
|
||
|
* @return
|
||
|
* A translated string.
|
||
|
*/
|
||
|
Drupal.formatPlural = function(count, singular, plural, args) {
|
||
|
var args = args || {};
|
||
|
args['@count'] = count;
|
||
|
// Determine the index of the plural form.
|
||
|
var index = Drupal.locale.pluralFormula ? Drupal.locale.pluralFormula(args['@count']) : ((args['@count'] == 1) ? 0 : 1);
|
||
|
|
||
|
if (index == 0) {
|
||
|
return Drupal.t(singular, args);
|
||
|
}
|
||
|
else if (index == 1) {
|
||
|
return Drupal.t(plural, args);
|
||
|
}
|
||
|
else {
|
||
|
args['@count['+ index +']'] = args['@count'];
|
||
|
delete args['@count'];
|
||
|
return Drupal.t(plural.replace('@count', '@count['+ index +']'));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Generate the themed representation of a Drupal object.
|
||
|
*
|
||
|
* All requests for themed output must go through this function. It examines
|
||
|
* the request and routes it to the appropriate theme function. If the current
|
||
|
* theme does not provide an override function, the generic theme function is
|
||
|
* called.
|
||
|
*
|
||
|
* For example, to retrieve the HTML that is output by theme_placeholder(text),
|
||
|
* call Drupal.theme('placeholder', text).
|
||
|
*
|
||
|
* @param func
|
||
|
* The name of the theme function to call.
|
||
|
* @param ...
|
||
|
* Additional arguments to pass along to the theme function.
|
||
|
* @return
|
||
|
* Any data the theme function returns. This could be a plain HTML string,
|
||
|
* but also a complex object.
|
||
|
*/
|
||
|
Drupal.theme = function(func) {
|
||
|
for (var i = 1, args = []; i < arguments.length; i++) {
|
||
|
args.push(arguments[i]);
|
||
|
}
|
||
|
|
||
|
return (Drupal.theme[func] || Drupal.theme.prototype[func]).apply(this, args);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Parse a JSON response.
|
||
|
*
|
||
|
* The result is either the JSON object, or an object with 'status' 0 and 'data' an error message.
|
||
|
*/
|
||
|
Drupal.parseJson = function (data) {
|
||
|
if ((data.substring(0, 1) != '{') && (data.substring(0, 1) != '[')) {
|
||
|
return { status: 0, data: data.length ? data : Drupal.t('Unspecified error') };
|
||
|
}
|
||
|
return eval('(' + data + ');');
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Freeze the current body height (as minimum height). Used to prevent
|
||
|
* unnecessary upwards scrolling when doing DOM manipulations.
|
||
|
*/
|
||
|
Drupal.freezeHeight = function () {
|
||
|
Drupal.unfreezeHeight();
|
||
|
var div = document.createElement('div');
|
||
|
$(div).css({
|
||
|
position: 'absolute',
|
||
|
top: '0px',
|
||
|
left: '0px',
|
||
|
width: '1px',
|
||
|
height: $('body').css('height')
|
||
|
}).attr('id', 'freeze-height');
|
||
|
$('body').append(div);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Unfreeze the body height
|
||
|
*/
|
||
|
Drupal.unfreezeHeight = function () {
|
||
|
$('#freeze-height').remove();
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Wrapper to address the mod_rewrite url encoding bug
|
||
|
* (equivalent of drupal_urlencode() in PHP).
|
||
|
*/
|
||
|
Drupal.encodeURIComponent = function (item, uri) {
|
||
|
uri = uri || location.href;
|
||
|
item = encodeURIComponent(item).replace(/%2F/g, '/');
|
||
|
return (uri.indexOf('?q=') != -1) ? item : item.replace(/%26/g, '%2526').replace(/%23/g, '%2523').replace(/\/\//g, '/%252F');
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Get the text selection in a textarea.
|
||
|
*/
|
||
|
Drupal.getSelection = function (element) {
|
||
|
if (typeof(element.selectionStart) != 'number' && document.selection) {
|
||
|
// The current selection
|
||
|
var range1 = document.selection.createRange();
|
||
|
var range2 = range1.duplicate();
|
||
|
// Select all text.
|
||
|
range2.moveToElementText(element);
|
||
|
// Now move 'dummy' end point to end point of original range.
|
||
|
range2.setEndPoint('EndToEnd', range1);
|
||
|
// Now we can calculate start and end points.
|
||
|
var start = range2.text.length - range1.text.length;
|
||
|
var end = start + range1.text.length;
|
||
|
return { 'start': start, 'end': end };
|
||
|
}
|
||
|
return { 'start': element.selectionStart, 'end': element.selectionEnd };
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Build an error message from ahah response.
|
||
|
*/
|
||
|
Drupal.ahahError = function(xmlhttp, uri) {
|
||
|
if (xmlhttp.status == 200) {
|
||
|
if (jQuery.trim($(xmlhttp.responseText).text())) {
|
||
|
var message = Drupal.t("An error occurred. \n@uri\n@text", {'@uri': uri, '@text': xmlhttp.responseText });
|
||
|
}
|
||
|
else {
|
||
|
var message = Drupal.t("An error occurred. \n@uri\n(no information available).", {'@uri': uri, '@text': xmlhttp.responseText });
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
var message = Drupal.t("An HTTP error @status occurred. \n@uri", {'@uri': uri, '@status': xmlhttp.status });
|
||
|
}
|
||
|
return message;
|
||
|
}
|
||
|
|
||
|
// Global Killswitch on the <html> element
|
||
|
if (Drupal.jsEnabled) {
|
||
|
// Global Killswitch on the <html> element
|
||
|
$(document.documentElement).addClass('js');
|
||
|
// 'js enabled' cookie
|
||
|
document.cookie = 'has_js=1; path=/';
|
||
|
// Attach all behaviors.
|
||
|
$(document).ready(function() {
|
||
|
Drupal.attachBehaviors(this);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The default themes.
|
||
|
*/
|
||
|
Drupal.theme.prototype = {
|
||
|
|
||
|
/**
|
||
|
* Formats text for emphasized display in a placeholder inside a sentence.
|
||
|
*
|
||
|
* @param str
|
||
|
* The text to format (plain-text).
|
||
|
* @return
|
||
|
* The formatted text (html).
|
||
|
*/
|
||
|
placeholder: function(str) {
|
||
|
return '<em>' + Drupal.checkPlain(str) + '</em>';
|
||
|
}
|
||
|
};
|
||
|
;// $Id: tabledrag.js,v 1.13.2.5 2009/06/18 12:24:24 goba Exp $
|
||
|
|
||
|
/**
|
||
|
* Drag and drop table rows with field manipulation.
|
||
|
*
|
||
|
* Using the drupal_add_tabledrag() function, any table with weights or parent
|
||
|
* relationships may be made into draggable tables. Columns containing a field
|
||
|
* may optionally be hidden, providing a better user experience.
|
||
|
*
|
||
|
* Created tableDrag instances may be modified with custom behaviors by
|
||
|
* overriding the .onDrag, .onDrop, .row.onSwap, and .row.onIndent methods.
|
||
|
* See blocks.js for an example of adding additional functionality to tableDrag.
|
||
|
*/
|
||
|
Drupal.behaviors.tableDrag = function(context) {
|
||
|
for (var base in Drupal.settings.tableDrag) {
|
||
|
if (!$('#' + base + '.tabledrag-processed', context).size()) {
|
||
|
var tableSettings = Drupal.settings.tableDrag[base];
|
||
|
|
||
|
$('#' + base).filter(':not(.tabledrag-processed)').each(function() {
|
||
|
// Create the new tableDrag instance. Save in the Drupal variable
|
||
|
// to allow other scripts access to the object.
|
||
|
Drupal.tableDrag[base] = new Drupal.tableDrag(this, tableSettings);
|
||
|
});
|
||
|
|
||
|
$('#' + base).addClass('tabledrag-processed');
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Constructor for the tableDrag object. Provides table and field manipulation.
|
||
|
*
|
||
|
* @param table
|
||
|
* DOM object for the table to be made draggable.
|
||
|
* @param tableSettings
|
||
|
* Settings for the table added via drupal_add_dragtable().
|
||
|
*/
|
||
|
Drupal.tableDrag = function(table, tableSettings) {
|
||
|
var self = this;
|
||
|
|
||
|
// Required object variables.
|
||
|
this.table = table;
|
||
|
this.tableSettings = tableSettings;
|
||
|
this.dragObject = null; // Used to hold information about a current drag operation.
|
||
|
this.rowObject = null; // Provides operations for row manipulation.
|
||
|
this.oldRowElement = null; // Remember the previous element.
|
||
|
this.oldY = 0; // Used to determine up or down direction from last mouse move.
|
||
|
this.changed = false; // Whether anything in the entire table has changed.
|
||
|
this.maxDepth = 0; // Maximum amount of allowed parenting.
|
||
|
this.rtl = $(this.table).css('direction') == 'rtl' ? -1 : 1; // Direction of the table.
|
||
|
|
||
|
// Configure the scroll settings.
|
||
|
this.scrollSettings = { amount: 4, interval: 50, trigger: 70 };
|
||
|
this.scrollInterval = null;
|
||
|
this.scrollY = 0;
|
||
|
this.windowHeight = 0;
|
||
|
|
||
|
// Check this table's settings to see if there are parent relationships in
|
||
|
// this table. For efficiency, large sections of code can be skipped if we
|
||
|
// don't need to track horizontal movement and indentations.
|
||
|
this.indentEnabled = false;
|
||
|
for (group in tableSettings) {
|
||
|
for (n in tableSettings[group]) {
|
||
|
if (tableSettings[group][n]['relationship'] == 'parent') {
|
||
|
this.indentEnabled = true;
|
||
|
}
|
||
|
if (tableSettings[group][n]['limit'] > 0) {
|
||
|
this.maxDepth = tableSettings[group][n]['limit'];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (this.indentEnabled) {
|
||
|
this.indentCount = 1; // Total width of indents, set in makeDraggable.
|
||
|
// Find the width of indentations to measure mouse movements against.
|
||
|
// Because the table doesn't need to start with any indentations, we
|
||
|
// manually append 2 indentations in the first draggable row, measure
|
||
|
// the offset, then remove.
|
||
|
var indent = Drupal.theme('tableDragIndentation');
|
||
|
// Match immediate children of the parent element to allow nesting.
|
||
|
var testCell = $('> tbody > tr.draggable:first td:first, > tr.draggable:first td:first', table).prepend(indent).prepend(indent);
|
||
|
this.indentAmount = $('.indentation', testCell).get(1).offsetLeft - $('.indentation', testCell).get(0).offsetLeft;
|
||
|
$('.indentation', testCell).slice(0, 2).remove();
|
||
|
}
|
||
|
|
||
|
// Make each applicable row draggable.
|
||
|
// Match immediate children of the parent element to allow nesting.
|
||
|
$('> tr.draggable, > tbody > tr.draggable', table).each(function() { self.makeDraggable(this); });
|
||
|
|
||
|
// Hide columns containing affected form elements.
|
||
|
this.hideColumns();
|
||
|
|
||
|
// Add mouse bindings to the document. The self variable is passed along
|
||
|
// as event handlers do not have direct access to the tableDrag object.
|
||
|
$(document).bind('mousemove', function(event) { return self.dragRow(event, self); });
|
||
|
$(document).bind('mouseup', function(event) { return self.dropRow(event, self); });
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Hide the columns containing form elements according to the settings for
|
||
|
* this tableDrag instance.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.hideColumns = function(){
|
||
|
for (var group in this.tableSettings) {
|
||
|
// Find the first field in this group.
|
||
|
for (var d in this.tableSettings[group]) {
|
||
|
var field = $('.' + this.tableSettings[group][d]['target'] + ':first', this.table);
|
||
|
if (field.size() && this.tableSettings[group][d]['hidden']) {
|
||
|
var hidden = this.tableSettings[group][d]['hidden'];
|
||
|
var cell = field.parents('td:first');
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Hide the column containing this field.
|
||
|
if (hidden && cell[0] && cell.css('display') != 'none') {
|
||
|
// Add 1 to our indexes. The nth-child selector is 1 based, not 0 based.
|
||
|
// Match immediate children of the parent element to allow nesting.
|
||
|
var columnIndex = $('> td', cell.parent()).index(cell.get(0)) + 1;
|
||
|
var headerIndex = $('> td:not(:hidden)', cell.parent()).index(cell.get(0)) + 1;
|
||
|
$('> thead > tr, > tbody > tr, > tr', this.table).each(function(){
|
||
|
var row = $(this);
|
||
|
var parentTag = row.parent().get(0).tagName.toLowerCase();
|
||
|
var index = (parentTag == 'thead') ? headerIndex : columnIndex;
|
||
|
|
||
|
// Adjust the index to take into account colspans.
|
||
|
row.children().each(function(n) {
|
||
|
if (n < index) {
|
||
|
index -= (this.colSpan && this.colSpan > 1) ? this.colSpan - 1 : 0;
|
||
|
}
|
||
|
});
|
||
|
if (index > 0) {
|
||
|
cell = row.children(':nth-child(' + index + ')');
|
||
|
if (cell[0].colSpan > 1) {
|
||
|
// If this cell has a colspan, simply reduce it.
|
||
|
cell[0].colSpan = cell[0].colSpan - 1;
|
||
|
}
|
||
|
else {
|
||
|
// Hide table body cells, but remove table header cells entirely
|
||
|
// (Safari doesn't hide properly).
|
||
|
parentTag == 'thead' ? cell.remove() : cell.css('display', 'none');
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Find the target used within a particular row and group.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.rowSettings = function(group, row) {
|
||
|
var field = $('.' + group, row);
|
||
|
for (delta in this.tableSettings[group]) {
|
||
|
var targetClass = this.tableSettings[group][delta]['target'];
|
||
|
if (field.is('.' + targetClass)) {
|
||
|
// Return a copy of the row settings.
|
||
|
var rowSettings = new Object();
|
||
|
for (var n in this.tableSettings[group][delta]) {
|
||
|
rowSettings[n] = this.tableSettings[group][delta][n];
|
||
|
}
|
||
|
return rowSettings;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Take an item and add event handlers to make it become draggable.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.makeDraggable = function(item) {
|
||
|
var self = this;
|
||
|
|
||
|
// Create the handle.
|
||
|
var handle = $('<a href="#" class="tabledrag-handle"><div class="handle"> </div></a>').attr('title', Drupal.t('Drag to re-order'));
|
||
|
// Insert the handle after indentations (if any).
|
||
|
if ($('td:first .indentation:last', item).after(handle).size()) {
|
||
|
// Update the total width of indentation in this entire table.
|
||
|
self.indentCount = Math.max($('.indentation', item).size(), self.indentCount);
|
||
|
}
|
||
|
else {
|
||
|
$('td:first', item).prepend(handle);
|
||
|
}
|
||
|
|
||
|
// Add hover action for the handle.
|
||
|
handle.hover(function() {
|
||
|
self.dragObject == null ? $(this).addClass('tabledrag-handle-hover') : null;
|
||
|
}, function() {
|
||
|
self.dragObject == null ? $(this).removeClass('tabledrag-handle-hover') : null;
|
||
|
});
|
||
|
|
||
|
// Add the mousedown action for the handle.
|
||
|
handle.mousedown(function(event) {
|
||
|
// Create a new dragObject recording the event information.
|
||
|
self.dragObject = new Object();
|
||
|
self.dragObject.initMouseOffset = self.getMouseOffset(item, event);
|
||
|
self.dragObject.initMouseCoords = self.mouseCoords(event);
|
||
|
if (self.indentEnabled) {
|
||
|
self.dragObject.indentMousePos = self.dragObject.initMouseCoords;
|
||
|
}
|
||
|
|
||
|
// If there's a lingering row object from the keyboard, remove its focus.
|
||
|
if (self.rowObject) {
|
||
|
$('a.tabledrag-handle', self.rowObject.element).blur();
|
||
|
}
|
||
|
|
||
|
// Create a new rowObject for manipulation of this row.
|
||
|
self.rowObject = new self.row(item, 'mouse', self.indentEnabled, self.maxDepth, true);
|
||
|
|
||
|
// Save the position of the table.
|
||
|
self.table.topY = self.getPosition(self.table).y;
|
||
|
self.table.bottomY = self.table.topY + self.table.offsetHeight;
|
||
|
|
||
|
// Add classes to the handle and row.
|
||
|
$(this).addClass('tabledrag-handle-hover');
|
||
|
$(item).addClass('drag');
|
||
|
|
||
|
// Set the document to use the move cursor during drag.
|
||
|
$('body').addClass('drag');
|
||
|
if (self.oldRowElement) {
|
||
|
$(self.oldRowElement).removeClass('drag-previous');
|
||
|
}
|
||
|
|
||
|
// Hack for IE6 that flickers uncontrollably if select lists are moved.
|
||
|
if (navigator.userAgent.indexOf('MSIE 6.') != -1) {
|
||
|
$('select', this.table).css('display', 'none');
|
||
|
}
|
||
|
|
||
|
// Hack for Konqueror, prevent the blur handler from firing.
|
||
|
// Konqueror always gives links focus, even after returning false on mousedown.
|
||
|
self.safeBlur = false;
|
||
|
|
||
|
// Call optional placeholder function.
|
||
|
self.onDrag();
|
||
|
return false;
|
||
|
});
|
||
|
|
||
|
// Prevent the anchor tag from jumping us to the top of the page.
|
||
|
handle.click(function() {
|
||
|
return false;
|
||
|
});
|
||
|
|
||
|
// Similar to the hover event, add a class when the handle is focused.
|
||
|
handle.focus(function() {
|
||
|
$(this).addClass('tabledrag-handle-hover');
|
||
|
self.safeBlur = true;
|
||
|
});
|
||
|
|
||
|
// Remove the handle class on blur and fire the same function as a mouseup.
|
||
|
handle.blur(function(event) {
|
||
|
$(this).removeClass('tabledrag-handle-hover');
|
||
|
if (self.rowObject && self.safeBlur) {
|
||
|
self.dropRow(event, self);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Add arrow-key support to the handle.
|
||
|
handle.keydown(function(event) {
|
||
|
// If a rowObject doesn't yet exist and this isn't the tab key.
|
||
|
if (event.keyCode != 9 && !self.rowObject) {
|
||
|
self.rowObject = new self.row(item, 'keyboard', self.indentEnabled, self.maxDepth, true);
|
||
|
}
|
||
|
|
||
|
var keyChange = false;
|
||
|
switch (event.keyCode) {
|
||
|
case 37: // Left arrow.
|
||
|
case 63234: // Safari left arrow.
|
||
|
keyChange = true;
|
||
|
self.rowObject.indent(-1 * self.rtl);
|
||
|
break;
|
||
|
case 38: // Up arrow.
|
||
|
case 63232: // Safari up arrow.
|
||
|
var previousRow = $(self.rowObject.element).prev('tr').get(0);
|
||
|
while (previousRow && $(previousRow).is(':hidden')) {
|
||
|
previousRow = $(previousRow).prev('tr').get(0);
|
||
|
}
|
||
|
if (previousRow) {
|
||
|
self.safeBlur = false; // Do not allow the onBlur cleanup.
|
||
|
self.rowObject.direction = 'up';
|
||
|
keyChange = true;
|
||
|
|
||
|
if ($(item).is('.tabledrag-root')) {
|
||
|
// Swap with the previous top-level row..
|
||
|
var groupHeight = 0;
|
||
|
while (previousRow && $('.indentation', previousRow).size()) {
|
||
|
previousRow = $(previousRow).prev('tr').get(0);
|
||
|
groupHeight += $(previousRow).is(':hidden') ? 0 : previousRow.offsetHeight;
|
||
|
}
|
||
|
if (previousRow) {
|
||
|
self.rowObject.swap('before', previousRow);
|
||
|
// No need to check for indentation, 0 is the only valid one.
|
||
|
window.scrollBy(0, -groupHeight);
|
||
|
}
|
||
|
}
|
||
|
else if (self.table.tBodies[0].rows[0] != previousRow || $(previousRow).is('.draggable')) {
|
||
|
// Swap with the previous row (unless previous row is the first one
|
||
|
// and undraggable).
|
||
|
self.rowObject.swap('before', previousRow);
|
||
|
self.rowObject.interval = null;
|
||
|
self.rowObject.indent(0);
|
||
|
window.scrollBy(0, -parseInt(item.offsetHeight));
|
||
|
}
|
||
|
handle.get(0).focus(); // Regain focus after the DOM manipulation.
|
||
|
}
|
||
|
break;
|
||
|
case 39: // Right arrow.
|
||
|
case 63235: // Safari right arrow.
|
||
|
keyChange = true;
|
||
|
self.rowObject.indent(1 * self.rtl);
|
||
|
break;
|
||
|
case 40: // Down arrow.
|
||
|
case 63233: // Safari down arrow.
|
||
|
var nextRow = $(self.rowObject.group).filter(':last').next('tr').get(0);
|
||
|
while (nextRow && $(nextRow).is(':hidden')) {
|
||
|
nextRow = $(nextRow).next('tr').get(0);
|
||
|
}
|
||
|
if (nextRow) {
|
||
|
self.safeBlur = false; // Do not allow the onBlur cleanup.
|
||
|
self.rowObject.direction = 'down';
|
||
|
keyChange = true;
|
||
|
|
||
|
if ($(item).is('.tabledrag-root')) {
|
||
|
// Swap with the next group (necessarily a top-level one).
|
||
|
var groupHeight = 0;
|
||
|
nextGroup = new self.row(nextRow, 'keyboard', self.indentEnabled, self.maxDepth, false);
|
||
|
if (nextGroup) {
|
||
|
$(nextGroup.group).each(function () {groupHeight += $(this).is(':hidden') ? 0 : this.offsetHeight});
|
||
|
nextGroupRow = $(nextGroup.group).filter(':last').get(0);
|
||
|
self.rowObject.swap('after', nextGroupRow);
|
||
|
// No need to check for indentation, 0 is the only valid one.
|
||
|
window.scrollBy(0, parseInt(groupHeight));
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
// Swap with the next row.
|
||
|
self.rowObject.swap('after', nextRow);
|
||
|
self.rowObject.interval = null;
|
||
|
self.rowObject.indent(0);
|
||
|
window.scrollBy(0, parseInt(item.offsetHeight));
|
||
|
}
|
||
|
handle.get(0).focus(); // Regain focus after the DOM manipulation.
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (self.rowObject && self.rowObject.changed == true) {
|
||
|
$(item).addClass('drag');
|
||
|
if (self.oldRowElement) {
|
||
|
$(self.oldRowElement).removeClass('drag-previous');
|
||
|
}
|
||
|
self.oldRowElement = item;
|
||
|
self.restripeTable();
|
||
|
self.onDrag();
|
||
|
}
|
||
|
|
||
|
// Returning false if we have an arrow key to prevent scrolling.
|
||
|
if (keyChange) {
|
||
|
return false;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Compatibility addition, return false on keypress to prevent unwanted scrolling.
|
||
|
// IE and Safari will supress scrolling on keydown, but all other browsers
|
||
|
// need to return false on keypress. http://www.quirksmode.org/js/keys.html
|
||
|
handle.keypress(function(event) {
|
||
|
switch (event.keyCode) {
|
||
|
case 37: // Left arrow.
|
||
|
case 38: // Up arrow.
|
||
|
case 39: // Right arrow.
|
||
|
case 40: // Down arrow.
|
||
|
return false;
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Mousemove event handler, bound to document.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.dragRow = function(event, self) {
|
||
|
if (self.dragObject) {
|
||
|
self.currentMouseCoords = self.mouseCoords(event);
|
||
|
|
||
|
var y = self.currentMouseCoords.y - self.dragObject.initMouseOffset.y;
|
||
|
var x = self.currentMouseCoords.x - self.dragObject.initMouseOffset.x;
|
||
|
|
||
|
// Check for row swapping and vertical scrolling.
|
||
|
if (y != self.oldY) {
|
||
|
self.rowObject.direction = y > self.oldY ? 'down' : 'up';
|
||
|
self.oldY = y; // Update the old value.
|
||
|
|
||
|
// Check if the window should be scrolled (and how fast).
|
||
|
var scrollAmount = self.checkScroll(self.currentMouseCoords.y);
|
||
|
// Stop any current scrolling.
|
||
|
clearInterval(self.scrollInterval);
|
||
|
// Continue scrolling if the mouse has moved in the scroll direction.
|
||
|
if (scrollAmount > 0 && self.rowObject.direction == 'down' || scrollAmount < 0 && self.rowObject.direction == 'up') {
|
||
|
self.setScroll(scrollAmount);
|
||
|
}
|
||
|
|
||
|
// If we have a valid target, perform the swap and restripe the table.
|
||
|
var currentRow = self.findDropTargetRow(x, y);
|
||
|
if (currentRow) {
|
||
|
if (self.rowObject.direction == 'down') {
|
||
|
self.rowObject.swap('after', currentRow, self);
|
||
|
}
|
||
|
else {
|
||
|
self.rowObject.swap('before', currentRow, self);
|
||
|
}
|
||
|
self.restripeTable();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Similar to row swapping, handle indentations.
|
||
|
if (self.indentEnabled) {
|
||
|
var xDiff = self.currentMouseCoords.x - self.dragObject.indentMousePos.x;
|
||
|
// Set the number of indentations the mouse has been moved left or right.
|
||
|
var indentDiff = Math.round(xDiff / self.indentAmount * self.rtl);
|
||
|
// Indent the row with our estimated diff, which may be further
|
||
|
// restricted according to the rows around this row.
|
||
|
var indentChange = self.rowObject.indent(indentDiff);
|
||
|
// Update table and mouse indentations.
|
||
|
self.dragObject.indentMousePos.x += self.indentAmount * indentChange * self.rtl;
|
||
|
self.indentCount = Math.max(self.indentCount, self.rowObject.indents);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Mouseup event handler, bound to document.
|
||
|
* Blur event handler, bound to drag handle for keyboard support.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.dropRow = function(event, self) {
|
||
|
// Drop row functionality shared between mouseup and blur events.
|
||
|
if (self.rowObject != null) {
|
||
|
var droppedRow = self.rowObject.element;
|
||
|
// The row is already in the right place so we just release it.
|
||
|
if (self.rowObject.changed == true) {
|
||
|
// Update the fields in the dropped row.
|
||
|
self.updateFields(droppedRow);
|
||
|
|
||
|
// If a setting exists for affecting the entire group, update all the
|
||
|
// fields in the entire dragged group.
|
||
|
for (var group in self.tableSettings) {
|
||
|
var rowSettings = self.rowSettings(group, droppedRow);
|
||
|
if (rowSettings.relationship == 'group') {
|
||
|
for (n in self.rowObject.children) {
|
||
|
self.updateField(self.rowObject.children[n], group);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
self.rowObject.markChanged();
|
||
|
if (self.changed == false) {
|
||
|
$(Drupal.theme('tableDragChangedWarning')).insertAfter(self.table).hide().fadeIn('slow');
|
||
|
self.changed = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (self.indentEnabled) {
|
||
|
self.rowObject.removeIndentClasses();
|
||
|
}
|
||
|
if (self.oldRowElement) {
|
||
|
$(self.oldRowElement).removeClass('drag-previous');
|
||
|
}
|
||
|
$(droppedRow).removeClass('drag').addClass('drag-previous');
|
||
|
self.oldRowElement = droppedRow;
|
||
|
self.onDrop();
|
||
|
self.rowObject = null;
|
||
|
}
|
||
|
|
||
|
// Functionality specific only to mouseup event.
|
||
|
if (self.dragObject != null) {
|
||
|
$('.tabledrag-handle', droppedRow).removeClass('tabledrag-handle-hover');
|
||
|
|
||
|
self.dragObject = null;
|
||
|
$('body').removeClass('drag');
|
||
|
clearInterval(self.scrollInterval);
|
||
|
|
||
|
// Hack for IE6 that flickers uncontrollably if select lists are moved.
|
||
|
if (navigator.userAgent.indexOf('MSIE 6.') != -1) {
|
||
|
$('select', this.table).css('display', 'block');
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Get the position of an element by adding up parent offsets in the DOM tree.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.getPosition = function(element){
|
||
|
var left = 0;
|
||
|
var top = 0;
|
||
|
// Because Safari doesn't report offsetHeight on table rows, but does on table
|
||
|
// cells, grab the firstChild of the row and use that instead.
|
||
|
// http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari
|
||
|
if (element.offsetHeight == 0) {
|
||
|
element = element.firstChild; // a table cell
|
||
|
}
|
||
|
|
||
|
while (element.offsetParent){
|
||
|
left += element.offsetLeft;
|
||
|
top += element.offsetTop;
|
||
|
element = element.offsetParent;
|
||
|
}
|
||
|
|
||
|
left += element.offsetLeft;
|
||
|
top += element.offsetTop;
|
||
|
|
||
|
return {x:left, y:top};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Get the mouse coordinates from the event (allowing for browser differences).
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.mouseCoords = function(event){
|
||
|
if (event.pageX || event.pageY) {
|
||
|
return {x:event.pageX, y:event.pageY};
|
||
|
}
|
||
|
return {
|
||
|
x:event.clientX + document.body.scrollLeft - document.body.clientLeft,
|
||
|
y:event.clientY + document.body.scrollTop - document.body.clientTop
|
||
|
};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Given a target element and a mouse event, get the mouse offset from that
|
||
|
* element. To do this we need the element's position and the mouse position.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.getMouseOffset = function(target, event) {
|
||
|
var docPos = this.getPosition(target);
|
||
|
var mousePos = this.mouseCoords(event);
|
||
|
return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Find the row the mouse is currently over. This row is then taken and swapped
|
||
|
* with the one being dragged.
|
||
|
*
|
||
|
* @param x
|
||
|
* The x coordinate of the mouse on the page (not the screen).
|
||
|
* @param y
|
||
|
* The y coordinate of the mouse on the page (not the screen).
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.findDropTargetRow = function(x, y) {
|
||
|
var rows = this.table.tBodies[0].rows;
|
||
|
for (var n=0; n<rows.length; n++) {
|
||
|
var row = rows[n];
|
||
|
var indentDiff = 0;
|
||
|
// Safari fix see Drupal.tableDrag.prototype.getPosition()
|
||
|
if (row.offsetHeight == 0) {
|
||
|
var rowY = this.getPosition(row.firstChild).y;
|
||
|
var rowHeight = parseInt(row.firstChild.offsetHeight)/2;
|
||
|
}
|
||
|
// Other browsers.
|
||
|
else {
|
||
|
var rowY = this.getPosition(row).y;
|
||
|
var rowHeight = parseInt(row.offsetHeight)/2;
|
||
|
}
|
||
|
|
||
|
// Because we always insert before, we need to offset the height a bit.
|
||
|
if ((y > (rowY - rowHeight)) && (y < (rowY + rowHeight))) {
|
||
|
if (this.indentEnabled) {
|
||
|
// Check that this row is not a child of the row being dragged.
|
||
|
for (n in this.rowObject.group) {
|
||
|
if (this.rowObject.group[n] == row) {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// Check that swapping with this row is allowed.
|
||
|
if (!this.rowObject.isValidSwap(row)) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// We may have found the row the mouse just passed over, but it doesn't
|
||
|
// take into account hidden rows. Skip backwards until we find a draggable
|
||
|
// row.
|
||
|
while ($(row).is(':hidden') && $(row).prev('tr').is(':hidden')) {
|
||
|
row = $(row).prev('tr').get(0);
|
||
|
}
|
||
|
return row;
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* After the row is dropped, update the table fields according to the settings
|
||
|
* set for this table.
|
||
|
*
|
||
|
* @param changedRow
|
||
|
* DOM object for the row that was just dropped.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.updateFields = function(changedRow) {
|
||
|
for (var group in this.tableSettings) {
|
||
|
// Each group may have a different setting for relationship, so we find
|
||
|
// the source rows for each seperately.
|
||
|
this.updateField(changedRow, group);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* After the row is dropped, update a single table field according to specific
|
||
|
* settings.
|
||
|
*
|
||
|
* @param changedRow
|
||
|
* DOM object for the row that was just dropped.
|
||
|
* @param group
|
||
|
* The settings group on which field updates will occur.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.updateField = function(changedRow, group) {
|
||
|
var rowSettings = this.rowSettings(group, changedRow);
|
||
|
|
||
|
// Set the row as it's own target.
|
||
|
if (rowSettings.relationship == 'self' || rowSettings.relationship == 'group') {
|
||
|
var sourceRow = changedRow;
|
||
|
}
|
||
|
// Siblings are easy, check previous and next rows.
|
||
|
else if (rowSettings.relationship == 'sibling') {
|
||
|
var previousRow = $(changedRow).prev('tr').get(0);
|
||
|
var nextRow = $(changedRow).next('tr').get(0);
|
||
|
var sourceRow = changedRow;
|
||
|
if ($(previousRow).is('.draggable') && $('.' + group, previousRow).length) {
|
||
|
if (this.indentEnabled) {
|
||
|
if ($('.indentations', previousRow).size() == $('.indentations', changedRow)) {
|
||
|
sourceRow = previousRow;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
sourceRow = previousRow;
|
||
|
}
|
||
|
}
|
||
|
else if ($(nextRow).is('.draggable') && $('.' + group, nextRow).length) {
|
||
|
if (this.indentEnabled) {
|
||
|
if ($('.indentations', nextRow).size() == $('.indentations', changedRow)) {
|
||
|
sourceRow = nextRow;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
sourceRow = nextRow;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// Parents, look up the tree until we find a field not in this group.
|
||
|
// Go up as many parents as indentations in the changed row.
|
||
|
else if (rowSettings.relationship == 'parent') {
|
||
|
var previousRow = $(changedRow).prev('tr');
|
||
|
while (previousRow.length && $('.indentation', previousRow).length >= this.rowObject.indents) {
|
||
|
previousRow = previousRow.prev('tr');
|
||
|
}
|
||
|
// If we found a row.
|
||
|
if (previousRow.length) {
|
||
|
sourceRow = previousRow[0];
|
||
|
}
|
||
|
// Otherwise we went all the way to the left of the table without finding
|
||
|
// a parent, meaning this item has been placed at the root level.
|
||
|
else {
|
||
|
// Use the first row in the table as source, because it's garanteed to
|
||
|
// be at the root level. Find the first item, then compare this row
|
||
|
// against it as a sibling.
|
||
|
sourceRow = $('tr.draggable:first').get(0);
|
||
|
if (sourceRow == this.rowObject.element) {
|
||
|
sourceRow = $(this.rowObject.group[this.rowObject.group.length - 1]).next('tr.draggable').get(0);
|
||
|
}
|
||
|
var useSibling = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Because we may have moved the row from one category to another,
|
||
|
// take a look at our sibling and borrow its sources and targets.
|
||
|
this.copyDragClasses(sourceRow, changedRow, group);
|
||
|
rowSettings = this.rowSettings(group, changedRow);
|
||
|
|
||
|
// In the case that we're looking for a parent, but the row is at the top
|
||
|
// of the tree, copy our sibling's values.
|
||
|
if (useSibling) {
|
||
|
rowSettings.relationship = 'sibling';
|
||
|
rowSettings.source = rowSettings.target;
|
||
|
}
|
||
|
|
||
|
var targetClass = '.' + rowSettings.target;
|
||
|
var targetElement = $(targetClass, changedRow).get(0);
|
||
|
|
||
|
// Check if a target element exists in this row.
|
||
|
if (targetElement) {
|
||
|
var sourceClass = '.' + rowSettings.source;
|
||
|
var sourceElement = $(sourceClass, sourceRow).get(0);
|
||
|
switch (rowSettings.action) {
|
||
|
case 'depth':
|
||
|
// Get the depth of the target row.
|
||
|
targetElement.value = $('.indentation', $(sourceElement).parents('tr:first')).size();
|
||
|
break;
|
||
|
case 'match':
|
||
|
// Update the value.
|
||
|
targetElement.value = sourceElement.value;
|
||
|
break;
|
||
|
case 'order':
|
||
|
var siblings = this.rowObject.findSiblings(rowSettings);
|
||
|
if ($(targetElement).is('select')) {
|
||
|
// Get a list of acceptable values.
|
||
|
var values = new Array();
|
||
|
$('option', targetElement).each(function() {
|
||
|
values.push(this.value);
|
||
|
});
|
||
|
var maxVal = values[values.length - 1];
|
||
|
// Populate the values in the siblings.
|
||
|
$(targetClass, siblings).each(function() {
|
||
|
// If there are more items than possible values, assign the maximum value to the row.
|
||
|
if (values.length > 0) {
|
||
|
this.value = values.shift();
|
||
|
}
|
||
|
else {
|
||
|
this.value = maxVal;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
// Assume a numeric input field.
|
||
|
var weight = parseInt($(targetClass, siblings[0]).val()) || 0;
|
||
|
$(targetClass, siblings).each(function() {
|
||
|
this.value = weight;
|
||
|
weight++;
|
||
|
});
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Copy all special tableDrag classes from one row's form elements to a
|
||
|
* different one, removing any special classes that the destination row
|
||
|
* may have had.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.copyDragClasses = function(sourceRow, targetRow, group) {
|
||
|
var sourceElement = $('.' + group, sourceRow);
|
||
|
var targetElement = $('.' + group, targetRow);
|
||
|
if (sourceElement.length && targetElement.length) {
|
||
|
targetElement[0].className = sourceElement[0].className;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Drupal.tableDrag.prototype.checkScroll = function(cursorY) {
|
||
|
var de = document.documentElement;
|
||
|
var b = document.body;
|
||
|
|
||
|
var windowHeight = this.windowHeight = window.innerHeight || (de.clientHeight && de.clientWidth != 0 ? de.clientHeight : b.offsetHeight);
|
||
|
var scrollY = this.scrollY = (document.all ? (!de.scrollTop ? b.scrollTop : de.scrollTop) : (window.pageYOffset ? window.pageYOffset : window.scrollY));
|
||
|
var trigger = this.scrollSettings.trigger;
|
||
|
var delta = 0;
|
||
|
|
||
|
// Return a scroll speed relative to the edge of the screen.
|
||
|
if (cursorY - scrollY > windowHeight - trigger) {
|
||
|
delta = trigger / (windowHeight + scrollY - cursorY);
|
||
|
delta = (delta > 0 && delta < trigger) ? delta : trigger;
|
||
|
return delta * this.scrollSettings.amount;
|
||
|
}
|
||
|
else if (cursorY - scrollY < trigger) {
|
||
|
delta = trigger / (cursorY - scrollY);
|
||
|
delta = (delta > 0 && delta < trigger) ? delta : trigger;
|
||
|
return -delta * this.scrollSettings.amount;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Drupal.tableDrag.prototype.setScroll = function(scrollAmount) {
|
||
|
var self = this;
|
||
|
|
||
|
this.scrollInterval = setInterval(function() {
|
||
|
// Update the scroll values stored in the object.
|
||
|
self.checkScroll(self.currentMouseCoords.y);
|
||
|
var aboveTable = self.scrollY > self.table.topY;
|
||
|
var belowTable = self.scrollY + self.windowHeight < self.table.bottomY;
|
||
|
if (scrollAmount > 0 && belowTable || scrollAmount < 0 && aboveTable) {
|
||
|
window.scrollBy(0, scrollAmount);
|
||
|
}
|
||
|
}, this.scrollSettings.interval);
|
||
|
};
|
||
|
|
||
|
Drupal.tableDrag.prototype.restripeTable = function() {
|
||
|
// :even and :odd are reversed because jquery counts from 0 and
|
||
|
// we count from 1, so we're out of sync.
|
||
|
// Match immediate children of the parent element to allow nesting.
|
||
|
$('> tbody > tr.draggable, > tr.draggable', this.table)
|
||
|
.filter(':odd').filter('.odd')
|
||
|
.removeClass('odd').addClass('even')
|
||
|
.end().end()
|
||
|
.filter(':even').filter('.even')
|
||
|
.removeClass('even').addClass('odd');
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Stub function. Allows a custom handler when a row begins dragging.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.onDrag = function() {
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Stub function. Allows a custom handler when a row is dropped.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.onDrop = function() {
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Constructor to make a new object to manipulate a table row.
|
||
|
*
|
||
|
* @param tableRow
|
||
|
* The DOM element for the table row we will be manipulating.
|
||
|
* @param method
|
||
|
* The method in which this row is being moved. Either 'keyboard' or 'mouse'.
|
||
|
* @param indentEnabled
|
||
|
* Whether the containing table uses indentations. Used for optimizations.
|
||
|
* @param maxDepth
|
||
|
* The maximum amount of indentations this row may contain.
|
||
|
* @param addClasses
|
||
|
* Whether we want to add classes to this row to indicate child relationships.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row = function(tableRow, method, indentEnabled, maxDepth, addClasses) {
|
||
|
this.element = tableRow;
|
||
|
this.method = method;
|
||
|
this.group = new Array(tableRow);
|
||
|
this.groupDepth = $('.indentation', tableRow).size();
|
||
|
this.changed = false;
|
||
|
this.table = $(tableRow).parents('table:first').get(0);
|
||
|
this.indentEnabled = indentEnabled;
|
||
|
this.maxDepth = maxDepth;
|
||
|
this.direction = ''; // Direction the row is being moved.
|
||
|
|
||
|
if (this.indentEnabled) {
|
||
|
this.indents = $('.indentation', tableRow).size();
|
||
|
this.children = this.findChildren(addClasses);
|
||
|
this.group = $.merge(this.group, this.children);
|
||
|
// Find the depth of this entire group.
|
||
|
for (var n = 0; n < this.group.length; n++) {
|
||
|
this.groupDepth = Math.max($('.indentation', this.group[n]).size(), this.groupDepth);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Find all children of rowObject by indentation.
|
||
|
*
|
||
|
* @param addClasses
|
||
|
* Whether we want to add classes to this row to indicate child relationships.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.findChildren = function(addClasses) {
|
||
|
var parentIndentation = this.indents;
|
||
|
var currentRow = $(this.element, this.table).next('tr.draggable');
|
||
|
var rows = new Array();
|
||
|
var child = 0;
|
||
|
while (currentRow.length) {
|
||
|
var rowIndentation = $('.indentation', currentRow).length;
|
||
|
// A greater indentation indicates this is a child.
|
||
|
if (rowIndentation > parentIndentation) {
|
||
|
child++;
|
||
|
rows.push(currentRow[0]);
|
||
|
if (addClasses) {
|
||
|
$('.indentation', currentRow).each(function(indentNum) {
|
||
|
if (child == 1 && (indentNum == parentIndentation)) {
|
||
|
$(this).addClass('tree-child-first');
|
||
|
}
|
||
|
if (indentNum == parentIndentation) {
|
||
|
$(this).addClass('tree-child');
|
||
|
}
|
||
|
else if (indentNum > parentIndentation) {
|
||
|
$(this).addClass('tree-child-horizontal');
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
break;
|
||
|
}
|
||
|
currentRow = currentRow.next('tr.draggable');
|
||
|
}
|
||
|
if (addClasses && rows.length) {
|
||
|
$('.indentation:nth-child(' + (parentIndentation + 1) + ')', rows[rows.length - 1]).addClass('tree-child-last');
|
||
|
}
|
||
|
return rows;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Ensure that two rows are allowed to be swapped.
|
||
|
*
|
||
|
* @param row
|
||
|
* DOM object for the row being considered for swapping.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.isValidSwap = function(row) {
|
||
|
if (this.indentEnabled) {
|
||
|
var prevRow, nextRow;
|
||
|
if (this.direction == 'down') {
|
||
|
prevRow = row;
|
||
|
nextRow = $(row).next('tr').get(0);
|
||
|
}
|
||
|
else {
|
||
|
prevRow = $(row).prev('tr').get(0);
|
||
|
nextRow = row;
|
||
|
}
|
||
|
this.interval = this.validIndentInterval(prevRow, nextRow);
|
||
|
|
||
|
// We have an invalid swap if the valid indentations interval is empty.
|
||
|
if (this.interval.min > this.interval.max) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Do not let an un-draggable first row have anything put before it.
|
||
|
if (this.table.tBodies[0].rows[0] == row && $(row).is(':not(.draggable)')) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Perform the swap between two rows.
|
||
|
*
|
||
|
* @param position
|
||
|
* Whether the swap will occur 'before' or 'after' the given row.
|
||
|
* @param row
|
||
|
* DOM element what will be swapped with the row group.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.swap = function(position, row) {
|
||
|
$(row)[position](this.group);
|
||
|
this.changed = true;
|
||
|
this.onSwap(row);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Determine the valid indentations interval for the row at a given position
|
||
|
* in the table.
|
||
|
*
|
||
|
* @param prevRow
|
||
|
* DOM object for the row before the tested position
|
||
|
* (or null for first position in the table).
|
||
|
* @param nextRow
|
||
|
* DOM object for the row after the tested position
|
||
|
* (or null for last position in the table).
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.validIndentInterval = function (prevRow, nextRow) {
|
||
|
var minIndent, maxIndent;
|
||
|
|
||
|
// Minimum indentation:
|
||
|
// Do not orphan the next row.
|
||
|
minIndent = nextRow ? $('.indentation', nextRow).size() : 0;
|
||
|
|
||
|
// Maximum indentation:
|
||
|
if (!prevRow || $(this.element).is('.tabledrag-root')) {
|
||
|
// Do not indent the first row in the table or 'root' rows..
|
||
|
maxIndent = 0;
|
||
|
}
|
||
|
else {
|
||
|
// Do not go deeper than as a child of the previous row.
|
||
|
maxIndent = $('.indentation', prevRow).size() + ($(prevRow).is('.tabledrag-leaf') ? 0 : 1);
|
||
|
// Limit by the maximum allowed depth for the table.
|
||
|
if (this.maxDepth) {
|
||
|
maxIndent = Math.min(maxIndent, this.maxDepth - (this.groupDepth - this.indents));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return {'min':minIndent, 'max':maxIndent};
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indent a row within the legal bounds of the table.
|
||
|
*
|
||
|
* @param indentDiff
|
||
|
* The number of additional indentations proposed for the row (can be
|
||
|
* positive or negative). This number will be adjusted to nearest valid
|
||
|
* indentation level for the row.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.indent = function(indentDiff) {
|
||
|
// Determine the valid indentations interval if not available yet.
|
||
|
if (!this.interval) {
|
||
|
prevRow = $(this.element).prev('tr').get(0);
|
||
|
nextRow = $(this.group).filter(':last').next('tr').get(0);
|
||
|
this.interval = this.validIndentInterval(prevRow, nextRow);
|
||
|
}
|
||
|
|
||
|
// Adjust to the nearest valid indentation.
|
||
|
var indent = this.indents + indentDiff;
|
||
|
indent = Math.max(indent, this.interval.min);
|
||
|
indent = Math.min(indent, this.interval.max);
|
||
|
indentDiff = indent - this.indents;
|
||
|
|
||
|
for (var n = 1; n <= Math.abs(indentDiff); n++) {
|
||
|
// Add or remove indentations.
|
||
|
if (indentDiff < 0) {
|
||
|
$('.indentation:first', this.group).remove();
|
||
|
this.indents--;
|
||
|
}
|
||
|
else {
|
||
|
$('td:first', this.group).prepend(Drupal.theme('tableDragIndentation'));
|
||
|
this.indents++;
|
||
|
}
|
||
|
}
|
||
|
if (indentDiff) {
|
||
|
// Update indentation for this row.
|
||
|
this.changed = true;
|
||
|
this.groupDepth += indentDiff;
|
||
|
this.onIndent();
|
||
|
}
|
||
|
|
||
|
return indentDiff;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Find all siblings for a row, either according to its subgroup or indentation.
|
||
|
* Note that the passed in row is included in the list of siblings.
|
||
|
*
|
||
|
* @param settings
|
||
|
* The field settings we're using to identify what constitutes a sibling.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.findSiblings = function(rowSettings) {
|
||
|
var siblings = new Array();
|
||
|
var directions = new Array('prev', 'next');
|
||
|
var rowIndentation = this.indents;
|
||
|
for (var d in directions) {
|
||
|
var checkRow = $(this.element)[directions[d]]();
|
||
|
while (checkRow.length) {
|
||
|
// Check that the sibling contains a similar target field.
|
||
|
if ($('.' + rowSettings.target, checkRow)) {
|
||
|
// Either add immediately if this is a flat table, or check to ensure
|
||
|
// that this row has the same level of indentaiton.
|
||
|
if (this.indentEnabled) {
|
||
|
var checkRowIndentation = $('.indentation', checkRow).length
|
||
|
}
|
||
|
|
||
|
if (!(this.indentEnabled) || (checkRowIndentation == rowIndentation)) {
|
||
|
siblings.push(checkRow[0]);
|
||
|
}
|
||
|
else if (checkRowIndentation < rowIndentation) {
|
||
|
// No need to keep looking for siblings when we get to a parent.
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
break;
|
||
|
}
|
||
|
checkRow = $(checkRow)[directions[d]]();
|
||
|
}
|
||
|
// Since siblings are added in reverse order for previous, reverse the
|
||
|
// completed list of previous siblings. Add the current row and continue.
|
||
|
if (directions[d] == 'prev') {
|
||
|
siblings.reverse();
|
||
|
siblings.push(this.element);
|
||
|
}
|
||
|
}
|
||
|
return siblings;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Remove indentation helper classes from the current row group.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.removeIndentClasses = function() {
|
||
|
for (n in this.children) {
|
||
|
$('.indentation', this.children[n])
|
||
|
.removeClass('tree-child')
|
||
|
.removeClass('tree-child-first')
|
||
|
.removeClass('tree-child-last')
|
||
|
.removeClass('tree-child-horizontal');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Add an asterisk or other marker to the changed row.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.markChanged = function() {
|
||
|
var marker = Drupal.theme('tableDragChangedMarker');
|
||
|
var cell = $('td:first', this.element);
|
||
|
if ($('span.tabledrag-changed', cell).length == 0) {
|
||
|
cell.append(marker);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Stub function. Allows a custom handler when a row is indented.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.onIndent = function() {
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Stub function. Allows a custom handler when a row is swapped.
|
||
|
*/
|
||
|
Drupal.tableDrag.prototype.row.prototype.onSwap = function(swappedRow) {
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
Drupal.theme.prototype.tableDragChangedMarker = function () {
|
||
|
return '<span class="warning tabledrag-changed">*</span>';
|
||
|
};
|
||
|
|
||
|
Drupal.theme.prototype.tableDragIndentation = function () {
|
||
|
return '<div class="indentation"> </div>';
|
||
|
};
|
||
|
|
||
|
Drupal.theme.prototype.tableDragChangedWarning = function () {
|
||
|
return '<div class="warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t("Changes made in this table will not be saved until the form is submitted.") + '</div>';
|
||
|
};
|
||
|
;/* $Id: lightbox.js,v 1.5.2.6.2.73 2008/06/29 15:25:12 snpower Exp $ */
|
||
|
|
||
|
/**
|
||
|
* jQuery Lightbox
|
||
|
* @author
|
||
|
* Stella Power, <http://drupal.org/user/66894>
|
||
|
*
|
||
|
* Based on Lightbox v2.03.3 by Lokesh Dhakar
|
||
|
* <http://www.huddletogether.com/projects/lightbox2/>
|
||
|
* Also partially based on the jQuery Lightbox by Warren Krewenki
|
||
|
* <http://warren.mesozen.com>
|
||
|
*
|
||
|
* Permission has been granted to Mark Ashmead & other Drupal Lightbox2 module
|
||
|
* maintainers to distribute this file via Drupal.org
|
||
|
* Under GPL license.
|
||
|
*
|
||
|
* Slideshow, iframe and video functionality added by Stella Power.
|
||
|
*/
|
||
|
|
||
|
var Lightbox = {
|
||
|
overlayOpacity : 0.8, // Controls transparency of shadow overlay.
|
||
|
overlayColor : '000', // Controls colour of shadow overlay.
|
||
|
// Controls the order of the lightbox resizing animation sequence.
|
||
|
resizeSequence: 0, // 0: simultaneous, 1: width then height, 2: height then width.
|
||
|
resizeSpeed: 'normal', // Controls the speed of the lightbox resizing animation.
|
||
|
fadeInSpeed: 'normal', // Controls the speed of the image appearance.
|
||
|
slideDownSpeed: 'slow', // Controls the speed of the image details appearance.
|
||
|
borderSize : 10,
|
||
|
boxColor : 'fff',
|
||
|
fontColor : '000',
|
||
|
topPosition : '',
|
||
|
infoHeight: 20,
|
||
|
alternative_layout : false,
|
||
|
imageArray : [],
|
||
|
imageNum : null,
|
||
|
total : 0,
|
||
|
activeImage : null,
|
||
|
inprogress : false,
|
||
|
disableResize : false,
|
||
|
disableZoom : false,
|
||
|
isZoomedIn : false,
|
||
|
rtl : false,
|
||
|
loopItems : false,
|
||
|
|
||
|
// Slideshow options.
|
||
|
slideInterval : 5000, // In milliseconds.
|
||
|
showPlayPause : true,
|
||
|
autoExit : true,
|
||
|
pauseOnNextClick : false, // True to pause the slideshow when the "Next" button is clicked.
|
||
|
pauseOnPrevClick : true, // True to pause the slideshow when the "Prev" button is clicked.
|
||
|
slideIdArray : [],
|
||
|
slideIdCount : 0,
|
||
|
isSlideshow : false,
|
||
|
isPaused : false,
|
||
|
loopSlides : false,
|
||
|
|
||
|
// Iframe options.
|
||
|
isLightframe : false,
|
||
|
iframe_width : 600,
|
||
|
iframe_height : 400,
|
||
|
iframe_border : 1,
|
||
|
|
||
|
// Video and modal options.
|
||
|
enableVideo : false,
|
||
|
isModal : false,
|
||
|
isVideo : false,
|
||
|
videoId : false,
|
||
|
modalWidth : 400,
|
||
|
modalHeight : 400,
|
||
|
modalHTML : null,
|
||
|
|
||
|
|
||
|
// initialize()
|
||
|
// Constructor runs on completion of the DOM loading. Calls initList
|
||
|
// and then the function inserts html at the bottom of the page which is used
|
||
|
// to display the shadow overlay and the image container.
|
||
|
initialize: function() {
|
||
|
|
||
|
var s = Drupal.settings.lightbox2;
|
||
|
Lightbox.overlayOpacity = s.overlay_opacity;
|
||
|
Lightbox.overlayColor = s.overlay_color;
|
||
|
Lightbox.resizeSequence = s.resize_sequence;
|
||
|
Lightbox.resizeSpeed = s.resize_speed;
|
||
|
Lightbox.fadeInSpeed = s.fade_in_speed;
|
||
|
Lightbox.slideDownSpeed = s.slide_down_speed;
|
||
|
Lightbox.borderSize = s.border_size;
|
||
|
Lightbox.boxColor = s.box_color;
|
||
|
Lightbox.fontColor = s.font_color;
|
||
|
Lightbox.topPosition = s.top_position;
|
||
|
Lightbox.rtl = s.rtl;
|
||
|
Lightbox.loopItems = s.loop_items;
|
||
|
Lightbox.disableResize = s.disable_resize;
|
||
|
Lightbox.disableZoom = s.disable_zoom;
|
||
|
Lightbox.slideInterval = s.slideshow_interval;
|
||
|
Lightbox.showPlayPause = s.show_play_pause;
|
||
|
Lightbox.autoExit = s.slideshow_automatic_exit;
|
||
|
Lightbox.pauseOnNextClick = s.pause_on_next_click;
|
||
|
Lightbox.pauseOnPrevClick = s.pause_on_previous_click;
|
||
|
Lightbox.loopSlides = s.loop_slides;
|
||
|
Lightbox.alternative_layout = s.use_alt_layout;
|
||
|
Lightbox.iframe_width = s.iframe_width;
|
||
|
Lightbox.iframe_height = s.iframe_height;
|
||
|
Lightbox.iframe_border = s.iframe_border;
|
||
|
Lightbox.enableVideo = s.enable_video;
|
||
|
|
||
|
// Attach lightbox to any links with lightbox rels.
|
||
|
Lightbox.initList();
|
||
|
|
||
|
// Make the lightbox divs.
|
||
|
var output = '<div id="overlay" style="display: none;"></div>\
|
||
|
<div id="lightbox" style="display: none;">\
|
||
|
<div id="outerImageContainer"></div>\
|
||
|
<div id="imageDataContainer" class="clearfix">\
|
||
|
<div id="imageData"></div>\
|
||
|
</div>\
|
||
|
</div>';
|
||
|
var loading = '<div id="loading"><a href="#" id="loadingLink"></a></div>';
|
||
|
var modal = '<div id="modalContainer" style="display: none;"></div>';
|
||
|
var frame = '<div id="frameContainer" style="display: none;"><iframe id="lightboxFrame" style="display: none;"></iframe></div>';
|
||
|
var imageContainer = '<div id="imageContainer" style="display: none;"></div>';
|
||
|
var details = '<div id="imageDetails"></div>';
|
||
|
var bottomNav = '<div id="bottomNav"></div>';
|
||
|
var image = '<img id="lightboxImage" />';
|
||
|
var hoverNav = '<div id="hoverNav"><a id="prevLink" href="#"></a><a id="nextLink" href="#"></a></div>';
|
||
|
var frameNav = '<div id="frameHoverNav"><a id="framePrevLink" href="#"></a><a id="frameNextLink" href="#"></a></div>';
|
||
|
var caption = '<span id="caption"></span>';
|
||
|
var numberDisplay = '<span id="numberDisplay"></span>';
|
||
|
var close = '<a id="bottomNavClose" href="#"></a>';
|
||
|
var zoom = '<a id="bottomNavZoom" href="#"></a>';
|
||
|
var zoomOut = '<a id="bottomNavZoomOut" href="#"></a>';
|
||
|
var pause = '<a id="lightshowPause" href="#" style="display: none;"></a>';
|
||
|
var play = '<a id="lightshowPlay" href="#" style="display: none;"></a>';
|
||
|
|
||
|
$("body").append(output);
|
||
|
$('#outerImageContainer').append(modal + frame + imageContainer + loading);
|
||
|
if (!s.use_alt_layout) {
|
||
|
$('#imageContainer').append(image + hoverNav);
|
||
|
$('#imageData').append(frameNav + details + bottomNav);
|
||
|
$('#imageDetails').append(caption + numberDisplay);
|
||
|
$('#bottomNav').append(close + zoom + zoomOut + pause + play);
|
||
|
}
|
||
|
else {
|
||
|
$('#imageContainer').append(image + bottomNav);
|
||
|
$('#bottomNav').append(close + zoom + zoomOut);
|
||
|
$('#imageData').append(hoverNav + details);
|
||
|
$('#imageDetails').append(caption + numberDisplay + pause + play);
|
||
|
}
|
||
|
|
||
|
// Setup onclick handlers.
|
||
|
$('#overlay').click(function() { Lightbox.end(); return false; } ).hide();
|
||
|
$('#loadingLink, #bottomNavClose').click(function() { Lightbox.end('forceClose'); return false; } );
|
||
|
$('#prevLink, #framePrevLink').click(function() { Lightbox.changeData(Lightbox.activeImage - 1); return false; } );
|
||
|
$('#nextLink, #frameNextLink').click(function() { Lightbox.changeData(Lightbox.activeImage + 1); return false; } );
|
||
|
$('#bottomNavZoom').click(function() { Lightbox.changeData(Lightbox.activeImage, true); return false; } );
|
||
|
$('#bottomNavZoomOut').click(function() { Lightbox.changeData(Lightbox.activeImage, false); return false; } );
|
||
|
$('#lightshowPause').click(function() { Lightbox.togglePlayPause("lightshowPause", "lightshowPlay"); return false; } );
|
||
|
$('#lightshowPlay').click(function() { Lightbox.togglePlayPause("lightshowPlay", "lightshowPause"); return false; } );
|
||
|
|
||
|
// Fix positioning.
|
||
|
$('#prevLink, #nextLink, #framePrevLink, #frameNextLink').css({ paddingTop: Lightbox.borderSize + 'px'});
|
||
|
$('#imageContainer, #frameContainer, #modalContainer').css({ padding: Lightbox.borderSize + 'px'});
|
||
|
$('#outerImageContainer, #imageDataContainer, #bottomNavClose').css({backgroundColor: '#' + Lightbox.boxColor, color: '#'+Lightbox.fontColor});
|
||
|
|
||
|
if (!Lightbox.iframe_border) {
|
||
|
$('#lightboxFrame').css({border: 'none'});
|
||
|
$('#lightboxFrame').attr("frameborder", '0');
|
||
|
}
|
||
|
|
||
|
// Force navigation links to always be displayed
|
||
|
if (s.force_show_nav) {
|
||
|
$('#prevLink, #nextLink').addClass("force_show_nav");
|
||
|
}
|
||
|
|
||
|
},
|
||
|
|
||
|
// initList()
|
||
|
// Loops through anchor tags looking for 'lightbox', 'lightshow' and
|
||
|
// 'lightframe', etc, references and applies onclick events to appropriate
|
||
|
// links. You can rerun after dynamically adding images w/ajax.
|
||
|
initList : function() {
|
||
|
|
||
|
// Attach lightbox to any links with rel 'lightbox', 'lightshow' or
|
||
|
// 'lightframe', etc.
|
||
|
$("a[@rel^='lightbox'], area[@rel^='lightbox']").click(function(e) {
|
||
|
$('#lightbox').click(function() { Lightbox.end('forceClose'); } );
|
||
|
Lightbox.start(this, false, false, false, false);
|
||
|
if (e.preventDefault) { e.preventDefault(); }
|
||
|
return false;
|
||
|
});
|
||
|
$("a[@rel^='lightshow'], area[@rel^='lightshow']").click(function(e) {
|
||
|
$('#lightbox').click(function() { Lightbox.end('forceClose'); } );
|
||
|
Lightbox.start(this, true, false, false, false);
|
||
|
if (e.preventDefault) { e.preventDefault(); }
|
||
|
return false;
|
||
|
});
|
||
|
$("a[@rel^='lightframe'], area[@rel^='lightframe']").click(function(e) {
|
||
|
$('#lightbox').click(function() { Lightbox.end('forceClose'); } );
|
||
|
Lightbox.start(this, false, true, false, false);
|
||
|
if (e.preventDefault) { e.preventDefault(); }
|
||
|
return false;
|
||
|
});
|
||
|
$("a[@rel^='lightvideo'], area[@rel^='lightvideo']").click(function(e) {
|
||
|
$('#lightbox').click(function() { Lightbox.end('forceClose'); } );
|
||
|
Lightbox.start(this, false, false, true, false);
|
||
|
if (e.preventDefault) { e.preventDefault(); }
|
||
|
return false;
|
||
|
});
|
||
|
$("a[@rel^='lightmodal'], area[@rel^='lightmodal']").click(function(e) {
|
||
|
$('#lightbox').unbind('click');
|
||
|
Lightbox.start(this, false, false, false, true);
|
||
|
if (e.preventDefault) { e.preventDefault(); }
|
||
|
return false;
|
||
|
});
|
||
|
},
|
||
|
|
||
|
// start()
|
||
|
// Display overlay and lightbox. If image is part of a set, add siblings to
|
||
|
// imageArray.
|
||
|
start: function(imageLink, slideshow, lightframe, lightvideo, lightmodal) {
|
||
|
|
||
|
Lightbox.isPaused = false;
|
||
|
|
||
|
// Replaces hideSelectBoxes() and hideFlash() calls in original lightbox2.
|
||
|
Lightbox.toggleSelectsFlash('hide');
|
||
|
|
||
|
// Stretch overlay to fill page and fade in.
|
||
|
var arrayPageSize = Lightbox.getPageSize();
|
||
|
$("#overlay").hide().css({
|
||
|
width: '100%',
|
||
|
zIndex: '10090',
|
||
|
height: arrayPageSize[1] + 'px',
|
||
|
backgroundColor : '#' + Lightbox.overlayColor,
|
||
|
opacity : Lightbox.overlayOpacity
|
||
|
}).fadeIn(Lightbox.fadeInSpeed);
|
||
|
|
||
|
Lightbox.isSlideshow = slideshow;
|
||
|
Lightbox.isLightframe = lightframe;
|
||
|
Lightbox.isVideo = lightvideo;
|
||
|
Lightbox.isModal = lightmodal;
|
||
|
Lightbox.imageArray = [];
|
||
|
Lightbox.imageNum = 0;
|
||
|
|
||
|
var anchors = $(imageLink.tagName);
|
||
|
var anchor = null;
|
||
|
var rel_parts = Lightbox.parseRel(imageLink);
|
||
|
var rel = rel_parts["rel"];
|
||
|
var rel_group = rel_parts["group"];
|
||
|
var title = (rel_parts["title"] ? rel_parts["title"] : imageLink.title);
|
||
|
var rel_style = null;
|
||
|
var i = 0;
|
||
|
|
||
|
// Handle lightbox images with no grouping.
|
||
|
if ((rel == 'lightbox' || rel == 'lightshow') && !rel_group) {
|
||
|
Lightbox.imageArray.push([imageLink.href, title]);
|
||
|
}
|
||
|
|
||
|
// Handle iframes with no grouping.
|
||
|
else if ((rel == 'lightframe' || rel == 'lightmodal') && !rel_group) {
|
||
|
rel_style = (!rel_parts["style"] ? 'width: '+ Lightbox.iframe_width +'px; height: '+ Lightbox.iframe_height +'px; scrolling: auto;' : rel_parts["style"]);
|
||
|
Lightbox.imageArray.push([imageLink.href, title, rel_style]);
|
||
|
}
|
||
|
|
||
|
// Handle video.
|
||
|
else if (rel == "lightvideo") {
|
||
|
// rel_group contains style information for videos.
|
||
|
rel_style = (!rel_group ? 'width: 400px; height: 400px;' : rel_group);
|
||
|
Lightbox.imageArray.push([imageLink.href, title, rel_style]);
|
||
|
}
|
||
|
|
||
|
// Handle iframes and lightbox & slideshow images.
|
||
|
else if (rel == 'lightbox' || rel == 'lightshow' || rel == 'lightframe' || rel == 'lightmodal') {
|
||
|
|
||
|
// Loop through anchors and add them to imageArray.
|
||
|
for (i = 0; i < anchors.length; i++) {
|
||
|
anchor = anchors[i];
|
||
|
if (anchor.href && $(anchor).attr('rel')) {
|
||
|
var rel_data = Lightbox.parseRel(anchor);
|
||
|
var anchor_title = (rel_data["title"] ? rel_data["title"] : anchor.title);
|
||
|
if (rel_data["rel"] == rel) {
|
||
|
if (rel_data["group"] == rel_group) {
|
||
|
if (Lightbox.isLightframe || Lightbox.isModal) {
|
||
|
rel_style = (!rel_data["style"] ? 'width: '+ Lightbox.iframe_width +'px; height: '+ Lightbox.iframe_height +'px; scrolling: auto;' : rel_data["style"]);
|
||
|
}
|
||
|
Lightbox.imageArray.push([anchor.href, anchor_title, rel_style]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Remove duplicates.
|
||
|
for (i = 0; i < Lightbox.imageArray.length; i++) {
|
||
|
for (j = Lightbox.imageArray.length-1; j > i; j--) {
|
||
|
if (Lightbox.imageArray[i][0] == Lightbox.imageArray[j][0]) {
|
||
|
Lightbox.imageArray.splice(j,1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (Lightbox.imageArray[Lightbox.imageNum][0] != imageLink.href) {
|
||
|
Lightbox.imageNum++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Lightbox.isSlideshow && Lightbox.showPlayPause && Lightbox.isPaused) {
|
||
|
$('#lightshowPlay').show();
|
||
|
$('#lightshowPause').hide();
|
||
|
}
|
||
|
|
||
|
// Calculate top and left offset for the lightbox.
|
||
|
var arrayPageScroll = Lightbox.getPageScroll();
|
||
|
var lightboxTop = arrayPageScroll[1] + (Lightbox.topPosition == '' ? (arrayPageSize[3] / 10) : Lightbox.topPosition) * 1;
|
||
|
var lightboxLeft = arrayPageScroll[0];
|
||
|
$('#lightbox').css({
|
||
|
zIndex: '10500',
|
||
|
top: lightboxTop + 'px',
|
||
|
left: lightboxLeft + 'px'
|
||
|
}).show();
|
||
|
|
||
|
Lightbox.total = Lightbox.imageArray.length;
|
||
|
Lightbox.changeData(Lightbox.imageNum);
|
||
|
},
|
||
|
|
||
|
// changeData()
|
||
|
// Hide most elements and preload image in preparation for resizing image
|
||
|
// container.
|
||
|
changeData: function(imageNum, zoomIn) {
|
||
|
|
||
|
if (Lightbox.inprogress === false) {
|
||
|
if (Lightbox.total > 1 && ((Lightbox.isSlideshow && Lightbox.loopSlides) || (!Lightbox.isSlideshow && Lightbox.loopItems))) {
|
||
|
if (imageNum >= Lightbox.total) imageNum = 0;
|
||
|
if (imageNum < 0) imageNum = Lightbox.total - 1;
|
||
|
}
|
||
|
|
||
|
if (Lightbox.isSlideshow) {
|
||
|
for (var i = 0; i < Lightbox.slideIdCount; i++) {
|
||
|
window.clearTimeout(Lightbox.slideIdArray[i]);
|
||
|
}
|
||
|
}
|
||
|
Lightbox.inprogress = true;
|
||
|
Lightbox.activeImage = imageNum;
|
||
|
|
||
|
if (Lightbox.disableResize && !Lightbox.isSlideshow) {
|
||
|
zoomIn = true;
|
||
|
}
|
||
|
Lightbox.isZoomedIn = zoomIn;
|
||
|
|
||
|
|
||
|
// Hide elements during transition.
|
||
|
$('#loading').css({zIndex: '10500'}).show();
|
||
|
if (!Lightbox.alternative_layout) {
|
||
|
$('#imageContainer').hide();
|
||
|
}
|
||
|
$('#frameContainer, #modalContainer, #lightboxImage, #lightboxFrame').hide();
|
||
|
$('#hoverNav, #prevLink, #nextLink, #frameHoverNav, #framePrevLink, #frameNextLink').hide();
|
||
|
$('#imageDataContainer, #numberDisplay, #bottomNavZoom, #bottomNavZoomOut').hide();
|
||
|
|
||
|
// Preload image content, but not iframe pages.
|
||
|
if (!Lightbox.isLightframe && !Lightbox.isVideo && !Lightbox.isModal) {
|
||
|
imgPreloader = new Image();
|
||
|
imgPreloader.onerror = function() { Lightbox.imgNodeLoadingError(this); };
|
||
|
|
||
|
imgPreloader.onload = function() {
|
||
|
var photo = document.getElementById('lightboxImage');
|
||
|
photo.src = Lightbox.imageArray[Lightbox.activeImage][0];
|
||
|
photo.alt = Lightbox.imageArray[Lightbox.activeImage][1];
|
||
|
|
||
|
var imageWidth = imgPreloader.width;
|
||
|
var imageHeight = imgPreloader.height;
|
||
|
|
||
|
// Resize code.
|
||
|
var arrayPageSize = Lightbox.getPageSize();
|
||
|
var targ = { w:arrayPageSize[2] - (Lightbox.borderSize * 2), h:arrayPageSize[3] - (Lightbox.borderSize * 6) - (Lightbox.infoHeight * 4) - (arrayPageSize[3] / 10) };
|
||
|
var orig = { w:imgPreloader.width, h:imgPreloader.height };
|
||
|
|
||
|
// Image is very large, so show a smaller version of the larger image
|
||
|
// with zoom button.
|
||
|
if (zoomIn !== true) {
|
||
|
var ratio = 1.0; // Shrink image with the same aspect.
|
||
|
$('#bottomNavZoomOut, #bottomNavZoom').hide();
|
||
|
if ((orig.w >= targ.w || orig.h >= targ.h) && orig.h && orig.w) {
|
||
|
ratio = ((targ.w / orig.w) < (targ.h / orig.h)) ? targ.w / orig.w : targ.h / orig.h;
|
||
|
if (!Lightbox.disableZoom && !Lightbox.isSlideshow) {
|
||
|
$('#bottomNavZoom').css({zIndex: '10500'}).show();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
imageWidth = Math.floor(orig.w * ratio);
|
||
|
imageHeight = Math.floor(orig.h * ratio);
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
$('#bottomNavZoom').hide();
|
||
|
// Only display zoom out button if the image is zoomed in already.
|
||
|
if ((orig.w >= targ.w || orig.h >= targ.h) && orig.h && orig.w) {
|
||
|
// Only display zoom out button if not a slideshow and if the
|
||
|
// buttons aren't disabled.
|
||
|
if (!Lightbox.disableResize && Lightbox.isSlideshow === false && !Lightbox.disableZoom) {
|
||
|
$('#bottomNavZoomOut').css({zIndex: '10500'}).show();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
photo.style.width = (imageWidth) + 'px';
|
||
|
photo.style.height = (imageHeight) + 'px';
|
||
|
Lightbox.resizeContainer(imageWidth, imageHeight);
|
||
|
|
||
|
// Clear onLoad, IE behaves irratically with animated gifs otherwise.
|
||
|
imgPreloader.onload = function() {};
|
||
|
};
|
||
|
|
||
|
imgPreloader.src = Lightbox.imageArray[Lightbox.activeImage][0];
|
||
|
imgPreloader.alt = Lightbox.imageArray[Lightbox.activeImage][1];
|
||
|
}
|
||
|
|
||
|
// Set up frame size, etc.
|
||
|
else if (Lightbox.isLightframe) {
|
||
|
var iframe = document.getElementById('lightboxFrame');
|
||
|
var iframeStyles = Lightbox.imageArray[Lightbox.activeImage][2];
|
||
|
iframe = Lightbox.setStyles(iframe, iframeStyles);
|
||
|
Lightbox.resizeContainer(parseInt(iframe.width, 10), parseInt(iframe.height, 10));
|
||
|
}
|
||
|
else if (Lightbox.isVideo || Lightbox.isModal) {
|
||
|
var container = document.getElementById('modalContainer');
|
||
|
var modalStyles = Lightbox.imageArray[Lightbox.activeImage][2];
|
||
|
container = Lightbox.setStyles(container, modalStyles);
|
||
|
if (Lightbox.isVideo) {
|
||
|
Lightbox.modalHeight = parseInt(container.height, 10);
|
||
|
Lightbox.modalWidth = parseInt(container.width, 10);
|
||
|
Lightvideo.startVideo(Lightbox.imageArray[Lightbox.activeImage][0]);
|
||
|
}
|
||
|
Lightbox.resizeContainer(parseInt(container.width, 10), parseInt(container.height, 10));
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
// imgNodeLoadingError()
|
||
|
imgNodeLoadingError: function(image) {
|
||
|
var s = Drupal.settings.lightbox2;
|
||
|
var original_image = Lightbox.imageArray[Lightbox.activeImage][0];
|
||
|
if (s.display_image_size !== "") {
|
||
|
original_image = original_image.replace(new RegExp("."+s.display_image_size), "");
|
||
|
}
|
||
|
Lightbox.imageArray[Lightbox.activeImage][0] = original_image;
|
||
|
image.onerror = function() { Lightbox.imgLoadingError(image); };
|
||
|
image.src = original_image;
|
||
|
},
|
||
|
|
||
|
// imgLoadingError()
|
||
|
imgLoadingError: function(image) {
|
||
|
var s = Drupal.settings.lightbox2;
|
||
|
Lightbox.imageArray[Lightbox.activeImage][0] = s.default_image;
|
||
|
image.src = s.default_image;
|
||
|
},
|
||
|
|
||
|
// resizeContainer()
|
||
|
resizeContainer: function(imgWidth, imgHeight) {
|
||
|
|
||
|
this.widthCurrent = $('#outerImageContainer').width();
|
||
|
this.heightCurrent = $('#outerImageContainer').height();
|
||
|
|
||
|
var widthNew = (imgWidth + (Lightbox.borderSize * 2));
|
||
|
var heightNew = (imgHeight + (Lightbox.borderSize * 2));
|
||
|
|
||
|
// Scalars based on change from old to new.
|
||
|
this.xScale = ( widthNew / this.widthCurrent) * 100;
|
||
|
this.yScale = ( heightNew / this.heightCurrent) * 100;
|
||
|
|
||
|
// Calculate size difference between new and old image, and resize if
|
||
|
// necessary.
|
||
|
wDiff = this.widthCurrent - widthNew;
|
||
|
hDiff = this.heightCurrent - heightNew;
|
||
|
|
||
|
// Detect animation sequence.
|
||
|
if (Lightbox.resizeSequence) {
|
||
|
var animate1 = {width: widthNew};
|
||
|
var animate2 = {height: heightNew};
|
||
|
if (Lightbox.resizeSequence == 2) {
|
||
|
animate1 = {height: heightNew};
|
||
|
animate2 = {width: widthNew};
|
||
|
}
|
||
|
$('#outerImageContainer').animate(animate1, Lightbox.resizeSpeed).animate(animate2, Lightbox.resizeSpeed, 'linear', function() { Lightbox.showData(); });
|
||
|
}
|
||
|
// Simultaneous.
|
||
|
else {
|
||
|
$('#outerImageContainer').animate({width: widthNew, height: heightNew}, Lightbox.resizeSpeed, 'linear', function() { Lightbox.showData(); });
|
||
|
}
|
||
|
|
||
|
// If new and old image are same size and no scaling transition is necessary
|
||
|
// do a quick pause to prevent image flicker.
|
||
|
if ((hDiff === 0) && (wDiff === 0)) {
|
||
|
if ($.browser.msie) {
|
||
|
Lightbox.pause(250);
|
||
|
}
|
||
|
else {
|
||
|
Lightbox.pause(100);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var s = Drupal.settings.lightbox2;
|
||
|
if (!s.use_alt_layout) {
|
||
|
$('#prevLink, #nextLink').css({height: imgHeight + 'px'});
|
||
|
}
|
||
|
$('#imageDataContainer').css({width: widthNew + 'px'});
|
||
|
},
|
||
|
|
||
|
// showData()
|
||
|
// Display image and begin preloading neighbors.
|
||
|
showData: function() {
|
||
|
$('#loading').hide();
|
||
|
|
||
|
if (Lightbox.isLightframe || Lightbox.isVideo || Lightbox.isModal) {
|
||
|
Lightbox.updateDetails();
|
||
|
if (Lightbox.isLightframe) {
|
||
|
$('#frameContainer').show();
|
||
|
if ($.browser.safari) {
|
||
|
$('#lightboxFrame').css({zIndex: '10500'}).show();
|
||
|
}
|
||
|
else {
|
||
|
$('#lightboxFrame').css({zIndex: '10500'}).fadeIn(Lightbox.fadeInSpeed);
|
||
|
}
|
||
|
try {
|
||
|
document.getElementById("lightboxFrame").src = Lightbox.imageArray[Lightbox.activeImage][0];
|
||
|
} catch(e) {}
|
||
|
}
|
||
|
else {
|
||
|
if (Lightbox.isVideo) {
|
||
|
$("#modalContainer").html(Lightbox.modalHTML);
|
||
|
$("#modalContainer").click(function() { return false; } );
|
||
|
}
|
||
|
else {
|
||
|
$("#modalContainer").load(Lightbox.imageArray[Lightbox.activeImage][0]);
|
||
|
$('#modalContainer').unbind('click');
|
||
|
}
|
||
|
$('#modalContainer').css({zIndex: '10500'}).show();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Handle display of image content.
|
||
|
else {
|
||
|
$('#imageContainer').show();
|
||
|
if($.browser.safari) {
|
||
|
$('#lightboxImage').css({zIndex: '10500'}).show();
|
||
|
}
|
||
|
else {
|
||
|
$('#lightboxImage').css({zIndex: '10500'}).fadeIn(Lightbox.fadeInSpeed);
|
||
|
}
|
||
|
Lightbox.updateDetails();
|
||
|
this.preloadNeighborImages();
|
||
|
}
|
||
|
Lightbox.inprogress = false;
|
||
|
|
||
|
// Slideshow specific stuff.
|
||
|
if (Lightbox.isSlideshow) {
|
||
|
if (!Lightbox.loopSlides && Lightbox.activeImage == (Lightbox.total - 1)) {
|
||
|
if (Lightbox.autoExit) {
|
||
|
Lightbox.slideIdArray[Lightbox.slideIdCount++] = setTimeout(function () {Lightbox.end('slideshow');}, Lightbox.slideInterval);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!Lightbox.isPaused) {
|
||
|
Lightbox.slideIdArray[Lightbox.slideIdCount++] = setTimeout(function () {Lightbox.changeData(Lightbox.activeImage + 1);}, Lightbox.slideInterval);
|
||
|
}
|
||
|
}
|
||
|
if (Lightbox.showPlayPause && Lightbox.total > 1 && !Lightbox.isPaused) {
|
||
|
$('#lightshowPause').show();
|
||
|
$('#lightshowPlay').hide();
|
||
|
}
|
||
|
else if (Lightbox.showPlayPause && Lightbox.total > 1) {
|
||
|
$('#lightshowPause').hide();
|
||
|
$('#lightshowPlay').show();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Adjust the page overlay size.
|
||
|
var arrayPageSize = Lightbox.getPageSize();
|
||
|
var arrayPageScroll = Lightbox.getPageScroll();
|
||
|
var pageHeight = arrayPageSize[1];
|
||
|
if (Lightbox.isZoomedIn && arrayPageSize[1] > arrayPageSize[3]) {
|
||
|
var lightboxTop = (Lightbox.topPosition == '' ? (arrayPageSize[3] / 10) : Lightbox.topPosition) * 1;
|
||
|
pageHeight = pageHeight + arrayPageScroll[1] + lightboxTop;
|
||
|
}
|
||
|
$('#overlay').css({height: pageHeight + 'px', width: arrayPageSize[0] + 'px'});
|
||
|
|
||
|
// Gecko browsers (e.g. Firefox, SeaMonkey, etc) don't handle pdfs as
|
||
|
// expected.
|
||
|
if ($.browser.mozilla) {
|
||
|
if (Lightbox.imageArray[Lightbox.activeImage][0].indexOf(".pdf") != -1) {
|
||
|
setTimeout(function () {
|
||
|
document.getElementById("lightboxFrame").src = Lightbox.imageArray[Lightbox.activeImage][0];
|
||
|
}, 1000);
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
// updateDetails()
|
||
|
// Display caption, image number, and bottom nav.
|
||
|
updateDetails: function() {
|
||
|
|
||
|
$("#imageDataContainer").hide();
|
||
|
|
||
|
var caption = Lightbox.imageArray[Lightbox.activeImage][1];
|
||
|
if (!caption) caption = ' ';
|
||
|
$('#caption').html(caption).css({zIndex: '10500'}).show();
|
||
|
|
||
|
// If image is part of set display 'Image x of x'.
|
||
|
var s = Drupal.settings.lightbox2;
|
||
|
var numberDisplay = null;
|
||
|
if (Lightbox.total > 1) {
|
||
|
var currentImage = Lightbox.activeImage + 1;
|
||
|
if (!Lightbox.isLightframe) {
|
||
|
numberDisplay = s.image_count.replace(/\!current/, currentImage).replace(/\!total/, Lightbox.total);
|
||
|
}
|
||
|
else {
|
||
|
numberDisplay = s.page_count.replace(/\!current/, currentImage).replace(/\!total/, Lightbox.total);
|
||
|
}
|
||
|
$('#numberDisplay').html(numberDisplay).css({zIndex: '10500'}).show();
|
||
|
}
|
||
|
|
||
|
$("#imageDataContainer").hide().slideDown(Lightbox.slideDownSpeed);
|
||
|
if (Lightbox.rtl) {
|
||
|
$("#bottomNav").css({float: 'left'});
|
||
|
}
|
||
|
Lightbox.updateNav();
|
||
|
},
|
||
|
|
||
|
// updateNav()
|
||
|
// Display appropriate previous and next hover navigation.
|
||
|
updateNav: function() {
|
||
|
|
||
|
$('#hoverNav').css({zIndex: '10500'}).show();
|
||
|
var prevLink = '#prevLink';
|
||
|
var nextLink = '#nextLink';
|
||
|
|
||
|
// Slideshow is separated as we need to show play / pause button.
|
||
|
if (Lightbox.isSlideshow) {
|
||
|
if ((Lightbox.total > 1 && Lightbox.loopSlides) || Lightbox.activeImage !== 0) {
|
||
|
$(prevLink).css({zIndex: '10500'}).show().click(function() {
|
||
|
if (Lightbox.pauseOnPrevClick) {
|
||
|
Lightbox.togglePlayPause("lightshowPause", "lightshowPlay");
|
||
|
}
|
||
|
Lightbox.changeData(Lightbox.activeImage - 1); return false;
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
$(prevLink).hide();
|
||
|
}
|
||
|
|
||
|
// If not last image in set, display next image button.
|
||
|
if ((Lightbox.total > 1 && Lightbox.loopSlides) || Lightbox.activeImage != (Lightbox.total - 1)) {
|
||
|
$(nextLink).css({zIndex: '10500'}).show().click(function() {
|
||
|
if (Lightbox.pauseOnNextClick) {
|
||
|
Lightbox.togglePlayPause("lightshowPause", "lightshowPlay");
|
||
|
}
|
||
|
Lightbox.changeData(Lightbox.activeImage + 1); return false;
|
||
|
});
|
||
|
}
|
||
|
// Safari browsers need to have hide() called again.
|
||
|
else {
|
||
|
$(nextLink).hide();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// All other types of content.
|
||
|
else {
|
||
|
|
||
|
if (Lightbox.isLightframe && !Lightbox.alternative_layout) {
|
||
|
$('#frameHoverNav').css({zIndex: '10500'}).show();
|
||
|
$('#hoverNav').css({zIndex: '10500'}).hide();
|
||
|
prevLink = '#framePrevLink';
|
||
|
nextLink = '#frameNextLink';
|
||
|
}
|
||
|
|
||
|
// If not first image in set, display prev image button.
|
||
|
if ((Lightbox.total > 1 && Lightbox.loopItems) || Lightbox.activeImage !== 0) {
|
||
|
$(prevLink).css({zIndex: '10500'}).show().click(function() {
|
||
|
Lightbox.changeData(Lightbox.activeImage - 1); return false;
|
||
|
});
|
||
|
}
|
||
|
// Safari browsers need to have hide() called again.
|
||
|
else {
|
||
|
$(prevLink).hide();
|
||
|
}
|
||
|
|
||
|
// If not last image in set, display next image button.
|
||
|
if ((Lightbox.total > 1 && Lightbox.loopItems) || Lightbox.activeImage != (Lightbox.total - 1)) {
|
||
|
$(nextLink).css({zIndex: '10500'}).show().click(function() {
|
||
|
Lightbox.changeData(Lightbox.activeImage + 1); return false;
|
||
|
});
|
||
|
}
|
||
|
// Safari browsers need to have hide() called again.
|
||
|
else {
|
||
|
$(nextLink).hide();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!Lightbox.isModal) {
|
||
|
this.enableKeyboardNav();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
|
||
|
// enableKeyboardNav()
|
||
|
enableKeyboardNav: function() {
|
||
|
$(document).bind("keydown", this.keyboardAction);
|
||
|
},
|
||
|
|
||
|
// disableKeyboardNav()
|
||
|
disableKeyboardNav: function() {
|
||
|
$(document).unbind("keydown", this.keyboardAction);
|
||
|
},
|
||
|
|
||
|
// keyboardAction()
|
||
|
keyboardAction: function(e) {
|
||
|
if (e === null) { // IE.
|
||
|
keycode = event.keyCode;
|
||
|
escapeKey = 27;
|
||
|
}
|
||
|
else { // Mozilla.
|
||
|
keycode = e.keyCode;
|
||
|
escapeKey = e.DOM_VK_ESCAPE;
|
||
|
}
|
||
|
|
||
|
key = String.fromCharCode(keycode).toLowerCase();
|
||
|
|
||
|
// Close lightbox.
|
||
|
if (key == 'x' || key == 'o' || key == 'c' || keycode == escapeKey) {
|
||
|
Lightbox.end('forceClose');
|
||
|
|
||
|
// Display previous image (p, <-).
|
||
|
}
|
||
|
else if (key == 'p' || keycode == 37) {
|
||
|
if ((Lightbox.total > 1 && ((Lightbox.isSlideshow && Lightbox.loopSlides) || (!Lightbox.isSlideshow && Lightbox.loopItems))) || Lightbox.activeImage !== 0) {
|
||
|
Lightbox.changeData(Lightbox.activeImage - 1);
|
||
|
}
|
||
|
|
||
|
// Display next image (n, ->).
|
||
|
}
|
||
|
else if (key == 'n' || keycode == 39) {
|
||
|
if ((Lightbox.total > 1 && ((Lightbox.isSlideshow && Lightbox.loopSlides) || (!Lightbox.isSlideshow && Lightbox.loopItems))) || Lightbox.activeImage != (Lightbox.total - 1)) {
|
||
|
Lightbox.changeData(Lightbox.activeImage + 1);
|
||
|
}
|
||
|
}
|
||
|
// Zoom in.
|
||
|
else if (key == 'z' && !Lightbox.disableResize && !Lightbox.disableZoom && !Lightbox.isSlideshow && !Lightbox.isLightframe) {
|
||
|
if (Lightbox.isZoomedIn) {
|
||
|
Lightbox.changeData(Lightbox.activeImage, false);
|
||
|
}
|
||
|
else if (!Lightbox.isZoomedIn) {
|
||
|
Lightbox.changeData(Lightbox.activeImage, true);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
// Toggle play / pause (space).
|
||
|
else if (keycode == 32 && Lightbox.isSlideshow) {
|
||
|
|
||
|
if (Lightbox.isPaused) {
|
||
|
Lightbox.togglePlayPause("lightshowPlay", "lightshowPause");
|
||
|
}
|
||
|
else {
|
||
|
Lightbox.togglePlayPause("lightshowPause", "lightshowPlay");
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
preloadNeighborImages: function() {
|
||
|
|
||
|
if ((Lightbox.total - 1) > Lightbox.activeImage) {
|
||
|
preloadNextImage = new Image();
|
||
|
preloadNextImage.src = Lightbox.imageArray[Lightbox.activeImage + 1][0];
|
||
|
}
|
||
|
if (Lightbox.activeImage > 0) {
|
||
|
preloadPrevImage = new Image();
|
||
|
preloadPrevImage.src = Lightbox.imageArray[Lightbox.activeImage - 1][0];
|
||
|
}
|
||
|
|
||
|
},
|
||
|
|
||
|
end: function(caller) {
|
||
|
var closeClick = (caller == 'slideshow' ? false : true);
|
||
|
if (Lightbox.isSlideshow && Lightbox.isPaused && !closeClick) {
|
||
|
return;
|
||
|
}
|
||
|
// To prevent double clicks on navigation links.
|
||
|
if (Lightbox.inprogress === true && caller != 'forceClose') {
|
||
|
return;
|
||
|
}
|
||
|
Lightbox.disableKeyboardNav();
|
||
|
$('#lightbox').hide();
|
||
|
$("#overlay").fadeOut();
|
||
|
Lightbox.isPaused = true;
|
||
|
Lightbox.inprogress = false;
|
||
|
// Replaces calls to showSelectBoxes() and showFlash() in original
|
||
|
// lightbox2.
|
||
|
Lightbox.toggleSelectsFlash('visible');
|
||
|
if (Lightbox.isSlideshow) {
|
||
|
for (var i = 0; i < Lightbox.slideIdCount; i++) {
|
||
|
window.clearTimeout(Lightbox.slideIdArray[i]);
|
||
|
}
|
||
|
$('#lightshowPause, #lightshowPlay').hide();
|
||
|
}
|
||
|
else if (Lightbox.isLightframe) {
|
||
|
document.getElementById("lightboxFrame").src = '';
|
||
|
if ($.browser.safari) {
|
||
|
var iFrame = document.getElementById("lightboxFrame");
|
||
|
var parent = iFrame.parentNode;
|
||
|
parent.removeChild(iFrame);
|
||
|
parent.appendChild(iFrame);
|
||
|
}
|
||
|
$('#lightboxFrame, #frameContainer').hide();
|
||
|
}
|
||
|
else if (Lightbox.isVideo || Lightbox.isModal) {
|
||
|
$('#modalContainer').hide();
|
||
|
$('#modalContainer').html("");
|
||
|
}
|
||
|
},
|
||
|
|
||
|
|
||
|
// getPageScroll()
|
||
|
// Returns array with x,y page scroll values.
|
||
|
// Core code from - quirksmode.com.
|
||
|
getPageScroll : function() {
|
||
|
|
||
|
var xScroll, yScroll;
|
||
|
|
||
|
if (self.pageYOffset) {
|
||
|
yScroll = self.pageYOffset;
|
||
|
xScroll = self.pageXOffset;
|
||
|
}
|
||
|
else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict.
|
||
|
yScroll = document.documentElement.scrollTop;
|
||
|
xScroll = document.documentElement.scrollLeft;
|
||
|
}
|
||
|
else if (document.body) {// All other Explorers.
|
||
|
yScroll = document.body.scrollTop;
|
||
|
xScroll = document.body.scrollLeft;
|
||
|
}
|
||
|
|
||
|
arrayPageScroll = [xScroll,yScroll];
|
||
|
return arrayPageScroll;
|
||
|
},
|
||
|
|
||
|
// getPageSize()
|
||
|
// Returns array with page width, height and window width, height.
|
||
|
// Core code from - quirksmode.com.
|
||
|
// Edit for Firefox by pHaez.
|
||
|
getPageSize : function() {
|
||
|
|
||
|
var xScroll, yScroll;
|
||
|
|
||
|
if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac
|
||
|
xScroll = document.body.scrollWidth;
|
||
|
yScroll = document.body.scrollHeight;
|
||
|
}
|
||
|
else if (window.innerHeight && window.scrollMaxY) {
|
||
|
xScroll = window.innerWidth + window.scrollMaxX;
|
||
|
yScroll = window.innerHeight + window.scrollMaxY;
|
||
|
}
|
||
|
// Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari.
|
||
|
else {
|
||
|
xScroll = document.body.offsetWidth;
|
||
|
yScroll = document.body.offsetHeight;
|
||
|
}
|
||
|
|
||
|
var windowWidth, windowHeight;
|
||
|
|
||
|
if (self.innerHeight) { // All except Explorer.
|
||
|
if (document.documentElement.clientWidth) {
|
||
|
windowWidth = document.documentElement.clientWidth;
|
||
|
}
|
||
|
else {
|
||
|
windowWidth = self.innerWidth;
|
||
|
}
|
||
|
windowHeight = self.innerHeight;
|
||
|
}
|
||
|
// Explorer 6 Strict Mode.
|
||
|
else if (document.documentElement && document.documentElement.clientHeight) {
|
||
|
windowWidth = document.documentElement.clientWidth;
|
||
|
windowHeight = document.documentElement.clientHeight;
|
||
|
}
|
||
|
else if (document.body) { // Other Explorers.
|
||
|
windowWidth = document.body.clientWidth;
|
||
|
windowHeight = document.body.clientHeight;
|
||
|
}
|
||
|
|
||
|
|
||
|
// For small pages with total height less then height of the viewport.
|
||
|
if (yScroll < windowHeight) {
|
||
|
pageHeight = windowHeight;
|
||
|
}
|
||
|
else {
|
||
|
pageHeight = yScroll;
|
||
|
}
|
||
|
|
||
|
|
||
|
// For small pages with total width less then width of the viewport.
|
||
|
if (xScroll < windowWidth) {
|
||
|
pageWidth = windowWidth;
|
||
|
}
|
||
|
else {
|
||
|
pageWidth = xScroll;
|
||
|
}
|
||
|
|
||
|
arrayPageSize = [pageWidth, pageHeight, windowWidth, windowHeight];
|
||
|
return arrayPageSize;
|
||
|
},
|
||
|
|
||
|
|
||
|
// pause(numberMillis)
|
||
|
pause : function(ms) {
|
||
|
var date = new Date();
|
||
|
var curDate = null;
|
||
|
do { curDate = new Date(); }
|
||
|
while (curDate - date < ms);
|
||
|
},
|
||
|
|
||
|
|
||
|
// toggleSelectsFlash()
|
||
|
// Hide / unhide select lists and flash objects as they appear above the
|
||
|
// lightbox in some browsers.
|
||
|
toggleSelectsFlash: function (state) {
|
||
|
if (state == 'visible') {
|
||
|
$("select.lightbox_hidden, embed.lightbox_hidden, object.lightbox_hidden").show();
|
||
|
}
|
||
|
else if (state == 'hide') {
|
||
|
$("select:visible, embed:visible, object:visible").addClass("lightbox_hidden");
|
||
|
$("select.lightbox_hidden, embed.lightbox_hidden, object.lightbox_hidden").hide();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
|
||
|
// parseRel()
|
||
|
parseRel: function (link) {
|
||
|
var parts = [];
|
||
|
parts["rel"] = $(link).attr('rel').match(/\w+/)[0];
|
||
|
parts["title"] = parts["group"] = parts["style"] = null;
|
||
|
|
||
|
if ($(link).attr('rel').match(/\[(.*)\]/)) {
|
||
|
var info = $(link).attr('rel').match(/\[(.*?)\]/)[1].split('|');
|
||
|
parts["group"] = info[0];
|
||
|
parts["style"] = info[1];
|
||
|
}
|
||
|
if ($(link).attr('rel').match(/\[.*\]\[(.*)\]/)) {
|
||
|
parts["title"] = $(link).attr('rel').match(/\[.*\]\[(.*)\]/)[1];
|
||
|
}
|
||
|
return parts;
|
||
|
},
|
||
|
|
||
|
// setStyles()
|
||
|
setStyles: function(item, styles) {
|
||
|
var stylesArray = styles.split(';');
|
||
|
for (var i = 0; i< stylesArray.length; i++) {
|
||
|
if (stylesArray[i].indexOf('width:') >= 0) {
|
||
|
var w = stylesArray[i].replace('width:', '');
|
||
|
item.width = jQuery.trim(w);
|
||
|
}
|
||
|
else if (stylesArray[i].indexOf('height:') >= 0) {
|
||
|
var h = stylesArray[i].replace('height:', '');
|
||
|
item.height = jQuery.trim(h);
|
||
|
}
|
||
|
else if (stylesArray[i].indexOf('scrolling:') >= 0) {
|
||
|
var scrolling = stylesArray[i].replace('scrolling:', '');
|
||
|
item.scrolling = jQuery.trim(scrolling);
|
||
|
}
|
||
|
else if (stylesArray[i].indexOf('overflow:') >= 0) {
|
||
|
var overflow = stylesArray[i].replace('overflow:', '');
|
||
|
item.overflow = jQuery.trim(overflow);
|
||
|
}
|
||
|
}
|
||
|
return item;
|
||
|
},
|
||
|
|
||
|
|
||
|
// togglePlayPause()
|
||
|
// Hide the pause / play button as appropriate. If pausing the slideshow also
|
||
|
// clear the timers, otherwise move onto the next image.
|
||
|
togglePlayPause: function(hideId, showId) {
|
||
|
if (Lightbox.isSlideshow && hideId == "lightshowPause") {
|
||
|
for (var i = 0; i < Lightbox.slideIdCount; i++) {
|
||
|
window.clearTimeout(Lightbox.slideIdArray[i]);
|
||
|
}
|
||
|
}
|
||
|
$('#' + hideId).hide();
|
||
|
$('#' + showId).show();
|
||
|
|
||
|
if (hideId == "lightshowPlay") {
|
||
|
Lightbox.isPaused = false;
|
||
|
if (!Lightbox.loopSlides && Lightbox.activeImage == (Lightbox.total - 1)) {
|
||
|
Lightbox.end();
|
||
|
}
|
||
|
else {
|
||
|
Lightbox.changeData(Lightbox.activeImage + 1);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
Lightbox.isPaused = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// Initialize the lightbox.
|
||
|
Drupal.behaviors.initLightbox = function (context) {
|
||
|
Lightbox.initialize();
|
||
|
};
|
||
|
|
||
|
;// $Id: panels.js,v 1.2.4.1 2009/10/05 22:40:35 merlinofchaos Exp $
|
||
|
|
||
|
(function ($) {
|
||
|
Drupal.Panels = {};
|
||
|
|
||
|
Drupal.Panels.autoAttach = function() {
|
||
|
if ($.browser.msie) {
|
||
|
// If IE, attach a hover event so we can see our admin links.
|
||
|
$("div.panel-pane").hover(
|
||
|
function() {
|
||
|
$('div.panel-hide', this).addClass("panel-hide-hover"); return true;
|
||
|
},
|
||
|
function() {
|
||
|
$('div.panel-hide', this).removeClass("panel-hide-hover"); return true;
|
||
|
}
|
||
|
);
|
||
|
$("div.admin-links").hover(
|
||
|
function() {
|
||
|
$(this).addClass("admin-links-hover"); return true;
|
||
|
},
|
||
|
function(){
|
||
|
$(this).removeClass("admin-links-hover"); return true;
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$(Drupal.Panels.autoAttach);
|
||
|
})(jQuery);
|
||
|
;// $Id: jquery.form.js,v 1.2 2007/11/19 10:05:48 goba Exp $
|
||
|
|
||
|
/*
|
||
|
* jQuery Form Plugin
|
||
|
* version: 2.01 (10/31/2007)
|
||
|
* @requires jQuery v1.1 or later
|
||
|
*
|
||
|
* Examples at: http://malsup.com/jquery/form/
|
||
|
* Dual licensed under the MIT and GPL licenses:
|
||
|
* http://www.opensource.org/licenses/mit-license.php
|
||
|
* http://www.gnu.org/licenses/gpl.html
|
||
|
*/
|
||
|
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5($){$.7.1j=5(o){2(P o==\'5\')o={L:o};o=$.2h({1h:4.X(\'2i\')||1E.2u.3D(),I:4.X(\'2g\')||\'29\'},o||{});3 p={};$.M.N(\'R.2P.2L\',[4,o,p]);2(p.1Q)6 4;3 a=4.1z(o.2r);2(o.V){H(3 n 3u o.V)a.C({z:n,A:o.V[n]})}2(o.28&&o.28(a,4,o)===E)6 4;$.M.N(\'R.K.36\',[a,4,o,p]);2(p.1Q)6 4;3 q=$.1x(a);2(o.I.31()==\'29\'){o.1h+=(o.1h.2Z(\'?\')>=0?\'&\':\'?\')+q;o.V=B}8 o.V=q;3 r=4,U=[];2(o.1r)U.C(5(){r.1r()});2(o.1o)U.C(5(){r.1o()});2(!o.18&&o.14){3 u=o.L||5(){};U.C(5(a){2(4.1N)$(o.14).X("1M",a).1N().D(u,1L);8 $(o.14).2t(a).D(u,1L)})}8 2(o.L)U.C(o.L);o.L=5(a,b){H(3 i=0,F=U.G;i<F;i++)U[i](a,b,r)};3 v=$(\'19:3v\',4).15();3 w=E;H(3 j=0;j<v.G;j++)2(v[j])w=T;2(o.2f||w){2($.1i.3o&&o.2a)$.3l(o.2a,1l);8 1l()}8 $.3h(o);$.M.N(\'R.K.3f\',[4,o]);6 4;5 1l(){3 d=r[0];3 f=$.2h({},$.39,o);3 h=\'35\'+$.7.1j.1a++;3 i=$(\'<2f 33="\'+h+\'" z="\'+h+\'" />\');3 j=i[0];3 k=$.1i.20&&1E.20.30()<9;2($.1i.1X||k)j.2Y=\'2W:E;1w.2U("");\';i.2S({2R:\'2Q\',23:\'-24\',1R:\'-24\'});3 l={Z:B,1b:B,2K:0,2J:\'n/a\',2H:5(){},2F:5(){},2E:5(){}};3 g=f.2B;2(g&&!$.1O++)$.M.N("2x");2(g)$.M.N("2w",[l,f]);3 m=0;3 n=0;1f(5(){i.2v(\'1n\');j.1K?j.1K(\'1J\',12):j.2s(\'1I\',12,E);3 a=d.1H?\'1H\':\'2q\';3 t=r.X(\'14\');r.X({14:h,2g:\'3C\',2i:f.1h});d[a]=\'3B/R-V\';2(f.1G)1f(5(){n=T;12()},f.1G);d.K();r.X(\'14\',t)},10);5 12(){2(m++)6;j.2o?j.2o(\'1J\',12):j.3A(\'1I\',12,E);3 a=T;3z{2(n)3x\'1G\';3 b,O;O=j.2n?j.2n.1w:j.2l?j.2l:j.1w;l.Z=O.1n?O.1n.1M:B;l.1b=O.2k?O.2k:O;2(f.18==\'2j\'||f.18==\'3s\'){3 c=O.1D(\'1C\')[0];b=c?c.A:l.Z;2(f.18==\'2j\')3r("V = "+b);8 $.3q(b)}8 2(f.18==\'2m\'){b=l.1b;2(!b&&l.Z!=B)b=2d(l.Z)}8{b=l.Z}}3p(e){a=E;$.3n(f,l,\'2b\',e)}2(a){f.L(b,\'L\');2(g)$.M.N("3m",[l,f])}2(g)$.M.N("3k",[l,f]);2(g&&!--$.1O)$.M.N("3j");2(f.27)f.27(l,a?\'L\':\'2b\');1f(5(){i.3i();l.1b=B},3g)};5 2d(s,a){2(1E.26){a=25 26(\'3d.3c\');a.3b=\'E\';a.3a(s)}8 a=(25 38()).37(s,\'1A/2m\');6(a&&a.22&&a.22.1e!=\'34\')?a:B}}};$.7.1j.1a=0;$.7.W=5(a){6 4.21().K(1m).D(5(){4.1u=$.7.W.1a++;$.7.W.1t[4.1u]=a;$(":K,19:Y",4).1Z(1s)})};$.7.W.1a=1;$.7.W.1t={};5 1s(e){3 a=4.R;a.Q=4;2(4.I==\'Y\'){2(e.1Y!=S){a.11=e.1Y;a.16=e.2X}8 2(P $.7.1U==\'5\'){3 b=$(4).1U();a.11=e.1V-b.1R;a.16=e.1W-b.23}8{a.11=e.1V-4.2V;a.16=e.1W-4.32}}1f(5(){a.Q=a.11=a.16=B},10)};5 1m(){3 a=4.1u;3 b=$.7.W.1t[a];$(4).1j(b);6 E};$.7.21=5(){4.1T(\'K\',1m);6 4.D(5(){$(":K,19:Y",4).1T(\'1Z\',1s)})};$.7.1z=5(b){3 a=[];2(4.G==0)6 a;3 c=4[0];3 d=b?c.1D(\'*\'):c.2T;2(!d)6 a;H(3 i=0,F=d.G;i<F;i++){3 e=d[i];3 n=e.z;2(!n)1v;2(b&&c.Q&&e.I=="Y"){2(!e.1d&&c.Q==e)a.C({z:n+\'.x\',A:c.11},{z:n+\'.y\',A:c.16});1v}3 v=$.15(e,T);2(v&&v.1c==1g){H(3 j=0,1S=v.G;j<1S;j++)a.C({z:n,A:v[j]})}8 2(v!==B&&P v!=\'S\')a.C({z:n,A:v})}2(!b&&c.Q){3 f=c.1D("19");H(3 i=0,F=f.G;i<F;i++){3 g=f[i];3 n=g.z;2(n&&!g.1d&&g.I=="Y"&&c.Q==g)a.C({z:n+\'.x\',A:c.11},{z:n+\'.y\',A:c.16})}}6 a};$.7.2O=5(a){6 $.1x(4.1z(a))};$.7.2N=5(b){3 a=[];4.D(5(){3 n=4.z;2(!n)6;3 v=$.15(4,b);2(v&&v.1c==1g){H(3 i=0,F=v.G;i<F;i++)a.C({z:n,A:v[i]})}8 2(v!==B&&P v!=\'S\')a.C({z:4.z,A:v})});6 $.1x(a)};$.7.15=5(a){H(3 b=[],i=0,F=4.G;i<F;i++){3 c=4[i];3 v=$.15(c,a);2(v===B||P v==\'S\'||(v.1c==1g&&!v.G))1v;v.1c==1g?$.3e(b,v):b.C(v)}6 b};$.15=5(b,c){3 n=b.z,t=b.I,13=b.1e.1F();2(P c==\'S\')c=T;2(c&&(!n||b.1d||t==\'17\'||t==\'2M\'||(t==\'1q\'||t==\'1B\')&&!b.1p||(t==\'K\'||t==\'Y\')&&b.R&&b.R.Q!=b||13==\'J\'&&b.1y==-1))6 B;2(13==\'J\'){3 d=b.1y;2(d<0)6 B;3 a=[],1k=b.2I;3 e=(t==\'J-2e\');3 f=(e?d+1:1k.G);H(3 i=(e?d:0);i<f;i++){3 g=1k[i];2(g.2c){3 v=$.1i.1X&&!(g.2G[\'A\'].3t)?g.1A:g.A;2(e)6 v;a.C(v)}}6 a}6 b.A};$.7.1o=5(){6 4.D(5(){$(\'19,J,1C\',4).2p()})};$.7.2p=$.7.2D=5(){6 4.D(5(){3 t=4.I,13=4.1e.1F();2(t==\'1A\'||t==\'3w\'||13==\'1C\')4.A=\'\';8 2(t==\'1q\'||t==\'1B\')4.1p=E;8 2(13==\'J\')4.1y=-1})};$.7.1r=5(){6 4.D(5(){2(P 4.17==\'5\'||(P 4.17==\'2C\'&&!4.17.3y))4.17()})};$.7.2A=5(b){2(b==S)b=T;6 4.D(5(){
|
||
|
;// $Id: ahah.js,v 1.7.2.1 2008/02/11 14:46:27 goba Exp $
|
||
|
|
||
|
/**
|
||
|
* Provides AJAX-like page updating via AHAH (Asynchronous HTML and HTTP).
|
||
|
*
|
||
|
* AHAH is a method of making a request via Javascript while viewing an HTML
|
||
|
* page. The request returns a small chunk of HTML, which is then directly
|
||
|
* injected into the page.
|
||
|
*
|
||
|
* Drupal uses this file to enhance form elements with #ahah[path] and
|
||
|
* #ahah[wrapper] properties. If set, this file will automatically be included
|
||
|
* to provide AHAH capabilities.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Attaches the ahah behavior to each ahah form element.
|
||
|
*/
|
||
|
Drupal.behaviors.ahah = function(context) {
|
||
|
for (var base in Drupal.settings.ahah) {
|
||
|
if (!$('#'+ base + '.ahah-processed').size()) {
|
||
|
var element_settings = Drupal.settings.ahah[base];
|
||
|
|
||
|
$(element_settings.selector).each(function() {
|
||
|
element_settings.element = this;
|
||
|
var ahah = new Drupal.ahah(base, element_settings);
|
||
|
});
|
||
|
|
||
|
$('#'+ base).addClass('ahah-processed');
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* AHAH object.
|
||
|
*/
|
||
|
Drupal.ahah = function(base, element_settings) {
|
||
|
// Set the properties for this object.
|
||
|
this.element = element_settings.element;
|
||
|
this.selector = element_settings.selector;
|
||
|
this.event = element_settings.event;
|
||
|
this.keypress = element_settings.keypress;
|
||
|
this.url = element_settings.url;
|
||
|
this.wrapper = '#'+ element_settings.wrapper;
|
||
|
this.effect = element_settings.effect;
|
||
|
this.method = element_settings.method;
|
||
|
this.progress = element_settings.progress;
|
||
|
this.button = element_settings.button || { };
|
||
|
|
||
|
if (this.effect == 'none') {
|
||
|
this.showEffect = 'show';
|
||
|
this.hideEffect = 'hide';
|
||
|
this.showSpeed = '';
|
||
|
}
|
||
|
else if (this.effect == 'fade') {
|
||
|
this.showEffect = 'fadeIn';
|
||
|
this.hideEffect = 'fadeOut';
|
||
|
this.showSpeed = 'slow';
|
||
|
}
|
||
|
else {
|
||
|
this.showEffect = this.effect + 'Toggle';
|
||
|
this.hideEffect = this.effect + 'Toggle';
|
||
|
this.showSpeed = 'slow';
|
||
|
}
|
||
|
|
||
|
// Record the form action and target, needed for iFrame file uploads.
|
||
|
var form = $(this.element).parents('form');
|
||
|
this.form_action = form.attr('action');
|
||
|
this.form_target = form.attr('target');
|
||
|
this.form_encattr = form.attr('encattr');
|
||
|
|
||
|
// Set the options for the ajaxSubmit function.
|
||
|
// The 'this' variable will not persist inside of the options object.
|
||
|
var ahah = this;
|
||
|
var options = {
|
||
|
url: ahah.url,
|
||
|
data: ahah.button,
|
||
|
beforeSubmit: function(form_values, element_settings, options) {
|
||
|
return ahah.beforeSubmit(form_values, element_settings, options);
|
||
|
},
|
||
|
success: function(response, status) {
|
||
|
// Sanity check for browser support (object expected).
|
||
|
// When using iFrame uploads, responses must be returned as a string.
|
||
|
if (typeof(response) == 'string') {
|
||
|
response = Drupal.parseJson(response);
|
||
|
}
|
||
|
return ahah.success(response, status);
|
||
|
},
|
||
|
complete: function(response, status) {
|
||
|
if (status == 'error' || status == 'parsererror') {
|
||
|
return ahah.error(response, ahah.url);
|
||
|
}
|
||
|
},
|
||
|
dataType: 'json',
|
||
|
type: 'POST'
|
||
|
};
|
||
|
|
||
|
// Bind the ajaxSubmit function to the element event.
|
||
|
$(element_settings.element).bind(element_settings.event, function() {
|
||
|
$(element_settings.element).parents('form').ajaxSubmit(options);
|
||
|
return false;
|
||
|
});
|
||
|
// If necessary, enable keyboard submission so that AHAH behaviors
|
||
|
// can be triggered through keyboard input as well as e.g. a mousedown
|
||
|
// action.
|
||
|
if (element_settings.keypress) {
|
||
|
$(element_settings.element).keypress(function(event) {
|
||
|
// Detect enter key.
|
||
|
if (event.keyCode == 13) {
|
||
|
$(element_settings.element).trigger(element_settings.event);
|
||
|
return false;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handler for the form redirection submission.
|
||
|
*/
|
||
|
Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) {
|
||
|
// Disable the element that received the change.
|
||
|
$(this.element).addClass('progress-disabled').attr('disabled', true);
|
||
|
|
||
|
// Insert progressbar or throbber.
|
||
|
if (this.progress.type == 'bar') {
|
||
|
var progressBar = new Drupal.progressBar('ahah-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
|
||
|
if (this.progress.message) {
|
||
|
progressBar.setProgress(-1, this.progress.message);
|
||
|
}
|
||
|
if (this.progress.url) {
|
||
|
progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
|
||
|
}
|
||
|
this.progress.element = $(progressBar.element).addClass('ahah-progress ahah-progress-bar');
|
||
|
this.progress.object = progressBar;
|
||
|
$(this.element).after(this.progress.element);
|
||
|
}
|
||
|
else if (this.progress.type == 'throbber') {
|
||
|
this.progress.element = $('<div class="ahah-progress ahah-progress-throbber"><div class="throbber"> </div></div>');
|
||
|
if (this.progress.message) {
|
||
|
$('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>')
|
||
|
}
|
||
|
$(this.element).after(this.progress.element);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handler for the form redirection completion.
|
||
|
*/
|
||
|
Drupal.ahah.prototype.success = function (response, status) {
|
||
|
var wrapper = $(this.wrapper);
|
||
|
var form = $(this.element).parents('form');
|
||
|
// Manually insert HTML into the jQuery object, using $() directly crashes
|
||
|
// Safari with long string lengths. http://dev.jquery.com/ticket/1152
|
||
|
var new_content = $('<div></div>').html(response.data);
|
||
|
|
||
|
// Restore the previous action and target to the form.
|
||
|
form.attr('action', this.form_action);
|
||
|
this.form_target ? form.attr('target', this.form_target) : form.removeAttr('target');
|
||
|
this.form_encattr ? form.attr('target', this.form_encattr) : form.removeAttr('encattr');
|
||
|
|
||
|
// Remove the progress element.
|
||
|
if (this.progress.element) {
|
||
|
$(this.progress.element).remove();
|
||
|
}
|
||
|
if (this.progress.object) {
|
||
|
this.progress.object.stopMonitoring();
|
||
|
}
|
||
|
$(this.element).removeClass('progress-disabled').attr('disabled', false);
|
||
|
|
||
|
// Add the new content to the page.
|
||
|
Drupal.freezeHeight();
|
||
|
if (this.method == 'replace') {
|
||
|
wrapper.empty().append(new_content);
|
||
|
}
|
||
|
else {
|
||
|
wrapper[this.method](new_content);
|
||
|
}
|
||
|
|
||
|
// Immediately hide the new content if we're using any effects.
|
||
|
if (this.showEffect != 'show') {
|
||
|
new_content.hide();
|
||
|
}
|
||
|
|
||
|
// Determine what effect use and what content will receive the effect, then
|
||
|
// show the new content. For browser compatibility, Safari is excluded from
|
||
|
// using effects on table rows.
|
||
|
if (($.browser.safari && $("tr.ahah-new-content", new_content).size() > 0)) {
|
||
|
new_content.show();
|
||
|
}
|
||
|
else if ($('.ahah-new-content', new_content).size() > 0) {
|
||
|
$('.ahah-new-content', new_content).hide();
|
||
|
new_content.show();
|
||
|
$(".ahah-new-content", new_content)[this.showEffect](this.showSpeed);
|
||
|
}
|
||
|
else if (this.showEffect != 'show') {
|
||
|
new_content[this.showEffect](this.showSpeed);
|
||
|
}
|
||
|
|
||
|
// Attach all javascript behaviors to the new content, if it was successfully
|
||
|
// added to the page, this if statement allows #ahah[wrapper] to be optional.
|
||
|
if (new_content.parents('html').length > 0) {
|
||
|
Drupal.attachBehaviors(new_content);
|
||
|
}
|
||
|
|
||
|
Drupal.unfreezeHeight();
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handler for the form redirection error.
|
||
|
*/
|
||
|
Drupal.ahah.prototype.error = function (response, uri) {
|
||
|
alert(Drupal.ahahError(response, uri));
|
||
|
// Resore the previous action and target to the form.
|
||
|
$(this.element).parent('form').attr( { action: this.form_action, target: this.form_target} );
|
||
|
// Remove the progress element.
|
||
|
if (this.progress.element) {
|
||
|
$(this.progress.element).remove();
|
||
|
}
|
||
|
if (this.progress.object) {
|
||
|
this.progress.object.stopMonitoring();
|
||
|
}
|
||
|
// Undo hide.
|
||
|
$(this.wrapper).show();
|
||
|
// Re-enable the element.
|
||
|
$(this.element).removeClass('progess-disabled').attr('disabled', false);
|
||
|
};
|
||
|
;// $Id: progress.js,v 1.20 2008/01/04 11:53:21 goba Exp $
|
||
|
|
||
|
/**
|
||
|
* A progressbar object. Initialized with the given id. Must be inserted into
|
||
|
* the DOM afterwards through progressBar.element.
|
||
|
*
|
||
|
* method is the function which will perform the HTTP request to get the
|
||
|
* progress bar state. Either "GET" or "POST".
|
||
|
*
|
||
|
* e.g. pb = new progressBar('myProgressBar');
|
||
|
* some_element.appendChild(pb.element);
|
||
|
*/
|
||
|
Drupal.progressBar = function (id, updateCallback, method, errorCallback) {
|
||
|
var pb = this;
|
||
|
this.id = id;
|
||
|
this.method = method || "GET";
|
||
|
this.updateCallback = updateCallback;
|
||
|
this.errorCallback = errorCallback;
|
||
|
|
||
|
this.element = document.createElement('div');
|
||
|
this.element.id = id;
|
||
|
this.element.className = 'progress';
|
||
|
$(this.element).html('<div class="bar"><div class="filled"></div></div>'+
|
||
|
'<div class="percentage"></div>'+
|
||
|
'<div class="message"> </div>');
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Set the percentage and status message for the progressbar.
|
||
|
*/
|
||
|
Drupal.progressBar.prototype.setProgress = function (percentage, message) {
|
||
|
if (percentage >= 0 && percentage <= 100) {
|
||
|
$('div.filled', this.element).css('width', percentage +'%');
|
||
|
$('div.percentage', this.element).html(percentage +'%');
|
||
|
}
|
||
|
$('div.message', this.element).html(message);
|
||
|
if (this.updateCallback) {
|
||
|
this.updateCallback(percentage, message, this);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Start monitoring progress via Ajax.
|
||
|
*/
|
||
|
Drupal.progressBar.prototype.startMonitoring = function (uri, delay) {
|
||
|
this.delay = delay;
|
||
|
this.uri = uri;
|
||
|
this.sendPing();
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Stop monitoring progress via Ajax.
|
||
|
*/
|
||
|
Drupal.progressBar.prototype.stopMonitoring = function () {
|
||
|
clearTimeout(this.timer);
|
||
|
// This allows monitoring to be stopped from within the callback
|
||
|
this.uri = null;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Request progress data from server.
|
||
|
*/
|
||
|
Drupal.progressBar.prototype.sendPing = function () {
|
||
|
if (this.timer) {
|
||
|
clearTimeout(this.timer);
|
||
|
}
|
||
|
if (this.uri) {
|
||
|
var pb = this;
|
||
|
// When doing a post request, you need non-null data. Otherwise a
|
||
|
// HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
|
||
|
$.ajax({
|
||
|
type: this.method,
|
||
|
url: this.uri,
|
||
|
data: '',
|
||
|
dataType: 'json',
|
||
|
success: function (progress) {
|
||
|
// Display errors
|
||
|
if (progress.status == 0) {
|
||
|
pb.displayError(progress.data);
|
||
|
return;
|
||
|
}
|
||
|
// Update display
|
||
|
pb.setProgress(progress.percentage, progress.message);
|
||
|
// Schedule next timer
|
||
|
pb.timer = setTimeout(function() { pb.sendPing(); }, pb.delay);
|
||
|
},
|
||
|
error: function (xmlhttp) {
|
||
|
pb.displayError(Drupal.ahahError(xmlhttp, pb.uri));
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Display errors on the page.
|
||
|
*/
|
||
|
Drupal.progressBar.prototype.displayError = function (string) {
|
||
|
var error = document.createElement('div');
|
||
|
error.className = 'error';
|
||
|
error.innerHTML = string;
|
||
|
|
||
|
$(this.element).before(error).hide();
|
||
|
|
||
|
if (this.errorCallback) {
|
||
|
this.errorCallback(this);
|
||
|
}
|
||
|
};
|
||
|
;// $Id: autocomplete.js,v 1.23 2008/01/04 11:53:21 goba Exp $
|
||
|
|
||
|
/**
|
||
|
* Attaches the autocomplete behavior to all required fields
|
||
|
*/
|
||
|
Drupal.behaviors.autocomplete = function (context) {
|
||
|
var acdb = [];
|
||
|
$('input.autocomplete:not(.autocomplete-processed)', context).each(function () {
|
||
|
var uri = this.value;
|
||
|
if (!acdb[uri]) {
|
||
|
acdb[uri] = new Drupal.ACDB(uri);
|
||
|
}
|
||
|
var input = $('#' + this.id.substr(0, this.id.length - 13))
|
||
|
.attr('autocomplete', 'OFF')[0];
|
||
|
$(input.form).submit(Drupal.autocompleteSubmit);
|
||
|
new Drupal.jsAC(input, acdb[uri]);
|
||
|
$(this).addClass('autocomplete-processed');
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Prevents the form from submitting if the suggestions popup is open
|
||
|
* and closes the suggestions popup when doing so.
|
||
|
*/
|
||
|
Drupal.autocompleteSubmit = function () {
|
||
|
return $('#autocomplete').each(function () {
|
||
|
this.owner.hidePopup();
|
||
|
}).size() == 0;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* An AutoComplete object
|
||
|
*/
|
||
|
Drupal.jsAC = function (input, db) {
|
||
|
var ac = this;
|
||
|
this.input = input;
|
||
|
this.db = db;
|
||
|
|
||
|
$(this.input)
|
||
|
.keydown(function (event) { return ac.onkeydown(this, event); })
|
||
|
.keyup(function (event) { ac.onkeyup(this, event); })
|
||
|
.blur(function () { ac.hidePopup(); ac.db.cancel(); });
|
||
|
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handler for the "keydown" event
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.onkeydown = function (input, e) {
|
||
|
if (!e) {
|
||
|
e = window.event;
|
||
|
}
|
||
|
switch (e.keyCode) {
|
||
|
case 40: // down arrow
|
||
|
this.selectDown();
|
||
|
return false;
|
||
|
case 38: // up arrow
|
||
|
this.selectUp();
|
||
|
return false;
|
||
|
default: // all other keys
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handler for the "keyup" event
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.onkeyup = function (input, e) {
|
||
|
if (!e) {
|
||
|
e = window.event;
|
||
|
}
|
||
|
switch (e.keyCode) {
|
||
|
case 16: // shift
|
||
|
case 17: // ctrl
|
||
|
case 18: // alt
|
||
|
case 20: // caps lock
|
||
|
case 33: // page up
|
||
|
case 34: // page down
|
||
|
case 35: // end
|
||
|
case 36: // home
|
||
|
case 37: // left arrow
|
||
|
case 38: // up arrow
|
||
|
case 39: // right arrow
|
||
|
case 40: // down arrow
|
||
|
return true;
|
||
|
|
||
|
case 9: // tab
|
||
|
case 13: // enter
|
||
|
case 27: // esc
|
||
|
this.hidePopup(e.keyCode);
|
||
|
return true;
|
||
|
|
||
|
default: // all other keys
|
||
|
if (input.value.length > 0)
|
||
|
this.populatePopup();
|
||
|
else
|
||
|
this.hidePopup(e.keyCode);
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Puts the currently highlighted suggestion into the autocomplete field
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.select = function (node) {
|
||
|
this.input.value = node.autocompleteValue;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Highlights the next suggestion
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.selectDown = function () {
|
||
|
if (this.selected && this.selected.nextSibling) {
|
||
|
this.highlight(this.selected.nextSibling);
|
||
|
}
|
||
|
else {
|
||
|
var lis = $('li', this.popup);
|
||
|
if (lis.size() > 0) {
|
||
|
this.highlight(lis.get(0));
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Highlights the previous suggestion
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.selectUp = function () {
|
||
|
if (this.selected && this.selected.previousSibling) {
|
||
|
this.highlight(this.selected.previousSibling);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Highlights a suggestion
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.highlight = function (node) {
|
||
|
if (this.selected) {
|
||
|
$(this.selected).removeClass('selected');
|
||
|
}
|
||
|
$(node).addClass('selected');
|
||
|
this.selected = node;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Unhighlights a suggestion
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.unhighlight = function (node) {
|
||
|
$(node).removeClass('selected');
|
||
|
this.selected = false;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Hides the autocomplete suggestions
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.hidePopup = function (keycode) {
|
||
|
// Select item if the right key or mousebutton was pressed
|
||
|
if (this.selected && ((keycode && keycode != 46 && keycode != 8 && keycode != 27) || !keycode)) {
|
||
|
this.input.value = this.selected.autocompleteValue;
|
||
|
}
|
||
|
// Hide popup
|
||
|
var popup = this.popup;
|
||
|
if (popup) {
|
||
|
this.popup = null;
|
||
|
$(popup).fadeOut('fast', function() { $(popup).remove(); });
|
||
|
}
|
||
|
this.selected = false;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Positions the suggestions popup and starts a search
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.populatePopup = function () {
|
||
|
// Show popup
|
||
|
if (this.popup) {
|
||
|
$(this.popup).remove();
|
||
|
}
|
||
|
this.selected = false;
|
||
|
this.popup = document.createElement('div');
|
||
|
this.popup.id = 'autocomplete';
|
||
|
this.popup.owner = this;
|
||
|
$(this.popup).css({
|
||
|
marginTop: this.input.offsetHeight +'px',
|
||
|
width: (this.input.offsetWidth - 4) +'px',
|
||
|
display: 'none'
|
||
|
});
|
||
|
$(this.input).before(this.popup);
|
||
|
|
||
|
// Do search
|
||
|
this.db.owner = this;
|
||
|
this.db.search(this.input.value);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Fills the suggestion popup with any matches received
|
||
|
*/
|
||
|
Drupal.jsAC.prototype.found = function (matches) {
|
||
|
// If no value in the textfield, do not show the popup.
|
||
|
if (!this.input.value.length) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Prepare matches
|
||
|
var ul = document.createElement('ul');
|
||
|
var ac = this;
|
||
|
for (key in matches) {
|
||
|
var li = document.createElement('li');
|
||
|
$(li)
|
||
|
.html('<div>'+ matches[key] +'</div>')
|
||
|
.mousedown(function () { ac.select(this); })
|
||
|
.mouseover(function () { ac.highlight(this); })
|
||
|
.mouseout(function () { ac.unhighlight(this); });
|
||
|
li.autocompleteValue = key;
|
||
|
$(ul).append(li);
|
||
|
}
|
||
|
|
||
|
// Show popup with matches, if any
|
||
|
if (this.popup) {
|
||
|
if (ul.childNodes.length > 0) {
|
||
|
$(this.popup).empty().append(ul).show();
|
||
|
}
|
||
|
else {
|
||
|
$(this.popup).css({visibility: 'hidden'});
|
||
|
this.hidePopup();
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Drupal.jsAC.prototype.setStatus = function (status) {
|
||
|
switch (status) {
|
||
|
case 'begin':
|
||
|
$(this.input).addClass('throbbing');
|
||
|
break;
|
||
|
case 'cancel':
|
||
|
case 'error':
|
||
|
case 'found':
|
||
|
$(this.input).removeClass('throbbing');
|
||
|
break;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* An AutoComplete DataBase object
|
||
|
*/
|
||
|
Drupal.ACDB = function (uri) {
|
||
|
this.uri = uri;
|
||
|
this.delay = 300;
|
||
|
this.cache = {};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Performs a cached and delayed search
|
||
|
*/
|
||
|
Drupal.ACDB.prototype.search = function (searchString) {
|
||
|
var db = this;
|
||
|
this.searchString = searchString;
|
||
|
|
||
|
// See if this key has been searched for before
|
||
|
if (this.cache[searchString]) {
|
||
|
return this.owner.found(this.cache[searchString]);
|
||
|
}
|
||
|
|
||
|
// Initiate delayed search
|
||
|
if (this.timer) {
|
||
|
clearTimeout(this.timer);
|
||
|
}
|
||
|
this.timer = setTimeout(function() {
|
||
|
db.owner.setStatus('begin');
|
||
|
|
||
|
// Ajax GET request for autocompletion
|
||
|
$.ajax({
|
||
|
type: "GET",
|
||
|
url: db.uri +'/'+ Drupal.encodeURIComponent(searchString),
|
||
|
dataType: 'json',
|
||
|
success: function (matches) {
|
||
|
if (typeof matches['status'] == 'undefined' || matches['status'] != 0) {
|
||
|
db.cache[searchString] = matches;
|
||
|
// Verify if these are still the matches the user wants to see
|
||
|
if (db.searchString == searchString) {
|
||
|
db.owner.found(matches);
|
||
|
}
|
||
|
db.owner.setStatus('found');
|
||
|
}
|
||
|
},
|
||
|
error: function (xmlhttp) {
|
||
|
alert(Drupal.ahahError(xmlhttp, db.uri));
|
||
|
}
|
||
|
});
|
||
|
}, this.delay);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Cancels the current autocomplete request
|
||
|
*/
|
||
|
Drupal.ACDB.prototype.cancel = function() {
|
||
|
if (this.owner) this.owner.setStatus('cancel');
|
||
|
if (this.timer) clearTimeout(this.timer);
|
||
|
this.searchString = '';
|
||
|
};
|
||
|
;// $Id: collapse.js,v 1.17 2008/01/29 10:58:25 goba Exp $
|
||
|
|
||
|
/**
|
||
|
* Toggle the visibility of a fieldset using smooth animations
|
||
|
*/
|
||
|
Drupal.toggleFieldset = function(fieldset) {
|
||
|
if ($(fieldset).is('.collapsed')) {
|
||
|
// Action div containers are processed separately because of a IE bug
|
||
|
// that alters the default submit button behavior.
|
||
|
var content = $('> div:not(.action)', fieldset);
|
||
|
$(fieldset).removeClass('collapsed');
|
||
|
content.hide();
|
||
|
content.slideDown( {
|
||
|
duration: 'fast',
|
||
|
easing: 'linear',
|
||
|
complete: function() {
|
||
|
Drupal.collapseScrollIntoView(this.parentNode);
|
||
|
this.parentNode.animating = false;
|
||
|
$('div.action', fieldset).show();
|
||
|
},
|
||
|
step: function() {
|
||
|
// Scroll the fieldset into view
|
||
|
Drupal.collapseScrollIntoView(this.parentNode);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
$('div.action', fieldset).hide();
|
||
|
var content = $('> div:not(.action)', fieldset).slideUp('fast', function() {
|
||
|
$(this.parentNode).addClass('collapsed');
|
||
|
this.parentNode.animating = false;
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Scroll a given fieldset into view as much as possible.
|
||
|
*/
|
||
|
Drupal.collapseScrollIntoView = function (node) {
|
||
|
var h = self.innerHeight || document.documentElement.clientHeight || $('body')[0].clientHeight || 0;
|
||
|
var offset = self.pageYOffset || document.documentElement.scrollTop || $('body')[0].scrollTop || 0;
|
||
|
var posY = $(node).offset().top;
|
||
|
var fudge = 55;
|
||
|
if (posY + node.offsetHeight + fudge > h + offset) {
|
||
|
if (node.offsetHeight > h) {
|
||
|
window.scrollTo(0, posY);
|
||
|
} else {
|
||
|
window.scrollTo(0, posY + node.offsetHeight - h + fudge);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Drupal.behaviors.collapse = function (context) {
|
||
|
$('fieldset.collapsible > legend:not(.collapse-processed)', context).each(function() {
|
||
|
var fieldset = $(this.parentNode);
|
||
|
// Expand if there are errors inside
|
||
|
if ($('input.error, textarea.error, select.error', fieldset).size() > 0) {
|
||
|
fieldset.removeClass('collapsed');
|
||
|
}
|
||
|
|
||
|
// Turn the legend into a clickable link and wrap the contents of the fieldset
|
||
|
// in a div for easier animation
|
||
|
var text = this.innerHTML;
|
||
|
$(this).empty().append($('<a href="#">'+ text +'</a>').click(function() {
|
||
|
var fieldset = $(this).parents('fieldset:first')[0];
|
||
|
// Don't animate multiple times
|
||
|
if (!fieldset.animating) {
|
||
|
fieldset.animating = true;
|
||
|
Drupal.toggleFieldset(fieldset);
|
||
|
}
|
||
|
return false;
|
||
|
}))
|
||
|
.after($('<div class="fieldset-wrapper"></div>')
|
||
|
.append(fieldset.children(':not(legend):not(.action)')))
|
||
|
.addClass('collapse-processed');
|
||
|
});
|
||
|
};
|
||
|
;// $Id: teaser.js,v 1.12.2.1 2009/05/20 11:50:54 goba Exp $
|
||
|
|
||
|
/**
|
||
|
* Auto-attach for teaser behavior.
|
||
|
*
|
||
|
* Note: depends on resizable textareas.
|
||
|
*/
|
||
|
Drupal.behaviors.teaser = function(context) {
|
||
|
// This breaks in Konqueror. Prevent it from running.
|
||
|
if (/KDE/.test(navigator.vendor)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$('textarea.teaser:not(.teaser-processed)', context).each(function() {
|
||
|
var teaser = $(this).addClass('teaser-processed');
|
||
|
|
||
|
// Move teaser textarea before body, and remove its form-item wrapper.
|
||
|
var body = $('#'+ Drupal.settings.teaser[this.id]);
|
||
|
var checkbox = $('#'+ Drupal.settings.teaserCheckbox[this.id]).parent();
|
||
|
var checked = $(checkbox).children('input').attr('checked') ? true : false;
|
||
|
var parent = teaser[0].parentNode;
|
||
|
$(body).before(teaser);
|
||
|
$(parent).remove();
|
||
|
|
||
|
function trim(text) {
|
||
|
return text.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
||
|
}
|
||
|
|
||
|
// Join the teaser back to the body.
|
||
|
function join_teaser() {
|
||
|
if (teaser.val()) {
|
||
|
body.val(trim(teaser.val()) +'\r\n\r\n'+ trim(body.val()));
|
||
|
}
|
||
|
// Empty, hide and disable teaser.
|
||
|
teaser[0].value = '';
|
||
|
$(teaser).attr('disabled', 'disabled');
|
||
|
$(teaser).parent().slideUp('fast');
|
||
|
// Change label.
|
||
|
$(this).val(Drupal.t('Split summary at cursor'));
|
||
|
// Hide separate teaser checkbox.
|
||
|
$(checkbox).hide();
|
||
|
// Force a hidden checkbox to be checked (to ensure that the body is
|
||
|
// correctly processed on form submit when teaser/body are in joined
|
||
|
// state), and remember the current checked status.
|
||
|
checked = $(checkbox).children('input').attr('checked') ? true : false;
|
||
|
$(checkbox).children('input').attr('checked', true);
|
||
|
}
|
||
|
|
||
|
// Split the teaser from the body.
|
||
|
function split_teaser() {
|
||
|
body[0].focus();
|
||
|
var selection = Drupal.getSelection(body[0]);
|
||
|
var split = selection.start;
|
||
|
var text = body.val();
|
||
|
|
||
|
// Note: using val() fails sometimes. jQuery bug?
|
||
|
teaser[0].value = trim(text.slice(0, split));
|
||
|
body[0].value = trim(text.slice(split));
|
||
|
// Reveal and enable teaser
|
||
|
$(teaser).attr('disabled', '');
|
||
|
$(teaser).parent().slideDown('fast');
|
||
|
// Change label
|
||
|
$(this).val(Drupal.t('Join summary'));
|
||
|
// Show separate teaser checkbox, restore checked value.
|
||
|
$(checkbox).show().children('input').attr('checked', checked);
|
||
|
}
|
||
|
|
||
|
// Add split/join button.
|
||
|
var button = $('<div class="teaser-button-wrapper"><input type="button" class="teaser-button" /></div>');
|
||
|
var include = $('#'+ this.id.substring(0, this.id.length - 2) +'include');
|
||
|
$(include).parent().parent().before(button);
|
||
|
|
||
|
// Extract the teaser from the body, if set. Otherwise, stay in joined mode.
|
||
|
var text = body.val().split('<!--break-->');
|
||
|
if (text.length >= 2) {
|
||
|
teaser[0].value = trim(text.shift());
|
||
|
body[0].value = trim(text.join('<!--break-->'));
|
||
|
$(teaser).attr('disabled', '');
|
||
|
$('input', button).val(Drupal.t('Join summary')).toggle(join_teaser, split_teaser);
|
||
|
}
|
||
|
else {
|
||
|
$('input', button).val(Drupal.t('Split summary at cursor')).toggle(split_teaser, join_teaser);
|
||
|
$(checkbox).hide().children('input').attr('checked', true);
|
||
|
}
|
||
|
|
||
|
// Make sure that textarea.js has done its magic to ensure proper visibility state.
|
||
|
if (Drupal.behaviors.textarea && teaser.is(('.form-textarea:not(.textarea-processed)'))) {
|
||
|
Drupal.behaviors.textarea(teaser.parentNode);
|
||
|
}
|
||
|
// Set initial visibility
|
||
|
if ($(teaser).is('[@disabled]')) {
|
||
|
$(teaser).parent().hide();
|
||
|
}
|
||
|
|
||
|
});
|
||
|
};
|
||
|
;// $Id: textarea.js,v 1.22 2008/01/17 19:31:56 goba Exp $
|
||
|
|
||
|
Drupal.behaviors.textarea = function(context) {
|
||
|
$('textarea.resizable:not(.textarea-processed)', context).each(function() {
|
||
|
// Avoid non-processed teasers.
|
||
|
if ($(this).is(('textarea.teaser:not(.teaser-processed)'))) {
|
||
|
return false;
|
||
|
}
|
||
|
var textarea = $(this).addClass('textarea-processed'), staticOffset = null;
|
||
|
|
||
|
// When wrapping the text area, work around an IE margin bug. See:
|
||
|
// http://jaspan.com/ie-inherited-margin-bug-form-elements-and-haslayout
|
||
|
$(this).wrap('<div class="resizable-textarea"><span></span></div>')
|
||
|
.parent().append($('<div class="grippie"></div>').mousedown(startDrag));
|
||
|
|
||
|
var grippie = $('div.grippie', $(this).parent())[0];
|
||
|
grippie.style.marginRight = (grippie.offsetWidth - $(this)[0].offsetWidth) +'px';
|
||
|
|
||
|
function startDrag(e) {
|
||
|
staticOffset = textarea.height() - e.pageY;
|
||
|
textarea.css('opacity', 0.25);
|
||
|
$(document).mousemove(performDrag).mouseup(endDrag);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
function performDrag(e) {
|
||
|
textarea.height(Math.max(32, staticOffset + e.pageY) + 'px');
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
function endDrag(e) {
|
||
|
$(document).unbind("mousemove", performDrag).unbind("mouseup", endDrag);
|
||
|
textarea.css('opacity', 1);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
;
|