/dev/_lib/Fluid/3akai_Infusion.js
JavaScript | 8226 lines | 6558 code | 671 blank | 997 comment | 642 complexity | 91d89959cfdaf5cbbe73468da5303662 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /* 3akai_Infusion.js
- * custom build for Sakai
- * built with: ant customBuild -Dinclude="uploader, reorderer" -Dexclude="jQuery, jQueryUICore, jQueryUIWidgets, jQueryTooltipPlugin" -Djsfilename="3akai_Infusion.js" -DnoMinify="true"
- */
-
- /*
- * jQuery delegate plug-in v1.0
- *
- * Copyright (c) 2007 Jörn Zaefferer
- *
- * $Id: jquery.delegate.js 7175 2009-05-15 16:59:09Z antranig@caret.cam.ac.uk $
- *
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- */
- // provides cross-browser focusin and focusout events
- // IE has native support, in other browsers, use event caputuring (neither bubbles)
- // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
- // handler is only called when $(event.target).is(delegate), in the scope of the jQuery-object for event.target
- // provides triggerEvent(type: String, target: Element) to trigger delegated events
- ;(function($) {
- $.each({
- focus: 'focusin',
- blur: 'focusout'
- }, function( original, fix ){
- $.event.special[fix] = {
- setup:function() {
- if ( $.browser.msie ) return false;
- this.addEventListener( original, $.event.special[fix].handler, true );
- },
- teardown:function() {
- if ( $.browser.msie ) return false;
- this.removeEventListener( original,
- $.event.special[fix].handler, true );
- },
- handler: function(e) {
- arguments[0] = $.event.fix(e);
- arguments[0].type = fix;
- return $.event.handle.apply(this, arguments);
- }
- };
- });
- $.extend($.fn, {
- delegate: function(type, delegate, handler) {
- return this.bind(type, function(event) {
- var target = $(event.target);
- if (target.is(delegate)) {
- return handler.apply(target, arguments);
- }
- });
- },
- triggerEvent: function(type, target) {
- return this.triggerHandler(type, [jQuery.event.fix({ type: type, target: target })]);
- }
- })
- })(jQuery);
- /*
- Copyright 2007-2010 University of Cambridge
- Copyright 2007-2009 University of Toronto
- Copyright 2007-2009 University of California, Berkeley
- Licensed under the Educational Community License (ECL), Version 2.0 or the New
- BSD license. You may not use this file except in compliance with one these
- Licenses.
- You may obtain a copy of the ECL 2.0 License and BSD License at
- https://source.fluidproject.org/svn/LICENSE.txt
- */
- // Declare dependencies.
- /*global jQuery, YAHOO, opera*/
- var fluid_1_2 = fluid_1_2 || {};
- var fluid = fluid || fluid_1_2;
- (function ($, fluid) {
-
- fluid.version = "Infusion 1.2";
-
- fluid.environment = {
- fluid: fluid
- };
- var globalObject = window || {};
-
- /**
- * Causes an error message to be logged to the console and a real runtime error to be thrown.
- *
- * @param {String|Error} message the error message to log
- */
- fluid.fail = function (message) {
- fluid.setLogging(true);
- fluid.log(message.message? message.message : message);
- throw new Error(message);
- //message.fail(); // Intentionally cause a browser error by invoking a nonexistent function.
- };
-
- /**
- * Wraps an object in a jQuery if it isn't already one. This function is useful since
- * it ensures to wrap a null or otherwise falsy argument to itself, rather than the
- * often unhelpful jQuery default of returning the overall document node.
- *
- * @param {Object} obj the object to wrap in a jQuery
- */
- fluid.wrap = function (obj) {
- return ((!obj || obj.jquery) ? obj : $(obj));
- };
-
- /**
- * If obj is a jQuery, this function will return the first DOM element within it.
- *
- * @param {jQuery} obj the jQuery instance to unwrap into a pure DOM element
- */
- fluid.unwrap = function (obj) {
- return obj && obj.jquery && obj.length === 1 ? obj[0] : obj; // Unwrap the element if it's a jQuery.
- };
-
- /**
- * Searches through the supplied object for the first value which matches the one supplied.
- * @param obj {Object} the Object to be searched through
- * @param value {Object} the value to be found. This will be compared against the object's
- * member using === equality.
- * @return {String} The first key whose value matches the one supplied, or <code>null</code> if no
- * such key is found.
- */
- fluid.keyForValue = function (obj, value) {
- for (var key in obj) {
- if (obj[key] === value) {
- return key;
- }
- }
- return null;
- };
-
- /**
- * This method is now deprecated and will be removed in a future release of Infusion.
- * See fluid.keyForValue instead.
- */
- fluid.findKeyInObject = fluid.keyForValue;
-
- /**
- * Clears an object or array of its contents. For objects, each property is deleted.
- *
- * @param {Object|Array} target the target to be cleared
- */
- fluid.clear = function (target) {
- if (target instanceof Array) {
- target.length = 0;
- }
- else {
- for (var i in target) {
- delete target[i];
- }
- }
- };
-
- /** A basic utility that returns its argument unchanged */
-
- fluid.identity = function(arg) {
- return arg;
- }
-
- // Framework and instantiation functions.
-
- /**
- * Fetches a single container element and returns it as a jQuery.
- *
- * @param {String||jQuery||element} an id string, a single-element jQuery, or a DOM element specifying a unique container
- * @return a single-element jQuery of container
- */
- fluid.container = function (containerSpec) {
- var container = containerSpec;
- if (typeof containerSpec === "string" ||
- containerSpec.nodeType && (containerSpec.nodeType === 1 || containerSpec.nodeType === 9)) {
- container = $(containerSpec);
- }
-
- // Throw an exception if we've got more or less than one element.
- if (!container || !container.jquery || container.length !== 1) {
- if (typeof(containerSpec) !== "string") {
- containerSpec = container.selector;
- }
- fluid.fail({
- name: "NotOne",
- message: "A single container element was not found for selector " + containerSpec
- });
- }
-
- return container;
- };
-
- // stubs for two functions in FluidDebugging.js
- fluid.dumpEl = fluid.identity;
- fluid.renderTimestamp = fluid.identity;
-
- /**
- * Retreives and stores a component's default settings centrally.
- * @param {boolean} (options) if true, manipulate a global option (for the head
- * component) rather than instance options.
- * @param {String} componentName the name of the component
- * @param {Object} (optional) an container of key/value pairs to set
- *
- */
- var defaultsStore = {};
- var globalDefaultsStore = {};
- fluid.defaults = function () {
- var offset = 0;
- var store = defaultsStore;
- if (typeof arguments[0] === "boolean") {
- store = globalDefaultsStore;
- offset = 1;
- }
- var componentName = arguments[offset];
- var defaultsObject = arguments[offset + 1];
- if (defaultsObject !== undefined) {
- store[componentName] = defaultsObject;
- return defaultsObject;
- }
-
- return store[componentName];
- };
-
- /**
- * Creates a new DOM Binder instance, used to locate elements in the DOM by name.
- *
- * @param {Object} container the root element in which to locate named elements
- * @param {Object} selectors a collection of named jQuery selectors
- */
- fluid.createDomBinder = function (container, selectors) {
- var cache = {}, that = {};
-
- function cacheKey(name, thisContainer) {
- return fluid.allocateSimpleId(thisContainer) + "-" + name;
- }
- function record(name, thisContainer, result) {
- cache[cacheKey(name, thisContainer)] = result;
- }
- that.locate = function (name, localContainer) {
- var selector, thisContainer, togo;
-
- selector = selectors[name];
- thisContainer = localContainer? localContainer: container;
- if (!thisContainer) {
- fluid.fail("DOM binder invoked for selector " + name + " without container");
- }
- if (!selector) {
- return thisContainer;
- }
- if (typeof(selector) === "function") {
- togo = $(selector.call(null, fluid.unwrap(thisContainer)));
- } else {
- togo = $(selector, thisContainer);
- }
- if (togo.get(0) === document) {
- togo = [];
- //fluid.fail("Selector " + name + " with value " + selectors[name] +
- // " did not find any elements with container " + fluid.dumpEl(container));
- }
- if (!togo.selector) {
- togo.selector = selector;
- togo.context = thisContainer;
- }
- togo.selectorName = name;
- record(name, thisContainer, togo);
- return togo;
- };
- that.fastLocate = function (name, localContainer) {
- var thisContainer = localContainer? localContainer: container;
- var key = cacheKey(name, thisContainer);
- var togo = cache[key];
- return togo? togo : that.locate(name, localContainer);
- };
- that.clear = function () {
- cache = {};
- };
- that.refresh = function (names, localContainer) {
- var thisContainer = localContainer? localContainer: container;
- if (typeof names === "string") {
- names = [names];
- }
- if (thisContainer.length === undefined) {
- thisContainer = [thisContainer];
- }
- for (var i = 0; i < names.length; ++ i) {
- for (var j = 0; j < thisContainer.length; ++ j) {
- that.locate(names[i], thisContainer[j]);
- }
- }
- };
-
- return that;
- };
-
- /** Determines whether the supplied object can be treated as an array, by
- * iterating an index towards its length. The test functions by detecting
- * a property named "length" which is of type "number", but excluding objects
- * which are themselves of type "string".
- */
- fluid.isArrayable = function(totest) {
- return typeof(totest) !== "string" && typeof(totest.length) === "number";
- }
-
- /**
- * Attaches the user's listeners to a set of events.
- *
- * @param {Object} events a collection of named event firers
- * @param {Object} listeners optional listeners to add
- */
- fluid.mergeListeners = function (events, listeners) {
- if (listeners) {
- for (var key in listeners) {
- var value = listeners[key];
- var keydot = key.indexOf(".");
- var namespace;
- if (keydot !== -1) {
- namespace = key.substring(keydot + 1);
- key = key.substring(0, keydot);
- }
- if (!events[key]) {
- events[key] = fluid.event.getEventFirer();
- }
- var firer = events[key];
- if (typeof(value) === "function") {
- firer.addListener(value, namespace);
- }
- else if (value && fluid.isArrayable(value)) {
- for (var i = 0; i < value.length; ++ i) {
- firer.addListener(value[i], namespace);
- }
- }
- }
- }
- };
-
- /**
- * Sets up a component's declared events.
- * Events are specified in the options object by name. There are three different types of events that can be
- * specified:
- * 1. an ordinary multicast event, specified by "null.
- * 2. a unicast event, which allows only one listener to be registered
- * 3. a preventable event
- *
- * @param {Object} that the component
- * @param {Object} options the component's options structure, containing the declared event names and types
- */
- fluid.instantiateFirers = function (that, options) {
- that.events = {};
- if (options.events) {
- for (var event in options.events) {
- var eventType = options.events[event];
- that.events[event] = fluid.event.getEventFirer(eventType === "unicast", eventType === "preventable");
- }
- }
- fluid.mergeListeners(that.events, options.listeners);
- };
-
- /**
- * Merges the component's declared defaults, as obtained from fluid.defaults(),
- * with the user's specified overrides.
- *
- * @param {Object} that the instance to attach the options to
- * @param {String} componentName the unique "name" of the component, which will be used
- * to fetch the default options from store. By recommendation, this should be the global
- * name of the component's creator function.
- * @param {Object} userOptions the user-specified configuration options for this component
- */
- fluid.mergeComponentOptions = function (that, componentName, userOptions) {
- var defaults = fluid.defaults(componentName);
- that.options = fluid.merge(defaults? defaults.mergePolicy: null, {}, defaults, userOptions);
- };
-
-
- /** Expect that an output from the DOM binder has resulted in a non-empty set of
- * results. If none are found, this function will fail with a diagnostic message,
- * with the supplied message prepended.
- */
- fluid.expectFilledSelector = function (result, message) {
- if (result && result.length === 0 && result.jquery) {
- fluid.fail(message + ": selector \"" + result.selector + "\" with name " + result.selectorName +
- " returned no results in context " + fluid.dumpEl(result.context));
- }
- };
-
- /**
- * The central initialiation method called as the first act of every Fluid
- * component. This function automatically merges user options with defaults,
- * attaches a DOM Binder to the instance, and configures events.
- *
- * @param {String} componentName The unique "name" of the component, which will be used
- * to fetch the default options from store. By recommendation, this should be the global
- * name of the component's creator function.
- * @param {jQueryable} container A specifier for the single root "container node" in the
- * DOM which will house all the markup for this component.
- * @param {Object} userOptions The configuration options for this component.
- */
- fluid.initView = function (componentName, container, userOptions) {
- var that = {};
- fluid.expectFilledSelector(container, "Error instantiating component with name \"" + componentName);
- fluid.mergeComponentOptions(that, componentName, userOptions);
-
- if (container) {
- that.container = fluid.container(container);
- fluid.initDomBinder(that);
- }
- fluid.instantiateFirers(that, that.options);
- return that;
- };
-
- /** A special "marker object" which is recognised as one of the arguments to
- * fluid.initSubcomponents. This object is recognised by reference equality -
- * where it is found, it is replaced in the actual argument position supplied
- * to the specific subcomponent instance, with the particular options block
- * for that instance attached to the overall "that" object.
- */
- fluid.COMPONENT_OPTIONS = {};
-
- /** Another special "marker object" representing that a distinguished
- * (probably context-dependent) value should be substituted.
- */
- fluid.VALUE = {};
-
- /** Construct a dummy or "placeholder" subcomponent, that optionally provides empty
- * implementations for a set of methods.
- */
- fluid.emptySubcomponent = function (options) {
- var that = {};
- options = $.makeArray(options);
- for (var i = 0; i < options.length; ++ i) {
- that[options[i]] = function () {};
- }
- return that;
- };
-
- /**
- * Creates a new "little component": a that-ist object with options merged into it by the framework.
- * This method is a convenience for creating small objects that have options but don't require full
- * View-like features such as the DOM Binder or events
- *
- * @param {Object} name the name of the little component to create
- * @param {Object} options user-supplied options to merge with the defaults
- */
- fluid.initLittleComponent = function(name, options) {
- var that = {};
- fluid.mergeComponentOptions(that, name, options);
- return that;
- };
-
- fluid.initSubcomponent = function (that, className, args) {
- return fluid.initSubcomponents(that, className, args)[0];
- };
-
- /** Initialise all the "subcomponents" which are configured to be attached to
- * the supplied top-level component, which share a particular "class name".
- * @param {Component} that The top-level component for which sub-components are
- * to be instantiated. It contains specifications for these subcomponents in its
- * <code>options</code> structure.
- * @param {String} className The "class name" or "category" for the subcomponents to
- * be instantiated. A class name specifies an overall "function" for a class of
- * subcomponents and represents a category which accept the same signature of
- * instantiation arguments.
- * @param {Array of Object} args The instantiation arguments to be passed to each
- * constructed subcomponent. These will typically be members derived from the
- * top-level <code>that</code> or perhaps globally discovered from elsewhere. One
- * of these arguments may be <code>fluid.COMPONENT_OPTIONS</code> in which case this
- * placeholder argument will be replaced by instance-specific options configured
- * into the member of the top-level <code>options</code> structure named for the
- * <code>className</code>
- * @return {Array of Object} The instantiated subcomponents, one for each member
- * of <code>that.options[className]</code>.
- */
-
- fluid.initSubcomponents = function (that, className, args) {
- var entry = that.options[className];
- if (!entry) {
- return;
- }
- var entries = $.makeArray(entry);
- var optindex = -1;
- var togo = [];
- args = $.makeArray(args);
- for (var i = 0; i < args.length; ++ i) {
- if (args[i] === fluid.COMPONENT_OPTIONS) {
- optindex = i;
- }
- }
- for (i = 0; i < entries.length; ++ i) {
- entry = entries[i];
- if (optindex !== -1 && entry.options) {
- args[optindex] = entry.options;
- }
- if (typeof(entry) !== "function") {
- var entryType = typeof(entry) === "string"? entry : entry.type;
- var globDef = fluid.defaults(true, entryType);
- fluid.merge("reverse", that.options, globDef);
- togo[i] = entryType === "fluid.emptySubcomponent"?
- fluid.emptySubcomponent(entry.options) :
- fluid.invokeGlobalFunction(entryType, args, {fluid: fluid});
- }
- else {
- togo[i] = entry.apply(null, args);
- }
- var returnedOptions = togo[i]? togo[i].returnedOptions : null;
- if (returnedOptions) {
- fluid.merge(that.options.mergePolicy, that.options, returnedOptions);
- if (returnedOptions.listeners) {
- fluid.mergeListeners(that.events, returnedOptions.listeners);
- }
- }
- }
- return togo;
- };
-
- /**
- * Creates a new DOM Binder instance for the specified component and mixes it in.
- *
- * @param {Object} that the component instance to attach the new DOM Binder to
- */
- fluid.initDomBinder = function (that) {
- that.dom = fluid.createDomBinder(that.container, that.options.selectors);
- that.locate = that.dom.locate;
- };
-
-
- /** Returns true if the argument is a primitive type **/
- fluid.isPrimitive = function (value) {
- var valueType = typeof(value);
- return !value || valueType === "string" || valueType === "boolean" || valueType === "number" || valueType === "function";
- };
-
- function mergeImpl(policy, basePath, target, source) {
- var thisPolicy = policy && typeof(policy) !== "string"? policy[basePath] : policy;
- if (typeof(thisPolicy) === "function") {
- thisPolicy.apply(null, target, source);
- return target;
- }
- if (thisPolicy === "replace") {
- fluid.clear(target);
- }
-
- for (var name in source) {
- var path = (basePath? basePath + ".": "") + name;
- var thisTarget = target[name];
- var thisSource = source[name];
- var primitiveTarget = fluid.isPrimitive(thisTarget);
-
- if (thisSource !== undefined) {
- if (thisSource !== null && typeof thisSource === 'object' &&
- !thisSource.nodeType && !thisSource.jquery && thisSource !== fluid.VALUE) {
- if (primitiveTarget) {
- target[name] = thisTarget = thisSource instanceof Array? [] : {};
- }
- mergeImpl(policy, path, thisTarget, thisSource);
- }
- else {
- if (thisTarget === null || thisTarget === undefined || thisPolicy !== "reverse") {
- target[name] = thisSource;
- }
- }
- }
- }
- return target;
- }
-
- /** Merge a collection of options structures onto a target, following an optional policy.
- * This function is typically called automatically, as a result of an invocation of
- * <code>fluid.iniView</code>. The behaviour of this function is explained more fully on
- * the page http://wiki.fluidproject.org/display/fluid/Options+Merging+for+Fluid+Components .
- * @param policy {Object/String} A "policy object" specifiying the type of merge to be performed.
- * If policy is of type {String} it should take on the value "reverse" or "replace" representing
- * a static policy. If it is an
- * Object, it should contain a mapping of EL paths onto these String values, representing a
- * fine-grained policy. If it is an Object, the values may also themselves be EL paths
- * representing that a default value is to be taken from that path.
- * @param target {Object} The options structure which is to be modified by receiving the merge results.
- * @param options1, options2, .... {Object} an arbitrary list of options structure which are to
- * be merged "on top of" the <code>target</code>. These will not be modified.
- */
-
- fluid.merge = function (policy, target) {
- var path = "";
-
- for (var i = 2; i < arguments.length; ++i) {
- var source = arguments[i];
- if (source !== null && source !== undefined) {
- mergeImpl(policy, path, target, source);
- }
- }
- if (policy && typeof(policy) !== "string") {
- for (var key in policy) {
- var elrh = policy[key];
- if (typeof(elrh) === 'string' && elrh !== "replace") {
- var oldValue = fluid.model.getBeanValue(target, key);
- if (oldValue === null || oldValue === undefined) {
- var value = fluid.model.getBeanValue(target, elrh);
- fluid.model.setBeanValue(target, key, value);
- }
- }
- }
- }
- return target;
- };
-
- /** Return an empty container as the same type as the argument (either an
- * array or hash */
- fluid.freshContainer = function(tocopy) {
- return fluid.isArrayable(tocopy)? [] : {};
- };
-
- /** Performs a deep copy (clone) of its argument **/
-
- fluid.copy = function (tocopy) {
- if (fluid.isPrimitive(tocopy)) {
- return tocopy;
- }
- return $.extend(true, fluid.freshContainer(tocopy), tocopy);
- };
-
- fluid.getGlobalValue = function(path, env) {
- env = env || fluid.environment;
- return fluid.model.getBeanValue(globalObject, path, env);
- };
-
- /**
- * Allows for the calling of a function from an EL expression "functionPath", with the arguments "args", scoped to an framework version "environment".
- * @param {Object} functionPath - An EL expression
- * @param {Object} args - An array of arguments to be applied to the function, specified in functionPath
- * @param {Object} environment - (optional) The object to scope the functionPath to (typically the framework root for version control)
- */
- fluid.invokeGlobalFunction = function (functionPath, args, environment) {
- var func = fluid.getGlobalValue(functionPath, environment);
- if (!func) {
- fluid.fail("Error invoking global function: " + functionPath + " could not be located");
- } else {
- return func.apply(null, args);
- }
- };
-
- /** Registers a new global function at a given path (currently assumes that
- * it lies within the fluid namespace)
- */
-
- fluid.registerGlobalFunction = function (functionPath, func, env) {
- env = env || fluid.environment;
- fluid.model.setBeanValue(globalObject, functionPath, func, env);
- };
-
- fluid.registerGlobal = fluid.registerGlobalFunction;
-
- /** Ensures that an entry in the global namespace exists **/
- fluid.registerNamespace = function (naimspace, env) {
- env = env || fluid.environment;
- var existing = fluid.getGlobalValue(naimspace, env);
- if (!existing) {
- existing = {};
- fluid.registerGlobal(naimspace, existing, env);
- }
- return existing;
- };
-
- // The Model Events system.
-
- fluid.event = {};
-
- var fluid_guid = 1;
- /** Construct an "event firer" object which can be used to register and deregister
- * listeners, to which "events" can be fired. These events consist of an arbitrary
- * function signature. General documentation on the Fluid events system is at
- * http://wiki.fluidproject.org/display/fluid/The+Fluid+Event+System .
- * @param {Boolean} unicast If <code>true</code>, this is a "unicast" event which may only accept
- * a single listener.
- * @param {Boolean} preventable If <code>true</code> the return value of each handler will
- * be checked for <code>false</code> in which case further listeners will be shortcircuited, and this
- * will be the return value of fire()
- */
-
- fluid.event.getEventFirer = function (unicast, preventable) {
- var log = fluid.log;
- var listeners = {};
- return {
- addListener: function (listener, namespace, predicate) {
- if (!listener) {
- return;
- }
- if (unicast) {
- namespace = "unicast";
- }
- if (!namespace) {
- if (!listener.$$guid) {
- listener.$$guid = fluid_guid++;
- }
- namespace = listener.$$guid;
- }
- listeners[namespace] = {listener: listener, predicate: predicate};
- },
- removeListener: function (listener) {
- if (typeof(listener) === 'string') {
- delete listeners[listener];
- }
- else if (typeof(listener) === 'object' && listener.$$guid) {
- delete listeners[listener.$$guid];
- }
- },
-
- fire: function () {
- for (var i in listeners) {
- var lisrec = listeners[i];
- var listener = lisrec.listener;
- if (lisrec.predicate && !lisrec.predicate(listener, arguments)) {
- continue;
- }
- try {
- var ret = listener.apply(null, arguments);
- if (preventable && ret === false) {
- return false;
- }
- }
- catch (e) {
- log("FireEvent received exception " + e.message + " e " + e + " firing to listener " + i);
- throw (e);
- }
- }
- }
- };
- };
-
-
- // Model functions
-
- fluid.model = {};
-
- /** Copy a source "model" onto a target **/
- fluid.model.copyModel = function (target, source) {
- fluid.clear(target);
- $.extend(true, target, source);
- };
-
- /** Parse an EL expression separated by periods (.) into its component segments.
- * @param {String} EL The EL expression to be split
- * @return {Array of String} the component path expressions.
- * TODO: This needs to be upgraded to handle (the same) escaping rules (as RSF), so that
- * path segments containing periods and backslashes etc. can be processed.
- */
- fluid.model.parseEL = function (EL) {
- return String(EL).split('.');
- };
-
- fluid.model.composePath = function (prefix, suffix) {
- return prefix === ""? suffix : prefix + "." + suffix;
- };
- fluid.model.getPenultimate = function (root, EL, environment, create) {
- var segs = fluid.model.parseEL(EL);
- for (var i = 0; i < segs.length - 1; ++i) {
- if (!root) {
- return root;
- }
- var segment = segs[i];
- if (environment && environment[segment]) {
- root = environment[segment];
- environment = null;
- }
- else {
- if (root[segment] === undefined && create) {
- root[segment] = {};
- }
- root = root[segment];
- }
- }
- return {root: root, last: segs[segs.length - 1]};
- };
-
- fluid.model.setBeanValue = function (root, EL, newValue, environment) {
- var pen = fluid.model.getPenultimate(root, EL, environment, true);
- pen.root[pen.last] = newValue;
- };
-
- /** Evaluates an EL expression by fetching a dot-separated list of members
- * recursively from a provided root.
- * @param root The root data structure in which the EL expression is to be evaluated
- * @param {string} EL The EL expression to be evaluated
- * @param environment An optional "environment" which, if it contains any members
- * at top level, will take priority over the root data structure.
- * @return The fetched data value.
- */
-
- fluid.model.getBeanValue = function (root, EL, environment) {
- if (EL === "" || EL === null || EL === undefined) {
- return root;
- }
- var pen = fluid.model.getPenultimate(root, EL, environment);
- return pen.root? pen.root[pen.last] : pen.root;
- };
-
- // Logging
- var logging;
- /** method to allow user to enable logging (off by default) */
- fluid.setLogging = function (enabled) {
- if (typeof enabled === "boolean") {
- logging = enabled;
- } else {
- logging = false;
- }
- };
- /** Log a message to a suitable environmental console. If the standard "console"
- * stream is available, the message will be sent there - otherwise either the
- * YAHOO logger or the Opera "postError" stream will be used. Logging must first
- * be enabled with a call fo the fluid.setLogging(true) function.
- */
- fluid.log = function (str) {
- if (logging) {
- str = fluid.renderTimestamp(new Date()) + ": " + str;
- if (typeof(console) !== "undefined") {
- if (console.debug) {
- console.debug(str);
- } else {
- console.log(str);
- }
- }
- else if (typeof(YAHOO) !== "undefined") {
- YAHOO.log(str);
- }
- else if (typeof(opera) !== "undefined") {
- opera.postError(str);
- }
- }
- };
- // DOM Utilities.
-
- /**
- * Finds the nearest ancestor of the element that passes the test
- * @param {Element} element DOM element
- * @param {Function} test A function which takes an element as a parameter and return true or false for some test
- */
- fluid.findAncestor = function (element, test) {
- element = fluid.unwrap(element);
- while (element) {
- if (test(element)) {
- return element;
- }
- element = element.parentNode;
- }
- };
-
- /**
- * Returns a jQuery object given the id of a DOM node. In the case the element
- * is not found, will return an empty list.
- */
- fluid.jById = function (id, dokkument) {
- dokkument = dokkument && dokkument.nodeType === 9? dokkument : document;
- var element = fluid.byId(id, dokkument);
- var togo = element? $(element) : [];
- togo.selector = "#" + id;
- togo.context = dokkument;
- return togo;
- };
-
- /**
- * Returns an DOM element quickly, given an id
- *
- * @param {Object} id the id of the DOM node to find
- * @param {Document} dokkument the document in which it is to be found (if left empty, use the current document)
- * @return The DOM element with this id, or null, if none exists in the document.
- */
- fluid.byId = function (id, dokkument) {
- dokkument = dokkument && dokkument.nodeType === 9? dokkument : document;
- var el = dokkument.getElementById(id);
- if (el) {
- if (el.getAttribute("id") !== id) {
- fluid.fail("Problem in document structure - picked up element " +
- fluid.dumpEl(el) +
- " for id " +
- id +
- " without this id - most likely the element has a name which conflicts with this id");
- }
- return el;
- }
- else {
- return null;
- }
- };
-
- /**
- * Returns the id attribute from a jQuery or pure DOM element.
- *
- * @param {jQuery||Element} element the element to return the id attribute for
- */
- fluid.getId = function (element) {
- return fluid.unwrap(element).getAttribute("id");
- };
-
- /**
- * Allocate an id to the supplied element if it has none already, by a simple
- * scheme resulting in ids "fluid-id-nnnn" where nnnn is an increasing integer.
- */
-
- fluid.allocateSimpleId = function (element) {
- element = fluid.unwrap(element);
- if (!element.id) {
- element.id = "fluid-id-" + (fluid_guid++);
- }
- return element.id;
- };
-
-
- // Functional programming utilities.
-
- function transformInternal(source, togo, key, args) {
- var transit = source[key];
- for (var j = 0; j < args.length - 1; ++ j) {
- transit = args[j + 1](transit, key);
- }
- togo[key] = transit;
- }
-
- /** Return a list or hash of objects, transformed by one or more functions. Similar to
- * jQuery.map, only will accept an arbitrary list of transformation functions and also
- * works on non-arrays.
- * @param list {Array or Object} The initial container of objects to be transformed.
- * @param fn1, fn2, etc. {Function} An arbitrary number of optional further arguments,
- * all of type Function, accepting the signature (object, index), where object is the
- * list member to be transformed, and index is its list index. Each function will be
- * applied in turn to each list member, which will be replaced by the return value
- * from the function.
- * @return The finally transformed list, where each member has been replaced by the
- * original member acted on by the function or functions.
- */
- fluid.transform = function (source) {
- var togo = fluid.freshContainer(source);
- if (fluid.isArrayable(source)) {
- for (var i = 0; i < source.length; ++ i) {
- transformInternal(source, togo, i, arguments);
- }
- }
- else {
- for (var key in source) {
- transformInternal(source, togo, key, arguments);
- }
- }
- return togo;
- };
-
- /** Scan through a list of objects, terminating on and returning the first member which
- * matches a predicate function.
- * @param list {Array} The list of objects to be searched.
- * @param fn {Function} A predicate function, acting on a list member. A predicate which
- * returns any value which is not <code>null</code> or <code>undefined</code> will terminate
- * the search. The function accepts (object, index).
- * @param deflt {Object} A value to be returned in the case no predicate function matches
- * a list member. The default will be the natural value of <code>undefined</code>
- * @return The first return value from the predicate function which is not <code>null</code>
- * or <code>undefined</code>
- */
- fluid.find = function (list, fn, deflt) {
- for (var i = 0; i < list.length; ++ i) {
- var transit = fn(list[i], i);
- if (transit !== null && transit !== undefined) {
- return transit;
- }
- }
- return deflt;
- };
-
- /** Scan through a list of objects, "accumulating" a value over them
- * (may be a straightforward "sum" or some other chained computation).
- * @param list {Array} The list of objects to be accumulated over.
- * @param fn {Function} An "accumulation function" accepting the signature (object, total, index) where
- * object is the list member, total is the "running total" object (which is the return value from the previous function),
- * and index is the index number.
- * @param arg {Object} The initial value for the "running total" object.
- * @return {Object} the final running total object as returned from the final invocation of the function on the last list member.
- */
- fluid.accumulate = function (list, fn, arg) {
- for (var i = 0; i < list.length; ++ i) {
- arg = fn(list[i], arg, i);
- }
- return arg;
- };
-
- /** Can through a list of objects, removing those which match a predicate. Similar to
- * jQuery.grep, only acts on the list in-place by removal, rather than by creating
- * a new list by inclusion.
- * @param list {Array} The list of objects to be scanned over.
- * @param fn {Function} A predicate function determining whether an element should be
- * removed. This accepts the standard signature (object, index) and returns a "truthy"
- * result in order to determine that the supplied object should be removed from the list.
- * @return The list, transformed by the operation of removing the matched elements. The
- * supplied list is modified by this operation.
- */
- fluid.remove_if = function (list, fn) {
- for (var i = 0; i < list.length; ++ i) {
- if (fn(list[i], i)) {
- list.splice(i, 1);
- --i;
- }
- }
- return list;
- };
-
- // Other useful helpers.
-
- /**
- * Simple string template system.
- * Takes a template string containing tokens in the form of "%value".
- * Returns a new string with the tokens replaced by the specified values.
- * Keys and values can be of any data type that can be coerced into a string. Arrays will work here as well.
- *
- * @param {String} template a string (can be HTML) that contains tokens embedded into it
- * @param {object} values a collection of token keys and values
- */
- fluid.stringTemplate = function (template, values) {
- var newString = template;
- for (var key in values) {
- var searchStr = "%" + key;
- newString = newString.replace(searchStr, values[key]);
- }
- return newString;
- };
-
- })(jQuery, fluid_1_2);
- /*
- Copyright 2008-2010 University of Cambridge
- Copyright 2008-2009 University of Toronto
- Licensed under the Educational Community License (ECL), Version 2.0 or the New
- BSD license. You may not use this file except in compliance with one these
- Licenses.
- You may obtain a copy of the ECL 2.0 License and BSD License at
- https://source.fluidproject.org/svn/LICENSE.txt
- */
- // Declare dependencies.
- /*global jQuery */
- var fluid_1_2 = fluid_1_2 || {};
- (function ($, fluid) {
-
- fluid.dom = fluid.dom || {};
-
- // Node walker function for iterateDom.
- var getNextNode = function (iterator) {
- if (iterator.node.firstChild) {
- iterator.node = iterator.node.firstChild;
- iterator.depth += 1;
- return iterator;
- }
- while (iterator.node) {
- if (iterator.node.nextSibling) {
- iterator.node = iterator.node.nextSibling;
- return iterator;
- }
- iterator.node = iterator.node.parentNode;
- iterator.depth -= 1;
- }
- return iterator;
- };
-
- /**
- * Walks the DOM, applying the specified acceptor function to each element.
- * There is a special case for the acceptor, allowing for quick deletion of elements and their children.
- * Return "delete" from your acceptor function if you want to delete the element in question.
- * Return "stop" to terminate iteration.
- *
- * @param {Element} node the node to start walking from
- * @param {Function} acceptor the function to invoke with each DOM element
- * @param {Boolean} allnodes Use <code>true</code> to call acceptor on all nodes,
- * rather than just element nodes (type 1)
- */
- fluid.dom.iterateDom = function (node, acceptor, allNodes) {
- var currentNode = {node: node, depth: 0};
- var prevNode = node;
- var condition;
- while (currentNode.node !== null && currentNode.depth >= 0 && currentNode.depth < fluid.dom.iterateDom.DOM_BAIL_DEPTH) {
- condition = null;
- if (currentNode.node.nodeType === 1 || allNodes) {
- condition = acceptor(currentNode.node, currentNode.depth);
- }
- if (condition) {
- if (condition === "delete") {
- currentNode.node.parentNode.removeChild(currentNode.node);
- currentNode.node = prevNode;
- }
- else if (condition === "stop") {
- return currentNode.node;
- }
- }
- prevNode = currentNode.node;
- currentNode = getNextNode(currentNode);
- }
- };
-
- // Work around IE circular DOM issue. This is the default max DOM depth on IE.
- // http://msdn2.microsoft.com/en-us/library/ms761392(VS.85).aspx
- fluid.dom.iterateDom.DOM_BAIL_DEPTH = 256;
-
- /**
- * Checks if the sepcified container is actually the parent of containee.
- *
- * @param {Element} container the potential parent
- * @param {Element} containee the child in question
- */
- fluid.dom.isContainer = function (container, containee) {
- for (; containee; containee = containee.parentNode) {
- if (container === containee) {
- return true;
- }
- }
- return false;
- };
-
- /** Return the element text from the supplied DOM node as a single String */
- fluid.dom.getElementText = function(element) {
- var nodes = element.childNodes;
- var text = "";
- for (var i = 0; i < nodes.length; ++ i) {
- var child = nodes[i];
- if (child.nodeType == 3) {
- text = text + child.nodeValue;
- }
- }
- return text;
- };
-
- })(jQuery, fluid_1_2);
- /*
- Copyright 2008-2010 University of Cambridge
- Copyright 2008-2009 University of Toronto
- Licensed under the Educational Community License (ECL), Version 2.0 or the New
- BSD license. You may not use this file except in compliance with one these
- Licenses.
- You may obtain a copy of the ECL 2.0 License and BSD License at
- https://source.fluidproject.org/svn/LICENSE.txt
- */
- /*global jQuery*/
- /*global fluid_1_2*/
- fluid_1_2 = fluid_1_2 || {};
- (function ($, fluid) {
-
- var unUnicode = /(\\u[\dabcdef]{4}|\\x[\dabcdef]{2})/g;
-
- fluid.unescapeProperties = function (string) {
- string = string.replace(unUnicode, function(match) {
- var code = match.substring(2);
- var parsed = parseInt(code, 16);
- return String.fromCharCode(parsed);
- }
- );
- var pos = 0;
- while (true) {
- var backpos = string.indexOf("\\", pos);
- if (backpos === -1) {
- break;
- }
- if (backpos === string.length - 1) {
- return [string.substring(0, string.length - 1), true];
- }
- var replace = string.charAt(backpos + 1);
- if (replace === "n") replace = "\n";
- if (replace === "r") replace = "\r";
- if (replace === "t") replace = "\t";
- string = string.substring(0, backpos) + replace + string.substring(backpos + 2);
- pos = backpos + 1;
- }
- return [string, false];
- };
-
- var breakPos = /[^\\][\s:=]/;
-
- fluid.parseJavaProperties = function(text) {
- // File format described at http://java.sun.com/javase/6/docs/api/java/util/Properties.html#load(java.io.Reader)
- var togo = {};
- text = text.replace(/\r\n/g, "\n");
- text = text.replace(/\r/g, "\n");
- lines = text.split("\n");
- var contin, key, valueComp, valueRaw, valueEsc;
- for (var i = 0; i < lines.length; ++ i) {
- var line = $.trim(lines[i]);
- if (!line || line.charAt(0) === "#" || line.charAt(0) === '!') {
- continue;
- }
- if (!contin) {
- valueComp = "";
- var breakpos = line.search(breakPos);
- if (breakpos === -1) {
- key = line;
- valueRaw = "";
- }
- else {
- key = $.trim(line.substring(0, breakpos + 1)); // +1 since first char is escape exclusion
- valueRaw = $.trim(line.substring(breakpos + 2));
- if (valueRaw.charAt(0) === ":" || valueRaw.charAt(0) === "=") {
- valueRaw = $.trim(valueRaw.substring(1));
- }
- }
-
- key = fluid.unescapeProperties(key)[0];
- valueEsc = fluid.unescapeProperties(valueRaw);
- }
- else {
- valueEsc = fluid.unescapeProperties(line);
- }
- contin = valueEsc[1];
- if (!valueEsc[1]) { // this line was not a continuation line - store the value
- togo[key] = valueComp + valueEsc[0];
- }
- else {
- valueComp += valueEsc[0];
- }
- }
- return togo;
- };
-
- /**
- * Expand a message string with respect to a set of arguments, following a basic
- * subset of the Java MessageFormat rules.
- * http://java.sun.com/j2se/1.4.2/docs/api/java/text/MessageFormat.html
- *
- * The message string is expected to contain replacement specifications such
- * as {0}, {1}, {2}, etc.
- * @param messageString {String} The message key to be expanded
- * @param args {String/Array of String} An array of arguments to be substituted into the message.
- * @return The expanded message string.
- */
- fluid.formatMessage = function (messageString, args) {
- if (!args) {
- return messageString;
- }
- if (typeof(args) === "string") {
- args = [args];
- }
- for (var i = 0; i < args.length; ++ i) {
- messageString = messageString.replace("{" + i + "}", args[i]);
- }
- return messageString;
- };
-
- })(jQuery, fluid_1_2);
- /*
- Copyright 2007-2010 University of Cambridge
- Copyright 2007-2009 University of Toronto
- Copyright 2007-2009 University of California, Berkeley
- Licensed under the Educational Community License (ECL), Version 2.0 or the New
- BSD license. You may not use this file except in compliance with one these
- Licenses.
- You may obtain a copy of the ECL 2.0 License and BSD License at
- https://source.fluidproject.org/svn/LICENSE.txt
- */
- // Declare dependencies.
- /*global jQuery, YAHOO, opera*/
- var fluid_1_2 = fluid_1_2 || {};
- var fluid = fluid || fluid_1_2;
- (function ($, fluid) {
-
- fluid.renderTimestamp = function (date) {
- var zeropad = function (num, width) {
- if (!width) width = 2;
- var numstr = (num == undefined? "" : num.toString());
- return "00000".substring(5 - width + numstr.length) + numstr;
- }
- return zeropad(date.getHours()) + ":" + zeropad(date.getMinutes()) + ":" + zeropad(date.getSeconds()) + "." + zeropad(date.getMilliseconds(), 3);
- };
-
-
- /**
- * Dumps a DOM element into a readily recognisable form for debugging - produces a
- * "semi-selector" summarising its tag name, class and id, whichever are set.
- *
- * @param {jQueryable} element The element to be dumped
- * @return A string representing the element.
- */
- fluid.dumpEl = function (element) {
- var togo;
-
- if (!element) {
- return "nu…
Large files files are truncated, but you can click here to view the full file