propagate from branch 'ca.inverse.sogo.1_3_15' (head d4a2b559c00ba43032aff09497fe8be50f429e21)

to branch 'ca.inverse.sogo' (head a7e1ea6582c544441d18a19cd60774003d863f46)

Monotone-Parent: a7e1ea6582c544441d18a19cd60774003d863f46
Monotone-Parent: d4a2b559c00ba43032aff09497fe8be50f429e21
Monotone-Revision: b2d9259d01bec3e1e78582b987d4091f8472b129

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2012-05-09T15:24:16
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2012-05-09 15:24:16 +00:00
commit 54c69836ab
24 changed files with 1997 additions and 4387 deletions

View File

@ -1,3 +1,28 @@
2012-05-09 Ludovic Marcotte <lmarcotte@inverse.ca>
* SoObjects/Mailer/SOGoDraftObject.m - don't encode message/rfc822
parts in base64 - it's not allowed.
2012-05-08 Francis Lachapelle <flachapelle@inverse.ca>
* UI/WebServerResources/ContactsUI.js (configureDraggables)
(configureDroppables, startDragging, whileDragging, stopDragging)
(dropAction): drag'n'drop is how handle by jQuery instead of Scriptaculous.
* UI/WebServerResources/MailerUI.js (configureDraggables)
(configureDroppables, startDragging, whileDragging, stopDragging)
(dropAction): idem.
* UI/WebServerResources/generic.js (onCloseButtonClick)
(showPromptDialog, showSelectDialog, showAuthenticationDialog)
(disposeDialog, _disposeDialog): idem.
* UI/WebServerResources/SOGoRootPage.js (initLogin): idem.
* UI/Contacts/UIxContactView.m (-primaryEmail): in the mailto
link, remove double-quotes and escape single-quotes from the fullname.
(-secondaryEmail): idem.
2012-05-04 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreSOGo.m: register and unregister current

3
NEWS
View File

@ -15,12 +15,15 @@ Enhancements
- updated CKEditor to version 3.6.3
- automatically add/remove attendees to recurrence exceptions when they are
being added to the master event
- replaced the Scriptaculous Javascript framework by jQuery to improve the
drag'n'drop experience
Bug Fixes
- fixed wrong date validation in preferences module affecting French users
- fixed bugs in weekly recurrence calculator
- when saving a draft, fixed content-transfer-encoding to properly handle
8bit data
- escaped single-quote in HTML view of contacts
1.3.14 (2012-03-23)
-------------------

View File

@ -1181,11 +1181,6 @@ static NSString *userAgent = nil;
content = [[NSData alloc] initWithContentsOfMappedFile:p];
[content autorelease];
content = [content dataByEncodingBase64];
[map setObject: @"base64" forKey: @"content-transfer-encoding"];
[map setObject:[NSNumber numberWithInt:[content length]]
forKey: @"content-length"];
/* Note: the -init method will create a temporary file! */
body = [[NGMimeFileData alloc] initWithBytes:[content bytes]
length:[content length]];

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2004 SKYRIX Software AG
Copyright (C) 2005-2011 Inverse inc.
Copyright (C) 2005-2012 Inverse inc.
This file is part of SOGo.
@ -135,13 +135,18 @@
- (NSString *) primaryEmail
{
NSString *email, *mailTo;
NSString *email, *fn, *mailTo;
email = [card preferredEMail];
if ([email length] > 0)
mailTo = [NSString stringWithFormat: @"<a href=\"mailto:%@\""
@" onclick=\"return openMailTo('%@ <%@>');\">"
@"%@</a>", email, [[card fn] stringByReplacingString: @"\"" withString: @""], email, email];
{
fn = [card fn];
fn = [fn stringByReplacingString: @"\"" withString: @""];
fn = [fn stringByReplacingString: @"'" withString: @"\\\'"];
mailTo = [NSString stringWithFormat: @"<a href=\"mailto:%@\""
@" onclick=\"return openMailTo('%@ <%@>');\">"
@"%@</a>", email, fn, email, email];
}
else
mailTo = nil;
@ -151,7 +156,7 @@
- (NSString *) secondaryEmail
{
NSString *email, *mailTo;
NSString *email, *fn, *mailTo;
NSMutableArray *emails;
emails = [NSMutableArray array];
@ -182,9 +187,12 @@
if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame)
{
fn = [card fn];
fn = [fn stringByReplacingString: @"\"" withString: @""];
fn = [fn stringByReplacingString: @"'" withString: @"\\\'"];
mailTo = [NSString stringWithFormat: @"<a href=\"mailto:%@\""
@" onclick=\"return openMailTo('%@ <%@>');\">"
@"%@</a>", email, [[card fn] stringByReplacingString: @"\"" withString: @""], email, email];
@"%@</a>", email, fn, email, email];
break;
}
}

View File

@ -8,6 +8,7 @@
xmlns:label="OGo:label"
xmlns:rsrc="OGo:url"
const:userDefaultsKeys="SOGoContactsCategories"
const:jsFiles="jquery-ui.js"
className="UIxPageFrame"
title="name"
var:popup="isPopup">

View File

@ -9,7 +9,7 @@
title="title"
const:userDefaultsKeys="SOGoMailMessageCheck,SOGoMailSortByThreads,SOGoMailListViewColumnsOrder"
const:userSettingsKeys="Mail"
const:jsFiles="dtree.js,MailerUIdTree.js,SOGoAutoCompletion.js,SOGoResizableTable.js,SOGoMailDataSource.js,SOGoDataTable.js">
const:jsFiles="dtree.js,MailerUIdTree.js,SOGoAutoCompletion.js,SOGoResizableTable.js,SOGoMailDataSource.js,SOGoDataTable.js,jquery-ui.js">
<script type="text/javascript">
var mailAccounts = <var:string value="mailAccounts" const:escapeHTML="NO"/>;
var inboxData = <var:string value="inboxData" const:escapeHTML="NO"/>;

View File

@ -152,6 +152,8 @@
<var:string value="productLocalizableStrings" const:escapeHTML="NO"/>
</script>
<script type="text/javascript" rsrc:src="prototype.js"><!-- space --></script>
<script type="text/javascript" rsrc:src="jquery.js"><!-- space --></script>
<script>jQuery.noConflict();</script>
<script type="text/javascript" rsrc:src="XMLHttpRequest.js"><!-- space --></script>
<script type="text/javascript" rsrc:src="tablekit.js"><!-- space --></script>
<script type="text/javascript" rsrc:src="tablekit-trueresize.js"><!-- space --></script>
@ -163,7 +165,6 @@
<script type="text/javascript" rsrc:src="generic.js"><!-- space --></script>
<script type="text/javascript" rsrc:src="SOGoDragHandles.js"><!-- space --></script>
<script type="text/javascript" rsrc:src="SOGoTabsController.js"><!-- space --></script>
<script type="text/javascript" rsrc:src="scriptaculous.js"><!-- space --></script>
<var:if condition="hasProductSpecificJavaScript"><script type="text/javascript"
var:src="productJavaScriptURL"><!-- space --></script></var:if>
<var:if condition="hasPageSpecificJavaScript"><script type="text/javascript"

View File

