window.Ice = {};
if (!window.ice) {
    window.ice = new Object;
}
if (!window.ice.compat) {
    (function(namespace) {
        namespace.compat = true;
function apply(fun, arguments) {
    return fun.apply(fun, arguments);
}
function withArguments() {
    var args = arguments;
    return function(fun) {
        apply(fun, args);
    };
}
function let(definition) {
    return function() {
        return apply(definition, arguments);
    };
}
function curry() {
    var args = arguments;
    return function() {
        var curriedArguments = [];
        var fun = args[0];
        for (var i = 1; i < args.length; i++) curriedArguments.push(args[i]);
        for (var j = 0; j < arguments.length; j++) curriedArguments.push(arguments[j]);
        return apply(fun, curriedArguments);
    };
}
function $witch(tests, defaultRun) {
    return function(val) {
        var args = arguments;
        var conditions = [];
        var runs = [];
        tests(function(condition, run) {
            conditions.push(condition);
            runs.push(run);
        });
        var size = conditions.length;
        for (var i = 0; i < size; i++) {
            if (apply(conditions[i], args)) {
                return apply(runs[i], args);
            }
        }
        if (defaultRun) apply(defaultRun, args);
    };
}
function identity(arg) {
    return arg;
}
function negate(b) {
    return !b;
}
function greater(a, b) {
    return a > b;
}
function less(a, b) {
    return a < b;
}
function not(a) {
    return !a;
}
function multiply(a, b) {
    return a * b;
}
function plus(a, b) {
    return a + b;
}
function max(a, b) {
    return a > b ? a : b;
}
function increment(value, step) {
    return value + (step ? step : 1);
}
function decrement(value, step) {
    return value - (step ? step : 1);
}
function any() {
    return true;
}
function none() {
    return false;
}
function noop() {
}
function isArray(a) {
    return a && !!a.push;
}
function isString(s) {
    return typeof s == 'string';
}
function isNumber(s) {
    return typeof s == 'number';
}
function isBoolean(s) {
    return typeof s == 'boolean';
}
function isIndexed(s) {
    return typeof s.length == 'number';
}
function isObject(o) {
    return o.instanceTag == o;
}
var uid = (function() {
    var id = 0;
    return function() {
        return id++;
    };
})();
function operationNotSupported() {
    throw 'operation not supported';
}
function operator(defaultOperation) {
    return function() {
        var args = arguments;
        var instance = arguments[0];
        if (instance.instanceTag && instance.instanceTag == instance) {
            var method = instance(arguments.callee);
            if (method) {
                return method.apply(method, args);
            } else {
                operationNotSupported();
            }
        } else {
            return defaultOperation ? defaultOperation.apply(defaultOperation, args) : operationNotSupported();
        }
    };
}
var asString = operator(String);
var asNumber = operator(Number);
var hash = operator(function(o) {
    var s;
    if (isString(o)) {
        s = o;
    } else if (isNumber(o)) {
        return Math.abs(Math.round(o));
    } else {
        s = o.toString();
    }
    var h = 0;
    for (var i = 0, l = s.length; i < l; i++) {
        var c = parseInt(s[i], 36);
        if (!isNaN(c)) {
            h = c + (h << 6) + (h << 16) - h;
        }
    }
    return Math.abs(h);
});
var equal = operator(function(a, b) {
    return a == b;
});
function object(definition) {
    var operators = [];
    var methods = [];
    var unknown = null;
    var id = uid();
    operators.push(hash);
    methods.push(function(self) {
        return id;
    });
    operators.push(equal);
    methods.push(function(self, other) {
        return self == other;
    });
    operators.push(asString);
    methods.push(function(self) {
        return 'Object:' + id.toString(16);
    });
    definition(function(operator, method) {
        var size = operators.length;
        for (var i = 0; i < size; i++) {
            if (operators[i] == operator) {
                methods[i] = method;
                return;
            }
        }
        operators.push(operator);
        methods.push(method);
    }, function(method) {
        unknown = method;
    });
    function self(operator) {
        var size = operators.length;
        for (var i = 0; i < size; i++) {
            if (operators[i] == operator) {
                return methods[i];
            }
        }
        return unknown;
    }
    return self.instanceTag = self;
}
function objectWithAncestors() {
    var definition = arguments[0];
    var args = arguments;
    var o = object(definition);
    function self(operator) {
        var method = o(operator);
        if (method) {
            return method;
        } else {
            var size = args.length;
            for (var i = 1; i < size; i++) {
                var ancestor = args[i];
                var overriddenMethod = ancestor(operator);
                if (overriddenMethod) {
                    return overriddenMethod;
                }
            }
            return null;
        }
    }
    return self.instanceTag = self;
}
var indexOf = operator($witch(function(condition) {
    condition(isString, function(items, item) {
        return items.indexOf(item);
    });
    condition(isArray, function(items, item) {
        for (var i = 0, size = items.length; i < size; i++) {
            if (items[i] == item) {
                return i;
            }
        }
        return -1;
    });
    condition(any, operationNotSupported);
}));
var concatenate = operator(function(items, other) {
    return items.concat(other);
});
var append = operator($witch(function(condition) {
    condition(isArray, function(items, item) {
        items.push(item);
        return items;
    });
    condition(any, operationNotSupported);
}));
var insert = operator($witch(function(condition) {
    condition(isArray, function(items, item) {
        items.unshift(item);
        return items;
    });
    condition(any, operationNotSupported);
}));
var each = operator(function(items, iterator) {
    var size = items.length;
    for (var i = 0; i < size; i++) iterator(items[i], i);
});
var inject = operator(function(items, initialValue, injector) {
    var tally = initialValue;
    var size = items.length;
    for (var i = 0; i < size; i++) {
        tally = injector(tally, items[i]);
    }
    return tally;
});
var select = operator($witch(function(condition) {
    condition(isArray, function(items, selector) {
        return inject(items, [], function(tally, item) {
            return selector(item) ? append(tally, item) : tally;
        });
    });
    condition(isString, function(items, selector) {
        return inject(items, '', function(tally, item) {
            return selector(item) ? concatenate(tally, item) : tally;
        });
    });
    condition(isIndexed, function(items, selector) {
        return Stream(function(cellConstructor) {
            function selectingStream(start, end) {
                if (start > end) return null;
                var item = items[start];
                return selector(item) ?
                       function() {
                           return cellConstructor(item, selectingStream(start + 1, end));
                       } : selectingStream(start + 1, end);
            }
            return selectingStream(0, items.length - 1);
        });
    });
}));
var detect = operator(function(items, iterator, notDetectedThunk) {
    var size = items.length;
    for (var i = 0; i < size; i++) {
        var element = items[i];
        if (iterator(element, i)) {
            return element;
        }
    }
    return notDetectedThunk ? notDetectedThunk(items) : null;
});
var contains = operator($witch(function(condition) {
    condition(isString, function(items, item) {
        return items.indexOf(item) > -1;
    });
    condition(isArray, function(items, item) {
        var size = items.length;
        for (var i = 0; i < size; i++) {
            if (items[i] == item) {
                return true;
            }
        }
        return false;
    });
    condition(any, operationNotSupported);
}));
var size = operator(function(items) {
    return items.length;
});
var isEmpty = operator(function(items) {
    return items.length == 0;
});
var notEmpty = function(items) {
    return !isEmpty(items);
};
var collect = operator($witch(function(condition) {
    condition(isString, function(items, collector) {
        return inject(items, '', function(tally, item) {
            return concatenate(tally, collector(item));
        });
    });
    condition(isArray, function(items, collector) {
        return inject(items, [], function(tally, item) {
            return append(tally, collector(item));
        });
    });
    condition(isIndexed, function(items, collector) {
        return Stream(function(cellConstructor) {
            function collectingStream(start, end) {
                if (start > end) return null;
                return function() {
                    return cellConstructor(collector(items[start], start), collectingStream(start + 1, end));
                };
            }
            return collectingStream(0, items.length - 1);
        });
    });
}));
var sort = operator(function(items, sorter) {
    return copy(items).sort(function(a, b) {
        return sorter(a, b) ? -1 : 1;
    });
});
var reverse = operator(function(items) {
    return copy(items).reverse();
});
var copy = operator(function(items) {
    return inject(items, [], curry(append));
});
var join = operator(function(items, separator) {
    return items.join(separator);
});
var inspect = operator();
var reject = function(items, rejector) {
    return select(items, function(i) {
        return !rejector(i);
    });
};
var intersect = operator(function(items, other) {
    return select(items, curry(contains, other));
});
var complement = operator(function(items, other) {
    return reject(items, curry(contains, other));
});
var broadcast = function(items, args) {
    args = args || [];
    each(items, function(i) {
        apply(i, args);
    });
};
var broadcaster = function(items) {
    return function() {
        var args = arguments;
        each(items, function(i) {
            apply(i, args);
        });
    };
};
var asArray = function(items) {
    return inject(items, [], append);
};
var asSet = function(items) {
    return inject(items, [], function(set, item) {
        if (not(contains(set, item))) {
            append(set, item);
        }
        return set;
    });
};
var key = operator();
var value = operator();
function Cell(k, v) {
    return object(function(method) {
        method(key, function(self) {
            return k;
        });
        method(value, function(self) {
            return v;
        });
        method(asString, function(self) {
            return 'Cell[' + asString(k) + ': ' + asString(v) + ']';
        });
    });
}
function Stream(streamDefinition) {
    var stream = streamDefinition(Cell);
    return object(function(method) {
        method(each, function(self, iterator) {
            var cursor = stream;
            while (cursor != null) {
                var cell = cursor();
                iterator(key(cell));
                cursor = value(cell);
            }
        });
        method(inject, function(self, initialValue, injector) {
            var tally = initialValue;
            var cursor = stream;
            while (cursor != null) {
                var cell = cursor();
                tally = injector(tally, key(cell));
                cursor = value(cell);
            }
            return tally;
        });
        method(join, function(self, separator) {
            var tally;
            var cursor = stream;
            while (cursor != null) {
                var cell = cursor();
                var itemAsString = asString(key(cell));
                tally = tally ? tally + separator + itemAsString : itemAsString;
                cursor = value(cell);
            }
            return tally;
        });
        method(collect, function(self, collector) {
            return Stream(function(cellConstructor) {
                function collectingStream(stream) {
                    if (!stream) return null;
                    var cell = stream();
                    return function() {
                        return cellConstructor(collector(key(cell)), collectingStream(value(cell)));
                    };
                }
                return collectingStream(stream);
            });
        });
        method(contains, function(self, item) {
            var cursor = stream;
            while (cursor != null) {
                var cell = cursor();
                if (item == key(cell)) return true;
                cursor = value(cell);
            }
            return false;
        });
        method(size, function(self) {
            var cursor = stream;
            var i = 0;
            while (cursor != null) {
                i++;
                cursor = value(cursor());
            }
            return i;
        });
        method(select, function(self, selector) {
            return Stream(function(cellConstructor) {
                function select(stream) {
                    if (!stream) return null;
                    var cell = stream();
                    var k = key(cell);
                    var v = value(cell);
                    return selector(k) ? function() {
                        return cellConstructor(k, select(v));
                    } : select(v);
                }
                return select(stream);
            });
        });
        method(detect, function(self, detector, notDetectedThunk) {
            var cursor = stream;
            var result;
            while (cursor != null) {
                var cell = cursor();
                var k = key(cell);
                if (detector(k)) {
                    result = k;
                    break;
                }
                cursor = value(cell);
            }
            if (result) {
                return result;
            } else {
                return notDetectedThunk ? notDetectedThunk(self) : null;
            }
        });
        method(isEmpty, function(self) {
            return stream == null;
        });
        method(copy, function(self) {
            return Stream(streamDefinition);
        });
        method(asString, function(self) {
            return 'Stream[' + join(self, ', ') + ']';
        });
    });
}
var indexOf = function(s, substring) {
    var index = s.indexOf(substring);
    if (index >= 0) {
        return index;
    } else {
        throw '"' + s + '" does not contain "' + substring + '"';
    }
};
var lastIndexOf = function(s, substring) {
    var index = s.lastIndexOf(substring);
    if (index >= 0) {
        return index;
    } else {
        throw 'string "' + s + '" does not contain "' + substring + '"';
    }
};
var startsWith = function(s, pattern) {
    return s.indexOf(pattern) == 0;
};
var endsWith = function(s, pattern) {
    return s.lastIndexOf(pattern) == s.length - pattern.length;
};
var containsSubstring = function(s, substring) {
    return s.indexOf(substring) >= 0;
};
var blank = function(s) {
    return /^\s*$/.test(s);
};
var split = function(s, separator) {
    return s.length == 0 ? [] : s.split(separator);
};
var replace = function(s, regex, replace) {
    return s.replace(regex, replace);
};
var toLowerCase = function(s) {
    return s.toLowerCase();
};
var toUpperCase = function(s) {
    return s.toUpperCase();
};
var substring = function(s, from, to) {
    return s.substring(from, to);
};
var trim = function(s) {
    s = s.replace(/^\s+/, '');
    for (var i = s.length - 1; i >= 0; i--) {
        if (/\S/.test(s.charAt(i))) {
            s = s.substring(0, i + 1);
            break;
        }
    }
    return s;
};
var asNumber = Number;
var asBoolean = function(s) {
    return 'true' == s || 'any' == s;
};
var asRegexp = function(s) {
    return new RegExp(s);
};
function registerListener(eventType, obj, listener) {
    if (obj.addEventListener) {
        obj.addEventListener(eventType, listener, false);
    } else {
        obj.attachEvent('on' + eventType, listener);
    }
}
var onLoad = curry(registerListener, 'load');
var onUnload = curry(registerListener, 'unload');
var onBeforeUnload = curry(registerListener, 'beforeunload');
var onResize = curry(registerListener, 'resize');
var onKeyPress = curry(registerListener, 'keypress');
var onKeyUp = curry(registerListener, 'keyup');
window.width = function() {
    return window.innerWidth ? window.innerWidth : (document.documentElement && document.documentElement.clientWidth) ? document.documentElement.clientWidth : document.body.clientWidth;
};
window.height = function() {
    return window.innerHeight ? window.innerHeight : (document.documentElement && document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight;
};
var run = operator();
var runOnce = operator();
var stop = operator();
function Delay(f, milliseconds) {
    return object(function(method) {
        var id = null;
        var canceled = false;
        method(run, function(self, times) {
            if (id || canceled) return;
            var call = times ? function() {
                try {
                    f();
                } finally {
                    if (--times < 1) stop(self);
                }
            } : f;
            id = setInterval(call, milliseconds);
            return self;
        });
        method(runOnce, function(self) {
            return run(self, 1);
        });
        method(stop, function(self) {
            if (id) {
                clearInterval(id);
                id = null;
            } else {
                canceled = true;
            }
        });
    });
}
var asURIEncodedString = operator();
var serializeOn = operator();
var Parameter = function(name, value) {
    return objectWithAncestors(function(method) {
        method(asURIEncodedString, function(self) {
            return encodeURIComponent(name) + '=' + encodeURIComponent(value);
        });
        method(serializeOn, function(self, query) {
            addParameter(query, self);
        });
    }, Cell(name, value));
};
var addParameter = operator();
var addNameValue = operator();
var queryParameters = operator();
var addQuery = operator();
var appendToURI = operator();
var Query = function() {
    var parameters = [];
    return object(function(method) {
        method(queryParameters, function(self) {
            return parameters;
        });
        method(addParameter, function(self, parameter) {
            append(parameters, parameter);
            return self;
        });
        method(addNameValue, function(self, name, value) {
            append(parameters, Parameter(name, value));
            return self;
        });
        method(addQuery, function(self, appended) {
            serializeOn(appended, self);
            return self;
        });
        method(serializeOn, function(self, query) {
            each(parameters, curry(addParameter, query));
        });
        method(asURIEncodedString, function(self) {
            return join(collect(parameters, asURIEncodedString), '&');
        });
        method(appendToURI, function(self, uri) {
            if (not(isEmpty(parameters))) {
                return uri + (contains(uri, '?') ? '&' : '?') + asURIEncodedString(self);
            } else {
                return uri;
            }
        });
        method(asString, function(self) {
            return inject(parameters, '', function(tally, p) {
                return tally + '|' + key(p) + '=' + value(p) + '|\n';
            });
        });
    });
};
var getSynchronously = operator();
var getAsynchronously = operator();
var postSynchronously = operator();
var postAsynchronously = operator();
var Client = function(autoclose) {
    var newNativeRequest;
    if (window.XMLHttpRequest) {
        newNativeRequest = function() {
            return new XMLHttpRequest();
        };
    } else if (window.ActiveXObject) {
        newNativeRequest = function() {
            return new window.ActiveXObject('Microsoft.XMLHTTP');
        };
    } else {
        throw 'cannot create XMLHttpRequest';
    }
    function withNewQuery(setup) {
        var query = Query();
        setup(query);
        return query;
    }
    var autoClose = autoclose ? close : noop;
    return object(function(method) {
        method(getAsynchronously, function(self, uri, setupQuery, setupRequest, onResponse) {
            var nativeRequestResponse = newNativeRequest();
            var request = RequestProxy(nativeRequestResponse);
            var response = ResponseProxy(nativeRequestResponse);
            nativeRequestResponse.open('GET', appendToURI(withNewQuery(setupQuery), uri), true);
            setupRequest(request);
            nativeRequestResponse.onreadystatechange = function() {
                if (nativeRequestResponse.readyState == 4) {
                    onResponse(response, request);
                    autoClose(request);
                }
            };
            nativeRequestResponse.send('');
            return request;
        });
        method(getSynchronously, function(self, uri, setupQuery, setupRequest, onResponse) {
            var nativeRequestResponse = newNativeRequest();
            var request = RequestProxy(nativeRequestResponse);
            var response = ResponseProxy(nativeRequestResponse);
            nativeRequestResponse.open('GET', appendToURI(withNewQuery(setupQuery), uri), false);
            setupRequest(request);
            nativeRequestResponse.send('');
            onResponse(response, request);
            autoClose(request);
        });
        method(postAsynchronously, function(self, uri, setupQuery, setupRequest, onResponse) {
            var nativeRequestResponse = newNativeRequest();
            var request = RequestProxy(nativeRequestResponse);
            var response = ResponseProxy(nativeRequestResponse);
            nativeRequestResponse.open('POST', uri, true);
            setupRequest(request);
            nativeRequestResponse.onreadystatechange = function() {
                if (nativeRequestResponse.readyState == 4) {
                    onResponse(response, request);
                    autoClose(request);
                }
            };
            nativeRequestResponse.send(asURIEncodedString(withNewQuery(setupQuery)));
            return request;
        });
        method(postSynchronously, function(self, uri, setupQuery, setupRequest, onResponse) {
            var nativeRequestResponse = newNativeRequest();
            var request = RequestProxy(nativeRequestResponse);
            var response = ResponseProxy(nativeRequestResponse);
            nativeRequestResponse.open('POST', uri, false);
            setupRequest(request);
            nativeRequestResponse.send(asURIEncodedString(withNewQuery(setupQuery)));
            onResponse(response, request);
            autoClose(request);
        });
    });
};
var close = operator();
var abort = operator();
var setHeader = operator();
var onResponse = operator();
var RequestProxy = function(nativeRequestResponse) {
    return object(function(method) {
        method(setHeader, function(self, name, value) {
            nativeRequestResponse.setRequestHeader(name, value);
        });
        method(close, function(self) {
            nativeRequestResponse.onreadystatechange = noop;
        });
        method(abort, function(self) {
            nativeRequestResponse.onreadystatechange = noop;
            nativeRequestResponse.abort();
            method(abort, noop);
        });
    });
};
var statusCode = operator();
var statusText = operator();
var getHeader = operator();
var getAllHeaders = operator();
var hasHeader = operator();
var contentAsText = operator();
var contentAsDOM = operator();
var ResponseProxy = function(nativeRequestResponse) {
    return object(function(method) {
        method(statusCode, function() {
            try {
                return nativeRequestResponse.status;
            } catch (e) {
                return 0;
            }
        });
        method(statusText, function(self) {
            try {
                return nativeRequestResponse.statusText;
            } catch (e) {
                return '';
            }
        });
        method(hasHeader, function(self, name) {
            try {
                var header = nativeRequestResponse.getResponseHeader(name);
                return header && header != '';
            } catch (e) {
                return false;
            }
        });
        method(getHeader, function(self, name) {
            try {
                return nativeRequestResponse.getResponseHeader(name);
            } catch (e) {
                return null;
            }
        });
        method(getAllHeaders, function(self, name) {
            try {
                return collect(reject(split(nativeRequestResponse.getAllResponseHeaders(), '\n'), isEmpty), function(pair) {
                    var nameValue = split(pair, ': ')
                    return Cell(nameValue[0], nameValue[1]);
                });
            } catch (e) {
                return [];
            }
        });
        method(contentAsText, function(self) {
            try {
                return nativeRequestResponse.responseText;
            } catch (e) {
                return '';
            }
        });
        method(contentAsDOM, function(self) {
            return nativeRequestResponse.responseXML;
        });
        method(asString, function(self) {
            return inject(getAllHeaders(self), 'HTTP Response\n', function(result, header) {
                return result + key(header) + ': ' + value(header) + '\n';
            }) + contentAsText(self);
        });
    });
};
function OK(response) {
    return statusCode(response) == 200;
}
function NotFound(response) {
    return statusCode(response) == 404;
}
function ServerInternalError(response) {
    var code = statusCode(response);
    return code >= 500 && code < 600;
}
function FormPost(request) {
    setHeader(request, 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
}
var cancel = operator();
var cancelBubbling = operator();
var cancelDefaultAction = operator();
var isKeyEvent = operator();
var isMouseEvent = operator();
var capturedBy = operator();
var triggeredBy = operator();
var serializeEventOn = operator();
var serializePositionOn = operator();
var type = operator();
var yes = any;
var no = none;
function isIEEvent(event) {
    return event.srcElement;
}
function Event(event, capturingElement) {
    return object(function (method) {
        method(cancel, function (self) {
            cancelBubbling(self);
            cancelDefaultAction(self);
        });
        method(isKeyEvent, no);
        method(isMouseEvent, no);
        method(type, function (self) {
            return event.type;
        });
        method(triggeredBy, function (self) {
            return capturingElement;
        });
        method(capturedBy, function (self) {
            return capturingElement;
        });
        method(serializeEventOn, function (self, query) {
            serializeElementOn(capturingElement, query);
            addNameValue(query, 'ice.event.target', identifier(triggeredBy(self)));
            addNameValue(query, 'ice.event.captured', identifier(capturedBy(self)));
            addNameValue(query, 'ice.event.type', 'on' + type(self));
        });
        method(serializeOn, curry(serializeEventOn));
    });
}
function IEEvent(event, capturingElement) {
    return objectWithAncestors(function (method) {
        method(triggeredBy, function (self) {
            return event.srcElement ? event.srcElement : null;
        });
        method(cancelBubbling, function (self) {
            event.cancelBubble = true;
        });
        method(cancelDefaultAction, function (self) {
            event.returnValue = false;
        });
        method(asString, function (self) {
            return 'IEEvent[' + type(self) + ']';
        });
    }, Event(event, capturingElement));
}
function NetscapeEvent(event, capturingElement) {
    return objectWithAncestors(function (method) {
        method(triggeredBy, function (self) {
            return event.target ? event.target : null;
        });
        method(cancelBubbling, function (self) {
            try {
                event.stopPropagation();
            } catch (e) {
            }
        });
        method(cancelDefaultAction, function (self) {
            try {
                event.preventDefault();
            } catch (e) {
            }
        });
        method(asString, function (self) {
            return 'NetscapeEvent[' + type(self) + ']';
        });
    }, Event(event, capturingElement));
}
var isAltPressed = operator();
var isCtrlPressed = operator();
var isShiftPressed = operator();
var isMetaPressed = operator();
var serializeKeyOrMouseEventOn = operator();
function KeyOrMouseEvent(event) {
    return object(function (method) {
        method(isAltPressed, function (self) {
            return event.altKey;
        });
        method(isCtrlPressed, function (self) {
            return event.ctrlKey;
        });
        method(isShiftPressed, function (self) {
            return event.shiftKey;
        });
        method(isMetaPressed, function (self) {
            return event.metaKey;
        });
        method(serializeKeyOrMouseEventOn, function (self, query) {
            addNameValue(query, 'ice.event.alt', isAltPressed(self));
            addNameValue(query, 'ice.event.ctrl', isCtrlPressed(self));
            addNameValue(query, 'ice.event.shift', isShiftPressed(self));
            addNameValue(query, 'ice.event.meta', isMetaPressed(self));
        });
    });
}
var isLeftButton = operator();
var isRightButton = operator();
var positionX = operator();
var positionY = operator();
var serializeMouseEventOn = operator();
function MouseEvent(event) {
    return objectWithAncestors(function (method) {
        method(isMouseEvent, yes);
        method(serializeMouseEventOn, function (self, query) {
            serializeKeyOrMouseEventOn(self, query);
            addNameValue(query, 'ice.event.x', positionX(self));
            addNameValue(query, 'ice.event.y', positionY(self));
            addNameValue(query, 'ice.event.left', isLeftButton(self));
            addNameValue(query, 'ice.event.right', isRightButton(self));
        });
    }, KeyOrMouseEvent(event));
}
function MouseEventTrait(method) {
    method(serializeOn, function (self, query) {
        serializeEventOn(self, query);
        serializeMouseEventOn(self, query);
    });
}
function IEMouseEvent(event, capturingElement) {
    return objectWithAncestors(function (method) {
        MouseEventTrait(method);
        method(positionX, function (self) {
            return event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
        });
        method(positionY, function (self) {
            return event.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
        });
        method(isLeftButton, function (self) {
            return event.button == 1;
        });
        method(isRightButton, function (self) {
            return event.button == 2;
        });
        method(asString, function (self) {
            return 'IEMouseEvent[' + type(self) + ']';
        });
    }, MouseEvent(event), IEEvent(event, capturingElement));
}
function NetscapeMouseEvent(event, capturingElement) {
    return objectWithAncestors(function (method) {
        MouseEventTrait(method);
        method(positionX, function (self) {
            return event.pageX;
        });
        method(positionY, function (self) {
            return event.pageY;
        });
        method(isLeftButton, function (self) {
            return event.which == 1;
        });
        method(isRightButton, function (self) {
            return event.which == 2;
        });
        method(asString, function (self) {
            return 'NetscapeMouseEvent[' + type(self) + ']';
        });
    }, MouseEvent(event), NetscapeEvent(event, capturingElement));
}
var keyCharacter = operator();
var keyCode = operator();
var serializeKeyEventOn = operator();
function KeyEvent(event) {
    return objectWithAncestors(function (method) {
        method(isKeyEvent, yes);
        method(keyCharacter, function (self) {
            return String.fromCharCode(keyCode(self));
        });
        method(serializeKeyEventOn, function (self, query) {
            serializeKeyOrMouseEventOn(self, query);
            addNameValue(query, 'ice.event.keycode', keyCode(self));
        });
    }, KeyOrMouseEvent(event));
}
function KeyEventTrait(method) {
    method(serializeOn, function (self, query) {
        serializeEventOn(self, query);
        serializeKeyEventOn(self, query);
    });
}
function IEKeyEvent(event, capturingElement) {
    return objectWithAncestors(function (method) {
        KeyEventTrait(method);
        method(keyCode, function (self) {
            return event.keyCode;
        });
        method(asString, function (self) {
            return 'IEKeyEvent[' + type(self) + ']';
        });
    }, KeyEvent(event), IEEvent(event, capturingElement));
}
function NetscapeKeyEvent(event, capturingElement) {
    return objectWithAncestors(function (method) {
        KeyEventTrait(method);
        method(keyCode, function (self) {
            return event.which == 0 ? event.keyCode : event.which;
        });
        method(asString, function (self) {
            return 'NetscapeKeyEvent[' + type(self) + ']';
        });
    }, KeyEvent(event), NetscapeEvent(event, capturingElement));
}
function isEnterKey(event) {
    return keyCode(event) == 13;
}
function isEscKey(event) {
    return keyCode(event) == 27;
}
function UnknownEvent(capturingElement) {
    return objectWithAncestors(function (method) {
        method(cancelBubbling, noop);
        method(cancelDefaultAction, noop);
        method(type, function (self) {
            return 'unknown';
        });
        method(asString, function (self) {
            return 'UnkownEvent[]';
        });
    }, Event(null, capturingElement));
}
var MouseListenerNames = [ 'onclick', 'ondblclick', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup' ];
var KeyListenerNames = [ 'onkeydown', 'onkeypress', 'onkeyup', 'onhelp' ];
function $event(e, element) {
    var capturedEvent = e || window.event;
    if (capturedEvent && capturedEvent.type) {
        var eventType = 'on' + capturedEvent.type;
        if (contains(KeyListenerNames, eventType)) {
            return isIEEvent(capturedEvent) ? IEKeyEvent(capturedEvent, element) : NetscapeKeyEvent(capturedEvent, element);
        } else if (contains(MouseListenerNames, eventType)) {
            return isIEEvent(capturedEvent) ? IEMouseEvent(capturedEvent, element) : NetscapeMouseEvent(capturedEvent, element);
        } else {
            return isIEEvent(capturedEvent) ? IEEvent(capturedEvent, element) : NetscapeEvent(capturedEvent, element);
        }
    } else {
        return UnknownEvent(element);
    }
}
        function findBridgeContainer(element) {
            while (element) {
                if (element.configuration) {
                    return element;
                }
                element = element.parentNode;
            }
            return document.body;
        }
var DefaultIndicators;
var ComponentIndicators;
(function() {
    var on = operator();
    var off = operator();
    var NOOPIndicator = object(function (method) {
        method(on, noop);
        method(off, noop);
    });
    function RedirectIndicator(uri) {
        return object(function (method) {
            method(on, function(self) {
                window.location.href = uri;
            });
            method(off, noop);
        });
    }
    function ElementIndicator(elementID, indicators) {
        var instance = object(function (method) {
            method(on, function(self) {
                each(indicators, function(indicator) {
                    if (indicator != self) off(indicator);
                });
                var e = document.getElementById(elementID);
                if (e) {
                    e.style.visibility = 'visible';
                }
            });
            method(off, function(self) {
                var e = document.getElementById(elementID);
                if (e) {
                    e.style.visibility = 'hidden';
                }
            });
        });
        append(indicators, instance);
        off(instance);
        return instance;
    }
    function OverlappingStateProtector(indicator) {
        var counter = 0;
        return object(function (method) {
            method(on, function() {
                if (counter == 0) on(indicator);
                ++counter;
            });
            method(off, function() {
                if (counter < 1) return;
                if (counter == 1) off(indicator);
                --counter;
            });
        });
    }
    function ToggleIndicator(onElement, offElement) {
        var instance = object(function (method) {
            method(on, function(self) {
                on(onElement);
                off(offElement);
            });
            method(off, function(self) {
                off(onElement);
                on(offElement);
            });
        });
        off(instance);
        return instance;
    }
    function MuxIndicator() {
        var indicators = arguments;
        var instance = object(function (method) {
            method(on, function(self) {
                each(indicators, on);
            });
            method(off, function(self) {
                each(indicators, off);
            });
        });
        off(instance);
        return instance;
    }
    function PointerIndicator(element) {
        var privateOff = noop;
        function toggle() {
            privateOn = noop;
            function toggleElementCursor(e) {
                var c = e.style.cursor;
                e.style.cursor = 'wait';
                return function() {
                    e.style.cursor = c;
                };
            }
            var cursorRollbacks = inject(['input', 'select', 'textarea', 'button', 'a'], [ toggleElementCursor(element) ], function(result, type) {
                each(element.getElementsByTagName(type), function(e) {
                    append(result, toggleElementCursor(e));
                });
                return result;
            });
            privateOff = function() {
                broadcast(cursorRollbacks);
                privateOn = toggle;
                privateOff = noop;
            };
        }
        var privateOn = toggle;
        return object(function (method) {
            method(on, function(self) {
                privateOn();
            });
            method(off, function(self) {
                privateOff();
            });
        });
    }
    function FastPointerIndicator(element) {
        var privateOff = noop;
        function toggle() {
            privateOn = noop;
            var elementStyle = element.style;
            var previousCursor = elementStyle.cursor;
            elementStyle.cursor = 'wait';
            privateOff = function() {
                elementStyle.cursor = previousCursor;
                privateOn = toggle;
                privateOff = noop;
            };
        }
        var privateOn = toggle;
        return object(function (method) {
            method(on, function(self) {
                privateOn();
            });
            method(off, function(self) {
                privateOff();
            });
        });
    }
    function OverlayIndicator() {
        return object(function(method) {
            var isIEBrowser = /MSIE/.test(navigator.userAgent);
            var overlay;
            var delayedOverlayRender;
            function createOverlay() {
                if (isIEBrowser) {
                    overlay = document.createElement('iframe');
                    overlay.setAttribute('src', 'javascript:document.write(\'<html><body style="cursor: wait;"></body><html>\');document.close();');
                    overlay.setAttribute('frameborder', '0');
                    document.body.appendChild(overlay);
                } else {
                    overlay = document.body.appendChild(document.createElement('div'));
                    overlay.style.cursor = 'wait';
                }
                var overlayStyle = overlay.style;
                overlayStyle.position = 'absolute';
                overlayStyle.backgroundColor = 'white';
                overlayStyle.zIndex = '38000';
                overlayStyle.top = '0';
                overlayStyle.left = '0';
                overlayStyle.opacity = '0';
                overlayStyle.filter = 'alpha(opacity=0)';
                overlayStyle.width = (Math.max(document.documentElement.scrollWidth, document.body.scrollWidth) - 20) + 'px';
                overlayStyle.height = (Math.max(document.documentElement.scrollHeight, document.body.scrollHeight) - 20) + 'px';
            }
            function deleteOverlay() {
                if (isIEBrowser) {
                    var blankOverlay = document.createElement('iframe');
                    blankOverlay.setAttribute('src', 'javascript:document.write("<html></html>");document.close();');
                    blankOverlay.setAttribute('frameborder', '0');
                    document.body.replaceChild(blankOverlay, overlay);
                    document.body.removeChild(blankOverlay);
                } else {
                    document.body.removeChild(overlay);
                }
                overlay = null;
            }
            method(on, function(self) {
                delayedOverlayRender = runOnce(Delay(createOverlay, 750));
            });
            method(off, function(self) {
                if (delayedOverlayRender) {
                    stop(delayedOverlayRender);
                }
                if (overlay) {
                    deleteOverlay();
                }
            });
        });
    }
    function PopupIndicator(message, description, buttonText, iconPath, panel) {
        return object(function (method) {
            method(on, function(self) {
                on(panel);
                var messageContainer = document.body.appendChild(document.createElement('div'));
                messageContainer.className = 'ice-status-indicator';
                var messageContainerStyle = messageContainer.style;
                messageContainerStyle.position = 'absolute';
                messageContainerStyle.textAlign = 'center';
                messageContainerStyle.zIndex = '28001';
                messageContainerStyle.color = 'black';
                messageContainerStyle.backgroundColor = 'white';
                messageContainerStyle.paddingLeft = '0';
                messageContainerStyle.paddingRight = '0';
                messageContainerStyle.paddingTop = '15px';
                messageContainerStyle.paddingBottom = '15px';
                messageContainerStyle.borderBottomColor = 'gray';
                messageContainerStyle.borderRightColor = 'gray';
                messageContainerStyle.borderTopColor = 'silver';
                messageContainerStyle.borderLeftColor = 'silver';
                messageContainerStyle.borderWidth = '2px';
                messageContainerStyle.borderStyle = 'solid';
                messageContainerStyle.width = '270px';
                var messageElement = messageContainer.appendChild(document.createElement('div'));
                messageElement.appendChild(document.createTextNode(message));
                messageElement.className = 'ice-status-indicator-message';
                var messageElementStyle = messageElement.style;
                messageElementStyle.marginLeft = '30px';
                messageElementStyle.textAlign = 'left';
                messageElementStyle.fontSize = '14px';
                messageElementStyle.fontSize = '14px';
                messageElementStyle.fontWeight = 'bold';
                var descriptionElement = messageElement.appendChild(document.createElement('div'));
                descriptionElement.appendChild(document.createTextNode(description));
                descriptionElement.className = 'ice-status-indicator-description';
                var descriptionElementStyle = descriptionElement.style;
                descriptionElementStyle.fontSize = '11px';
                descriptionElementStyle.marginTop = '7px';
                descriptionElementStyle.marginBottom = '7px';
                descriptionElementStyle.fontWeight = 'normal';
                var buttonElement = document.createElement('input');
                buttonElement.type = 'button';
                buttonElement.value = buttonText;
                var buttonElementStyle = buttonElement.style;
                buttonElementStyle.fontSize = '11px';
                buttonElementStyle.fontWeight = 'normal';
                buttonElement.onclick = function() {
                    window.location.reload();
                };
                messageContainer.appendChild(buttonElement);
                var resize = function() {
                    messageContainerStyle.left = ((window.width() - messageContainer.clientWidth) / 2) + 'px';
                    messageContainerStyle.top = ((window.height() - messageContainer.clientHeight) / 2) + 'px';
                };
                resize();
                onResize(window, resize);
            });
            method(off, noop);
        });
    }
    var indctrs;
    DefaultIndicators = function(configuration, setupID) {
        var container = document.getElementById(setupID).parentNode;
        container.compatDefaultIndicatorsSetupCount = container.compatDefaultIndicatorsSetupCount ? (container.compatDefaultIndicatorsSetupCount + 1) : 1;
        if (container.compatDefaultIndicatorsSetupCount == 1) {
            if (container.configuration.disableDefaultErrorPopups) {
                indctrs = {
                    busy: NOOPIndicator,
                    sessionExpired: NOOPIndicator,
                    connectionLost: NOOPIndicator,
                    serverError: NOOPIndicator,
                    connectionTrouble: NOOPIndicator
                }
            } else {
                container.configuration.disableDefaultErrorPopups = true;
                var connectionLostURI = configuration.connectionLostRedirectURI;
                if (connectionLostURI == "null") {
                    connectionLostURI = null;
                }
                var sessionExpiredURI = configuration.sessionExpiredRedirectURI;
                if (sessionExpiredURI == "null") {
                    sessionExpiredURI = null;
                }
                var connectionLostRedirect = connectionLostURI ? RedirectIndicator(connectionLostURI) : null;
                var sessionExpiredRedirect = sessionExpiredURI ? RedirectIndicator(sessionExpiredURI) : null;
                var messages = configuration.messages;
                var sessionExpiredIcon = configuration.connection.context + '/xmlhttp/css/xp/css-images/connect_disconnected.gif';
                var connectionLostIcon = configuration.connection.context + '/xmlhttp/css/xp/css-images/connect_caution.gif';
                var busyIndicator = configuration.fastBusyIndicator ? FastPointerIndicator(container) : PointerIndicator(container);
                var overlay = object(function(method) {
                    method(on, function(self) {
                        var overlay = container.ownerDocument.createElement('iframe');
                        overlay.setAttribute('src', 'about:blank');
                        overlay.setAttribute('frameborder', '0');
                        var overlayStyle = overlay.style;
                        overlayStyle.position = 'absolute';
                        overlayStyle.display = 'block';
                        overlayStyle.visibility = 'visible';
                        overlayStyle.backgroundColor = 'white';
                        overlayStyle.zIndex = '28000';
                        overlayStyle.top = '0';
                        overlayStyle.left = '0';
                        overlayStyle.opacity = 0.22;
                        overlayStyle.filter = 'alpha(opacity=22)';
                        container.appendChild(overlay);
                        var resize = container.tagName.toLowerCase() == 'body' ?
                            function() {
                                overlayStyle.width = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth) + 'px';
                                overlayStyle.height = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight) + 'px';
                            } :
                            function() {
                                overlayStyle.width = container.offsetWidth + 'px';
                                overlayStyle.height = container.offsetHeight + 'px';
                            };
                        resize();
                        onResize(window, resize);
                    });
                    method(off, noop);
                });
                indctrs = {
                    busy: busyIndicator,
                    sessionExpired: sessionExpiredRedirect ? sessionExpiredRedirect : PopupIndicator(messages.sessionExpired, messages.description, messages.buttonText, sessionExpiredIcon, overlay),
                    connectionLost: connectionLostRedirect ? connectionLostRedirect : PopupIndicator(messages.connectionLost, messages.description, messages.buttonText, connectionLostIcon, overlay),
                    serverError: PopupIndicator(messages.serverError, messages.description, messages.buttonText, connectionLostIcon, overlay),
                    connectionTrouble: NOOPIndicator
                };
            }
        }
        if (container.compatComponentIndicatorsInit) {
            container.compatComponentIndicatorsInit();
        }
    };
    var workingIDs = [];
    ComponentIndicators = function(workingID, idleID, troubleID, lostID, showPopups, displayHourglassWhenActive) {
        var container = findBridgeContainer(document.getElementById(workingID));
        if (contains(workingIDs, workingID)) {
            container.compatComponentIndicatorsInit = noop;
            return;
        } else {
            append(workingIDs, workingID);
            container.compatComponentIndicatorsInit = function() {
                var indicators = [];
                var connectionWorking = ElementIndicator(workingID, indicators);
                var connectionIdle = ElementIndicator(idleID, indicators);
                var connectionLost = ElementIndicator(lostID, indicators);
                var busyElementIndicator = ToggleIndicator(connectionWorking, connectionIdle);
                var busyIndicator = displayHourglassWhenActive ? busyElementIndicator : MuxIndicator(busyElementIndicator, OverlayIndicator());
                var busy = OverlappingStateProtector(displayHourglassWhenActive ? MuxIndicator(indctrs.busy, busyIndicator) : busyIndicator);
                var connectionTrouble = ElementIndicator(troubleID, indicators);
                if (showPopups) {
                    indctrs = {
                        busy: busy,
                        connectionTrouble: connectionTrouble,
                        connectionLost: MuxIndicator(connectionLost, indctrs.connectionLost),
                        sessionExpired: MuxIndicator(connectionLost, indctrs.sessionExpired),
                        serverError: MuxIndicator(connectionLost, indctrs.serverError)
                    };
                } else {
                    indctrs = {
                        busy: busy,
                        connectionTrouble: connectionTrouble,
                        connectionLost: indctrs.connectionLostRedirect ? indctrs.connectionLostRedirect : connectionLost,
                        sessionExpired: indctrs.sessionExpiredRedirect ? indctrs.sessionExpiredRedirect : connectionLost,
                        serverError: connectionLost
                    };
                }
            }
        }
    };
    onLoad(window, function() {
        ice.onBeforeSubmit(function(source, isClientRequest) {
            if(isClientRequest){
                indctrs && on(indctrs.busy);
            }
        });
        ice.onBeforeUpdate(function() {
            indctrs && off(indctrs.busy);
        });
        ice.onNetworkError(function() {
            indctrs && on(indctrs.connectionLost);
        });
        ice.onServerError(function() {
            indctrs && on(indctrs.serverError);
        });
        ice.onSessionExpiry(function() {
            if (indctrs) {
                indctrs.connectionTrouble = NOOPIndicator;
                indctrs.connectionLost = NOOPIndicator;
                on(indctrs.sessionExpired);
            }
        });
        if (ice.push) {
            ice.onBlockingConnectionUnstable(function() {
                indctrs && on(indctrs.connectionTrouble);
            });
            ice.onBlockingConnectionLost(function() {
                indctrs && on(indctrs.connectionLost);
            });
        }
    });
})();
        namespace.DefaultIndicators = DefaultIndicators;
        namespace.ComponentIndicators = ComponentIndicators;
        window.setFocus = namespace.setFocus;
var iceSubmitPartial;
var iceSubmit;
var formOf;
(function() {
    iceSubmitPartial = function(form, component, evt) {
        form = form || formOf(component);
        ice.submit(evt, component || form, function(parameter) {
            if (Ice.Menu != null && Ice.Menu.menuContext != null) {
                parameter('ice.menuContext', Ice.Menu.menuContext);
            }
            parameter('ice.submit.partial', true);
        });
        return false;
    };
    iceSubmit = function(form, component, evt) {
        form = form || formOf(component);
        var code;
        if (evt.keyCode) code = evt.keyCode;
        else if (evt.which) code = evt.which;
        if (code > 3) {
            if (code != 13) {
                return false;
            }
        }
        ice.submit(evt, component || form, function(parameter) {
            if (Ice.Menu != null && Ice.Menu.menuContext != null) {
                parameter('ice.menuContext', Ice.Menu.menuContext);
            }
        });
        return false;
    };
    formOf = function(element) {
        var parent = element.parentNode;
        while (parent) {
            if (parent.tagName && parent.tagName.toLowerCase() == 'form') return parent;
            parent = parent.parentNode;
        }
        throw 'Cannot find enclosing form.';
    };
})();
        window.iceSubmitPartial = iceSubmitPartial;
        window.iceSubmit = iceSubmit;
        window.formOf = formOf;
        window.onLoad = namespace.onLoad;
        window.onUnload = namespace.onUnload;
        var compatLogger = namespace.log.childLogger(namespace.log, "compat");
        window.logger = {
            debug:  curry(namespace.log.debug, compatLogger),
            info:   curry(namespace.log.info, compatLogger),
            warn:   curry(namespace.log.warn, compatLogger),
            error:  curry(namespace.log.error, compatLogger),
            child:  function() {
                return window.logger;
            }
        };
        namespace.cancelEnterKeyEvent = function(e, element) {
            var ev = $event(e, element);
            if (isEnterKey(ev)) {
                cancel(ev);
            }
        };
    })(window.ice);
}
