/* Added by module "editor_tools", file "mods/editor_tools/editor_tools.js" */
///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2007 Phorum Development Team //
// http://www.phorum.org //
// //
// This program is free software. You can redistribute it and/or modify //
// it under the terms of either the current Phorum License (viewable at //
// phorum.org) or the Phorum License that was distributed with this file //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY, without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. //
// //
// You should have received a copy of the Phorum License //
// along with this program. //
///////////////////////////////////////////////////////////////////////////////
// Javascript code for the Phorum editor_tools module.
// Valid object ids for textarea objects to handle. The first object
// that can be matched will be use as the object to work with.
// This is done to arrange for backward compatibility between
// Phorum versions.
var editor_tools_textarea_ids = new Array(
'phorum_textarea', // Phorum 5.1
'body', // Phorum 5.2
'message' // PM interface
);
// Valid object ids for subject text field objects to handle.
var editor_tools_subject_ids = new Array(
'phorum_subject', // Phorum 5.1
'subject' // Phorum 5.2
);
// Storage for language translation strings from the Phorum language system.
var editor_tools_lang = new Array();
// Some variables for storing objects that we need globally.
var editor_tools_textarea_obj = null;
var editor_tools_subject_obj = null;
var editor_tools_help_picker_obj = null;
// A variable for storing the current selection range of the 
// textarea. Needed for working around an MSIE problem.
var editor_tools_textarea_range = null;
// A variable for storing all popup objects that we have, so we
// can hide them all at once.
var editor_tools_popup_objects = new Array();
// Storage for the tools that have to be added to the editor tools panel.
// The array value contains the following fields:
//
// 1) the id for the tool (must be unique)
// 2) a description to use as the tooltip title for the button
// 3) the icon image to display as a button.
// 4) the javascript action to run when the user clicks the button
// 5) optional: the width of the icon image
// 6) optional: the height of the icon image (presumed 20px by default)
//
// This array will be filled from PHP-generated javascript.
var editor_tools = new Array();
// Storage for help chapters that must be put under the editor tools
// help button. The array value contains the following fields:
//
// 1) a description that will be used as the clickable link text.
// 2) the url for the help page (absolute or relative to the Phorum dir).
//
// This array will be filled from PHP-generated javascript.
var editor_tools_help_chapters = new Array();
// The dimensions of the help window.
var editor_tools_help_width = '400px';
var editor_tools_help_height = '400px';
// The default height for our icons.
// This one is filled from PHP-generated javascript.
var editor_tools_default_iconheight;
// A simple browser check. We need to know the browser version, because
// the color picker won't work on at least MacOS MSIE 5.
var OLD_MSIE =
navigator.userAgent.indexOf('MSIE')>=0 &&
navigator.appVersion.replace(/.*MSIE (\d\.\d).*/g,'$1')/1 < 6;
// ----------------------------------------------------------------------
// Uitilty functions
// ----------------------------------------------------------------------
// Find the Phorum textarea object and return it. In case of
// problems, null will be returned.
function editor_tools_get_textarea()
{
if (editor_tools_textarea_obj != null) {
return editor_tools_textarea_obj;
}
for (var i=0; editor_tools_textarea_ids[i]; i++) {
editor_tools_textarea_obj =
document.getElementById(editor_tools_textarea_ids[i]);
if (editor_tools_textarea_obj) break;
}
if (! editor_tools_textarea_obj) {
alert("editor_tools.js library reports: " +
"no textarea found on the current page.");
return null;
}
return editor_tools_textarea_obj;
}
// Find the Phorum subject field object and return it. In case of
// problems, null will be returned.
function editor_tools_get_subjectfield()
{
if (editor_tools_subject_obj != null) {
return editor_tools_subject_obj;
}
for (var i=0; editor_tools_subject_ids[i]; i++) {
editor_tools_subject_obj =
document.getElementById(editor_tools_subject_ids[i]);
if (editor_tools_subject_obj) break;
}
if (! editor_tools_subject_obj) {
return null;
}
return editor_tools_subject_obj;
}
// Return a translated string, based on the Phorum language system.
function editor_tools_translate(str)
{
if (editor_tools_lang[str]) {
return editor_tools_lang[str];
} else {
return str;
}
}
// Strip whitespace from the start and end of a string.
function editor_tools_strip_whitespace(str, return_stripped)
{
var strip_pre = '';
var strip_post = '';
// Strip whitespace from end of string.
for (;;) {
var lastchar = str.substring(str.length-1, str.length);
if (lastchar == ' ') {
strip_post += ' ';
str = str.substring(0, str.length-1);
} else {
break;
}
}
// Strip whitespace from start of string.
for (;;) {
var firstchar = str.substring(0,1);
if (firstchar == ' ') {
strip_pre += ' ';
str = str.substring(1);
} else {
break;
}
}
if (return_stripped) {
return new Array(str, strip_pre, strip_post);
} else {
return str;
}
} 
// Close all popup windows and move the focus to the textarea.
function editor_tools_focus_textarea()
{
var textarea_obj = editor_tools_get_textarea();
if (textarea_obj == null) return;
editor_tools_hide_all_popups();
textarea_obj.focus();
}
// Close all popup windows and move the focus to the subject field.
function editor_tools_focus_subjectfield()
{
var subjectfield_obj = editor_tools_get_subjectfield();
if (subjectfield_obj == null) return;
editor_tools_hide_all_popups();
subjectfield_obj.focus();
}
// ----------------------------------------------------------------------
// Construction of the editor tools
// ----------------------------------------------------------------------
// Add the editor tools panel to the page.
function editor_tools_construct()
{
var textarea_obj;
var div_obj;
var parent_obj;
var a_obj;
var img_obj;
// If the browser does not support document.getElementById,
// then the javascript code won't run. Do not display the
// editor tools at all in that case.
if (! document.getElementById) return;
// No editor tools selected to display? Then we're done.
if (editor_tools.length == 0) return;
// Find the textarea and subject field object.
textarea_obj = editor_tools_get_textarea();
if (textarea_obj == null) return; // we consider this fatal.
var subjectfield_obj = editor_tools_get_subjectfield();
// Insert a<div>for containing the buttons, just before the textarea,
// unless there is already an object with id "editor-tools". In that
// case, the existing object is used instead.
div_obj = document.getElementById('editor-tools');
if (! div_obj) {
parent_obj = textarea_obj.parentNode;
div_obj = document.createElement('div');
div_obj.id = 'editor-tools';
parent_obj.insertBefore(div_obj, textarea_obj);
}
// Add the buttons to the new<div>for the editor tools.
for (var i = 0; i < editor_tools.length; i++)
{
var toolinfo = editor_tools[i];
var tool = toolinfo[0];
var description = toolinfo[1];
var icon = toolinfo[2];
var jsaction = toolinfo[3];
var iwidth = toolinfo[4];
var iheight = toolinfo[5];
var target = toolinfo[6];
// Do not use the color picker on MSIE 5. I tested this on a
// Macintosh OS9 system and the color picker about hung MSIE.
if (tool == 'color' && OLD_MSIE) continue;
a_obj = document.createElement('a');
a_obj.id = "editor-tools-a-" + tool;
a_obj.href = "javascript:" + jsaction;
img_obj = document.createElement('img');
img_obj.id = "editor-tools-img-" + tool;
img_obj.className = "editor-tools-button";
img_obj.src = icon;
img_obj.width = iwidth;
img_obj.height = iheight;
img_obj.style.padding = '2px';
img_obj.alt = description;
img_obj.title = description;
// If an icon is added that is less high than our default icon
// height, we try to make the button the same height as the
// others by adding some dynamic padding to it.
if (iheight < editor_tools_default_iconheight) {
var fill = editor_tools_default_iconheight - iheight;
var addbottom = Math.round(fill / 2);
var addtop = fill - addbottom;
img_obj.style.paddingTop = (addtop + 2) + 'px';
img_obj.style.paddingBottom = (addbottom + 2) + 'px';
}
a_obj.appendChild(img_obj);
// Add the button to the page.
// target = subject is a feature that was added for supporting
// the subjectsmiley tool. This one is added to the subject field
// instead of the textarea. 
if (target == 'subject') {
// Find the subject text field. If we can't find one,
// then simply ignore this tool.
if (subjectfield_obj) {
img_obj.style.verticalAlign = 'top';
var parent = subjectfield_obj.parentNode;
var sibling = subjectfield_obj.nextSibling;
parent.insertBefore(a_obj, sibling);
}
} else {
div_obj.appendChild(a_obj);
}
}
// Hide any open popup when the user clicks the textarea or subject field.
textarea_obj.onclick = function() {
editor_tools_hide_all_popups();
};
if (subjectfield_obj) {
subjectfield_obj.onclick = function() {
editor_tools_hide_all_popups();
}
}
}
// ----------------------------------------------------------------------
// Popup window utilities
// ----------------------------------------------------------------------
// Create a popup window.
function editor_tools_construct_popup(create_id, anchor)
{
// Create the outer div for the popup window.
var popup_obj = document.createElement('div');
popup_obj.id = create_id;
popup_obj.className = 'editor-tools-popup';
popup_obj.style.display = 'none';
document.getElementById('editor-tools').appendChild(popup_obj);
popup_obj._anchor = anchor;
// Create the inner content div.
var content_obj = document.createElement('div');
content_obj.id = create_id + '-content';
popup_obj.appendChild(content_obj);
return new Array(popup_obj, content_obj);
}
// Toggle a popup window.
function editor_tools_toggle_popup(popup_obj, button_obj, width, leftoffset)
{
// Determine where to show the popup on screen.
var work_obj = button_obj;
var top = work_obj.offsetTop + work_obj.offsetHeight + 2;
var left = work_obj.offsetLeft;
while (work_obj.offsetParent != null) {
work_obj = work_obj.offsetParent;
left += work_obj.offsetLeft;
top += work_obj.offsetTop;
}
if (leftoffset) left -= leftoffset;
if (width) popup_obj.style.width = width;
// Move the popup window to the right place.
if (popup_obj._anchor == 'r')
{
// Determine the screen width.
var scrwidth = null;
if (document.documentElement.clientWidth) {
// Firefox screen width.
scrwidth = document.documentElement.clientWidth;
} else {
scrwidth = document.body.clientWidth;
// -16 for scrollbar that is counted in in some browsers.
if (document.getElementById && !document.all) {
scrwidth -= 16;
}
}
var right = scrwidth - left - button_obj.offsetWidth;
popup_obj.style.right = right + 'px';
popup_obj.style.top = top + 'px';
} else {
popup_obj.style.left = left + 'px';
popup_obj.style.top = top + 'px';
}
// Toggle the popup window's visibility.
if (popup_obj.style.display == 'none') {
editor_tools_hide_all_popups();
popup_obj.style.display = 'block';
} else {
popup_obj.style.display = 'none';
editor_tools_focus_textarea();
}
}
// Register an object as a popup, so editor_tools_hide_all_popups() 
// can hide it.
function editor_tools_register_popup_object(object)
{
if (! object) return;
editor_tools_popup_objects[editor_tools_popup_objects.length] = object;
}
// Hide all objects that were registered as a popup.
function editor_tools_hide_all_popups()
{
for (var i = 0; i < editor_tools_popup_objects.length; i++) {
var object = editor_tools_popup_objects[i];
object.style.display = 'none';
}
}
// Save the selection range of the textarea. This is needed because
// sometimes clicking in a popup can clear the selection in MSIE.
function editor_tools_store_range()
{
var ta = editor_tools_get_textarea();
if (ta == null || ta.setSelectionRange || ! document.selection) return;
ta.focus();
editor_tools_textarea_range = document.selection.createRange();
}
// Restored a saved textarea selection range.
function editor_tools_restore_range()
{
if (editor_tools_textarea_range != null)
{
editor_tools_textarea_range.select();
editor_tools_textarea_range = null;
}
}
// ----------------------------------------------------------------------
// Textarea manipulation
// ----------------------------------------------------------------------
// Add tags to the textarea. If some text is selected, then place the
// tags around the selected text. If no text is selected and a prompt_str
// is provided, then prompt the user for the data to place inside
// the tags.
function editor_tools_add_tags(pre, post, target, prompt_str)
{
var text;
var pretext;
var posttext;
var range;
var ta = target ? target : editor_tools_get_textarea();
if (ta == null) return;
if(ta.setSelectionRange)
{
// Add pre and post to the text.
pretext = ta.value.substring(0, ta.selectionStart);
text = ta.value.substring(ta.selectionStart, ta.selectionEnd);
posttext = ta.value.substring(ta.selectionEnd, ta.value.length);
if (text == '' && prompt_str) {
text = prompt(prompt_str, '');
if (text == null) return;
}
// Strip whitespace from text selection and move it to the
// pre- and post.
var res = editor_tools_strip_whitespace(text, true);
text = res[0];
pre = res[1] + pre;
post = post + res[2];
ta.value = pretext + pre + text + post + posttext;
// Set the cursor to a logical position.
var cursorpos = pretext.length + pre.length;
if (text.length != 0) cursorpos += text.length + post.length;
ta.setSelectionRange(cursorpos, cursorpos);
ta.focus();
}
else if (document.selection) /* MSIE support */
{
// Add pre and post to the text.
ta.focus();
range = document.selection.createRange();
text = range.text;
if (text == '' && prompt_str) {
text = prompt(prompt_str, '');
if (text == null) return;
}
if (text.length <= 0) {
// Add pre and post to the text.
range.text = pre + post;
// Set the cursor to a logical position.
range.moveStart("character", -(post.length));
range.moveEnd("character", -(post.length));
range.select();
} else {
// Strip whitespace from text selection and move it to the
// pre- and post.
var res = editor_tools_strip_whitespace(text, true);
text = res[0];
pre = res[1] + pre;
post = post + res[2];
// Add pre and post to the text.
range.text = pre + text + post;
// Set the cursor to a logical position.
range.select();
}
} else { /* Support for really limited browsers, e.g. MSIE5 on MacOS */
ta.value = ta.value + pre + post;
}
}
// ----------------------------------------------------------------------
// Tool: Help
// ----------------------------------------------------------------------
function editor_tools_handle_help()
{
var c = editor_tools_help_chapters;
// Shouldn't happen.
if (c.length == 0) {
alert('No help chapters available');
return;
}
// Exactly one help chapter available. Immediately open the chapter.
if (c.length == 1) {
editor_tools_handle_help_select(c[0][1]);
return;
}
// Multiple chapters available. Show a help picker menu with some
// choices. Create the help picker on first access.
if (!editor_tools_help_picker_obj)
{
// Create a new popup.
var popup = editor_tools_construct_popup('editor-tools-help-picker','r');
editor_tools_help_picker_obj = popup[0];
var content_obj = popup[1];
// Populate the new popup.
for (var i = 0; i < editor_tools_help_chapters.length; i++) 
{
var helpinfo = editor_tools_help_chapters[i];
var a_obj = document.createElement('a');
a_obj.href = 'javascript:editor_tools_handle_help_select("' + helpinfo[1] + '")';
a_obj.innerHTML = helpinfo[0];
content_obj.appendChild(a_obj);
content_obj.appendChild(document.createElement('br'));
}
// Register the popup with the editor tools.
editor_tools_register_popup_object(editor_tools_help_picker_obj);
}
// Display the popup.
var button_obj = document.getElementById('editor-tools-img-help');
editor_tools_toggle_popup(editor_tools_help_picker_obj, button_obj);
}
function editor_tools_handle_help_select(url)
{
var help_window = window.open(
url,
'editor_tools_help',
'resizable=yes,' +
'menubar=no,' +
'directories=no,' +
'scrollbars=yes,' +
'toolbar=no,' +
'status=no,' +
'width=' + editor_tools_help_width + ',' +
'height=' + editor_tools_help_height
);
editor_tools_focus_textarea();
help_window.focus();
}
/* Added by module "smileys", file "mods/smileys/smileys_editor_tools.js.php" */
///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2007 Phorum Development Team //
// http://www.phorum.org //
// //
// This program is free software. You can redistribute it and/or modify //
// it under the terms of either the current Phorum License (viewable at //
// phorum.org) or the Phorum License that was distributed with this file //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY, without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. //
// //
// You should have received a copy of the Phorum License //
// along with this program. //
///////////////////////////////////////////////////////////////////////////////
// Javascript code for Smileys support in the Phorum editor_tools module.
// Some variables for storing objects that we need globally.
var editor_tools_smiley_picker_obj = null;
var editor_tools_subjectsmiley_picker_obj = null;
// Smileys for the smiley picker.
// *_s = search strings (smileys)
// *_r = replace strings (image urls)
var editor_tools_smileys = new Array();
var editor_tools_smileys_r = new Array();
var editor_tools_smileys_a = new Array();
var editor_tools_subjectsmileys = new Array();
var editor_tools_subjectsmileys_r = new Array();
var editor_tools_subjectsmileys_a = new Array();
// The width and offset to the left for the smiley picker popup menus.
// These values can be tweaked from the smiley module settings page.
var editor_tools_smileys_popupwidth = '150px';
var editor_tools_smileys_popupoffset = 0;
var editor_tools_subjectsmileys_popupwidth = '150px';
var editor_tools_subjectsmileys_popupoffset = 0;
// The available smileys.
editor_tools_smileys[0] = '(:P)';
editor_tools_smileys_r[0] = 'http://www.botbh.com/./mods/smileys/images/smiley25.gif';
editor_tools_smileys_a[0] = 'spinning smiley sticking its tongue out';
editor_tools_subjectsmileys[0] = '(:P)';
editor_tools_subjectsmileys_r[0] = 'http://www.botbh.com/./mods/smileys/images/smiley25.gif';
editor_tools_subjectsmileys_a[0] = 'spinning smiley sticking its tongue out';
editor_tools_smileys[1] = '(td)';
editor_tools_smileys_r[1] = 'http://www.botbh.com/./mods/smileys/images/smiley23.gif';
editor_tools_smileys_a[1] = 'thumbs down';
editor_tools_subjectsmileys[1] = '(td)';
editor_tools_subjectsmileys_r[1] = 'http://www.botbh.com/./mods/smileys/images/smiley23.gif';
editor_tools_subjectsmileys_a[1] = 'thumbs down';
editor_tools_smileys[2] = '(tu)';
editor_tools_smileys_r[2] = 'http://www.botbh.com/./mods/smileys/images/smiley24.gif';
editor_tools_smileys_a[2] = 'thumbs up';
editor_tools_subjectsmileys[2] = '(tu)';
editor_tools_subjectsmileys_r[2] = 'http://www.botbh.com/./mods/smileys/images/smiley24.gif';
editor_tools_subjectsmileys_a[2] = 'thumbs up';
editor_tools_smileys[3] = ':)-D';
editor_tools_smileys_r[3] = 'http://www.botbh.com/./mods/smileys/images/smiley15.gif';
editor_tools_smileys_a[3] = 'smileys with beer';
editor_tools_subjectsmileys[3] = ':)-D';
editor_tools_subjectsmileys_r[3] = 'http://www.botbh.com/./mods/smileys/images/smiley15.gif';
editor_tools_subjectsmileys_a[3] = 'smileys with beer';
editor_tools_smileys[4] = '>:D<';
editor_tools_smileys_r[4] = 'http://www.botbh.com/./mods/smileys/images/smiley14.gif';
editor_tools_smileys_a[4] = 'the finger smiley';
editor_tools_subjectsmileys[4] = '>:D<';
editor_tools_subjectsmileys_r[4] = 'http://www.botbh.com/./mods/smileys/images/smiley14.gif';
editor_tools_subjectsmileys_a[4] = 'the finger smiley';
editor_tools_smileys[5] = '(:D';
editor_tools_smileys_r[5] = 'http://www.botbh.com/./mods/smileys/images/smiley12.gif';
editor_tools_smileys_a[5] = 'smiling bouncing smiley';
editor_tools_subjectsmileys[5] = '(:D';
editor_tools_subjectsmileys_r[5] = 'http://www.botbh.com/./mods/smileys/images/smiley12.gif';
editor_tools_subjectsmileys_a[5] = 'smiling bouncing smiley';
editor_tools_smileys[6] = '8-)';
editor_tools_smileys_r[6] = 'http://www.botbh.com/./mods/smileys/images/smilie8.gif';
editor_tools_smileys_a[6] = 'eye rolling smiley';
editor_tools_subjectsmileys[6] = '8-)';
editor_tools_subjectsmileys_r[6] = 'http://www.botbh.com/./mods/smileys/images/smilie8.gif';
editor_tools_subjectsmileys_a[6] = 'eye rolling smiley';
editor_tools_smileys[7] = ':)o';
editor_tools_smileys_r[7] = 'http://www.botbh.com/./mods/smileys/images/smiley16.gif';
editor_tools_smileys_a[7] = 'drinking smiley';
editor_tools_subjectsmileys[7] = ':)o';
editor_tools_subjectsmileys_r[7] = 'http://www.botbh.com/./mods/smileys/images/smiley16.gif';
editor_tools_subjectsmileys_a[7] = 'drinking smiley';
editor_tools_smileys[8] = '::o';
editor_tools_smileys_r[8] = 'http://www.botbh.com/./mods/smileys/images/smilie10.gif';
editor_tools_smileys_a[8] = 'eye popping smiley';
editor_tools_subjectsmileys[8] = '::o';
editor_tools_subjectsmileys_r[8] = 'http://www.botbh.com/./mods/smileys/images/smilie10.gif';
editor_tools_subjectsmileys_a[8] = 'eye popping smiley';
editor_tools_smileys[9] = 'B)-';
editor_tools_smileys_r[9] = 'http://www.botbh.com/./mods/smileys/images/smilie7.gif';
editor_tools_smileys_a[9] = 'smoking smiley';
editor_tools_subjectsmileys[9] = 'B)-';
editor_tools_subjectsmileys_r[9] = 'http://www.botbh.com/./mods/smileys/images/smilie7.gif';
editor_tools_subjectsmileys_a[9] = 'smoking smiley';
editor_tools_smileys[10] = ':(';
editor_tools_smileys_r[10] = 'http://www.botbh.com/./mods/smileys/images/smilie2.gif';
editor_tools_smileys_a[10] = 'sad smiley';
editor_tools_subjectsmileys[10] = ':(';
editor_tools_subjectsmileys_r[10] = 'http://www.botbh.com/./mods/smileys/images/smilie2.gif';
editor_tools_subjectsmileys_a[10] = 'sad smiley';
editor_tools_smileys[11] = ':)';
editor_tools_smileys_r[11] = 'http://www.botbh.com/./mods/smileys/images/smilie1.gif';
editor_tools_smileys_a[11] = 'smiling smiley';
editor_tools_subjectsmileys[11] = ':)';
editor_tools_subjectsmileys_r[11] = 'http://www.botbh.com/./mods/smileys/images/smilie1.gif';
editor_tools_subjectsmileys_a[11] = 'smiling smiley';
editor_tools_smileys[12] = ':?';
editor_tools_smileys_r[12] = 'http://www.botbh.com/./mods/smileys/images/smiley17.gif';
editor_tools_smileys_a[12] = 'moody smiley';
editor_tools_subjectsmileys[12] = ':?';
editor_tools_subjectsmileys_r[12] = 'http://www.botbh.com/./mods/smileys/images/smiley17.gif';
editor_tools_subjectsmileys_a[12] = 'moody smiley';
editor_tools_smileys[13] = ':D';
editor_tools_smileys_r[13] = 'http://www.botbh.com/./mods/smileys/images/smilie5.gif';
editor_tools_smileys_a[13] = 'grinning smiley';
editor_tools_subjectsmileys[13] = ':D';
editor_tools_subjectsmileys_r[13] = 'http://www.botbh.com/./mods/smileys/images/smilie5.gif';
editor_tools_subjectsmileys_a[13] = 'grinning smiley';
editor_tools_smileys[14] = ':P';
editor_tools_smileys_r[14] = 'http://www.botbh.com/./mods/smileys/images/smilie6.gif';
editor_tools_smileys_a[14] = 'tongue sticking out smiley';
editor_tools_subjectsmileys[14] = ':P';
editor_tools_subjectsmileys_r[14] = 'http://www.botbh.com/./mods/smileys/images/smilie6.gif';
editor_tools_subjectsmileys_a[14] = 'tongue sticking out smiley';
editor_tools_smileys[15] = ':S';
editor_tools_smileys_r[15] = 'http://www.botbh.com/./mods/smileys/images/smilie11.gif';
editor_tools_smileys_a[15] = 'confused smiley';
editor_tools_subjectsmileys[15] = ':S';
editor_tools_subjectsmileys_r[15] = 'http://www.botbh.com/./mods/smileys/images/smilie11.gif';
editor_tools_subjectsmileys_a[15] = 'confused smiley';
editor_tools_smileys[16] = ':X';
editor_tools_smileys_r[16] = 'http://www.botbh.com/./mods/smileys/images/smilie9.gif';
editor_tools_smileys_a[16] = 'angry smiley';
editor_tools_subjectsmileys[16] = ':X';
editor_tools_subjectsmileys_r[16] = 'http://www.botbh.com/./mods/smileys/images/smilie9.gif';
editor_tools_subjectsmileys_a[16] = 'angry smiley';
editor_tools_smileys[17] = ':o';
editor_tools_smileys_r[17] = 'http://www.botbh.com/./mods/smileys/images/smilie4.gif';
editor_tools_smileys_a[17] = 'yawning smiley';
editor_tools_subjectsmileys[17] = ':o';
editor_tools_subjectsmileys_r[17] = 'http://www.botbh.com/./mods/smileys/images/smilie4.gif';
editor_tools_subjectsmileys_a[17] = 'yawning smiley';
editor_tools_smileys[18] = ';)';
editor_tools_smileys_r[18] = 'http://www.botbh.com/./mods/smileys/images/smilie3.gif';
editor_tools_smileys_a[18] = 'winking smiley';
editor_tools_subjectsmileys[18] = ';)';
editor_tools_subjectsmileys_r[18] = 'http://www.botbh.com/./mods/smileys/images/smilie3.gif';
editor_tools_subjectsmileys_a[18] = 'winking smiley';
editor_tools_smileys[19] = 'B)';
editor_tools_smileys_r[19] = 'http://www.botbh.com/./mods/smileys/images/cool.gif';
editor_tools_smileys_a[19] = 'cool smiley';
editor_tools_subjectsmileys[19] = 'B)';
editor_tools_subjectsmileys_r[19] = 'http://www.botbh.com/./mods/smileys/images/cool.gif';
editor_tools_subjectsmileys_a[19] = 'cool smiley';
editor_tools_smileys[20] = 'X(';
editor_tools_smileys_r[20] = 'http://www.botbh.com/./mods/smileys/images/hot.gif';
editor_tools_smileys_a[20] = 'hot smiley';
editor_tools_subjectsmileys[20] = 'X(';
editor_tools_subjectsmileys_r[20] = 'http://www.botbh.com/./mods/smileys/images/hot.gif';
editor_tools_subjectsmileys_a[20] = 'hot smiley';
// ----------------------------------------------------------------------
// Tool: smiley
// ----------------------------------------------------------------------
function editor_tools_handle_smiley()
{
// Create the smiley picker on first access.
if (!editor_tools_smiley_picker_obj)
{
// Create a new popup.
var popup = editor_tools_construct_popup('editor-tools-smiley-picker','l');
editor_tools_smiley_picker_obj = popup[0];
var content_obj = popup[1];
editor_tools_smiley_picker_obj.style.width = editor_tools_smileys_popupwidth;
// Populate the new popup.
for (var i = 0; i < editor_tools_smileys.length; i++)
{
var s = editor_tools_smileys[i];
var r = editor_tools_smileys_r[i];
var a = editor_tools_smileys_a[i];
var a_obj = document.createElement('a');
a_obj.href = 'javascript:editor_tools_handle_smiley_select("'+s+'")';
var img_obj = document.createElement('img');
img_obj.src = r;
img_obj.title = a;
img_obj.alt = a;
a_obj.appendChild(img_obj);
content_obj.appendChild(a_obj);
}
// Register the popup with the editor tools.
editor_tools_register_popup_object(editor_tools_smiley_picker_obj);
}
// Display the popup.
var button_obj = document.getElementById('editor-tools-img-smiley');
editor_tools_toggle_popup(
editor_tools_smiley_picker_obj,
button_obj,
editor_tools_smileys_popupwidth,
editor_tools_smileys_popupoffset
);
}
// Called by the smiley picker.
function editor_tools_handle_smiley_select(smiley)
{
smiley = editor_tools_strip_whitespace(smiley);
editor_tools_add_tags(smiley, '');
editor_tools_focus_textarea();
}
function editor_tools_handle_subjectsmiley()
{
// Create the smiley picker on first access.
if (!editor_tools_subjectsmiley_picker_obj)
{
// Create a new popup.
var popup = editor_tools_construct_popup('editor-tools-subjectsmiley-picker','l');
editor_tools_subjectsmiley_picker_obj = popup[0];
var content_obj = popup[1];
// Populate the new popup.
for (var i = 0; i < editor_tools_subjectsmileys.length; i++)
{
var s = editor_tools_subjectsmileys[i];
var r = editor_tools_subjectsmileys_r[i];
var a = editor_tools_subjectsmileys_a[i];
var a_obj = document.createElement('a');
a_obj.href = 'javascript:editor_tools_handle_subjectsmiley_select("'+s+'")';
var img_obj = document.createElement('img');
img_obj.src = r;
img_obj.alt = a;
img_obj.title = a;
a_obj.appendChild(img_obj);
content_obj.appendChild(a_obj);
}
// Register the popup with the editor tools.
editor_tools_register_popup_object(editor_tools_subjectsmiley_picker_obj);
}
// Display the popup.
var button_obj = document.getElementById('editor-tools-img-subjectsmiley');
editor_tools_toggle_popup(
editor_tools_subjectsmiley_picker_obj,
button_obj,
editor_tools_subjectsmileys_popupwidth,
editor_tools_subjectsmileys_popupoffset
);
}
// Called by the subject smiley picker.
function editor_tools_handle_subjectsmiley_select(smiley)
{
smiley = editor_tools_strip_whitespace(smiley);
editor_tools_add_tags(smiley, '', editor_tools_subject_obj);
editor_tools_focus_subjectfield();
}
// ----------------------------------------------------------------------
// Tool: subject smiley
// ----------------------------------------------------------------------
function editor_tools_handle_subjectsmiley()
{
// Create the smiley picker on first access.
if (!editor_tools_subjectsmiley_picker_obj)
{
// Create a new popup.
var popup = editor_tools_construct_popup('editor-tools-subjectsmiley-picker','l');
editor_tools_subjectsmiley_picker_obj = popup[0];
var content_obj = popup[1];
// Populate the new popup.
for (var i = 0; i < editor_tools_subjectsmileys.length; i++)
{
var s = editor_tools_subjectsmileys[i];
var r = editor_tools_subjectsmileys_r[i];
var a = editor_tools_subjectsmileys_a[i];
var a_obj = document.createElement('a');
a_obj.href = 'javascript:editor_tools_handle_subjectsmiley_select("'+s+'")';
var img_obj = document.createElement('img');
img_obj.src = r;
img_obj.alt = a;
img_obj.title = a;
a_obj.appendChild(img_obj);
content_obj.appendChild(a_obj);
}
// Register the popup with the editor tools.
editor_tools_register_popup_object(editor_tools_subjectsmiley_picker_obj);
}
// Display the popup.
var button_obj = document.getElementById('editor-tools-img-subjectsmiley');
editor_tools_toggle_popup(
editor_tools_subjectsmiley_picker_obj,
button_obj,
editor_tools_subjectsmileys_popupwidth,
editor_tools_subjectsmileys_popupoffset
);
}
// Called by the subject smiley picker.
function editor_tools_handle_subjectsmiley_select(smiley)
{
smiley = editor_tools_strip_whitespace(smiley);
editor_tools_add_tags(smiley, '', editor_tools_subject_obj);
editor_tools_focus_subjectfield();
}
/* Added by module "embed_images", file "mods/embed_images/embed_images.js" */
function mod_embed_images_loadimage(viewer_id, thumbnail_url, fullimage_url, ajax_url, target_url, message_id, max_w, max_h, loading_txt, rescheduled)
{
var container = document.getElementById('imagediv_'+viewer_id);
if (!container) return;
// If the image for the viewer id is already on the page, then we are
// handling a cached thumbnail for which no Ajax magic is required,
// but which is already loaded in the page. We'll only use this function
// for setting up a full size image viewer.
var image = document.getElementById('image_'+viewer_id);
if (image)
{
// If a function was loaded for a viewer to initialize the
// viewer, then hand over the image data to that function.
// Don't do this in case we have a target_url.
if (window.mod_embed_images_initviewer && !target_url) {
var link = document.getElementById('link_'+viewer_id);
mod_embed_images_initviewer(
container, image, link, fullimage_url, message_id
);
}
return;
}
if (!rescheduled)
{
// We use a bit of a strange hack here, by checking for readyState.
// This is not availble in all browsers. That's no problem though.
// We mainly want MSIE to check it and to let it postpone image
// loading till after the page is fully loaded. When doing things
// earlier in MSIE from script code that is not a direct descendant
// of<body>, we might get "operation aborted" errors.
if (document.readyState &&
document.readyState != 'loaded' &&
document.readyState != 'complete' &&
window.attachEvent &&
!window.opera) {
window.attachEvent('onload', function() {
mod_embed_images_loadimage(
viewer_id, thumbnail_url, fullimage_url,
ajax_url, target_url, message_id,
max_w, max_h, loading_txt, true
);
});
return;
}
// Display a "Loading ..." message to the user.
container.innerHTML =
'<div class="mod_embed_images_loading">' +
loading_txt +
'<\/div>';
}
// Create the XMLHttpRequest object that we can use to send an
// Ajax request to the server.
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
var versions = [
"MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0",
"MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp",
"Microsoft.XMLHttp"
];
for (var i=0; i < versions.length; i++)
try { xhr = new ActiveXObject(versions[i]); } catch (e) { }
}
// No XMLHttpRequest object found? Fallback to a simpler way of
// displaying the thumbnail image. This way we won't have
// loading or error feedback and full size viewer support,
// but at least we do show the image. This should't happen for
// modern browsers.
if (!xhr)
{
target.innerHTML =
(target_url ? '<a href="'+target_url+'">' : '') +
'<img id="image_'+viewer_id+'" src="'+thumbnail_url+'"/>' +
(target_url ? '<\/a>' : '');
return;
}
// Setup the XMLHttpRequest object for the request.
xhr.open("get", ajax_url, true);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4 && xhr.status == 200)
{
var res = xhr.responseText;
// An "OK <w>x<h> <scw>x<sch>" message was returned.
if (res.substr(0,2) == 'OK')
{
// Parse the respones message.
// I know... a bit old school parsing.
var dim = res.substr(3);
var xpos = dim.indexOf('x');
var spos = dim.indexOf(' ');
var origw = dim.substr(0,xpos);
var origh = dim.substr(xpos+1, spos-xpos-1);
dim = dim.substr(spos+1);
xpos = dim.indexOf('x');
var w = dim.substr(0,xpos);
var h = dim.substr(xpos+1);
var origsize = origw+"x"+origh;
var scalesize = w+"x"+h;
var is_scaled = (origsize != scalesize);
// Opera does not seem to load images that are not visible :(
// So for those, we never get an onload event. Therefore,
// we make the image 0x0 pixels and resize it to the real
// size after loading.
var html =
(target_url ? '<a href="'+target_url+'">' : '') +
'<img style="width:0px;height:0px" ' +
'id="image_'+viewer_id+'" ' +
'onload="' +
'mod_embed_images_image_loaded(this,'+w+','+h+')" ' +
'src="'+thumbnail_url+'"/>' +
(target_url ? '<\/a>' : '');
container.innerHTML += html;
// Go to extended viewer mode if the image was scaled down
// or if a target URL was provided.
if (is_scaled || target_url)
{
var info = document.getElementById('info_'+viewer_id);
if (info) info.style.display = 'block';
var div = document.getElementById('div_'+viewer_id);
if (div) div.className = 'mod_embed_images_extended';
}
// If a function was loaded for a viewer to initialize the
// viewer, then hand over the image data to that function.
if (window.mod_embed_images_initviewer) {
var image = document.getElementById('image_'+viewer_id);
var link = document.getElementById('link_'+viewer_id);
mod_embed_images_initviewer(
container, image, link, fullimage_url, message_id
);
}
}
// Some error message was returned. Show the error to the user.
else container.innerHTML =
'<div class="mod_embed_images_error">' +
'<strong>Image error<\/strong><br\/>' +
res + '<br/>' +
'<a href="' + fullimage_url + '">open image URL<\/a>' +
'<\/div>';
}
}
// Send the request to the server.
xhr.send('');
}
function mod_embed_images_image_loaded(image, w, h)
{
image.style.width = w+'px';
image.style.height = h+'px';
var container = image.parentNode;
while (container.className != 'mod_embed_images_image') {
container = container.parentNode;
if (!container) return; // Should not happen.
}
container.style.width = image.width + 'px';
container.parentNode.style.width = parseInt(image.width) + 'px';
container.style.height = image.height + 'px';
for (var i = 0; i < container.childNodes.length; i++) {
if (container.childNodes[i].className == 'mod_embed_images_loading') {
container.childNodes[i].style.display = 'none';
}
}
}
/* Added by module "embed_images/viewer:lightbox", file "mods/embed_images/viewers/lightbox/code/js/prototype.js" */
/* Prototype JavaScript framework, version 1.4.0
* (c) 2005 Sam Stephenson <sam@conio.net>
*
* THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
* against the source tree, available from the Prototype darcs repository.
*
* Prototype is freely distributable under the terms of an MIT-style license.
*
* For details, see the Prototype web site: http://prototype.conio.net/
*
/*--------------------------------------------------------------------------*/
var Prototype = {
Version: '1.4.0',
ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
emptyFunction: function() {},
K: function(x) {return x}
}
var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
var Abstract = new Object();
Object.extend = function(destination, source) {
for (property in source) {
destination[property] = source[property];
}
return destination;
}
Object.inspect = function(object) {
try {
if (object == undefined) return 'undefined';
if (object == null) return 'null';
return object.inspect ? object.inspect() : object.toString();
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
}
Function.prototype.bind = function() {
var __method = this, args = $A(arguments), object = args.shift();
return function() {
return __method.apply(object, args.concat($A(arguments)));
}
}
Function.prototype.bindAsEventListener = function(object) {
var __method = this;
return function(event) {
return __method.call(object, event || window.event);
}
}
Object.extend(Number.prototype, {
toColorPart: function() {
var digits = this.toString(16);
if (this < 16) return '0' + digits;
return digits;
},
succ: function() {
return this + 1;
},
times: function(iterator) {
$R(0, this, true).each(iterator);
return this;
}
});
var Try = {
these: function() {
var returnValue;
for (var i = 0; i < arguments.length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) {}
}
return returnValue;
}
}
/*--------------------------------------------------------------------------*/
var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
this.registerCallback();
},
registerCallback: function() {
setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.callback();
} finally {
this.currentlyExecuting = false;
}
}
}
}
/*--------------------------------------------------------------------------*/
function $() {
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string')
element = document.getElementById(element);
if (arguments.length == 1)
return element;
elements.push(element);
}
return elements;
}
Object.extend(String.prototype, {
stripTags: function() {
return this.replace(/<\/?[^>]+>/gi, '');
},
stripScripts: function() {
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
},
extractScripts: function() {
var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
return (this.match(matchAll) || []).map(function(scriptTag) {
return (scriptTag.match(matchOne) || ['', ''])[1];
});
},
evalScripts: function() {
return this.extractScripts().map(eval);
},
escapeHTML: function() {
var div = document.createElement('div');
var text = document.createTextNode(this);
div.appendChild(text);
return div.innerHTML;
},
unescapeHTML: function() {
var div = document.createElement('div');
div.innerHTML = this.stripTags();
return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
},
toQueryParams: function() {
var pairs = this.match(/^\??(.*)$/)[1].split('&');
return pairs.inject({}, function(params, pairString) {
var pair = pairString.split('=');
params[pair[0]] = pair[1];
return params;
});
},
toArray: function() {
return this.split('');
},
camelize: function() {
var oStringList = this.split('-');
if (oStringList.length == 1) return oStringList[0];
var camelizedString = this.indexOf('-') == 0
? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
: oStringList[0];
for (var i = 1, len = oStringList.length; i < len; i++) {
var s = oStringList[i];
camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
}
return camelizedString;
},
inspect: function() {
return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
}
});
String.prototype.parseQuery = String.prototype.toQueryParams;
var $break = new Object();
var $continue = new Object();
var Enumerable = {
each: function(iterator) {
var index = 0;
try {
this._each(function(value) {
try {
iterator(value, index++);
} catch (e) {
if (e != $continue) throw e;
}
});
} catch (e) {
if (e != $break) throw e;
}
},
all: function(iterator) {
var result = true;
this.each(function(value, index) {
result = result && !!(iterator || Prototype.K)(value, index);
if (!result) throw $break;
});
return result;
},
any: function(iterator) {
var result = true;
this.each(function(value, index) {
if (result = !!(iterator || Prototype.K)(value, index))
throw $break;
});
return result;
},
collect: function(iterator) {
var results = [];
this.each(function(value, index) {
results.push(iterator(value, index));
});
return results;
},
detect: function (iterator) {
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
result = value;
throw $break;
}
});
return result;
},
findAll: function(iterator) {
var results = [];
this.each(function(value, index) {
if (iterator(value, index))
results.push(value);
});
return results;
},
grep: function(pattern, iterator) {
var results = [];
this.each(function(value, index) {
var stringValue = value.toString();
if (stringValue.match(pattern))
results.push((iterator || Prototype.K)(value, index));
})
return results;
},
include: function(object) {
var found = false;
this.each(function(value) {
if (value == object) {
found = true;
throw $break;
}
});
return found;
},
inject: function(memo, iterator) {
this.each(function(value, index) {
memo = iterator(memo, value, index);
});
return memo;
},
invoke: function(method) {
var args = $A(arguments).slice(1);
return this.collect(function(value) {
return value[method].apply(value, args);
});
},
max: function(iterator) {
var result;
this.each(function(value, index) {
value = (iterator || Prototype.K)(value, index);
if (value >= (result || value))
result = value;
});
return result;
},
min: function(iterator) {
var result;
this.each(function(value, index) {
value = (iterator || Prototype.K)(value, index);
if (value <= (result || value))
result = value;
});
return result;
},
partition: function(iterator) {
var trues = [], falses = [];
this.each(function(value, index) {
((iterator || Prototype.K)(value, index) ?
trues : falses).push(value);
});
return [trues, falses];
},
pluck: function(property) {
var results = [];
this.each(function(value, index) {
results.push(value[property]);
});
return results;
},
reject: function(iterator) {
var results = [];
this.each(function(value, index) {
if (!iterator(value, index))
results.push(value);
});
return results;
},
sortBy: function(iterator) {
return this.collect(function(value, index) {
return {value: value, criteria: iterator(value, index)};
}).sort(function(left, right) {
var a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
}).pluck('value');
},
toArray: function() {
return this.collect(Prototype.K);
},
zip: function() {
var iterator = Prototype.K, args = $A(arguments);
if (typeof args.last() == 'function')
iterator = args.pop();
var collections = [this].concat(args).map($A);
return this.map(function(value, index) {
iterator(value = collections.pluck(index));
return value;
});
},
inspect: function() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
}
Object.extend(Enumerable, {
map: Enumerable.collect,
find: Enumerable.detect,
select: Enumerable.findAll,
member: Enumerable.include,
entries: Enumerable.toArray
});
var $A = Array.from = function(iterable) {
if (!iterable) return [];
if (iterable.toArray) {
return iterable.toArray();
} else {
var results = [];
for (var i = 0; i < iterable.length; i++)
results.push(iterable[i]);
return results;
}
}
Object.extend(Array.prototype, Enumerable);
Array.prototype._reverse = Array.prototype.reverse;
Object.extend(Array.prototype, {
_each: function(iterator) {
for (var i = 0; i < this.length; i++)
iterator(this[i]);
},
clear: function() {
this.length = 0;
return this;
},
first: function() {
return this[0];
},
last: function() {
return this[this.length - 1];
},
compact: function() {
return this.select(function(value) {
return value != undefined || value != null;
});
},
flatten: function() {
return this.inject([], function(array, value) {
return array.concat(value.constructor == Array ?
value.flatten() : [value]);
});
},
without: function() {
var values = $A(arguments);
return this.select(function(value) {
return !values.include(value);
});
},
indexOf: function(object) {
for (var i = 0; i < this.length; i++)
if (this[i] == object) return i;
return -1;
},
reverse: function(inline) {
return (inline !== false ? this : this.toArray())._reverse();
},
shift: function() {
var result = this[0];
for (var i = 0; i < this.length - 1; i++)
this[i] = this[i + 1];
this.length--;
return result;
},
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
}
});
var Hash = {
_each: function(iterator) {
for (key in this) {
var value = this[key];
if (typeof value == 'function') continue;
var pair = [key, value];
pair.key = key;
pair.value = value;
iterator(pair);
}
},
keys: function() {
return this.pluck('key');
},
values: function() {
return this.pluck('value');
},
merge: function(hash) {
return $H(hash).inject($H(this), function(mergedHash, pair) {
mergedHash[pair.key] = pair.value;
return mergedHash;
});
},
toQueryString: function() {
return this.map(function(pair) {
return pair.map(encodeURIComponent).join('=');
}).join('&');
},
inspect: function() {
return '#<Hash:{' + this.map(function(pair) {
return pair.map(Object.inspect).join(': ');
}).join(', ') + '}>';
}
}
function $H(object) {
var hash = Object.extend({}, object || {});
Object.extend(hash, Enumerable);
Object.extend(hash, Hash);
return hash;
}
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
initialize: function(start, end, exclusive) {
this.start = start;
this.end = end;
this.exclusive = exclusive;
},
_each: function(iterator) {
var value = this.start;
do {
iterator(value);
value = value.succ();
} while (this.include(value));
},
include: function(value) {
if (value < this.start)
return false;
if (this.exclusive)
return value < this.end;
return value <= this.end;
}
});
var $R = function(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
}
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')},
function() {return new XMLHttpRequest()}
) || false;
},
activeRequestCount: 0
}
Ajax.Responders = {
responders: [],
_each: function(iterator) {
this.responders._each(iterator);
},
register: function(responderToAdd) {
if (!this.include(responderToAdd))
this.responders.push(responderToAdd);
},
unregister: function(responderToRemove) {
this.responders = this.responders.without(responderToRemove);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
if (responder[callback] && typeof responder[callback] == 'function') {
try {
responder[callback].apply(responder, [request, transport, json]);
} catch (e) {}
}
});
}
};
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
onCreate: function() {
Ajax.activeRequestCount++;
},
onComplete: function() {
Ajax.activeRequestCount--;
}
});
Ajax.Base = function() {};
Ajax.Base.prototype = {
setOptions: function(options) {
this.options = {
method: 'post',
asynchronous: true,
parameters: ''
}
Object.extend(this.options, options || {});
},
responseIsSuccess: function() {
return this.transport.status == undefined
|| this.transport.status == 0
|| (this.transport.status >= 200 && this.transport.status < 300);
},
responseIsFailure: function() {
return !this.responseIsSuccess();
}
}
Ajax.Request = Class.create();
Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
initialize: function(url, options) {
this.transport = Ajax.getTransport();
this.setOptions(options);
this.request(url);
},
request: function(url) {
var parameters = this.options.parameters || '';
if (parameters.length > 0) parameters += '&_=';
try {
this.url = url;
if (this.options.method == 'get' && parameters.length > 0)
this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
Ajax.Responders.dispatch('onCreate', this, this.transport);
this.transport.open(this.options.method, this.url,
this.options.asynchronous);
if (this.options.asynchronous) {
this.transport.onreadystatechange = this.onStateChange.bind(this);
setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
}
this.setRequestHeaders();
var body = this.options.postBody ? this.options.postBody : parameters;
this.transport.send(this.options.method == 'post' ? body : null);
} catch (e) {
this.dispatchException(e);
}
},
setRequestHeaders: function() {
var requestHeaders =
['X-Requested-With', 'XMLHttpRequest',
'X-Prototype-Version', Prototype.Version];
if (this.options.method == 'post') {
requestHeaders.push('Content-type',
'application/x-www-form-urlencoded');
/* Force "Connection: close" for Mozilla browsers to work around
* a bug where XMLHttpReqeuest sends an incorrect Content-length
* header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType)
requestHeaders.push('Connection', 'close');
}
if (this.options.requestHeaders)
requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
for (var i = 0; i < requestHeaders.length; i += 2)
this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
},
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState != 1)
this.respondToReadyState(this.transport.readyState);
},
header: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) {}
},
evalJSON: function() {
try {
return eval(this.header('X-JSON'));
} catch (e) {}
},
evalResponse: function() {
try {
return eval(this.transport.responseText);
} catch (e) {
this.dispatchException(e);
}
},
respondToReadyState: function(readyState) {
var event = Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON();
if (event == 'Complete') {
try {
(this.options['on' + this.transport.status]
|| this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(transport, json);
} catch (e) {
this.dispatchException(e);
}
if ((this.header('Content-type') || '').match(/^text\/javascript/i))
this.evalResponse();
}
try {
(this.options['on' + event] || Prototype.emptyFunction)(transport, json);
Ajax.Responders.dispatch('on' + event, this, transport, json);
} catch (e) {
this.dispatchException(e);
}
/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
if (event == 'Complete')
this.transport.onreadystatechange = Prototype.emptyFunction;
},
dispatchException: function(exception) {
(this.options.onException || Prototype.emptyFunction)(this, exception);
Ajax.Responders.dispatch('onException', this, exception);
}
});
Ajax.Updater = Class.create();
Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
initialize: function(container, url, options) {
this.containers = {
success: container.success ? $(container.success) : $(container),
failure: container.failure ? $(container.failure) :
(container.success ? null : $(container))
}
this.transport = Ajax.getTransport();
this.setOptions(options);
var onComplete = this.options.onComplete || Prototype.emptyFunction;
this.options.onComplete = (function(transport, object) {
this.updateContent();
onComplete(transport, object);
}).bind(this);
this.request(url);
},
updateContent: function() {
var receiver = this.responseIsSuccess() ?
this.containers.success : this.containers.failure;
var response = this.transport.responseText;
if (!this.options.evalScripts)
response = response.stripScripts();
if (receiver) {
if (this.options.insertion) {
new this.options.insertion(receiver, response);
} else {
Element.update(receiver, response);
}
}
if (this.responseIsSuccess()) {
if (this.onComplete)
setTimeout(this.onComplete.bind(this), 10);
}
}
});
Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
initialize: function(container, url, options) {
this.setOptions(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.options.frequency || 2);
this.decay = (this.options.decay || 1);
this.updater = {};
this.container = container;
this.url = url;
this.start();
},
start: function() {
this.options.onComplete = this.updateComplete.bind(this);
this.onTimerEvent();
},
stop: function() {
this.updater.onComplete = undefined;
clearTimeout(this.timer);
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
updateComplete: function(request) {
if (this.options.decay) {
this.decay = (request.responseText == this.lastText ?
this.decay * this.options.decay : 1);
this.lastText = request.responseText;
}
this.timer = setTimeout(this.onTimerEvent.bind(this),
this.decay * this.frequency * 1000);
},
onTimerEvent: function() {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
document.getElementsByClassName = function(className, parentElement) {
var children = ($(parentElement) || document.body).getElementsByTagName('*');
return $A(children).inject([], function(elements, child) {
if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
elements.push(child);
return elements;
});
}
/*--------------------------------------------------------------------------*/
if (!window.Element) {
var Element = new Object();
}
Object.extend(Element, {
visible: function(element) {
return $(element).style.display != 'none';
},
toggle: function() {
for (var i = 0; i < arguments.length; i++) {
var element = $(arguments[i]);
Element[Element.visible(element) ? 'hide' : 'show'](element);
}
},
hide: function() {
for (var i = 0; i < arguments.length; i++) {
var element = $(arguments[i]);
element.style.display = 'none';
}
},
show: function() {
for (var i = 0; i < arguments.length; i++) {
var element = $(arguments[i]);
element.style.display = '';
}
},
remove: function(element) {
element = $(element);
element.parentNode.removeChild(element);
},
update: function(element, html) {
$(element).innerHTML = html.stripScripts();
setTimeout(function() {html.evalScripts()}, 10);
},
getHeight: function(element) {
element = $(element);
return element.offsetHeight;
},
classNames: function(element) {
return new Element.ClassNames(element);
},
hasClassName: function(element, className) {
if (!(element = $(element))) return;
return Element.classNames(element).include(className);
},
addClassName: function(element, className) {
if (!(element = $(element))) return;
return Element.classNames(element).add(className);
},
removeClassName: function(element, className) {
if (!(element = $(element))) return;
return Element.classNames(element).remove(className);
},
// removes whitespace-only text node children
cleanWhitespace: function(element) {
element = $(element);
for (var i = 0; i < element.childNodes.length; i++) {
var node = element.childNodes[i];
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
Element.remove(node);
}
},
empty: function(element) {
return $(element).innerHTML.match(/^\s*$/);
},
scrollTo: function(element) {
element = $(element);
var x = element.x ? element.x : element.offsetLeft,
y = element.y ? element.y : element.offsetTop;
window.scrollTo(x, y);
},
getStyle: function(element, style) {
element = $(element);
var value = element.style[style.camelize()];
if (!value) {
if (document.defaultView && document.defaultView.getComputedStyle) {
var css = document.defaultView.getComputedStyle(element, null);
value = css ? css.getPropertyValue(style) : null;
} else if (element.currentStyle) {
value = element.currentStyle[style.camelize()];
}
}
if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
if (Element.getStyle(element, 'position') == 'static') value = 'auto';
return value == 'auto' ? null : value;
},
setStyle: function(element, style) {
element = $(element);
for (name in style)
element.style[name.camelize()] = style[name];
},
getDimensions: function(element) {
element = $(element);
if (Element.getStyle(element, 'display') != 'none')
return {width: element.offsetWidth, height: element.offsetHeight};
// All *Width and *Height properties give 0 on elements with display none,
// so enable the element temporarily
var els = element.style;
var originalVisibility = els.visibility;
var originalPosition = els.position;
els.visibility = 'hidden';
els.position = 'absolute';
els.display = '';
var originalWidth = element.clientWidth;
var originalHeight = element.clientHeight;
els.display = 'none';
els.position = originalPosition;
els.visibility = originalVisibility;
return {width: originalWidth, height: originalHeight};
},
makePositioned: function(element) {
element = $(element);
var pos = Element.getStyle(element, 'position');
if (pos == 'static' || !pos) {
element._madePositioned = true;
element.style.position = 'relative';
// Opera returns the offset relative to the positioning context, when an
// element is position relative but top and left have not been defined
if (window.opera) {
element.style.top = 0;
element.style.left = 0;
}
}
},
undoPositioned: function(element) {
element = $(element);
if (element._madePositioned) {
element._madePositioned = undefined;
element.style.position =
element.style.top =
element.style.left =
element.style.bottom =
element.style.right = '';
}
},
makeClipping: function(element) {
element = $(element);
if (element._overflow) return;
element._overflow = element.style.overflow;
if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
element.style.overflow = 'hidden';
},
undoClipping: function(element) {
element = $(element);
if (element._overflow) return;
element.style.overflow = element._overflow;
element._overflow = undefined;
}
});
var Toggle = new Object();
Toggle.display = Element.toggle;
/*--------------------------------------------------------------------------*/
Abstract.Insertion = function(adjacency) {
this.adjacency = adjacency;
}
Abstract.Insertion.prototype = {
initialize: function(element, content) {
this.element = $(element);
this.content = content.stripScripts();
if (this.adjacency && this.element.insertAdjacentHTML) {
try {
this.element.insertAdjacentHTML(this.adjacency, this.content);
} catch (e) {
if (this.element.tagName.toLowerCase() == 'tbody') {
this.insertContent(this.contentFromAnonymousTable());
} else {
throw e;
}
}
} else {
this.range = this.element.ownerDocument.createRange();
if (this.initializeRange) this.initializeRange();
this.insertContent([this.range.createContextualFragment(this.content)]);
}
setTimeout(function() {content.evalScripts()}, 10);
},
contentFromAnonymousTable: function() {
var div = document.createElement('div');
div.innerHTML = '<table><tbody>' + this.content + '<\/tbody><\/table>';
return $A(div.childNodes[0].childNodes[0].childNodes);
}
}
var Insertion = new Object();
Insertion.Before = Class.create();
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
initializeRange: function() {
this.range.setStartBefore(this.element);
},
insertContent: function(fragments) {
fragments.each((function(fragment) {
this.element.parentNode.insertBefore(fragment, this.element);
}).bind(this));
}
});
Insertion.Top = Class.create();
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
initializeRange: function() {
this.range.selectNodeContents(this.element);
this.range.collapse(true);
},
insertContent: function(fragments) {
fragments.reverse(false).each((function(fragment) {
this.element.insertBefore(fragment, this.element.firstChild);
}).bind(this));
}
});
Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
initializeRange: function() {
this.range.selectNodeContents(this.element);
this.range.collapse(this.element);
},
insertContent: function(fragments) {
fragments.each((function(fragment) {
this.element.appendChild(fragment);
}).bind(this));
}
});
Insertion.After = Class.create();
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
initializeRange: function() {
this.range.setStartAfter(this.element);
},
insertContent: function(fragments) {
fragments.each((function(fragment) {
this.element.parentNode.insertBefore(fragment,
this.element.nextSibling);
}).bind(this));
}
});
/*--------------------------------------------------------------------------*/
Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
initialize: function(element) {
this.element = $(element);
},
_each: function(iterator) {
this.element.className.split(/\s+/).select(function(name) {
return name.length > 0;
})._each(iterator);
},
set: function(className) {
this.element.className = className;
},
add: function(classNameToAdd) {
if (this.include(classNameToAdd)) return;
this.set(this.toArray().concat(classNameToAdd).join(' '));
},
remove: function(classNameToRemove) {
if (!this.include(classNameToRemove)) return;
this.set(this.select(function(className) {
return className != classNameToRemove;
}).join(' '));
},
toString: function() {
return this.toArray().join(' ');
}
}
Object.extend(Element.ClassNames.prototype, Enumerable);
var Field = {
clear: function() {
for (var i = 0; i < arguments.length; i++)
$(arguments[i]).value = '';
},
focus: function(element) {
$(element).focus();
},
present: function() {
for (var i = 0; i < arguments.length; i++)
if ($(arguments[i]).value == '') return false;
return true;
},
select: function(element) {
$(element).select();
},
activate: function(element) {
element = $(element);
element.focus();
if (element.select)
element.select();
}
}
/*--------------------------------------------------------------------------*/
var Form = {
serialize: function(form) {
var elements = Form.getElements($(form));
var queryComponents = new Array();
for (var i = 0; i < elements.length; i++) {
var queryComponent = Form.Element.serialize(elements[i]);
if (queryComponent)
queryComponents.push(queryComponent);
}
return queryComponents.join('&');
},
getElements: function(form) {
form = $(form);
var elements = new Array();
for (tagName in Form.Element.Serializers) {
var tagElements = form.getElementsByTagName(tagName);
for (var j = 0; j < tagElements.length; j++)
elements.push(tagElements[j]);
}
return elements;
},
getInputs: function(form, typeName, name) {
form = $(form);
var inputs = form.getElementsByTagName('input');
if (!typeName && !name)
return inputs;
var matchingInputs = new Array();
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
if ((typeName && input.type != typeName) ||
(name && input.name != name))
continue;
matchingInputs.push(input);
}
return matchingInputs;
},
disable: function(form) {
var elements = Form.getElements(form);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
element.blur();
element.disabled = 'true';
}
},
enable: function(form) {
var elements = Form.getElements(form);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
element.disabled = '';
}
},
findFirstElement: function(form) {
return Form.getElements(form).find(function(element) {
return element.type != 'hidden' && !element.disabled &&
['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
});
},
focusFirstElement: function(form) {
Field.activate(Form.findFirstElement(form));
},
reset: function(form) {
$(form).reset();
}
}
Form.Element = {
serialize: function(element) {
element = $(element);
var method = element.tagName.toLowerCase();
var parameter = Form.Element.Serializers[method](element);
if (parameter) {
var key = encodeURIComponent(parameter[0]);
if (key.length == 0) return;
if (parameter[1].constructor != Array)
parameter[1] = [parameter[1]];
return parameter[1].map(function(value) {
return key + '=' + encodeURIComponent(value);
}).join('&');
}
},
getValue: function(element) {
element = $(element);
var method = element.tagName.toLowerCase();
var parameter = Form.Element.Serializers[method](element);
if (parameter)
return parameter[1];
}
}
Form.Element.Serializers = {
input: function(element) {
switch (element.type.toLowerCase()) {
case 'submit':
case 'hidden':
case 'password':
case 'text':
return Form.Element.Serializers.textarea(element);
case 'checkbox':
case 'radio':
return Form.Element.Serializers.inputSelector(element);
}
return false;
},
inputSelector: function(element) {
if (element.checked)
return [element.name, element.value];
},
textarea: function(element) {
return [element.name, element.value];
},
select: function(element) {
return Form.Element.Serializers[element.type == 'select-one' ?
'selectOne' : 'selectMany'](element);
},
selectOne: function(element) {
var value = '', opt, index = element.selectedIndex;
if (index >= 0) {
opt = element.options[index];
value = opt.value;
if (!value && !('value' in opt))
value = opt.text;
}
return [element.name, value];
},
selectMany: function(element) {
var value = new Array();
for (var i = 0; i < element.length; i++) {
var opt = element.options[i];
if (opt.selected) {
var optValue = opt.value;
if (!optValue && !('value' in opt))
optValue = opt.text;
value.push(optValue);
}
}
return [element.name, value];
}
}
/*--------------------------------------------------------------------------*/
var $F = Form.Element.getValue;
/*--------------------------------------------------------------------------*/
Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
initialize: function(element, frequency, callback) {
this.frequency = frequency;
this.element = $(element);
this.callback = callback;
this.lastValue = this.getValue();
this.registerCallback();
},
registerCallback: function() {
setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
onTimerEvent: function() {
var value = this.getValue();
if (this.lastValue != value) {
this.callback(this.element, value);
this.lastValue = value;
}
}
}
Form.Element.Observer = Class.create();
Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
Form.Observer = Class.create();
Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
getValue: function() {
return Form.serialize(this.element);
}
});
/*--------------------------------------------------------------------------*/
Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;
this.lastValue = this.getValue();
if (this.element.tagName.toLowerCase() == 'form')
this.registerFormCallbacks();
else
this.registerCallback(this.element);
},
onElementEvent: function() {
var value = this.getValue();
if (this.lastValue != value) {
this.callback(this.element, value);
this.lastValue = value;
}
},
registerFormCallbacks: function() {
var elements = Form.getElements(this.element);
for (var i = 0; i < elements.length; i++)
this.registerCallback(elements[i]);
},
registerCallback: function(element) {
if (element.type) {
switch (element.type.toLowerCase()) {
case 'checkbox':
case 'radio':
Event.observe(element, 'click', this.onElementEvent.bind(this));
break;
case 'password':
case 'text':
case 'textarea':
case 'select-one':
case 'select-multiple':
Event.observe(element, 'change', this.onElementEvent.bind(this));
break;
}
}
}
}
Form.Element.EventObserver = Class.create();
Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
Form.EventObserver = Class.create();
Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
getValue: function() {
return Form.serialize(this.element);
}
});
if (!window.Event) {
var Event = new Object();
}
Object.extend(Event, {
KEY_BACKSPACE: 8,
KEY_TAB: 9,
KEY_RETURN: 13,
KEY_ESC: 27,
KEY_LEFT: 37,
KEY_UP: 38,
KEY_RIGHT: 39,
KEY_DOWN: 40,
KEY_DELETE: 46,
element: function(event) {
return event.target || event.srcElement;
},
isLeftClick: function(event) {
return (((event.which) && (event.which == 1)) ||
((event.button) && (event.button == 1)));
},
pointerX: function(event) {
return event.pageX || (event.clientX +
(document.documentElement.scrollLeft || document.body.scrollLeft));
},
pointerY: function(event) {
return event.pageY || (event.clientY +
(document.documentElement.scrollTop || document.body.scrollTop));
},
stop: function(event) {
if (event.preventDefault) {
event.preventDefault();
event.stopPropagation();
} else {
event.returnValue = false;
event.cancelBubble = true;
}
},
// find the first node with the given tagName, starting from the
// node the event was triggered on; traverses the DOM upwards
findElement: function(event, tagName) {
var element = Event.element(event);
while (element.parentNode && (!element.tagName ||
(element.tagName.toUpperCase() != tagName.toUpperCase())))
element = element.parentNode;
return element;
},
observers: false,
_observeAndCache: function(element, name, observer, useCapture) {
if (!this.observers) this.observers = [];
if (element.addEventListener) {
this.observers.push([element, name, observer, useCapture]);
element.addEventListener(name, observer, useCapture);
} else if (element.attachEvent) {
this.observers.push([element, name, observer, useCapture]);
element.attachEvent('on' + name, observer);
}
},
unloadCache: function() {
if (!Event.observers) return;
for (var i = 0; i < Event.observers.length; i++) {
Event.stopObserving.apply(this, Event.observers[i]);
Event.observers[i][0] = null;
}
Event.observers = false;
},
observe: function(element, name, observer, useCapture) {
var element = $(element);
useCapture = useCapture || false;
if (name == 'keypress' &&
(navigator.appVersion.match(/Konqueror|Safari|KHTML/)
|| element.attachEvent))
name = 'keydown';
this._observeAndCache(element, name, observer, useCapture);
},
stopObserving: function(element, name, observer, useCapture) {
var element = $(element);
useCapture = useCapture || false;
if (name == 'keypress' &&
(navigator.appVersion.match(/Konqueror|Safari|KHTML/)
|| element.detachEvent))
name = 'keydown';
if (element.removeEventListener) {
element.removeEventListener(name, observer, useCapture);
} else if (element.detachEvent) {
element.detachEvent('on' + name, observer);
}
}
});
/* prevent memory leaks in IE */
Event.observe(window, 'unload', Event.unloadCache, false);
var Position = {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
// scrollable elements
includeScrollOffsets: false,
// must be called before calling withinIncludingScrolloffset, every time the
// page is scrolled
prepare: function() {
this.deltaX = window.pageXOffset
|| document.documentElement.scrollLeft
|| document.body.scrollLeft
|| 0;
this.deltaY = window.pageYOffset
|| document.documentElement.scrollTop
|| document.body.scrollTop
|| 0;
},
realOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.scrollTop || 0;
valueL += element.scrollLeft || 0;
element = element.parentNode;
} while (element);
return [valueL, valueT];
},
cumulativeOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
} while (element);
return [valueL, valueT];
},
positionedOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
if (element) {
p = Element.getStyle(element, 'position');
if (p == 'relative' || p == 'absolute') break;
}
} while (element);
return [valueL, valueT];
},
offsetParent: function(element) {
if (element.offsetParent) return element.offsetParent;
if (element == document.body) return element;
while ((element = element.parentNode) && element != document.body)
if (Element.getStyle(element, 'position') != 'static')
return element;
return document.body;
},
// caches x/y coordinate pair to use with overlap
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
this.xcomp = x;
this.ycomp = y;
this.offset = this.cumulativeOffset(element);
return (y >= this.offset[1] &&
y < this.offset[1] + element.offsetHeight &&
x >= this.offset[0] &&
x < this.offset[0] + element.offsetWidth);
},
withinIncludingScrolloffsets: function(element, x, y) {
var offsetcache = this.realOffset(element);
this.xcomp = x + offsetcache[0] - this.deltaX;
this.ycomp = y + offsetcache[1] - this.deltaY;
this.offset = this.cumulativeOffset(element);
return (this.ycomp >= this.offset[1] &&
this.ycomp < this.offset[1] + element.offsetHeight &&
this.xcomp >= this.offset[0] &&
this.xcomp < this.offset[0] + element.offsetWidth);
},
// within must be called directly before
overlap: function(mode, element) {
if (!mode) return 0;
if (mode == 'vertical')
return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
element.offsetHeight;
if (mode == 'horizontal')
return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
element.offsetWidth;
},
clone: function(source, target) {
source = $(source);
target = $(target);
target.style.position = 'absolute';
var offsets = this.cumulativeOffset(source);
target.style.top = offsets[1] + 'px';
target.style.left = offsets[0] + 'px';
target.style.width = source.offsetWidth + 'px';
target.style.height = source.offsetHeight + 'px';
},
page: function(forElement) {
var valueT = 0, valueL = 0;
var element = forElement;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
// Safari fix
if (element.offsetParent==document.body)
if (Element.getStyle(element,'position')=='absolute') break;
} while (element = element.offsetParent);
element = forElement;
do {
valueT -= element.scrollTop || 0;
valueL -= element.scrollLeft || 0;
} while (element = element.parentNode);
return [valueL, valueT];
},
clone: function(source, target) {
var options = Object.extend({
setLeft: true,
setTop: true,
setWidth: true,
setHeight: true,
offsetTop: 0,
offsetLeft: 0
}, arguments[2] || {})
// find page position of source
source = $(source);
var p = Position.page(source);
// find coordinate system to use
target = $(target);
var delta = [0, 0];
var parent = null;
// delta [0,0] will do fine with position: fixed elements,
// position:absolute needs offsetParent deltas
if (Element.getStyle(target,'position') == 'absolute') {
parent = Position.offsetParent(target);
delta = Position.page(parent);
}
// correct by body offsets (fixes Safari)
if (parent == document.body) {
delta[0] -= document.body.offsetLeft;
delta[1] -= document.body.offsetTop;
}
// set position
if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
if(options.setWidth) target.style.width = source.offsetWidth + 'px';
if(options.setHeight) target.style.height = source.offsetHeight + 'px';
},
absolutize: function(element) {
element = $(element);
if (element.style.position == 'absolute') return;
Position.prepare();
var offsets = Position.positionedOffset(element);
var top = offsets[1];
var left = offsets[0];
var width = element.clientWidth;
var height = element.clientHeight;
element._originalLeft = left - parseFloat(element.style.left || 0);
element._originalTop = top - parseFloat(element.style.top || 0);
element._originalWidth = element.style.width;
element._originalHeight = element.style.height;
element.style.position = 'absolute';
element.style.top = top + 'px';;
element.style.left = left + 'px';;
element.style.width = width + 'px';;
element.style.height = height + 'px';;
},
relativize: function(element) {
element = $(element);
if (element.style.position == 'relative') return;
Position.prepare();
element.style.position = 'relative';
var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
element.style.top = top + 'px';
element.style.left = left + 'px';
element.style.height = element._originalHeight;
element.style.width = element._originalWidth;
}
}
// Safari returns margins on body which is incorrect if the child is absolutely
// positioned. For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
Position.cumulativeOffset = function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
if (element.offsetParent == document.body)
if (Element.getStyle(element, 'position') == 'absolute') break;
element = element.offsetParent;
} while (element);
return [valueL, valueT];
}
}
/* Added by module "embed_images/viewer:lightbox", file "mods/embed_images/viewers/lightbox/code/js/scriptaculous.js" */
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var Scriptaculous = {
Version: '1.5.1',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
},
load: function() {
if((typeof Prototype=='undefined') ||
parseFloat(Prototype.Version.split(".")[0] + "." +
Prototype.Version.split(".")[1]) < 1.4)
throw("script.aculo.us requires the Prototype JavaScript framework >= 1.4.0");
$A(document.getElementsByTagName("script")).findAll( function(s) {
return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
}).each( function(s) {
var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
var includes = s.src.match(/\?.*load=([a-z,]*)/);
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
}
}
Scriptaculous.load();
/* Added by module "embed_images/viewer:lightbox", file "mods/embed_images/viewers/lightbox/code/js/effects.js" */
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
// Martin Bialasinki
// 
// See scriptaculous.js for full license. 
/* ------------- element ext -------------- */ 
// converts rgb() and #xxx to #xxxxxx format, 
// returns self (or first argument) if not convertable 
String.prototype.parseColor = function() { 
var color = '#'; 
if(this.slice(0,4) == 'rgb(') { 
var cols = this.slice(4,this.length-1).split(','); 
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); 
} else { 
if(this.slice(0,1) == '#') { 
if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); 
if(this.length==7) color = this.toLowerCase(); 
} 
} 
return(color.length==7 ? color : (arguments[0] || this)); 
}
Element.collectTextNodes = function(element) { 
return $A($(element).childNodes).collect( function(node) {
return (node.nodeType==3 ? node.nodeValue : 
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
}).flatten().join('');
}
Element.collectTextNodesIgnoreClass = function(element, className) { 
return $A($(element).childNodes).collect( function(node) {
return (node.nodeType==3 ? node.nodeValue : 
((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
Element.collectTextNodes(node) : ''));
}).flatten().join('');
}
Element.setStyle = function(element, style) {
element = $(element);
for(k in style) element.style[k.camelize()] = style[k];
}
Element.setContentZoom = function(element, percent) { 
Element.setStyle(element, {fontSize: (percent/100) + 'em'}); 
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); 
}
Element.getOpacity = function(element){ 
var opacity;
if (opacity = Element.getStyle(element, 'opacity')) 
return parseFloat(opacity); 
if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) 
if(opacity[1]) return parseFloat(opacity[1]) / 100; 
return 1.0; 
}
Element.setOpacity = function(element, value){ 
element= $(element); 
if (value == 1){
Element.setStyle(element, { opacity: 
(/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
0.999999 : null });
if(/MSIE/.test(navigator.userAgent)) 
Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); 
} else { 
if(value < 0.00001) value = 0; 
Element.setStyle(element, {opacity: value});
if(/MSIE/.test(navigator.userAgent)) 
Element.setStyle(element, 
{ filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
'alpha(opacity='+value*100+')' }); 
} 
} 
Element.getInlineOpacity = function(element){ 
return $(element).style.opacity || '';
} 
Element.childrenWithClassName = function(element, className) { 
return $A($(element).getElementsByTagName('*')).select(
function(c) { return Element.hasClassName(c, className) });
}
Array.prototype.call = function() {
var args = arguments;
this.each(function(f){ f.apply(this, args) });
}
/*--------------------------------------------------------------------------*/
var Effect = {
tagifyText: function(element) {
var tagifyStyle = 'position:relative';
if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
element = $(element);
$A(element.childNodes).each( function(child) {
if(child.nodeType==3) {
child.nodeValue.toArray().each( function(character) {
element.insertBefore(
Builder.node('span',{style: tagifyStyle},
character == ' ' ? String.fromCharCode(160) : character), 
child);
});
Element.remove(child);
}
});
},
multiple: function(element, effect) {
var elements;
if(((typeof element == 'object') || 
(typeof element == 'function')) && 
(element.length))
elements = element;
else
elements = $(element).childNodes;
var options = Object.extend({
speed: 0.1,
delay: 0.0
}, arguments[2] || {});
var masterDelay = options.delay;
$A(elements).each( function(element, index) {
new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
});
},
PAIRS: {
'slide': ['SlideDown','SlideUp'],
'blind': ['BlindDown','BlindUp'],
'appear': ['Appear','Fade']
},
toggle: function(element, effect) {
element = $(element);
effect = (effect || 'appear').toLowerCase();
var options = Object.extend({
queue: { position:'end', scope:(element.id || 'global') }
}, arguments[2] || {});
Effect[Element.visible(element) ? 
Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
}
};
var Effect2 = Effect; // deprecated
/* ------------- transitions ------------- */
Effect.Transitions = {}
Effect.Transitions.linear = function(pos) {
return pos;
}
Effect.Transitions.sinoidal = function(pos) {
return (-Math.cos(pos*Math.PI)/2) + 0.5;
}
Effect.Transitions.reverse = function(pos) {
return 1-pos;
}
Effect.Transitions.flicker = function(pos) {
return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
}
Effect.Transitions.wobble = function(pos) {
return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
}
Effect.Transitions.pulse = function(pos) {
return (Math.floor(pos*10) % 2 == 0 ? 
(pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
}
Effect.Transitions.none = function(pos) {
return 0;
}
Effect.Transitions.full = function(pos) {
return 1;
}
/* ------------- core effects ------------- */
Effect.ScopedQueue = Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
initialize: function() {
this.effects = [];
this.interval = null;
},
_each: function(iterator) {
this.effects._each(iterator);
},
add: function(effect) {
var timestamp = new Date().getTime();
var position = (typeof effect.options.queue == 'string') ? 
effect.options.queue : effect.options.queue.position;
switch(position) {
case 'front':
// move unstarted effects after this effect 
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
e.startOn += effect.finishOn;
e.finishOn += effect.finishOn;
});
break;
case 'end':
// start effect after last queued effect has finished
timestamp = this.effects.pluck('finishOn').max() || timestamp;
break;
}
effect.startOn += timestamp;
effect.finishOn += timestamp;
this.effects.push(effect);
if(!this.interval) 
this.interval = setInterval(this.loop.bind(this), 40);
},
remove: function(effect) {
this.effects = this.effects.reject(function(e) { return e==effect });
if(this.effects.length == 0) {
clearInterval(this.interval);
this.interval = null;
}
},
loop: function() {
var timePos = new Date().getTime();
this.effects.invoke('loop', timePos);
}
});
Effect.Queues = {
instances: $H(),
get: function(queueName) {
if(typeof queueName != 'string') return queueName;
if(!this.instances[queueName])
this.instances[queueName] = new Effect.ScopedQueue();
return this.instances[queueName];
}
}
Effect.Queue = Effect.Queues.get('global');
Effect.DefaultOptions = {
transition: Effect.Transitions.sinoidal,
duration: 1.0, // seconds
fps: 25.0, // max. 25fps due to Effect.Queue implementation
sync: false, // true for combining
from: 0.0,
to: 1.0,
delay: 0.0,
queue: 'parallel'
}
Effect.Base = function() {};
Effect.Base.prototype = {
position: null,
start: function(options) {
this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
this.currentFrame = 0;
this.state = 'idle';
this.startOn = this.options.delay*1000;
this.finishOn = this.startOn + (this.options.duration*1000);
this.event('beforeStart');
if(!this.options.sync)
Effect.Queues.get(typeof this.options.queue == 'string' ? 
'global' : this.options.queue.scope).add(this);
},
loop: function(timePos) {
if(timePos >= this.startOn) {
if(timePos >= this.finishOn) {
this.render(1.0);
this.cancel();
this.event('beforeFinish');
if(this.finish) this.finish(); 
this.event('afterFinish');
return; 
}
var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
var frame = Math.round(pos * this.options.fps * this.options.duration);
if(frame > this.currentFrame) {
this.render(pos);
this.currentFrame = frame;
}
}
},
render: function(pos) {
if(this.state == 'idle') {
this.state = 'running';
this.event('beforeSetup');
if(this.setup) this.setup();
this.event('afterSetup');
}
if(this.state == 'running') {
if(this.options.transition) pos = this.options.transition(pos);
pos *= (this.options.to-this.options.from);
pos += this.options.from;
this.position = pos;
this.event('beforeUpdate');
if(this.update) this.update(pos);
this.event('afterUpdate');
}
},
cancel: function() {
if(!this.options.sync)
Effect.Queues.get(typeof this.options.queue == 'string' ? 
'global' : this.options.queue.scope).remove(this);
this.state = 'finished';
},
event: function(eventName) {
if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
if(this.options[eventName]) this.options[eventName](this);
},
inspect: function() {
return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
}
}
Effect.Parallel = Class.create();
Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
initialize: function(effects) {
this.effects = effects || [];
this.start(arguments[1]);
},
update: function(position) {
this.effects.invoke('render', position);
},
finish: function(position) {
this.effects.each( function(effect) {
effect.render(1.0);
effect.cancel();
effect.event('beforeFinish');
if(effect.finish) effect.finish(position);
effect.event('afterFinish');
});
}
});
Effect.Opacity = Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
initialize: function(element) {
this.element = $(element);
// make this work on IE on elements without 'layout'
if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
Element.setStyle(this.element, {zoom: 1});
var options = Object.extend({
from: Element.getOpacity(this.element) || 0.0,
to: 1.0
}, arguments[1] || {});
this.start(options);
},
update: function(position) {
Element.setOpacity(this.element, position);
}
});
Effect.Move = Class.create();
Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
initialize: function(element) {
this.element = $(element);
var options = Object.extend({
x: 0,
y: 0,
mode: 'relative'
}, arguments[1] || {});
this.start(options);
},
setup: function() {
// Bug in Opera: Opera returns the "real" position of a static element or
// relative element that does not have top/left explicitly set.
// ==> Always set top and left for position relative elements in your stylesheets 
// (to 0 if you do not need them) 
Element.makePositioned(this.element);
this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0');
this.originalTop = parseFloat(Element.getStyle(this.element,'top') || '0');
if(this.options.mode == 'absolute') {
// absolute movement, so we need to calc deltaX and deltaY
this.options.x = this.options.x - this.originalLeft;
this.options.y = this.options.y - this.originalTop;
}
},
update: function(position) {
Element.setStyle(this.element, {
left: this.options.x * position + this.originalLeft + 'px',
top: this.options.y * position + this.originalTop + 'px'
});
}
});
// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
return new Effect.Move(element, 
Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
};
Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
initialize: function(element, percent) {
this.element = $(element)
var options = Object.extend({
scaleX: true,
scaleY: true,
scaleContent: true,
scaleFromCenter: false,
scaleMode: 'box', // 'box' or 'contents' or {} with provided values
scaleFrom: 100.0,
scaleTo: percent
}, arguments[2] || {});
this.start(options);
},
setup: function() {
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
this.elementPositioning = Element.getStyle(this.element,'position');
this.originalStyle = {};
['top','left','width','height','fontSize'].each( function(k) {
this.originalStyle[k] = this.element.style[k];
}.bind(this));
this.originalTop = this.element.offsetTop;
this.originalLeft = this.element.offsetLeft;
var fontSize = Element.getStyle(this.element,'font-size') || '100%';
['em','px','%'].each( function(fontSizeType) {
if(fontSize.indexOf(fontSizeType)>0) {
this.fontSize = parseFloat(fontSize);
this.fontSizeType = fontSizeType;
}
}.bind(this));
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
this.dims = null;
if(this.options.scaleMode=='box')
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
if(/^content/.test(this.options.scaleMode))
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
if(!this.dims)
this.dims = [this.options.scaleMode.originalHeight,
this.options.scaleMode.originalWidth];
},
update: function(position) {
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
if(this.options.scaleContent && this.fontSize)
Element.setStyle(this.element, {fontSize: this.fontSize * currentScale + this.fontSizeType });
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
},
finish: function(position) {
if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle);
},
setDimensions: function(height, width) {
var d = {};
if(this.options.scaleX) d.width = width + 'px';
if(this.options.scaleY) d.height = height + 'px';
if(this.options.scaleFromCenter) {
var topd = (height - this.dims[0])/2;
var leftd = (width - this.dims[1])/2;
if(this.elementPositioning == 'absolute') {
if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
} else {
if(this.options.scaleY) d.top = -topd + 'px';
if(this.options.scaleX) d.left = -leftd + 'px';
}
}
Element.setStyle(this.element, d);
}
});
Effect.Highlight = Class.create();
Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
initialize: function(element) {
this.element = $(element);
var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
this.start(options);
},
setup: function() {
// Prevent executing on elements not in the layout flow
if(Element.getStyle(this.element, 'display')=='none') { this.cancel(); return; }
// Disable background image during the effect
this.oldStyle = {
backgroundImage: Element.getStyle(this.element, 'background-image') };
Element.setStyle(this.element, {backgroundImage: 'none'});
if(!this.options.endcolor)
this.options.endcolor = Element.getStyle(this.element, 'background-color').parseColor('#ffffff');
if(!this.options.restorecolor)
this.options.restorecolor = Element.getStyle(this.element, 'background-color');
// init color calculations
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
},
update: function(position) {
Element.setStyle(this.element,{backgroundColor: $R(0,2).inject('#',function(m,v,i){
return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
},
finish: function() {
Element.setStyle(this.element, Object.extend(this.oldStyle, {
backgroundColor: this.options.restorecolor
}));
}
});
Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
initialize: function(element) {
this.element = $(element);
this.start(arguments[1] || {});
},
setup: function() {
Position.prepare();
var offsets = Position.cumulativeOffset(this.element);
if(this.options.offset) offsets[1] += this.options.offset;
var max = window.innerHeight ? 
window.height - window.innerHeight :
document.body.scrollHeight - 
(document.documentElement.clientHeight ? 
document.documentElement.clientHeight : document.body.clientHeight);
this.scrollStart = Position.deltaY;
this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
},
update: function(position) {
Position.prepare();
window.scrollTo(Position.deltaX, 
this.scrollStart + (position*this.delta));
}
});
/* ------------- combination effects ------------- */
Effect.Fade = function(element) {
var oldOpacity = Element.getInlineOpacity(element);
var options = Object.extend({
from: Element.getOpacity(element) || 1.0,
to: 0.0,
afterFinishInternal: function(effect) { with(Element) { 
if(effect.options.to!=0) return;
hide(effect.element);
setStyle(effect.element, {opacity: oldOpacity}); }}
}, arguments[1] || {});
return new Effect.Opacity(element,options);
}
Effect.Appear = function(element) {
var options = Object.extend({
from: (Element.getStyle(element, 'display') == 'none' ? 0.0 : Element.getOpacity(element) || 0.0),
to: 1.0,
beforeSetup: function(effect) { with(Element) {
setOpacity(effect.element, effect.options.from);
show(effect.element); }}
}, arguments[1] || {});
return new Effect.Opacity(element,options);
}
Effect.Puff = function(element) {
element = $(element);
var oldStyle = { opacity: Element.getInlineOpacity(element), position: Element.getStyle(element, 'position') };
return new Effect.Parallel(
[ new Effect.Scale(element, 200, 
{ sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
Object.extend({ duration: 1.0, 
beforeSetupInternal: function(effect) { with(Element) {
setStyle(effect.effects[0].element, {position: 'absolute'}); }},
afterFinishInternal: function(effect) { with(Element) {
hide(effect.effects[0].element);
setStyle(effect.effects[0].element, oldStyle); }}
}, arguments[1] || {})
);
}
Effect.BlindUp = function(element) {
element = $(element);
Element.makeClipping(element);
return new Effect.Scale(element, 0, 
Object.extend({ scaleContent: false, 
scaleX: false, 
restoreAfterFinish: true,
afterFinishInternal: function(effect) { with(Element) {
[hide, undoClipping].call(effect.element); }} 
}, arguments[1] || {})
);
}
Effect.BlindDown = function(element) {
element = $(element);
var oldHeight = Element.getStyle(element, 'height');
var elementDimensions = Element.getDimensions(element);
return new Effect.Scale(element, 100, 
Object.extend({ scaleContent: false, 
scaleX: false,
scaleFrom: 0,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
afterSetup: function(effect) { with(Element) {
makeClipping(effect.element);
setStyle(effect.element, {height: '0px'});
show(effect.element); 
}}, 
afterFinishInternal: function(effect) { with(Element) {
undoClipping(effect.element);
setStyle(effect.element, {height: oldHeight});
}}
}, arguments[1] || {})
);
}
Effect.SwitchOff = function(element) {
element = $(element);
var oldOpacity = Element.getInlineOpacity(element);
return new Effect.Appear(element, { 
duration: 0.4,
from: 0,
transition: Effect.Transitions.flicker,
afterFinishInternal: function(effect) {
new Effect.Scale(effect.element, 1, { 
duration: 0.3, scaleFromCenter: true,
scaleX: false, scaleContent: false, restoreAfterFinish: true,
beforeSetup: function(effect) { with(Element) {
[makePositioned,makeClipping].call(effect.element);
}},
afterFinishInternal: function(effect) { with(Element) {
[hide,undoClipping,undoPositioned].call(effect.element);
setStyle(effect.element, {opacity: oldOpacity});
}}
})
}
});
}
Effect.DropOut = function(element) {
element = $(element);
var oldStyle = {
top: Element.getStyle(element, 'top'),
left: Element.getStyle(element, 'left'),
opacity: Element.getInlineOpacity(element) };
return new Effect.Parallel(
[ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
Object.extend(
{ duration: 0.5,
beforeSetup: function(effect) { with(Element) {
makePositioned(effect.effects[0].element); }},
afterFinishInternal: function(effect) { with(Element) {
[hide, undoPositioned].call(effect.effects[0].element);
setStyle(effect.effects[0].element, oldStyle); }} 
}, arguments[1] || {}));
}
Effect.Shake = function(element) {
element = $(element);
var oldStyle = {
top: Element.getStyle(element, 'top'),
left: Element.getStyle(element, 'left') };
return new Effect.Move(element, 
{ x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { with(Element) {
undoPositioned(effect.element);
setStyle(effect.element, oldStyle);
}}}) }}) }}) }}) }}) }});
}
Effect.SlideDown = function(element) {
element = $(element);
Element.cleanWhitespace(element);
// SlideDown need to have the content of the element wrapped in a container element with fixed height!
var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
var elementDimensions = Element.getDimensions(element);
return new Effect.Scale(element, 100, Object.extend({ 
scaleContent: false, 
scaleX: false, 
scaleFrom: 0,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
afterSetup: function(effect) { with(Element) {
makePositioned(effect.element);
makePositioned(effect.element.firstChild);
if(window.opera) setStyle(effect.element, {top: ''});
makeClipping(effect.element);
setStyle(effect.element, {height: '0px'});
show(element); }},
afterUpdateInternal: function(effect) { with(Element) {
setStyle(effect.element.firstChild, {bottom:
(effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
afterFinishInternal: function(effect) { with(Element) {
undoClipping(effect.element); 
undoPositioned(effect.element.firstChild);
undoPositioned(effect.element);
setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
}, arguments[1] || {})
);
}
Effect.SlideUp = function(element) {
element = $(element);
Element.cleanWhitespace(element);
var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
return new Effect.Scale(element, 0, 
Object.extend({ scaleContent: false, 
scaleX: false, 
scaleMode: 'box',
scaleFrom: 100,
restoreAfterFinish: true,
beforeStartInternal: function(effect) { with(Element) {
makePositioned(effect.element);
makePositioned(effect.element.firstChild);
if(window.opera) setStyle(effect.element, {top: ''});
makeClipping(effect.element);
show(element); }}, 
afterUpdateInternal: function(effect) { with(Element) {
setStyle(effect.element.firstChild, {bottom:
(effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
afterFinishInternal: function(effect) { with(Element) {
[hide, undoClipping].call(effect.element); 
undoPositioned(effect.element.firstChild);
undoPositioned(effect.element);
setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
}, arguments[1] || {})
);
}
// Bug in opera makes the TD containing this element expand for a instance after finish 
Effect.Squish = function(element) {
return new Effect.Scale(element, window.opera ? 1 : 0, 
{ restoreAfterFinish: true,
beforeSetup: function(effect) { with(Element) {
makeClipping(effect.element); }}, 
afterFinishInternal: function(effect) { with(Element) {
hide(effect.element); 
undoClipping(effect.element); }}
});
}
Effect.Grow = function(element) {
element = $(element);
var options = Object.extend({
direction: 'center',
moveTransistion: Effect.Transitions.sinoidal,
scaleTransition: Effect.Transitions.sinoidal,
opacityTransition: Effect.Transitions.full
}, arguments[1] || {});
var oldStyle = {
top: element.style.top,
left: element.style.left,
height: element.style.height,
width: element.style.width,
opacity: Element.getInlineOpacity(element) };
var dims = Element.getDimensions(element); 
var initialMoveX, initialMoveY;
var moveX, moveY;
switch (options.direction) {
case 'top-left':
initialMoveX = initialMoveY = moveX = moveY = 0; 
break;
case 'top-right':
initialMoveX = dims.width;
initialMoveY = moveY = 0;
moveX = -dims.width;
break;
case 'bottom-left':
initialMoveX = moveX = 0;
initialMoveY = dims.height;
moveY = -dims.height;
break;
case 'bottom-right':
initialMoveX = dims.width;
initialMoveY = dims.height;
moveX = -dims.width;
moveY = -dims.height;
break;
case 'center':
initialMoveX = dims.width / 2;
initialMoveY = dims.height / 2;
moveX = -dims.width / 2;
moveY = -dims.height / 2;
break;
}
return new Effect.Move(element, {
x: initialMoveX,
y: initialMoveY,
duration: 0.01, 
beforeSetup: function(effect) { with(Element) {
hide(effect.element);
makeClipping(effect.element);
makePositioned(effect.element);
}},
afterFinishInternal: function(effect) {
new Effect.Parallel(
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
new Effect.Scale(effect.element, 100, {
scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
], Object.extend({
beforeSetup: function(effect) { with(Element) {
setStyle(effect.effects[0].element, {height: '0px'});
show(effect.effects[0].element); }},
afterFinishInternal: function(effect) { with(Element) {
[undoClipping, undoPositioned].call(effect.effects[0].element); 
setStyle(effect.effects[0].element, oldStyle); }}
}, options)
)
}
});
}
Effect.Shrink = function(element) {
element = $(element);
var options = Object.extend({
direction: 'center',
moveTransistion: Effect.Transitions.sinoidal,
scaleTransition: Effect.Transitions.sinoidal,
opacityTransition: Effect.Transitions.none
}, arguments[1] || {});
var oldStyle = {
top: element.style.top,
left: element.style.left,
height: element.style.height,
width: element.style.width,
opacity: Element.getInlineOpacity(element) };
var dims = Element.getDimensions(element);
var moveX, moveY;
switch (options.direction) {
case 'top-left':
moveX = moveY = 0;
break;
case 'top-right':
moveX = dims.width;
moveY = 0;
break;
case 'bottom-left':
moveX = 0;
moveY = dims.height;
break;
case 'bottom-right':
moveX = dims.width;
moveY = dims.height;
break;
case 'center': 
moveX = dims.width / 2;
moveY = dims.height / 2;
break;
}
return new Effect.Parallel(
[ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
], Object.extend({ 
beforeStartInternal: function(effect) { with(Element) {
[makePositioned, makeClipping].call(effect.effects[0].element) }},
afterFinishInternal: function(effect) { with(Element) {
[hide, undoClipping, undoPositioned].call(effect.effects[0].element);
setStyle(effect.effects[0].element, oldStyle); }}
}, options)
);
}
Effect.Pulsate = function(element) {
element = $(element);
var options = arguments[1] || {};
var oldOpacity = Element.getInlineOpacity(element);
var transition = options.transition || Effect.Transitions.sinoidal;
var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
reverser.bind(transition);
return new Effect.Opacity(element, 
Object.extend(Object.extend({ duration: 3.0, from: 0,
afterFinishInternal: function(effect) { Element.setStyle(effect.element, {opacity: oldOpacity}); }
}, options), {transition: reverser}));
}
Effect.Fold = function(element) {
element = $(element);
var oldStyle = {
top: element.style.top,
left: element.style.left,
width: element.style.width,
height: element.style.height };
Element.makeClipping(element);
return new Effect.Scale(element, 5, Object.extend({ 
scaleContent: false,
scaleX: false,
afterFinishInternal: function(effect) {
new Effect.Scale(element, 1, { 
scaleContent: false, 
scaleY: false,
afterFinishInternal: function(effect) { with(Element) {
[hide, undoClipping].call(effect.element); 
setStyle(effect.element, oldStyle);
}} });
}}, arguments[1] || {}));
}
/* Added by module "embed_images/viewer:lightbox", file "mods/embed_images/viewers/lightbox/code/js/lightbox.js" */
// -----------------------------------------------------------------------------------
//
// Lightbox v2.03.3
// by Lokesh Dhakar - http://www.huddletogether.com
// 5/21/06
//
// For more information on this script, visit:
// http://huddletogether.com/projects/lightbox2/
//
// Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
// 
// Credit also due to those who have helped, inspired, and made their code available to the public.
// Including: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), Thomas Fuchs(mir.aculo.us), and others.
//
//
// -----------------------------------------------------------------------------------
/*
Table of Contents
-----------------
Configuration
Global Variables
Extending Built-in Objects 
- Object.extend(Element)
- Array.prototype.removeDuplicates()
- Array.prototype.empty()
Lightbox Class Declaration
- initialize()
- updateImageList()
- start()
- changeImage()
- resizeImageContainer()
- showImage()
- updateDetails()
- updateNav()
- enableKeyboardNav()
- disableKeyboardNav()
- keyboardAction()
- preloadNeighborImages()
- end()
Miscellaneous Functions
- getPageScroll()
- getPageSize()
- getKey()
- listenKey()
- showSelectBoxes()
- hideSelectBoxes()
- showFlash()
- hideFlash()
- pause()
- initLightbox()
Function Calls
- addLoadEvent(initLightbox)
*/
// -----------------------------------------------------------------------------------
//
// Configuration
//
var fileLoadingImage = "images/loading.gif"; 
var fileBottomNavCloseImage = "images/closelabel.gif";
var overlayOpacity = 0.8; // controls transparency of shadow overlay
var animate = true; // toggles resizing animations
var resizeSpeed = 7; // controls the speed of the image resizing animations (1=slowest and 10=fastest)
var borderSize = 10; //if you adjust the padding in the CSS, you will need to update this variable
// -----------------------------------------------------------------------------------
//
// Global Variables
//
var imageArray = new Array;
var activeImage;
if(animate == true){
overlayDuration = 0.2; // shadow fade in/out duration
if(resizeSpeed > 10){ resizeSpeed = 10;}
if(resizeSpeed < 1){ resizeSpeed = 1;}
resizeDuration = (11 - resizeSpeed) * 0.15;
} else { 
overlayDuration = 0;
resizeDuration = 0;
}
// -----------------------------------------------------------------------------------
//
// Additional methods for Element added by SU, Couloir
// - further additions by Lokesh Dhakar (huddletogether.com)
//
Object.extend(Element, {
getWidth: function(element) {
element = $(element);
return element.offsetWidth; 
},
setWidth: function(element,w) {
element = $(element);
element.style.width = w +"px";
},
setHeight: function(element,h) {
element = $(element);
element.style.height = h +"px";
},
setTop: function(element,t) {
element = $(element);
element.style.top = t +"px";
},
setLeft: function(element,l) {
element = $(element);
element.style.left = l +"px";
},
setSrc: function(element,src) {
element = $(element);
element.src = src; 
},
setHref: function(element,href) {
element = $(element);
element.href = href; 
},
setInnerHTML: function(element,content) {
element = $(element);
element.innerHTML = content;
}
});
// -----------------------------------------------------------------------------------
//
// Extending built-in Array object
// - array.removeDuplicates()
// - array.empty()
//
Array.prototype.removeDuplicates = function () {
for(i = 0; i < this.length; i++){
for(j = this.length-1; j>i; j--){ 
if(this[i][0] == this[j][0]){
this.splice(j,1);
}
}
}
}
// -----------------------------------------------------------------------------------
Array.prototype.empty = function () {
for(i = 0; i <= this.length; i++){
this.shift();
}
}
// -----------------------------------------------------------------------------------
//
// Lightbox Class Declaration
// - initialize()
// - start()
// - changeImage()
// - resizeImageContainer()
// - showImage()
// - updateDetails()
// - updateNav()
// - enableKeyboardNav()
// - disableKeyboardNav()
// - keyboardNavAction()
// - preloadNeighborImages()
// - end()
//
// Structuring of code inspired by Scott Upton (http://www.uptonic.com/)
//
var Lightbox = Class.create();
Lightbox.prototype = {
// initialize()
// Constructor runs on completion of the DOM loading. Calls updateImageList 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() { 
this.updateImageList();
// Code inserts html at the bottom of the page that looks similar to this:
//
//<div id="overlay"></div>//<div id="lightbox">//<div id="outerImageContainer">//<div id="imageContainer">// <img id="lightboxImage">
//<div style="" id="hoverNav">// <a href="#" id="prevLink"></a>
// <a href="#" id="nextLink"></a>
//</div>//<div id="loading">// <a href="#" id="loadingLink">
// <img src="images/loading.gif">
// </a>
//</div>//</div>//</div>//<div id="imageDataContainer">//<div id="imageData">//<div id="imageDetails">// <span id="caption"></span>
// <span id="numberDisplay"></span>
//</div>//<div id="bottomNav">// <a href="#" id="bottomNavClose">
// <img src="images/close.gif">
// </a>
//</div>//</div>//</div>//</div>var objBody = document.getElementsByTagName("body").item(0);
var objOverlay = document.createElement("div");
objOverlay.setAttribute('id','overlay');
objOverlay.style.display = 'none';
objOverlay.onclick = function() { myLightbox.end(); }
objBody.appendChild(objOverlay);
var objLightbox = document.createElement("div");
objLightbox.setAttribute('id','lightbox');
objLightbox.style.display = 'none';
objLightbox.onclick = function(e) { // close Lightbox is user clicks shadow overlay
if (!e) var e = window.event;
var clickObj = Event.element(e).id;
if ( clickObj == 'lightbox') {
myLightbox.end();
}
};
objBody.appendChild(objLightbox);
var objOuterImageContainer = document.createElement("div");
objOuterImageContainer.setAttribute('id','outerImageContainer');
objLightbox.appendChild(objOuterImageContainer);
// When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
// If animations are turned off, it will be hidden as to prevent a flicker of a
// white 250 by 250 box.
if(animate){
Element.setWidth('outerImageContainer', 250);
Element.setHeight('outerImageContainer', 250); 
} else {
Element.setWidth('outerImageContainer', 1);
Element.setHeight('outerImageContainer', 1); 
}
var objImageContainer = document.createElement("div");
objImageContainer.setAttribute('id','imageContainer');
objOuterImageContainer.appendChild(objImageContainer);
var objLightboxImage = document.createElement("img");
objLightboxImage.setAttribute('id','lightboxImage');
objImageContainer.appendChild(objLightboxImage);
var objHoverNav = document.createElement("div");
objHoverNav.setAttribute('id','hoverNav');
objImageContainer.appendChild(objHoverNav);
var objPrevLink = document.createElement("a");
objPrevLink.setAttribute('id','prevLink');
objPrevLink.setAttribute('href','#');
objHoverNav.appendChild(objPrevLink);
var objNextLink = document.createElement("a");
objNextLink.setAttribute('id','nextLink');
objNextLink.setAttribute('href','#');
objHoverNav.appendChild(objNextLink);
var objLoading = document.createElement("div");
objLoading.setAttribute('id','loading');
objImageContainer.appendChild(objLoading);
var objLoadingLink = document.createElement("a");
objLoadingLink.setAttribute('id','loadingLink');
objLoadingLink.setAttribute('href','#');
objLoadingLink.onclick = function() { myLightbox.end(); return false; }
objLoading.appendChild(objLoadingLink);
var objLoadingImage = document.createElement("img");
objLoadingImage.setAttribute('src', fileLoadingImage);
objLoadingLink.appendChild(objLoadingImage);
var objImageDataContainer = document.createElement("div");
objImageDataContainer.setAttribute('id','imageDataContainer');
objLightbox.appendChild(objImageDataContainer);
var objImageData = document.createElement("div");
objImageData.setAttribute('id','imageData');
objImageDataContainer.appendChild(objImageData);
var objImageDetails = document.createElement("div");
objImageDetails.setAttribute('id','imageDetails');
objImageData.appendChild(objImageDetails);
var objCaption = document.createElement("span");
objCaption.setAttribute('id','caption');
objImageDetails.appendChild(objCaption);
var objNumberDisplay = document.createElement("span");
objNumberDisplay.setAttribute('id','numberDisplay');
objImageDetails.appendChild(objNumberDisplay);
var objBottomNav = document.createElement("div");
objBottomNav.setAttribute('id','bottomNav');
objImageData.appendChild(objBottomNav);
var objBottomNavCloseLink = document.createElement("a");
objBottomNavCloseLink.setAttribute('id','bottomNavClose');
objBottomNavCloseLink.setAttribute('href','#');
objBottomNavCloseLink.onclick = function() { myLightbox.end(); return false; }
objBottomNav.appendChild(objBottomNavCloseLink);
var objBottomNavCloseImage = document.createElement("img");
objBottomNavCloseImage.setAttribute('src', fileBottomNavCloseImage);
objBottomNavCloseLink.appendChild(objBottomNavCloseImage);
},
//
// updateImageList()
// Loops through anchor tags looking for 'lightbox' references and applies onclick
// events to appropriate links. You can rerun after dynamically adding images w/ajax.
//
updateImageList: function() { 
if (!document.getElementsByTagName){ return; }
var anchors = document.getElementsByTagName('a');
var areas = document.getElementsByTagName('area');
// loop through all anchor tags
for (var i=0; i<anchors.length; i++){
var anchor = anchors[i];
var relAttribute = String(anchor.getAttribute('rel'));
// use the string.match() method to catch 'lightbox' references in the rel attribute
if (anchor.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))){
anchor.onclick = function () {myLightbox.start(this); return false;}
}
}
// loop through all area tags
// todo: combine anchor & area tag loops
for (var i=0; i< areas.length; i++){
var area = areas[i];
var relAttribute = String(area.getAttribute('rel'));
// use the string.match() method to catch 'lightbox' references in the rel attribute
if (area.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))){
area.onclick = function () {myLightbox.start(this); return false;}
}
}
},
//
// start()
// Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
//
start: function(imageLink) { 
hideSelectBoxes();
hideFlash();
// stretch overlay to fill page and fade in
var arrayPageSize = getPageSize();
Element.setWidth('overlay', arrayPageSize[0]);
Element.setHeight('overlay', arrayPageSize[1]);
new Effect.Appear('overlay', { duration: overlayDuration, from: 0.0, to: overlayOpacity });
imageArray = [];
imageNum = 0; 
if (!document.getElementsByTagName){ return; }
var anchors = document.getElementsByTagName( imageLink.tagName);
// if image is NOT part of a set..
if((imageLink.getAttribute('rel') == 'lightbox')){
// add single image to imageArray
imageArray.push(new Array(imageLink.getAttribute('href'), imageLink.getAttribute('title'))); 
} else {
// if image is part of a set..
// loop through anchors, find other images in set, and add them to imageArray
for (var i=0; i<anchors.length; i++){
var anchor = anchors[i];
if (anchor.getAttribute('href') && (anchor.getAttribute('rel') == imageLink.getAttribute('rel'))){
imageArray.push(new Array(anchor.getAttribute('href'), anchor.getAttribute('title')));
}
}
imageArray.removeDuplicates();
while(imageArray[imageNum][0] != imageLink.getAttribute('href')) { imageNum++;}
}
// calculate top and left offset for the lightbox 
var arrayPageScroll = getPageScroll();
var lightboxTop = arrayPageScroll[1] + (arrayPageSize[3] / 10);
var lightboxLeft = arrayPageScroll[0];
Element.setTop('lightbox', lightboxTop);
Element.setLeft('lightbox', lightboxLeft);
Element.show('lightbox');
this.changeImage(imageNum);
},
//
// changeImage()
// Hide most elements and preload image in preparation for resizing image container.
//
changeImage: function(imageNum) { 
activeImage = imageNum; // update global var
// hide elements during transition
if(animate){ Element.show('loading');}
Element.hide('lightboxImage');
Element.hide('hoverNav');
Element.hide('prevLink');
Element.hide('nextLink');
Element.hide('imageDataContainer');
Element.hide('numberDisplay'); 
imgPreloader = new Image();
// once image is preloaded, resize image container
imgPreloader.onload=function(){
Element.setSrc('lightboxImage', imageArray[activeImage][0]);
myLightbox.resizeImageContainer(imgPreloader.width, imgPreloader.height);
imgPreloader.onload=function(){}; // clear onLoad, IE behaves irratically with animated gifs otherwise 
}
imgPreloader.src = imageArray[activeImage][0];
},
//
// resizeImageContainer()
//
resizeImageContainer: function( imgWidth, imgHeight) {
// get curren width and height
this.widthCurrent = Element.getWidth('outerImageContainer');
this.heightCurrent = Element.getHeight('outerImageContainer');
// get new width and height
var widthNew = (imgWidth + (borderSize * 2));
var heightNew = (imgHeight + (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;
if(!( hDiff == 0)){ new Effect.Scale('outerImageContainer', this.yScale, {scaleX: false, duration: resizeDuration, queue: 'front'}); }
if(!( wDiff == 0)){ new Effect.Scale('outerImageContainer', this.xScale, {scaleY: false, delay: resizeDuration, duration: resizeDuration}); }
// 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 (navigator.appVersion.indexOf("MSIE")!=-1){ pause(250); } else { pause(100);} 
}
Element.setHeight('prevLink', imgHeight);
Element.setHeight('nextLink', imgHeight);
Element.setWidth( 'imageDataContainer', widthNew);
this.showImage();
},
//
// showImage()
// Display image and begin preloading neighbors.
//
showImage: function(){
Element.hide('loading');
new Effect.Appear('lightboxImage', { duration: resizeDuration, queue: 'end', afterFinish: function(){ myLightbox.updateDetails(); } });
this.preloadNeighborImages();
},
//
// updateDetails()
// Display caption, image number, and bottom nav.
//
updateDetails: function() {
// if caption is not null
if(imageArray[activeImage][1]){
Element.show('caption');
Element.setInnerHTML( 'caption', imageArray[activeImage][1]);
}
// if image is part of set display 'Image x of x' 
if(imageArray.length > 1){
Element.show('numberDisplay');
Element.setInnerHTML( 'numberDisplay', "Image " + eval(activeImage + 1) + " of " + imageArray.length);
}
new Effect.Parallel(
[ new Effect.SlideDown( 'imageDataContainer', { sync: true, duration: resizeDuration, from: 0.0, to: 1.0 }), 
new Effect.Appear('imageDataContainer', { sync: true, duration: resizeDuration }) ], 
{ duration: resizeDuration, afterFinish: function() {
// update overlay size and update nav
var arrayPageSize = getPageSize();
Element.setHeight('overlay', arrayPageSize[1]);
myLightbox.updateNav();
}
} 
);
},
//
// updateNav()
// Display appropriate previous and next hover navigation.
//
updateNav: function() {
Element.show('hoverNav'); 
// if not first image in set, display prev image button
if(activeImage != 0){
Element.show('prevLink');
document.getElementById('prevLink').onclick = function() {
myLightbox.changeImage(activeImage - 1); return false;
}
}
// if not last image in set, display next image button
if(activeImage != (imageArray.length - 1)){
Element.show('nextLink');
document.getElementById('nextLink').onclick = function() {
myLightbox.changeImage(activeImage + 1); return false;
}
}
this.enableKeyboardNav();
},
//
// enableKeyboardNav()
//
enableKeyboardNav: function() {
document.onkeydown = this.keyboardAction; 
},
//
// disableKeyboardNav()
//
disableKeyboardNav: function() {
document.onkeydown = '';
},
//
// 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();
if((key == 'x') || (key == 'o') || (key == 'c') || (keycode == escapeKey)){ // close lightbox
myLightbox.end();
} else if((key == 'p') || (keycode == 37)){ // display previous image
if(activeImage != 0){
myLightbox.disableKeyboardNav();
myLightbox.changeImage(activeImage - 1);
}
} else if((key == 'n') || (keycode == 39)){ // display next image
if(activeImage != (imageArray.length - 1)){
myLightbox.disableKeyboardNav();
myLightbox.changeImage(activeImage + 1);
}
}
},
//
// preloadNeighborImages()
// Preload previous and next images.
//
preloadNeighborImages: function(){
if((imageArray.length - 1) > activeImage){
preloadNextImage = new Image();
preloadNextImage.src = imageArray[activeImage + 1][0];
}
if(activeImage > 0){
preloadPrevImage = new Image();
preloadPrevImage.src = imageArray[activeImage - 1][0];
}
},
//
// end()
//
end: function() {
this.disableKeyboardNav();
Element.hide('lightbox');
new Effect.Fade('overlay', { duration: overlayDuration});
showSelectBoxes();
showFlash();
}
}
// -----------------------------------------------------------------------------------
//
// getPageScroll()
// Returns array with x,y page scroll values.
// Core code from - quirksmode.com
//
function getPageScroll(){
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 = new Array(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
//
function getPageSize(){
var xScroll, yScroll;
if (window.innerHeight && window.scrollMaxY) { 
xScroll = window.innerWidth + window.scrollMaxX;
yScroll = window.innerHeight + window.scrollMaxY;
} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}
var windowWidth, windowHeight;
// console.log(self.innerWidth);
// console.log(document.documentElement.clientWidth);
if (self.innerHeight) { // all except Explorer
if(document.documentElement.clientWidth){
windowWidth = document.documentElement.clientWidth; 
} else {
windowWidth = self.innerWidth;
}
windowHeight = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
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;
}
// console.log("xScroll " + xScroll)
// console.log("windowWidth " + windowWidth)
// for small pages with total width less then width of the viewport
if(xScroll < windowWidth){ 
pageWidth = xScroll; 
} else {
pageWidth = windowWidth;
}
// console.log("pageWidth " + pageWidth)
arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
return arrayPageSize;
}
// -----------------------------------------------------------------------------------
//
// getKey(key)
// Gets keycode. If 'x' is pressed then it hides the lightbox.
//
function getKey(e){
if (e == null) { // ie
keycode = event.keyCode;
} else { // mozilla
keycode = e.which;
}
key = String.fromCharCode(keycode).toLowerCase();
if(key == 'x'){
}
}
// -----------------------------------------------------------------------------------
//
// listenKey()
//
function listenKey () { document.onkeypress = getKey; }
// ---------------------------------------------------
function showSelectBoxes(){
var selects = document.getElementsByTagName("select");
for (i = 0; i != selects.length; i++) {
selects[i].style.visibility = "visible";
}
}
// ---------------------------------------------------
function hideSelectBoxes(){
var selects = document.getElementsByTagName("select");
for (i = 0; i != selects.length; i++) {
selects[i].style.visibility = "hidden";
}
}
// ---------------------------------------------------
function showFlash(){
var flashObjects = document.getElementsByTagName("object");
for (i = 0; i < flashObjects.length; i++) {
flashObjects[i].style.visibility = "visible";
}
var flashEmbeds = document.getElementsByTagName("embed");
for (i = 0; i < flashEmbeds.length; i++) {
flashEmbeds[i].style.visibility = "visible";
}
}
// ---------------------------------------------------
function hideFlash(){
var flashObjects = document.getElementsByTagName("object");
for (i = 0; i < flashObjects.length; i++) {
flashObjects[i].style.visibility = "hidden";
}
var flashEmbeds = document.getElementsByTagName("embed");
for (i = 0; i < flashEmbeds.length; i++) {
flashEmbeds[i].style.visibility = "hidden";
}
}
// ---------------------------------------------------
/