@ -216,6 +216,8 @@ function contactsListCallback(http) {
tBody.removeChild(tBody.rows[i]);
}
}
configureDraggables();
}
else
log ("ajax problem 1: status = " + http.status);
@ -1475,37 +1477,26 @@ function unsetCategoryOnNode(contactNode, category) {
function configureDraggables() {
if ($("contactFolders")) {
var mainElement = $("dragDropVisual");
Draggables.empty();
if (mainElement == null) {
mainElement = new Element("div", {id: "dragDropVisual"});
document.body.appendChild(mainElement);
mainElement.absolutize();
}
mainElement.hide();
new Draggable("dragDropVisual",
{ handle: "contactsList",
onStart: startDragging,
onEnd: stopDragging,
onDrag: whileDragging,
scroll: window,
delay: 250 });
var rows = jQuery("tr.vcard");
rows.draggable("destroy");
rows.draggable({
helper: function (event) { return '<div id="dragDropVisual"></div>'; },
start: startDragging,
drag: whileDragging,
stop: stopDragging,
appendTo: 'body',
cursorAt: { right: 25 },
scroll: false,
distance: 4,
zIndex: 20
});
}
}
function configureDroppables() {
var drops = $$("ul#contactFolders li");
Droppables.empty ();
drops.each (function (drop) {
if (!drop.hasClassName ("remote"))
Droppables.add (drop.id,
{ hoverclass: "genericHoverClass",
onDrop: dropAction
});
});
jQuery("li.local").droppable({
hoverClass: 'genericHoverClass',
drop: dropAction });
}
function currentFolderIsRemote() {
@ -1518,46 +1509,26 @@ function currentFolderIsRemote() {
return rc;
}
function startDragging(itm, e) {
if (!Event.isLeftClick(e))
return;
var target = Event.element(e);
if (target.up().up().tagName != "TBODY")
return;
$("contactsListContent").setStyle({ overflow: "visible" });
// Create overlapping safety block to avoid selection issues
var rightSafetyBlock = $("rightSafetyBlock");
if (!rightSafetyBlock) {
rightSafetyBlock = new Element('div', {'id': 'rightSafetyBlock', 'class': 'safetyBlock'});
document.body.appendChild(rightSafetyBlock);
}
var rightBlock = $("rightPanel");
rightSafetyBlock.setStyle({
top: rightBlock.getStyle('top'),
left: rightBlock.getStyle('left') });
rightSafetyBlock.show();
function startDragging(e, itm) {
var row = e.target;
var handle = $("dragDropVisual");
var contacts = $('contactsList').getSelectedRowsId();
var count = contacts.length;
var row = target.up('TR');
if (count == 0 || contacts.indexOf(row.id) < 0) {
onRowClick(e, target);
onRowClick(e, $(row.id));
contacts = $("contactsList").getSelectedRowsId();
count = contacts.length;
}
handle.update(count);
handle.update (count);
if (e.shiftKey || currentFolderIsRemote()) {
handle.addClassName("copy");
}
handle.show();
}
function whileDragging(itm, e) {
function whileDragging(e, itm) {
if (e) {
var handle = $("dragDropVisual");
if (e.shiftKey || currentFolderIsRemote())
@ -1567,25 +1538,23 @@ function whileDragging(itm, e) {
}
}
function stopDragging () {
$("contactsListContent").setStyle({ overflow: "auto", overflowX: "hidden" });
$("rightSafetyBlock").hide();
function stopDragging(e, itm) {
var handle = $("dragDropVisual");
handle.hide();
if (handle.hasClassName ("copy"))
handle.removeClassName ("copy");
if (handle.hasClassName("copy"))
handle.removeClassName("copy");
}
function dropAction (dropped, zone, e) {
function dropAction(event, ui) {
var action = "move";
if ($("dragDropVisual").hasClassName ("copy"))
if ($("dragDropVisual").hasClassName("copy"))
action = "copy";
else
$('contactView').update();
dropSelectedContacts (action, zone.id.substr (1));
dropSelectedContacts(action, this.id.substr(1));
}
function dropSelectedContacts (action, toId) {
function dropSelectedContacts(action, toId) {
var selectedFolders = $("contactFolders").getSelectedNodes();
if (selectedFolders.length > 0) {
var contactIds = $('contactsList').getSelectedRowsId();

View File

@ -14,7 +14,6 @@ install ::
cp $(WEBSERVER_RESOURCE_FILES) $(SOGO_WEBSERVERRESOURCESDIR)/; \
cp -r ckeditor $(SOGO_WEBSERVERRESOURCESDIR)/; \
rm -rf $(SOGO_WEBSERVERRESOURCESDIR)/ckeditor/_source; \
cp -r scriptaculous $(SOGO_WEBSERVERRESOURCESDIR)/; \
fi
clean ::

View File

@ -2911,96 +2911,44 @@ Mailbox.prototype = {
};
function configureDraggables() {
var mainElement = $("dragDropVisual");
if (mainElement == null) {
mainElement = new Element("div", {id: "dragDropVisual"});
document.body.appendChild(mainElement);
mainElement.absolutize();
}
mainElement.hide();
new Draggable("dragDropVisual",
{ handle: "messageListBody",
onStart: startDragging,
onEnd: stopDragging,
onDrag: whileDragging,
scroll: "folderTreeContent",
delay: 250 });
var table = jQuery("#messageListBody");
table.draggable({
addClasses: false,
helper: function (event) { return '<div id="dragDropVisual"></div>'; },
start: startDragging,
drag: whileDragging,
stop: stopDragging,
appendTo: 'body',
cursorAt: { top: 15, right: 15 },
scroll: false,
distance: 4,
zIndex: 20
});
}
function configureDroppables() {
var drops = $$("div#mailboxTree div.dTreeNode a.node span.nodeName");
if (Mailer.drops)
Mailer.drops.each(function (drop) { Droppables.remove(drop); });
drops.each(function (drop) {
var dataname = drop.parentNode.parentNode.getAttribute("dataname");
var acceptClass = "account";
if (dataname.length > 0) {
var parts = dataname.split("/");
acceptClass += parts[1];
}
var parent = drop.parentNode.parentNode;
if (parent.getAttribute("datatype") != "account") {
drop.identify();
Droppables.add(drop.id,
{ hoverclass: "genericHoverClass",
accept: [ acceptClass ],
onDrop: dropAction });
Mailer.drops.push(drop);
}
});
jQuery('#mailboxTree .dTreeNode[datatype!="account"][datatype!="additional"] .node .nodeName').droppable({
hoverClass: 'genericHoverClass',
drop: dropAction });
}
function startDragging(itm, e) {
if (!Event.isLeftClick(e))
return;
var target = Event.element(e);
if (target.up('TBODY') == undefined)
return;
function startDragging(e, ui) {
var handle = ui.helper;
var count = $('messageListBody').getSelectedRowsId().length;
$("mailboxList").setStyle({ overflow: "visible" });
// Create overlapping safety block to avoid selection issues
var rightSafetyBlock = $("rightSafetyBlock");
if (!rightSafetyBlock) {
rightSafetyBlock = new Element('div', {'id': 'rightSafetyBlock', 'class': 'safetyBlock'});
document.body.appendChild(rightSafetyBlock);
if (count == 0) {
jQuery(this).trigger("stop");
return false;
}
var rightBlock = $("rightPanel");
rightSafetyBlock.setStyle({
top: rightBlock.getStyle('top'),
left: rightBlock.getStyle('left') });
rightSafetyBlock.show();
handle.html(count);
var row = target.up('TR');
var handle = $("dragDropVisual");
var selectedIds = $("messageListBody").getSelectedRowsId();
var count = selectedIds.length;
var rowId = row.id;
if (count == 0 || selectedIds.indexOf(rowId) < 0) {
if (target.tagName != 'TD')
target = target.up('TD');
onRowClick(e, target);
selectedIds = $("messageListBody").getSelectedRowsId();
count = selectedIds.length;
}
handle.update(count);
if (Mailer.currentMailbox) {
var parts = Mailer.currentMailbox.split("/");
handle.addClassName("account" + parts[1]);
}
if (e.shiftKey) {
handle.addClassName("copy");
handle.addClassName("copy");
}
handle.show();
}
function whileDragging(itm, e) {
function whileDragging(e, ui) {
if (e) {
var handle = $("dragDropVisual");
if (e.shiftKey)
@ -3011,8 +2959,6 @@ function whileDragging(itm, e) {
}
function stopDragging() {
$("mailboxList").setStyle({ overflow: "auto", overflowX: "hidden" });
$("rightSafetyBlock").hide();
var handle = $("dragDropVisual");
handle.hide();
if (handle.hasClassName("copy"))
@ -3022,8 +2968,8 @@ function stopDragging() {
}
}
function dropAction (dropped, zone, e) {
var destination = zone.up("div.dTreeNode");
function dropAction(event, ui) {
var destination = $(this).up("div.dTreeNode");
var sourceAct = Mailer.currentMailbox.split("/")[1];
var destAct = destination.getAttribute("dataname").split("/")[1];

View File

@ -16,12 +16,11 @@ function initLogin() {
var about = $("about");
if (about) {
about.observe("click", function(event) {
if (!$("aboutBox").visible())
Effect.SlideDown("aboutBox", { queue: { position: 'end', scope: 'aboutscope', limit: 2 } });
jQuery('#aboutBox').slideToggle('fast');
event.stop(); });
var aboutClose = $("aboutClose");
aboutClose.observe("click", function(event) {
Effect.SlideUp("aboutBox", { duration: 1.0, queue: { position: 'end', scope: 'aboutscope', limit: 2 } });
jQuery('#aboutBox').slideUp('fast');
event.stop() });
}

View File

@ -1620,7 +1620,7 @@ function onCloseButtonClick(event) {
Event.stop(event);
if (window.frameElement && window.frameElement.id) {
parent$("bgFrameDiv").fade({ duration: 0.2 });
jQuery(parent$("bgFrameDiv")).fadeOut('fast');
var div = parent$("popupFrame");
div.hide();
div.down("iframe").src = "/SOGo/loading";
@ -1970,7 +1970,7 @@ function _showAlertDialog(label) {
document.body.appendChild(dialog);
dialogs[label] = dialog;
}
dialog.appear({ duration: 0.2 });
jQuery(dialog).fadeIn('fast');
}
function showConfirmDialog(title, label, callbackYes, callbackNo, yesLabel, noLabel) {
@ -2008,7 +2008,7 @@ function _showConfirmDialog(title, label, callbackYes, callbackNo, yesLabel, noL
document.body.appendChild(dialog);
dialogs[key] = dialog;
}
dialog.appear({ duration: 0.2 });
jQuery(dialog).fadeIn('fast');
}
function showPromptDialog(title, label, callback, defaultValue) {
@ -2047,8 +2047,7 @@ function _showPromptDialog(title, label, callback, defaultValue) {
document.body.appendChild(dialog);
dialogs[title+label] = dialog;
}
dialog.appear({ duration: 0.2,
afterFinish: function () { dialog.down("input").focus(); } });
jQuery(dialog).fadeIn('fast', function () { dialog.down("input").focus(); });
}
function showSelectDialog(title, label, options, button, callbackFcn, callbackArg, defaultValue) {
@ -2094,7 +2093,7 @@ function _showSelectDialog(title, label, options, button, callbackFcn, callbackA
}
if (defaultValue)
defaultOption = dialog.down('option[value="'+defaultValue+'"]').selected = true;
dialog.appear({ duration: 0.2 });
jQuery(dialog).fadeIn('fast');
}
function showAuthenticationDialog(label, callback) {
@ -2137,14 +2136,13 @@ function _showAuthenticationDialog(label, callback) {
document.body.appendChild(dialog);
dialogs[label] = dialog;
}
dialog.appear({ duration: 0.2,
afterFinish: function () { dialog.down("input").focus(); } });
jQuery(dialog).fadeIn('fast', function () { dialog.down("input").focus(); });
}
function disposeDialog() {
$$("DIV.dialog").each(function(div) {
if (div.visible() && div.getOpacity() == 1)
div.fade({ duration: 0.2 });
jQuery(div).fadeOut('fast');
});
if (dialogsStack.length > 0) {
// Show the next dialog box
@ -2153,19 +2151,16 @@ function disposeDialog() {
dialogFcn.delay(0.2);
}
else if ($('bgDialogDiv')) {
var bgFade = Effect.Fade('bgDialogDiv', { duration: 0.2 });
// By the end the background fade out, a new dialog
// may need to be displayed.
_disposeDialog.delay(0.1, bgFade);
jQuery('#bgDialogDiv').fadeOut('fast', _disposeDialog);
}
}
function _disposeDialog(bgEffect) {
function _disposeDialog() {
if (dialogsStack.length) {
var div = $("bgDialogDiv");
bgEffect.cancel();
div.show();
div.appear({ duration: 0.2, to: 0.3 });
jQuery(div).fadeIn(100);
var dialogFcn = dialogsStack.first();
dialogsStack.splice(0, 1);
dialogFcn();

1874
UI/WebServerResources/jquery-ui.js vendored 100644

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,65 +0,0 @@
// script.aculo.us scriptaculous.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 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.
//
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Scriptaculous = {
Version: '1.8.2',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
},
REQUIRED_PROTOTYPE: '1.6.0.3',
load: function() {
function convertVersionString(versionString) {
var v = versionString.replace(/_.*|\./g, '');
v = parseInt(v + '0'.times(4-v.length));
return versionString.indexOf('_') > -1 ? v-1 : v;
}
if((typeof Prototype=='undefined') ||
(typeof Element == 'undefined') ||
(typeof Element.Methods=='undefined') ||
(convertVersionString(Prototype.Version) <
convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
throw("script.aculo.us requires the Prototype JavaScript framework >= " +
Scriptaculous.REQUIRED_PROTOTYPE);
var path = ResourcesURL + "/scriptaculous/";
var includes = ["effects", "dragdrop"];
includes.each (function (include) { Scriptaculous.require (path+include+'.js') });
/* Default Scriptaculous shit
var js = /scriptaculous\.js(\?.*)?$/;
$$('head script[src]').findAll(function(s) {
return s.src.match(js);
}).each(function(s) {
var path = s.src.replace(js, ''),
includes = s.src.match(/\?.*load=([a-z,]*)/);
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});*/
}
};
Scriptaculous.load();

View File

@ -1,20 +0,0 @@
Copyright (c) 2005-2008 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.

View File

@ -1,136 +0,0 @@
// script.aculo.us builder.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Builder = {
NODEMAP: {
AREA: 'map',
CAPTION: 'table',
COL: 'table',
COLGROUP: 'table',
LEGEND: 'fieldset',
OPTGROUP: 'select',
OPTION: 'select',
PARAM: 'object',
TBODY: 'table',
TD: 'table',
TFOOT: 'table',
TH: 'table',
THEAD: 'table',
TR: 'table'
},
// note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
// due to a Firefox bug
node: function(elementName) {
elementName = elementName.toUpperCase();
// try innerHTML approach
var parentTag = this.NODEMAP[elementName] || 'div';
var parentElement = document.createElement(parentTag);
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
} catch(e) {}
var element = parentElement.firstChild || null;
// see if browser added wrapping tags
if(element && (element.tagName.toUpperCase() != elementName))
element = element.getElementsByTagName(elementName)[0];
// fallback to createElement approach
if(!element) element = document.createElement(elementName);
// abort if nothing could be created
if(!element) return;
// attributes (or text)
if(arguments[1])
if(this._isStringOrNumber(arguments[1]) ||
(arguments[1] instanceof Array) ||
arguments[1].tagName) {
this._children(element, arguments[1]);
} else {
var attrs = this._attributes(arguments[1]);
if(attrs.length) {
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
parentElement.innerHTML = "<" +elementName + " " +
attrs + "></" + elementName + ">";
} catch(e) {}
element = parentElement.firstChild || null;
// workaround firefox 1.0.X bug
if(!element) {
element = document.createElement(elementName);
for(attr in arguments[1])
element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
}
if(element.tagName.toUpperCase() != elementName)
element = parentElement.getElementsByTagName(elementName)[0];
}
}
// text, or array of children
if(arguments[2])
this._children(element, arguments[2]);
return $(element);
},
_text: function(text) {
return document.createTextNode(text);
},
ATTR_MAP: {
'className': 'class',
'htmlFor': 'for'
},
_attributes: function(attributes) {
var attrs = [];
for(attribute in attributes)
attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
'="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
return attrs.join(" ");
},
_children: function(element, children) {
if(children.tagName) {
element.appendChild(children);
return;
}
if(typeof children=='object') { // array can hold nodes and text
children.flatten().each( function(e) {
if(typeof e=='object')
element.appendChild(e);
else
if(Builder._isStringOrNumber(e))
element.appendChild(Builder._text(e));
});
} else
if(Builder._isStringOrNumber(children))
element.appendChild(Builder._text(children));
},
_isStringOrNumber: function(param) {
return(typeof param=='string' || typeof param=='number');
},
build: function(html) {
var element = this.node('div');
$(element).update(html.strip());
return element.down();
},
dump: function(scope) {
if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
"BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
"FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
"KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
"PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
"TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
tags.each( function(tag){
scope[tag] = function() {
return Builder.node.apply(Builder, [tag].concat($A(arguments)));
};
});
}
};

View File

@ -1,965 +0,0 @@
// script.aculo.us controls.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least,
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most
// useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks.
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
var Autocompleter = { };
Autocompleter.Base = Class.create({
baseInitialize: function(element, update, options) {
element = $(element);
this.element = element;
this.update = $(update);
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
this.oldElementValue = this.element.value;
if(this.setOptions)
this.setOptions(options);
else
this.options = options || { };
this.options.paramName = this.options.paramName || this.element.name;
this.options.tokens = this.options.tokens || [];
this.options.frequency = this.options.frequency || 0.4;
this.options.minChars = this.options.minChars || 1;
this.options.onShow = this.options.onShow ||
function(element, update){
if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute';
Position.clone(element, update, {
setHeight: false,
offsetTop: element.offsetHeight
});
}
Effect.Appear(update,{duration:0.15});
};
this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
if(typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens);
// Force carriage returns as token delimiters anyway
if (!this.options.tokens.include('\n'))
this.options.tokens.push('\n');
this.observer = null;
this.element.setAttribute('autocomplete','off');
Element.hide(this.update);
Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
(Prototype.Browser.IE) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
this.iefix = $(this.update.id+'_iefix');
}
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
},
fixIEOverlapping: function() {
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2;
Element.show(this.iefix);
},
hide: function() {
this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
if(this.iefix) Element.hide(this.iefix);
},
startIndicator: function() {
if(this.options.indicator) Element.show(this.options.indicator);
},
stopIndicator: function() {
if(this.options.indicator) Element.hide(this.options.indicator);
},
onKeyPress: function(event) {
if(this.active)
switch(event.keyCode) {
case Event.KEY_TAB:
case Event.KEY_RETURN:
this.selectEntry();
Event.stop(event);
case Event.KEY_ESC:
this.hide();
this.active = false;
Event.stop(event);
return;
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
return;
case Event.KEY_UP:
this.markPrevious();
this.render();
Event.stop(event);
return;
case Event.KEY_DOWN:
this.markNext();
this.render();
Event.stop(event);
return;
}
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
(Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
this.changed = true;
this.hasFocus = true;
if(this.observer) clearTimeout(this.observer);
this.observer =
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},
activate: function() {
this.changed = false;
this.hasFocus = true;
this.getUpdatedChoices();
},
onHover: function(event) {
var element = Event.findElement(event, 'LI');
if(this.index != element.autocompleteIndex)
{
this.index = element.autocompleteIndex;
this.render();
}
Event.stop(event);
},
onClick: function(event) {
var element = Event.findElement(event, 'LI');
this.index = element.autocompleteIndex;
this.selectEntry();
this.hide();
},
onBlur: function(event) {
// needed to make click events working
setTimeout(this.hide.bind(this), 250);
this.hasFocus = false;
this.active = false;
},
render: function() {
if(this.entryCount > 0) {
for (var i = 0; i < this.entryCount; i++)
this.index==i ?
Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
if(this.hasFocus) {
this.show();
this.active = true;
}
} else {
this.active = false;
this.hide();
}
},
markPrevious: function() {
if(this.index > 0) this.index--;
else this.index = this.entryCount-1;
this.getEntry(this.index).scrollIntoView(true);
},
markNext: function() {
if(this.index < this.entryCount-1) this.index++;
else this.index = 0;
this.getEntry(this.index).scrollIntoView(false);
},
getEntry: function(index) {
return this.update.firstChild.childNodes[index];
},
getCurrentEntry: function() {
return this.getEntry(this.index);
},
selectEntry: function() {
this.active = false;
this.updateElement(this.getCurrentEntry());
},
updateElement: function(selectedElement) {
if (this.options.updateElement) {
this.options.updateElement(selectedElement);
return;
}
var value = '';
if (this.options.select) {
var nodes = $(selectedElement).select('.' + this.options.select) || [];
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var bounds = this.getTokenBounds();
if (bounds[0] != -1) {
var newValue = this.element.value.substr(0, bounds[0]);
var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
if (whitespace)
newValue += whitespace[0];
this.element.value = newValue + value + this.element.value.substr(bounds[1]);
} else {
this.element.value = value;
}
this.oldElementValue = this.element.value;
this.element.focus();
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, selectedElement);
},
updateChoices: function(choices) {
if(!this.changed && this.hasFocus) {
this.update.innerHTML = choices;
Element.cleanWhitespace(this.update);
Element.cleanWhitespace(this.update.down());
if(this.update.firstChild && this.update.down().childNodes) {
this.entryCount =
this.update.down().childNodes.length;
for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i);
entry.autocompleteIndex = i;
this.addObservers(entry);
}
} else {
this.entryCount = 0;
}
this.stopIndicator();
this.index = 0;
if(this.entryCount==1 && this.options.autoSelect) {
this.selectEntry();
this.hide();
} else {
this.render();
}
}
},
addObservers: function(element) {
Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
Event.observe(element, "click", this.onClick.bindAsEventListener(this));
},
onObserverEvent: function() {
this.changed = false;
this.tokenBounds = null;
if(this.getToken().length>=this.options.minChars) {
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
this.oldElementValue = this.element.value;
},
getToken: function() {
var bounds = this.getTokenBounds();
return this.element.value.substring(bounds[0], bounds[1]).strip();
},
getTokenBounds: function() {
if (null != this.tokenBounds) return this.tokenBounds;
var value = this.element.value;
if (value.strip().empty()) return [-1, 0];
var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
var offset = (diff == this.oldElementValue.length ? 1 : 0);
var prevTokenPos = -1, nextTokenPos = value.length;
var tp;
for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
if (tp > prevTokenPos) prevTokenPos = tp;
tp = value.indexOf(this.options.tokens[index], diff + offset);
if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
}
return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
}
});
Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
var boundary = Math.min(newS.length, oldS.length);
for (var index = 0; index < boundary; ++index)
if (newS[index] != oldS[index])
return index;
return boundary;
};
Ajax.Autocompleter = Class.create(Autocompleter.Base, {
initialize: function(element, update, url, options) {
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
this.options.onComplete = this.onComplete.bind(this);
this.options.defaultParams = this.options.parameters || null;
this.url = url;
},
getUpdatedChoices: function() {
this.startIndicator();
var entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
this.options.callback(this.element, entry) : entry;
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
});
// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
// text only at the beginning of strings in the
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
// search anywhere in the string, additionally set
// the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
// a partial match (unlike minChars, which defines
// how many characters are required to do any match
// at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
// It's possible to pass in a custom function as the 'selector'
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.
Autocompleter.Local = Class.create(Autocompleter.Base, {
initialize: function(element, update, array, options) {
this.baseInitialize(element, update, options);
this.options.array = array;
},
getUpdatedChoices: function() {
this.updateChoices(this.options.selector(this));
},
setOptions: function(options) {
this.options = Object.extend({
choices: 10,
partialSearch: true,
partialChars: 2,
ignoreCase: true,
fullSearch: false,
selector: function(instance) {
var ret = []; // Beginning matches
var partial = []; // Inside matches
var entry = instance.getToken();
var count = 0;
for (var i = 0; i < instance.options.array.length &&
ret.length < instance.options.choices ; i++) {
var elem = instance.options.array[i];
var foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase()) :
elem.indexOf(entry);
while (foundPos != -1) {
if (foundPos == 0 && elem.length != entry.length) {
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
elem.substr(entry.length) + "</li>");
break;
} else if (entry.length >= instance.options.partialChars &&
instance.options.partialSearch && foundPos != -1) {
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
foundPos + entry.length) + "</li>");
break;
}
}
foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
elem.indexOf(entry, foundPos + 1);
}
}
if (partial.length)
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
return "<ul>" + ret.join('') + "</ul>";
}
}, options || { });
}
});
// AJAX in-place editor and collection editor
// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
setTimeout(function() {
Field.activate(field);
}, 1);
};
Ajax.InPlaceEditor = Class.create({
initialize: function(element, url, options) {
this.url = url;
this.element = element = $(element);
this.prepareOptions();
this._controls = { };
arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
Object.extend(this.options, options || { });
if (!this.options.formId && this.element.id) {
this.options.formId = this.element.id + '-inplaceeditor';
if ($(this.options.formId))
this.options.formId = '';
}
if (this.options.externalControl)
this.options.externalControl = $(this.options.externalControl);
if (!this.options.externalControl)
this.options.externalControlOnly = false;
this._originalBackground = this.element.getStyle('background-color') || 'transparent';
this.element.title = this.options.clickToEditText;
this._boundCancelHandler = this.handleFormCancellation.bind(this);
this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
this._boundFailureHandler = this.handleAJAXFailure.bind(this);
this._boundSubmitHandler = this.handleFormSubmission.bind(this);
this._boundWrapperHandler = this.wrapUp.bind(this);
this.registerListeners();
},
checkForEscapeOrReturn: function(e) {
if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
if (Event.KEY_ESC == e.keyCode)
this.handleFormCancellation(e);
else if (Event.KEY_RETURN == e.keyCode)
this.handleFormSubmission(e);
},
createControl: function(mode, handler, extraClasses) {
var control = this.options[mode + 'Control'];
var text = this.options[mode + 'Text'];
if ('button' == control) {
var btn = document.createElement('input');
btn.type = 'submit';
btn.value = text;
btn.className = 'editor_' + mode + '_button';
if ('cancel' == mode)
btn.onclick = this._boundCancelHandler;
this._form.appendChild(btn);
this._controls[mode] = btn;
} else if ('link' == control) {
var link = document.createElement('a');
link.href = '#';
link.appendChild(document.createTextNode(text));
link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
link.className = 'editor_' + mode + '_link';
if (extraClasses)
link.className += ' ' + extraClasses;
this._form.appendChild(link);
this._controls[mode] = link;
}
},
createEditField: function() {
var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
var fld;
if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
fld = document.createElement('input');
fld.type = 'text';
var size = this.options.size || this.options.cols || 0;
if (0 < size) fld.size = size;
} else {
fld = document.createElement('textarea');
fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
fld.cols = this.options.cols || 40;
}
fld.name = this.options.paramName;
fld.value = text; // No HTML breaks conversion anymore
fld.className = 'editor_field';
if (this.options.submitOnBlur)
fld.onblur = this._boundSubmitHandler;
this._controls.editor = fld;
if (this.options.loadTextURL)
this.loadExternalText();
this._form.appendChild(this._controls.editor);
},
createForm: function() {
var ipe = this;
function addText(mode, condition) {
var text = ipe.options['text' + mode + 'Controls'];
if (!text || condition === false) return;
ipe._form.appendChild(document.createTextNode(text));
};
this._form = $(document.createElement('form'));
this._form.id = this.options.formId;
this._form.addClassName(this.options.formClassName);
this._form.onsubmit = this._boundSubmitHandler;
this.createEditField();
if ('textarea' == this._controls.editor.tagName.toLowerCase())
this._form.appendChild(document.createElement('br'));
if (this.options.onFormCustomization)
this.options.onFormCustomization(this, this._form);
addText('Before', this.options.okControl || this.options.cancelControl);
this.createControl('ok', this._boundSubmitHandler);
addText('Between', this.options.okControl && this.options.cancelControl);
this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
addText('After', this.options.okControl || this.options.cancelControl);
},
destroy: function() {
if (this._oldInnerHTML)
this.element.innerHTML = this._oldInnerHTML;
this.leaveEditMode();
this.unregisterListeners();
},
enterEditMode: function(e) {
if (this._saving || this._editing) return;
this._editing = true;
this.triggerCallback('onEnterEditMode');
if (this.options.externalControl)
this.options.externalControl.hide();
this.element.hide();
this.createForm();
this.element.parentNode.insertBefore(this._form, this.element);
if (!this.options.loadTextURL)
this.postProcessEditField();
if (e) Event.stop(e);
},
enterHover: function(e) {
if (this.options.hoverClassName)
this.element.addClassName(this.options.hoverClassName);
if (this._saving) return;
this.triggerCallback('onEnterHover');
},
getText: function() {
return this.element.innerHTML.unescapeHTML();
},
handleAJAXFailure: function(transport) {
this.triggerCallback('onFailure', transport);
if (this._oldInnerHTML) {
this.element.innerHTML = this._oldInnerHTML;
this._oldInnerHTML = null;
}
},
handleFormCancellation: function(e) {
this.wrapUp();
if (e) Event.stop(e);
},
handleFormSubmission: function(e) {
var form = this._form;
var value = $F(this._controls.editor);
this.prepareSubmission();
var params = this.options.callback(form, value) || '';
if (Object.isString(params))
params = params.toQueryParams();
params.editorId = this.element.id;
if (this.options.htmlResponse) {
var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Updater({ success: this.element }, this.url, options);
} else {
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.url, options);
}
if (e) Event.stop(e);
},
leaveEditMode: function() {
this.element.removeClassName(this.options.savingClassName);
this.removeForm();
this.leaveHover();
this.element.style.backgroundColor = this._originalBackground;
this.element.show();
if (this.options.externalControl)
this.options.externalControl.show();
this._saving = false;
this._editing = false;
this._oldInnerHTML = null;
this.triggerCallback('onLeaveEditMode');
},
leaveHover: function(e) {
if (this.options.hoverClassName)
this.element.removeClassName(this.options.hoverClassName);
if (this._saving) return;
this.triggerCallback('onLeaveHover');
},
loadExternalText: function() {
this._form.addClassName(this.options.loadingClassName);
this._controls.editor.disabled = true;
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
this._form.removeClassName(this.options.loadingClassName);
var text = transport.responseText;
if (this.options.stripLoadedTextTags)
text = text.stripTags();
this._controls.editor.value = text;
this._controls.editor.disabled = false;
this.postProcessEditField();
}.bind(this),
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.options.loadTextURL, options);
},
postProcessEditField: function() {
var fpc = this.options.fieldPostCreation;
if (fpc)
$(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
},
prepareOptions: function() {
this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
[this._extraDefaultOptions].flatten().compact().each(function(defs) {
Object.extend(this.options, defs);
}.bind(this));
},
prepareSubmission: function() {
this._saving = true;
this.removeForm();
this.leaveHover();
this.showSaving();
},
registerListeners: function() {
this._listeners = { };
var listener;
$H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
listener = this[pair.value].bind(this);
this._listeners[pair.key] = listener;
if (!this.options.externalControlOnly)
this.element.observe(pair.key, listener);
if (this.options.externalControl)
this.options.externalControl.observe(pair.key, listener);
}.bind(this));
},
removeForm: function() {
if (!this._form) return;
this._form.remove();
this._form = null;
this._controls = { };
},
showSaving: function() {
this._oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
this.element.addClassName(this.options.savingClassName);
this.element.style.backgroundColor = this._originalBackground;
this.element.show();
},
triggerCallback: function(cbName, arg) {
if ('function' == typeof this.options[cbName]) {
this.options[cbName](this, arg);
}
},
unregisterListeners: function() {
$H(this._listeners).each(function(pair) {
if (!this.options.externalControlOnly)
this.element.stopObserving(pair.key, pair.value);
if (this.options.externalControl)
this.options.externalControl.stopObserving(pair.key, pair.value);
}.bind(this));
},
wrapUp: function(transport) {
this.leaveEditMode();
// Can't use triggerCallback due to backward compatibility: requires
// binding + direct element
this._boundComplete(transport, this.element);
}
});
Object.extend(Ajax.InPlaceEditor.prototype, {
dispose: Ajax.InPlaceEditor.prototype.destroy
});
Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
initialize: function($super, element, url, options) {
this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
$super(element, url, options);
},
createEditField: function() {
var list = document.createElement('select');
list.name = this.options.paramName;
list.size = 1;
this._controls.editor = list;
this._collection = this.options.collection || [];
if (this.options.loadCollectionURL)
this.loadCollection();
else
this.checkForExternalText();
this._form.appendChild(this._controls.editor);
},
loadCollection: function() {
this._form.addClassName(this.options.loadingClassName);
this.showLoadingText(this.options.loadingCollectionText);
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
var js = transport.responseText.strip();
if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
throw('Server returned an invalid collection representation.');
this._collection = eval(js);
this.checkForExternalText();
}.bind(this),
onFailure: this.onFailure
});
new Ajax.Request(this.options.loadCollectionURL, options);
},
showLoadingText: function(text) {
this._controls.editor.disabled = true;
var tempOption = this._controls.editor.firstChild;
if (!tempOption) {
tempOption = document.createElement('option');
tempOption.value = '';
this._controls.editor.appendChild(tempOption);
tempOption.selected = true;
}
tempOption.update((text || '').stripScripts().stripTags());
},
checkForExternalText: function() {
this._text = this.getText();
if (this.options.loadTextURL)
this.loadExternalText();
else
this.buildOptionList();
},
loadExternalText: function() {
this.showLoadingText(this.options.loadingText);
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
this._text = transport.responseText.strip();
this.buildOptionList();
}.bind(this),
onFailure: this.onFailure
});
new Ajax.Request(this.options.loadTextURL, options);
},
buildOptionList: function() {
this._form.removeClassName(this.options.loadingClassName);
this._collection = this._collection.map(function(entry) {
return 2 === entry.length ? entry : [entry, entry].flatten();
});
var marker = ('value' in this.options) ? this.options.value : this._text;
var textFound = this._collection.any(function(entry) {
return entry[0] == marker;
}.bind(this));
this._controls.editor.update('');
var option;
this._collection.each(function(entry, index) {
option = document.createElement('option');
option.value = entry[0];
option.selected = textFound ? entry[0] == marker : 0 == index;
option.appendChild(document.createTextNode(entry[1]));
this._controls.editor.appendChild(option);
}.bind(this));
this._controls.editor.disabled = false;
Field.scrollFreeActivate(this._controls.editor);
}
});
//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
//**** This only exists for a while, in order to let ****
//**** users adapt to the new API. Read up on the new ****
//**** API and convert your code to it ASAP! ****
Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
if (!options) return;
function fallback(name, expr) {
if (name in options || expr === undefined) return;
options[name] = expr;
};
fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
options.cancelLink == options.cancelButton == false ? false : undefined)));
fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
options.okLink == options.okButton == false ? false : undefined)));
fallback('highlightColor', options.highlightcolor);
fallback('highlightEndColor', options.highlightendcolor);
};
Object.extend(Ajax.InPlaceEditor, {
DefaultOptions: {
ajaxOptions: { },
autoRows: 3, // Use when multi-line w/ rows == 1
cancelControl: 'link', // 'link'|'button'|false
cancelText: 'cancel',
clickToEditText: 'Click to edit',
externalControl: null, // id|elt
externalControlOnly: false,
fieldPostCreation: 'activate', // 'activate'|'focus'|false
formClassName: 'inplaceeditor-form',
formId: null, // id|elt
highlightColor: '#ffff99',
highlightEndColor: '#ffffff',
hoverClassName: '',
htmlResponse: true,
loadingClassName: 'inplaceeditor-loading',
loadingText: 'Loading...',
okControl: 'button', // 'link'|'button'|false
okText: 'ok',
paramName: 'value',
rows: 1, // If 1 and multi-line, uses autoRows
savingClassName: 'inplaceeditor-saving',
savingText: 'Saving...',
size: 0,
stripLoadedTextTags: false,
submitOnBlur: false,
textAfterControls: '',
textBeforeControls: '',
textBetweenControls: ''
},
DefaultCallbacks: {
callback: function(form) {
return Form.serialize(form);
},
onComplete: function(transport, element) {
// For backward compatibility, this one is bound to the IPE, and passes
// the element directly. It was too often customized, so we don't break it.
new Effect.Highlight(element, {
startcolor: this.options.highlightColor, keepBackgroundImage: true });
},
onEnterEditMode: null,
onEnterHover: function(ipe) {
ipe.element.style.backgroundColor = ipe.options.highlightColor;
if (ipe._effect)
ipe._effect.cancel();
},
onFailure: function(transport, ipe) {
alert('Error communication with the server: ' + transport.responseText.stripTags());
},
onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
onLeaveEditMode: null,
onLeaveHover: function(ipe) {
ipe._effect = new Effect.Highlight(ipe.element, {
startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
restorecolor: ipe._originalBackground, keepBackgroundImage: true
});
}
},
Listeners: {
click: 'enterEditMode',
keydown: 'checkForEscapeOrReturn',
mouseover: 'enterHover',
mouseout: 'leaveHover'
}
});
Ajax.InPlaceCollectionEditor.DefaultOptions = {
loadingCollectionText: 'Loading options...'
};
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
Form.Element.DelayedObserver = Class.create({
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
this.callback = callback;
this.timer = null;
this.lastValue = $F(this.element);
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
delayedListener: function(event) {
if(this.lastValue == $F(this.element)) return;
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
this.lastValue = $F(this.element);
},
onTimerEvent: function() {
this.timer = null;
this.callback(this.element, $F(this.element));
}
});

View File

@ -1,995 +0,0 @@
// script.aculo.us dragdrop.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
if(Object.isUndefined(Effect))
throw("dragdrop.js requires including script.aculo.us' effects.js library");
var Droppables = {
drops: [],
empty: function () {
this.drops = [];
},
remove: function(element) {
this.drops = this.drops.reject(function(d) { return d.element==$(element) });
},
add: function(element) {
element = $(element);
var options = Object.extend({
greedy: true,
hoverclass: null,
tree: false
}, arguments[1] || { });
// cache containers
if(options.containment) {
options._containers = [];
var containment = options.containment;
if(Object.isArray(containment)) {
containment.each( function(c) { options._containers.push($(c)) });
} else {
options._containers.push($(containment));
}
}
if(options.accept) options.accept = [options.accept].flatten();
Element.makePositioned(element); // fix IE
options.element = element;
this.drops.push(options);
},
findDeepestChild: function(drops) {
deepest = drops[0];
for (i = 1; i < drops.length; ++i)
if (Element.isParent(drops[i].element, deepest.element))
deepest = drops[i];
return deepest;
},
isContained: function(element, drop) {
var containmentNode;
if(drop.tree) {
containmentNode = element.treeNode;
} else {
containmentNode = element.parentNode;
}
return drop._containers.detect(function(c) { return containmentNode == c });
},
isAffected: function(point, element, drop) {
return (
(drop.element!=element) &&
((!drop._containers) ||
this.isContained(element, drop)) &&
((!drop.accept) ||
(Element.classNames(element).detect(
function(v) { return drop.accept.include(v) } ) )) &&
Position.within(drop.element, point[0], point[1]) );
},
deactivate: function(drop) {
if(drop.hoverclass)
Element.removeClassName(drop.element, drop.hoverclass);
this.last_active = null;
},
activate: function(drop) {
if(drop.hoverclass)
Element.addClassName(drop.element, drop.hoverclass);
this.last_active = drop;
},
show: function(point, element) {
if(!this.drops.length) return;
var drop, affected = [];
this.drops.each( function(drop) {
if(Droppables.isAffected(point, element, drop))
affected.push(drop);
});
if(affected.length>0)
drop = Droppables.findDeepestChild(affected);
if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
if (drop) {
Position.within(drop.element, point[0], point[1]);
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
if (drop != this.last_active) Droppables.activate(drop);
}
},
fire: function(event, element) {
if(!this.last_active) return;
Position.prepare();
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
if (this.last_active.onDrop) {
this.last_active.onDrop(element, this.last_active.element, event);
return true;
}
},
reset: function() {
if(this.last_active)
this.deactivate(this.last_active);
}
};
var Draggables = {
drags: [],
observers: [],
empty: function () {
this.drags = [];
this.observers = [];
},
register: function(draggable) {
if(this.drags.length == 0) {
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
this.eventKeypress = this.keyPress.bindAsEventListener(this);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
}
this.drags.push(draggable);
},
unregister: function(draggable) {
this.drags = this.drags.reject(function(d) { return d==draggable });
if(this.drags.length == 0) {
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
Event.stopObserving(document, "keypress", this.eventKeypress);
}
},
activate: function(draggable) {
if(draggable.options.delay) {
this._timeout = setTimeout(function() {
Draggables._timeout = null;
window.focus();
Draggables.activeDraggable = draggable;
}.bind(this), draggable.options.delay);
} else {
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
this.activeDraggable = draggable;
}
},
deactivate: function() {
this.activeDraggable = null;
},
updateDrag: function(event) {
if(!this.activeDraggable) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
// Mozilla-based browsers fire successive mousemove events with
// the same coordinates, prevent needless redrawing (moz bug?)
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
this._lastPointer = pointer;
this.activeDraggable.updateDrag(event, pointer);
},
endDrag: function(event) {
if(this._timeout) {
clearTimeout(this._timeout);
this._timeout = null;
}
if(!this.activeDraggable) return;
this._lastPointer = null;
this.activeDraggable.endDrag(event);
this.activeDraggable = null;
},
keyPress: function(event) {
if(this.activeDraggable)
this.activeDraggable.keyPress(event);
},
addObserver: function(observer) {
this.observers.push(observer);
this._cacheObserverCallbacks();
},
removeObserver: function(element) { // element instead of observer fixes mem leaks
this.observers = this.observers.reject( function(o) { return o.element==element });
this._cacheObserverCallbacks();
},
notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
if(this[eventName+'Count'] > 0)
this.observers.each( function(o) {
if(o[eventName]) o[eventName](eventName, draggable, event);
});
if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
},
_cacheObserverCallbacks: function() {
['onStart','onEnd','onDrag'].each( function(eventName) {
Draggables[eventName+'Count'] = Draggables.observers.select(
function(o) { return o[eventName]; }
).length;
});
}
};
/*--------------------------------------------------------------------------*/
var Draggable = Class.create({
initialize: function(element) {
var defaults = {
handle: false,
reverteffect: function(element, top_offset, left_offset) {
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
queue: {scope:'_draggable', position:'end'}
});
},
endeffect: function(element) {
var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
queue: {scope:'_draggable', position:'end'},
afterFinish: function(){
Draggable._dragging[element] = false
}
});
},
zindex: 1000,
revert: false,
quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
delay: 0
};
if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
Object.extend(defaults, {
starteffect: function(element) {
element._opacity = Element.getOpacity(element);
Draggable._dragging[element] = true;
new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
}
});
var options = Object.extend(defaults, arguments[1] || { });
this.element = $(element);
if(options.handle && Object.isString(options.handle))
this.handle = this.element.down('.'+options.handle, 0);
if(!this.handle) this.handle = $(options.handle);
if(!this.handle) this.handle = this.element;
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
options.scroll = $(options.scroll);
this._isScrollChild = Element.childOf(this.element, options.scroll);
}
Element.makePositioned(this.element); // fix IE
this.options = options;
this.dragging = false;
this.eventMouseDown = this.initDrag.bindAsEventListener(this);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
Draggables.register(this);
},
destroy: function() {
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
Draggables.unregister(this);
},
currentDelta: function() {
return([
parseInt(Element.getStyle(this.element,'left') || '0'),
parseInt(Element.getStyle(this.element,'top') || '0')]);
},
initDrag: function(event) {
if(!Object.isUndefined(Draggable._dragging[this.element]) &&
Draggable._dragging[this.element]) return;
if(Event.isLeftClick(event)) {
// abort on form elements, fixes a Firefox issue
var src = Event.element(event);
if((tag_name = src.tagName.toUpperCase()) && (
tag_name=='INPUT' ||
tag_name=='SELECT' ||
tag_name=='OPTION' ||
tag_name=='BUTTON' ||
tag_name=='TEXTAREA')) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var pos = Position.cumulativeOffset(this.element);
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
Draggables.activate(this);
}
},
startDrag: function(event) {
this.dragging = true;
if(!this.delta)
this.delta = this.currentDelta();
if(this.options.zindex) {
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
this.element.style.zIndex = this.options.zindex;
}
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
if (!this._originallyAbsolute)
Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
if(this.options.scroll) {
Position.includeScrollOffsets = true;
if (this.options.scroll == window) {
var where = this._getWindowScroll(this.options.scroll);
this.originalScrollLeft = where.left;
this.originalScrollTop = where.top;
} else {
this.originalScrollLeft = this.options.scroll.scrollLeft;
this.originalScrollTop = this.options.scroll.scrollTop;
}
}
else
Position.includeScrollOffsets = false;
Draggables.notify('onStart', this, event);
if(this.options.starteffect) this.options.starteffect(this.element);
},
updateDrag: function(event, pointer) {
if(!this.dragging) this.startDrag(event);
if(!this.options.quiet){
Position.prepare();
Droppables.show(pointer, this.element);
}
Draggables.notify('onDrag', this, event);
this.draw(pointer);
if(this.options.change) this.options.change(this);
if(this.options.scroll) {
this.stopScrolling();
var p;
if (this.options.scroll == window) {
with(this._getWindowScroll(this.options.scroll)) {
p = [ left, top, left+width, top+height ];
}
} else {
p = Position.page(this.options.scroll).toArray();
p[0] += this.options.scroll.scrollLeft + Position.deltaX;
p[1] += this.options.scroll.scrollTop + Position.deltaY;
p.push(p[0]+this.options.scroll.offsetWidth);
p.push(p[1]+this.options.scroll.offsetHeight);
}
var speed = [0,0];
if(pointer[0] < (p[0]+this.options.scrollSensitivity))
speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
if(pointer[1] < (p[1]+this.options.scrollSensitivity))
speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
if(pointer[0] > (p[2]-this.options.scrollSensitivity))
speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
if(pointer[1] > (p[3]-this.options.scrollSensitivity))
speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
this.startScrolling(speed);
}
// fix AppleWebKit rendering
if(Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
},
finishDrag: function(event, success) {
this.dragging = false;
if(this.options.quiet){
Position.prepare();
var pointer = [Event.pointerX(event), Event.pointerY(event)];
Droppables.show(pointer, this.element);
}
if(this.options.ghosting) {
if (!this._originallyAbsolute)
Position.relativize(this.element);
delete this._originallyAbsolute;
Element.remove(this._clone);
this._clone = null;
}
var dropped = false;
if(success) {
dropped = Droppables.fire(event, this.element);
if (!dropped) dropped = false;
}
if(dropped && this.options.onDropped) this.options.onDropped(this.element);
Draggables.notify('onEnd', this, event);
var revert = this.options.revert;
if(revert && Object.isFunction(revert)) revert = revert(this.element);
var d = this.currentDelta();
if(revert && this.options.reverteffect) {
if (dropped == 0 || revert != 'failure')
this.options.reverteffect(this.element,
d[1]-this.delta[1], d[0]-this.delta[0]);
} else {
this.delta = d;
}
if(this.options.zindex)
this.element.style.zIndex = this.originalZ;
if(this.options.endeffect)
this.options.endeffect(this.element);
Draggables.deactivate(this);
Droppables.reset();
},
keyPress: function(event) {
if(event.keyCode!=Event.KEY_ESC) return;
this.finishDrag(event, false);
Event.stop(event);
},
endDrag: function(event) {
if(!this.dragging) return;
this.stopScrolling();
this.finishDrag(event, true);
Event.stop(event);
Position.includeScrollOffsets = false;
},
draw: function(point) {
var pos = Position.cumulativeOffset(this.element);
if(this.options.ghosting) {
var r = Position.realOffset(this.element);
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
}
var d = this.currentDelta();
pos[0] -= d[0]; pos[1] -= d[1];
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
}
var __size = [parseInt(this.element.style.width)*0.75,
parseInt(this.element.style.height)*0.80]
var p = [0,1].map(function(i){
return (point[i]-pos[i]-__size[i])
}.bind(this));
if(this.options.snap) {
if(Object.isFunction(this.options.snap)) {
p = this.options.snap(p[0],p[1],this);
} else {
if(Object.isArray(this.options.snap)) {
p = p.map( function(v, i) {
return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
} else {
p = p.map( function(v) {
return (v/this.options.snap).round()*this.options.snap }.bind(this));
}
}}
var style = this.element.style;
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
style.left = p[0] + "px";
if((!this.options.constraint) || (this.options.constraint=='vertical'))
style.top = p[1] + "px";
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
},
stopScrolling: function() {
if(this.scrollInterval) {
clearInterval(this.scrollInterval);
this.scrollInterval = null;
Draggables._lastScrollPointer = null;
}
},
startScrolling: function(speed) {
if(!(speed[0] || speed[1])) return;
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
this.lastScrolled = new Date();
this.scrollInterval = setInterval(this.scroll.bind(this), 10);
},
scroll: function() {
var current = new Date();
var delta = current - this.lastScrolled;
this.lastScrolled = current;
if(this.options.scroll == window) {
with (this._getWindowScroll(this.options.scroll)) {
if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
var d = delta / 1000;
this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
}
}
} else {
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
}
Position.prepare();
Droppables.show(Draggables._lastPointer, this.element);
Draggables.notify('onDrag', this);
if (this._isScrollChild) {
Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
if (Draggables._lastScrollPointer[0] < 0)
Draggables._lastScrollPointer[0] = 0;
if (Draggables._lastScrollPointer[1] < 0)
Draggables._lastScrollPointer[1] = 0;
this.draw(Draggables._lastScrollPointer);
}
if(this.options.change) this.options.change(this);
},
_getWindowScroll: function(w) {
var T, L, W, H;
with (w.document) {
if (w.document.documentElement && documentElement.scrollTop) {
T = documentElement.scrollTop;
L = documentElement.scrollLeft;
} else if (w.document.body) {
T = body.scrollTop;
L = body.scrollLeft;
}
if (w.innerWidth) {
W = w.innerWidth;
H = w.innerHeight;
} else if (w.document.documentElement && documentElement.clientWidth) {
W = documentElement.clientWidth;
H = documentElement.clientHeight;
} else {
W = body.offsetWidth;
H = body.offsetHeight;
}
}
return { top: T, left: L, width: W, height: H };
}
});
Draggable._dragging = { };
/*--------------------------------------------------------------------------*/
var SortableObserver = Class.create({
initialize: function(element, observer) {
this.element = $(element);
this.observer = observer;
this.lastValue = Sortable.serialize(this.element);
},
onStart: function() {
this.lastValue = Sortable.serialize(this.element);
},
onEnd: function() {
Sortable.unmark();
if(this.lastValue != Sortable.serialize(this.element))
this.observer(this.element)
}
});
var Sortable = {
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
sortables: { },
_findRootElement: function(element) {
while (element.tagName.toUpperCase() != "BODY") {
if(element.id && Sortable.sortables[element.id]) return element;
element = element.parentNode;
}
},
options: function(element) {
element = Sortable._findRootElement($(element));
if(!element) return;
return Sortable.sortables[element.id];
},
destroy: function(element){
element = $(element);
var s = Sortable.sortables[element.id];
if(s) {
Draggables.removeObserver(s.element);
s.droppables.each(function(d){ Droppables.remove(d) });
s.draggables.invoke('destroy');
delete Sortable.sortables[s.element.id];
}
},
create: function(element) {
element = $(element);
var options = Object.extend({
element: element,
tag: 'li', // assumes li children, override with tag: 'tagname'
dropOnEmpty: false,
tree: false,
treeTag: 'ul',
overlap: 'vertical', // one of 'vertical', 'horizontal'
constraint: 'vertical', // one of 'vertical', 'horizontal', false
containment: element, // also takes array of elements (or id's); or false
handle: false, // or a CSS class
only: false,
delay: 0,
hoverclass: null,
ghosting: false,
quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
format: this.SERIALIZE_RULE,
// these take arrays of elements or ids and can be
// used for better initialization performance
elements: false,
handles: false,
onChange: Prototype.emptyFunction,
onUpdate: Prototype.emptyFunction
}, arguments[1] || { });
// clear any old sortable with same element
this.destroy(element);
// build options for the draggables
var options_for_draggable = {
revert: true,
quiet: options.quiet,
scroll: options.scroll,
scrollSpeed: options.scrollSpeed,
scrollSensitivity: options.scrollSensitivity,
delay: options.delay,
ghosting: options.ghosting,
constraint: options.constraint,
handle: options.handle };
if(options.starteffect)
options_for_draggable.starteffect = options.starteffect;
if(options.reverteffect)
options_for_draggable.reverteffect = options.reverteffect;
else
if(options.ghosting) options_for_draggable.reverteffect = function(element) {
element.style.top = 0;
element.style.left = 0;
};
if(options.endeffect)
options_for_draggable.endeffect = options.endeffect;
if(options.zindex)
options_for_draggable.zindex = options.zindex;
// build options for the droppables
var options_for_droppable = {
overlap: options.overlap,
containment: options.containment,
tree: options.tree,
hoverclass: options.hoverclass,
onHover: Sortable.onHover
};
var options_for_tree = {
onHover: Sortable.onEmptyHover,
overlap: options.overlap,
containment: options.containment,
hoverclass: options.hoverclass
};
// fix for gecko engine
Element.cleanWhitespace(element);
options.draggables = [];
options.droppables = [];
// drop on empty handling
if(options.dropOnEmpty || options.tree) {
Droppables.add(element, options_for_tree);
options.droppables.push(element);
}
(options.elements || this.findElements(element, options) || []).each( function(e,i) {
var handle = options.handles ? $(options.handles[i]) :
(options.handle ? $(e).select('.' + options.handle)[0] : e);
options.draggables.push(
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
Droppables.add(e, options_for_droppable);
if(options.tree) e.treeNode = element;
options.droppables.push(e);
});
if(options.tree) {
(Sortable.findTreeElements(element, options) || []).each( function(e) {
Droppables.add(e, options_for_tree);
e.treeNode = element;
options.droppables.push(e);
});
}
// keep reference
this.sortables[element.id] = options;
// for onupdate
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
},
// return all suitable-for-sortable elements in a guaranteed order
findElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.tag);
},
findTreeElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.treeTag);
},
onHover: function(element, dropon, overlap) {
if(Element.isParent(dropon, element)) return;
if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
return;
} else if(overlap>0.5) {
Sortable.mark(dropon, 'before');
if(dropon.previousSibling != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, dropon);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
} else {
Sortable.mark(dropon, 'after');
var nextElement = dropon.nextSibling || null;
if(nextElement != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, nextElement);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
}
},
onEmptyHover: function(element, dropon, overlap) {
var oldParentNode = element.parentNode;
var droponOptions = Sortable.options(dropon);
if(!Element.isParent(dropon, element)) {
var index;
var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
var child = null;
if(children) {
var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
for (index = 0; index < children.length; index += 1) {
if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
offset -= Element.offsetSize (children[index], droponOptions.overlap);
} else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
child = index + 1 < children.length ? children[index + 1] : null;
break;
} else {
child = children[index];
break;
}
}
}
dropon.insertBefore(element, child);
Sortable.options(oldParentNode).onChange(element);
droponOptions.onChange(element);
}
},
unmark: function() {
if(Sortable._marker) Sortable._marker.hide();
},
mark: function(dropon, position) {
// mark on ghosting only
var sortable = Sortable.options(dropon.parentNode);
if(sortable && !sortable.ghosting) return;
if(!Sortable._marker) {
Sortable._marker =
($('dropmarker') || Element.extend(document.createElement('DIV'))).
hide().addClassName('dropmarker').setStyle({position:'absolute'});
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
}
var offsets = Position.cumulativeOffset(dropon);
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
if(position=='after')
if(sortable.overlap == 'horizontal')
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
else
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
Sortable._marker.show();
},
_tree: function(element, options, parent) {
var children = Sortable.findElements(element, options) || [];
for (var i = 0; i < children.length; ++i) {
var match = children[i].id.match(options.format);
if (!match) continue;
var child = {
id: encodeURIComponent(match ? match[1] : null),
element: element,
parent: parent,
children: [],
position: parent.children.length,
container: $(children[i]).down(options.treeTag)
};
/* Get the element containing the children and recurse over it */
if (child.container)
this._tree(child.container, options, child);
parent.children.push (child);
}
return parent;
},
tree: function(element) {
element = $(element);
var sortableOptions = this.options(element);
var options = Object.extend({
tag: sortableOptions.tag,
treeTag: sortableOptions.treeTag,
only: sortableOptions.only,
name: element.id,
format: sortableOptions.format
}, arguments[1] || { });
var root = {
id: null,
parent: null,
children: [],
container: element,
position: 0
};
return Sortable._tree(element, options, root);
},
/* Construct a [i] index for a particular node */
_constructIndex: function(node) {
var index = '';
do {
if (node.id) index = '[' + node.position + ']' + index;
} while ((node = node.parent) != null);
return index;
},
sequence: function(element) {
element = $(element);
var options = Object.extend(this.options(element), arguments[1] || { });
return $(this.findElements(element, options) || []).map( function(item) {
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
});
},
setSequence: function(element, new_sequence) {
element = $(element);
var options = Object.extend(this.options(element), arguments[2] || { });
var nodeMap = { };
this.findElements(element, options).each( function(n) {
if (n.id.match(options.format))
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
n.parentNode.removeChild(n);
});
new_sequence.each(function(ident) {
var n = nodeMap[ident];
if (n) {
n[1].appendChild(n[0]);
delete nodeMap[ident];
}
});
},
serialize: function(element) {
element = $(element);
var options = Object.extend(Sortable.options(element), arguments[1] || { });
var name = encodeURIComponent(
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
if (options.tree) {
return Sortable.tree(element, arguments[1]).children.map( function (item) {
return [name + Sortable._constructIndex(item) + "[id]=" +
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
}).flatten().join('&');
} else {
return Sortable.sequence(element, arguments[1]).map( function(item) {
return name + "[]=" + encodeURIComponent(item);
}).join('&');
}
}
};
// Returns true if child is contained within element
Element.isParent = function(child, element) {
if (!child.parentNode || child == element) return false;
if (child.parentNode == element) return true;
return Element.isParent(child.parentNode, element);
};
Element.findChildren = function(element, only, recursive, tagName) {
if(!element.hasChildNodes()) return null;
tagName = tagName.toUpperCase();
if(only) only = [only].flatten();
var elements = [];
$A(element.childNodes).each( function(e) {
if(e.tagName && e.tagName.toUpperCase()==tagName &&
(!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
elements.push(e);
if(recursive) {
var grandchildren = Element.findChildren(e, only, recursive, tagName);
if(grandchildren) elements.push(grandchildren);
}
});
return (elements.length>0 ? elements.flatten() : []);
};
Element.offsetSize = function (element, type) {
return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
};

File diff suppressed because it is too large Load Diff

View File

@ -1,275 +0,0 @@
// script.aculo.us slider.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Marty Haught, Thomas Fuchs
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
if (!Control) var Control = { };
// options:
// axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
// onChange(value)
// onSlide(value)
Control.Slider = Class.create({
initialize: function(handle, track, options) {
var slider = this;
if (Object.isArray(handle)) {
this.handles = handle.collect( function(e) { return $(e) });
} else {
this.handles = [$(handle)];
}
this.track = $(track);
this.options = options || { };
this.axis = this.options.axis || 'horizontal';
this.increment = this.options.increment || 1;
this.step = parseInt(this.options.step || '1');
this.range = this.options.range || $R(0,1);
this.value = 0; // assure backwards compat
this.values = this.handles.map( function() { return 0 });
this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
this.options.startSpan = $(this.options.startSpan || null);
this.options.endSpan = $(this.options.endSpan || null);
this.restricted = this.options.restricted || false;
this.maximum = this.options.maximum || this.range.end;
this.minimum = this.options.minimum || this.range.start;
// Will be used to align the handle onto the track, if necessary
this.alignX = parseInt(this.options.alignX || '0');
this.alignY = parseInt(this.options.alignY || '0');
this.trackLength = this.maximumOffset() - this.minimumOffset();
this.handleLength = this.isVertical() ?
(this.handles[0].offsetHeight != 0 ?
this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
(this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
this.handles[0].style.width.replace(/px$/,""));
this.active = false;
this.dragging = false;
this.disabled = false;
if (this.options.disabled) this.setDisabled();
// Allowed values array
this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
if (this.allowedValues) {
this.minimum = this.allowedValues.min();
this.maximum = this.allowedValues.max();
}
this.eventMouseDown = this.startDrag.bindAsEventListener(this);
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.update.bindAsEventListener(this);
// Initialize handles in reverse (make sure first handle is active)
this.handles.each( function(h,i) {
i = slider.handles.length-1-i;
slider.setValue(parseFloat(
(Object.isArray(slider.options.sliderValue) ?
slider.options.sliderValue[i] : slider.options.sliderValue) ||
slider.range.start), i);
h.makePositioned().observe("mousedown", slider.eventMouseDown);
});
this.track.observe("mousedown", this.eventMouseDown);
document.observe("mouseup", this.eventMouseUp);
document.observe("mousemove", this.eventMouseMove);
this.initialized = true;
},
dispose: function() {
var slider = this;
Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
this.handles.each( function(h) {
Event.stopObserving(h, "mousedown", slider.eventMouseDown);
});
},
setDisabled: function(){
this.disabled = true;
},
setEnabled: function(){
this.disabled = false;
},
getNearestValue: function(value){
if (this.allowedValues){
if (value >= this.allowedValues.max()) return(this.allowedValues.max());
if (value <= this.allowedValues.min()) return(this.allowedValues.min());
var offset = Math.abs(this.allowedValues[0] - value);
var newValue = this.allowedValues[0];
this.allowedValues.each( function(v) {
var currentOffset = Math.abs(v - value);
if (currentOffset <= offset){
newValue = v;
offset = currentOffset;
}
});
return newValue;
}
if (value > this.range.end) return this.range.end;
if (value < this.range.start) return this.range.start;
return value;
},
setValue: function(sliderValue, handleIdx){
if (!this.active) {
this.activeHandleIdx = handleIdx || 0;
this.activeHandle = this.handles[this.activeHandleIdx];
this.updateStyles();
}
handleIdx = handleIdx || this.activeHandleIdx || 0;
if (this.initialized && this.restricted) {
if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
sliderValue = this.values[handleIdx-1];
if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
sliderValue = this.values[handleIdx+1];
}
sliderValue = this.getNearestValue(sliderValue);
this.values[handleIdx] = sliderValue;
this.value = this.values[0]; // assure backwards compat
this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
this.translateToPx(sliderValue);
this.drawSpans();
if (!this.dragging || !this.event) this.updateFinished();
},
setValueBy: function(delta, handleIdx) {
this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
handleIdx || this.activeHandleIdx || 0);
},
translateToPx: function(value) {
return Math.round(
((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
(value - this.range.start)) + "px";
},
translateToValue: function(offset) {
return ((offset/(this.trackLength-this.handleLength) *
(this.range.end-this.range.start)) + this.range.start);
},
getRange: function(range) {
var v = this.values.sortBy(Prototype.K);
range = range || 0;
return $R(v[range],v[range+1]);
},
minimumOffset: function(){
return(this.isVertical() ? this.alignY : this.alignX);
},
maximumOffset: function(){
return(this.isVertical() ?
(this.track.offsetHeight != 0 ? this.track.offsetHeight :
this.track.style.height.replace(/px$/,"")) - this.alignY :
(this.track.offsetWidth != 0 ? this.track.offsetWidth :
this.track.style.width.replace(/px$/,"")) - this.alignX);
},
isVertical: function(){
return (this.axis == 'vertical');
},
drawSpans: function() {
var slider = this;
if (this.spans)
$R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
if (this.options.startSpan)
this.setSpan(this.options.startSpan,
$R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
if (this.options.endSpan)
this.setSpan(this.options.endSpan,
$R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
},
setSpan: function(span, range) {
if (this.isVertical()) {
span.style.top = this.translateToPx(range.start);
span.style.height = this.translateToPx(range.end - range.start + this.range.start);
} else {
span.style.left = this.translateToPx(range.start);
span.style.width = this.translateToPx(range.end - range.start + this.range.start);
}
},
updateStyles: function() {
this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
Element.addClassName(this.activeHandle, 'selected');
},
startDrag: function(event) {
if (Event.isLeftClick(event)) {
if (!this.disabled){
this.active = true;
var handle = Event.element(event);
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var track = handle;
if (track==this.track) {
var offsets = Position.cumulativeOffset(this.track);
this.event = event;
this.setValue(this.translateToValue(
(this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
));
var offsets = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
} else {
// find the handle (prevents issues with Safari)
while((this.handles.indexOf(handle) == -1) && handle.parentNode)
handle = handle.parentNode;
if (this.handles.indexOf(handle)!=-1) {
this.activeHandle = handle;
this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
this.updateStyles();
var offsets = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
}
}
}
Event.stop(event);
}
},
update: function(event) {
if (this.active) {
if (!this.dragging) this.dragging = true;
this.draw(event);
if (Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
}
},
draw: function(event) {
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var offsets = Position.cumulativeOffset(this.track);
pointer[0] -= this.offsetX + offsets[0];
pointer[1] -= this.offsetY + offsets[1];
this.event = event;
this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
if (this.initialized && this.options.onSlide)
this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
},
endDrag: function(event) {
if (this.active && this.dragging) {
this.finishDrag(event, true);
Event.stop(event);
}
this.active = false;
this.dragging = false;
},
finishDrag: function(event, success) {
this.active = false;
this.dragging = false;
this.updateFinished();
},
updateFinished: function() {
if (this.initialized && this.options.onChange)
this.options.onChange(this.values.length>1 ? this.values : this.value, this);
this.event = null;
}
});

View File

@ -1,55 +0,0 @@
// script.aculo.us sound.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Based on code created by Jules Gravinese (http://www.webveteran.com/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
Sound = {
tracks: {},
_enabled: true,
template:
new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
enable: function(){
Sound._enabled = true;
},
disable: function(){
Sound._enabled = false;
},
play: function(url){
if(!Sound._enabled) return;
var options = Object.extend({
track: 'global', url: url, replace: false
}, arguments[1] || {});
if(options.replace && this.tracks[options.track]) {
$R(0, this.tracks[options.track].id).each(function(id){
var sound = $('sound_'+options.track+'_'+id);
sound.Stop && sound.Stop();
sound.remove();
});
this.tracks[options.track] = null;
}
if(!this.tracks[options.track])
this.tracks[options.track] = { id: 0 };
else
this.tracks[options.track].id++;
options.id = this.tracks[options.track].id;
$$('body')[0].insert(
Prototype.Browser.IE ? new Element('bgsound',{
id: 'sound_'+options.track+'_'+options.id,
src: options.url, loop: 1, autostart: true
}) : Sound.template.evaluate(options));
}
};
if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>');
else
Sound.play = function(){};
}

View File

@ -1,568 +0,0 @@
// script.aculo.us unittest.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
// (c) 2005-2008 Michael Schuerig (http://www.schuerig.de/michael/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// experimental, Firefox-only
Event.simulateMouse = function(element, eventName) {
var options = Object.extend({
pointerX: 0,
pointerY: 0,
buttons: 0,
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false
}, arguments[2] || {});
var oEvent = document.createEvent("MouseEvents");
oEvent.initMouseEvent(eventName, true, true, document.defaultView,
options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
if(this.mark) Element.remove(this.mark);
this.mark = document.createElement('div');
this.mark.appendChild(document.createTextNode(" "));
document.body.appendChild(this.mark);
this.mark.style.position = 'absolute';
this.mark.style.top = options.pointerY + "px";
this.mark.style.left = options.pointerX + "px";
this.mark.style.width = "5px";
this.mark.style.height = "5px;";
this.mark.style.borderTop = "1px solid red;";
this.mark.style.borderLeft = "1px solid red;";
if(this.step)
alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
$(element).dispatchEvent(oEvent);
};
// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
// You need to downgrade to 1.0.4 for now to get this working
// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
Event.simulateKey = function(element, eventName) {
var options = Object.extend({
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false,
keyCode: 0,
charCode: 0
}, arguments[2] || {});
var oEvent = document.createEvent("KeyEvents");
oEvent.initKeyEvent(eventName, true, true, window,
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
options.keyCode, options.charCode );
$(element).dispatchEvent(oEvent);
};
Event.simulateKeys = function(element, command) {
for(var i=0; i<command.length; i++) {
Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
}
};
var Test = {};
Test.Unit = {};
// security exception workaround
Test.Unit.inspect = Object.inspect;
Test.Unit.Logger = Class.create();
Test.Unit.Logger.prototype = {
initialize: function(log) {
this.log = $(log);
if (this.log) {
this._createLogTable();
}
},
start: function(testName) {
if (!this.log) return;
this.testName = testName;
this.lastLogLine = document.createElement('tr');
this.statusCell = document.createElement('td');
this.nameCell = document.createElement('td');
this.nameCell.className = "nameCell";
this.nameCell.appendChild(document.createTextNode(testName));
this.messageCell = document.createElement('td');
this.lastLogLine.appendChild(this.statusCell);
this.lastLogLine.appendChild(this.nameCell);
this.lastLogLine.appendChild(this.messageCell);
this.loglines.appendChild(this.lastLogLine);
},
finish: function(status, summary) {
if (!this.log) return;
this.lastLogLine.className = status;
this.statusCell.innerHTML = status;
this.messageCell.innerHTML = this._toHTML(summary);
this.addLinksToResults();
},
message: function(message) {
if (!this.log) return;
this.messageCell.innerHTML = this._toHTML(message);
},
summary: function(summary) {
if (!this.log) return;
this.logsummary.innerHTML = this._toHTML(summary);
},
_createLogTable: function() {
this.log.innerHTML =
'<div id="logsummary"></div>' +
'<table id="logtable">' +
'<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
'<tbody id="loglines"></tbody>' +
'</table>';
this.logsummary = $('logsummary');
this.loglines = $('loglines');
},
_toHTML: function(txt) {
return txt.escapeHTML().replace(/\n/g,"<br/>");
},
addLinksToResults: function(){
$$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
td.title = "Run only this test";
Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
});
$$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
td.title = "Run all tests";
Event.observe(td, 'click', function(){ window.location.search = "";});
});
}
};
Test.Unit.Runner = Class.create();
Test.Unit.Runner.prototype = {
initialize: function(testcases) {
this.options = Object.extend({
testLog: 'testlog'
}, arguments[1] || {});
this.options.resultsURL = this.parseResultsURLQueryParameter();
this.options.tests = this.parseTestsQueryParameter();
if (this.options.testLog) {
this.options.testLog = $(this.options.testLog) || null;
}
if(this.options.tests) {
this.tests = [];
for(var i = 0; i < this.options.tests.length; i++) {
if(/^test/.test(this.options.tests[i])) {
this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
}
}
} else {
if (this.options.test) {
this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
} else {
this.tests = [];
for(var testcase in testcases) {
if(/^test/.test(testcase)) {
this.tests.push(
new Test.Unit.Testcase(
this.options.context ? ' -> ' + this.options.titles[testcase] : testcase,
testcases[testcase], testcases["setup"], testcases["teardown"]
));
}
}
}
}
this.currentTest = 0;
this.logger = new Test.Unit.Logger(this.options.testLog);
setTimeout(this.runTests.bind(this), 1000);
},
parseResultsURLQueryParameter: function() {
return window.location.search.parseQuery()["resultsURL"];
},
parseTestsQueryParameter: function(){
if (window.location.search.parseQuery()["tests"]){
return window.location.search.parseQuery()["tests"].split(',');
};
},
// Returns:
// "ERROR" if there was an error,
// "FAILURE" if there was a failure, or
// "SUCCESS" if there was neither
getResult: function() {
var hasFailure = false;
for(var i=0;i<this.tests.length;i++) {
if (this.tests[i].errors > 0) {
return "ERROR";
}
if (this.tests[i].failures > 0) {
hasFailure = true;
}
}
if (hasFailure) {
return "FAILURE";
} else {
return "SUCCESS";
}
},
postResults: function() {
if (this.options.resultsURL) {
new Ajax.Request(this.options.resultsURL,
{ method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
}
},
runTests: function() {
var test = this.tests[this.currentTest];
if (!test) {
// finished!
this.postResults();
this.logger.summary(this.summary());
return;
}
if(!test.isWaiting) {
this.logger.start(test.name);
}
test.run();
if(test.isWaiting) {
this.logger.message("Waiting for " + test.timeToWait + "ms");
setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
} else {
this.logger.finish(test.status(), test.summary());
this.currentTest++;
// tail recursive, hopefully the browser will skip the stackframe
this.runTests();
}
},
summary: function() {
var assertions = 0;
var failures = 0;
var errors = 0;
var messages = [];
for(var i=0;i<this.tests.length;i++) {
assertions += this.tests[i].assertions;
failures += this.tests[i].failures;
errors += this.tests[i].errors;
}
return (
(this.options.context ? this.options.context + ': ': '') +
this.tests.length + " tests, " +
assertions + " assertions, " +
failures + " failures, " +
errors + " errors");
}
};
Test.Unit.Assertions = Class.create();
Test.Unit.Assertions.prototype = {
initialize: function() {
this.assertions = 0;
this.failures = 0;
this.errors = 0;
this.messages = [];
},
summary: function() {
return (
this.assertions + " assertions, " +
this.failures + " failures, " +
this.errors + " errors" + "\n" +
this.messages.join("\n"));
},
pass: function() {
this.assertions++;
},
fail: function(message) {
this.failures++;
this.messages.push("Failure: " + message);
},
info: function(message) {
this.messages.push("Info: " + message);
},
error: function(error) {
this.errors++;
this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
},
status: function() {
if (this.failures > 0) return 'failed';
if (this.errors > 0) return 'error';
return 'passed';
},
assert: function(expression) {
var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
try { expression ? this.pass() :
this.fail(message); }
catch(e) { this.error(e); }
},
assertEqual: function(expected, actual) {
var message = arguments[2] || "assertEqual";
try { (expected == actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertInspect: function(expected, actual) {
var message = arguments[2] || "assertInspect";
try { (expected == actual.inspect()) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertEnumEqual: function(expected, actual) {
var message = arguments[2] || "assertEnumEqual";
try { $A(expected).length == $A(actual).length &&
expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) +
', actual ' + Test.Unit.inspect(actual)); }
catch(e) { this.error(e); }
},
assertNotEqual: function(expected, actual) {
var message = arguments[2] || "assertNotEqual";
try { (expected != actual) ? this.pass() :
this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertIdentical: function(expected, actual) {
var message = arguments[2] || "assertIdentical";
try { (expected === actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertNotIdentical: function(expected, actual) {
var message = arguments[2] || "assertNotIdentical";
try { !(expected === actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertNull: function(obj) {
var message = arguments[1] || 'assertNull';
try { (obj==null) ? this.pass() :
this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
catch(e) { this.error(e); }
},
assertMatch: function(expected, actual) {
var message = arguments[2] || 'assertMatch';
var regex = new RegExp(expected);
try { (regex.exec(actual)) ? this.pass() :
this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertHidden: function(element) {
var message = arguments[1] || 'assertHidden';
this.assertEqual("none", element.style.display, message);
},
assertNotNull: function(object) {
var message = arguments[1] || 'assertNotNull';
this.assert(object != null, message);
},
assertType: function(expected, actual) {
var message = arguments[2] || 'assertType';
try {
(actual.constructor == expected) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + (actual.constructor) + '"'); }
catch(e) { this.error(e); }
},
assertNotOfType: function(expected, actual) {
var message = arguments[2] || 'assertNotOfType';
try {
(actual.constructor != expected) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + (actual.constructor) + '"'); }
catch(e) { this.error(e); }
},
assertInstanceOf: function(expected, actual) {
var message = arguments[2] || 'assertInstanceOf';
try {
(actual instanceof expected) ? this.pass() :
this.fail(message + ": object was not an instance of the expected type"); }
catch(e) { this.error(e); }
},
assertNotInstanceOf: function(expected, actual) {
var message = arguments[2] || 'assertNotInstanceOf';
try {
!(actual instanceof expected) ? this.pass() :
this.fail(message + ": object was an instance of the not expected type"); }
catch(e) { this.error(e); }
},
assertRespondsTo: function(method, obj) {
var message = arguments[2] || 'assertRespondsTo';
try {
(obj[method] && typeof obj[method] == 'function') ? this.pass() :
this.fail(message + ": object doesn't respond to [" + method + "]"); }
catch(e) { this.error(e); }
},
assertReturnsTrue: function(method, obj) {
var message = arguments[2] || 'assertReturnsTrue';
try {
var m = obj[method];
if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
m() ? this.pass() :
this.fail(message + ": method returned false"); }
catch(e) { this.error(e); }
},
assertReturnsFalse: function(method, obj) {
var message = arguments[2] || 'assertReturnsFalse';
try {
var m = obj[method];
if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
!m() ? this.pass() :
this.fail(message + ": method returned true"); }
catch(e) { this.error(e); }
},
assertRaise: function(exceptionName, method) {
var message = arguments[2] || 'assertRaise';
try {
method();
this.fail(message + ": exception expected but none was raised"); }
catch(e) {
((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e);
}
},
assertElementsMatch: function() {
var expressions = $A(arguments), elements = $A(expressions.shift());
if (elements.length != expressions.length) {
this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
return false;
}
elements.zip(expressions).all(function(pair, index) {
var element = $(pair.first()), expression = pair.last();
if (element.match(expression)) return true;
this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
}.bind(this)) && this.pass();
},
assertElementMatches: function(element, expression) {
this.assertElementsMatch([element], expression);
},
benchmark: function(operation, iterations) {
var startAt = new Date();
(iterations || 1).times(operation);
var timeTaken = ((new Date())-startAt);
this.info((arguments[2] || 'Operation') + ' finished ' +
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
return timeTaken;
},
_isVisible: function(element) {
element = $(element);
if(!element.parentNode) return true;
this.assertNotNull(element);
if(element.style && Element.getStyle(element, 'display') == 'none')
return false;
return this._isVisible(element.parentNode);
},
assertNotVisible: function(element) {
this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
},
assertVisible: function(element) {
this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
},
benchmark: function(operation, iterations) {
var startAt = new Date();
(iterations || 1).times(operation);
var timeTaken = ((new Date())-startAt);
this.info((arguments[2] || 'Operation') + ' finished ' +
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
return timeTaken;
}
};
Test.Unit.Testcase = Class.create();
Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
initialize: function(name, test, setup, teardown) {
Test.Unit.Assertions.prototype.initialize.bind(this)();
this.name = name;
if(typeof test == 'string') {
test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
this.test = function() {
eval('with(this){'+test+'}');
}
} else {
this.test = test || function() {};
}
this.setup = setup || function() {};
this.teardown = teardown || function() {};
this.isWaiting = false;
this.timeToWait = 1000;
},
wait: function(time, nextPart) {
this.isWaiting = true;
this.test = nextPart;
this.timeToWait = time;
},
run: function() {
try {
try {
if (!this.isWaiting) this.setup.bind(this)();
this.isWaiting = false;
this.test.bind(this)();
} finally {
if(!this.isWaiting) {
this.teardown.bind(this)();
}
}
}
catch(e) { this.error(e); }
}
});
// *EXPERIMENTAL* BDD-style testing to please non-technical folk
// This draws many ideas from RSpec http://rspec.rubyforge.org/
Test.setupBDDExtensionMethods = function(){
var METHODMAP = {
shouldEqual: 'assertEqual',
shouldNotEqual: 'assertNotEqual',
shouldEqualEnum: 'assertEnumEqual',
shouldBeA: 'assertType',
shouldNotBeA: 'assertNotOfType',
shouldBeAn: 'assertType',
shouldNotBeAn: 'assertNotOfType',
shouldBeNull: 'assertNull',
shouldNotBeNull: 'assertNotNull',
shouldBe: 'assertReturnsTrue',
shouldNotBe: 'assertReturnsFalse',
shouldRespondTo: 'assertRespondsTo'
};
var makeAssertion = function(assertion, args, object) {
this[assertion].apply(this,(args || []).concat([object]));
};
Test.BDDMethods = {};
$H(METHODMAP).each(function(pair) {
Test.BDDMethods[pair.key] = function() {
var args = $A(arguments);
var scope = args.shift();
makeAssertion.apply(scope, [pair.value, args, this]); };
});
[Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
function(p){ Object.extend(p, Test.BDDMethods) }
);
};
Test.context = function(name, spec, log){
Test.setupBDDExtensionMethods();
var compiledSpec = {};
var titles = {};
for(specName in spec) {
switch(specName){
case "setup":
case "teardown":
compiledSpec[specName] = spec[specName];
break;
default:
var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
var body = spec[specName].toString().split('\n').slice(1);
if(/^\{/.test(body[0])) body = body.slice(1);
body.pop();
body = body.map(function(statement){
return statement.strip()
});
compiledSpec[testName] = body.join('\n');
titles[testName] = specName;
}
}
new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
};

View File

@ -1,4 +1,4 @@
sogo: embedded-javascript-library usr/lib/GNUstep/SOGo/WebServerResources/prototype.js
sogo: extra-license-file usr/lib/GNUstep/SOGo/WebServerResources/scriptaculous/MIT-LICENSE
sogo: embedded-javascript-library usr/lib/GNUstep/SOGo/WebServerResources/scriptaculous/scriptaculous.js
sogo: embedded-javascript-library usr/lib/GNUstep/SOGo/WebServerResources/jquery.js
sogo: embedded-javascript-library usr/lib/GNUstep/SOGo/WebServerResources/jquery-ui.js
sogo: package-name-doesnt-match-sonames libGDLContentStore4.9 libNGCards4.9 libOGoContentStore0.9 libSOGoUI1.0