diff --git a/js/app/app.js b/js/app/app.js
deleted file mode 100644
index 0d2e0c7..0000000
--- a/js/app/app.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * This file sets application-wide settings and launches the application when everything has
- * been loaded onto the page. By default we just render the applications Viewport inside the
- * launch method (see app/views/Viewport.js).
- */ 
-AMDA-NG4 = new Ext.Application({
-    defaultTarget: "viewport",
-    name: "AMDA-NG4",
-    launch: function() {
-        this.viewport = new AMDA-NG4.Viewport();
-    }
-});
diff --git a/js/lib/JSBuilder/bin/Dispatch.js b/js/lib/JSBuilder/bin/Dispatch.js
deleted file mode 100644
index 69a987f..0000000
--- a/js/lib/JSBuilder/bin/Dispatch.js
+++ /dev/null
@@ -1,37 +0,0 @@
-var JSBuilderPath = system.cwd + '/lib/JSBuilder/';
-
-load(JSBuilderPath + 'src/Loader.js');
-Loader.setBasePath(JSBuilderPath + 'src');
-
-Loader.require([
-    'Ext', 'Cmd', 'Filesystem', 'Platform', 'Cli', 'Logger', 'Project', 'Target', 'Package', 'Build'
-]);
-
-/**
- * @class Ext.CommandDispatcher
- * @extends Object
- * Dispaches to the relevant Cli subclass from the command line 'sencha' command. e.g.
- * sencha generate xyz is dispatched to whichever Ext.Cli subclass registered itself to
- * handler the 'generate' command (Ext.generator.Factory in this case).
- */
-Ext.CommandDispatcher = {
-    types: {},
-    
-    dispatch: function(module, args) {
-        new this.types[module]({args: args});
-    }
-};
-
-Ext.regDispatchable = function(name, constructor) {
-    Ext.CommandDispatcher.types[name] = constructor;
-};
-
-load('src/Generator.js');
-load('src/generators/app/Application.js');
-load('src/generators/controller/Controller.js');
-load('src/generators/model/Model.js');
-
-var args   = system.arguments,
-    module = args[0];
-
-Ext.CommandDispatcher.dispatch(module, args.slice(1));
\ No newline at end of file
diff --git a/js/lib/JSBuilder/bin/Generator.js b/js/lib/JSBuilder/bin/Generator.js
deleted file mode 100644
index 55ae8e9..0000000
--- a/js/lib/JSBuilder/bin/Generator.js
+++ /dev/null
@@ -1,6 +0,0 @@
-load('src/Generator.js');
-load('src/generators/app/Application.js');
-load('src/generators/controller/Controller.js');
-load('src/generators/model/Model.js');
-
-new Ext.generator.Factory();
diff --git a/js/lib/JSBuilder/bin/JSBuilder.js b/js/lib/JSBuilder/bin/JSBuilder.js
deleted file mode 100644
index e0973f2..0000000
--- a/js/lib/JSBuilder/bin/JSBuilder.js
+++ /dev/null
@@ -1,2 +0,0 @@
-load('src/JSBuilder.js');
-new JSBuilder();
diff --git a/js/lib/JSBuilder/jsdb b/js/lib/JSBuilder/jsdb
deleted file mode 100755
index 366ba45..0000000
Binary files a/js/lib/JSBuilder/jsdb and /dev/null differ
diff --git a/js/lib/JSBuilder/src/Build.js b/js/lib/JSBuilder/src/Build.js
deleted file mode 100644
index 3820742..0000000
--- a/js/lib/JSBuilder/src/Build.js
+++ /dev/null
@@ -1,62 +0,0 @@
-Loader.require('Parser');
-
-Build = Ext.extend(Target, {
-    getDefaultTarget : function() {
-        return (this.get('id') || this.get('name').replace(/ /g, '').toLowerCase()) + '.js';
-    },
-
-    onCreate: function(file) {
-        Build.superclass.onCreate.apply(this, arguments);
-
-        var project = this.project,
-            verbose = project.builder.get('verbose'),
-            packages = this.get('packages') || [];
-
-        if (verbose && packages.length) {
-            Logger.log('  - ' + packages.length + ' package(s) included in this target.');
-        }
-
-        // Loop over all file includes, read the contents, and write
-        // it to our target file
-        packages.forEach(function(id) {
-            var pkg = this.project.getPackageById(id),
-                content;
-
-            if (!pkg) {
-                return true;
-            }
-
-            if (verbose) {
-                Logger.log('    + ' + pkg.get('target'));
-            }
-
-            pkg = new Stream(pkg.get('targetPath'));
-            content = pkg.readFile();
-            pkg.close();
-
-            file.writeln(content);
-            return true;
-        }, this);
-    },
-
-    afterCreate : function() {
-        var params = Ext.apply({debug: this.get('debug'), debugLevel: 1}, this.get('options') || {});
-
-        Logger.log('  * Parse ' + this.get('target') + ' with options:');
-
-        Ext.iterate(params, function(n, v) {
-            Logger.log('    - ' + n + ": " + v);
-        });
-
-        Parser.setParams(params);
-
-        var filePath = this.get('targetPath');
-        var parsedContent = Parser.parse(filePath);
-
-        var file = new Stream(filePath, 'w');
-        file.writeln(parsedContent);
-        file.close();
-
-        Build.superclass.afterCreate.apply(this);
-    }
-});
diff --git a/js/lib/JSBuilder/src/Cli.js b/js/lib/JSBuilder/src/Cli.js
deleted file mode 100644
index 3ab7d0d..0000000
--- a/js/lib/JSBuilder/src/Cli.js
+++ /dev/null
@@ -1,140 +0,0 @@
-Cli = Ext.extend(Object, {
-    map: {
-        h: {
-            name: 'help',
-            desc: 'Prints this help display'
-        }
-    },
-
-    // Override this on a subclass of Cli.
-    // An array with a description on how to use this Cli.
-    // Each entry in the array is printed on a new line.
-    usage: [],
-    
-    constructor : function() {
-        if (this.map !== this.superproto.map) {
-            this.map = Ext.apply({}, this.map, this.superproto.map);
-        }
-        
-        this.initArguments();
-        
-        try {
-            this.run();
-        }
-        catch (e) {
-            Logger.log(e);
-            if (e.stack) {
-                Logger.log('\n' + 'Stack trace:\n' + e.stack);
-            }
-        }
-    },
-    
-    initArguments : function() {
-        var args = system.arguments,
-            ln = args.length,
-            parsedArgs = this.args = {},
-            curArg = null,
-            i, arg;
-
-        for (i = 0; i < ln; i++) {
-            arg = args[i];
-            if (arg[0] == '-') {
-                if (arg[1] == '-') {
-                    curArg = arg.substr(2);
-                }
-                else if (arg.length == 2) {
-                    curArg = this.map[arg[1]] ? this.map[arg[1]].name : arg[1];
-                }
-                else {
-                    continue;
-                }
-
-                if (args[i + 1] && args[i + 1][0] != '-') {
-                    parsedArgs[curArg] = args[i + 1] || true;
-                    i++;
-                }
-                else {
-                    parsedArgs[curArg] = true;
-                }
-            }
-        }
-    },
-    
-    printUsage : function(message) {
-        var map = this.map,
-            usage = [''],
-            i, mapping;
-        
-        if (!message) {
-            usage.push(this.name + ' version ' + this.version);
-            usage.push('Powered by Sencha Inc');
-            usage.push('');
-            usage.push('Available arguments:');
-            for (i in map) {
-                mapping = map[i];
-                usage.push(
-                    '    --' + mapping.name + '  -' + i
-                );
-                usage.push('      ' + (mapping.required ? '(required)' : '(optional)') + ' ' + (mapping.desc || ''));
-                usage.push('');
-            }
-        }
-        else {
-            usage.push(message);
-        }
-        
-        usage.push('');
-        usage = usage.concat(this.usage);
-        usage.push('');
-
-        for (i = 0; i < usage.length; i++) {
-            Logger.log(usage[i]);
-        }
-    },
-    
-    checkRequired : function() {
-        var args = this.args,
-            i, req;
-        
-        for (i in this.map) {
-            if (this.map[i].required && args[this.map[i].name] === undefined) {
-                return i;
-            }
-        }
-        
-        return true;
-    },
-    
-    run : function() {
-        if (this.get('help')) {
-            this.printUsage();
-            return false;            
-        }
-        
-        var required = this.checkRequired();
-        if (required !== true) {
-            this.error('The --' + this.map[required].name + ' or -' + required + ' argument is required');
-            this.printUsage();
-            return false;
-        }
-    },
-    
-    get : function(key) {
-        return this.args[key] || false;
-    },
-    
-    set : function(key, value, ifNotExists) {
-        if (ifNotExists && this.get(key) !== false) {
-            return;
-        }
-        this.args[key] = value;
-    },
-    
-    log : function(variable) {
-        Logger.log(variable);
-    },
-    
-    error : function(error) {
-        throw error;
-    }
-});
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Cmd.js b/js/lib/JSBuilder/src/Cmd.js
deleted file mode 100644
index f931619..0000000
--- a/js/lib/JSBuilder/src/Cmd.js
+++ /dev/null
@@ -1,11 +0,0 @@
-Cmd = {
-    execute: function(cmd) {
-        if (Platform.isWindows) {
-            var stream = new Stream('exec://' + cmd);
-            stream.close();   
-        }
-        else {
-            system.execute(cmd);
-        }
-    }
-};
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Ext.js b/js/lib/JSBuilder/src/Ext.js
deleted file mode 100644
index 0a59501..0000000
--- a/js/lib/JSBuilder/src/Ext.js
+++ /dev/null
@@ -1,267 +0,0 @@
-Ext = {
-    /**
-     * Copies all the properties of config to obj.
-     * @param {Object} object The receiver of the properties
-     * @param {Object} config The source of the properties
-     * @param {Object} defaults A different object that will also be applied for default values
-     * @return {Object} returns obj
-     * @member Ext apply
-     */
-    apply : function(object, config, defaults) {
-        // no "this" reference for friendly out of scope calls
-        if (defaults) {
-            Ext.apply(object, defaults);
-        }
-        if (object && config && typeof config == 'object') {
-            for (var key in config) {
-                object[key] = config[key];
-            }
-        }
-        return object;
-    },
-
-    /**
-     * Copies all the properties of config to obj if they don't already exist.
-     * @param {Object} obj The receiver of the properties
-     * @param {Object} config The source of the properties
-     * @return {Object} returns obj
-     */
-    applyIf : function(object, config) {
-        var property, undefined;
-        if (object) {
-            for (property in config) {
-                if (object[property] === undefined) {
-                    object[property] = config[property];
-                }
-            }
-        }
-        return object;
-    },
-        
-    /**
-     * <p>Extends one class to create a subclass and optionally overrides members with the passed literal. This method
-     * also adds the function "override()" to the subclass that can be used to override members of the class.</p>
-     * @param {Function} superclass The constructor of class being extended.
-     * @param {Object} overrides <p>A literal with members which are copied into the subclass's
-     * prototype, and are therefore shared between all instances of the new class.</p>
-     * <p>This may contain a special member named <tt><b>constructor</b></tt>. This is used
-     * to define the constructor of the new class, and is returned. If this property is
-     * <i>not</i> specified, a constructor is generated and returned which just calls the
-     * superclass's constructor passing on its parameters.</p>
-     * <p><b>It is essential that you call the superclass constructor in any provided constructor. See example code.</b></p>
-     * @return {Function} The subclass constructor from the <code>overrides</code> parameter, or a generated one if not provided.
-     */
-    extend : function() {
-        // inline overrides
-        var inlineOverrides = function(o){
-            for(var m in o){
-                this[m] = o[m];
-            }
-        };
-
-        var objectConstructor = Object.prototype.constructor;
-
-        return function(subclass, superclass, overrides){
-            // First we check if the user passed in just the superClass with overrides
-            if(Ext.isObject(superclass)){
-                overrides = superclass;
-                superclass = subclass;
-                subclass = overrides.constructor != objectConstructor
-                ? overrides.constructor
-                : function(){
-                    superclass.apply(this, arguments);
-                };
-            }
-
-            // We create a new temporary class
-            var F = function(){},
-            subclassProto,
-            superclassProto = superclass.prototype;
-
-            F.prototype = superclassProto;
-            subclassProto = subclass.prototype = new F();
-            subclassProto.constructor = subclass;
-            subclass.superclass = superclassProto;
-
-            if(superclassProto.constructor == objectConstructor){
-                superclassProto.constructor = superclass;
-            }
-
-            subclass.override = function(overrides){
-                Ext.override(subclass, overrides);
-            };
-
-            subclassProto.superclass = subclassProto.supr = (function(){
-                return superclassProto;
-            });
-
-            subclassProto.override = inlineOverrides;
-            subclassProto.proto = subclassProto;
-            subclassProto.superproto = superclassProto;
-            
-            subclass.override(overrides);
-            subclass.extend = function(o){
-                return Ext.extend(subclass, o);
-            };
-
-            return subclass;
-        };
-    }(),
-    
-    /**
-     * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
-     * @param {Object} origclass The class to override
-     * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
-     * containing one or more methods.
-     * @method override
-     */
-    override : function(origclass, overrides) {
-        if (overrides) {
-            Ext.apply(origclass.prototype, overrides);
-        }
-    },
-    
-    /**
-     * <p>Returns true if the passed value is empty.</p>
-     * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
-     * <li>null</li>
-     * <li>undefined</li>
-     * <li>an empty array</li>
-     * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
-     * </ul></div>
-     * @param {Mixed} value The value to test
-     * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
-     * @return {Boolean}
-     */
-    isEmpty : function(v, allowBlank) {
-        return v == null || ((Ext.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
-    },
-
-    /**
-     * Returns true if the passed value is a JavaScript array, otherwise false.
-     * @param {Mixed} value The value to test
-     * @return {Boolean}
-     */
-    isArray : function(v) {
-        return Object.prototype.toString.apply(v) === '[object Array]';
-    },
-
-    /**
-     * Returns true if the passed object is a JavaScript date object, otherwise false.
-     * @param {Object} object The object to test
-     * @return {Boolean}
-     */
-    isDate : function(v) {
-        return Object.prototype.toString.apply(v) === '[object Date]';
-    },
-
-    /**
-     * Returns true if the passed value is a JavaScript Object, otherwise false.
-     * @param {Mixed} value The value to test
-     * @return {Boolean}
-     */
-    isObject : function(v) {
-        return !!v && Object.prototype.toString.call(v) === '[object Object]';
-    },
-
-    /**
-     * Returns true if the passed value is a JavaScript 'primitive', a string, number or boolean.
-     * @param {Mixed} value The value to test
-     * @return {Boolean}
-     */
-    isPrimitive : function(v) {
-        return Ext.isString(v) || Ext.isNumber(v) || Ext.isBoolean(v);
-    },
-
-    /**
-     * Returns true if the passed value is a JavaScript Function, otherwise false.
-     * @param {Mixed} value The value to test
-     * @return {Boolean}
-     */
-    isFunction : function(v) {
-        return Object.prototype.toString.apply(v) === '[object Function]';
-    },
-
-    /**
-     * Returns true if the passed value is a number. Returns false for non-finite numbers.
-     * @param {Mixed} value The value to test
-     * @return {Boolean}
-     */
-    isNumber : function(v) {
-        return Object.prototype.toString.apply(v) === '[object Number]' && isFinite(v);
-    },
-
-    /**
-     * Returns true if the passed value is a string.
-     * @param {Mixed} value The value to test
-     * @return {Boolean}
-     */
-    isString : function(v) {
-        return Object.prototype.toString.apply(v) === '[object String]';
-    },
-
-    /**util
-     * Returns true if the passed value is a boolean.
-     * @param {Mixed} value The value to test
-     * @return {Boolean}
-     */
-    isBoolean : function(v) {
-        return Object.prototype.toString.apply(v) === '[object Boolean]';
-    },
-
-    /**
-     * Returns true if the passed value is not undefined.
-     * @param {Mixed} value The value to test
-     * @return {Boolean}
-     */
-    isDefined : function(v){
-        return typeof v !== 'undefined';
-    },
-
-    each : function(array, fn, scope) {
-        if (Ext.isEmpty(array, true)) {
-            return 0;
-        }
-        if (!Ext.isIterable(array) || Ext.isPrimitive(array)) {
-            array = [array];
-        }
-        for (var i = 0, len = array.length; i < len; i++) {
-            if (fn.call(scope || array[i], array[i], i, array) === false) {
-                return i;
-            }
-        }
-        return true;
-    },
-    
-    iterate : function(obj, fn, scope) {
-        if (Ext.isEmpty(obj)) {
-            return;
-        }
-        if (Ext.isIterable(obj)) {
-            Ext.each(obj, fn, scope);
-            return;
-        }
-        else if (Ext.isObject(obj)) {
-            for (var prop in obj) {
-                if (obj.hasOwnProperty(prop)) {
-                    if (fn.call(scope || obj, prop, obj[prop], obj) === false) {
-                        return;
-                    }
-                }
-            }
-        }
-    },
-    
-    isIterable : function(v) {
-        //check for array or arguments
-        if (Ext.isArray(v) || v.callee) {
-            return true;
-        }
-    },
-
-    $included: {},
-
-    require: function(className) {
-
-    }
-}
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Filesystem.js b/js/lib/JSBuilder/src/Filesystem.js
deleted file mode 100644
index 1fe373a..0000000
--- a/js/lib/JSBuilder/src/Filesystem.js
+++ /dev/null
@@ -1,111 +0,0 @@
-Filesystem = {
-    exists : function(path) {
-        return system.exists(path);
-    },
-
-    getFullPath: function(path) {
-        var currentPath = system.setcwd(path);
-        return system.setcwd(currentPath);
-    },
-
-    getPath: function(path){
-        return path.replace(/\//g, Fs.sep);
-    },
-
-    mkdir: function(path) {
-        if (Platform.isWindows) {
-            system.mkdir(path);
-        }
-        else {
-            Cmd.execute('mkdir -p ' + path);
-        }
-        return this.getFullPath(path);
-    },
-
-    readFile : function(file) {
-        if (!Fs.exists(file)) {
-            return '';
-        }
-
-        file = new Stream(file);
-        var contents = file.readFile();
-        file.close();
-
-        return contents;
-    },
-
-    writeFile: function(file, contents) {
-        file = new Stream(file, 'w');
-        file.writeln(contents);
-        file.close();
-
-        return contents;
-    },
-
-    copy: function(src, dest) {
-        src = Fs.getPath(src);
-        dest = Fs.getPath(dest);
-
-        if (Platform.isWindows) {
-            if (Fs.endsWith(src, Fs.sep)) {
-                src = src.slice(0, -1); // cut off any trailing \
-            }
-
-            /**
-             * Check if we're copying a single file. This isn't bulletproof, however xcopy
-             * will prompt regarding if the item is a directory or file, with no way to
-             * suppress the prompt. As such, this will catch a majority of scenarios
-             * and actually make the build work!
-             */
-            var isFile = /\.[0-9a-z]{2,4}$/i;
-            if (isFile.test(src)) {
-                system.copy(src, dest);
-            } else {
-                Cmd.execute('xcopy ' + src + ' ' + dest + ' /E /Y /I');
-            }
-        }
-        else {
-            try {
-                // q: quiet
-                // r: recursive
-                // u: only update if newer
-                // p: keep permissions
-                // L: copy the contents of symlinks
-                Cmd.execute('rsync -qrupL ' + src + ' ' + dest);
-            }
-            catch(e) {
-                Cmd.execute('cp -Rpf ' + src + ' ' + dest);
-            }
-        }
-    },
-
-    endsWith: function(str, last){
-        return str.lastIndexOf(last) == str.length - 1;
-    },
-
-    split: function(file) {
-        var split = [];
-        if (!Fs.exists(file)) {
-            return split;
-        }
-        file = new Stream(file);
-        while (!file.eof) {
-            split.push(file.readln().trim());
-        }
-        return split;
-    },
-
-    remove: function(file) {
-        if (Platform.isWindows) {
-            Cmd.execute('del /f /q "' + file + '"');
-        } else {
-            Cmd.execute('rm -Rf "' + file + '"');
-        }
-    }
-};
-
-// Create short alias
-Fs = Filesystem;
-
-Fs.sep = (Fs.getFullPath('.')[0] == '/') ? '/': '\\';
-Fs.fileWorkingDir = Fs.getFullPath('.');
diff --git a/js/lib/JSBuilder/src/Generator.js b/js/lib/JSBuilder/src/Generator.js
deleted file mode 100644
index 54a72d5..0000000
--- a/js/lib/JSBuilder/src/Generator.js
+++ /dev/null
@@ -1,203 +0,0 @@
-load(JSBuilderPath + 'src/Template.js');
-load(JSBuilderPath + 'src/XTemplate.js');
-
-Ext.generator = {};
-
-/**
- * @class Ext.generator.Base
- * @extends Object
- * Base class for all Generators
- */
-Ext.generator.Base = Ext.extend(Object, {
-    /**
-     * @cfg {Boolean} pretend True to only output what the generator would do (e.g. which files would be created),
-     * without actually modifying anything on the filesystem.
-     */
-    pretend: false,
-    
-    basePath: '.',
-    
-    constructor: function(config) {
-        Ext.apply(this, config);
-        
-        if (this.args) {
-            this.decodeArgs(this.args);
-        }
-    },
-    
-    /**
-     * Creates an empty directory at the given location
-     * @param {String} path The directory path
-     */
-    mkdir: function() {
-        var length = arguments.length,
-            dirName, i;
-        
-        for (i = 0; i < length; i++) {
-            dirName = this.basePath + "/" + arguments[i];
-            Logger.log("    Creating dir: " + dirName);
-            
-            if (!this.pretend) {
-                Filesystem.mkdir(dirName);
-            }
-        }
-    },
-    
-    /**
-     * Applies data to an XTemplate, saving its output to the given file name
-     * @param {String} name The name of the template
-     */
-    template: function(name, data, filename) {
-        Logger.log("    Creating file: " + filename);
-        
-        // dirty hack to let <tpl> get through without being picked up
-        Ext.apply(data, {
-            tpl: 'tpl'
-        });
-        
-        var name        = 'src/generators/' + this.dirName + '/templates/' + name + '.js',
-            stream      = new Stream(name, 'rw'),
-            template    = new Ext.XTemplate(stream.readText()),
-            contents    = template.apply(data),
-            destination = this.basePath + '/' + filename,
-            newFile     = new Stream(destination, "w");
-        
-        newFile.writeLine(contents);
-        system.move(destination, filename, true);
-        newFile.close();
-    },
-    
-    /**
-     * Copies a file from the generator's files directory into the app
-     * @param {String} fileName The name of the file to copy
-     * @param {String} destination The destination path (defaults to the fileName)
-     * @param {Boolean} silent True to not log any messages (defaults to false)
-     */
-    file: function(fileName, destination, silent) {
-        Logger.log("    Copying " + fileName);
-        
-        destination = this.basePath + '/' + (destination || fileName);
-        fileName = 'src/generators/' + this.dirName + '/files/' + fileName;
-        
-        if (!this.pretend && this.silent !== true) {
-            Filesystem.copy(fileName, destination);
-        }
-    },
-    
-    /**
-     * Copies all contents of the given source directory to a destination
-     * @param {String} dirName The name of the directory to copy
-     * @param {String} destination The destination for the source files
-     */
-    copyDir: function(dirName, destination) {
-        destination = this.basePath + '/' + (destination || dirName);
-        
-        if (!this.pretend) {
-            Filesystem.copy(dirName, destination);
-        }
-    },
-    
-    /**
-     * Inserts a script tag to load the given src file inside the given div id
-     * @param {String} path The path to the script to be included
-     * @param {String} id The id of the div to include after
-     * @param {String} htmlFile Optional html file to update (defaults to index.html)
-     */
-    insertInclude: function(path, id, htmlFile) {
-        htmlFile = htmlFile || 'index.html';
-        
-        var stream = new Stream(htmlFile, 'rw'),
-            regex  = new RegExp('<div id="' + id + '">'),
-            lines  = [],
-            line;
-        
-        while (line = stream.readLine()) {
-            lines.push(line);
-            
-            if (regex.test(line)) {
-                lines.push('            <script type="text/javascript" src="' + path + '"></script>');
-            }
-        }
-        
-        var destination = htmlFile + "-modified",
-            newFile     = new Stream(destination, "w");
-        
-        newFile.writeLine(lines.join("\n"));
-        system.move(destination, htmlFile, true);
-        newFile.close();
-    },
-    
-    /**
-     * Convenience function for displaying a clear message to the user
-     * @param {String} message The message to display
-     */
-    headline: function(message) {
-        Logger.log("");
-        Logger.log("*********************************************");
-        Logger.log(message);
-        Logger.log("*********************************************");
-        Logger.log("");
-    },
-    
-    generate: function() {
-        
-    }
-});
-
-/**
- * @class GeneratorHelper
- * @extends Cli
- * Generates files and folders based on a template
- */
-Ext.generator.Factory = Ext.extend(Object, {
-    name: "Generator",
-    version: "0.0.1",
-    
-    constructor: function(config) {
-        Ext.apply(this, config);
-        
-        Cli.call(this);
-    },
-    
-    initArguments: function() {},
-    
-    usage: [
-        'Example usage:',
-        'Arguments in square brackets are optional',
-        '',
-        'Generating an application:',
-        '    ./generate app AppName [../path/to/app]',
-        '',
-        'Generating a model:',
-        '    ./generate model User id:int name:string active:boolean',
-        '',
-        'Generating a controller:',
-        '    ./generate controller users create update destroy',
-        ''
-    ],
-    
-    run: function() {
-        var args = this.args || system.arguments,
-            Gen  = Ext.generator.Factory.types[args[0]];
-        
-        if (Gen) {
-            new Gen({args: args.slice(1)}).generate();
-        } else {
-            this.printUsage();
-        }
-    }
-});
-
-Ext.generator.Factory.types = {};
-Ext.regGenerator = function(name, constructor) {
-    Ext.generator.Factory.types[name] = constructor;
-    
-    constructor.prototype.dirName = name;
-    constructor.templates = {};
-};
-
-Ext.regDispatchable('generate', Ext.generator.Factory);
-
-// generate app FB examples/facebook
-// generate model User id:int name:string email:string
-// generate controller users index build show new
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/JSBuilder.js b/js/lib/JSBuilder/src/JSBuilder.js
deleted file mode 100644
index b10cdba..0000000
--- a/js/lib/JSBuilder/src/JSBuilder.js
+++ /dev/null
@@ -1,77 +0,0 @@
-var JSBuilderPath = system.script.replace(/bin(\/|\\)JSBuilder\.js/, '');
-
-load(JSBuilderPath + 'src/Loader.js');
-Loader.setBasePath(JSBuilderPath + 'src');
-
-Loader.require([
-    'Ext', 'Cmd', 'Filesystem', 'Platform', 'Cli', 'Logger', 'Project', 'Target', 'Package', 'Build'
-]);
-
-/**
- * @class JSBuilder
- */
-JSBuilder = Ext.extend(Cli, {
-    name: 'JSBuilder',
-    version: '3.0.0',
-    
-    map: {
-        p: {
-            name: 'projectFile',
-            required: true,
-            desc: 'Location of a jsb2 project file'
-        },
-        d: {
-            name: 'deployDir',
-            required: true,
-            desc: 'The directory to build the project to'
-        },
-        v: {
-            name: 'verbose',
-            desc: 'Output detailed information about what is being built'
-        },
-        s: {
-            name: 'debugSuffix',
-            desc: 'Suffix to append to JS debug targets, defaults to \'debug\''
-        },
-        c: {
-            name: 'nocompress',
-            desc: 'Dont compress the targets'
-        }     
-    },
-    
-    usage: [
-        'Example Usage:',
-        '',
-        'Windows:',
-        'JSBuilder.bat -p C:\\Apps\\www\\ext3svn\\ext.jsb2 -d C:\\Apps\\www\\deploy\\',
-        '',
-        'Linux and OS X:',
-        'JSBuilder.sh -p /home/tommy/www/trunk/ext.jsb2 -d /home/tommy/www/deploy/',
-        '',
-        'JSBuilder3 is a Sencha Project build tool.',
-        'For additional information, see http://www.sencha.com/products/jsbuilder/'
-    ],
-    
-    run : function() {
-        if (JSBuilder.superclass.run.call(this) === false) {
-            return;
-        }
-        
-        // true to only set if it is not defined
-        this.set('debugSuffix', '-debug', true); 
-
-        this.project = new Project(this.get('projectFile'), this);
-        
-        if (this.get('sourceFiles')) {
-            this.project.getSourceFiles();
-        } else if (this.get('specFiles')) {
-            this.project.getSpecFiles();
-        } else {
-            this.log('\nLoading the ' + this.project.get('name') + ' Project'); 
-            this.log('Loaded ' + this.project.get('packages').length + ' Packages');
-            this.log('Loaded ' + this.project.get('builds').length + ' Builds');
-
-            this.project.build();
-        }
-    }    
-});
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Loader.js b/js/lib/JSBuilder/src/Loader.js
deleted file mode 100644
index d8b773f..0000000
--- a/js/lib/JSBuilder/src/Loader.js
+++ /dev/null
@@ -1,74 +0,0 @@
-(function(ROOT) {
-
-var Loader = ROOT.Loader = {
-    paths: {
-        _base: "."
-    },
-
-    existing: {},
-
-    exists: function(name) {
-        var root = ROOT;
-        var chunks = name.split('.');
-
-        for (var i = 0; i < chunks.length; i++) {
-            if (!root.hasOwnProperty(chunks[i]))
-                return false;
-
-            root = root[chunks[i]];
-        }
-
-        return true;
-    },
-
-    setBasePath: function(name, path) {
-        if (!path) {
-            path = name;
-            name = "_base";
-        }
-
-        Loader.paths[name] = path;
-    },
-
-    getBasePath: function(name) {
-        // Start with the base path
-        var path = Loader.paths._base;
-
-        // Iterate through each specified name path ("Ext.layout.Layout" => "js/Ext/layout/Layout.js")
-        for (var stub in Loader.paths) {
-            if (stub === name.substring(0, stub.length)) {
-                path += "/" + Loader.paths[stub];
-                // Remove stub from name, as we've already pathed it
-                name = name.substring(stub.length + 1);
-                break;
-            }
-        }
-
-        return path + "/" + name.replace(/\./g, "/");
-    },
-
-    require: function(names, compulsory) {
-        if (compulsory == undefined)
-            compulsory = true;
-
-        if (typeof names == 'string')
-            names = [names];
-
-        names.forEach(function(name) {
-            if (!this.existing.hasOwnProperty(name)) {
-//                writeln(this.getBasePath(name) + '.js');
-                load(this.getBasePath(name) + '.js');
-
-                var loaded = this.exists(name);
-                this.existing[name] = loaded;
-            }
-
-            if (this.existing[name] == false && compulsory) {
-                throw new Error("[Loader] Failed loading '" + name + "'");
-            }
-        }, Loader);
-    }
-};
-
-})(this);
-
diff --git a/js/lib/JSBuilder/src/Logger.js b/js/lib/JSBuilder/src/Logger.js
deleted file mode 100644
index 291bf4a..0000000
--- a/js/lib/JSBuilder/src/Logger.js
+++ /dev/null
@@ -1,8 +0,0 @@
-Logger = {
-  /**
-    * Logs the variable to the command line
-    */
-    log: function(variable) {
-        writeln(variable);
-    }
-};
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Package.js b/js/lib/JSBuilder/src/Package.js
deleted file mode 100644
index e53ed20..0000000
--- a/js/lib/JSBuilder/src/Package.js
+++ /dev/null
@@ -1,5 +0,0 @@
-Package = Ext.extend(Target, {
-    getDefaultTarget : function() {
-        return 'pkgs' + Fs.sep + (this.get('id') || this.get('name').replace(/ /g, '').toLowerCase()) + '.js';
-    }
-});
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Parser.js b/js/lib/JSBuilder/src/Parser.js
deleted file mode 100644
index 00ba569..0000000
--- a/js/lib/JSBuilder/src/Parser.js
+++ /dev/null
@@ -1,156 +0,0 @@
-// Singleton
-Parser = new(Ext.extend(Object, {
-    params: {},
-
-    parse: function(filename) {
-        var stream = new Stream(filename),
-            ret;
-
-        Loader.require('Parser.Statement');
-        ret = (new Parser.Statement()).parse(stream);
-        stream.close();
-
-        return ret;
-    },
-
-    evaluate: function(name, value) {
-        var modifier = null,
-            param = (this.params.hasOwnProperty(name)) ? this.params[name] : false,
-            match;
-
-        if (value === undefined) {
-            value = true;
-        }
-
-        if (Ext.isString(value)) {
-            match = value.match(/^(\!|<=|>=|<|>)/);
-
-            if (match) {
-                modifier = match[0];
-                value = value.slice(modifier.length);
-            }
-
-            // Boolean
-            if (value === 'true') {
-                value = true;
-            }
-            else if (value === 'false') {
-                value = false;
-            }
-            // Numeric
-            else if (!isNaN(value)) {
-                value = parseFloat(value);
-            }
-        }
-
-        switch (modifier) {
-            case '!':
-                return (param !== value);
-            case '>':
-                return (param > value);
-            case '<':
-                return (param < value);
-            case '<=':
-                return (param <= value);
-            case '>=':
-                return (param >= value);
-            default:
-                return (param === value);
-        }
-    },
-
-    setParams: function(params) {
-        this.params = params || {};
-    },
-
-    isCloseOf: function(str, statement) {
-        if (!statement.type) {
-            return false;
-        }
-
-        return str.trim().match(new RegExp("^\\/\\/(?:\\t|\\s)*<\\/" + ((statement.isInverted) ? "!" : "") + statement.type + ">$")) !== null;
-    },
-
-    isStatement: function(str) {
-        return this.parseStatementParts(str) !== null;
-    },
-
-    parseStatementParts: function(str) {
-        return str.trim().match(/^\/\/(?:\t|\s)*<([^\/]+)>$/);
-    },
-
-    parseStatementProperties: function(str) {
-        var properties = {},
-            expect = function(regexp) {
-                var result = str.match(regexp);
-
-                if (result !== null) {
-                    str = str.slice(result[0].length);
-                    return result[0];
-                }
-
-                return null;
-            },
-            name, equalSign, valueWrapper, valueCheck, value;
-
-        while (str.length > 0) {
-            expect(/^[^\w]+/i);
-            name = expect(/^[\w]+/i);
-
-            if (name === null) {
-                break;
-            }
-
-            equalSign = expect(/^=/);
-
-            if (equalSign === null) {
-                properties[name] = true;
-                continue;
-            }
-
-            valueWrapper = expect(/^('|")/i);
-            valueCheck = valueWrapper || "\\s";
-
-            value = expect(new RegExp('^[^' + valueCheck + ']+'));
-
-            if (valueWrapper !== null) {
-                expect(new RegExp(valueWrapper));
-            }
-
-            properties[name] = value;
-        }
-
-        return properties;
-    },
-
-    parseStatement: function(string) {
-        var str = string.trim(),
-            parts = this.parseStatementParts(str),
-            typeMatch, statement;
-
-        // Check if it's actually a valid statement
-        if (parts === null) {
-            return false;
-        }
-
-        str = parts[1];
-
-        typeMatch = str.match(/^(\!)?([\w]+)/i);
-
-        if (typeMatch === null) {
-            return false;
-        }
-
-        statement = {
-            properties: {}
-        };
-
-        statement.type = typeMatch[2];
-        statement.isInverted = (typeMatch[1] !== undefined);
-
-        str = str.substr(typeMatch[0].length, str.length).trim();
-        statement.properties = this.parseStatementProperties(str);
-
-        return statement;
-    }
-}));
diff --git a/js/lib/JSBuilder/src/Parser.old.js b/js/lib/JSBuilder/src/Parser.old.js
deleted file mode 100644
index e036e75..0000000
--- a/js/lib/JSBuilder/src/Parser.old.js
+++ /dev/null
@@ -1,116 +0,0 @@
-Parser = {
-    isBuild: function(builds) {
-        return builds.split('|').indexOf(this.build) != -1;
-    },
-
-    parse: function(file, build) {
-        var line,
-            trimmed,
-            o = this.output = [];
-
-        this.build = build;
-
-        file = new Stream(file);
-        while (!file.eof) {
-            line = file.readLine();
-            trimmed = line.trim();
-            if (this.isStatement(trimmed)) {
-                this.handleStatement(this.parseStatement(trimmed), file);
-            }
-            else {
-                this.output.push(line);
-                this.checkExtraComma();
-            }
-        }
-        file.close();
-        return this.output.join('\n');
-    },
-
-    checkExtraComma: function() {
-        var output = this.output,
-            ln = output.length - 1,
-            line = output[ln],
-            trimmed = line.trim(),
-            prevLine;
-
-        if (trimmed[0] == '}') {
-            while (output[--ln].trim() == '') {
-                output.splice(ln, 1);
-            }
-            prevLine = output[ln];
-            if (prevLine.trim().slice( - 1) == ',') {
-                output[ln] = prevLine.slice(0, prevLine.lastIndexOf(','));
-            }
-        }
-    },
-
-    isStatement: function(line) {
-        return line.substr(0, 3) == '//[' && line.substr( - 1) == ']';
-    },
-
-    handleStatement: function(statement, file) {
-        switch (statement.type) {
-            case 'if':
-            case 'elseif':
-                this.handleIf(file, statement.condition);
-                break;
-
-            case 'else':
-                this.handleElse(file);
-                break;
-        }
-    },
-
-    parseStatement: function(statement) {
-        var parts = statement.substring(3, statement.length - 1).split(' ');
-        return {
-            type: parts[0],
-            condition: parts[1]
-        };
-    },
-
-    handleIf: function(file, condition) {
-        if (this.isBuild(condition)) {
-            var next = this.getNextStatement(file);
-            this.output.push(next.buffer);
-            this.toEndIf(file, next);
-        }
-        else {
-            this.handleStatement(this.getNextStatement(file), file);
-        }
-    },
-
-    handleElse: function(file) {
-        var next = this.toEndIf(file);
-        this.output.push(next.buffer);
-    },
-
-    toEndIf: function(file, next) {
-        next = next || this.getNextStatement(file);
-        while (next && next.type != 'endif') {
-            next = this.getNextStatement(file);
-        }
-        return next;
-    },
-
-    getNextStatement: function(file) {
-        var buffer = [],
-            line,
-            trimmed,
-            ret;
-
-        while (!file.eof) {
-            line = file.readLine();
-            trimmed = line.trim();
-            if (!this.isStatement(trimmed)) {
-                buffer.push(line);
-            }
-            else {
-                ret = this.parseStatement(trimmed);
-                ret.buffer = buffer.join('\n');
-                return ret;
-            }
-        }
-        return null;
-    }
-};
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Parser/Statement.js b/js/lib/JSBuilder/src/Parser/Statement.js
deleted file mode 100644
index 9c327fa..0000000
--- a/js/lib/JSBuilder/src/Parser/Statement.js
+++ /dev/null
@@ -1,103 +0,0 @@
-Loader.require('Logger');
-
-Parser.Statement = Ext.extend(Object, {
-    isInverted: false,
-    properties: {},
-    buffer: '',
-    parent: null,
-
-    constructor: function(properties, isInverted) {
-        if (properties === undefined) {
-            properties = {};
-        }
-
-        if (isInverted === undefined) {
-            isInverted = false;
-        }
-
-        this.properties = properties;
-        this.isInverted = isInverted;
-    },
-
-    setProperty: function(name, value) {
-        this.properties[name] = value;
-    },
-
-    getProperty: function(name) {
-        return this.properties.hasOwnProperty(name) ? this.properties[name] : null;
-    },
-
-    removeProperty: function(name) {
-        delete this.properties[name];
-    },
-
-    isEnd: function(line, stream) {
-        return Parser.isCloseOf(line, this);
-    },
-
-    pushBuffer: function(content, withNewLine) {
-        if (withNewLine === undefined) {
-            withNewLine = false;
-        }
-
-        this.buffer += content + ((withNewLine) ? "\n" : "");
-    },
-
-    resetBuffer: function() {
-        this.buffer = '';
-    },
-
-    parse: function(stream) {
-        var line, subStatementData, subStatement;
-
-        while (!stream.eof) {
-            line = stream.readLine();
-
-            if (this.isEnd(line, stream)) {
-                break;
-            }
-
-            if ((subStatementData = Parser.parseStatement(line)) && (subStatement = Parser.Statement.factory(subStatementData))) {
-                subStatement.parent = this;
-                this.onSubStatement(subStatement, stream);
-            } else {
-                this.pushBuffer(line, !stream.eof);
-            }
-        }
-
-        return this.buffer;
-    },
-
-    onSubStatement: function(statement, stream) {
-        this.pushBuffer(statement.parse(stream));
-    }
-});
-
-Ext.apply(Parser.Statement, {
-    factory: function(type, properties, isInverted) {
-        var capitalizedType, statementClass, statement;
-
-        if (Ext.isObject(type)) {
-            properties = type.properties;
-            isInverted = type.isInverted;
-            type = type.type;
-        }
-
-        type = type.toLowerCase();
-        capitalizedType = type.charAt(0).toUpperCase() + type.slice(1);
-
-        Loader.require('Parser.Statement.' + capitalizedType, false);
-        statementClass = Parser.Statement[capitalizedType];
-
-        if (!statementClass) {
-            // Not supported
-            Logger.log("[NOTICE][Parser.Statement.factory] Statement type '" + type + "' is currently not supported, ignored");
-            return false;
-        }
-
-        statement = new statementClass(properties, isInverted);
-        statement.type = type;
-
-        return statement;
-    }
-});
diff --git a/js/lib/JSBuilder/src/Parser/Statement/Debug.js b/js/lib/JSBuilder/src/Parser/Statement/Debug.js
deleted file mode 100644
index e58c32f..0000000
--- a/js/lib/JSBuilder/src/Parser/Statement/Debug.js
+++ /dev/null
@@ -1,38 +0,0 @@
-Loader.require('Parser.Statement.If');
-
-(function() {
-
-var priorities = {
-    error: 3,
-    warn: 2,
-    info: 1
-};
-
-var Debug = Parser.Statement.Debug = Ext.extend(Parser.Statement.If, {
-    constructor: function() {
-        var priority, name;
-
-        Debug.superclass.constructor.apply(this, arguments);
-
-        this.setProperty('debug', true);
-
-        for (name in priorities) {
-            if (priorities.hasOwnProperty(name)) {
-                if (this.getProperty(name)) {
-                    priority = priorities[name];
-                    this.removeProperty(name);
-                    break;
-                }
-            }
-        }
-
-        if (!priority) {
-            priority = 1;
-        }
-
-        this.setProperty('debugLevel', '<=' + priority);
-    }
-});
-
-
-})();
diff --git a/js/lib/JSBuilder/src/Parser/Statement/Deprecated.js b/js/lib/JSBuilder/src/Parser/Statement/Deprecated.js
deleted file mode 100644
index 5fc94b4..0000000
--- a/js/lib/JSBuilder/src/Parser/Statement/Deprecated.js
+++ /dev/null
@@ -1,14 +0,0 @@
-Loader.require('Parser.Statement.If');
-
-Parser.Statement.Deprecated = Ext.extend(Parser.Statement.If, {
-    constructor: function() {
-        Parser.Statement.Deprecated.superclass.constructor.apply(this, arguments);
-
-        if (this.getProperty('since') === null) {
-            throw new Error("[Parser.Statement.Deprecated] 'since' property is required for deprecated statement");
-        }
-
-        this.setProperty('minVersion', '<=' + this.getProperty('since'));
-        this.removeProperty('since');
-    }
-});
diff --git a/js/lib/JSBuilder/src/Parser/Statement/Else.js b/js/lib/JSBuilder/src/Parser/Statement/Else.js
deleted file mode 100644
index ea27103..0000000
--- a/js/lib/JSBuilder/src/Parser/Statement/Else.js
+++ /dev/null
@@ -1,10 +0,0 @@
-Parser.Statement.Else = Ext.extend(Parser.Statement, {
-    isEnd: function(line, stream) {
-        if (this.parent.isEnd.apply(this.parent, arguments)) {
-            stream.goBack(line.length + 1);
-            return true;
-        }
-
-        return false;
-    }
-});
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Parser/Statement/Elseif.js b/js/lib/JSBuilder/src/Parser/Statement/Elseif.js
deleted file mode 100644
index c791121..0000000
--- a/js/lib/JSBuilder/src/Parser/Statement/Elseif.js
+++ /dev/null
@@ -1,22 +0,0 @@
-Parser.Statement.Elseif = Ext.extend(Parser.Statement.If, {
-    isEnd: function(line, stream) {
-        var statement,
-            isEnd = false;
-
-        statement = Parser.parseStatement(line);
-
-        if (statement) {
-            if (statement.type === 'elseif' || statement.type === 'else') {
-                isEnd = true;
-            }
-        } else if (this.parent.isEnd.apply(this.parent, arguments)) {
-            isEnd = true;
-        }
-
-        if (isEnd) {
-            stream.goBack(line.length + 1);
-        }
-
-        return isEnd;
-    }
-});
diff --git a/js/lib/JSBuilder/src/Parser/Statement/If.js b/js/lib/JSBuilder/src/Parser/Statement/If.js
deleted file mode 100644
index 544b52b..0000000
--- a/js/lib/JSBuilder/src/Parser/Statement/If.js
+++ /dev/null
@@ -1,57 +0,0 @@
-Parser.Statement.If = Ext.extend(Parser.Statement, {
-    satisfied: false,
-
-    evaluate: function() {
-        var ret = true, n;
-
-        for (n in this.properties) {
-            if (!Parser.evaluate(n, this.properties[n])) {
-                ret = false;
-                break;
-            }
-        }
-
-        return (this.isInverted ? !ret : ret);
-    },
-
-    parse: function(stream) {
-        if (this.evaluate()) {
-            this.satisfied = true;
-        }
-
-        Parser.Statement.If.superclass.parse.apply(this, arguments);
-
-        if (!this.satisfied) {
-            return '';
-        }
-
-        return this.buffer;
-    },
-
-    onSubStatement: function(statement, stream) {
-        var parsed = statement.parse(stream),
-            satisfied = false;
-
-        if (statement.type === 'elseif') {
-            if (!this.satisfied) {
-                if (statement.evaluate()) {
-                    this.satisfied = true;
-                    satisfied = true;
-                }
-            }
-        } else if (statement.type === 'else') {
-            if (!this.satisfied) {
-                this.satisfied = true;
-                satisfied = true;
-            }
-        } else {
-            this.pushBuffer(parsed);
-            return;
-        }
-
-        if (satisfied) {
-            this.resetBuffer();
-            this.pushBuffer(parsed);
-        }
-    }
-});
diff --git a/js/lib/JSBuilder/src/Parser/Statement/Uncomment.js b/js/lib/JSBuilder/src/Parser/Statement/Uncomment.js
deleted file mode 100644
index fa222ac..0000000
--- a/js/lib/JSBuilder/src/Parser/Statement/Uncomment.js
+++ /dev/null
@@ -1,17 +0,0 @@
-Parser.Statement.Uncomment = Ext.extend(Parser.Statement, {
-    parse: function(stream) {
-        var line;
-
-        while (!stream.eof) {
-            line = stream.readLine();
-
-            if (this.isEnd(line, stream)) {
-                break;
-            }
-
-            this.pushBuffer(line.replace(/^([\s\t]*)\/\//, "$1"), !stream.eof);
-        }
-
-        return this.buffer;
-    }
-});
diff --git a/js/lib/JSBuilder/src/Platform.js b/js/lib/JSBuilder/src/Platform.js
deleted file mode 100644
index 4e569fd..0000000
--- a/js/lib/JSBuilder/src/Platform.js
+++ /dev/null
@@ -1,4 +0,0 @@
-Platform = {
-    isUnix: Fs.sep == '/',
-    isWindows: Fs.sep != '/'
-};
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/Project.js b/js/lib/JSBuilder/src/Project.js
deleted file mode 100644
index c6dc4e1..0000000
--- a/js/lib/JSBuilder/src/Project.js
+++ /dev/null
@@ -1,217 +0,0 @@
-Project = Ext.extend(Object, {
-    constructor : function(projectFile, builder) {
-        var fileName = projectFile.split(/\\|\//i).pop(),
-            dir = projectFile.replace(fileName, ''),
-            contents, config;
-
-        if (!Fs.exists(projectFile)) {
-            throw 'Project file doesn\'t exist';
-        }
-
-        contents = Fs.readFile(projectFile);
-        try {
-            config = JSON.parse(contents);
-        }
-        catch (e) {
-            throw 'The JSB file is not valid JSON.\n' + e.toString();
-        }
-
-        Ext.apply(config, {
-            targets: config.targets || config.pkgs || [],
-            name: config.projectName,
-            license: config.licenseText,
-            jsbDir: Fs.getFullPath(dir),
-            jsbFile: fileName,
-            packages: config.packages || [],
-            builds: config.builds || [],
-            // If the JSB file contains a deployDir property, append that to the -d deployDir
-            deployDir: builder.get('deployDir') + Fs.sep + (config.deployDir || ''),
-            resources: config.resources || []
-        });
-
-        this.builder = builder;
-        this.config = config;
-
-        this.parseTargets();
-    },
-
-    parseTargets : function() {
-        // Split targets up into packages and builds for backwards compatibility
-        this.get('targets').forEach(function(item) {
-            if (item.packages) {
-                this.get('builds').push(item);
-            }
-            else {
-                this.get('packages').push(item);
-            }
-        }, this);
-
-        // Convert each package config object into an actual Package instance
-        this.set('packages', this.get('packages').map(function(item) {
-            return new Package(item, this);
-        }, this));
-
-        // Convert each build config object into an actual Build instance
-        this.set('builds', this.get('builds').map(function(item) {
-            return new Build(item, this);
-        }, this));
-    },
-
-    getPackageById : function(id) {
-        var ret = false;
-        this.get('packages').forEach(function(pkg) {
-            if (pkg.get('id') == id) {
-                ret = pkg;
-            }
-        });
-        return ret;
-    },
-
-    /**
-     * Creates the directory we are going to deploy to.
-     */
-    makeDeployDir: function() {
-        var project = this.project,
-            deployDir = Fs.mkdir(this.get('deployDir'));
-
-        this.set('deployDir', deployDir);
-
-        if (this.get('verbose')) {
-            this.log('Created the deploy directory ' + deployDir);
-        }
-    },
-
-    build : function() {
-        this.makeDeployDir();
-        this.createPackages();
-        this.createBuilds();
-        this.copyResources();
-
-        if (this.builder.get('verbose')) {
-            Logger.log('');
-        }
-        Logger.log('Done building!\n');
-    },
-
-    createPackages : function() {
-        this.get('packages').forEach(function(pkg) {
-            pkg.create();
-        });
-    },
-
-    createBuilds : function() {
-        this.get('builds').forEach(function(build) {
-            build.create();
-        });
-    },
-
-    copyResources : function() {
-        if (this.builder.get('verbose')) {
-            Logger.log('');
-        }
-
-        Logger.log('Copy resources...');
-
-        this.get('resources').forEach(function(resource) {
-            var filters = resource.filters,
-                srcDir = this.get('jsbDir') + Fs.sep + resource.src,
-                dest = resource.dest || resource.src;
-
-            dest = dest || '';
-            dest = this.get('deployDir') + Fs.sep + dest;
-
-            // TODO: Implement filters
-            if (this.builder.get('verbose')) {
-                Logger.log('  + ' + resource.src + ' -> ' + dest);
-            }
-
-            Fs.copy(srcDir, dest);
-        }, this);
-    },
-
-    get : function(key) {
-        return this.config[key] || false;
-    },
-
-    set : function(key, value, ifNotExists) {
-        if (ifNotExists && this.get(key) !== false) {
-            return;
-        }
-        this.config[key] = value;
-    },
-
-    compressTarget : function(target) {
-        if (this.builder.get('nocompress') || !target.get('compress')) {
-            return;
-        }
-
-        Logger.log('  * Compress and obfuscate ' + target.get('target') + '...');
-
-        var destination = target.get('targetPath'),
-            source = destination + '-temp-' + Date.now() * Math.random();
-            system.move(destination, source),
-            command = this.getCompressor() + '-o ' + destination + ' ' + source;
-
-        Cmd.execute(command);
-
-        Fs.remove(source);
-    },
-
-    getCompressor : function() {
-        return 'java -jar ' + system.script.replace(Fs.getPath('bin/JSBuilder.js'), '') + Fs.getPath('ycompressor/ycompressor.jar') + ' --type js ';
-    },
-
-    getSourceFiles: function() {
-        Logger.log('<!--');
-        Logger.log('    Source files');
-        Logger.log('-->');
-        Logger.log('');
-
-        this.get('builds').forEach(function(build) {
-            if (build.get('packages')) {
-                Logger.log('<!-- build: ' + build.get('name') + ' -->');
-
-                build.get('packages').forEach(function(pkg) {
-                    pkg = build.project.getPackageById(pkg);
-
-                    Logger.log('<!-- package: ' + pkg.get('name') + ' -->');
-
-                    pkg.get('files').forEach(function(file) {
-                        Logger.log('<script type="text/javascript" src="../../' + file.path + file.name + '"></script>');
-                    });
-
-                    Logger.log('');
-                });
-
-                Logger.log('');
-            };
-        });
-    },
-
-    getSpecFiles: function() {
-        Logger.log('<!--');
-        Logger.log('    Spec files');
-        Logger.log('-->');
-        Logger.log('');
-
-        this.get('builds').forEach(function(build) {
-            if (build.get('packages')) {
-                Logger.log('<!-- build: ' + build.get('name') + ' -->');
-
-                build.get('packages').forEach(function(pkg) {
-                    pkg = build.project.getPackageById(pkg);
-
-                    Logger.log('<!-- package: ' + pkg.get('name') + ' -->');
-
-                    pkg.get('files').forEach(function(file) {
-                        Logger.log('<script type="text/javascript" src="spec/' + file.path.replace('src/', '') + file.name + '"></script>');
-                    });
-
-                    Logger.log('');
-                });
-
-                Logger.log('');
-            };
-        });
-    }
-});
diff --git a/js/lib/JSBuilder/src/Target.js b/js/lib/JSBuilder/src/Target.js
deleted file mode 100644
index 1562b58..0000000
--- a/js/lib/JSBuilder/src/Target.js
+++ /dev/null
@@ -1,216 +0,0 @@
-Target = Ext.extend(Object, {
-    constructor: function(config, project) {
-        this.config = config || {};
-        this.project = project;
-    },
-
-    create: function() {
-        this.parseTarget();
-
-        var project = this.project,
-            builder = project.builder,
-            verbose = builder.get('verbose'),
-            file;
-
-        if (verbose) {
-            Logger.log('\nCreating the "' + this.get('name') + '" target as "' + this.get('target') + '"');
-        }
-
-        // Open the file stream
-        file = new Stream(this.get('targetPath'), 'w');
-
-        this.onCreate(file);
-        this.writeIncludes(file);
-        this.onAfterWriteIncludes(file);
-
-        // Close the target file
-        file.close();
-
-        this.afterCreate();
-    },
-
-    afterCreate: function() {
-        this.project.compressTarget(this);
-
-        var filePath = this.get('targetPath');
-        var license = (this.project.get('license')) ? "/*\n" + this.project.get('license') + "\n*/\n" : '';
-
-        if (license) {
-            var content = Fs.readFile(filePath);
-
-            if (content.substring(0, license.length) !== license) {
-                Fs.writeFile(filePath, license + content);
-            }
-        }
-    },
-
-    onAfterWriteIncludes: function(file) {
-        var namespaceRewrites = this.get('namespaceRewrites'),
-            settings = this.get('settings'),
-            suffix = '})(',
-            names = [];
-
-        if (namespaceRewrites) {
-            namespaceRewrites.forEach(function(rewrite) {
-                names.push('this.' + rewrite.to + ' || (this.' + rewrite.to + ' = {})');
-            });
-
-            suffix += names.join(', ');
-            suffix += ');';
-
-            file.writeln(suffix);
-        }
-    },
-
-    onCreate: function(file) {
-        var namespaceRewrites = this.get('namespaceRewrites'),
-            prefix = '(function(',
-            settings = this.get('settings'),
-            names = [];
-
-        if (namespaceRewrites) {
-            namespaceRewrites.forEach(function(rewrite) {
-                names.push(rewrite.from);
-            });
-
-            prefix += names.join(', ');
-            prefix += '){';
-
-            if (settings) {
-                prefix += "\n";
-                prefix +=  ["if (typeof Ext === 'undefined') {",
-                                "this.Ext = {};",
-                            "}",
-                            "",
-                            "Ext.buildSettings = " + JSON.stringify(settings) + ";"
-                           ].join("\n");
-            }
-
-
-            file.writeln(prefix);
-        }
-    },
-
-    parseTarget: function() {
-        if (this.parsed) {
-            return;
-        }
-
-        // Backwards compatibility with JSB2
-        var target = this.get('target') || this.get('file') || this.getDefaultTarget(),
-            basePath = this.project.get('deployDir') + Fs.sep,
-            dir;
-
-        target = target.replace(/\//g, Fs.sep);
-
-        if (target.indexOf('.js') !== -1) {
-            target = target.replace('.js', '');
-//            if (this.get('debug')) {
-//                target += this.project.builder.get('debugSuffix');
-//            }
-            target += '.js';
-        }
-
-        this.set('target', target);
-
-        // If the target is a path, then create the needed folders
-        if (target.indexOf(Fs.sep) !== -1) {
-            dir = target.substr(0, target.lastIndexOf(Fs.sep));
-            target = target.replace(dir, '').substr(1);
-            target = Fs.mkdir(basePath + dir) + Fs.sep + target;
-        }
-        else {
-            target = basePath + target;
-        }
-
-        this.set('targetPath', target);
-        this.parsed = true;
-    },
-
-    writeIncludes: function(file) {
-        var project = this.project,
-            verbose = project.builder.get('verbose'),
-            includes = this.get('files') || this.get('fileIncludes') || [],
-            jsbDir = project.get('jsbDir') + Fs.sep;
-
-        if (verbose && includes.length) {
-            Logger.log('  - ' + includes.length + ' file(s) included in this target.');
-        }
-
-        // Loop over all file includes, read the contents, and write
-        // it to our target file
-        includes.forEach(function(include) {
-            var path = this.getIncludePath(include),
-                content = '',
-                filesStream, files;
-
-            if (verbose) {
-                Logger.log('    + ' + path);
-            }
-
-
-            if (!Fs.exists(jsbDir + path)) {
-                if (Platform.isUnix) {
-                    filesStream = new Stream('exec://ls -a ' + jsbDir + path);
-                    files = filesStream.readFile().split('\n');
-                    filesStream.close();
-                    files.forEach(function(filePath) {
-                        if (!Ext.isEmpty(filePath)) {
-                            include = new Stream(filePath);
-                            content += include.readFile() + '\n';
-                            include.close();
-                        }
-                    });
-                }
-            }
-            else {
-                content = this.getContent(jsbDir + path);
-            }
-
-
-
-            file.writeln(content);
-        }, this);
-    },
-
-
-    getContent: function(file, callNum) {
-        /**
-         * This function should pretty much never fail since we already know the file exists.
-         * However in Windows it seems to randomly omit files when building because it can't
-         * open the stream, which causes the build to break. Since we know the file is there,
-         * we'll just re-request it until we get it. While stupid, this makes it reliable.
-         */
-
-        var content = '',
-            stream;
-
-        callNum = callNum || 0;
-        try {
-            stream = new Stream(file);
-            content = stream.readFile();
-            stream.close();
-        } catch (e) {
-            if (Platform.isWindows && callNum < 5) {
-                return this.getContent(file, callNum + 1);
-            }
-        }
-        return content;
-    },
-
-    getIncludePath : function(include) {
-        return include.path.replace(/\//g, Fs.sep) + (include.name || include.text || '');
-    },
-
-
-    get: function(key) {
-        return this.config[key] || false;
-    },
-
-    set: function(key, value, ifNotExists) {
-        if (ifNotExists && this.get(key) !== false) {
-            return;
-        }
-        this.config[key] = value;
-    }
-});
diff --git a/js/lib/JSBuilder/src/Template.js b/js/lib/JSBuilder/src/Template.js
deleted file mode 100644
index 9bb5ff1..0000000
--- a/js/lib/JSBuilder/src/Template.js
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- * @class Ext.Template
- * <p>Represents an HTML fragment template. Templates may be {@link #compile precompiled}
- * for greater performance.</p>
- * <p>For example usage {@link #Template see the constructor}.</p>
- *
- * @constructor
- * An instance of this class may be created by passing to the constructor either
- * a single argument, or multiple arguments:
- * <div class="mdetail-params"><ul>
- * <li><b>single argument</b> : String/Array
- * <div class="sub-desc">
- * The single argument may be either a String or an Array:<ul>
- * <li><tt>String</tt> : </li><pre><code>
-var t = new Ext.Template("&lt;div>Hello {0}.&lt;/div>");
-t.{@link #append}('some-element', ['foo']);
-   </code></pre>
- * <li><tt>Array</tt> : </li>
- * An Array will be combined with <code>join('')</code>.
-<pre><code>
-var t = new Ext.Template([
-    '&lt;div name="{id}"&gt;',
-        '&lt;span class="{cls}"&gt;{name:trim} {value:ellipsis(10)}&lt;/span&gt;',
-    '&lt;/div&gt;',
-]);
-t.{@link #compile}();
-t.{@link #append}('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
-   </code></pre>
- * </ul></div></li>
- * <li><b>multiple arguments</b> : String, Object, Array, ...
- * <div class="sub-desc">
- * Multiple arguments will be combined with <code>join('')</code>.
- * <pre><code>
-var t = new Ext.Template(
-    '&lt;div name="{id}"&gt;',
-        '&lt;span class="{cls}"&gt;{name} {value}&lt;/span&gt;',
-    '&lt;/div&gt;',
-    // a configuration object:
-    {
-        compiled: true,      // {@link #compile} immediately
-    }
-);
-   </code></pre>
- * <p><b>Notes</b>:</p>
- * <div class="mdetail-params"><ul>
- * <li>Formatting and <code>disableFormats</code> are not applicable for Sencha Touch.</li>
- * </ul></div>
- * </div></li>
- * </ul></div>
- * @param {Mixed} config
- */
-Ext.Template = function(html) {
-    var me = this,
-        a = arguments,
-        buf = [];
-
-    if (Ext.isArray(html)) {
-        html = html.join("");
-    }
-    else if (a.length > 1) {
-        Ext.each(a, function(v) {
-            if (Ext.isObject(v)) {
-                Ext.apply(me, v);
-            } else {
-                buf.push(v);
-            }
-        });
-        html = buf.join('');
-    }
-
-    // @private
-    me.html = html;
-    
-    if (me.compiled) {
-        me.compile();
-    }
-};
-
-Ext.Template.prototype = {
-    isTemplate: true,
-    
-    re: /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
-    argsRe: /^\s*['"](.*)["']\s*$/,
-    compileARe: /\\/g,
-    compileBRe: /(\r\n|\n)/g,
-    compileCRe: /'/g,
-    
-    /**
-     * @cfg {Boolean} disableFormats true to disable format functions in the template. If the template doesn't contain format functions, setting 
-     * disableFormats to true will reduce apply time (defaults to false)
-     */
-    disableFormats: false,
-    
-    /**
-     * Returns an HTML fragment of this template with the specified values applied.
-     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
-     * @return {String} The HTML fragment
-     * @hide repeat doc
-     */
-    applyTemplate: function(values) {
-        var me = this,
-            useF = me.disableFormats !== true,
-            fm = Ext.util.Format,
-            tpl = me,
-            re,
-            i,
-            len;
-
-        if (me.compiled) {
-            return me.compiled(values);
-        }
-        function fn(m, name, format, args) {
-            if (format && useF) {
-                if (format.substr(0, 5) == "this.") {
-                    return tpl.call(format.substr(5), values[name], values);
-                }
-                else {
-                    if (args) {
-                        // quoted values are required for strings in compiled templates,
-                        // but for non compiled we need to strip them
-                        // quoted reversed for jsmin
-                        re = me.argsRe;
-                        args = args.split(',');
-                        for (i = 0, len = args.length; i < len; i++) {
-                            args[i] = args[i].replace(re, "$1");
-                        }
-                        args = [values[name]].concat(args);
-                    }
-                    else {
-                        args = [values[name]];
-                    }
-                    return fm[format].apply(fm, args);
-                }
-            }
-            else {
-                return values[name] !== undefined ? values[name] : "";
-            }
-        }
-        return me.html.replace(me.re, fn);
-    },
-
-    /**
-     * Sets the HTML used as the template and optionally compiles it.
-     * @param {String} html
-     * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
-     * @return {Ext.Template} this
-     */
-    set: function(html, compile) {
-        var me = this;
-        me.html = html;
-        me.compiled = null;
-        return compile ? me.compile() : me;
-    },
-
-    /**
-     * Compiles the template into an internal function, eliminating the RegEx overhead.
-     * @return {Ext.Template} this
-     * @hide repeat doc
-     */
-    compile: function() {
-        var me = this,
-            fm = Ext.util.Format,
-            useF = me.disableFormats !== true,
-            body;
-
-        function fn(m, name, format, args) {
-            if (format && useF) {
-                args = args ? ',' + args: "";
-                if (format.substr(0, 5) != "this.") {
-                    format = "fm." + format + '(';
-                }
-                else {
-                    format = 'this.call("' + format.substr(5) + '", ';
-                    args = ", values";
-                }
-            }
-            else {
-                args = '';
-                format = "(values['" + name + "'] == undefined ? '' : ";
-            }
-            return "'," + format + "values['" + name + "']" + args + ") ,'";
-        }
-
-
-        body = ["this.compiled = function(values){ return ['"];
-        body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
-        body.push("'].join('');};");
-        body = body.join('');
-        eval(body);
-        return me;
-    },
-
-    /**
-     * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
-     * @param {Mixed} el The context element
-     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
-     * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
-     * @return {HTMLElement/Ext.Element} The new node or Element
-     */
-    insertFirst: function(el, values, returnElement) {
-        return this.doInsert('afterBegin', el, values, returnElement);
-    },
-
-    /**
-     * Applies the supplied values to the template and inserts the new node(s) before el.
-     * @param {Mixed} el The context element
-     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
-     * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
-     * @return {HTMLElement/Ext.Element} The new node or Element
-     */
-    insertBefore: function(el, values, returnElement) {
-        return this.doInsert('beforeBegin', el, values, returnElement);
-    },
-
-    /**
-     * Applies the supplied values to the template and inserts the new node(s) after el.
-     * @param {Mixed} el The context element
-     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
-     * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
-     * @return {HTMLElement/Ext.Element} The new node or Element
-     */
-    insertAfter: function(el, values, returnElement) {
-        return this.doInsert('afterEnd', el, values, returnElement);
-    },
-
-    /**
-     * Applies the supplied <code>values</code> to the template and appends
-     * the new node(s) to the specified <code>el</code>.
-     * <p>For example usage {@link #Template see the constructor}.</p>
-     * @param {Mixed} el The context element
-     * @param {Object/Array} values
-     * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
-     * or an object (i.e. <code>{foo: 'bar'}</code>).
-     * @param {Boolean} returnElement (optional) true to return an Ext.Element (defaults to undefined)
-     * @return {HTMLElement/Ext.Element} The new node or Element
-     */
-    append: function(el, values, returnElement) {
-        return this.doInsert('beforeEnd', el, values, returnElement);
-    },
-
-    doInsert: function(where, el, values, returnEl) {
-        el = Ext.getDom(el);
-        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
-        return returnEl ? Ext.get(newNode, true) : newNode;
-    },
-
-    /**
-     * Applies the supplied values to the template and overwrites the content of el with the new node(s).
-     * @param {Mixed} el The context element
-     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
-     * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
-     * @return {HTMLElement/Ext.Element} The new node or Element
-     */
-    overwrite: function(el, values, returnElement) {
-        el = Ext.getDom(el);
-        el.innerHTML = this.applyTemplate(values);
-        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
-    },
-
-    // private function used to call members
-    call: function(fnName, value, allValues) {
-        return this[fnName](value, allValues);
-    }
-};
-/**
- * Alias for {@link #applyTemplate}
- * Returns an HTML fragment of this template with the specified <code>values</code> applied.
- * @param {Object/Array} values
- * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
- * or an object (i.e. <code>{foo: 'bar'}</code>).
- * @return {String} The HTML fragment
- * @member Ext.Template
- * @method apply
- */
-Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/XTemplate.js b/js/lib/JSBuilder/src/XTemplate.js
deleted file mode 100644
index 3846f76..0000000
--- a/js/lib/JSBuilder/src/XTemplate.js
+++ /dev/null
@@ -1,469 +0,0 @@
-/**
- * @class Ext.XTemplate
- * @extends Ext.Template
- * <p>A template class that supports advanced functionality like:<div class="mdetail-params"><ul>
- * <li>Autofilling arrays using templates and sub-templates</li>
- * <li>Conditional processing with basic comparison operators</li>
- * <li>Basic math function support</li>
- * <li>Execute arbitrary inline code with special built-in template variables</li>
- * <li>Custom member functions</li>
- * <li>Many special tags and built-in operators that aren't defined as part of
- * the API, but are supported in the templates that can be created</li>
- * </ul></div></p>
- * <p>XTemplate provides the templating mechanism built into:<div class="mdetail-params"><ul>
- * <li>{@link Ext.view.View}</li>
- * </ul></div></p>
- *
- * <p>For example usage {@link #XTemplate see the constructor}.</p>
- *
- * @constructor
- * The {@link Ext.Template#Template Ext.Template constructor} describes
- * the acceptable parameters to pass to the constructor. The following
- * examples demonstrate all of the supported features.</p>
- *
- * <div class="mdetail-params"><ul>
- *
- * <li><b><u>Sample Data</u></b>
- * <div class="sub-desc">
- * <p>This is the data object used for reference in each code example:</p>
- * <pre><code>
-var data = {
-    name: 'Tommy Maintz',
-    title: 'Lead Developer',
-    company: 'Sencha Inc.',
-    email: 'tommy@sencha.com',
-    address: '5 Cups Drive',
-    city: 'Palo Alto',
-    state: 'CA',
-    zip: '44102',
-    drinks: ['Coffee', 'Soda', 'Water'],
-    kids: [{
-        name: 'Joshua',
-        age:3
-    },{
-        name: 'Matthew',
-        age:2
-    },{
-        name: 'Solomon',
-        age:0
-    }]
-};
-   </code></pre>
- * </div>
- * </li>
- *
- *
- * <li><b><u>Auto filling of arrays</u></b>
- * <div class="sub-desc">
- * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>for</tt></b> operator are used
- * to process the provided data object:
- * <ul>
- * <li>If the value specified in <tt>for</tt> is an array, it will auto-fill,
- * repeating the template block inside the <tt>tpl</tt> tag for each item in the
- * array.</li>
- * <li>If <tt>for="."</tt> is specified, the data object provided is examined.</li>
- * <li>While processing an array, the special variable <tt>{#}</tt>
- * will provide the current array index + 1 (starts at 1, not 0).</li>
- * </ul>
- * </p>
- * <pre><code>
-&lt;tpl <b>for</b>=".">...&lt;/tpl>       // loop through array at root node
-&lt;tpl <b>for</b>="foo">...&lt;/tpl>     // loop through array at foo node
-&lt;tpl <b>for</b>="foo.bar">...&lt;/tpl> // loop through array at foo.bar node
-   </code></pre>
- * Using the sample data above:
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Kids: ',
-    '&lt;tpl <b>for</b>=".">',       // process the data.kids node
-        '&lt;p>{#}. {name}&lt;/p>',  // use current array index to autonumber
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
-   </code></pre>
- * <p>An example illustrating how the <b><tt>for</tt></b> property can be leveraged
- * to access specified members of the provided data object to populate the template:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Title: {title}&lt;/p>',
-    '&lt;p>Company: {company}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl <b>for="kids"</b>>',     // interrogate the kids property within the data
-        '&lt;p>{name}&lt;/p>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);  // pass the root node of the data object
-   </code></pre>
- * <p>Flat arrays that contain values (and not objects) can be auto-rendered
- * using the special <b><tt>{.}</tt></b> variable inside a loop.  This variable
- * will represent the value of the array at the current index:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>{name}\&#39;s favorite beverages:&lt;/p>',
-    '&lt;tpl for="drinks">',
-       '&lt;div> - {.}&lt;/div>',
-    '&lt;/tpl>'
-);
-tpl.overwrite(panel.body, data);
-   </code></pre>
- * <p>When processing a sub-template, for example while looping through a child array,
- * you can access the parent object's members via the <b><tt>parent</tt></b> object:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-        '&lt;tpl if="age &amp;gt; 1">',
-            '&lt;p>{name}&lt;/p>',
-            '&lt;p>Dad: {<b>parent</b>.name}&lt;/p>',
-        '&lt;/tpl>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);
-   </code></pre>
- * </div>
- * </li>
- *
- *
- * <li><b><u>Conditional processing with basic comparison operators</u></b>
- * <div class="sub-desc">
- * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>if</tt></b> operator are used
- * to provide conditional checks for deciding whether or not to render specific
- * parts of the template. Notes:<div class="sub-desc"><ul>
- * <li>Double quotes must be encoded if used within the conditional</li>
- * <li>There is no <tt>else</tt> operator &mdash; if needed, two opposite
- * <tt>if</tt> statements should be used.</li>
- * </ul></div>
- * <pre><code>
-&lt;tpl if="age &gt; 1 &amp;&amp; age &lt; 10">Child&lt;/tpl>
-&lt;tpl if="age >= 10 && age < 18">Teenager&lt;/tpl>
-&lt;tpl <b>if</b>="this.isGirl(name)">...&lt;/tpl>
-&lt;tpl <b>if</b>="id==\'download\'">...&lt;/tpl>
-&lt;tpl <b>if</b>="needsIcon">&lt;img src="{icon}" class="{iconCls}"/>&lt;/tpl>
-// no good:
-&lt;tpl if="name == "Tommy"">Hello&lt;/tpl>
-// encode &#34; if it is part of the condition, e.g.
-&lt;tpl if="name == &#38;quot;Tommy&#38;quot;">Hello&lt;/tpl>
- * </code></pre>
- * Using the sample data above:
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-        '&lt;tpl if="age &amp;gt; 1">',
-            '&lt;p>{name}&lt;/p>',
-        '&lt;/tpl>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);
-   </code></pre>
- * </div>
- * </li>
- *
- *
- * <li><b><u>Basic math support</u></b>
- * <div class="sub-desc">
- * <p>The following basic math operators may be applied directly on numeric
- * data values:</p><pre>
- * + - * /
- * </pre>
- * For example:
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-        '&lt;tpl if="age &amp;gt; 1">',  // <-- Note that the &gt; is encoded
-            '&lt;p>{#}: {name}&lt;/p>',  // <-- Auto-number each item
-            '&lt;p>In 5 Years: {age+5}&lt;/p>',  // <-- Basic math
-            '&lt;p>Dad: {[parent.name]}&lt;/p>',
-        '&lt;/tpl>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);
-   </code></pre>
- * </div>
- * </li>
- *
- *
- * <li><b><u>Execute arbitrary inline code with special built-in template variables</u></b>
- * <div class="sub-desc">
- * <p>Anything between <code>{[ ... ]}</code> is considered code to be executed
- * in the scope of the template. There are some special variables available in that code:
- * <ul>
- * <li><b><tt>values</tt></b>: The values in the current scope. If you are using
- * scope changing sub-templates, you can change what <tt>values</tt> is.</li>
- * <li><b><tt>parent</tt></b>: The scope (values) of the ancestor template.</li>
- * <li><b><tt>xindex</tt></b>: If you are in a looping template, the index of the
- * loop you are in (1-based).</li>
- * <li><b><tt>xcount</tt></b>: If you are in a looping template, the total length
- * of the array you are looping.</li>
- * </ul>
- * This example demonstrates basic row striping using an inline code block and the
- * <tt>xindex</tt> variable:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Company: {[values.company.toUpperCase() + ", " + values.title]}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-       '&lt;div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
-        '{name}',
-        '&lt;/div>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);
-   </code></pre>
- * </div>
- * </li>
- *
- * <li><b><u>Template member functions</u></b>
- * <div class="sub-desc">
- * <p>One or more member functions can be specified in a configuration
- * object passed into the XTemplate constructor for more complex processing:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-        '&lt;tpl if="this.isGirl(name)">',
-            '&lt;p>Girl: {name} - {age}&lt;/p>',
-        '&lt;/tpl>',
-        // use opposite if statement to simulate 'else' processing:
-        '&lt;tpl if="this.isGirl(name) == false">',
-            '&lt;p>Boy: {name} - {age}&lt;/p>',
-        '&lt;/tpl>',
-        '&lt;tpl if="this.isBaby(age)">',
-            '&lt;p>{name} is a baby!&lt;/p>',
-        '&lt;/tpl>',
-    '&lt;/tpl>&lt;/p>',
-    {
-        // XTemplate configuration:
-        compiled: true,
-        // member functions:
-        isGirl: function(name){
-            return name == 'Sara Grace';
-        },
-        isBaby: function(age){
-            return age < 1;
-        }
-    }
-);
-tpl.overwrite(panel.body, data);
-   </code></pre>
- * </div>
- * </li>
- *
- * </ul></div>
- *
- * @param {Mixed} config
- */
-Ext.XTemplate = function() {
-    Ext.XTemplate.superclass.constructor.apply(this, arguments);
-
-    var me = this,
-        s = me.html,
-        re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
-        nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
-        ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
-        execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
-        id = 0,
-        tpls = [],
-        VALUES = 'values',
-        PARENT = 'parent',
-        XINDEX = 'xindex',
-        XCOUNT = 'xcount',
-        RETURN = 'return ',
-        WITHVALUES = 'with(values){ ',
-        m,
-        m2,
-        m3,
-        m4,
-        exp,
-        fn,
-        exec,
-        name,
-        i;
-
-    s = ['<tpl>', s, '</tpl>'].join('');
-
-    while ((m = s.match(re))) {
-        m2 = m[0].match(nameRe);
-        m3 = m[0].match(ifRe);
-        m4 = m[0].match(execRe);
-        exp = null;
-        fn = null;
-        exec = null;
-        name = m2 && m2[1] ? m2[1] : '';
-
-        if (m3) {
-            exp = m3 && m3[1] ? m3[1] : null;
-            if (exp) {
-                fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + 'try{' + RETURN + (Ext.util.Format.htmlDecode(exp)) + ';}catch(e){return;}}');
-            }
-        }
-        if (m4) {
-            exp = m4 && m4[1] ? m4[1] : null;
-            if (exp) {
-                exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + (Ext.util.Format.htmlDecode(exp)) + '; }');
-            }
-        }
-        if (name) {
-            switch (name) {
-            case '.':
-                name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }');
-                break;
-            case '..':
-                name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }');
-                break;
-            default:
-                name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
-            }
-        }
-        tpls.push({
-            id: id,
-            target: name,
-            exec: exec,
-            test: fn,
-            body: m[1] || ''
-        });
-        s = s.replace(m[0], '{xtpl' + id + '}');
-        ++id;
-    }
-    for (i = tpls.length - 1; i >= 0; --i) {
-        me.compileTpl(tpls[i]);
-    }
-    me.master = tpls[tpls.length - 1];
-    me.tpls = tpls;
-};
-Ext.extend(Ext.XTemplate, Ext.Template, {
-    re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?\}/g,
-    
-    /**
-     * @cfg {RegExp} codeRe The regular expression used to match code variables (default: matches <tt>{[expression]}</tt>).
-     */
-    codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,
-
-    // @private
-    applySubTemplate: function(id, values, parent, xindex, xcount) {
-        var me = this,
-            len,
-            t = me.tpls[id],
-            vs,
-            buf = [],
-            i;
-        if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
-        (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
-            return '';
-        }
-        vs = t.target ? t.target.call(me, values, parent) : values;
-        len = vs.length;
-        parent = t.target ? values: parent;
-        if (t.target && Ext.isArray(vs)) {
-            for (i = 0, len = vs.length; i < len; i++) {
-                buf[buf.length] = t.compiled.call(me, vs[i], parent, i + 1, len);
-            }
-            return buf.join('');
-        }
-        return t.compiled.call(me, vs, parent, xindex, xcount);
-    },
-
-    // @private
-    compileTpl: function(tpl) {
-        var fm = Ext.util.Format,
-            useF = this.disableFormats !== true,
-            body;
-
-        function fn(m, name, format, args, math) {
-            var v;
-            // name is what is inside the {}
-
-            // Name begins with xtpl, use a Sub Template
-            if (name.substr(0, 4) == 'xtpl') {
-                return "',this.applySubTemplate(" + name.substr(4) + ", values, parent, xindex, xcount),'";
-            }
-            // name = "." - Just use the values object.
-            if (name == '.') {
-                v = 'typeof values == "string" ? values : ""';
-            }
-
-            // name = "#" - Use the xindex
-            else if (name == '#') {
-                v = 'xindex';
-            }
-
-            // name has a . in it - Use object literal notation, starting from values
-            else if (name.indexOf('.') != -1) {
-                v = "values."+name;
-            }
-
-            // name is a property of values
-            else {
-                v = "values['" + name + "']";
-            }
-            if (math) {
-                v = '(' + v + math + ')';
-            }
-            if (format && useF) {
-                args = args ? ',' + args: "";
-                if (format.substr(0, 5) != "this.") {
-                    format = "fm." + format + '(';
-                }
-                else {
-                    format = 'this.call("' + format.substr(5) + '", ';
-                    args = ", values";
-                }
-            }
-            else {
-                args = '';
-                format = "(" + v + " === undefined ? '' : ";
-            }
-            return "'," + format + v + args + "),'";
-        }
-
-        function codeFn(m, code) {
-            // Single quotes get escaped when the template is compiled, however we want to undo this when running code.
-            return "',(" + code.replace(/\\'/g, "'") + "),'";
-        }
-        body = ["tpl.compiled = function(values, parent, xindex, xcount){return ['"];
-        body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
-        body.push("'].join('');};");
-        body = body.join('');
-        eval(body);
-        return this;
-    },
-
-    /**
-      * Returns an HTML fragment of this template with the specified values applied.
-      * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
-      * @return {String} The HTML fragment
-      */
-    applyTemplate: function(values) {
-        return this.master.compiled.call(this, values, {}, 1, 1);
-    },
-
-    /**
-      * Compile the template to a function for optimized performance.  Recommended if the template will be used frequently.
-      * @return {Function} The compiled function
-      */
-    compile: function() {
-        return this;
-    }
-});
-/**
-  * Alias for {@link #applyTemplate}
-  * Returns an HTML fragment of this template with the specified values applied.
-  * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
-  * @return {String} The HTML fragment
-  * @member Ext.XTemplate
-  * @method apply
-  */
-Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
-
-if (Ext.util == undefined) {
-    Ext.util = {
-        Format: {}
-    };
-}
diff --git a/js/lib/JSBuilder/src/generators/app/Application.js b/js/lib/JSBuilder/src/generators/app/Application.js
deleted file mode 100644
index a552447..0000000
--- a/js/lib/JSBuilder/src/generators/app/Application.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * @class Ext.generator.Application
- * @extends Ext.generator.Base
- * Generates a full application
- */
-Ext.generator.Application = Ext.extend(Ext.generator.Base, {
-    generate: function() {
-        this.headline('Generating the ' + this.name + ' application');
-        
-        this.createDirectoryStructure();
-        this.copyApplicationFiles();
-        this.copyJasmine();
-        this.copyJSBuilder();
-    },
-    
-    /**
-     * Copies all files required for jasmine to the lib directory
-     */
-    copyJasmine: function() {
-        Logger.log("Copying dependencies...");
-        
-        this.mkdir('lib/jasmine', 'lib/sencha-jasmine', 'lib/sencha-jasmine/matchers');
-        
-        this.file('lib/jasmine/jasmine.css');
-        this.file('lib/jasmine/jasmine-html.js');
-        this.file('lib/jasmine/jasmine.js');
-        this.file('lib/jasmine/MIT.LICENSE');
-        
-        this.file('lib/sencha-jasmine/sencha-jasmine.css');
-        this.file('lib/sencha-jasmine/sencha-jasmine.js');
-        this.file('lib/sencha-jasmine/matchers/Model.js');
-        this.file('lib/sencha-jasmine/matchers/Controller.js');
-    },
-    
-    /**
-     * Copies all static application files to their destination directories
-     */
-    copyApplicationFiles: function() {
-        Logger.log("Copying files...");
-        
-        this.file('index.html');
-        this.file('app/routes.js');
-        this.file('public/resources/css/application.css');
-        this.file('test/unit/index.html');
-        this.file('test/unit/SpecOptions.js');
-        this.file('test/unit/.htaccess');
-        
-        this.template('Application', this, "app/app.js");
-        this.template('Viewport', this, "app/views/Viewport.js");
-    },
-    
-    /**
-     * Creates all of the necessary directories for a new app
-     */
-    createDirectoryStructure: function() {
-        Logger.log("Creating directories...");
-        this.mkdir(
-            'app', 'app/models', 'app/controllers', 'app/views', 'lib', 
-            'public', 'public/resources/images', 'public/resources/css',
-            'test', 'test/acceptance', 'test/fixtures', 'test/unit',
-            'test/unit/models', 'test/unit/controllers', 'test/unit/views'
-        );
-    },
-    
-    /**
-     * Copies all files/folders required for JSBuilder into the lib directory
-     */
-    copyJSBuilder: function() {
-        Logger.log("Copying JSBuilder");
-        this.mkdir("lib/JSBuilder", "lib/JSBuilder/bin");
-        this.file("lib/JSBuilder/bin/Dispatch.js");
-        
-        var builderDirs = ['bin', 'jsdb', 'src', 'tests', 'ycompressor'],
-            length      = builderDirs.length,
-            i;
-        
-        for (i = 0; i < length; i++) {
-            this.copyDir(builderDirs[i], "lib/JSBuilder");
-        }
-        
-        Logger.log("    Copying JSBuilder files");
-        this.file("sencha.sh");
-    },
-    
-    decodeArgs: function(args) {
-        this.name = args[0];
-        this.basePath = args[1] || this.name;
-    }
-});
-
-Ext.regGenerator('app', Ext.generator.Application);
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/app/routes.js b/js/lib/JSBuilder/src/generators/app/files/app/routes.js
deleted file mode 100644
index a2e621c..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/app/routes.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * The Router maps local urls to controller and action pairs. This is used primarily 
- * for providing history support without reloading the page. Example usage:
- * 
- * Connects http://myapp.com/#home to the index controller's overview action
- * map.connect("home", {controller: 'index', action: 'overview'});
- * 
- * Connects urls like "images/myImage.jpg" to the images controller's show action, passing
- * "myImage.jpg" as the "url" property of the options object each controller action receives
- * map.connect("images/:url", {controller: 'images', action: 'show'});
- */
-Ext.Router.draw(function(map) {
-    
-    
-    //These are default fallback routes and can be removed if not needed
-    map.connect(':controller/:action');
-    map.connect(':controller/:action/:id');
-});
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/index.html b/js/lib/JSBuilder/src/generators/app/files/index.html
deleted file mode 100644
index 2dbeb8d..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/index.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!doctype html>
-<html>
-<head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">	
-    <title>Sencha Application</title>
-    
-    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
-    <meta name="apple-mobile-web-app-capable" content="yes" />
-    <link rel="apple-touch-icon" href="apple-touch-icon.png" />
-    
-    <link rel="stylesheet" href="lib/touch/resources/css/ext-touch.css" type="text/css">
-    <link rel="stylesheet" href="public/resources/css/application.css" type="text/css">
-</head>
-<body>
-    <script type="text/javascript" src="lib/touch/ext-touch-debug.js"></script>
-    <script type="text/javascript" src="lib/touch/pkgs/platform/mvc.js"></script>
-    
-    <div id="sencha-app">
-        <script type="text/javascript" src="app/routes.js"></script>
-        <script type="text/javascript" src="app/app.js"></script>
-        
-        <!-- Place your view files here -->
-        <div id="sencha-views">
-            <script type="text/javascript" src="app/views/Viewport.js"></script>
-        </div>
-        
-        <!-- Place your model files here -->
-        <div id="sencha-models">
-            
-        </div>
-        
-        <!-- Place your controller files here -->
-        <div id="sencha-controllers">
-            
-        </div>
-    </div>
-</body>
-</html>
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/JSBuilder/bin/Dispatch.js b/js/lib/JSBuilder/src/generators/app/files/lib/JSBuilder/bin/Dispatch.js
deleted file mode 100644
index 69a987f..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/JSBuilder/bin/Dispatch.js
+++ /dev/null
@@ -1,37 +0,0 @@
-var JSBuilderPath = system.cwd + '/lib/JSBuilder/';
-
-load(JSBuilderPath + 'src/Loader.js');
-Loader.setBasePath(JSBuilderPath + 'src');
-
-Loader.require([
-    'Ext', 'Cmd', 'Filesystem', 'Platform', 'Cli', 'Logger', 'Project', 'Target', 'Package', 'Build'
-]);
-
-/**
- * @class Ext.CommandDispatcher
- * @extends Object
- * Dispaches to the relevant Cli subclass from the command line 'sencha' command. e.g.
- * sencha generate xyz is dispatched to whichever Ext.Cli subclass registered itself to
- * handler the 'generate' command (Ext.generator.Factory in this case).
- */
-Ext.CommandDispatcher = {
-    types: {},
-    
-    dispatch: function(module, args) {
-        new this.types[module]({args: args});
-    }
-};
-
-Ext.regDispatchable = function(name, constructor) {
-    Ext.CommandDispatcher.types[name] = constructor;
-};
-
-load('src/Generator.js');
-load('src/generators/app/Application.js');
-load('src/generators/controller/Controller.js');
-load('src/generators/model/Model.js');
-
-var args   = system.arguments,
-    module = args[0];
-
-Ext.CommandDispatcher.dispatch(module, args.slice(1));
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/MIT.LICENSE b/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/MIT.LICENSE
deleted file mode 100644
index 1eb9b49..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/MIT.LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2008-2010 Pivotal Labs
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine-html.js b/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine-html.js
deleted file mode 100644
index c59f2de..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine-html.js
+++ /dev/null
@@ -1,182 +0,0 @@
-jasmine.TrivialReporter = function(doc) {
-  this.document = doc || document;
-  this.suiteDivs = {};
-  this.logRunningSpecs = false;
-};
-
-jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
-  var el = document.createElement(type);
-
-  for (var i = 2; i < arguments.length; i++) {
-    var child = arguments[i];
-
-    if (typeof child === 'string') {
-      el.appendChild(document.createTextNode(child));
-    } else {
-      if (child) { el.appendChild(child); }
-    }
-  }
-
-  for (var attr in attrs) {
-    if (attr == "className") {
-      el[attr] = attrs[attr];
-    } else {
-      el.setAttribute(attr, attrs[attr]);
-    }
-  }
-
-  return el;
-};
-
-jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
-  var showPassed, showSkipped;
-
-  this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
-      this.createDom('div', { className: 'banner' },
-        this.createDom('div', { className: 'logo' },
-            this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
-            this.createDom('span', { className: 'version' }, runner.env.versionString())),
-        this.createDom('div', { className: 'options' },
-            "Show ",
-            showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
-            this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
-            showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
-            this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
-            )
-          ),
-
-      this.runnerDiv = this.createDom('div', { className: 'runner running' },
-          this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
-          this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
-          this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
-      );
-
-  this.document.body.appendChild(this.outerDiv);
-
-  var suites = runner.suites();
-  for (var i = 0; i < suites.length; i++) {
-    var suite = suites[i];
-    var suiteDiv = this.createDom('div', { className: 'suite' },
-        this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
-        this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
-    this.suiteDivs[suite.id] = suiteDiv;
-    var parentDiv = this.outerDiv;
-    if (suite.parentSuite) {
-      parentDiv = this.suiteDivs[suite.parentSuite.id];
-    }
-    parentDiv.appendChild(suiteDiv);
-  }
-
-  this.startedAt = new Date();
-
-  var self = this;
-  showPassed.onchange = function(evt) {
-    if (evt.target.checked) {
-      self.outerDiv.className += ' show-passed';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
-    }
-  };
-
-  showSkipped.onchange = function(evt) {
-    if (evt.target.checked) {
-      self.outerDiv.className += ' show-skipped';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
-    }
-  };
-};
-
-jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
-  var results = runner.results();
-  var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
-  this.runnerDiv.setAttribute("class", className);
-  //do it twice for IE
-  this.runnerDiv.setAttribute("className", className);
-  var specs = runner.specs();
-  var specCount = 0;
-  for (var i = 0; i < specs.length; i++) {
-    if (this.specFilter(specs[i])) {
-      specCount++;
-    }
-  }
-  var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
-  message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
-  this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
-
-  this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
-};
-
-jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
-  var results = suite.results();
-  var status = results.passed() ? 'passed' : 'failed';
-  if (results.totalCount == 0) { // todo: change this to check results.skipped
-    status = 'skipped';
-  }
-  this.suiteDivs[suite.id].className += " " + status;
-};
-
-jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
-  if (this.logRunningSpecs) {
-    this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
-  }
-};
-
-jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
-  var results = spec.results();
-  var status = results.passed() ? 'passed' : 'failed';
-  if (results.skipped) {
-    status = 'skipped';
-  }
-  var specDiv = this.createDom('div', { className: 'spec '  + status },
-      this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
-      this.createDom('a', {
-        className: 'description',
-        href: '?spec=' + encodeURIComponent(spec.getFullName()),
-        title: spec.getFullName()
-      }, spec.description));
-
-
-  var resultItems = results.getItems();
-  var messagesDiv = this.createDom('div', { className: 'messages' });
-  for (var i = 0; i < resultItems.length; i++) {
-    var result = resultItems[i];
-
-    if (result.type == 'log') {
-      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
-    } else if (result.type == 'expect' && result.passed && !result.passed()) {
-      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
-
-      if (result.trace.stack) {
-        messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
-      }
-    }
-  }
-
-  if (messagesDiv.childNodes.length > 0) {
-    specDiv.appendChild(messagesDiv);
-  }
-
-  this.suiteDivs[spec.suite.id].appendChild(specDiv);
-};
-
-jasmine.TrivialReporter.prototype.log = function() {
-  var console = jasmine.getGlobal().console;
-  if (console && console.log) console.log.apply(console, arguments);
-};
-
-jasmine.TrivialReporter.prototype.getLocation = function() {
-  return this.document.location;
-};
-
-jasmine.TrivialReporter.prototype.specFilter = function(spec) {
-  var paramMap = {};
-  var params = this.getLocation().search.substring(1).split('&');
-  for (var i = 0; i < params.length; i++) {
-    var p = params[i].split('=');
-    paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
-  }
-
-  if (!paramMap["spec"]) return true;
-  return spec.getFullName().indexOf(paramMap["spec"]) == 0;
-};
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine.css b/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine.css
deleted file mode 100644
index 6583fe7..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine.css
+++ /dev/null
@@ -1,166 +0,0 @@
-body {
-  font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
-}
-
-
-.jasmine_reporter a:visited, .jasmine_reporter a {
-  color: #303; 
-}
-
-.jasmine_reporter a:hover, .jasmine_reporter a:active {
-  color: blue; 
-}
-
-.run_spec {
-  float:right;
-  padding-right: 5px;
-  font-size: .8em;
-  text-decoration: none;
-}
-
-.jasmine_reporter {
-  margin: 0 5px;
-}
-
-.banner {
-  color: #303;
-  background-color: #fef;
-  padding: 5px;
-}
-
-.logo {
-  float: left;
-  font-size: 1.1em;
-  padding-left: 5px;
-}
-
-.logo .version {
-  font-size: .6em;
-  padding-left: 1em;
-}
-
-.runner.running {
-  background-color: yellow;
-}
-
-
-.options {
-  text-align: right;
-  font-size: .8em;
-}
-
-
-
-
-.suite {
-  border: 1px outset gray;
-  margin: 5px 0;
-  padding-left: 1em;
-}
-
-.suite .suite {
-  margin: 5px; 
-}
-
-.suite.passed {
-  background-color: #dfd;
-}
-
-.suite.failed {
-  background-color: #fdd;
-}
-
-.spec {
-  margin: 5px;
-  padding-left: 1em;
-  clear: both;
-}
-
-.spec.failed, .spec.passed, .spec.skipped {
-  padding-bottom: 5px;
-  border: 1px solid gray;
-}
-
-.spec.failed {
-  background-color: #fbb;
-  border-color: red;
-}
-
-.spec.passed {
-  background-color: #bfb;
-  border-color: green;
-}
-
-.spec.skipped {
-  background-color: #bbb;
-}
-
-.messages {
-  border-left: 1px dashed gray;
-  padding-left: 1em;
-  padding-right: 1em;
-}
-
-.passed {
-  background-color: #cfc;
-  display: none;
-}
-
-.failed {
-  background-color: #fbb;
-}
-
-.skipped {
-  color: #777;
-  background-color: #eee;
-  display: none;
-}
-
-
-/*.resultMessage {*/
-  /*white-space: pre;*/
-/*}*/
-
-.resultMessage span.result {
-  display: block;
-  line-height: 2em;
-  color: black;
-}
-
-.resultMessage .mismatch {
-  color: black;
-}
-
-.stackTrace {
-  white-space: pre;
-  font-size: .8em;
-  margin-left: 10px;
-  max-height: 5em;
-  overflow: auto;
-  border: 1px inset red;
-  padding: 1em;
-  background: #eef;
-}
-
-.finished-at {
-  padding-left: 1em;
-  font-size: .6em;
-}
-
-.show-passed .passed,
-.show-skipped .skipped {
-  display: block;
-}
-
-
-#jasmine_content {
-  position:fixed;
-  right: 100%;
-}
-
-.runner {
-  border: 1px solid gray;
-  display: block;
-  margin: 5px 0;
-  padding: 2px 0 2px 10px;
-}
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine.js b/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine.js
deleted file mode 100644
index 68baf53..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/jasmine/jasmine.js
+++ /dev/null
@@ -1,2421 +0,0 @@
-/**
- * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
- *
- * @namespace
- */
-var jasmine = {};
-
-/**
- * @private
- */
-jasmine.unimplementedMethod_ = function() {
-  throw new Error("unimplemented method");
-};
-
-/**
- * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
- * a plain old variable and may be redefined by somebody else.
- *
- * @private
- */
-jasmine.undefined = jasmine.___undefined___;
-
-/**
- * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
- *
- */
-jasmine.DEFAULT_UPDATE_INTERVAL = 250;
-
-/**
- * Default timeout interval in milliseconds for waitsFor() blocks.
- */
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
-
-jasmine.getGlobal = function() {
-  function getGlobal() {
-    return this;
-  }
-
-  return getGlobal();
-};
-
-/**
- * Allows for bound functions to be compared.  Internal use only.
- *
- * @ignore
- * @private
- * @param base {Object} bound 'this' for the function
- * @param name {Function} function to find
- */
-jasmine.bindOriginal_ = function(base, name) {
-  var original = base[name];
-  if (original.apply) {
-    return function() {
-      return original.apply(base, arguments);
-    };
-  } else {
-    // IE support
-    return jasmine.getGlobal()[name];
-  }
-};
-
-jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
-jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
-jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
-jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
-
-jasmine.MessageResult = function(values) {
-  this.type = 'log';
-  this.values = values;
-  this.trace = new Error(); // todo: test better
-};
-
-jasmine.MessageResult.prototype.toString = function() {
-  var text = "";
-  for(var i = 0; i < this.values.length; i++) {
-    if (i > 0) text += " ";
-    if (jasmine.isString_(this.values[i])) {
-      text += this.values[i];
-    } else {
-      text += jasmine.pp(this.values[i]);
-    }
-  }
-  return text;
-};
-
-jasmine.ExpectationResult = function(params) {
-  this.type = 'expect';
-  this.matcherName = params.matcherName;
-  this.passed_ = params.passed;
-  this.expected = params.expected;
-  this.actual = params.actual;
-
-  this.message = this.passed_ ? 'Passed.' : params.message;
-  this.trace = this.passed_ ? '' : new Error(this.message);
-};
-
-jasmine.ExpectationResult.prototype.toString = function () {
-  return this.message;
-};
-
-jasmine.ExpectationResult.prototype.passed = function () {
-  return this.passed_;
-};
-
-/**
- * Getter for the Jasmine environment. Ensures one gets created
- */
-jasmine.getEnv = function() {
-  return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isArray_ = function(value) {
-  return jasmine.isA_("Array", value);  
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isString_ = function(value) {
-  return jasmine.isA_("String", value);
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isNumber_ = function(value) {
-  return jasmine.isA_("Number", value);
-};
-
-/**
- * @ignore
- * @private
- * @param {String} typeName
- * @param value
- * @returns {Boolean}
- */
-jasmine.isA_ = function(typeName, value) {
-  return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
-};
-
-/**
- * Pretty printer for expecations.  Takes any object and turns it into a human-readable string.
- *
- * @param value {Object} an object to be outputted
- * @returns {String}
- */
-jasmine.pp = function(value) {
-  var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
-  stringPrettyPrinter.format(value);
-  return stringPrettyPrinter.string;
-};
-
-/**
- * Returns true if the object is a DOM Node.
- *
- * @param {Object} obj object to check
- * @returns {Boolean}
- */
-jasmine.isDomNode = function(obj) {
-  return obj['nodeType'] > 0;
-};
-
-/**
- * Returns a matchable 'generic' object of the class type.  For use in expecations of type when values don't matter.
- *
- * @example
- * // don't care about which function is passed in, as long as it's a function
- * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
- *
- * @param {Class} clazz
- * @returns matchable object of the type clazz
- */
-jasmine.any = function(clazz) {
-  return new jasmine.Matchers.Any(clazz);
-};
-
-/**
- * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
- *
- * Spies should be created in test setup, before expectations.  They can then be checked, using the standard Jasmine
- * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
- *
- * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
- *
- * Spies are torn down at the end of every spec.
- *
- * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
- *
- * @example
- * // a stub
- * var myStub = jasmine.createSpy('myStub');  // can be used anywhere
- *
- * // spy example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- *
- * // actual foo.not will not be called, execution stops
- * spyOn(foo, 'not');
-
- // foo.not spied upon, execution will continue to implementation
- * spyOn(foo, 'not').andCallThrough();
- *
- * // fake example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- *
- * // foo.not(val) will return val
- * spyOn(foo, 'not').andCallFake(function(value) {return value;});
- *
- * // mock example
- * foo.not(7 == 7);
- * expect(foo.not).toHaveBeenCalled();
- * expect(foo.not).toHaveBeenCalledWith(true);
- *
- * @constructor
- * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
- * @param {String} name
- */
-jasmine.Spy = function(name) {
-  /**
-   * The name of the spy, if provided.
-   */
-  this.identity = name || 'unknown';
-  /**
-   *  Is this Object a spy?
-   */
-  this.isSpy = true;
-  /**
-   * The actual function this spy stubs.
-   */
-  this.plan = function() {
-  };
-  /**
-   * Tracking of the most recent call to the spy.
-   * @example
-   * var mySpy = jasmine.createSpy('foo');
-   * mySpy(1, 2);
-   * mySpy.mostRecentCall.args = [1, 2];
-   */
-  this.mostRecentCall = {};
-
-  /**
-   * Holds arguments for each call to the spy, indexed by call count
-   * @example
-   * var mySpy = jasmine.createSpy('foo');
-   * mySpy(1, 2);
-   * mySpy(7, 8);
-   * mySpy.mostRecentCall.args = [7, 8];
-   * mySpy.argsForCall[0] = [1, 2];
-   * mySpy.argsForCall[1] = [7, 8];
-   */
-  this.argsForCall = [];
-  this.calls = [];
-};
-
-/**
- * Tells a spy to call through to the actual implemenatation.
- *
- * @example
- * var foo = {
- *   bar: function() { // do some stuff }
- * }
- *
- * // defining a spy on an existing property: foo.bar
- * spyOn(foo, 'bar').andCallThrough();
- */
-jasmine.Spy.prototype.andCallThrough = function() {
-  this.plan = this.originalValue;
-  return this;
-};
-
-/**
- * For setting the return value of a spy.
- *
- * @example
- * // defining a spy from scratch: foo() returns 'baz'
- * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
- *
- * // defining a spy on an existing property: foo.bar() returns 'baz'
- * spyOn(foo, 'bar').andReturn('baz');
- *
- * @param {Object} value
- */
-jasmine.Spy.prototype.andReturn = function(value) {
-  this.plan = function() {
-    return value;
-  };
-  return this;
-};
-
-/**
- * For throwing an exception when a spy is called.
- *
- * @example
- * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
- * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
- *
- * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
- * spyOn(foo, 'bar').andThrow('baz');
- *
- * @param {String} exceptionMsg
- */
-jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
-  this.plan = function() {
-    throw exceptionMsg;
-  };
-  return this;
-};
-
-/**
- * Calls an alternate implementation when a spy is called.
- *
- * @example
- * var baz = function() {
- *   // do some stuff, return something
- * }
- * // defining a spy from scratch: foo() calls the function baz
- * var foo = jasmine.createSpy('spy on foo').andCall(baz);
- *
- * // defining a spy on an existing property: foo.bar() calls an anonymnous function
- * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
- *
- * @param {Function} fakeFunc
- */
-jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
-  this.plan = fakeFunc;
-  return this;
-};
-
-/**
- * Resets all of a spy's the tracking variables so that it can be used again.
- *
- * @example
- * spyOn(foo, 'bar');
- *
- * foo.bar();
- *
- * expect(foo.bar.callCount).toEqual(1);
- *
- * foo.bar.reset();
- *
- * expect(foo.bar.callCount).toEqual(0);
- */
-jasmine.Spy.prototype.reset = function() {
-  this.wasCalled = false;
-  this.callCount = 0;
-  this.argsForCall = [];
-  this.calls = [];
-  this.mostRecentCall = {};
-};
-
-jasmine.createSpy = function(name) {
-
-  var spyObj = function() {
-    spyObj.wasCalled = true;
-    spyObj.callCount++;
-    var args = jasmine.util.argsToArray(arguments);
-    spyObj.mostRecentCall.object = this;
-    spyObj.mostRecentCall.args = args;
-    spyObj.argsForCall.push(args);
-    spyObj.calls.push({object: this, args: args});
-    return spyObj.plan.apply(this, arguments);
-  };
-
-  var spy = new jasmine.Spy(name);
-
-  for (var prop in spy) {
-    spyObj[prop] = spy[prop];
-  }
-
-  spyObj.reset();
-
-  return spyObj;
-};
-
-/**
- * Determines whether an object is a spy.
- *
- * @param {jasmine.Spy|Object} putativeSpy
- * @returns {Boolean}
- */
-jasmine.isSpy = function(putativeSpy) {
-  return putativeSpy && putativeSpy.isSpy;
-};
-
-/**
- * Creates a more complicated spy: an Object that has every property a function that is a spy.  Used for stubbing something
- * large in one call.
- *
- * @param {String} baseName name of spy class
- * @param {Array} methodNames array of names of methods to make spies
- */
-jasmine.createSpyObj = function(baseName, methodNames) {
-  if (!jasmine.isArray_(methodNames) || methodNames.length == 0) {
-    throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
-  }
-  var obj = {};
-  for (var i = 0; i < methodNames.length; i++) {
-    obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
-  }
-  return obj;
-};
-
-/**
- * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
-jasmine.log = function() {
-  var spec = jasmine.getEnv().currentSpec;
-  spec.log.apply(spec, arguments);
-};
-
-/**
- * Function that installs a spy on an existing object's method name.  Used within a Spec to create a spy.
- *
- * @example
- * // spy example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
- *
- * @see jasmine.createSpy
- * @param obj
- * @param methodName
- * @returns a Jasmine spy that can be chained with all spy methods
- */
-var spyOn = function(obj, methodName) {
-  return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
-};
-
-/**
- * Creates a Jasmine spec that will be added to the current suite.
- *
- * // TODO: pending tests
- *
- * @example
- * it('should be true', function() {
- *   expect(true).toEqual(true);
- * });
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
-var it = function(desc, func) {
-  return jasmine.getEnv().it(desc, func);
-};
-
-/**
- * Creates a <em>disabled</em> Jasmine spec.
- *
- * A convenience method that allows existing specs to be disabled temporarily during development.
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
-var xit = function(desc, func) {
-  return jasmine.getEnv().xit(desc, func);
-};
-
-/**
- * Starts a chain for a Jasmine expectation.
- *
- * It is passed an Object that is the actual value and should chain to one of the many
- * jasmine.Matchers functions.
- *
- * @param {Object} actual Actual value to test against and expected value
- */
-var expect = function(actual) {
-  return jasmine.getEnv().currentSpec.expect(actual);
-};
-
-/**
- * Defines part of a jasmine spec.  Used in cominbination with waits or waitsFor in asynchrnous specs.
- *
- * @param {Function} func Function that defines part of a jasmine spec.
- */
-var runs = function(func) {
-  jasmine.getEnv().currentSpec.runs(func);
-};
-
-/**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
-var waits = function(timeout) {
-  jasmine.getEnv().currentSpec.waits(timeout);
-};
-
-/**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
-var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
-  jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
-};
-
-/**
- * A function that is called before each spec in a suite.
- *
- * Used for spec setup, including validating assumptions.
- *
- * @param {Function} beforeEachFunction
- */
-var beforeEach = function(beforeEachFunction) {
-  jasmine.getEnv().beforeEach(beforeEachFunction);
-};
-
-/**
- * A function that is called after each spec in a suite.
- *
- * Used for restoring any state that is hijacked during spec execution.
- *
- * @param {Function} afterEachFunction
- */
-var afterEach = function(afterEachFunction) {
-  jasmine.getEnv().afterEach(afterEachFunction);
-};
-
-/**
- * Defines a suite of specifications.
- *
- * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
- * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
- * of setup in some tests.
- *
- * @example
- * // TODO: a simple suite
- *
- * // TODO: a simple suite with a nested describe block
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
-var describe = function(description, specDefinitions) {
-  return jasmine.getEnv().describe(description, specDefinitions);
-};
-
-/**
- * Disables a suite of specifications.  Used to disable some suites in a file, or files, temporarily during development.
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
-var xdescribe = function(description, specDefinitions) {
-  return jasmine.getEnv().xdescribe(description, specDefinitions);
-};
-
-
-// Provide the XMLHttpRequest class for IE 5.x-6.x:
-jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
-  try {
-    return new ActiveXObject("Msxml2.XMLHTTP.6.0");
-  } catch(e) {
-  }
-  try {
-    return new ActiveXObject("Msxml2.XMLHTTP.3.0");
-  } catch(e) {
-  }
-  try {
-    return new ActiveXObject("Msxml2.XMLHTTP");
-  } catch(e) {
-  }
-  try {
-    return new ActiveXObject("Microsoft.XMLHTTP");
-  } catch(e) {
-  }
-  throw new Error("This browser does not support XMLHttpRequest.");
-} : XMLHttpRequest;
-/**
- * @namespace
- */
-jasmine.util = {};
-
-/**
- * Declare that a child class inherit it's prototype from the parent class.
- *
- * @private
- * @param {Function} childClass
- * @param {Function} parentClass
- */
-jasmine.util.inherit = function(childClass, parentClass) {
-  /**
-   * @private
-   */
-  var subclass = function() {
-  };
-  subclass.prototype = parentClass.prototype;
-  childClass.prototype = new subclass;
-};
-
-jasmine.util.formatException = function(e) {
-  var lineNumber;
-  if (e.line) {
-    lineNumber = e.line;
-  }
-  else if (e.lineNumber) {
-    lineNumber = e.lineNumber;
-  }
-
-  var file;
-
-  if (e.sourceURL) {
-    file = e.sourceURL;
-  }
-  else if (e.fileName) {
-    file = e.fileName;
-  }
-
-  var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
-
-  if (file && lineNumber) {
-    message += ' in ' + file + ' (line ' + lineNumber + ')';
-  }
-
-  return message;
-};
-
-jasmine.util.htmlEscape = function(str) {
-  if (!str) return str;
-  return str.replace(/&/g, '&amp;')
-    .replace(/</g, '&lt;')
-    .replace(/>/g, '&gt;');
-};
-
-jasmine.util.argsToArray = function(args) {
-  var arrayOfArgs = [];
-  for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
-  return arrayOfArgs;
-};
-
-jasmine.util.extend = function(destination, source) {
-  for (var property in source) destination[property] = source[property];
-  return destination;
-};
-
-/**
- * Environment for Jasmine
- *
- * @constructor
- */
-jasmine.Env = function() {
-  this.currentSpec = null;
-  this.currentSuite = null;
-  this.currentRunner_ = new jasmine.Runner(this);
-
-  this.reporter = new jasmine.MultiReporter();
-
-  this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
-  this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
-  this.lastUpdate = 0;
-  this.specFilter = function() {
-    return true;
-  };
-
-  this.nextSpecId_ = 0;
-  this.nextSuiteId_ = 0;
-  this.equalityTesters_ = [];
-
-  // wrap matchers
-  this.matchersClass = function() {
-    jasmine.Matchers.apply(this, arguments);
-  };
-  jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
-
-  jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
-};
-
-
-jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
-jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
-jasmine.Env.prototype.setInterval = jasmine.setInterval;
-jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
-
-/**
- * @returns an object containing jasmine version build info, if set.
- */
-jasmine.Env.prototype.version = function () {
-  if (jasmine.version_) {
-    return jasmine.version_;
-  } else {
-    throw new Error('Version not set');
-  }
-};
-
-/**
- * @returns string containing jasmine version build info, if set.
- */
-jasmine.Env.prototype.versionString = function() {
-  if (jasmine.version_) {
-    var version = this.version();
-    return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
-  } else {
-    return "version unknown";
-  }
-};
-
-/**
- * @returns a sequential integer starting at 0
- */
-jasmine.Env.prototype.nextSpecId = function () {
-  return this.nextSpecId_++;
-};
-
-/**
- * @returns a sequential integer starting at 0
- */
-jasmine.Env.prototype.nextSuiteId = function () {
-  return this.nextSuiteId_++;
-};
-
-/**
- * Register a reporter to receive status updates from Jasmine.
- * @param {jasmine.Reporter} reporter An object which will receive status updates.
- */
-jasmine.Env.prototype.addReporter = function(reporter) {
-  this.reporter.addReporter(reporter);
-};
-
-jasmine.Env.prototype.execute = function() {
-  this.currentRunner_.execute();
-};
-
-jasmine.Env.prototype.describe = function(description, specDefinitions) {
-  var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
-
-  var parentSuite = this.currentSuite;
-  if (parentSuite) {
-    parentSuite.add(suite);
-  } else {
-    this.currentRunner_.add(suite);
-  }
-
-  this.currentSuite = suite;
-
-  var declarationError = null;
-  try {
-    specDefinitions.call(suite);
-  } catch(e) {
-    declarationError = e;
-  }
-
-  this.currentSuite = parentSuite;
-
-  if (declarationError) {
-    this.it("encountered a declaration exception", function() {
-      throw declarationError;
-    });
-  }
-
-  return suite;
-};
-
-jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
-  if (this.currentSuite) {
-    this.currentSuite.beforeEach(beforeEachFunction);
-  } else {
-    this.currentRunner_.beforeEach(beforeEachFunction);
-  }
-};
-
-jasmine.Env.prototype.currentRunner = function () {
-  return this.currentRunner_;
-};
-
-jasmine.Env.prototype.afterEach = function(afterEachFunction) {
-  if (this.currentSuite) {
-    this.currentSuite.afterEach(afterEachFunction);
-  } else {
-    this.currentRunner_.afterEach(afterEachFunction);
-  }
-
-};
-
-jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
-  return {
-    execute: function() {
-    }
-  };
-};
-
-jasmine.Env.prototype.it = function(description, func) {
-  var spec = new jasmine.Spec(this, this.currentSuite, description);
-  this.currentSuite.add(spec);
-  this.currentSpec = spec;
-
-  if (func) {
-    spec.runs(func);
-  }
-
-  return spec;
-};
-
-jasmine.Env.prototype.xit = function(desc, func) {
-  return {
-    id: this.nextSpecId(),
-    runs: function() {
-    }
-  };
-};
-
-jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
-  if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
-    return true;
-  }
-
-  a.__Jasmine_been_here_before__ = b;
-  b.__Jasmine_been_here_before__ = a;
-
-  var hasKey = function(obj, keyName) {
-    return obj != null && obj[keyName] !== jasmine.undefined;
-  };
-
-  for (var property in b) {
-    if (!hasKey(a, property) && hasKey(b, property)) {
-      mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
-    }
-  }
-  for (property in a) {
-    if (!hasKey(b, property) && hasKey(a, property)) {
-      mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
-    }
-  }
-  for (property in b) {
-    if (property == '__Jasmine_been_here_before__') continue;
-    if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
-      mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
-    }
-  }
-
-  if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
-    mismatchValues.push("arrays were not the same length");
-  }
-
-  delete a.__Jasmine_been_here_before__;
-  delete b.__Jasmine_been_here_before__;
-  return (mismatchKeys.length == 0 && mismatchValues.length == 0);
-};
-
-jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
-  mismatchKeys = mismatchKeys || [];
-  mismatchValues = mismatchValues || [];
-
-  for (var i = 0; i < this.equalityTesters_.length; i++) {
-    var equalityTester = this.equalityTesters_[i];
-    var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
-    if (result !== jasmine.undefined) return result;
-  }
-
-  if (a === b) return true;
-
-  if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
-    return (a == jasmine.undefined && b == jasmine.undefined);
-  }
-
-  if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
-    return a === b;
-  }
-
-  if (a instanceof Date && b instanceof Date) {
-    return a.getTime() == b.getTime();
-  }
-
-  if (a instanceof jasmine.Matchers.Any) {
-    return a.matches(b);
-  }
-
-  if (b instanceof jasmine.Matchers.Any) {
-    return b.matches(a);
-  }
-
-  if (jasmine.isString_(a) && jasmine.isString_(b)) {
-    return (a == b);
-  }
-
-  if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
-    return (a == b);
-  }
-
-  if (typeof a === "object" && typeof b === "object") {
-    return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
-  }
-
-  //Straight check
-  return (a === b);
-};
-
-jasmine.Env.prototype.contains_ = function(haystack, needle) {
-  if (jasmine.isArray_(haystack)) {
-    for (var i = 0; i < haystack.length; i++) {
-      if (this.equals_(haystack[i], needle)) return true;
-    }
-    return false;
-  }
-  return haystack.indexOf(needle) >= 0;
-};
-
-jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
-  this.equalityTesters_.push(equalityTester);
-};
-/** No-op base class for Jasmine reporters.
- *
- * @constructor
- */
-jasmine.Reporter = function() {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecResults = function(spec) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.log = function(str) {
-};
-
-/**
- * Blocks are functions with executable code that make up a spec.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {Function} func
- * @param {jasmine.Spec} spec
- */
-jasmine.Block = function(env, func, spec) {
-  this.env = env;
-  this.func = func;
-  this.spec = spec;
-};
-
-jasmine.Block.prototype.execute = function(onComplete) {  
-  try {
-    this.func.apply(this.spec);
-  } catch (e) {
-    this.spec.fail(e);
-  }
-  onComplete();
-};
-/** JavaScript API reporter.
- *
- * @constructor
- */
-jasmine.JsApiReporter = function() {
-  this.started = false;
-  this.finished = false;
-  this.suites_ = [];
-  this.results_ = {};
-};
-
-jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
-  this.started = true;
-  var suites = runner.topLevelSuites();
-  for (var i = 0; i < suites.length; i++) {
-    var suite = suites[i];
-    this.suites_.push(this.summarize_(suite));
-  }
-};
-
-jasmine.JsApiReporter.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
-  var isSuite = suiteOrSpec instanceof jasmine.Suite;
-  var summary = {
-    id: suiteOrSpec.id,
-    name: suiteOrSpec.description,
-    type: isSuite ? 'suite' : 'spec',
-    children: []
-  };
-  
-  if (isSuite) {
-    var children = suiteOrSpec.children();
-    for (var i = 0; i < children.length; i++) {
-      summary.children.push(this.summarize_(children[i]));
-    }
-  }
-  return summary;
-};
-
-jasmine.JsApiReporter.prototype.results = function() {
-  return this.results_;
-};
-
-jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
-  return this.results_[specId];
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
-  this.finished = true;
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
-  this.results_[spec.id] = {
-    messages: spec.results().getItems(),
-    result: spec.results().failedCount > 0 ? "failed" : "passed"
-  };
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.log = function(str) {
-};
-
-jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
-  var results = {};
-  for (var i = 0; i < specIds.length; i++) {
-    var specId = specIds[i];
-    results[specId] = this.summarizeResult_(this.results_[specId]);
-  }
-  return results;
-};
-
-jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
-  var summaryMessages = [];
-  var messagesLength = result.messages.length;
-  for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
-    var resultMessage = result.messages[messageIndex];
-    summaryMessages.push({
-      text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
-      passed: resultMessage.passed ? resultMessage.passed() : true,
-      type: resultMessage.type,
-      message: resultMessage.message,
-      trace: {
-        stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
-      }
-    });
-  }
-
-  return {
-    result : result.result,
-    messages : summaryMessages
-  };
-};
-
-/**
- * @constructor
- * @param {jasmine.Env} env
- * @param actual
- * @param {jasmine.Spec} spec
- */
-jasmine.Matchers = function(env, actual, spec, opt_isNot) {
-  this.env = env;
-  this.actual = actual;
-  this.spec = spec;
-  this.isNot = opt_isNot || false;
-  this.reportWasCalled_ = false;
-};
-
-// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
-jasmine.Matchers.pp = function(str) {
-  throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
-};
-
-// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
-jasmine.Matchers.prototype.report = function(result, failing_message, details) {
-  throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
-};
-
-jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
-  for (var methodName in prototype) {
-    if (methodName == 'report') continue;
-    var orig = prototype[methodName];
-    matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
-  }
-};
-
-jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
-  return function() {
-    var matcherArgs = jasmine.util.argsToArray(arguments);
-    var result = matcherFunction.apply(this, arguments);
-
-    if (this.isNot) {
-      result = !result;
-    }
-
-    if (this.reportWasCalled_) return result;
-
-    var message;
-    if (!result) {
-      if (this.message) {
-        message = this.message.apply(this, arguments);
-        if (jasmine.isArray_(message)) {
-          message = message[this.isNot ? 1 : 0];
-        }
-      } else {
-        var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
-        message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
-        if (matcherArgs.length > 0) {
-          for (var i = 0; i < matcherArgs.length; i++) {
-            if (i > 0) message += ",";
-            message += " " + jasmine.pp(matcherArgs[i]);
-          }
-        }
-        message += ".";
-      }
-    }
-    var expectationResult = new jasmine.ExpectationResult({
-      matcherName: matcherName,
-      passed: result,
-      expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
-      actual: this.actual,
-      message: message
-    });
-    this.spec.addMatcherResult(expectationResult);
-    return jasmine.undefined;
-  };
-};
-
-
-
-
-/**
- * toBe: compares the actual to the expected using ===
- * @param expected
- */
-jasmine.Matchers.prototype.toBe = function(expected) {
-  return this.actual === expected;
-};
-
-/**
- * toNotBe: compares the actual to the expected using !==
- * @param expected
- * @deprecated as of 1.0. Use not.toBe() instead.
- */
-jasmine.Matchers.prototype.toNotBe = function(expected) {
-  return this.actual !== expected;
-};
-
-/**
- * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
- *
- * @param expected
- */
-jasmine.Matchers.prototype.toEqual = function(expected) {
-  return this.env.equals_(this.actual, expected);
-};
-
-/**
- * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
- * @param expected
- * @deprecated as of 1.0. Use not.toNotEqual() instead.
- */
-jasmine.Matchers.prototype.toNotEqual = function(expected) {
-  return !this.env.equals_(this.actual, expected);
-};
-
-/**
- * Matcher that compares the actual to the expected using a regular expression.  Constructs a RegExp, so takes
- * a pattern or a String.
- *
- * @param expected
- */
-jasmine.Matchers.prototype.toMatch = function(expected) {
-  return new RegExp(expected).test(this.actual);
-};
-
-/**
- * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
- * @param expected
- * @deprecated as of 1.0. Use not.toMatch() instead.
- */
-jasmine.Matchers.prototype.toNotMatch = function(expected) {
-  return !(new RegExp(expected).test(this.actual));
-};
-
-/**
- * Matcher that compares the actual to jasmine.undefined.
- */
-jasmine.Matchers.prototype.toBeDefined = function() {
-  return (this.actual !== jasmine.undefined);
-};
-
-/**
- * Matcher that compares the actual to jasmine.undefined.
- */
-jasmine.Matchers.prototype.toBeUndefined = function() {
-  return (this.actual === jasmine.undefined);
-};
-
-/**
- * Matcher that compares the actual to null.
- */
-jasmine.Matchers.prototype.toBeNull = function() {
-  return (this.actual === null);
-};
-
-/**
- * Matcher that boolean not-nots the actual.
- */
-jasmine.Matchers.prototype.toBeTruthy = function() {
-  return !!this.actual;
-};
-
-
-/**
- * Matcher that boolean nots the actual.
- */
-jasmine.Matchers.prototype.toBeFalsy = function() {
-  return !this.actual;
-};
-
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was called.
- */
-jasmine.Matchers.prototype.toHaveBeenCalled = function() {
-  if (arguments.length > 0) {
-    throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
-  }
-
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy " + this.actual.identity + " to have been called.",
-      "Expected spy " + this.actual.identity + " not to have been called."
-    ];
-  };
-
-  return this.actual.wasCalled;
-};
-
-/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
-jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was not called.
- *
- * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
- */
-jasmine.Matchers.prototype.wasNotCalled = function() {
-  if (arguments.length > 0) {
-    throw new Error('wasNotCalled does not take arguments');
-  }
-
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy " + this.actual.identity + " to not have been called.",
-      "Expected spy " + this.actual.identity + " to have been called."
-    ];
-  };
-
-  return !this.actual.wasCalled;
-};
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
- *
- * @example
- *
- */
-jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
-  var expectedArgs = jasmine.util.argsToArray(arguments);
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-  this.message = function() {
-    if (this.actual.callCount == 0) {
-      // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
-      return [
-        "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
-        "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
-      ];
-    } else {
-      return [
-        "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
-        "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
-      ];
-    }
-  };
-
-  return this.env.contains_(this.actual.argsForCall, expectedArgs);
-};
-
-/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
-
-/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasNotCalledWith = function() {
-  var expectedArgs = jasmine.util.argsToArray(arguments);
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
-      "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
-    ]
-  };
-
-  return !this.env.contains_(this.actual.argsForCall, expectedArgs);
-};
-
-/**
- * Matcher that checks that the expected item is an element in the actual Array.
- *
- * @param {Object} expected
- */
-jasmine.Matchers.prototype.toContain = function(expected) {
-  return this.env.contains_(this.actual, expected);
-};
-
-/**
- * Matcher that checks that the expected item is NOT an element in the actual Array.
- *
- * @param {Object} expected
- * @deprecated as of 1.0. Use not.toNotContain() instead.
- */
-jasmine.Matchers.prototype.toNotContain = function(expected) {
-  return !this.env.contains_(this.actual, expected);
-};
-
-jasmine.Matchers.prototype.toBeLessThan = function(expected) {
-  return this.actual < expected;
-};
-
-jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
-  return this.actual > expected;
-};
-
-/**
- * Matcher that checks that the expected exception was thrown by the actual.
- *
- * @param {String} expected
- */
-jasmine.Matchers.prototype.toThrow = function(expected) {
-  var result = false;
-  var exception;
-  if (typeof this.actual != 'function') {
-    throw new Error('Actual is not a function');
-  }
-  try {
-    this.actual();
-  } catch (e) {
-    exception = e;
-  }
-  if (exception) {
-    result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
-  }
-
-  var not = this.isNot ? "not " : "";
-
-  this.message = function() {
-    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
-      return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' ');
-    } else {
-      return "Expected function to throw an exception.";
-    }
-  };
-
-  return result;
-};
-
-jasmine.Matchers.Any = function(expectedClass) {
-  this.expectedClass = expectedClass;
-};
-
-jasmine.Matchers.Any.prototype.matches = function(other) {
-  if (this.expectedClass == String) {
-    return typeof other == 'string' || other instanceof String;
-  }
-
-  if (this.expectedClass == Number) {
-    return typeof other == 'number' || other instanceof Number;
-  }
-
-  if (this.expectedClass == Function) {
-    return typeof other == 'function' || other instanceof Function;
-  }
-
-  if (this.expectedClass == Object) {
-    return typeof other == 'object';
-  }
-
-  return other instanceof this.expectedClass;
-};
-
-jasmine.Matchers.Any.prototype.toString = function() {
-  return '<jasmine.any(' + this.expectedClass + ')>';
-};
-
-/**
- * @constructor
- */
-jasmine.MultiReporter = function() {
-  this.subReporters_ = [];
-};
-jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
-
-jasmine.MultiReporter.prototype.addReporter = function(reporter) {
-  this.subReporters_.push(reporter);
-};
-
-(function() {
-  var functionNames = [
-    "reportRunnerStarting",
-    "reportRunnerResults",
-    "reportSuiteResults",
-    "reportSpecStarting",
-    "reportSpecResults",
-    "log"
-  ];
-  for (var i = 0; i < functionNames.length; i++) {
-    var functionName = functionNames[i];
-    jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
-      return function() {
-        for (var j = 0; j < this.subReporters_.length; j++) {
-          var subReporter = this.subReporters_[j];
-          if (subReporter[functionName]) {
-            subReporter[functionName].apply(subReporter, arguments);
-          }
-        }
-      };
-    })(functionName);
-  }
-})();
-/**
- * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
- *
- * @constructor
- */
-jasmine.NestedResults = function() {
-  /**
-   * The total count of results
-   */
-  this.totalCount = 0;
-  /**
-   * Number of passed results
-   */
-  this.passedCount = 0;
-  /**
-   * Number of failed results
-   */
-  this.failedCount = 0;
-  /**
-   * Was this suite/spec skipped?
-   */
-  this.skipped = false;
-  /**
-   * @ignore
-   */
-  this.items_ = [];
-};
-
-/**
- * Roll up the result counts.
- *
- * @param result
- */
-jasmine.NestedResults.prototype.rollupCounts = function(result) {
-  this.totalCount += result.totalCount;
-  this.passedCount += result.passedCount;
-  this.failedCount += result.failedCount;
-};
-
-/**
- * Adds a log message.
- * @param values Array of message parts which will be concatenated later.
- */
-jasmine.NestedResults.prototype.log = function(values) {
-  this.items_.push(new jasmine.MessageResult(values));
-};
-
-/**
- * Getter for the results: message & results.
- */
-jasmine.NestedResults.prototype.getItems = function() {
-  return this.items_;
-};
-
-/**
- * Adds a result, tracking counts (total, passed, & failed)
- * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
- */
-jasmine.NestedResults.prototype.addResult = function(result) {
-  if (result.type != 'log') {
-    if (result.items_) {
-      this.rollupCounts(result);
-    } else {
-      this.totalCount++;
-      if (result.passed()) {
-        this.passedCount++;
-      } else {
-        this.failedCount++;
-      }
-    }
-  }
-  this.items_.push(result);
-};
-
-/**
- * @returns {Boolean} True if <b>everything</b> below passed
- */
-jasmine.NestedResults.prototype.passed = function() {
-  return this.passedCount === this.totalCount;
-};
-/**
- * Base class for pretty printing for expectation results.
- */
-jasmine.PrettyPrinter = function() {
-  this.ppNestLevel_ = 0;
-};
-
-/**
- * Formats a value in a nice, human-readable string.
- *
- * @param value
- */
-jasmine.PrettyPrinter.prototype.format = function(value) {
-  if (this.ppNestLevel_ > 40) {
-    throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
-  }
-
-  this.ppNestLevel_++;
-  try {
-    if (value === jasmine.undefined) {
-      this.emitScalar('undefined');
-    } else if (value === null) {
-      this.emitScalar('null');
-    } else if (value === jasmine.getGlobal()) {
-      this.emitScalar('<global>');
-    } else if (value instanceof jasmine.Matchers.Any) {
-      this.emitScalar(value.toString());
-    } else if (typeof value === 'string') {
-      this.emitString(value);
-    } else if (jasmine.isSpy(value)) {
-      this.emitScalar("spy on " + value.identity);
-    } else if (value instanceof RegExp) {
-      this.emitScalar(value.toString());
-    } else if (typeof value === 'function') {
-      this.emitScalar('Function');
-    } else if (typeof value.nodeType === 'number') {
-      this.emitScalar('HTMLNode');
-    } else if (value instanceof Date) {
-      this.emitScalar('Date(' + value + ')');
-    } else if (value.__Jasmine_been_here_before__) {
-      this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
-    } else if (jasmine.isArray_(value) || typeof value == 'object') {
-      value.__Jasmine_been_here_before__ = true;
-      if (jasmine.isArray_(value)) {
-        this.emitArray(value);
-      } else {
-        this.emitObject(value);
-      }
-      delete value.__Jasmine_been_here_before__;
-    } else {
-      this.emitScalar(value.toString());
-    }
-  } finally {
-    this.ppNestLevel_--;
-  }
-};
-
-jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
-  for (var property in obj) {
-    if (property == '__Jasmine_been_here_before__') continue;
-    fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false);
-  }
-};
-
-jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
-
-jasmine.StringPrettyPrinter = function() {
-  jasmine.PrettyPrinter.call(this);
-
-  this.string = '';
-};
-jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
-
-jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
-  this.append(value);
-};
-
-jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
-  this.append("'" + value + "'");
-};
-
-jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
-  this.append('[ ');
-  for (var i = 0; i < array.length; i++) {
-    if (i > 0) {
-      this.append(', ');
-    }
-    this.format(array[i]);
-  }
-  this.append(' ]');
-};
-
-jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
-  var self = this;
-  this.append('{ ');
-  var first = true;
-
-  this.iterateObject(obj, function(property, isGetter) {
-    if (first) {
-      first = false;
-    } else {
-      self.append(', ');
-    }
-
-    self.append(property);
-    self.append(' : ');
-    if (isGetter) {
-      self.append('<getter>');
-    } else {
-      self.format(obj[property]);
-    }
-  });
-
-  this.append(' }');
-};
-
-jasmine.StringPrettyPrinter.prototype.append = function(value) {
-  this.string += value;
-};
-jasmine.Queue = function(env) {
-  this.env = env;
-  this.blocks = [];
-  this.running = false;
-  this.index = 0;
-  this.offset = 0;
-  this.abort = false;
-};
-
-jasmine.Queue.prototype.addBefore = function(block) {
-  this.blocks.unshift(block);
-};
-
-jasmine.Queue.prototype.add = function(block) {
-  this.blocks.push(block);
-};
-
-jasmine.Queue.prototype.insertNext = function(block) {
-  this.blocks.splice((this.index + this.offset + 1), 0, block);
-  this.offset++;
-};
-
-jasmine.Queue.prototype.start = function(onComplete) {
-  this.running = true;
-  this.onComplete = onComplete;
-  this.next_();
-};
-
-jasmine.Queue.prototype.isRunning = function() {
-  return this.running;
-};
-
-jasmine.Queue.LOOP_DONT_RECURSE = true;
-
-jasmine.Queue.prototype.next_ = function() {
-  var self = this;
-  var goAgain = true;
-
-  while (goAgain) {
-    goAgain = false;
-    
-    if (self.index < self.blocks.length && !this.abort) {
-      var calledSynchronously = true;
-      var completedSynchronously = false;
-
-      var onComplete = function () {
-        if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
-          completedSynchronously = true;
-          return;
-        }
-
-        if (self.blocks[self.index].abort) {
-          self.abort = true;
-        }
-
-        self.offset = 0;
-        self.index++;
-
-        var now = new Date().getTime();
-        if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
-          self.env.lastUpdate = now;
-          self.env.setTimeout(function() {
-            self.next_();
-          }, 0);
-        } else {
-          if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
-            goAgain = true;
-          } else {
-            self.next_();
-          }
-        }
-      };
-      self.blocks[self.index].execute(onComplete);
-
-      calledSynchronously = false;
-      if (completedSynchronously) {
-        onComplete();
-      }
-      
-    } else {
-      self.running = false;
-      if (self.onComplete) {
-        self.onComplete();
-      }
-    }
-  }
-};
-
-jasmine.Queue.prototype.results = function() {
-  var results = new jasmine.NestedResults();
-  for (var i = 0; i < this.blocks.length; i++) {
-    if (this.blocks[i].results) {
-      results.addResult(this.blocks[i].results());
-    }
-  }
-  return results;
-};
-
-
-/**
- * Runner
- *
- * @constructor
- * @param {jasmine.Env} env
- */
-jasmine.Runner = function(env) {
-  var self = this;
-  self.env = env;
-  self.queue = new jasmine.Queue(env);
-  self.before_ = [];
-  self.after_ = [];
-  self.suites_ = [];
-};
-
-jasmine.Runner.prototype.execute = function() {
-  var self = this;
-  if (self.env.reporter.reportRunnerStarting) {
-    self.env.reporter.reportRunnerStarting(this);
-  }
-  self.queue.start(function () {
-    self.finishCallback();
-  });
-};
-
-jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
-  beforeEachFunction.typeName = 'beforeEach';
-  this.before_.splice(0,0,beforeEachFunction);
-};
-
-jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
-  afterEachFunction.typeName = 'afterEach';
-  this.after_.splice(0,0,afterEachFunction);
-};
-
-
-jasmine.Runner.prototype.finishCallback = function() {
-  this.env.reporter.reportRunnerResults(this);
-};
-
-jasmine.Runner.prototype.addSuite = function(suite) {
-  this.suites_.push(suite);
-};
-
-jasmine.Runner.prototype.add = function(block) {
-  if (block instanceof jasmine.Suite) {
-    this.addSuite(block);
-  }
-  this.queue.add(block);
-};
-
-jasmine.Runner.prototype.specs = function () {
-  var suites = this.suites();
-  var specs = [];
-  for (var i = 0; i < suites.length; i++) {
-    specs = specs.concat(suites[i].specs());
-  }
-  return specs;
-};
-
-jasmine.Runner.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.Runner.prototype.topLevelSuites = function() {
-  var topLevelSuites = [];
-  for (var i = 0; i < this.suites_.length; i++) {
-    if (!this.suites_[i].parentSuite) {
-      topLevelSuites.push(this.suites_[i]);
-    }
-  }
-  return topLevelSuites;
-};
-
-jasmine.Runner.prototype.results = function() {
-  return this.queue.results();
-};
-/**
- * Internal representation of a Jasmine specification, or test.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {jasmine.Suite} suite
- * @param {String} description
- */
-jasmine.Spec = function(env, suite, description) {
-  if (!env) {
-    throw new Error('jasmine.Env() required');
-  }
-  if (!suite) {
-    throw new Error('jasmine.Suite() required');
-  }
-  var spec = this;
-  spec.id = env.nextSpecId ? env.nextSpecId() : null;
-  spec.env = env;
-  spec.suite = suite;
-  spec.description = description;
-  spec.queue = new jasmine.Queue(env);
-
-  spec.afterCallbacks = [];
-  spec.spies_ = [];
-
-  spec.results_ = new jasmine.NestedResults();
-  spec.results_.description = description;
-  spec.matchersClass = null;
-};
-
-jasmine.Spec.prototype.getFullName = function() {
-  return this.suite.getFullName() + ' ' + this.description + '.';
-};
-
-
-jasmine.Spec.prototype.results = function() {
-  return this.results_;
-};
-
-/**
- * All parameters are pretty-printed and concatenated together, then written to the spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
-jasmine.Spec.prototype.log = function() {
-  return this.results_.log(arguments);
-};
-
-jasmine.Spec.prototype.runs = function (func) {
-  var block = new jasmine.Block(this.env, func, this);
-  this.addToQueue(block);
-  return this;
-};
-
-jasmine.Spec.prototype.addToQueue = function (block) {
-  if (this.queue.isRunning()) {
-    this.queue.insertNext(block);
-  } else {
-    this.queue.add(block);
-  }
-};
-
-/**
- * @param {jasmine.ExpectationResult} result
- */
-jasmine.Spec.prototype.addMatcherResult = function(result) {
-  this.results_.addResult(result);
-};
-
-jasmine.Spec.prototype.expect = function(actual) {
-  var positive = new (this.getMatchersClass_())(this.env, actual, this);
-  positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
-  return positive;
-};
-
-/**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
-jasmine.Spec.prototype.waits = function(timeout) {
-  var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
-  this.addToQueue(waitsFunc);
-  return this;
-};
-
-/**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
-jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
-  var latchFunction_ = null;
-  var optional_timeoutMessage_ = null;
-  var optional_timeout_ = null;
-
-  for (var i = 0; i < arguments.length; i++) {
-    var arg = arguments[i];
-    switch (typeof arg) {
-      case 'function':
-        latchFunction_ = arg;
-        break;
-      case 'string':
-        optional_timeoutMessage_ = arg;
-        break;
-      case 'number':
-        optional_timeout_ = arg;
-        break;
-    }
-  }
-
-  var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
-  this.addToQueue(waitsForFunc);
-  return this;
-};
-
-jasmine.Spec.prototype.fail = function (e) {
-  var expectationResult = new jasmine.ExpectationResult({
-    passed: false,
-    message: e ? jasmine.util.formatException(e) : 'Exception'
-  });
-  this.results_.addResult(expectationResult);
-};
-
-jasmine.Spec.prototype.getMatchersClass_ = function() {
-  return this.matchersClass || this.env.matchersClass;
-};
-
-jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
-  var parent = this.getMatchersClass_();
-  var newMatchersClass = function() {
-    parent.apply(this, arguments);
-  };
-  jasmine.util.inherit(newMatchersClass, parent);
-  jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
-  this.matchersClass = newMatchersClass;
-};
-
-jasmine.Spec.prototype.finishCallback = function() {
-  this.env.reporter.reportSpecResults(this);
-};
-
-jasmine.Spec.prototype.finish = function(onComplete) {
-  this.removeAllSpies();
-  this.finishCallback();
-  if (onComplete) {
-    onComplete();
-  }
-};
-
-jasmine.Spec.prototype.after = function(doAfter) {
-  if (this.queue.isRunning()) {
-    this.queue.add(new jasmine.Block(this.env, doAfter, this));
-  } else {
-    this.afterCallbacks.unshift(doAfter);
-  }
-};
-
-jasmine.Spec.prototype.execute = function(onComplete) {
-  var spec = this;
-  if (!spec.env.specFilter(spec)) {
-    spec.results_.skipped = true;
-    spec.finish(onComplete);
-    return;
-  }
-
-  this.env.reporter.reportSpecStarting(this);
-
-  spec.env.currentSpec = spec;
-
-  spec.addBeforesAndAftersToQueue();
-
-  spec.queue.start(function () {
-    spec.finish(onComplete);
-  });
-};
-
-jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
-  var runner = this.env.currentRunner();
-  var i;
-
-  for (var suite = this.suite; suite; suite = suite.parentSuite) {
-    for (i = 0; i < suite.before_.length; i++) {
-      this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
-    }
-  }
-  for (i = 0; i < runner.before_.length; i++) {
-    this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
-  }
-  for (i = 0; i < this.afterCallbacks.length; i++) {
-    this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
-  }
-  for (suite = this.suite; suite; suite = suite.parentSuite) {
-    for (i = 0; i < suite.after_.length; i++) {
-      this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
-    }
-  }
-  for (i = 0; i < runner.after_.length; i++) {
-    this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
-  }
-};
-
-jasmine.Spec.prototype.explodes = function() {
-  throw 'explodes function should not have been called';
-};
-
-jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
-  if (obj == jasmine.undefined) {
-    throw "spyOn could not find an object to spy upon for " + methodName + "()";
-  }
-
-  if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
-    throw methodName + '() method does not exist';
-  }
-
-  if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
-    throw new Error(methodName + ' has already been spied upon');
-  }
-
-  var spyObj = jasmine.createSpy(methodName);
-
-  this.spies_.push(spyObj);
-  spyObj.baseObj = obj;
-  spyObj.methodName = methodName;
-  spyObj.originalValue = obj[methodName];
-
-  obj[methodName] = spyObj;
-
-  return spyObj;
-};
-
-jasmine.Spec.prototype.removeAllSpies = function() {
-  for (var i = 0; i < this.spies_.length; i++) {
-    var spy = this.spies_[i];
-    spy.baseObj[spy.methodName] = spy.originalValue;
-  }
-  this.spies_ = [];
-};
-
-/**
- * Internal representation of a Jasmine suite.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {String} description
- * @param {Function} specDefinitions
- * @param {jasmine.Suite} parentSuite
- */
-jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
-  var self = this;
-  self.id = env.nextSuiteId ? env.nextSuiteId() : null;
-  self.description = description;
-  self.queue = new jasmine.Queue(env);
-  self.parentSuite = parentSuite;
-  self.env = env;
-  self.before_ = [];
-  self.after_ = [];
-  self.children_ = [];
-  self.suites_ = [];
-  self.specs_ = [];
-};
-
-jasmine.Suite.prototype.getFullName = function() {
-  var fullName = this.description;
-  for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
-    fullName = parentSuite.description + ' ' + fullName;
-  }
-  return fullName;
-};
-
-jasmine.Suite.prototype.finish = function(onComplete) {
-  this.env.reporter.reportSuiteResults(this);
-  this.finished = true;
-  if (typeof(onComplete) == 'function') {
-    onComplete();
-  }
-};
-
-jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
-  beforeEachFunction.typeName = 'beforeEach';
-  this.before_.unshift(beforeEachFunction);
-};
-
-jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
-  afterEachFunction.typeName = 'afterEach';
-  this.after_.unshift(afterEachFunction);
-};
-
-jasmine.Suite.prototype.results = function() {
-  return this.queue.results();
-};
-
-jasmine.Suite.prototype.add = function(suiteOrSpec) {
-  this.children_.push(suiteOrSpec);
-  if (suiteOrSpec instanceof jasmine.Suite) {
-    this.suites_.push(suiteOrSpec);
-    this.env.currentRunner().addSuite(suiteOrSpec);
-  } else {
-    this.specs_.push(suiteOrSpec);
-  }
-  this.queue.add(suiteOrSpec);
-};
-
-jasmine.Suite.prototype.specs = function() {
-  return this.specs_;
-};
-
-jasmine.Suite.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.Suite.prototype.children = function() {
-  return this.children_;
-};
-
-jasmine.Suite.prototype.execute = function(onComplete) {
-  var self = this;
-  this.queue.start(function () {
-    self.finish(onComplete);
-  });
-};
-jasmine.WaitsBlock = function(env, timeout, spec) {
-  this.timeout = timeout;
-  jasmine.Block.call(this, env, null, spec);
-};
-
-jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
-
-jasmine.WaitsBlock.prototype.execute = function (onComplete) {
-  this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
-  this.env.setTimeout(function () {
-    onComplete();
-  }, this.timeout);
-};
-/**
- * A block which waits for some condition to become true, with timeout.
- *
- * @constructor
- * @extends jasmine.Block
- * @param {jasmine.Env} env The Jasmine environment.
- * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
- * @param {Function} latchFunction A function which returns true when the desired condition has been met.
- * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
- * @param {jasmine.Spec} spec The Jasmine spec.
- */
-jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
-  this.timeout = timeout || env.defaultTimeoutInterval;
-  this.latchFunction = latchFunction;
-  this.message = message;
-  this.totalTimeSpentWaitingForLatch = 0;
-  jasmine.Block.call(this, env, null, spec);
-};
-jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
-
-jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
-
-jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
-  this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
-  var latchFunctionResult;
-  try {
-    latchFunctionResult = this.latchFunction.apply(this.spec);
-  } catch (e) {
-    this.spec.fail(e);
-    onComplete();
-    return;
-  }
-
-  if (latchFunctionResult) {
-    onComplete();
-  } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
-    var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
-    this.spec.fail({
-      name: 'timeout',
-      message: message
-    });
-
-    this.abort = true;
-    onComplete();
-  } else {
-    this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
-    var self = this;
-    this.env.setTimeout(function() {
-      self.execute(onComplete);
-    }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
-  }
-};
-// Mock setTimeout, clearTimeout
-// Contributed by Pivotal Computer Systems, www.pivotalsf.com
-
-jasmine.FakeTimer = function() {
-  this.reset();
-
-  var self = this;
-  self.setTimeout = function(funcToCall, millis) {
-    self.timeoutsMade++;
-    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
-    return self.timeoutsMade;
-  };
-
-  self.setInterval = function(funcToCall, millis) {
-    self.timeoutsMade++;
-    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
-    return self.timeoutsMade;
-  };
-
-  self.clearTimeout = function(timeoutKey) {
-    self.scheduledFunctions[timeoutKey] = jasmine.undefined;
-  };
-
-  self.clearInterval = function(timeoutKey) {
-    self.scheduledFunctions[timeoutKey] = jasmine.undefined;
-  };
-
-};
-
-jasmine.FakeTimer.prototype.reset = function() {
-  this.timeoutsMade = 0;
-  this.scheduledFunctions = {};
-  this.nowMillis = 0;
-};
-
-jasmine.FakeTimer.prototype.tick = function(millis) {
-  var oldMillis = this.nowMillis;
-  var newMillis = oldMillis + millis;
-  this.runFunctionsWithinRange(oldMillis, newMillis);
-  this.nowMillis = newMillis;
-};
-
-jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
-  var scheduledFunc;
-  var funcsToRun = [];
-  for (var timeoutKey in this.scheduledFunctions) {
-    scheduledFunc = this.scheduledFunctions[timeoutKey];
-    if (scheduledFunc != jasmine.undefined &&
-        scheduledFunc.runAtMillis >= oldMillis &&
-        scheduledFunc.runAtMillis <= nowMillis) {
-      funcsToRun.push(scheduledFunc);
-      this.scheduledFunctions[timeoutKey] = jasmine.undefined;
-    }
-  }
-
-  if (funcsToRun.length > 0) {
-    funcsToRun.sort(function(a, b) {
-      return a.runAtMillis - b.runAtMillis;
-    });
-    for (var i = 0; i < funcsToRun.length; ++i) {
-      try {
-        var funcToRun = funcsToRun[i];
-        this.nowMillis = funcToRun.runAtMillis;
-        funcToRun.funcToCall();
-        if (funcToRun.recurring) {
-          this.scheduleFunction(funcToRun.timeoutKey,
-              funcToRun.funcToCall,
-              funcToRun.millis,
-              true);
-        }
-      } catch(e) {
-      }
-    }
-    this.runFunctionsWithinRange(oldMillis, nowMillis);
-  }
-};
-
-jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
-  this.scheduledFunctions[timeoutKey] = {
-    runAtMillis: this.nowMillis + millis,
-    funcToCall: funcToCall,
-    recurring: recurring,
-    timeoutKey: timeoutKey,
-    millis: millis
-  };
-};
-
-/**
- * @namespace
- */
-jasmine.Clock = {
-  defaultFakeTimer: new jasmine.FakeTimer(),
-
-  reset: function() {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.defaultFakeTimer.reset();
-  },
-
-  tick: function(millis) {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.defaultFakeTimer.tick(millis);
-  },
-
-  runFunctionsWithinRange: function(oldMillis, nowMillis) {
-    jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
-  },
-
-  scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
-    jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
-  },
-
-  useMock: function() {
-    if (!jasmine.Clock.isInstalled()) {
-      var spec = jasmine.getEnv().currentSpec;
-      spec.after(jasmine.Clock.uninstallMock);
-
-      jasmine.Clock.installMock();
-    }
-  },
-
-  installMock: function() {
-    jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
-  },
-
-  uninstallMock: function() {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.installed = jasmine.Clock.real;
-  },
-
-  real: {
-    setTimeout: jasmine.getGlobal().setTimeout,
-    clearTimeout: jasmine.getGlobal().clearTimeout,
-    setInterval: jasmine.getGlobal().setInterval,
-    clearInterval: jasmine.getGlobal().clearInterval
-  },
-
-  assertInstalled: function() {
-    if (!jasmine.Clock.isInstalled()) {
-      throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
-    }
-  },
-
-  isInstalled: function() {
-    return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
-  },
-
-  installed: null
-};
-jasmine.Clock.installed = jasmine.Clock.real;
-
-//else for IE support
-jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
-  if (jasmine.Clock.installed.setTimeout.apply) {
-    return jasmine.Clock.installed.setTimeout.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.setTimeout(funcToCall, millis);
-  }
-};
-
-jasmine.getGlobal().setInterval = function(funcToCall, millis) {
-  if (jasmine.Clock.installed.setInterval.apply) {
-    return jasmine.Clock.installed.setInterval.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.setInterval(funcToCall, millis);
-  }
-};
-
-jasmine.getGlobal().clearTimeout = function(timeoutKey) {
-  if (jasmine.Clock.installed.clearTimeout.apply) {
-    return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.clearTimeout(timeoutKey);
-  }
-};
-
-jasmine.getGlobal().clearInterval = function(timeoutKey) {
-  if (jasmine.Clock.installed.clearTimeout.apply) {
-    return jasmine.Clock.installed.clearInterval.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.clearInterval(timeoutKey);
-  }
-};
-
-
-jasmine.version_= {
-  "major": 1,
-  "minor": 0,
-  "build": 0,
-  "revision": 1284494074
-};
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/matchers/Controller.js b/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/matchers/Controller.js
deleted file mode 100644
index f26044b..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/matchers/Controller.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Sencha-specific matchers for convenient testing of Controller expectations
- */
-beforeEach(function() {
-    this.addMatchers({
-        toHaveRendered: function(expected) {
-            
-        }
-    });
-});
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/matchers/Model.js b/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/matchers/Model.js
deleted file mode 100644
index 0c91149..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/matchers/Model.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Sencha-specific matchers for convenient testing of Model expectations
- */
-beforeEach(function() {
-    this.addMatchers({
-        /**
-         * Sample usage:
-         * expect('User').toHaveMany('Product');
-         */
-        toHaveMany: function(expected) {
-            if (typeof this.actual == 'string') {
-                this.actual = Ext.ModelManager.types[this.actual].prototype;
-            }
-            
-            var associations = this.actual.associations.items,
-                length       = associations.length,
-                association, i;
-            
-            for (i = 0; i < length; i++) {
-                association = associations[i];
-                
-                if (association.associatedName == expected && association.type == 'hasMany') {
-                    return true;
-                }
-            }
-            
-            return false;
-        },
-        
-        /**
-         * Sample usage:
-         * expect('Product').toBelongTo('User')
-         */
-        toBelongTo: function(expected) {
-            if (typeof this.actual == 'string') {
-                this.actual = Ext.ModelManager.types[this.actual].prototype;
-            }
-            
-            var associations = this.actual.associations.items,
-                length       = associations.length,
-                association, i;
-            
-            for (i = 0; i < length; i++) {
-                association = associations[i];
-                
-                if (association.associatedName == expected && association.type == 'belongsTo') {
-                    return true;
-                }
-            }
-            
-            return false;
-        }
-    });
-});
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/sencha-jasmine.css b/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/sencha-jasmine.css
deleted file mode 100644
index 784d48f..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/sencha-jasmine.css
+++ /dev/null
@@ -1,226 +0,0 @@
-body {
-    font-family:"Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
-    margin:0;
-}
-
-.jasmine_reporter > * {
-    margin:10px;
-}
-
-.run_spec {
-    float:right;
-    font-size:10px;
-}
-
-/*banner*/
-.banner {
-    position:relative;
-    background:#fff;
-    -webkit-box-shadow:0 0 10px #ccc;
-    padding:4px 0 6px 6px;
-    margin:0 0 10px 0;
-}
-.banner .logo {
-    width:120px;
-    height:50px;
-
-    background:url(http://www.sencha.com/assets/images/logo-sencha-sm.png) no-repeat;
-}
-.banner .options {
-    position:absolute;
-    top:3px;
-    right:3px;
-    color:#666;
-    font-size:10px;
-}
-.banner .options .show {
-    text-align:right;
-}
-.banner .options .show > * {
-    display:inline-block;
-}
-.banner .options .show label {
-    margin-right:3px;
-}
-
-/*runner*/
-.runner,
-.suite {
-    display:block;
-
-    text-shadow:0 1px 0 #fff;
-
-    border:1px solid #bbb;
-    border-radius:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#eee), to(#d1d1d1));
-
-    -webkit-box-shadow:0 0 10px #ccc;
-
-    padding:6px;
-}
-.runner a,
-.suite a {
-    display:inline-block;
-
-    color:#eee;
-    font-size:11px;
-    text-decoration:none;
-    text-shadow:0 -1px 0 #000;
-
-    border:1px solid #111;
-    border-radius:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#555), to(#212121));
-
-    -webkit-background-clip: padding-box;
-
-    padding:1px 4px 2px 4px;
-}
-.runner .finished-at {
-    font-size:10px;
-
-    padding-top:1px;
-    padding-left:6px;
-}
-
-.runner.running {
-    text-shadow:0 1px 0 #EDECCA;
-
-    border-color:#D1CF84;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#EDE613), to(#DBD61F));
-}
-.runner.running a {
-    display:none;
-}
-
-.runner.failed a,
-.suite.failed a {
-    border-color:#660000;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#dd0000), to(#880000));
-}
-
-.runner.passed a,
-.suite.passed a {
-    border-color:#006600;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#00aa00), to(#006600));
-}
-
-/*suite*/
-.suite a.run_spec {
-    display:none;
-}
-.suite > a.description {
-    color:#000;
-    font-size:18px;
-    text-shadow:0 1px 0 #fff;
-
-    border:0;
-    background:transparent;
-}
-.suite .suite > a.description {
-    font-size:14px;
-}
-.suite.failed {
-    border-color:#E0C1C5;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#FFF7F8), to(#F0DADD));
-}
-.suite.failed a.description {
-    color:#440000;
-}
-.suite .suite {
-    margin:5px;
-}
-
-/*spec*/
-.spec {
-    margin: 5px;
-    padding-left: 1em;
-    clear: both;
-
-    border:1px solid #ccc;
-    border-radius:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-
-    background:#fff;
-
-    -webkit-box-shadow:inset 0 0 10px #ddd;
-
-    -webkit-background-clip:padding-box;
-
-    padding:10px;
-}
-.spec a.description {
-    display:block;
-
-    border:0;
-
-    background:transparent;
-
-    padding:0;
-
-    color:#000 !important;
-    font-size:16px;
-    text-shadow:none;
-}
-.spec .messages {
-    border:1px dashed #ccc;
-    border-radius:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-
-    background:#f1f1f1;
-
-    margin:10px 0 0 0;
-    padding:5px;
-
-    font-size:11px;
-    line-height:15px;
-}
-
-.passed,
-.skipped {
-    display:none;
-}
-
-.runner.passed,
-.runner.skipped {
-    display:block;
-}
-
-.suite.passed {
-    border-color:#AEBFA6;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#ECF2E9), to(#C8DBBF));
-}
-
-.show-passed .passed,
-.show-skipped .skipped {
-    display:block;
-}
-
-.stackTrace {
-  white-space: pre;
-  font-size: .8em;
-  margin-left: 10px;
-  max-height: 5em;
-  overflow: auto;
-  border: 1px inset red;
-  padding: 1em;
-  background: #eef;
-}
-
-
-#jasmine_content {
-  position:fixed;
-  right: 100%;
-}
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/sencha-jasmine.js b/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/sencha-jasmine.js
deleted file mode 100644
index c670d5c..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/lib/sencha-jasmine/sencha-jasmine.js
+++ /dev/null
@@ -1,88 +0,0 @@
-jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
-  var showPassed, showSkipped;
-
-  this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
-      this.createDom('div', { className: 'banner' },
-        this.createDom('div', { className: 'logo' }),
-        this.createDom('div', { className: 'options' },
-            this.createDom('div', { className: 'show' },
-                this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
-                showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' })
-            ),
-            this.createDom('div', { className: 'show' },
-                this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped"),
-                showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' })
-            ),
-            this.createDom('div', { className: 'show' },
-                this.createDom('label', { "for": "__jasmine_TrivialReporter_automaticReload__" }," automatic reload"),
-                automaticReload = this.createDom('input',
-                    (window.location.hash == "#reload") ? {id: "__jasmine_TrivialReporter_automaticReload__", type: 'checkbox', checked: true } : {id: "__jasmine_TrivialReporter_automaticReload__", type: 'checkbox'}
-                )
-            )
-            )
-          ),
-
-      this.runnerDiv = this.createDom('div', { className: 'runner running' },
-          this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
-          this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
-          this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
-      );
-
-  this.document.body.appendChild(this.outerDiv);
-
-  var suites = runner.suites();
-  for (var i = 0; i < suites.length; i++) {
-    var suite = suites[i];
-    var suiteDiv = this.createDom('div', { className: 'suite' },
-        this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
-        this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
-    this.suiteDivs[suite.id] = suiteDiv;
-    var parentDiv = this.outerDiv;
-    if (suite.parentSuite) {
-      parentDiv = this.suiteDivs[suite.parentSuite.id];
-    }
-    parentDiv.appendChild(suiteDiv);
-  }
-
-  this.startedAt = new Date();
-
-  var self = this;
-  showPassed.onchange = function(evt) {
-    if (evt.target.checked) {
-      self.outerDiv.className += ' show-passed';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
-    }
-  };
-
-  showSkipped.onchange = function(evt) {
-    if (evt.target.checked) {
-      self.outerDiv.className += ' show-skipped';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
-    }
-  };
-
-  automaticReload.onchange = function(evt) {
-      if (evt.target.checked) {
-        window.location.hash = "#reload";
-        window.location.reload();
-      } else {
-        window.location.hash = "";
-        window.location.reload();
-      }
-    };
-};
-
-if (window.location.hash == "#reload") {
-    var interval = setInterval(function() {
-        var isRunning = jasmine.getEnv().currentRunner_.queue.isRunning();
-        if (!isRunning) {
-            clearInterval(interval);
-        
-            setTimeout(function() {
-                window.location.reload();
-            }, 5000);
-        };
-    }, 1500);
-};
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/public/resources/css/application.css b/js/lib/JSBuilder/src/generators/app/files/public/resources/css/application.css
deleted file mode 100644
index c0b4f5f..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/public/resources/css/application.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.x-tablet .x-list, .x-desktop .x-list {
-  border-right: 1px solid #000;
-}
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/sencha.sh b/js/lib/JSBuilder/src/generators/app/files/sencha.sh
deleted file mode 100755
index e422430..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/sencha.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-UNAME="$(uname)"
-ARGUMENTS=$*
-DIRNAME="$(dirname $0)/lib/JSBuilder"
-if [ $UNAME = "Darwin" ] ; then
-    OS="mac"
-else
-    OS="linux"
-fi
-CMD="$DIRNAME/jsdb/$OS/jsdb -path $DIRNAME $DIRNAME/bin/Dispatch.js $ARGUMENTS"
-$CMD
diff --git a/js/lib/JSBuilder/src/generators/app/files/test/unit/.htaccess b/js/lib/JSBuilder/src/generators/app/files/test/unit/.htaccess
deleted file mode 100644
index 832ea9b..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/test/unit/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-ExpiresActive On
-ExpiresDefault "access"
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/files/test/unit/SpecOptions.js b/js/lib/JSBuilder/src/generators/app/files/test/unit/SpecOptions.js
deleted file mode 100644
index acf0c05..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/test/unit/SpecOptions.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * This file is included by your test/unit/index.html file and is used to apply settings before 
- * the tests are run.
- */
-
-Ext.ns('fixtures');
-
-//Stops the Application from being booted up automatically
-Ext.Application.prototype.bindReady = Ext.emptyFn;
diff --git a/js/lib/JSBuilder/src/generators/app/files/test/unit/index.html b/js/lib/JSBuilder/src/generators/app/files/test/unit/index.html
deleted file mode 100644
index d3ad4cc..0000000
--- a/js/lib/JSBuilder/src/generators/app/files/test/unit/index.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-  "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>Sencha - Jasmine Test Runner</title>
-    <link rel="stylesheet" type="text/css" href="../../lib/sencha-jasmine/sencha-jasmine.css" />
-    
-    <script type="text/javascript" src="../../lib/touch/ext-touch-debug.js"></script>
-    
-    <script type="text/javascript" src="../../lib/jasmine/jasmine.js"></script>
-    <script type="text/javascript" src="../../lib/jasmine/jasmine-html.js"></script>
-    <script type="text/javascript" src="../../lib/sencha-jasmine/sencha-jasmine.js"></script>
-    <script type="text/javascript" src="../../lib/sencha-jasmine/matchers/Model.js"></script>
-    <script type="text/javascript" src="../../lib/sencha-jasmine/matchers/Controller.js"></script>
-    
-    <script type="text/javascript" src="SpecOptions.js"></script>
-</head>
-<body>
-    
-    <!-- include source files here... -->
-    <div id="sourceFiles">
-        <script type="text/javascript" src="../../app/app.js"></script>
-        
-        <div id="app-models">
-                  
-        </div>
-        
-        <div id="app-controllers">
-            
-        </div>
-        
-        <div id="app-views">
-            
-        </div>
-        
-        <div id="app-stores">
-            
-        </div>
-    </div>
-    
-    <!-- include fixture files here -->
-    <div id="fixtures">
-        
-    </div>
-    
-    <!-- include spec files here... -->
-    <div id="specFiles">
-        <script type="text/javascript" src="app.js"></script>
-        
-        <div id="spec-models">
-            
-        </div>
-        
-        <div id="spec-controllers">
-            
-        </div>
-        
-        <div id="spec-views">
-            
-        </div>
-    </div>
-    
-    <script type="text/javascript">
-      jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
-      jasmine.getEnv().execute();
-    </script>
-    
-</body>
-</html>
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/templates/Application.js b/js/lib/JSBuilder/src/generators/app/templates/Application.js
deleted file mode 100644
index 4353412..0000000
--- a/js/lib/JSBuilder/src/generators/app/templates/Application.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * This file sets application-wide settings and launches the application when everything has
- * been loaded onto the page. By default we just render the application\s Viewport inside the
- * launch method (see app/views/Viewport.js).
- */ 
-{name} = new Ext.Application({
-    defaultTarget: "viewport",
-    name: "{name}",
-    launch: function() {
-        this.viewport = new {name}.Viewport();
-    }
-});
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/app/templates/Viewport.js b/js/lib/JSBuilder/src/generators/app/templates/Viewport.js
deleted file mode 100644
index af3b57d..0000000
--- a/js/lib/JSBuilder/src/generators/app/templates/Viewport.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * @class {name}.Viewport
- * @extends Ext.Panel
- * This is a default generated class which would usually be used to initialize your application's
- * main viewport. By default this is simply a welcome screen that tells you that the app was 
- * generated correctly.
- */
-{name}.Viewport = Ext.extend(Ext.Panel, {
-    id        : 'viewport',
-    layout    : 'card',
-    fullscreen: true,
-
-    initComponent: function() {
-        var store = new Ext.data.Store({
-            fields: ['text', 'href'],
-            data  : [
-                {
-                    text: 'Touch API',
-                    href: 'http://dev.sencha.com/deploy/touch/docs/'
-                },
-                {
-                    text: 'Touch Examples',
-                    href: 'http://dev.sencha.com/deploy/touch/examples/'
-                }
-            ]
-        });
-
-        Ext.apply(this, {
-            dockedItems: [
-                {
-                    dock : 'left',
-                    xtype: 'list',
-                    store: store,
-                    width: 250,
-
-                    tpl         : '<{tpl} for="."><div class="link"><strong>\{text\}</strong></div></{tpl}>',
-                    itemSelector: 'div.link',
-
-                    listeners: {
-                        itemtap: this.onListItemTap
-                    },
-
-                    dockedItems: [
-                        {
-                            xtype: 'toolbar',
-                            dock : 'top',
-                            ui   : 'light'
-                        }
-                    ]
-                }
-            ],
-
-            items: [
-                {
-                    xtype : 'panel',
-                    layout: 'fit',
-
-                    dockedItems: [
-                        {
-                            dock : 'top',
-                            xtype: 'toolbar',
-                            title: 'Welcome to Sencha Touch'
-                        }
-                    ],
-
-                    items: [
-                        {
-                            xtype: 'panel',
-                            style: 'background:#fff',
-
-                            styleHtmlContent: true,
-
-                            html : [
-                                '<h3>Getting Started</h3>',
-                                '<p>You have successfully generated the {name} application. Currently this app is a blank slate, ',
-                                'with just the minimum set of files and directories. The file creating this interface can be found ',
-                                'in app/views/Viewport.js</p>'
-                            ]
-                        }
-                    ]
-                }
-            ]
-        });
-
-        {name}.Viewport.superclass.initComponent.apply(this, arguments);
-    },
-
-    onListItemTap: function(list, index, node, e) {
-        var record = list.getRecord(node);
-
-        window.open(record.get('href'));
-    }
-});
diff --git a/js/lib/JSBuilder/src/generators/controller/Controller.js b/js/lib/JSBuilder/src/generators/controller/Controller.js
deleted file mode 100644
index 3482fe3..0000000
--- a/js/lib/JSBuilder/src/generators/controller/Controller.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * @class Ext.generator.Controller
- * @extends Ext.generator.Base
- * Generates a Controller file based on a template
- */
-Ext.generator.Controller = Ext.extend(Ext.generator.Base, {
-
-    generate: function() {
-        var controllerFile = 'app/controllers/' + this.name + '.js';
-        
-        this.headline("Generating the " + this.name + " controller");
-        
-        this.template('Controller', this, controllerFile);
-        this.template('ControllerSpec', this, 'test/unit/controllers/' + this.name + '.js');
-        
-        this.insertInclude(controllerFile, 'sencha-controllers');
-        this.insertInclude('../../' + controllerFile, 'app-controllers', 'test/unit/index.html');
-        this.insertInclude('controllers/' + this.name + '.js', 'spec-controllers', 'test/unit/index.html');
-    },
-    
-    decodeArgs: function(args) {
-        this.name = args[0];
-        this.actions = args.slice(1);
-    }
-});
-
-Ext.regGenerator('controller', Ext.generator.Controller);
-
-load('src/generators/controller/templates/ControllerSpec.js');
-load('src/generators/controller/templates/Controller.js');
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/controller/templates/Controller.js b/js/lib/JSBuilder/src/generators/controller/templates/Controller.js
deleted file mode 100644
index ca509de..0000000
--- a/js/lib/JSBuilder/src/generators/controller/templates/Controller.js
+++ /dev/null
@@ -1,9 +0,0 @@
-Ext.generator.Controller.templates.Controller = new Ext.XTemplate(
-    'Ext.regController("{name}", {\n',
-    '<tpl for="actions">',
-    '    {.}: function() {\n',
-    '        \n',
-    '    }{[xindex != xcount ? ",\n\n" : ""]}',
-    '</tpl>',    
-    '\n});\n'
-);
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/controller/templates/ControllerSpec.js b/js/lib/JSBuilder/src/generators/controller/templates/ControllerSpec.js
deleted file mode 100644
index 1b7e754..0000000
--- a/js/lib/JSBuilder/src/generators/controller/templates/ControllerSpec.js
+++ /dev/null
@@ -1,12 +0,0 @@
-Ext.generator.Controller.templates.ControllerSpec = new Ext.XTemplate(
-    'describe("The {name} controller", function() {\n',
-    '    var controller = Ext.ControllerManager.get("{name}");\n\n',
-    '<tpl for="actions">',
-    '    describe("the {.} action", function() {\n',
-    '        beforeEach(function() {\n',
-    '            \n',
-    '        });\n\n\n',
-    '    });\n\n',
-    '</tpl>',
-    '});\n'
-);
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/model/Model.js b/js/lib/JSBuilder/src/generators/model/Model.js
deleted file mode 100644
index 0fbc515..0000000
--- a/js/lib/JSBuilder/src/generators/model/Model.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * @class Ext.generator.Model
- * @extends Ext.generator.Base
- * Generates a model file based on config
- */
-Ext.generator.Model = Ext.extend(Ext.generator.Base, {
-
-    generate: function() {
-        var modelFile   = 'app/models/' + this.name + '.js',
-            specFile    = 'test/unit/models/' + this.name + '.js',
-            fixtureFile = 'test/fixtures/' + this.name + '.js';
-        
-        this.headline("Generating the " + this.name + " model");
-        this.template("Model", this, modelFile);
-        this.template("ModelSpec", this, specFile);
-        this.template("Fixture", this, fixtureFile);
-        
-        this.insertInclude(modelFile, 'sencha-models');
-        
-        this.insertInclude('../../' + modelFile, 'app-models', 'test/unit/index.html');
-        this.insertInclude('models/' + this.name + '.js',  'spec-models', 'test/unit/index.html');
-        this.insertInclude('../fixtures/' + this.name + '.js',  'fixtures', 'test/unit/index.html');
-    },
-    
-    decodeArgs: function(args) {
-        this.name = args[0];
-        this.fields = args.slice(1);
-        
-        var length = this.fields.length,
-            field, i;
-        
-        for (i = 0; i < length; i++) {
-            field = this.fields[i].split(':');
-            
-            this.fields[i] = {
-                name: field[0],
-                type: field[1]
-            };
-        }
-    }
-});
-
-Ext.regGenerator('model', Ext.generator.Model);
-
-load('src/generators/model/templates/ModelSpec.js');
-load('src/generators/model/templates/Model.js');
-load('src/generators/model/templates/Fixture.js');
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/model/templates/Fixture.js b/js/lib/JSBuilder/src/generators/model/templates/Fixture.js
deleted file mode 100644
index b1f92e3..0000000
--- a/js/lib/JSBuilder/src/generators/model/templates/Fixture.js
+++ /dev/null
@@ -1,9 +0,0 @@
-Ext.generator.Model.templates.Fixture = new Ext.XTemplate(
-    '(function() \{\n',
-    '    var {name} = Ext.ModelManager.getModel("{name}");\n',
-    '    \n',
-    '    fixtures.{name} = \{\n',
-    '        \n',
-    '    \};\n',
-    '\})();\n'
-);
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/model/templates/Model.js b/js/lib/JSBuilder/src/generators/model/templates/Model.js
deleted file mode 100644
index 9df678d..0000000
--- a/js/lib/JSBuilder/src/generators/model/templates/Model.js
+++ /dev/null
@@ -1,9 +0,0 @@
-Ext.generator.Model.templates.Model = new Ext.XTemplate(
-    'Ext.regModel("{name}", {\n',
-    '    fields: [\n',
-    '<tpl for="fields">',
-    '        \{name: "{name}", type: "{type}"\}{[xindex != xcount ? "," : ""]}\n',
-    '</tpl>',
-    '    ]\n',
-    '});'
-);
\ No newline at end of file
diff --git a/js/lib/JSBuilder/src/generators/model/templates/ModelSpec.js b/js/lib/JSBuilder/src/generators/model/templates/ModelSpec.js
deleted file mode 100644
index bacc8d8..0000000
--- a/js/lib/JSBuilder/src/generators/model/templates/ModelSpec.js
+++ /dev/null
@@ -1,9 +0,0 @@
-Ext.generator.Model.templates.ModelSpec = new Ext.XTemplate(
-    'describe("A {name}", function() {\n',
-    '    var {name} = Ext.ModelManager.getModel("{name}"),\n',
-    '        instance;\n\n',
-    '    beforeEach(function() {\n',
-    '        instance = new {name}({});\n',
-    '    });\n\n',
-    '});'
-);
\ No newline at end of file
diff --git a/js/lib/JSBuilder/tests/builder.js b/js/lib/JSBuilder/tests/builder.js
deleted file mode 100644
index 3089378..0000000
--- a/js/lib/JSBuilder/tests/builder.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* 
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-
diff --git a/js/lib/JSBuilder/tests/parser.js b/js/lib/JSBuilder/tests/parser.js
deleted file mode 100644
index 305068c..0000000
--- a/js/lib/JSBuilder/tests/parser.js
+++ /dev/null
@@ -1,51 +0,0 @@
-Loader.require('Parser');
-Loader.require('Filesystem');
-
-Parser.setParams({
-    browser: 'ie',
-    browserVersion: 6,
-    version: 3.1,
-    minVersion: 2.0,
-    debug: true
-});
-
-assertTrue("Browser is IE", Parser.evaluate('browser', 'ie'));
-assertTrue("Browser is not firefox", Parser.evaluate('browser', '!firefox'));
-assertTrue("Browser version is greater than 5", Parser.evaluate('browserVersion', '>5'));
-assertTrue("Browser version is less than 7", Parser.evaluate('browserVersion', '<7'));
-assertTrue("Browser version is greater or equal to 6", Parser.evaluate('browserVersion', '>=6'));
-assertFalse("Nonexistent", Parser.evaluate('nonexistent'));
-
-assertTrue("//<if browser=ie> is a valid statement", Parser.isStatement('//<if browser=ie>'));
-assertTrue("    //<if browser=ie> (tab in front) is a valid statement", Parser.isStatement('    //<if browser=ie>'));
-assertTrue("//<if browser=ie> (spaces at the end) is a valid statement", Parser.isStatement('//<if browser=ie>      '));
-
-assertFalse("//</if> is not a valid opening statement", Parser.isStatement('//</if>'));
-assertTrue("//</if> is valid close of if", Parser.isCloseOf('//</if>', { type: 'if', isInverted: false }));
-assertTrue("//</!if> is valid close of inverted if", Parser.isCloseOf('//</!if>', { type: 'if', isInverted: true }));
-
-assertEqual("Parser.parseStatementProperties('browser=ie debug')",
-    Parser.parseStatementProperties('browser=ie debug'), { browser: 'ie', debug: true });
-
-assertEqual("Parser.parseStatementProperties('browser=\"ie\" browserVersion='!7' debug=false')",
-    Parser.parseStatementProperties('browser="ie" browserVersion=\'!7\' debug=false'), { browser: 'ie', browserVersion: '!7', debug: "false" });
-
-assertEqual("Parser.parseStatement('//<deprecated since=\"3.0\">')",
-    Parser.parseStatement('//<deprecated since="3.0">'), { properties: { since: '3.0' }, type: 'deprecated', isInverted: false });
-
-assertEqual("Parser.parse before1.js and after1.js",
-    Parser.parse(PATH + 'tests/parser/before1.js'), Filesystem.readFile(PATH + 'tests/parser/after1.js'));
-
-assertEqual("Parser.parse before2.js and after2.js",
-    Parser.parse(PATH + 'tests/parser/before2.js'), Filesystem.readFile(PATH + 'tests/parser/after2.js'));
-
-Parser.setParams({
-    debug: true,
-    debugLevel: 2
-});
-
-assertEqual("Parser.parse before3.js and after3.js",
-    Parser.parse(PATH + 'tests/parser/before3.js'), Filesystem.readFile(PATH + 'tests/parser/after3.js'));
-
-assertEqual("Parser.parse before4.js and after4.js",
-    Parser.parse(PATH + 'tests/parser/before4.js'), Filesystem.readFile(PATH + 'tests/parser/after4.js'));
diff --git a/js/lib/JSBuilder/tests/parser/after1.js b/js/lib/JSBuilder/tests/parser/after1.js
deleted file mode 100644
index f30c8c9..0000000
--- a/js/lib/JSBuilder/tests/parser/after1.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Normal comment here
-var lorem = {
-    ipsum: true,
-    // Nested if here
-    else_here: 'ok',
-    other: 'thing'
-};
-//<unknownTag>
-var testing = 123;
\ No newline at end of file
diff --git a/js/lib/JSBuilder/tests/parser/after2.js b/js/lib/JSBuilder/tests/parser/after2.js
deleted file mode 100644
index b06e7af..0000000
--- a/js/lib/JSBuilder/tests/parser/after2.js
+++ /dev/null
@@ -1,2 +0,0 @@
-alert('Debug here');
-
diff --git a/js/lib/JSBuilder/tests/parser/after3.js b/js/lib/JSBuilder/tests/parser/after3.js
deleted file mode 100644
index 87430bb..0000000
--- a/js/lib/JSBuilder/tests/parser/after3.js
+++ /dev/null
@@ -1,9 +0,0 @@
-    if (someCondition) {
-        throw new Error("Some error");
-    }
-
-    if (someCondition) {
-        console.warn("Some warning");
-    }
-
-
diff --git a/js/lib/JSBuilder/tests/parser/after4.js b/js/lib/JSBuilder/tests/parser/after4.js
deleted file mode 100644
index 5029c1f..0000000
--- a/js/lib/JSBuilder/tests/parser/after4.js
+++ /dev/null
@@ -1 +0,0 @@
-var test = 1+1;
diff --git a/js/lib/JSBuilder/tests/parser/before1.js b/js/lib/JSBuilder/tests/parser/before1.js
deleted file mode 100644
index b56fdef..0000000
--- a/js/lib/JSBuilder/tests/parser/before1.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Normal comment here
-//<if debug>
-var lorem = {
-    ipsum: true,
-    // Nested if here
-    //<if browser=ie browserVersion=7>
-    if_here: 'blah',
-    //<elseif browser="!ie">
-    elseif_here: 'tada',
-    //<else>
-    else_here: 'ok',
-    //</if>
-    other: 'thing'
-};
-//</if>
-//<unknownTag>
-var testing = 123;
\ No newline at end of file
diff --git a/js/lib/JSBuilder/tests/parser/before2.js b/js/lib/JSBuilder/tests/parser/before2.js
deleted file mode 100644
index 2e80e73..0000000
--- a/js/lib/JSBuilder/tests/parser/before2.js
+++ /dev/null
@@ -1,9 +0,0 @@
-//<debug>
-alert('Debug here');
-//<else>
-alert('Not debug here');
-//</debug>
-
-//<deprecated since="1.0">
-alert("Deprecated since 1.0")
-//</deprecated>
\ No newline at end of file
diff --git a/js/lib/JSBuilder/tests/parser/before3.js b/js/lib/JSBuilder/tests/parser/before3.js
deleted file mode 100644
index 3b3512c..0000000
--- a/js/lib/JSBuilder/tests/parser/before3.js
+++ /dev/null
@@ -1,23 +0,0 @@
-//<debug error>
-    if (someCondition) {
-        throw new Error("Some error");
-    }
-//</debug>
-
-//<debug warn>
-    if (someCondition) {
-        console.warn("Some warning");
-    }
-//</debug>
-
-//<debug info>
-    if (someCondition) {
-        console.log("Some info");
-    }
-//</debug>
-
-//<debug>
-    if (someCondition) {
-        console.log("Some other info");
-    }
-//</debug>
diff --git a/js/lib/JSBuilder/tests/parser/before4.js b/js/lib/JSBuilder/tests/parser/before4.js
deleted file mode 100644
index aa133f8..0000000
--- a/js/lib/JSBuilder/tests/parser/before4.js
+++ /dev/null
@@ -1,5 +0,0 @@
-//<debug error>
-//<uncomment>
-//var test = 1+1;
-//</uncomment>
-//</debug>
diff --git a/js/lib/JSBuilder/tests/run.js b/js/lib/JSBuilder/tests/run.js
deleted file mode 100644
index b8e1a0f..0000000
--- a/js/lib/JSBuilder/tests/run.js
+++ /dev/null
@@ -1,50 +0,0 @@
-var PATH = system.script.replace(/tests(\/|\\)run.js/, '');
-load(PATH + 'src/Loader.js');
-
-Loader.setBasePath(PATH + 'src');
-
-Loader.require([
-    'Ext',
-    'Cli',
-    'Logger'
-]);
-
-var assertTrue = function(message, a) {
-    assertEqual(message, a, true);
-};
-var assertFalse = function(message, a) {
-    assertEqual(message, a, false);
-};
-var assertEqual = function(message, a, b) {
-    if ((Ext.isArray(a) || Ext.isObject(a)) && (Ext.isArray(b) || Ext.isObject(b))) {
-        a = JSON.stringify(a);
-        b = JSON.stringify(b);
-    }
-    Logger.log("[" + ((a === b) ? "PASSED" : "FAILED") + "] " + message);
-};
-var assertNotEqual = function(message, a, b) {
-    assertEqual(message, a, !b);
-};
-
-var Tester = Ext.extend(Cli, {
-    name: "Super simple Unit Tester",
-    version: "1.0",
-
-    map: {
-        n: {
-            name: 'name',
-            required: true,
-            desc: 'Name of the test you want to run, e.g Parser'
-        }
-    },
-
-    run: function() {
-        if (Tester.superclass.run.call(this) === false)
-            return;
-
-        load(PATH + 'tests/'+this.get('name')+'.js');
-    }
-});
-
-var tester = new Tester();
-tester.run();
diff --git a/js/lib/JSBuilder/ycompressor/ycompressor.jar b/js/lib/JSBuilder/ycompressor/ycompressor.jar
deleted file mode 100644
index c29470b..0000000
Binary files a/js/lib/JSBuilder/ycompressor/ycompressor.jar and /dev/null differ
diff --git a/js/lib/compat/ext3-compat.css b/js/lib/compat/ext3-compat.css
deleted file mode 100644
index 288e5cc..0000000
--- a/js/lib/compat/ext3-compat.css
+++ /dev/null
@@ -1,138 +0,0 @@
-/*===============================================================================================
- Creates rounded, raised boxes like on the Ext website - the markup isn't pretty:
-  <div class="x-box-blue">
-        <div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>
-        <div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">
-            <h3>YOUR TITLE HERE (optional)</h3>
-            <div>YOUR CONTENT HERE</div>
-        </div></div></div>
-        <div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>
-    </div>
-  These rules used to be part of ext-all.css but this markup is no longer 
-  officially supported as part of the framework.
- */
-.x-box-tl {
-    background: transparent no-repeat 0 0;
-    zoom:1;
-}
-.x-box-tc {
-    height: 8px;
-    background: transparent repeat-x 0 0;
-    overflow: hidden;
-}
-.x-box-tr {
-    background: transparent no-repeat right -8px;
-}
-.x-box-ml {
-    background: transparent repeat-y 0;
-    padding-left: 4px;
-    overflow: hidden;
-    zoom:1;
-}
-.x-box-mc {
-    background: repeat-x 0 -16px;
-    padding: 4px 10px;
-}
-.x-box-mc h3 {
-    margin: 0 0 4px 0;
-    zoom:1;
-}
-.x-box-mr {
-    background: transparent repeat-y right;
-    padding-right: 4px;
-    overflow: hidden;
-}
-.x-box-bl {
-    background: transparent no-repeat 0 -16px;
-    zoom:1;
-}
-.x-box-bc {
-    background: transparent repeat-x 0 -8px;
-    height: 8px;
-    overflow: hidden;
-}
-.x-box-br {
-    background: transparent no-repeat right -24px;
-}
-.x-box-tl, .x-box-bl {
-    padding-left: 8px;
-    overflow: hidden;
-}
-.x-box-tr, .x-box-br {
-    padding-right: 8px;
-    overflow: hidden;
-}
-.x-box-tl {
-    background-image: url(images/box/corners.gif);
-}
-.x-box-tc {
-    background-image: url(images/box/tb.gif);
-}
-.x-box-tr {
-    background-image: url(images/box/corners.gif);
-}
-.x-box-ml {
-    background-image: url(images/box/l.gif);
-}
-.x-box-mc {
-    background-color: #eee;
-    background-image: url(images/box/tb.gif);
-    font-family: "Myriad Pro","Myriad Web","Tahoma","Helvetica","Arial",sans-serif;
-    color: #393939;
-    font-size: 12px;
-}
-.x-box-mc h3 {
-    font-size: 14px;
-    font-weight: bold;
-}
-.x-box-mr {
-    background-image: url(images/box/r.gif);
-}
-.x-box-bl {
-    background-image: url(images/box/corners.gif);
-}
-.x-box-bc {
-    background-image: url(images/box/tb.gif);
-}
-.x-box-br {
-    background-image: url(images/box/corners.gif);
-}
-.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {
-    background-image: url(images/box/corners-blue.gif);
-}
-.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {
-    background-image: url(images/box/tb-blue.gif);
-}
-.x-box-blue .x-box-mc {
-    background-color: #c3daf9;
-}
-.x-box-blue .x-box-mc h3 {
-    color: #17385b;
-}
-.x-box-blue .x-box-ml {
-    background-image: url(images/box/l-blue.gif);
-}
-.x-box-blue .x-box-mr {
-    background-image: url(images/box/r-blue.gif);
-}
-
-/*===============================================================================================
- * Spotlight utility
- */
-.x-spotlight {
-    z-index: 8999;
-    position: absolute;
-    top:0;
-    left:0;
-    -moz-opacity: 0.5;
-    opacity: .50;
-    filter: alpha(opacity=50);
-    width:0;
-    height:0;
-    zoom: 1;
-    background-color: #ccc;
-}
-
-/*===============================================================================================
- * 
- */
diff --git a/js/lib/compat/ext3-compat.js b/js/lib/compat/ext3-compat.js
deleted file mode 100644
index cb8217d..0000000
--- a/js/lib/compat/ext3-compat.js
+++ /dev/null
@@ -1,1808 +0,0 @@
-//
-// TODO: Add GridPanel.getView() to the lib
-// TODO: Rename Ext.ux.PreviewPlugin -> Ext.grid.RowPreviewPlugin
-// TODO: Move CSS styles from paging.html into grid.css
-// TODO: Move JsonStore fix into the lib
-//
-/*========================================================================
- * 
- * This section contains stuff that should be in Ext4, or stuff that
- * is up for discussion. It should be removed prior to Ext 4 final.
- *
- *========================================================================*/
-
-// This should be working as the alternateClassName but doesn't for some reason
-Ext.toolbar.Toolbar.SplitButton = Ext.button.Split;
-
-// DomHelper does not currently go through the ClassManager so there is no alternateClassName
-Ext.DomHelper = Ext.core.DomHelper;
-
-Ext.apply(Ext.panel.Panel.prototype, {
-    getToolbars : function(){
-        return this.getDockedItems('toolbar');
-    }
-});
-
-// Not sure if these are intended to be deprecated or they just haven't been moved over
-Ext.apply(Ext.menu.Menu.prototype, {
-    addSeparator : function() {
-        return this.add(Ext.create('Ext.menu.Separator'));
-    },
-    addElement : function(el) {
-        return this.add(Ext.create('Ext.menu.Item', {
-            el: el
-        }));
-    },
-    addItem : function(item) {
-        return this.add(item);
-    },
-    addMenuItem : function(config) {
-        return this.add(this.lookupComponent(config));
-    },
-    addText : function(text){
-        return this.add(Ext.create('Ext.menu.Item', {
-            plain: true,
-            text: text
-        }));
-    }
-});
-
-
-/*========================================================================
- * 
- * This section contains true compatibility overrides and should ship
- * with Ext 4 as an optional compatibility layer for Ext 3 code.
- * Ext.Compat is defined in ext3-core-compat.js.
- *
- *========================================================================*/
-
-(function(){
-    var compat = Ext.Compat,
-        deprecate = Ext.bind(compat.deprecate, compat),
-        notify = Ext.bind(compat.notify, compat),
-        breaking = Ext.bind(compat.breaking, compat);
-    
-    /*-------------------------------------------------------------
-     * Date (from the Ext.util folder in 3.x)
-     *-------------------------------------------------------------*/
-    (function(){
-        var nativeDate = window.Date,
-            utilDate = Ext.Date,
-            staticMappings = ['useStrict', 'formatCodeToRegex', 'parseFunctions', 'parseRegexes', 'formatFunctions', 'y2kYear', 
-                'MILLI', 'SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH', 'YEAR', 'defaults', 'dayNames', 'monthNames', 
-                'monthNumbers', 'formatCodes', 'getFormatCode', 'createFormat', 'createParser', 'parseCodes'],
-            staticOverrides = ['getShortMonthName', 'getShortDayName', 'getMonthNumber', 'isValid', 'parseDate'],
-            proto = ['dateFormat', 'format', 'getTimezone', 'getGMTOffset', 'getDayOfYear', 'getWeekOfYear', 'isLeapYear', 
-                'getFirstDayOfMonth', 'getLastDayOfMonth', 'getFirstDateOfMonth', 'getLastDateOfMonth', 'getDaysInMonth', 
-                'getSuffix', 'clone', 'isDST', 'clearTime', 'add', 'between'];
-            
-        // Static direct mappings. These are either private methods or any members
-        // that cannot be aliased as methods to include a warning. These are documented
-        // in the migration guide as breaking changes to be fixed.
-        Ext.Array.forEach(staticMappings, function(member) {
-            nativeDate[member] = utilDate[member];
-        });
-        
-        // Static overrides. These are public static methods that can be overridden
-        // as methods to include console warnings.
-        Ext.Array.forEach(staticOverrides, function(member) {
-            nativeDate[member] = function(){
-                deprecate({pkg:'Date', member:member, alt:'Ext.Date.'+member});
-                return utilDate[member].apply(utilDate, arguments);
-            };
-        });
-        
-        // Prototype (instance) overrides
-        Ext.Array.forEach(proto, function(member) {
-            nativeDate.prototype[member] = function() {
-                if(member !== 'dateFormat'){
-                    // dateFormat is actually private, and it is aliased publicly as "format". It needs
-                    // to be included, but we can skip the warning as it would be a duplicate of the format
-                    // warning and would actually be misleading since it won't have been called directly.
-                    // All other methods in this array are public and should give a warning.
-                    deprecate({pkg:'Date', member:'<date>.'+member, alt:'Ext.Date.'+member,
-                        msg:'Note that this is now a static method, so the date instance will be the first argument to the new version.'});
-                }
-                return utilDate[member].apply(utilDate, [this].concat(Array.prototype.slice.call(arguments)));
-            };
-        });
-    })();
-
-    /*-------------------------------------------------------------
-     * XTypes
-     *-------------------------------------------------------------*/
-    if (Ext.ClassManager) {
-        Ext.apply(Ext.ClassManager, {
-            instantiateByAlias: Ext.Function.createInterceptor(Ext.ClassManager.instantiateByAlias, function() {
-                var args = Ext.Array.toArray(arguments),
-                    alias = args.shift();
-                //
-                // These are xtypes that are not currently aliased in the framework code.
-                // Not sure if these should really be deprecated or not...
-                //
-                if(alias == 'widget.tbsplit'){
-                    deprecate({pkg:'Core', member:'tbsplit', alt:'splitbutton', type:'xtype'});
-                    Ext.ClassManager.setAlias('Ext.button.Split', 'widget.tbsplit');
-                }
-                if(alias == 'widget.progress'){
-                    deprecate({pkg:'Core', member:'progress', alt:'progressbar', type:'xtype'});
-                    Ext.ClassManager.setAlias('Ext.ProgressBar', 'widget.progress');
-                }
-            })
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * MicedCollection
-     *-------------------------------------------------------------*/
-    if (Ext.util.AbstractMixedCollection) {
-        Ext.apply(Ext.util.AbstractMixedCollection.prototype, {
-            removeKey : function() {
-                deprecate({pkg:'Ext.util.MixedCollection', member:'removeKey', alt:'removeAtKey'});
-                return this.removeAtKey.apply(this, arguments);
-            },
-            item : function() {
-                deprecate({pkg:'Ext.util.MixedCollection', member:'item', alt:'get'});
-                return this.get.apply(this, arguments);
-            },
-            itemAt : function() {
-                deprecate({pkg:'Ext.util.MixedCollection', member:'itemAt', alt:'getAt'});
-                return this.getAt.apply(this, arguments);
-            },
-            key : function() {
-                deprecate({pkg:'Ext.util.MixedCollection', member:'key', alt:'getByKey'});
-                return this.getByKey.apply(this, arguments);
-            }
-        });
-    }
-    if (Ext.util.MixedCollection) {
-        Ext.apply(Ext.util.MixedCollection.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.util.MixedCollection.prototype.constructor, function() {
-                this._origSort = this.sort;
-                this.sort = function(dir, fn) {
-                    if (Ext.isFunction(fn)) {
-                        deprecate({pkg:'Ext.util.MixedCollection', member:'sort (with a comparator fn)', alt:'sortBy', 
-                            msg:'Calling MixedCollection.sort and passing a comparator function as the second parameter '+
-                                'is no longer supported. See the docs for MixedCollection.sort to see the current '+
-                                'valid parameter list. When passing a comparator function, use sortBy instead.'});
-                        
-                        return this.sortBy(fn);
-                    }
-                    return this._origSort(arguments);
-                }
-            }),
-            keySort : function() {
-                deprecate({pkg:'Ext.util.MixedCollection', member:'keySort', alt:'sortByKey'});
-                return this.sortByKey.apply(this, arguments);
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * AbstractComponent
-     *-------------------------------------------------------------*/
-    if (Ext.AbstractComponent) {
-        Ext.apply(Ext.AbstractComponent.prototype, {
-            addClass : function() {
-                deprecate({pkg:'Ext.Component', member:'addClass', alt:'addCls'});
-                return this.addCls.apply(this, arguments);
-            },
-            removeClass : function() {
-                deprecate({pkg:'Ext.Component', member:'removeClass', alt:'removeCls'});
-                return this.removeCls.apply(this, arguments);
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Component
-     *-------------------------------------------------------------*/
-    if (Ext.Component) {
-        Ext.apply(Ext.Component.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.Component.prototype.initComponent, function() {
-                if(Ext.isDefined(this.applyTo)){
-                    deprecate({pkg:'Ext.Component', member:'applyTo', type:'config', alt:'renderTo',
-                        msg:'Applying components to existing markup via "applyTo" is no longer supported.'});
-                    
-                    var replaced = false;
-                    try{
-                        var target = Ext.get(this.applyTo);
-                        if (target) {
-                            var parent = target.parent();
-                            if (parent) {
-                                this.renderTo = parent;
-                                target.remove();
-                                replaced = true;
-                                notify({pkg:'Ext.Component', member:'applyTo', msg:'This component will attempt to render to '+
-                                    'the applyTo target\'s parent node ("' + parent.id + '"). If this did not work as expected then '+
-                                    'you will have to replace the applyTo config manually before this component will render properly.'})
-                            }
-                        }
-                    } catch(ex) {}
-                    
-                    if (!replaced) {
-                        breaking({pkg:'Ext.Component', member:'applyTo', msg:'Attempted to render the component to the applyTo target\'s '+
-                            'parent node, but this failed. You must resolve this manually before the component can render.'})
-                    }
-                }
-            })
-        });
-
-        Ext.define('Ext.BoxComponent', {
-            extend: 'Ext.Component',
-            constructor: function() {
-                deprecate({member:'Ext.BoxComponent', alt:'Ext.Component', 
-                    msg:'All functionality from BoxComponent is now directly in Component. '+
-                        'Replace "BoxComponent" with "Component" and/or xtype "box" with "component".'});
-                
-                this.callParent(arguments);
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * ComponentManager
-     *-------------------------------------------------------------*/
-    if (Ext.ComponentManager) {
-        var regMsg = 'Calling a separate function to register custom types is no longer necessary. '+
-                     'Switch your class definition to use Ext.define with "{0}" as the alias config.';
-        
-        var checkClassRef = function(pkg, cls, member) {
-            if (!Ext.isString(cls)) {
-                breaking({pkg:pkg, member:member, msg:'You must either convert the passed class reference to a string -- e.g. ' + 
-                    pkg + '.' + member + '("myclass", "Ext.ux.MyClass") -- or change your class definition to use Ext.define. '+
-                    'See the section in the Migration Guide on registering xtypes for more info.'});
-            }
-        };
-        
-        Ext.ComponentManager.registerType = function(xtype, cls){
-            deprecate({pkg:'ComponentManager', member:'registerType', msg:Ext.String.format(regMsg, 'widget.'+xtype)});
-            checkClassRef('ComponentManager', cls, 'registerType');
-            Ext.ClassManager.setAlias(cls, 'widget.'+xtype);
-        };
-        Ext.reg = function(xtype, cls){
-            deprecate({pkg:'Ext', member:'reg', msg:Ext.String.format(regMsg, 'widget.'+xtype)});
-            checkClassRef('Ext', cls, 'reg');
-            Ext.ClassManager.setAlias(cls, 'widget.'+xtype);
-        };
-        Ext.ComponentManager.registerPlugin = function(ptype, cls){
-            deprecate({pkg:'ComponentManager', member:'registerPlugin', msg:Ext.String.format(regMsg, 'plugin.'+ptype)});
-            checkClassRef('ComponentManager', cls, 'registerPlugin');
-            Ext.ClassManager.setAlias(cls, 'plugin.'+ptype);
-        };
-        Ext.preg = function(ptype, cls){
-            deprecate({pkg:'Ext', member:'preg', msg:Ext.String.format(regMsg, 'plugin.'+ptype)});
-            checkClassRef('Ext', cls, 'preg');
-            Ext.ClassManager.setAlias(cls, 'plugin.'+ptype);
-        };
-    }
-    
-    /*-------------------------------------------------------------
-     * Container
-     *-------------------------------------------------------------*/
-    if (Ext.container.AbstractContainer) {
-        Ext.apply(Ext.container.AbstractContainer.prototype, {
-            get: function(comp) {
-                deprecate({pkg:'Ext.Container', member:'get', alt:'getComponent'});
-                return this.getComponent(comp);
-            },
-            findById: function(id) {
-                deprecate({pkg:'Ext.Container', member:'findById', alt:'query', msg:'Use the query method with the # id syntax, e.g. comp.query("#"+id).'});
-                return this.query('#'+id);
-            }
-        });
-    }
-    if (Ext.container.Container) {
-        Ext.apply(Ext.container.Container.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.container.Container.prototype.initComponent, function() {
-                if (this.layout === 'form') {
-                    deprecate({pkg:'FormPanel', member:'form', type:'layout', 
-                        msg:'Form layout no longer exists, use a different container layout and allow each field\'s '+
-                            'Field layout to apply labels. Falling back to anchor layout.'});
-                    
-                    this.layout = 'anchor';
-                }
-            })
-        });
-    }
-
-    /*-------------------------------------------------------------
-     * Toolbar
-     *-------------------------------------------------------------*/
-    if (Ext.toolbar.Toolbar) {
-        Ext.apply(Ext.toolbar.Toolbar.prototype, {
-            addField : function(field){
-                deprecate({pkg:'Toolbar', member:'addField', alt:'add'});
-                return this.add(field);
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * PagingToolbar
-     *-------------------------------------------------------------*/
-    if (Ext.toolbar.Paging) {
-        Ext.apply(Ext.toolbar.Paging.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.toolbar.Paging.prototype.constructor, function(config) {
-                if (config.paramNames) {
-                    var msg = 'Instead of params specific to this toolbar you should set any needed options on the associated store/proxy. '+
-                        'See the header docs for Ext.data.Store for details. The defaults for PagingToolbar {start: \'start\', limit: \'limit\'} '+
-                        'would map to the store\'s proxy as {startParam: \'start\', limitParam: \'limit\'}.';
-                    
-                    if (config.store && config.store.proxy) {
-                        config.store.proxy.startParam = config.paramNames[start];
-                        config.store.proxy.limitParam = config.paramNames[limit];
-                        deprecate({pkg:'PagingToolbar', member:'paramNames', msg:msg});
-                    }
-                    else {
-                        breaking({pkg:'PagingToolbar', member:'paramNames', msg:msg + ' No proxy is available in the current PagingToolbar '+
-                            'configuration so this cannot be aliased automatically.'});
-                    }
-                    delete config.paramNames;
-                }
-                if (config.pageSize) {
-                    config.store.pageSize = config.pageSize;
-                    deprecate({pkg:'PagingToolbar', member:'pageSize', alt:'store.pageSize'});
-                }
-            }),
-            changePage : function(page){
-                deprecate({pkg:'PagingToolbar', member:'changePage', alt:'store.loadPage'});
-                this.store.loadPage(page);
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Views
-     *-------------------------------------------------------------*/
-    if (Ext.view.AbstractView) {
-        Ext.apply(Ext.view.AbstractView.prototype, {
-            initComponent : function(){
-                var isDef = Ext.isDefined;
-                if (!isDef(this.tpl) || !isDef(this.store) || !isDef(this.itemSelector)) {
-                    throw "DataView requires tpl, store and itemSelector configurations to be defined.";
-                }
-                Ext.view.AbstractView.superclass.initComponent.call(this);
-                if(Ext.isString(this.tpl) || Ext.isArray(this.tpl)){
-                    this.tpl = new Ext.XTemplate(this.tpl);
-                }
-                
-                if (isDef(this.overClass)){
-                    deprecate({pkg:'DataView', member:'overClass', alt:'overItemCls', type:'config'});
-                    this.overItemCls = this.overClass;
-                    delete this.overClass;
-                }
-                if (isDef(this.overCls)){
-                    deprecate({pkg:'DataView', member:'overCls', alt:'overItemCls', type:'config'});
-                    this.overItemCls = this.overCls;
-                    delete this.overCls;
-                }
-                if (isDef(this.selectedClass)){
-                    deprecate({pkg:'DataView', member:'selectedClass', alt:'selectedItemCls', type:'config'});
-                    this.selectedItemCls = this.selectedClass;
-                    delete this.selectedClass;
-                }
-                if (isDef(this.selectedCls)){
-                    deprecate({pkg:'DataView', member:'selectedCls', alt:'selectedItemCls', type:'config'});
-                    this.selectedItemCls = this.selectedCls;
-                    delete this.selectedCls;
-                }
-                
-                this.addEvents(
-                    'beforerefresh',
-                    'refresh'
-                );
-                this.addCmpEvents();
-                this.store = Ext.data.StoreManager.lookup(this.store);
-                this.all = new Ext.CompositeElementLite();
-                this.getSelectionModel().bindComponent(this);
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Panel
-     *-------------------------------------------------------------*/
-    if (Ext.panel.Panel) {
-        Ext.apply(Ext.panel.AbstractPanel.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.panel.AbstractPanel.prototype.initComponent, function() {
-                if (this.bodyCssClass) {
-                    var me = this,
-                        msg = '',
-                        bodyCssClass = me.bodyCssClass;
-                        
-                    if (Ext.isFunction(bodyCssClass)) {
-                        me.bodyCls = bodyCssClass();
-                        msg = 'Note that passing a function reference as the config value is no longer supported.'
-                    }
-                    else {
-                        me.bodyCls = bodyCssClass;
-                    }
-                    delete me.bodyCssClass;
-                    deprecate({pkg:'Ext.panel.Panel', member:'bodyCssClass', type:'config', alt:'bodyCls', msg:msg});
-                }
-            })
-        });
-        
-        Ext.apply(Ext.panel.Panel.prototype, {
-            getTopToolbar: function(){
-                notify('Panel now supports an arbitrary number of toolbars, so getTopToolbar() will return the top toolbar at index 0 if multiple are found');
-                var items = this.getToolbars();
-                return items.length > 0 ? items[0] : null;
-            },
-            getBottomToolbar: function(){
-                notify('Panel now supports an arbitrary number of toolbars, so getBottomToolbar() will return the bottom toolbar at index 0 if multiple are found');
-                var items = this.getToolbars();
-                return items.length > 0 ? items[0] : null;
-            }
-        });
-    }
-
-    /*-------------------------------------------------------------
-     * Layouts
-     *-------------------------------------------------------------*/
-    if (Ext.layout.container.Accordion) {
-        Ext.apply(Ext.layout.container.Accordion.prototype, {
-            constructor: Ext.Function.createSequence(Ext.layout.container.Accordion.prototype.constructor, function() {
-                notify('AccordionLayout now defaults to animating expand/collapse. To revert to the 3.x default behavior set animate:false on the layout.')
-            })
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * TablePanel
-     *-------------------------------------------------------------*/
-    if (Ext.panel.Table) {
-        Ext.apply(Ext.panel.Table.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.panel.Table.prototype.initComponent, function() {
-                if (Ext.isDefined(this.preventHeaders)) {
-                    deprecate({pkg:'Ext.grid.Panel', member:'preventHeaders', type:'config', alt:'hideHeaders'});
-                    this.hideHeaders = this.preventHeaders;
-                    delete this.preventHeaders;
-                }
-            })
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Grid components
-     *-------------------------------------------------------------*/
-    if (Ext.grid.Panel) {
-        Ext.apply(Ext.grid.Panel.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.grid.Panel.prototype.constructor, function(config) {
-                if (config.trackMouseOver !== undefined) {
-                    deprecate({pkg:'Ext.GridPanel', member:'trackMouseOver', alt:'trackOver', type:'config',
-                        msg:'Specify this as an attribute of the "viewConfig" config (e.g. viewConfig: {trackOver: false}).'});
-                    
-                    config.viewConfig = config.viewConfig || {};
-                    config.viewConfig.trackOver = config.viewConfig.trackOver || config.trackMouseOver;
-                    delete config.trackMouseOver; 
-                }
-                if (config.stripeRows !== undefined) {
-                    deprecate({pkg:'Ext.GridPanel', member:'stripeRows', type:'config',
-                        msg:'The stripeRows option should now be passed as an attribute of the "viewConfig" config (e.g. viewConfig: {stripeRows: true}).'});
-                    
-                    config.viewConfig = config.viewConfig || {};
-                    config.viewConfig.stripeRows = config.viewConfig.stripeRows || config.stripeRows;
-                    delete config.stripeRows; 
-                }
-                if (config.cm || config.colModel) {
-                    deprecate({pkg:'Ext.GridPanel', member:'colModel/cm', type:'config',
-                        msg:'Grids no longer use a ColumnModel class. Just specify the columns array config instead.'});
-                    
-                    // the ColumnModel mock constructor below just returns the columns array
-                    config.columns = config.cm || config.colModel;
-                    delete config.cm;
-                    delete config.colModel;
-                }
-                var cols = config.columns || this.columns;
-                if (cols && Ext.isArray(cols)) {
-                    Ext.each(cols, function(col) {
-                        if (col.id && !col.dataIndex) {
-                            notify('Grid column "' + col.id + '" is defined with an id, but no dataIndex. In Ext 4 the id is used to reference the '+
-                                'columns as components, and dataIndex is used to map back to the data id. Please add dataIndex to all columns.');
-                            col.dataIndex = col.id;
-                        }
-                    });
-                }
-                if (config.store && config.store instanceof Ext.data.GroupingStore) {
-                    notify({pkg:'Ext.GridPanel', msg:'Attempting to convert a GroupingStore store config into a Grouping feature. See the '+
-                        'GroupingStore constructor warning for additional details.'});
-                        
-                    config.features = config.features || [];
-                    config.features.push(Ext.create('Ext.grid.feature.Grouping'));
-                }
-            }),
-            
-            initComponent: Ext.Function.createInterceptor(Ext.grid.Panel.prototype.initComponent, function() {
-                if (this.autoExpandColumn !== undefined) {
-                    deprecate({pkg:'Ext.grid.Panel', member:'autoExpandColumn', alt:'flex (header config)', type:'config',
-                        msg:'You can set "flex: 1" in a specific header config for behavior equivalent to autoExpandColumn.'});
-                        
-                    var id;
-                    Ext.Array.each(this.headers, function(header){
-                        id = header.id || header.dataIndex;
-                        if(id === this.autoExpandColumn){
-                            header.flex = 1;
-                            return false;
-                        }
-                    }, this);
-                }
-            })
-        });
-        
-        Ext.apply(Ext.grid.GridPanel.prototype, {
-            getColumnModel: function(){
-                if (!this.colModel && !this.cm) {
-                    this.cm = this.colModel = new Ext.grid.ColumnModel({
-                        columns: this.columns
-                    });
-                }
-                return this.cm;
-            }
-        });
-        
-        Ext.grid.EditorGridPanel = function(config) {
-            deprecate({pkg:'Ext.grid.EditorGridPanel', msg:'EditorGridPanel no longer exists as a separate class. Instead just '+
-                'create a standard GridPanel and include the CellEditing plugin, e.g. "plugins: Ext.create("Ext.grid.plugin.CellEditing", {...})'});
-            
-            return Ext.createWidget('grid', Ext.apply(config || {}, {
-                plugins: Ext.create('Ext.grid.plugin.CellEditing', {
-                    clicksToEdit: 1
-                })
-            }));
-        }
-    }
-    
-    if (Ext.grid.View) {
-        Ext.apply(Ext.grid.View.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.grid.View.prototype.constructor, function(config) {
-                if(Ext.isFunction(config.getRowClass)){
-                    var getRowClass = config.getRowClass;
-                    this.__getRowClass = Ext.bind(getRowClass, this);
-                    delete config.getRowClass;
-                    
-                    this.getRowClass = function(rec, rowIndex, rowParams, store){
-                        var result = this.__getRowClass(rec, rowIndex, rowParams, store);
-                        if (rowParams.body) {
-                            delete rowParams.body;
-                            breaking({pkg:'Ext.grid.View', member:'getRowClass.rowParams.body', single:true,
-                                msg:'To implement a custom row body you must add the RowBody feature (ftype:"rowbody") '+
-                                    'to the grid\'s viewConfig and override the "getAdditionalData" template method '+
-                                    '(or use the Ext.grid.RowBodyPlugin helper class). Unfortunately this cannot be '+
-                                    'inferred at design time so it must be fixed manually.'});
-                        }
-                        if (rowParams.bodyStyle) {
-                            delete rowParams.bodyStyle;
-                            deprecate({pkg:'Ext.grid.View', member:'getRowClass.rowParams.bodyStyle', single:true,
-                                msg:'To implement a custom row styles you must add the RowBody feature (ftype:"rowbody") '+
-                                    'to the grid\'s viewConfig and override the "getAdditionalData" template method '+
-                                    '(or use the Ext.grid.RowBodyPlugin helper class). Note that in 3.x this property '+
-                                    'was a CSS style spec, whereas now you specify "rowBodyCls" as a CSS classname instead. Ignoring for now.'});
-                        }
-                        if (rowParams.tstyle) {
-                            delete rowParams.tstyle;
-                            deprecate({pkg:'Ext.grid.View', member:'getRowClass.rowParams.tstyle', single:true,
-                                msg:'Grid row bodies no longer use a wrapping TABLE element, so the "tstyle" property '+
-                                    'no longer directly applies. If you have CSS styles that still need to be applied, you '+
-                                    'should add the RowBody feature (ftype:"rowbody") to the grid\'s viewConfig and override '+
-                                    'the "getAdditionalData" template method (or use the Ext.grid.RowBodyPlugin helper class). '+
-                                    'Note that in 3.x this property was a CSS style spec, whereas now you would use the "rowBodyCls" '+
-                                    'CSS classname instead (and adjust for the fact that there is no TABLE if needed). Ignoring for now.'});
-                        }
-                        return result;
-                    };
-                }
-            })
-        });
-        
-        Ext.grid.GroupingView = function(config) {
-            breaking({pkg:'Ext.grid.GroupingView', msg:'GroupingView no longer exists as a separate class, and grid views should '+
-                'not need to be instantiated directly. Instead just create a standard GridPanel and include the Grouping feature, '+
-                'e.g. "features: Ext.create("Ext.grid.feature.Grouping", {...}). Unfortunately there is no way to alias a call to this '+
-                'constructor properly, so you\'ll need to adjust your GridPanel constructor as noted to resolve this.'});
-        }
-    }
-    
-    if (Ext.grid.header.Container) {
-        Ext.apply(Ext.grid.header.Container.prototype, {
-            constructor: Ext.Function.createSequence(Ext.grid.header.Container.prototype.constructor, function() {
-                this.__prepareData = this.prepareData;
-                this.prepareData = function() {
-                    var obj = this.__prepareData.apply(this, arguments);
-                    if (obj.cssWarning) {
-                        delete obj.cssWarning;
-                        deprecate({pkg:'Ext.grid.Panel', single:true, msg:'Your grid column renderer is including the legacy "css" attribute '+
-                            'in the returned metaData object. This has been renamed to "tdCls" so you should change the attribute name in your renderer.'});
-                    }
-                    return obj;
-                }
-            })
-        });
-    }
-    
-    if (Ext.grid.Header) {
-        Ext.apply(Ext.grid.Header.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.grid.Header.prototype.initComponent, function() {
-                if (Ext.isDefined(this.header)) {
-                    deprecate({pkg:'Ext.grid.Panel', member:'header', alt:'text', type:'config', single: true,
-                        msg:'In 3.x the grid had a "columns" array containing "header" configs for the title of each column. '+
-                            'In 4.0 the grid has a "headers" array and you should specify the "text" config for each header.'});
-                            
-                    this.text = this.header;
-                    delete this.header;
-                }
-            })
-        });
-    }
-    
-    Ext.grid.ColumnModel = function(config) {
-        return Ext.applyIf(config.columns ? config.columns : config, {
-            on: Ext.emptyFn,
-            addListener: Ext.emptyFn,
-            getColumnId: Ext.emptyFn,
-            getColumnAt: Ext.emptyFn,
-            setConfig: Ext.emptyFn,
-            getColumnById: Ext.emptyFn,
-            getIndexById: Ext.emptyFn,
-            moveColumn: Ext.emptyFn,
-            getColumnCount: Ext.emptyFn,
-            getColumnsBy: Ext.emptyFn,
-            isSortable: Ext.emptyFn,
-            isMenuDisabled: Ext.emptyFn,
-            getRenderer: Ext.emptyFn,
-            getRendererScope: Ext.emptyFn,
-            setRenderer: Ext.emptyFn,
-            getColumnWidth: Ext.emptyFn,
-            setColumnWidth: Ext.emptyFn,
-            getTotalWidth: Ext.emptyFn,
-            getColumnHeader: Ext.emptyFn,
-            setColumnHeader: Ext.emptyFn,
-            getColumnTooltip: Ext.emptyFn,
-            setColumnTooltip: Ext.emptyFn,
-            getDataIndex: Ext.emptyFn,
-            setDataIndex: Ext.emptyFn,
-            findColumnIndex: Ext.emptyFn,
-            isCellEditable: Ext.emptyFn,
-            getCellEditor: Ext.emptyFn,
-            setEditable: Ext.emptyFn,
-            isHidden: Ext.emptyFn,
-            isFixed: Ext.emptyFn,
-            isResizable: Ext.emptyFn,
-            setHidden: Ext.emptyFn,
-            setEditor: Ext.emptyFn,
-            destroy: Ext.emptyFn,
-            setState: Ext.emptyFn
-        });
-    };
-    
-    if (Ext.grid.Column) {
-        Ext.Compat.bindProperty({owner:Ext.grid.Column, name:'types', defaultValue:{},
-            getterMsg: function(){
-                deprecate({pkg:'Ext.grid.Column', member:'types', type:'property', alt:'alias (config)',
-                    msg:'The new approach to creating a custom column type is to specify the alias config '+
-                    'within your column\'s class definition (e.g., alias: ["widget.mycolumn"]). You could also '+
-                    'call the setAlias method after the class is defined.'});
-            }
-        });
-    }
-    
-    // temp aliases -- these will be added into Ext 4
-    Ext.apply(Ext.grid.Panel.prototype, {
-        getStore: function() {
-            return this.store;
-        }
-    });
-    
-    if (Ext.selection.Model) {
-        Ext.apply(Ext.selection.Model.prototype, {
-            selectRow: function(index){
-                deprecate({pkg:'Ext.grid.RowSelectionModel', member:'selectRow', alt:'Ext.selection.RowModel.selectRange', 
-                    msg:'Note that selectRange requires both start and end rows as its first two arguments (defaulting both to '+index+').'});
-                
-                return this.selectRange(index, index);
-            },
-            getSelections: function(){
-                deprecate({pkg:'Ext.grid.RowSelectionModel', member:'getSelections', alt:'Ext.selection.RowModel.getSelection'});
-                return this.getSelection();
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Tree (removed classes)
-     *-------------------------------------------------------------*/
-    Ext.tree.TreeNode = function(config){
-        deprecate({pkg:'Ext.tree.TreeNode', msg:'This class is no longer needed. The Tree now uses standard Records that get decorated '+
-            'by the NodeInterface class in Ext 4.'});
-        Ext.apply(this, config);
-    };
-    Ext.tree.AsyncTreeNode = function(config){
-        deprecate({pkg:'Ext.tree.AsyncTreeNode', msg:'This class is no longer needed. Specify a TreeStore with an AjaxProxy instead.'});
-        Ext.apply(this, config);
-    };
-    Ext.tree.AsyncTreeNode.prototype = {
-        expand: function(){
-            if (this.store) {
-                this.store.load({
-                    url: this.url || this.dataUrl
-                });
-            }
-        }
-    };
-    
-    Ext.tree.TreeSorter = function(tree, config){
-        deprecate({pkg:'Ext.tree.TreeSorter', msg:'This class is no longer needed. Specify a TreeStore with standard "sorter" config options instead.'});
-        Ext.apply(this, config);
-    };
-    
-    Ext.tree.TreeLoader = function(config){
-        deprecate({pkg:'Ext.tree.TreeLoader', msg:'This class is no longer needed. Specify a TreeStore with standard store options to load the tree.'});
-        Ext.apply(this, config);
-    };
-    
-    /*-------------------------------------------------------------
-     * TreePanel
-     *-------------------------------------------------------------*/
-    if (Ext.tree.Panel) {
-        Ext.apply(Ext.tree.Panel.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.tree.Panel.prototype.constructor, function(config) {
-                if (config.hlDrop) {
-                    delete config.hlDrop;
-                    deprecate({pkg:'Ext.tree.TreePanel', member:'hlDrop', type:'config', 
-                        msg:'Highlighting tree nodes on drop is no longer supported. You can simply remove this config.'});
-                }
-                if (config.hlColor) {
-                    delete config.hlDrop;
-                    deprecate({pkg:'Ext.tree.TreePanel', member:'hlColor', type:'config',
-                        msg:'Highlighting tree nodes on drop is no longer supported. You can simply remove this config.'});
-                }
-                
-                var ddConfig = config.ddConfig || {};
-                if (Ext.isDefined(config.enableDrag)) {
-                    deprecate({pkg:'Ext.tree.TreePanel', member:'enableDrag', type:'config', alt:'ddConfig.enableDrag'});
-                    ddConfig.enableDrag = config.enableDrag;
-                    delete config.enableDrag;
-                }
-                if (Ext.isDefined(config.enableDrop)) {
-                    deprecate({pkg:'Ext.tree.TreePanel', member:'enableDrop', type:'config', alt:'ddConfig.enableDrop'});
-                    ddConfig.enableDrop = config.enableDrop;
-                    delete config.enableDrop;
-                }
-                if (Ext.isDefined(config.enableDD)) {
-                    var msg = config.enableDD ? 'Note that ddConfig defaults to enabling both drag and drop by default in Ext 4. Since you are '+
-                        'currently passing "enableDD: true", in this case the config can simply be ommitted entirely.' : '';
-                    
-                    ddConfig = {
-                        enableDrag: config.enableDD,
-                        enableDrop: config.enableDD
-                    };
-                    delete config.enableDD;
-                    deprecate({pkg:'Ext.tree.TreePanel', member:'enableDD', type:'config', alt:'ddConfig', msg:msg});
-                }
-                config.ddConfig = ddConfig;
-                
-                var url = config.dataUrl || this.dataUrl;
-                if (url) {
-                    deprecate({pkg:'Ext.tree.TreePanel', member:'dataUrl', type:'config', alt:'TreeStore',
-                        msg:'The TreePanel no longer supports loading data directly. Creating an implicit TreeStore using the url: '+url});
-                    
-                    this.loader = { dataUrl: url };
-                    delete config.dataUrl;
-                    delete this.dataUrl;
-                }
-                else if (config.loader) {
-                    this.loader = config.loader;
-                    delete config.loader;
-                    deprecate({pkg:'Ext.tree.TreePanel', member:'loader', type:'config', alt:'TreeStore',
-                        msg:'The TreeLoader class and TreePanel.loader config have been removed. Trees now use the TreeStore '+
-                            'which provides all standard Ext.data.Store loading capabilities.'});
-                }
-                
-                if (config.root && (config.root instanceof Ext.tree.AsyncTreeNode || config.root.nodeType == 'async')) {
-                    config.loader = this.loader;
-                }
-                this.applyCompatOptions();
-            }),
-            
-            initComponent: Ext.Function.createSequence(Ext.tree.Panel.prototype.initComponent, function() {
-                this.on('itemclick', function(view, model, el, idx, e){
-                    if (this.events['click']) {
-                        model.attributes = model.attributes || model.data;
-                        this.fireEvent('click', model, e);
-                        deprecate({pkg:'Ext.tree.TreePanel', member:'click', type:'event', alt:'itemclick', 
-                            msg:'Note that the argument order has changed, and that the data argument was a node in 3.x and is now '+
-                                'the selected model. Instead of node.attributes you can access the data via model.data.'})
-                    }
-                });
-            }),
-            
-            applyCompatOptions: function(){
-                var loader = this.loader;
-                if (loader && (loader.url || loader.dataUrl || loader.proxy)) {
-                    var urlProp = loader.url ? 'url' : 'dataUrl',
-                        proxy = loader.proxy || {
-                            type: 'ajax',
-                            url: loader[urlProp]
-                        },
-                        storeConfig = {
-                            proxy: proxy
-                        }
-                    
-                    if (this.root) {
-                        storeConfig.root = this.root;
-                        delete this.root;
-                    }
-                    this.store = new Ext.data.TreeStore(storeConfig);
-                    this.loader.store = this.store;
-                    
-                    notify({pkg:'Ext.tree.Panel', msg:'Using the TreeLoader.' + urlProp + 
-                        ' config to generate a default TreeStore + Proxy with the url: '+loader[urlProp]});
-                }
-            },
-            
-            // Aliased in TreePanel
-//            setRootNode: function(root){
-//                deprecate({pkg:'Ext.tree.Panel', member:'setRootNode', alt:'TreeStore.setRootNode', 
-//                    msg:'Alternately you could add a "root" option to your TreeStore config.'});
-//                
-//                if (this.store) {
-//                    this.store.setRootNode(root);
-//                }
-//                else {
-//                    this.root = root;
-//                    this.applyCompatOptions();
-//                }
-//            },
-            
-            // Aliased in TreePanel
-//            getRootNode : function(){
-//                deprecate({pkg:'Ext.tree.Panel', member:'getRootNode', alt:'TreeStore.getRootNode'});
-//                return this.store.getRootNode.apply(this.store, arguments);
-//            },
-            
-            getNodeById : function(){
-                deprecate({pkg:'Ext.tree.Panel', member:'getNodeById', alt:'TreeStore.getNodeById',
-                    msg:'If you have a TreePanel reference you can call treePanel.getStore().getNodeById("id").'});
-                
-                return this.store.getNodeById.apply(this.store, arguments);
-            },
-            
-            getChecked : function(){
-                deprecate({pkg:'Ext.tree.Panel', member:'getChecked', alt:'Ext.tree.View.getChecked',
-                    msg:'Note that in 3.x this method returned objects of type TreeNode. In 4.0 it returns standard Records, '+
-                        'so the code that processes the checked items will have to be adjusted accordingly. For compatibility '+
-                        'the record\'s data objects are being returned, as each record\'s data is now decorated with the node '+
-                        'interface so they should match the 3.x API. However your 4.0 code should expect full Record objects '+
-                        'instead and will access the node attributes via Record.get(\'attrName\') or Record.data.attrName.'});
-                
-                var recs = this.getView().getChecked(),
-                    nodes = [];
-                
-                Ext.each(recs, function(rec){
-                    nodes.push(rec.data);
-                });
-                
-                return nodes;
-            }
-        });
-    }
-    
-    if (Ext.data.TreeStore) {
-        Ext.override(Ext.data.TreeStore, {
-            fillNode: function(node, records) {
-                var me = this,
-                    ln = records ? records.length : 0,
-                    i = 0, sortCollection;
-        
-//                if (ln && me.sortOnLoad && !me.remoteSort && me.sorters && me.sorters.items) {
-//                    sortCollection = Ext.create('Ext.util.MixedCollection');
-//                    sortCollection.addAll(records);
-//                    sortCollection.sort(me.sorters.items);
-//                    records = sortCollection.items;
-//                }
-                
-                node.set('loaded', true);
-                for (; i < ln; i++) {
-                    node.appendChild(records[i], undefined, true);
-                }
-                
-                return records;
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * SelectionModel
-     *-------------------------------------------------------------*/
-    if (Ext.selection.RowModel) {
-        Ext.apply(Ext.selection.RowModel.prototype, {
-            constructor: Ext.Function.createSequence(Ext.selection.RowModel.prototype.constructor, function() {
-                this.on('select', function(sm, rec, idx){
-                    if (this.events['rowselect']) {
-                        this.fireEvent('rowselect', sm, idx, rec);
-                        deprecate({pkg:'Ext.grid.RowSelectionModel', member:'rowselect', type:'event', alt:'select', 
-                            msg:'Note that the argument order has changed (the index and record/model args have been switched).'})
-                    }
-                });
-                this.on('deselect', function(sm, rec, idx){
-                    if (this.events['rowdeselect']) {
-                        this.fireEvent('rowdeselect', sm, idx, rec);
-                        deprecate({pkg:'Ext.grid.RowSelectionModel', member:'rowdeselect', type:'event', alt:'deselect', 
-                            msg:'Note that the argument order has changed (the index and record/model args have been switched).'})
-                    }
-                });
-            })
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Window
-     *-------------------------------------------------------------*/
-    if (Ext.window.Window) {
-        Ext.apply(Ext.window.Window.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.window.Window.prototype.constructor, function(config) {
-                if (config.closeAction === 'close') {
-                    deprecate({pkg:'Ext.Window', member:'closeAction', type:'config', 
-                        msg:'The default value of "close" is no longer valid. Use "destroy" instead.'});
-                        
-                    delete config.closeAction;
-                    this.closeAction = 'destroy';
-                }
-            })
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Forms
-     *-------------------------------------------------------------*/
-    if (Ext.form.Basic) {
-        Ext.apply(Ext.form.Basic.prototype, {
-            add: function() {
-                deprecate({pkg:'Ext.form.Basic', member:'add'});
-                return this;
-            },
-            
-            remove: function(field) {
-                deprecate({pkg:'Ext.form.Basic', member:'remove'});
-                return this;
-            },
-            
-            cleanDestroyed: function() {
-                deprecate({pkg:'Ext.form.Basic', member:'cleanDestroyed'});
-            },
-            
-            render: function() {
-                deprecate({pkg:'Ext.form.Basic', member:'render'});
-                return this;
-            },
-            
-            getFieldValues: function(dirtyOnly) {
-                deprecate({pkg:'Ext.form.Basic', member:'getFieldValues', alt:'getValues'});
-                return this.getValues(false, dirtyOnly);
-            },
-    
-            callFieldMethod: function(fnName, args) {
-                deprecate({pkg:'Ext.form.Basic', member:'callFieldMethod'});
-    
-                args = args || [];
-                this.getFields().each(function(f) {
-                    if (Ext.isFunction(f[fnName])) {
-                        f[fnName].apply(f, args);
-                    }
-                });
-                return this;
-            }
-        });
-    }
-
-    if (Ext.form.Panel) {
-        Ext.apply(Ext.form.Panel.prototype, {
-            monitorValid: false,
-            monitorPoll: 200,
-            
-            initComponent: Ext.Function.createInterceptor(Ext.form.Panel.prototype.initComponent, function() {
-                var me = this,
-                    fieldDefaultsProps = {
-                        hideLabels: 'hideLabel',
-                        labelAlign: 'labelAlign',
-                        labelPad: 'labelPad',
-                        labelSeparator: 'labelSeparator',
-                        labelWidth: 'labelWidth'
-                    },
-                    fieldDefaults = me.fieldDefaults || (me.fieldDefaults = {});
-    
-                Ext.iterate(fieldDefaultsProps, function(from, to) {
-                    if (from in me) {
-                        deprecate({pkg:'Ext.form.Panel', member:from, type:'config', 
-                            msg:'Use the fieldDefaults config object with a "' + to + '" property instead.'});
-                            
-                        fieldDefaults[to] = me[from];
-                    }
-                });
-    
-                if (me.hasOwnProperty('monitorValid')) {
-                    deprecate({pkg:'Ext.form.Panel', member:'monitorValid', alt:'pollForChanges'});
-                }
-                if (me.hasOwnProperty('monitorPoll')) {
-                    deprecate({pkg:'Ext.form.Panel', member:'monitorPoll', alt:'pollInterval'});
-                }
-            }),
-            
-            startMonitoring: function() {
-                deprecate({pkg:'Ext.form.Panel', member:'startMonitoring', alt:'startPolling'});
-                this.startPolling(this.monitorPoll);
-            },
-            
-            stopMonitoring: function() {
-                deprecate({pkg:'Ext.form.Panel', member:'stopMonitoring', alt:'stopPolling'});
-                this.stopPolling();
-            }
-        });
-    }
-
-    if (Ext.form.field.Base) {
-        Ext.apply(Ext.form.field.Base.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.form.field.Base.prototype.initComponent, function() {
-                // Many legacy examples modify the default msgTarget on the Ext.form.Field class's prototype; this doesn't
-                // work anymore since Field is a mixin. Copy to Ext.form.field.Base and inform about change and the new
-                // recommended FormPanel.fieldDefaults. Only do this once rather than for every field.
-                var msgTarget = Ext.form.Field.prototype.msgTarget;
-                if (msgTarget && msgTarget !== 'qtip') {
-                    deprecate({pkg:'Ext.form.Field', member:'msgTarget', type:'config', single: true,
-                        msg:'Found an overridden value for Ext.form.Field.prototype.msgTarget -- Ext.form.Field is ' +
-                            'now Ext.form.field.Base; either override msgTarget on Ext.form.field.Base\'s prototype ' +
-                            'or use the new recommended Ext.form.Panel#fieldDefaults object instead.'});
-                    
-                    Ext.form.field.Base.prototype.msgTarget = Ext.form.Field.prototype.msgTarget;
-                }
-            })
-        });
-    }
-
-    if (Ext.form.field.Checkbox) {
-        Ext.apply(Ext.form.field.Checkbox.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.form.field.Checkbox.prototype.initComponent, function() {
-                this.addEvents(
-                    /**
-                     * @event check
-                     * Fires when the checkbox is checked or unchecked.
-                     * @deprecated Use the 'change' event instead.
-                     * @param {Ext.form.field.Checkbox} this This checkbox
-                     * @param {Boolean} checked The new checked value
-                     */
-                    'check'
-                );
-                // TODO is there a clean way to throw a deprecation warning when the user listens for the check event?
-            }),
-            
-            onChange: Ext.Function.createInterceptor(Ext.form.field.Checkbox.prototype.onChange, function(newVal, oldVal) {
-                this.fireEvent('check', this, this.checked);
-            })
-        });
-    }
-
-    if (Ext.form.CheckboxGroup) {
-        var cbgSetValue = Ext.form.CheckboxGroup.prototype.setValue;
-    
-        Ext.apply(Ext.form.CheckboxGroup.prototype, {
-    
-            initComponent: Ext.Function.createInterceptor(Ext.form.CheckboxGroup.prototype.initComponent, function() {
-                var me = this,
-                    items = me.items;
-    
-                // Handle the old structure where the 'items' could be a set of column configs
-                if (items && items[0] && 'columnWidth' in items[0] && me.layout !== 'column') {
-                    deprecate({pkg:'Ext.form.CheckboxGroup', type:'config',
-                        msg:'CheckboxGroup and RadioGroup no longer accept implicit column containers in the "items" ' +
-                            'config. If you wish to use a custom column arrangement, set layout:"column" and create ' +
-                            'a standard items structure with container xtypes.'});
-                    me.layout = 'column';
-                    Ext.Array.forEach(items, function(column) {
-                        column.xtype = 'container';
-                        column.defaultType = me.defaultType;
-                    });
-                }
-            }),
-            
-            setValue: function(id, value) {
-                var me = this,
-                    f;
-                if (arguments.length === 1) {
-                    value = id;
-                    if (Ext.isObject(value)) {
-                        cbgSetValue.call(me, value);
-                    }
-                    if (Ext.isString(value)) {
-                        deprecate({pkg:'Ext.form.CheckboxGroup', member:'setValue', 
-                            msg:'The setValue method no longer accepts a String argument. Use the new Object form instead.'});
-                            
-                        me.setValueForItem(value);
-                    }
-                    else if (Ext.isArray(value)) {
-                        deprecate({pkg:'Ext.form.CheckboxGroup', member:'setValue', 
-                            msg:'The setValue method no longer accepts an Array argument. Use the new Object form instead.'});
-                            
-                        me.batchChanges(function() {
-                            Ext.each(value, function(val, idx){
-                                if (Ext.isObject(val) && val.setValue) { // array of checkbox components to be checked
-                                    val.setValue(true);
-                                }
-                                else if (Ext.isString(val)) {
-                                    f = me.getBox(val);
-                                    if (f) {
-                                        f.setValue(true);
-                                    }
-                                }
-                                else { // an array of boolean values
-                                    var item = me.getBoxes()[idx];
-                                    if (item) {
-                                        item.setValue(val);
-                                    }
-                                }
-                            });
-                        });
-                    }
-                }
-                else {
-                    deprecate({pkg:'Ext.form.CheckboxGroup', member:'setValue', 
-                        msg:'The setValue method no longer accepts a two-argument form. Use the new single Object form instead.'});
-                        
-                    f = me.getBox(id);
-                    if (f) {
-                        f.setValue(value);
-                    }
-                }
-    
-                return me;
-            },
-    
-            // private
-            setValueForItem : function(val){
-                deprecate({pkg:'Ext.form.CheckboxGroup', member:'setValueForItem'});
-                var me = this;
-                val = String(val).split(',');
-                me.batchChanges(function() {
-                    me.eachBox(function(item) {
-                        if (val.indexOf(item.inputValue) > -1) {
-                            item.setValue(true);
-                        }
-                    });
-                });
-            },
-    
-            // private
-            getBox : function(id){
-                deprecate({pkg:'Ext.form.CheckboxGroup', member:'getBox'});
-                var box = null;
-                this.eachBox(function(f) {
-                    if (id == f || f.dataIndex == id || f.id == id || f.getName() == id) {
-                        box = f;
-                        return false;
-                    }
-                });
-                return box;
-            }
-        });
-    }
-
-
-    /*-------------------------------------------------------------
-     * CompositeField
-     *-------------------------------------------------------------*/
-    if (Ext.form.FieldContainer) {
-        Ext.define('Ext.form.CompositeField', {
-            extend: 'Ext.form.FieldContainer',
-            alias: 'widget.compositefield',
-            uses: ['Ext.layout.container.HBox'],
-    
-            isComposite: true,
-            combineErrors: true,
-    
-            layout: {
-                type: 'hbox',
-                defaultMargins: {top: 0, right: 5, bottom: 0, left: 0}
-            },
-            baseDefaults: {
-                hideLabel: true
-            },
-    
-            initComponent: function() {
-                deprecate({member:'Ext.form.CompositeField', alt:'Ext.form.FieldContainer',
-                    msg:'What used to be CompositeField has been replaced by the more flexible FieldContainer. '+
-                        'We will reintroduce a true Composite field in a future release.'});
-    
-                this.defaults = Ext.apply({}, this.defaults, this.baseDefaults);
-    
-                this.callParent(arguments);
-            }
-        });
-    }
-    
-    
-    /*-------------------------------------------------------------
-     * ComboBox
-     *-------------------------------------------------------------*/
-    if (Ext.form.field.ComboBox) {
-        Ext.apply(Ext.form.field.ComboBox.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.form.field.ComboBox.prototype.initComponent, function() {
-                var me = this,
-                    isDef = Ext.isDefined;
-                
-                // shortcut for configs that just changed names:
-                var remap = function(cfg, alt){
-                    if(isDef(me[cfg])){
-                        deprecate({pkg:'Ext.form.field.ComboBox', member:cfg, type:'config', alt:alt});
-                        me[alt] = me[cfg];
-                        delete me[cfg];
-                    }
-                };
-                remap('listAlign', 'pickerAlign');
-                remap('mode', 'queryMode');
-                remap('triggerClass', 'triggerCls');
-    
-                // shortcut for configs that were moved into the listConfig object:
-                var listConfig = me.listConfig || (me.listConfig = {}),
-                remapToListConfig = function(cfg, alt) {
-                    if(isDef(me[cfg])){
-                        // the defaultListConfig has been applied at this point, so check that this 
-                        // option was not simply the default value applied by the superclass
-                        if(!isDef(me.defaultListConfig[cfg]) || me.defaultListConfig[cfg] !== me[cfg]) {
-                            deprecate({pkg:'Ext.form.field.ComboBox', member:cfg, type:'config', alt:'listConfig.' + alt});
-                            listConfig[alt] = me[cfg];
-                            delete me[cfg];
-                        }
-                    }
-                };
-                remapToListConfig('itemSelector', 'itemSelector');
-                remapToListConfig('listClass', 'cls');
-                remapToListConfig('listWidth', 'width');
-                remapToListConfig('loadingText', 'loadingText');
-                remapToListConfig('minHeight', 'minHeight');
-                remapToListConfig('minListWidth', 'minWidth');
-                remapToListConfig('maxHeight', 'maxHeight');
-                remapToListConfig('resizable', 'resizable');
-                remapToListConfig('selectedClass', 'selectedItemCls');
-                remapToListConfig('shadow', 'shadow');
-    
-                // shortcut for configs that were completely removed with no replacement:
-                var remove = function(cfg){
-                    if(isDef(me[cfg])){
-                        notify({pkg:'Ext.form.field.ComboBox', member:cfg,
-                            msg:'This config is no longer needed and has no replacement -- just remove it from your code.'});
-                        delete me[cfg];
-                    }
-                };
-                remove('autoCreate');
-                remove('clearFilterOnReset');
-                remove('handleHeight');
-                remove('hiddenId');
-                remove('hiddenName');
-                remove('lazyInit');
-                remove('lazyRender');
-                remove('title');
-                
-                // non-standard mappings:
-                if(isDef(me.tpl)){
-                    deprecate({pkg:'Ext.form.field.ComboBox', member:'tpl', type:'config', alt:'getInnerTpl (method)',
-                        msg:'There is no config for providing the combo\'s item template now. Instead, you should override '+
-                            'the "getInnerTpl" method to provide whatever logic is required and return the template string.'});
-                    
-                    // make sure we are returning a template string and not an XTemplate instance:
-                    var tpl = me.tpl.html ? me.tpl.html : me.tpl;
-                    
-                    me.getInnerTpl = function(){
-                        return tpl;
-                    };
-                    delete me.tpl;
-                }
-            })
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Slider
-     *-------------------------------------------------------------*/
-    if (Ext.slider.Multi) {
-        Ext.apply(Ext.slider.Multi.prototype, {
-            initComponent: Ext.Function.createInterceptor(Ext.slider.Multi.prototype.initComponent, function() {
-                if (this.plugins) {
-                    Ext.each(this.plugins, function(p){
-                        if (p.getText) {
-                            deprecate({pkg:'Ext.Slider', msg:'In 3.x the Ext.slider.Tip plugin was required to provide custom slider tip text. '+
-                                'In 4.0 you should instead supply the tipText config directly.'});
-                                
-                            this.tipText = p.getText;
-                            Ext.Array.remove(this.plugins, p);
-                            return;
-                        }
-                    }, this); 
-                }
-            })
-        });
-    }
-
-    /*-------------------------------------------------------------
-     * Store
-     *-------------------------------------------------------------*/
-    if (Ext.data.Store) {
-        Ext.apply(Ext.data.AbstractStore.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.data.AbstractStore.prototype.constructor, function(config) {
-                if (this.$className == 'Ext.data.NodeStore') {
-                    return;
-                }
-                if (config.url) {
-                    deprecate({pkg:'Ext.data.Store', member:'url', type:'config', alt:'proxy.url',
-                        msg:'The store\'s "url" config should now be passed as a config to a valid remote-style proxy.'});
-                            
-                    if (!config.proxy) {
-                        deprecate({pkg:'Ext.data.Store', msg:'A store url was specified with no proxy config. Implcitily creating an AjaxProxy with that url. '+
-                            'Please see the header docs for Ext.data.Store for details on properly setting up your data components.'});
-                        
-                        config.proxy = {
-                            type: 'ajax',
-                            url: config.url
-                        };
-                        delete config.url;
-                        
-                        if (config.reader) {
-                            config.proxy.reader = config.reader;
-                            delete config.reader;
-                            deprecate({pkg:'Ext.data.Store', member:'reader', type:'config', msg:'As part of creating an implicit AjaxProxy for compatibility, '+
-                                'the store\'s existing reader config has also been moved to the proxy. Note that the reader config should no longer be passed '+
-                                'directly as a store config, but should be specified on the proxy instead.'});
-                        }
-                    }
-                }
-                else if (!this.model && !config.model){
-                    // there is no model set, so we need to try the various possible configurations supported by 3.x
-                    // and hopefully find something we can convert into an implicit model
-                    var fields;
-                    if (config.fields) {
-                        // shorthand store classes like ArrayStore and XmlStore support fields directly on the store config
-                        fields = config.fields;
-                        delete config.fields;
-                        // this is required to be done, but skip the warning. In some cases TreeStore internally adds this. The bigger picture
-                        // issue of configuring the store correctly will already be covered by other warnings.
-//                        deprecate({pkg:'Ext.data.Store', msg:'Passing a "fields" config directly on the store\'s config is no longer supported. '+
-//                            'Instead you should configure a model and pass it as the store\'s "model" config. ' +
-//                            'Please see the header docs for Ext.data.Store for details on properly setting up your data components.'});
-                    }
-                    else if (config.reader) {
-                        if (config.reader.model) {
-                            // the compat warning for this case is displayed below in the Ext.data.Reader override where
-                            // reader.model is set. This code is just here to make it work properly.
-                            config.model = config.reader.model;
-                            delete this.fields;
-                            this.implicitModel = true;
-                            return true;
-                        }
-                        else if (config.reader.fields) {
-                            // standard stores typically get fields from the reader config
-                            fields = config.reader.fields;
-                            delete config.reader.fields;
-                            deprecate({pkg:'Ext.data.Store', msg:'Passing a "fields" config via the store\'s reader config is no longer supported. '+
-                                'Instead you should configure a model and pass it as the store\'s "model" config. ' +
-                                'Please see the header docs for Ext.data.Store for details on properly setting up your data components.'});
-                        }
-                        else {
-                            breaking({pkg:'Ext.data.Store', msg:'No valid model or field configuration could be found '+
-                                'so this store could not be constructed. Please see the header docs for Ext.data.Store for '+
-                                'details on properly setting up your data components.'});
-                            
-                            return false;
-                        }
-                        if (config.proxy) {
-                            config.proxy.reader = config.reader;
-                            delete config.reader;
-                            deprecate({pkg:'Ext.data.Store', member:'reader', type:'config', msg:'The reader config should now be specified on the '+
-                                'configured proxy rather than directly on the store.'});
-                        }
-                    }
-                    else {
-                        // we should never get here, but just in case
-                        breaking({pkg:'Ext.data.Store', msg: 'A store was specified with no model, url, or fields configured. '+
-                            'Please see the header docs for Ext.data.Store for details on properly setting up your data components.'});
-                        
-                        return false;
-                    }
-    
-                    var pn = config.paramNames;                
-                    if (config.proxy && pn) {
-                        Ext.apply(config.proxy, {
-                            startParam: pn.start || 'start',
-                            limitParam: pn.limit || 'limit',
-                            sortParam : pn.sort || 'sort',
-                            directionParam  : pn.dir || 'dir'
-                        });
-                        deprecate({pkg:'Ext.data.Store', member:'paramNames', msg:'This is now split out into individual configs at the proxy '+
-                            'level (e.g., paramNames.start == proxy.startParam). Set each config directly on the proxy as needed.'})
-                    }
-                    
-                    var id = 'Ext.data.Store.ImplicitModel-' + (config.storeId || config.id || Ext.id());
-                    notify({pkg:'Ext.data.Store', msg:'Registering implicit model ' + id + '. Please update your code to create a model explicitly.'});
-                    
-                    config.model = Ext.define(id, {
-                        extend: 'Ext.data.Model',
-                        fields: fields,
-                        proxy: config.proxy
-                    });
-                    this.implicitModel = true;
-                }
-            })
-        });
-        
-        Ext.apply(Ext.data.Store.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.data.Store.prototype.constructor, function(config) {
-                if (config.data && Ext.isObject(config.data)) {
-                // Seems to be still supported officially for now
-//                    deprecate({pkg:'Ext.data.Store', member:'data<Object>', type:'config', alt:'data<Array>',
-//                        msg:'Passing inline data to store\'s constructor as an object is no longer supported. Pass a '+
-//                            'plain array of record data or use one of the standard proxy configurations for loading data.'});
-                    
-                    if(config.root){
-                        this.inlineData = config.data[config.root];
-                        delete config.data;
-                    }
-//                    else {
-//                        breaking({pkg:'Ext.data.Store', 
-//                            msg:'Passing inline data as an object to the Store constructor without specifying a root property is not supported.'});
-//                    }
-                }
-                if (config.sortInfo) {
-                    deprecate({pkg:'Ext.data.Store', member:'sortInfo', type:'config', alt:'sorters'});
-                    config.sorters = [{
-                        property: config.sortInfo.field,
-                        direction: config.sortInfo.direction
-                    }];
-                }
-                if (config.autoSave) {
-                    deprecate({pkg:'Ext.data.Store', member:'autoSave', type:'config', alt:'autoSync'});
-                    this.autoSync = config.autoSave;
-                    delete config.autoSave;
-                }
-            }),
-            
-            setDefaultSort : function(field, dir) {
-                deprecate({pkg:'Ext.data.Store', member:'setDefaultSort', alt:'sorters (config)',
-                    msg:'Either add the default sort via the "sorters" config or by adding it to the "sorters" property after the store is created. '+
-                        'See the Ext.data.Store header docs for details on configuring sorters.'});
-                
-                this.sorters = new Ext.util.MixedCollection();
-                this.sorters.add(new Ext.util.Sorter({
-                    property: field,
-                    direction: dir ? dir.toUpperCase() : 'ASC'
-                }));
-            },
-            
-            save: function() {
-                deprecate({pkg:'Ext.data.Store', member:'save', alt:'sync'});
-                return this.sync.apply(this, arguments);
-            }
-        });
-        
-        Ext.Compat.bindProperty({owner:Ext.data.Store, name:'recordType',
-            getter: function(){
-                return this.model;
-            },
-            getterMsg: function(){
-                deprecate({pkg:'Ext.data.Store', member:'recordType', type:'property', alt:'model'});
-            }
-        });
-    }
-    
-    if (Ext.data.JsonStore) {
-        // TODO: Move this override into the lib?
-        Ext.apply(Ext.data.JsonStore.prototype, {
-            constructor: function(config) {
-                config = config || {};
-                config.proxy = config.proxy || {};
-                
-                Ext.applyIf(config.proxy, {
-                    url   : config.url,
-                    type  : 'ajax',
-                    writer: 'json',
-                    reader: new Ext.data.JsonReader(config)
-                });
-                Ext.data.JsonStore.superclass.constructor.call(this, config);
-            }
-        });
-    }
-    
-    Ext.data.GroupingStore = function(config) {
-        deprecate({pkg:'Ext.data.GroupingStore', msg:'GroupingStore no longer exists as a separate class. Instead just '+
-            'create a standard GridPanel and include the Grouping feature, e.g. "features: Ext.create("Ext.grid.feature.Grouping", {...})'});
-        
-        return Ext.create('Ext.data.Store', config);
-    }
-    
-    /*-------------------------------------------------------------
-     * Record
-     *-------------------------------------------------------------*/
-    if (Ext.data.Record) {
-        Ext.data.Record.create = function(o){
-            deprecate({pkg:'Ext.data.Record', member:'create', msg:'There is no longer any need to statically define records. '+
-                'You can simply define a new Model configured with the necessary fields via Ext.define, extending Ext.data.Model.'});
-                
-            var f = Ext.extend(Ext.data.Record, {});
-            var p = f.prototype;
-            p.fields = new Ext.util.MixedCollection(false, function(field){
-                return field.name;
-            });
-            for(var i = 0, len = o.length; i < len; i++){
-                p.fields.add(new Ext.data.Field(o[i]));
-            }
-            f.getField = function(name){
-                return p.fields.get(name);
-            };
-            return f;
-        };
-    }
-    
-    /*-------------------------------------------------------------
-     * Readers
-     *-------------------------------------------------------------*/
-    if (Ext.data.JsonReader) {
-        Ext.data.JsonReader.override({
-            //TODO: seems to be a bug in the class system that this is required for the Reader override 
-            constructor: function(){
-                this.callParent(arguments);
-            }
-        });
-    }
-    
-    if (Ext.data.Reader) {
-        Ext.apply(Ext.data.Reader.prototype, {
-            constructor: function(config, recordType) {
-                Ext.apply(this, config || {});
-        
-                if (config.fields) {
-                    // this will get converted to an implicit model in the store constructor
-                    deprecate({pkg:'Ext.data.Reader', member:'fields', type:'config',
-                        msg:'The fields config is no longer supported. Please refer to the '+
-                            'Ext.data.Store header docs for the proper way to set up your data components.'});
-                }
-                if (recordType) {
-                    // this will get converted to an implicit model in the store constructor
-                    config.fields = recordType;
-                    deprecate({pkg:'Ext.data.Reader', member:'recordType', type:'arg',
-                        msg:'The recordType argument to the Reader constructor is no longer supported. Please refer to the '+
-                            'Ext.data.Store header docs for the proper way to set up your data components.'});
-                }
-                
-                if (config.model) {
-                    this.model = Ext.ModelManager.getModel(config.model);
-                }
-                else if (config.fields) {
-                    this.model = Ext.define('Ext.data.Store.ImplicitModel-' + Ext.id(), {
-                        extend: 'Ext.data.Model',
-                        fields: config.fields
-                    });
-                }
-                // This is not always true, e.g. with inline array data:
-//                else {
-//                    breaking({pkg:'Ext.data.Reader', 
-//                        msg:'No valid model or field configuration could be found so this reader could not be constructed.'});
-//                }
-                
-                if (this.model) {
-                    this.buildExtractors();
-                }
-            }
-        });
-    }
-    
-    if (Ext.data.XmlReader) {
-        Ext.apply(Ext.data.XmlReader.prototype, {
-            // FYI, this entire constructor is now deprecated because all behavior is now in the superclass constructor
-            constructor: function(config, recordType) {
-                config = config || {};
-                if (config.idPath) {
-                    config.idProperty = config.idPath;
-                    deprecate({pkg:'Ext.data.XmlReader', member:'idPath', type:'config', alt:'idProperty'});
-                }
-                if (config.id) {
-                    config.idProperty = config.id;
-                    deprecate({pkg:'Ext.data.XmlReader', member:'id', type:'config', alt:'idProperty'});
-                }
-                if (config.success) {
-                    config.successProperty = config.success;
-                    deprecate({pkg:'Ext.data.XmlReader', member:'success', type:'config', alt:'successProperty'});
-                }
-                // make sure we pass arguments in case the deprecated recordType arg is included
-                Ext.data.XmlReader.superclass.constructor.apply(this, arguments);
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Proxies
-     *-------------------------------------------------------------*/
-    if (Ext.data.ServerProxy) {
-        Ext.apply(Ext.data.ServerProxy.prototype, {
-            getParams: Ext.Function.createInterceptor(Ext.data.ServerProxy.prototype.getParams, function(params, operation) {
-                if (this.sortParam && operation.sorters && operation.sorters.length > 0) {
-                    if (!this.simpleSortMode) {
-                        this.simpleSortMode = true;
-                        Ext.Compat.warn('ServerProxy now supports multiple sort, so if any sort options are specified '+
-                            'the sort params get JSON-encoded by default. Unless you have specifically coded for this on '+
-                            'the server it will not work and you should set "simpleSortMode = true" on the proxy. Since '+
-                            'this was not supported in Ext 3 and you are passing a sort param, simple sorting is assumed '+
-                            'and has been set automatically, but you should reexamine this code as you migrate to Ext 4. '+
-                            'For now just set "simpleSortMode: true" on your proxy to dismiss this warning.');
-                    }
-                }
-            })
-        });
-    }
-    
-    if (Ext.data.MemoryProxy) {
-        Ext.apply(Ext.data.MemoryProxy.prototype, {
-            read: Ext.Function.createInterceptor(Ext.data.MemoryProxy.prototype.read, function(op, cb, scope) {
-                if (this.doRequest) {
-                    deprecate({pkg:'Ext.data.MemoryProxy', member:'doRequest', alt: 'read',
-                        msg:'ClientProxy subclasses no longer implement doRequest.'});
-                        
-                    var params = {
-                        start: op.start, 
-                        limit: op.limit
-                    };
-                    if (op.sorters && op.sorters.length > 0) {
-                        var idx = op.sorters.length-1; // take the last sort if multiple
-                        params[this.sortParam || 'sort'] = op.sorters[idx].property;
-                        params[this.directionParam || 'dir'] = op.sorters[idx].direction;
-                    }
-                    if (op.filters && op.filters.length > 0) {
-                        // not sure if we can compat this
-                        //params[this.filterParam || 'filter'] = ??;
-                    }
-                    this.doRequest(op.action, op.getRecords(), params, this.getReader(), function(result, options){
-                        Ext.apply(op, {
-                            resultSet: result
-                        });
-                        op.setCompleted();
-                        op.setSuccessful();
-                        Ext.callback(cb, scope || this, [op]);
-                    }, scope);
-                    
-                    return false; // skip original read logic
-                }
-            })
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Model
-     *-------------------------------------------------------------*/
-    if (Ext.data.Model) {
-        Ext.apply(Ext.data.Model.prototype, {
-            constructor: Ext.Function.createInterceptor(Ext.data.Model.prototype.constructor, function(data, id) {
-                var newData = {};
-                if (Ext.isArray(data)){
-                    // Support for loading an array, needed for calling loadData on an ArrayStore
-                    var fields = this.fields.items,
-                        length = fields.length,
-                        field, name, 
-                        i = 0, 
-                        newData = {};
-                        
-                    for (; i < length; i++) {
-                        field = fields[i];
-                        name  = field.name;
-                        newData[name] = data[i];
-                    }
-                    data = newData;
-                }
-            }),
-            
-            initComponent: Ext.Function.createInterceptor(Ext.data.Model.prototype.initComponent, function() {
-                // Needed to bootstrap 3.x stores that use id. Once converted to a model this will
-                // not be needed, so there's no need for a separate warning, just a temp shim.
-                this.id = this.internalId;
-            })
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Other Ext.data.* stuff
-     *-------------------------------------------------------------*/
-    if (Ext.data.Operation) {
-        Ext.apply(Ext.data.Operation.prototype, {
-            markStarted: function() {
-                deprecate({pkg:'Ext.data.Operation', member:'markStarted', alt:'setStarted'});
-                return this.setStarted();
-            },
-            markCompleted: function() {
-                deprecate({pkg:'Ext.data.Operation', member:'markCompleted', alt:'setCompleted'});
-                return this.setCompleted();
-            },
-            markSuccessful: function() {
-                deprecate({pkg:'Ext.data.Operation', member:'markSuccessful', alt:'setSuccessful'});
-                return this.setSuccessful();
-            },
-            markException: function() {
-                deprecate({pkg:'Ext.data.Operation', member:'markException', alt:'setException'});
-                return this.setException();
-            }
-        });
-    }
-    
-    /*-------------------------------------------------------------
-     * Tooltip
-     *-------------------------------------------------------------*/
-    if (Ext.tip.ToolTip) {
-        Ext.apply(Ext.tip.ToolTip.prototype, {
-            initTarget: function(target) {
-                deprecate({pkg:'Ext.ToolTip', member:'initTarget', alt:'setTarget'});
-                return this.setTarget(target);
-            }
-        });
-    }
-    
-    if (Ext.TaskManager) {
-        Ext.TaskMgr = function() {
-            deprecate({pkg:'Ext.TaskMgr', alt:'Ext.TaskManager'});
-            return Ext.TaskManager;
-        }
-        Ext.TaskMgr.start = Ext.TaskManager.start;
-        Ext.TaskMgr.stop = Ext.TaskManager.stop;
-        Ext.TaskMgr.stopAll = Ext.TaskManager.stopAll;
-    }
-    
-})();
-
-//
-// TODO: Remove this once the plugin is integrated into the lib
-//
-Ext.define('Ext.ux.PreviewPlugin', {
-    extend: 'Ext.AbstractPlugin',
-    alias: 'plugin.preview',
-    requires: ['Ext.grid.feature.RowBody', 'Ext.grid.feature.RowWrap'],
-    
-    // private, css class to use to hide the body
-    hideBodyCls: 'x-grid-row-body-hidden',
-    
-    /**
-     * @cfg {String} bodyField
-     * Field to display in the preview. Must me a field within the Model definition
-     * that the store is using.
-     */
-    bodyField: '',
-    
-    /**
-     * @cfg {Boolean} previewExpanded
-     */
-    previewExpanded: true,
-    
-    constructor: function(config) {
-        this.callParent(arguments);
-        var bodyField   = this.bodyField,
-            hideBodyCls = this.hideBodyCls,
-            section     = this.getCmp();
-        
-        section.previewExpanded = this.previewExpanded;
-        section.features = [{
-            ftype: 'rowbody',
-            getAdditionalData: function(data, idx, record, orig, view) {
-                var o = Ext.grid.feature.RowBody.prototype.getAdditionalData.apply(this, arguments);
-                Ext.apply(o, {
-                    rowBody: data[bodyField],
-                    rowBodyCls: section.previewExpanded ? '' : hideBodyCls
-                });
-                return o;
-            }
-        },{
-            ftype: 'rowwrap'
-        }];
-    },
-    
-    /**
-     * Toggle between the preview being expanded/hidden
-     * @param {Boolean} expanded Pass true to expand the record and false to not show the preview.
-     */
-    toggleExpanded: function(expanded) {
-        var view = this.getCmp();
-        this.previewExpanded = view.previewExpanded = expanded;
-        view.refresh();
-    }
-});
diff --git a/js/lib/compat/ext3-core-compat.js b/js/lib/compat/ext3-core-compat.js
deleted file mode 100644
index d18c799..0000000
--- a/js/lib/compat/ext3-core-compat.js
+++ /dev/null
@@ -1,735 +0,0 @@
-
-/*========================================================================
- * 
- * This section contains stuff that should be in Ext4, or stuff that
- * is up for discussion. It should be removed prior to Ext 4 final.
- *
- *========================================================================*/
-
-// Beefed up getDockedItems to make it easier to find specific items like top toolbars only
-//Ext.apply(Ext.panel.AbstractPanel.prototype, {
-//    /**
-//     * Retrieve an array of all currently docked components, optionally matching a
-//     * specific docked side and/or component type.
-//     * @param {Array} options
-//     * @return {Array} An array of matching components
-//     */
-//    // ex: {dock: 'top', alias: 'widget.toolbar'}
-//    getDockedItems : function(options) {
-//        var me = this,
-//            items = [];
-//        
-//        if (me.dockedItems && me.dockedItems.items.length) {
-//            items = me.dockedItems.items.slice();
-//        }
-//        
-//        if (options && items.length > 0) {
-//            var i = 0,
-//                ln = items.length,
-//                matches = [],
-//                item;
-//            
-//            for (; i < ln; i++) {
-//                item = items[i];
-//                if (options.dock && options.dock !== item.dock){
-//                    continue;
-//                }
-//                if (options.alias && options.alias !== item.alias){
-//                    continue;
-//                }
-//                matches.push(item);
-//            }
-//            return matches;
-//        }
-//        return items;
-//    }
-//});
-
-
-/*========================================================================
- * 
- * This section contains the Ext.Compat object definition.
- * Also shared by ext3-compat.js.
- *
- *========================================================================*/
-
-Ext.Compat = function(){
-    // private
-    var notificationCache = [],
-    
-    // private
-    getMsg = function(o, tag){
-        var version = o.version ? o.version : '4.0',
-            pkg = o.pkg ? '[' + o.pkg + ']': '',
-            member = o.member ? ' ' + o.member : '',
-            type = o.type ? ' (' + o.type + ')' : '',
-            use = o.type === 'event' ? ' Handle ' : ' Use ',
-            alt = o.alt ? use + o.alt + ' instead.' : '',
-            msg = o.msg ? ' ' + o.msg : '';
-            
-        return '[' + tag + '][' + version + ']' + pkg + member + type + ':' + alt + msg;
-    },
-    
-    // private    
-    showMsg = function(msg, method, single){
-        var isNew = Ext.Array.indexOf(notificationCache, msg) == -1;
-        if (isNew || !single) {
-            Ext.Compat[method](msg);
-            if (single) {
-                notificationCache.push(msg);
-            }
-        }
-    },
-    
-    // private
-    consoleOut = function(type, msg){
-        if (Ext.Compat.silent === true) {
-            return;
-        }
-        if (!Ext.isDefined(Ext.global.console)){
-            if (type === 'error' && Ext.Array.indexOf(notificationCache, '__consoleMsg') == -1) {
-                notificationCache.push('__consoleMsg');
-                alert('You have Ext compatibility errors that must be resolved. Please enable your browser\'s console '+
-                    '(or switch to a console-capable browser) to see complete error details.');
-            }
-            return;
-        }
-        var con = Ext.global.console;
-        
-        if(Ext.Array.indexOf(notificationCache, '__initMsg') == -1){
-            notificationCache.push('__initMsg');
-            con.info('#### Ext 3 compatibility mode active. See the Migration Guide included with the Ext 4 download for details.');
-            if(!Ext.Compat.showErrors){
-                var errMsg = '#### Set "Ext.Compat.showErrors = true;" in your code to include a stack trace with each warning.';
-                con.info(con.firebug ? errMsg : errMsg + ' (Firebug required)');
-            }
-            con.log(' ');
-        }
-        con[Ext.Compat.showErrors ? 'error' : type](msg);
-    };
-    
-    return {
-        /**
-         * False to display console messages (default), true to skip displaying console messages. Useful
-         * when running an app in compatibility mode for end users prior to completing full migration to Ext 4.
-         */
-        silent: false,
-        /**
-         * True to ignore informational messages and show only warnings, false to show all messages (default)
-         */
-        ignoreInfo: false,
-        /**
-         * True to display messages via console.error instead of console.warn/info (defaults to false). When 
-         * viewing the console in Firebug in particular this can be a useful option to enable as Firebug will
-         * capture the stack trace and include it in the displayed error object, which can make finding the 
-         * source of warnings much easier in most cases. In other browsers enabling this option will simply 
-         * display the message as an error cosmetically but won't provide any additional benefit. 
-         */
-        showErrors: false,
-        
-        /**
-         * Wrapper for the browser console.warn() method that checks for the existence of console
-         * and also honors the Ext.Compat.silent flag. Should be used for any breaking change
-         * or deprecation warnings.
-         * @param {String} msg The console message to log
-         */
-        warn: function(msg) {
-            consoleOut('warn', msg);
-        },
-        
-        /**
-         * Wrapper for the browser console.info() method that checks for the existence of console
-         * and also honors the Ext.Compat.silent flag. Should be used for informational
-         * messages or non-breaking changes that modify existing behavior.
-         * @param {String} msg The console message to log
-         */
-        info: function(msg){
-            if(this.ignoreInfo !== true){
-                consoleOut('info', msg);
-            }
-        },
-        
-        /**
-         * This method should generally be eschewed in favor of Ext.compat.deprecate. However it might be necessary
-         * to log a console error in certain cases, e.g. when backwards-compatibility is only conditionally possible.
-         * @param {String} msg The console message to log
-         */
-        error: function(msg){
-            consoleOut('error', msg);
-        },
-        
-        /**
-         * Display a standard deprecation message. The method takes a single object argument that contains
-         * properties as described below. All properties are optional, although typically the pkg and member would be 
-         * specified along with a descriptive message.
-         * @param {String} pkg (optional) The package ("Core") or component ("Ext.grid.Grid") being referenced (defaults to '')
-         * @param {String} member (optional) The member being deprecated (defaults to '')
-         * @param {String} alt (optional) An alternate member that is replacing the deprecated member (defaults to '')
-         * @param {String} type (optional) The member type (method, config, property, xtype, etc.) Defaults to 'method', 
-         * which does not get displayed -- any other specified type will be displayed in the output.
-         * @param {String} msg (optional) An additional message to provide more explanation about the change (defaults to '')
-         * @param {String} tag (optional) The first bracketed item in the output that describes the message type (defaults to 'DEPRECATED')
-         * @param {Boolean} single (optional) True to limit each unique message to being displayed only one time (defaults to false,
-         * meaning the same message can be displayed multiple times). Usually it's good to set single:true for logging issues 
-         * that can happen repetitively with the same root cause (e.g., the same issue within each row of a grid).
-         */
-        deprecate: function(o) {
-            var msg = getMsg(o, o.tag || 'DEPRECATED');
-            showMsg(msg, 'warn', o.single);
-        },
-        
-        /**
-         * Display a console error with the special tag "BREAKING" to signify a breaking change that cannot be
-         * resolved in the compatibility layer. These issues generally must be resolved immediately before the
-         * compatibility layer be successfully applied. The method takes a single object argument that contains
-         * properties as described below. All properties are optional, although typically the pkg and member would be 
-         * specified along with a descriptive message.
-         * @param {String} msg (optional) A message to provide more explanation about the breaking change (defaults to '')
-         * @param {String} pkg (optional) The package ("Core") or component ("Ext.grid.Grid") being referenced (defaults to '')
-         * @param {String} member (optional) The member being referenced in relation to the change (defaults to '')
-         * @param {String} type (optional) The member type (method, config, property, xtype, etc.) Defaults to 'method', 
-         * which does not get displayed -- any other specified type will be displayed in the output.
-         * @param {String} tag (optional) The first bracketed item in the output that describes the message type (defaults to 'BREAKING')
-         * @param {Boolean} single (optional) True to limit each unique message to being displayed only one time (defaults to false,
-         * meaning the same message can be displayed multiple times). Usually it's good to set single:true for logging issues 
-         * that can happen repetitively with the same root cause (e.g., the same issue within each row of a grid).
-         */
-        breaking: function(o){
-            o.msg = (o.msg || '') + ' This is a breaking change that cannot be resolved in the compatibility layer!';
-            var msg = getMsg(o, o.tag || 'BREAKING');
-            showMsg(msg, 'error', o.single);
-        },
-        
-        /**
-         * Display a freeform notification that a compatibility change exists. This would be used, for example,
-         * if an existing method has changed its default behavior, or has a different argument signature. 
-         * The method takes either a string message or an object argument that contains properties as described below.
-         * If a member is being deprecated you might consider using <tt>deprecate</tt> instead.
-         * @param {String} msg A message explaining the change
-         * @param {String} pkg (optional) The package ("Core") or component ("Ext.grid.Grid") being referenced (defaults to '')
-         * @param {String} member (optional) The member being referenced in relation to the change (defaults to '')
-         * @param {String} type (optional) The member type (method, config, property, xtype, etc.) Defaults to 'method', 
-         * which does not get displayed -- any other specified type will be displayed in the output.
-         * @param {String} tag (optional) The first bracketed item in the output that describes the message type (defaults to 'INFO')
-         * @param {Boolean} single (optional) True to limit each unique message to being displayed only one time (defaults to false,
-         * meaning the same message can be displayed multiple times). Usually it's good to set single:true for logging issues 
-         * that can happen repetitively with the same root cause (e.g., the same issue within each row of a grid).
-         */
-        notify: function(o) {
-            if(Ext.isString(o)){
-                o = {msg:o};
-            }
-            if(o.msg){
-                var msg = getMsg(o, o.tag || 'INFO'),
-                    single = Ext.isDefined(o.single) ? o.single : !this.showErrors;
-                
-                showMsg(msg, 'info', single);
-            }
-        },
-        
-        /*
-         * Currently experimental
-         */
-        bindProperty: function(options) {
-            var localValue,
-                o = options;
-            
-            if (o.owner.__defineGetter__) {
-                o.owner.__defineGetter__(o.name, function(){
-                    if (o.getterMsg) {
-                        o.getterMsg();
-                    }
-                    return localValue ? localValue : (o.getter ? o.getter() : o.defaultValue);
-                });
-                o.owner.__defineSetter__(o.name, function(val){
-                    if (o.setterMsg) {
-                        o.setterMsg();
-                    }
-                    if (o.setter) {
-                        o.setter(val);
-                    }
-                    else {
-                        o.owner[o.name] = val;
-                    }
-                    localValue = val;
-                });
-            }
-            else {
-                o.owner[o.name] = o.defaultValue;
-            }
-        }
-    };
-}();
-
-
-/*========================================================================
- * 
- * This section contains compatibility overrides for Ext Core
- *
- *========================================================================*/
-
-(function(){
-    var compat = Ext.Compat,
-        deprecate = Ext.bind(compat.deprecate, compat),
-        notify = Ext.bind(compat.notify, compat),
-        breaking = Ext.bind(compat.breaking, compat),
-        bindProperty = Ext.bind(compat.bindProperty, compat);
-    
-    /*-------------------------------------------------------------
-     * Ext
-     *-------------------------------------------------------------*/
-    Ext.apply(Ext, {
-        createDelegate: function() {
-            deprecate({pkg:'Ext', member:'createDelegate', alt:'Ext.bind'});
-            return Ext.Function.bind.apply(Ext.Function, arguments);
-        },
-        createCallback: function() {
-            deprecate({pkg:'Ext', member:'createCallback', alt:'Ext.pass'});
-            return Ext.Function.pass.apply(Ext.Function, arguments);
-        },
-        createInterceptor: function() {
-            deprecate({pkg:'Ext', member:'createInterceptor', alt:'Ext.Function.createInterceptor'});
-            return Ext.Function.createInterceptor.apply(Ext.Function, arguments);
-        },
-        createSequence: function() {
-            deprecate({pkg:'Ext', member:'createSequence', alt:'Ext.Function.createSequence'});
-            return Ext.Function.createSequence.apply(Ext.Function, arguments);
-        },
-        // This is still aliased in Ext.Array
-//        toArray: function() {
-//            deprecate({pkg:'Ext', member:'toArray', alt:'Ext.Array.toArray'});
-//            return Ext.Array.toArray.apply(Ext.Array, arguments);
-//        },
-        pluck: function(arr, prop) {
-            deprecate({pkg:'Ext', member:'pluck', alt:'Ext.Array.pluck'});
-            return Ext.Array.pluck.apply(Ext.Array, arguments);
-        }
-        
-        // TODO: Verify if this is really deprecated or not: 
-//        iterate: function() {
-//            Ext.each.apply(this, arguments);
-//            deprecate({pkg:'Ext', member:'iterate', alt:'each', 
-//                msg:'Ext.each is now a wrapper for both Ext.Array.forEach and Ext.Object.each.'});
-//        }
-    });
-    
-    /*-------------------------------------------------------------
-     * Ext properties
-     *-------------------------------------------------------------*/
-    var versionObj = Ext.getVersion('extjs');
-            
-    bindProperty({owner:Ext, name:'version', defaultValue:versionObj.version,
-        getterMsg: function(){
-            deprecate({pkg:'Ext', member:'version', type:'property', alt:'getVersion (method)',
-                msg:'Ext.getVersion() takes one argument which is the package name to look up. This will be defaulted '+
-                    'to "extjs" but could also be "core" or "touch". Note also that getVersion returns an object. For the '+
-                    'simple string representation use the Ext.getVersion("extjs").version property.'});
-        }
-    });
-    
-    // For no logical reason this one causes Firebug to go into an infinite loop. It makes no sense...
-//    bindProperty({owner:Ext, name:'versionDetail', defaultValue: {
-//            major: versionObj.major,
-//            minor: versionObj.minor,
-//            patch: versionObj.patch
-//        },
-//        getterMsg: function(){
-//            deprecate({pkg:'Ext', member:'versionDetail', type:'property', alt:'getVersion (method)',
-//                msg:'Ext.getVersion() takes one argument which is the package name to look up. This will be defaulted '+
-//                    'to "extjs" but could also be "core" or "touch". Note also that getVersion returns an object. For the '+
-//                    'version detail representation use Ext.getVersion("extjs") and inspect the properties major, minor and patch.'});
-//        }
-//    });
-    
-    /*-------------------------------------------------------------
-     * Ext.lib.Dom
-     *-------------------------------------------------------------*/
-    // Helper function for aliasing Ext.lib.Dom
-    var aliasDom = function(name, args){
-        deprecate({pkg:'Ext.lib.Dom', member:name, alt:'Ext.core.Element.'+name});
-        return Ext.core.Element[name].apply(Ext.core.Element, args);
-    };
-    Ext.lib = {};
-    Ext.lib.Dom = {
-        isAncestor : function(p, c) {
-            return aliasDom('isAncestor', arguments);
-        },
-        getViewWidth : function(full) {
-            return aliasDom('getViewWidth', arguments);
-        },
-        getViewHeight : function(full) {
-            return aliasDom('getViewHeight', arguments);
-        },
-        getDocumentHeight: function() {
-            return aliasDom('getDocumentHeight', arguments);
-        },
-        getDocumentWidth: function() {
-            return aliasDom('getDocumentWidth', arguments);
-        },
-        getViewportHeight: function(){
-            return aliasDom('getViewportHeight', arguments);
-        },
-        getViewportWidth : function() {
-            return aliasDom('getViewportWidth', arguments);
-        },
-        getY : function(el) {
-            return aliasDom('getY', arguments);
-        },
-        getX : function(el) {
-            return aliasDom('getX', arguments);
-        },
-        getXY : function(el) {
-            return aliasDom('getXY', arguments);
-        },
-        setXY : function(el, xy) {
-            aliasDom('setXY', arguments);
-        },
-        setX : function(el, x) {
-            aliasDom('setX', arguments);
-        },
-        setY : function(el, y) {
-            aliasDom('setY', arguments);
-        }
-    };
-    
-    /*-------------------------------------------------------------
-     * Ext.lib.Event
-     *-------------------------------------------------------------*/
-    // Helper function for aliasing Ext.lib.Event
-    var aliasEvent = function(e, name, args){
-        deprecate({pkg:'Ext.lib.Event', member:name, alt:'<event>.'+name});
-        return e[name].apply(e, args);
-    };
-    Ext.lib.Event = {
-        getTarget : function(e) {
-            return aliasEvent(e, 'getTarget', arguments);
-        },
-        getRelatedTarget : function(ev) {
-            return aliasEvent(e, 'getRelatedTarget', arguments);
-        },
-        getPageX : function(e) {
-            return aliasEvent(e, 'getPageX', arguments);
-        },
-        getPageY : function(e) {
-            return aliasEvent(e, 'getPageY', arguments);
-        },
-        getXY : function(e) {                             
-            return aliasEvent(e, 'getXY', arguments);
-        },
-        stopEvent : function(e) {                            
-            return aliasEvent(e, 'stopEvent', arguments);
-        },
-        stopPropagation : function(e) {
-            return aliasEvent(e, 'stopPropagation', arguments);
-        },
-        preventDefault : function(e) {
-            return aliasEvent(e, 'preventDefault', arguments);
-        },
-        getCharCode : function(e) {
-            return aliasEvent(e, 'getCharCode', arguments);
-        },
-        getEvent : function(e) {
-            deprecate({pkg:'Ext.lib.Event', member:'getEvent', alt:'<event>', msg:'Just use the event instance directly.'});
-            return e;
-        }
-    };
-    
-    /*-------------------------------------------------------------
-     * Ext.lib.Point
-     *-------------------------------------------------------------*/
-    Ext.lib.Point = function(x, y) {
-        deprecate({pkg:'Ext.lib.Point', alt:'Ext.util.Point'});
-        return new Ext.util.Point(x, y);
-    };
-    
-    /*-------------------------------------------------------------
-     * Ext.lib.Ajax
-     *-------------------------------------------------------------*/
-    Ext.lib.Ajax = {
-        request : function() {
-            deprecate({pkg:'Ext.lib.Ajax', member:'request', alt:'Ext.Ajax.request',
-                msg:'This method is not backwards-compatible and must be updated manually.'});
-        },
-        serializeForm : function(form) {
-            deprecate({pkg:'Ext.lib.Ajax', member:'serializeForm', alt:'Ext.core.Element.serializeForm'});
-            return Ext.core.Element.serializeForm(form);
-        },
-        abort : function() {
-            deprecate({pkg:'Ext.lib.Ajax', member:'abort', alt:'Ext.Ajax.abort',
-                msg:'This method is not backwards-compatible and must be updated manually.'});
-        },
-        isCallInProgress : function() {
-            deprecate({pkg:'Ext.lib.Ajax', member:'isCallInProgress', alt:'Ext.Ajax.isLoading',
-                msg:'This method is not backwards-compatible and must be updated manually.'});
-        }
-    };
-    
-    /*-------------------------------------------------------------
-     * Function prototype overrides
-     *-------------------------------------------------------------*/
-    Ext.apply(Function.prototype, {
-        createInterceptor : function(){
-            deprecate({pkg:'Function', member:'<fn>.createInterceptor', alt:'Ext.Function.createInterceptor',
-                msg:'Note that this is now a static method, so the function will be the first argument to the new version.'});
-            return Ext.Function.createInterceptor.apply(Ext.Function, [this].concat(Array.prototype.slice.call(arguments)));
-        },
-        
-        createSequence : function(){
-            deprecate({pkg:'Function', member:'<fn>.createSequence', alt:'Ext.Function.createSequence',
-                msg:'Note that this is now a static method, so the function will be the first argument to the new version.'});
-            return Ext.Function.createInterceptor.apply(Ext.Function, [this].concat(Array.prototype.slice.call(arguments)));
-        },
-    
-        createCallback : function(){
-            deprecate({pkg:'Function', member:'<fn>.createCallback', alt:'Ext.pass',
-                msg:'Note that this is now a static method, so the function will be the first argument to the new version.'});
-            return Ext.pass.apply(Ext.Function, [this].concat(Array.prototype.slice.call(arguments)));
-        },
-    
-        createDelegate : function(obj, args, appendArgs){
-            deprecate({pkg:'Function', member:'<fn>.createDelegate', alt:'Ext.bind',
-                msg:'Note that this is now a static method, so the function will be the first argument to the new version.'});
-            return Ext.bind.apply(Ext.Function, [this].concat(Array.prototype.slice.call(arguments)));
-        },
-        
-        defer : function(){
-            deprecate({pkg:'Function', member:'<fn>.defer', alt:'Ext.defer',
-                msg:'Note that this is now a static method, so the function will be the first argument to the new version.'});
-            return Ext.defer.apply(Ext.Function, [this].concat(Array.prototype.slice.call(arguments)));
-        }
-    });
-    
-    /*-------------------------------------------------------------
-     * String overrides
-     *-------------------------------------------------------------*/
-    // String static methods:
-    Ext.applyIf(String, {
-        format : function(){
-            deprecate({pkg:'String', member:'format', alt:'Ext.String.format'});
-            return Ext.String.format.apply(Ext.String, arguments);
-        },
-        escape : function(string) {
-            deprecate({pkg:'String', member:'escape', alt:'Ext.String.escape'});
-            return Ext.String.escape.apply(Ext.String, arguments);
-        },
-        leftPad : function (val, size, ch) {
-            deprecate({pkg:'String', member:'leftPad', alt:'Ext.String.leftPad'});
-            return Ext.String.leftPad.apply(Ext.String, arguments);
-        }
-    });
-    // String instance methods:
-    Ext.applyIf(String.prototype, {
-        toggle : function(value, other){
-            deprecate({pkg:'String', member:'<string>.toggle', alt:'Ext.String.toggle',
-                msg:'Note that this is now a static method, so the string instance will be the first argument to the new version.'});
-            return Ext.String.toggle.call(Ext.String, this, value, other);
-        },
-        trim : function(){
-            deprecate({pkg:'String', member:'<string>.trim', alt:'Ext.String.trim',
-                msg:'Note that this is now a static method, so the string instance will be the first argument to the new version.'});
-            return Ext.String.trim.call(Ext.String, this);
-        }
-    });
-    
-    /*-------------------------------------------------------------
-     * Array overrides
-     *-------------------------------------------------------------*/
-    Ext.applyIf(Array.prototype, {
-        indexOf : function(o){
-            deprecate({pkg:'Array', member:'<array>.indexOf', alt:'Ext.Array.indexOf',
-                msg:'Note that this is now a static method, so the array instance will be the first argument to the new version. '+
-                    'Also the new version adds an optional "from index" as the last argument.'});
-            return Ext.Array.indexOf.call(Ext.Array, this, o);
-        },
-        remove : function(o){
-            deprecate({pkg:'Array', member:'<array>.remove', alt:'Ext.Array.remove',
-                msg:'Note that this is now a static method, so the array instance will be the first argument to the new version.'});
-            return Ext.Array.remove.call(Ext.Array, this, o);
-        }
-    });
-    
-    /*-------------------------------------------------------------
-     * Number overrides
-     *-------------------------------------------------------------*/
-    Ext.applyIf(Number.prototype, {
-        constrain : function(min, max){
-            deprecate({pkg:'Number', member:'<number>.constrain', alt:'Ext.Number.constrain',
-                msg:'Note that this is now a static method, so the number instance will be the first argument to the new version.'});
-            return Ext.Number.constrain.call(Ext.Number, this, min, max);
-        }
-    });
-    
-    /*-------------------------------------------------------------
-     * Date overrides.
-     * NOTE: The methods from the Date class under Ext.util
-     * in 3.x are aliased separately in ext3-compat.js. 
-     *-------------------------------------------------------------*/
-    Ext.applyIf(Date.prototype, {
-        /**
-         Returns the number of milliseconds between this date and date
-         @param {Date} date (optional) Defaults to now
-         @return {Number} The diff in milliseconds
-         @member Date getElapsed
-         @deprecated
-         */
-        getElapsed : function(date) {
-            deprecate({pkg:'Core', member:'<date>.getElapsed', alt:'Ext.Date.getElapsed'});
-            return Ext.Date.getElapsed.call(Ext.Date, this, date);
-        }
-    });
-    
-    /*-------------------------------------------------------------
-     * Element
-     *-------------------------------------------------------------*/
-    Ext.apply(Ext.core.Element.prototype, {
-        getMargins : function(){
-            deprecate({pkg:'Ext.Element', member:'getMargins', alt:'getMargin'});
-            return this.getMargin.apply(this, arguments);
-        },
-        addClass : function(){
-            deprecate({pkg:'Ext.Element', member:'addClass', alt:'addCls'});
-            return this.addCls.apply(this, arguments);
-        },
-        addClassOnClick : function(){
-            deprecate({pkg:'Ext.Element', member:'addClassOnClick', alt:'addClsOnClick'});
-            return this.addClsOnClick.apply(this, arguments);
-        },
-        addClassOnFocus : function(){
-            deprecate({pkg:'Ext.Element', member:'addClassOnFocus', alt:'addClsOnFocus'});
-            return this.addClsOnFocus.apply(this, arguments);
-        },
-        addClassOnOver : function(){
-            deprecate({pkg:'Ext.Element', member:'addClassOnOver', alt:'addClsOnOver'});
-            return this.addClsOnOver.apply(this, arguments);
-        },
-        hasClass : function(){
-            deprecate({pkg:'Ext.Element', member:'hasClass', alt:'hasCls'});
-            return this.hasCls.apply(this, arguments);
-        },
-        radioClass : function(){
-            deprecate({pkg:'Ext.Element', member:'radioClass', alt:'radioCls'});
-            return this.radioCls.apply(this, arguments);
-        },
-        removeClass : function(){
-            deprecate({pkg:'Ext.Element', member:'removeClass', alt:'removeCls'});
-            return this.removeCls.apply(this, arguments);
-        },
-        replaceClass : function(){
-            deprecate({pkg:'Ext.Element', member:'replaceClass', alt:'replaceCls'});
-            return this.replaceCls.apply(this, arguments);
-        },
-        toggleClass : function(){
-            deprecate({pkg:'Ext.Element', member:'toggleClass', alt:'toggleCls'});
-            return this.toggleCls.apply(this, arguments);
-        },
-        
-// Can't do this since Ext internally uses these calls. Reverting them will break Ext 4 code, so have to doc as breaking changes.
-//        child : function(selector, returnDom){
-//            notify('Ext.Element.child now returns a single direct child in 4.0 (switched with Ext.Element.down). '+
-//                'Reverting to the 3.x behavior that matches at any depth -- please verify this call when migrating to Ext 4.');
-//                
-//            var n = Ext.DomQuery.selectNode(selector, this.dom);
-//            return returnDom ? n : Ext.get(n);
-//        },
-//        down : function(selector, returnDom){
-//            notify('Ext.Element.down now returns a single child at any depth in 4.0 (switched with Ext.Element.child). '+
-//                'Reverting to the 3.x behavior that matches a direct child only -- please verify this call when migrating to Ext 4.');
-//                
-//            var n = Ext.DomQuery.selectNode(" > " + selector, this.dom);
-//            return returnDom ? n : Ext.get(n);
-//        },
-        animate: function(args, duration, onComplete, easing) {
-            if (arguments.length > 1 || Ext.isEmpty(args)) {
-                deprecate({pkg:'Ext.Element', member:'animate', msg:'Ext.Element.animate should be called with a single configuration object. '+
-                    'See the header API docs for Ext.util.Animate for details on the supported config attribute syntax.'});
-            }
-            var me = this;
-            if (!me.id) {
-                me = Ext.get(me.dom);
-            }
-            if (Ext.fx.Manager.hasFxBlock(me.id)) {
-                return me;
-            }
-            args = args || {};
-            if (duration) {
-                args.duration = duration;
-            }
-            if (onComplete) {
-                args.callback = onComplete;
-            }
-            if (easing) {
-                args.easing = easing;
-            }
-            Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(args)));
-            return this;
-        },
-        anim: Ext.Function.createInterceptor(Ext.core.Element.prototype.anim, function(config) {
-            if (Ext.isObject(config)) {
-                if (config.delay && config.delay < 10) {
-                    config.delay *= 1000;
-                    notify({pkg:'Ext.Element', member:'animate', msg:'Detected an extremely small animation delay, assuming the '+
-                        'deprecated unit seconds were used.  Please change to milliseconds.'});
-                }
-                if (config.duration && config.duration < 10) {
-                    config.duration *= 1000;
-                    notify({pkg:'Ext.Element', member:'animate', msg:'Detected an extremely small animation duration, assuming the '+
-                        'deprecated unit seconds were used.  Please change to milliseconds.'});
-                }
-                if (config.endOpacity) {
-                    config.opacity = config.endOpacity;
-                    delete config.endOpacity;
-                    deprecate({pkg:'Ext.Element', member:'animate', msg:'The endOpacity attribute of the animate config object is '+
-                        'no longer supported. Please use opacity instead.'});
-                }
-            }
-        })
-    });
-    
-    /*-------------------------------------------------------------
-     * Ajax
-     *-------------------------------------------------------------*/
-    Ext.Ajax.serializeForm = function(form) {
-        deprecate({pkg:'Ext.Ajax', member:'serializeForm', alt:'Ext.core.Element.serializeForm'});
-        return Ext.core.Element.serializeForm(form);
-    };
-    
-//    Ext.extend = function(subclass, superclass, members) {
-//        deprecate({pkg:'Ext', member:'extend', alt:'Ext.define', 
-//            msg:'Declare your class with Ext.define() and use the "extend" config to specify the superclass.'});
-//    
-//        if (arguments.length === 2 && Ext.isObject(superclass)) {
-//            members = superclass;
-//            superclass = subclass;
-//            subclass = null;
-//        }
-//
-//        var cls;
-//
-//        if (!superclass) {
-//            compat.error("Attempting to extend from a class which has not been loaded on the page.");
-//        }
-//        members = members || {};
-//        members.extend = superclass;
-//        members.preprocessors = ['extend', 'mixins', 'config', 'statics'];
-//        
-//        if (subclass) {
-//            if (!subclass.hasOwnProperty('constructor')) {
-//                subclass.constructor = Ext.apply({}, subclass);
-//            }
-//            cls = new Ext.Class(subclass, members);
-//        }
-//        else {
-//            cls = new Ext.Class(members);
-//        }
-//
-//        cls.prototype.override = function(o) {
-//            for (var m in o) {
-//                if (o.hasOwnProperty(m)) {
-//                    this[m] = o[m];
-//                }
-//            }
-//        };
-//
-//        return cls;
-//    };
-})();
diff --git a/js/lib/jasmine/MIT.LICENSE b/js/lib/jasmine/MIT.LICENSE
deleted file mode 100644
index 1eb9b49..0000000
--- a/js/lib/jasmine/MIT.LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2008-2010 Pivotal Labs
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/js/lib/jasmine/jasmine-html.js b/js/lib/jasmine/jasmine-html.js
deleted file mode 100644
index c59f2de..0000000
--- a/js/lib/jasmine/jasmine-html.js
+++ /dev/null
@@ -1,182 +0,0 @@
-jasmine.TrivialReporter = function(doc) {
-  this.document = doc || document;
-  this.suiteDivs = {};
-  this.logRunningSpecs = false;
-};
-
-jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
-  var el = document.createElement(type);
-
-  for (var i = 2; i < arguments.length; i++) {
-    var child = arguments[i];
-
-    if (typeof child === 'string') {
-      el.appendChild(document.createTextNode(child));
-    } else {
-      if (child) { el.appendChild(child); }
-    }
-  }
-
-  for (var attr in attrs) {
-    if (attr == "className") {
-      el[attr] = attrs[attr];
-    } else {
-      el.setAttribute(attr, attrs[attr]);
-    }
-  }
-
-  return el;
-};
-
-jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
-  var showPassed, showSkipped;
-
-  this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
-      this.createDom('div', { className: 'banner' },
-        this.createDom('div', { className: 'logo' },
-            this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
-            this.createDom('span', { className: 'version' }, runner.env.versionString())),
-        this.createDom('div', { className: 'options' },
-            "Show ",
-            showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
-            this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
-            showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
-            this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
-            )
-          ),
-
-      this.runnerDiv = this.createDom('div', { className: 'runner running' },
-          this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
-          this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
-          this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
-      );
-
-  this.document.body.appendChild(this.outerDiv);
-
-  var suites = runner.suites();
-  for (var i = 0; i < suites.length; i++) {
-    var suite = suites[i];
-    var suiteDiv = this.createDom('div', { className: 'suite' },
-        this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
-        this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
-    this.suiteDivs[suite.id] = suiteDiv;
-    var parentDiv = this.outerDiv;
-    if (suite.parentSuite) {
-      parentDiv = this.suiteDivs[suite.parentSuite.id];
-    }
-    parentDiv.appendChild(suiteDiv);
-  }
-
-  this.startedAt = new Date();
-
-  var self = this;
-  showPassed.onchange = function(evt) {
-    if (evt.target.checked) {
-      self.outerDiv.className += ' show-passed';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
-    }
-  };
-
-  showSkipped.onchange = function(evt) {
-    if (evt.target.checked) {
-      self.outerDiv.className += ' show-skipped';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
-    }
-  };
-};
-
-jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
-  var results = runner.results();
-  var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
-  this.runnerDiv.setAttribute("class", className);
-  //do it twice for IE
-  this.runnerDiv.setAttribute("className", className);
-  var specs = runner.specs();
-  var specCount = 0;
-  for (var i = 0; i < specs.length; i++) {
-    if (this.specFilter(specs[i])) {
-      specCount++;
-    }
-  }
-  var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
-  message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
-  this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
-
-  this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
-};
-
-jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
-  var results = suite.results();
-  var status = results.passed() ? 'passed' : 'failed';
-  if (results.totalCount == 0) { // todo: change this to check results.skipped
-    status = 'skipped';
-  }
-  this.suiteDivs[suite.id].className += " " + status;
-};
-
-jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
-  if (this.logRunningSpecs) {
-    this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
-  }
-};
-
-jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
-  var results = spec.results();
-  var status = results.passed() ? 'passed' : 'failed';
-  if (results.skipped) {
-    status = 'skipped';
-  }
-  var specDiv = this.createDom('div', { className: 'spec '  + status },
-      this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
-      this.createDom('a', {
-        className: 'description',
-        href: '?spec=' + encodeURIComponent(spec.getFullName()),
-        title: spec.getFullName()
-      }, spec.description));
-
-
-  var resultItems = results.getItems();
-  var messagesDiv = this.createDom('div', { className: 'messages' });
-  for (var i = 0; i < resultItems.length; i++) {
-    var result = resultItems[i];
-
-    if (result.type == 'log') {
-      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
-    } else if (result.type == 'expect' && result.passed && !result.passed()) {
-      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
-
-      if (result.trace.stack) {
-        messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
-      }
-    }
-  }
-
-  if (messagesDiv.childNodes.length > 0) {
-    specDiv.appendChild(messagesDiv);
-  }
-
-  this.suiteDivs[spec.suite.id].appendChild(specDiv);
-};
-
-jasmine.TrivialReporter.prototype.log = function() {
-  var console = jasmine.getGlobal().console;
-  if (console && console.log) console.log.apply(console, arguments);
-};
-
-jasmine.TrivialReporter.prototype.getLocation = function() {
-  return this.document.location;
-};
-
-jasmine.TrivialReporter.prototype.specFilter = function(spec) {
-  var paramMap = {};
-  var params = this.getLocation().search.substring(1).split('&');
-  for (var i = 0; i < params.length; i++) {
-    var p = params[i].split('=');
-    paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
-  }
-
-  if (!paramMap["spec"]) return true;
-  return spec.getFullName().indexOf(paramMap["spec"]) == 0;
-};
diff --git a/js/lib/jasmine/jasmine.css b/js/lib/jasmine/jasmine.css
deleted file mode 100644
index 6583fe7..0000000
--- a/js/lib/jasmine/jasmine.css
+++ /dev/null
@@ -1,166 +0,0 @@
-body {
-  font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
-}
-
-
-.jasmine_reporter a:visited, .jasmine_reporter a {
-  color: #303; 
-}
-
-.jasmine_reporter a:hover, .jasmine_reporter a:active {
-  color: blue; 
-}
-
-.run_spec {
-  float:right;
-  padding-right: 5px;
-  font-size: .8em;
-  text-decoration: none;
-}
-
-.jasmine_reporter {
-  margin: 0 5px;
-}
-
-.banner {
-  color: #303;
-  background-color: #fef;
-  padding: 5px;
-}
-
-.logo {
-  float: left;
-  font-size: 1.1em;
-  padding-left: 5px;
-}
-
-.logo .version {
-  font-size: .6em;
-  padding-left: 1em;
-}
-
-.runner.running {
-  background-color: yellow;
-}
-
-
-.options {
-  text-align: right;
-  font-size: .8em;
-}
-
-
-
-
-.suite {
-  border: 1px outset gray;
-  margin: 5px 0;
-  padding-left: 1em;
-}
-
-.suite .suite {
-  margin: 5px; 
-}
-
-.suite.passed {
-  background-color: #dfd;
-}
-
-.suite.failed {
-  background-color: #fdd;
-}
-
-.spec {
-  margin: 5px;
-  padding-left: 1em;
-  clear: both;
-}
-
-.spec.failed, .spec.passed, .spec.skipped {
-  padding-bottom: 5px;
-  border: 1px solid gray;
-}
-
-.spec.failed {
-  background-color: #fbb;
-  border-color: red;
-}
-
-.spec.passed {
-  background-color: #bfb;
-  border-color: green;
-}
-
-.spec.skipped {
-  background-color: #bbb;
-}
-
-.messages {
-  border-left: 1px dashed gray;
-  padding-left: 1em;
-  padding-right: 1em;
-}
-
-.passed {
-  background-color: #cfc;
-  display: none;
-}
-
-.failed {
-  background-color: #fbb;
-}
-
-.skipped {
-  color: #777;
-  background-color: #eee;
-  display: none;
-}
-
-
-/*.resultMessage {*/
-  /*white-space: pre;*/
-/*}*/
-
-.resultMessage span.result {
-  display: block;
-  line-height: 2em;
-  color: black;
-}
-
-.resultMessage .mismatch {
-  color: black;
-}
-
-.stackTrace {
-  white-space: pre;
-  font-size: .8em;
-  margin-left: 10px;
-  max-height: 5em;
-  overflow: auto;
-  border: 1px inset red;
-  padding: 1em;
-  background: #eef;
-}
-
-.finished-at {
-  padding-left: 1em;
-  font-size: .6em;
-}
-
-.show-passed .passed,
-.show-skipped .skipped {
-  display: block;
-}
-
-
-#jasmine_content {
-  position:fixed;
-  right: 100%;
-}
-
-.runner {
-  border: 1px solid gray;
-  display: block;
-  margin: 5px 0;
-  padding: 2px 0 2px 10px;
-}
diff --git a/js/lib/jasmine/jasmine.js b/js/lib/jasmine/jasmine.js
deleted file mode 100644
index 68baf53..0000000
--- a/js/lib/jasmine/jasmine.js
+++ /dev/null
@@ -1,2421 +0,0 @@
-/**
- * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
- *
- * @namespace
- */
-var jasmine = {};
-
-/**
- * @private
- */
-jasmine.unimplementedMethod_ = function() {
-  throw new Error("unimplemented method");
-};
-
-/**
- * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
- * a plain old variable and may be redefined by somebody else.
- *
- * @private
- */
-jasmine.undefined = jasmine.___undefined___;
-
-/**
- * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
- *
- */
-jasmine.DEFAULT_UPDATE_INTERVAL = 250;
-
-/**
- * Default timeout interval in milliseconds for waitsFor() blocks.
- */
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
-
-jasmine.getGlobal = function() {
-  function getGlobal() {
-    return this;
-  }
-
-  return getGlobal();
-};
-
-/**
- * Allows for bound functions to be compared.  Internal use only.
- *
- * @ignore
- * @private
- * @param base {Object} bound 'this' for the function
- * @param name {Function} function to find
- */
-jasmine.bindOriginal_ = function(base, name) {
-  var original = base[name];
-  if (original.apply) {
-    return function() {
-      return original.apply(base, arguments);
-    };
-  } else {
-    // IE support
-    return jasmine.getGlobal()[name];
-  }
-};
-
-jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
-jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
-jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
-jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
-
-jasmine.MessageResult = function(values) {
-  this.type = 'log';
-  this.values = values;
-  this.trace = new Error(); // todo: test better
-};
-
-jasmine.MessageResult.prototype.toString = function() {
-  var text = "";
-  for(var i = 0; i < this.values.length; i++) {
-    if (i > 0) text += " ";
-    if (jasmine.isString_(this.values[i])) {
-      text += this.values[i];
-    } else {
-      text += jasmine.pp(this.values[i]);
-    }
-  }
-  return text;
-};
-
-jasmine.ExpectationResult = function(params) {
-  this.type = 'expect';
-  this.matcherName = params.matcherName;
-  this.passed_ = params.passed;
-  this.expected = params.expected;
-  this.actual = params.actual;
-
-  this.message = this.passed_ ? 'Passed.' : params.message;
-  this.trace = this.passed_ ? '' : new Error(this.message);
-};
-
-jasmine.ExpectationResult.prototype.toString = function () {
-  return this.message;
-};
-
-jasmine.ExpectationResult.prototype.passed = function () {
-  return this.passed_;
-};
-
-/**
- * Getter for the Jasmine environment. Ensures one gets created
- */
-jasmine.getEnv = function() {
-  return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isArray_ = function(value) {
-  return jasmine.isA_("Array", value);  
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isString_ = function(value) {
-  return jasmine.isA_("String", value);
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isNumber_ = function(value) {
-  return jasmine.isA_("Number", value);
-};
-
-/**
- * @ignore
- * @private
- * @param {String} typeName
- * @param value
- * @returns {Boolean}
- */
-jasmine.isA_ = function(typeName, value) {
-  return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
-};
-
-/**
- * Pretty printer for expecations.  Takes any object and turns it into a human-readable string.
- *
- * @param value {Object} an object to be outputted
- * @returns {String}
- */
-jasmine.pp = function(value) {
-  var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
-  stringPrettyPrinter.format(value);
-  return stringPrettyPrinter.string;
-};
-
-/**
- * Returns true if the object is a DOM Node.
- *
- * @param {Object} obj object to check
- * @returns {Boolean}
- */
-jasmine.isDomNode = function(obj) {
-  return obj['nodeType'] > 0;
-};
-
-/**
- * Returns a matchable 'generic' object of the class type.  For use in expecations of type when values don't matter.
- *
- * @example
- * // don't care about which function is passed in, as long as it's a function
- * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
- *
- * @param {Class} clazz
- * @returns matchable object of the type clazz
- */
-jasmine.any = function(clazz) {
-  return new jasmine.Matchers.Any(clazz);
-};
-
-/**
- * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
- *
- * Spies should be created in test setup, before expectations.  They can then be checked, using the standard Jasmine
- * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
- *
- * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
- *
- * Spies are torn down at the end of every spec.
- *
- * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
- *
- * @example
- * // a stub
- * var myStub = jasmine.createSpy('myStub');  // can be used anywhere
- *
- * // spy example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- *
- * // actual foo.not will not be called, execution stops
- * spyOn(foo, 'not');
-
- // foo.not spied upon, execution will continue to implementation
- * spyOn(foo, 'not').andCallThrough();
- *
- * // fake example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- *
- * // foo.not(val) will return val
- * spyOn(foo, 'not').andCallFake(function(value) {return value;});
- *
- * // mock example
- * foo.not(7 == 7);
- * expect(foo.not).toHaveBeenCalled();
- * expect(foo.not).toHaveBeenCalledWith(true);
- *
- * @constructor
- * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
- * @param {String} name
- */
-jasmine.Spy = function(name) {
-  /**
-   * The name of the spy, if provided.
-   */
-  this.identity = name || 'unknown';
-  /**
-   *  Is this Object a spy?
-   */
-  this.isSpy = true;
-  /**
-   * The actual function this spy stubs.
-   */
-  this.plan = function() {
-  };
-  /**
-   * Tracking of the most recent call to the spy.
-   * @example
-   * var mySpy = jasmine.createSpy('foo');
-   * mySpy(1, 2);
-   * mySpy.mostRecentCall.args = [1, 2];
-   */
-  this.mostRecentCall = {};
-
-  /**
-   * Holds arguments for each call to the spy, indexed by call count
-   * @example
-   * var mySpy = jasmine.createSpy('foo');
-   * mySpy(1, 2);
-   * mySpy(7, 8);
-   * mySpy.mostRecentCall.args = [7, 8];
-   * mySpy.argsForCall[0] = [1, 2];
-   * mySpy.argsForCall[1] = [7, 8];
-   */
-  this.argsForCall = [];
-  this.calls = [];
-};
-
-/**
- * Tells a spy to call through to the actual implemenatation.
- *
- * @example
- * var foo = {
- *   bar: function() { // do some stuff }
- * }
- *
- * // defining a spy on an existing property: foo.bar
- * spyOn(foo, 'bar').andCallThrough();
- */
-jasmine.Spy.prototype.andCallThrough = function() {
-  this.plan = this.originalValue;
-  return this;
-};
-
-/**
- * For setting the return value of a spy.
- *
- * @example
- * // defining a spy from scratch: foo() returns 'baz'
- * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
- *
- * // defining a spy on an existing property: foo.bar() returns 'baz'
- * spyOn(foo, 'bar').andReturn('baz');
- *
- * @param {Object} value
- */
-jasmine.Spy.prototype.andReturn = function(value) {
-  this.plan = function() {
-    return value;
-  };
-  return this;
-};
-
-/**
- * For throwing an exception when a spy is called.
- *
- * @example
- * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
- * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
- *
- * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
- * spyOn(foo, 'bar').andThrow('baz');
- *
- * @param {String} exceptionMsg
- */
-jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
-  this.plan = function() {
-    throw exceptionMsg;
-  };
-  return this;
-};
-
-/**
- * Calls an alternate implementation when a spy is called.
- *
- * @example
- * var baz = function() {
- *   // do some stuff, return something
- * }
- * // defining a spy from scratch: foo() calls the function baz
- * var foo = jasmine.createSpy('spy on foo').andCall(baz);
- *
- * // defining a spy on an existing property: foo.bar() calls an anonymnous function
- * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
- *
- * @param {Function} fakeFunc
- */
-jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
-  this.plan = fakeFunc;
-  return this;
-};
-
-/**
- * Resets all of a spy's the tracking variables so that it can be used again.
- *
- * @example
- * spyOn(foo, 'bar');
- *
- * foo.bar();
- *
- * expect(foo.bar.callCount).toEqual(1);
- *
- * foo.bar.reset();
- *
- * expect(foo.bar.callCount).toEqual(0);
- */
-jasmine.Spy.prototype.reset = function() {
-  this.wasCalled = false;
-  this.callCount = 0;
-  this.argsForCall = [];
-  this.calls = [];
-  this.mostRecentCall = {};
-};
-
-jasmine.createSpy = function(name) {
-
-  var spyObj = function() {
-    spyObj.wasCalled = true;
-    spyObj.callCount++;
-    var args = jasmine.util.argsToArray(arguments);
-    spyObj.mostRecentCall.object = this;
-    spyObj.mostRecentCall.args = args;
-    spyObj.argsForCall.push(args);
-    spyObj.calls.push({object: this, args: args});
-    return spyObj.plan.apply(this, arguments);
-  };
-
-  var spy = new jasmine.Spy(name);
-
-  for (var prop in spy) {
-    spyObj[prop] = spy[prop];
-  }
-
-  spyObj.reset();
-
-  return spyObj;
-};
-
-/**
- * Determines whether an object is a spy.
- *
- * @param {jasmine.Spy|Object} putativeSpy
- * @returns {Boolean}
- */
-jasmine.isSpy = function(putativeSpy) {
-  return putativeSpy && putativeSpy.isSpy;
-};
-
-/**
- * Creates a more complicated spy: an Object that has every property a function that is a spy.  Used for stubbing something
- * large in one call.
- *
- * @param {String} baseName name of spy class
- * @param {Array} methodNames array of names of methods to make spies
- */
-jasmine.createSpyObj = function(baseName, methodNames) {
-  if (!jasmine.isArray_(methodNames) || methodNames.length == 0) {
-    throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
-  }
-  var obj = {};
-  for (var i = 0; i < methodNames.length; i++) {
-    obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
-  }
-  return obj;
-};
-
-/**
- * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
-jasmine.log = function() {
-  var spec = jasmine.getEnv().currentSpec;
-  spec.log.apply(spec, arguments);
-};
-
-/**
- * Function that installs a spy on an existing object's method name.  Used within a Spec to create a spy.
- *
- * @example
- * // spy example
- * var foo = {
- *   not: function(bool) { return !bool; }
- * }
- * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
- *
- * @see jasmine.createSpy
- * @param obj
- * @param methodName
- * @returns a Jasmine spy that can be chained with all spy methods
- */
-var spyOn = function(obj, methodName) {
-  return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
-};
-
-/**
- * Creates a Jasmine spec that will be added to the current suite.
- *
- * // TODO: pending tests
- *
- * @example
- * it('should be true', function() {
- *   expect(true).toEqual(true);
- * });
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
-var it = function(desc, func) {
-  return jasmine.getEnv().it(desc, func);
-};
-
-/**
- * Creates a <em>disabled</em> Jasmine spec.
- *
- * A convenience method that allows existing specs to be disabled temporarily during development.
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
-var xit = function(desc, func) {
-  return jasmine.getEnv().xit(desc, func);
-};
-
-/**
- * Starts a chain for a Jasmine expectation.
- *
- * It is passed an Object that is the actual value and should chain to one of the many
- * jasmine.Matchers functions.
- *
- * @param {Object} actual Actual value to test against and expected value
- */
-var expect = function(actual) {
-  return jasmine.getEnv().currentSpec.expect(actual);
-};
-
-/**
- * Defines part of a jasmine spec.  Used in cominbination with waits or waitsFor in asynchrnous specs.
- *
- * @param {Function} func Function that defines part of a jasmine spec.
- */
-var runs = function(func) {
-  jasmine.getEnv().currentSpec.runs(func);
-};
-
-/**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
-var waits = function(timeout) {
-  jasmine.getEnv().currentSpec.waits(timeout);
-};
-
-/**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
-var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
-  jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
-};
-
-/**
- * A function that is called before each spec in a suite.
- *
- * Used for spec setup, including validating assumptions.
- *
- * @param {Function} beforeEachFunction
- */
-var beforeEach = function(beforeEachFunction) {
-  jasmine.getEnv().beforeEach(beforeEachFunction);
-};
-
-/**
- * A function that is called after each spec in a suite.
- *
- * Used for restoring any state that is hijacked during spec execution.
- *
- * @param {Function} afterEachFunction
- */
-var afterEach = function(afterEachFunction) {
-  jasmine.getEnv().afterEach(afterEachFunction);
-};
-
-/**
- * Defines a suite of specifications.
- *
- * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
- * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
- * of setup in some tests.
- *
- * @example
- * // TODO: a simple suite
- *
- * // TODO: a simple suite with a nested describe block
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
-var describe = function(description, specDefinitions) {
-  return jasmine.getEnv().describe(description, specDefinitions);
-};
-
-/**
- * Disables a suite of specifications.  Used to disable some suites in a file, or files, temporarily during development.
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
-var xdescribe = function(description, specDefinitions) {
-  return jasmine.getEnv().xdescribe(description, specDefinitions);
-};
-
-
-// Provide the XMLHttpRequest class for IE 5.x-6.x:
-jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
-  try {
-    return new ActiveXObject("Msxml2.XMLHTTP.6.0");
-  } catch(e) {
-  }
-  try {
-    return new ActiveXObject("Msxml2.XMLHTTP.3.0");
-  } catch(e) {
-  }
-  try {
-    return new ActiveXObject("Msxml2.XMLHTTP");
-  } catch(e) {
-  }
-  try {
-    return new ActiveXObject("Microsoft.XMLHTTP");
-  } catch(e) {
-  }
-  throw new Error("This browser does not support XMLHttpRequest.");
-} : XMLHttpRequest;
-/**
- * @namespace
- */
-jasmine.util = {};
-
-/**
- * Declare that a child class inherit it's prototype from the parent class.
- *
- * @private
- * @param {Function} childClass
- * @param {Function} parentClass
- */
-jasmine.util.inherit = function(childClass, parentClass) {
-  /**
-   * @private
-   */
-  var subclass = function() {
-  };
-  subclass.prototype = parentClass.prototype;
-  childClass.prototype = new subclass;
-};
-
-jasmine.util.formatException = function(e) {
-  var lineNumber;
-  if (e.line) {
-    lineNumber = e.line;
-  }
-  else if (e.lineNumber) {
-    lineNumber = e.lineNumber;
-  }
-
-  var file;
-
-  if (e.sourceURL) {
-    file = e.sourceURL;
-  }
-  else if (e.fileName) {
-    file = e.fileName;
-  }
-
-  var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
-
-  if (file && lineNumber) {
-    message += ' in ' + file + ' (line ' + lineNumber + ')';
-  }
-
-  return message;
-};
-
-jasmine.util.htmlEscape = function(str) {
-  if (!str) return str;
-  return str.replace(/&/g, '&amp;')
-    .replace(/</g, '&lt;')
-    .replace(/>/g, '&gt;');
-};
-
-jasmine.util.argsToArray = function(args) {
-  var arrayOfArgs = [];
-  for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
-  return arrayOfArgs;
-};
-
-jasmine.util.extend = function(destination, source) {
-  for (var property in source) destination[property] = source[property];
-  return destination;
-};
-
-/**
- * Environment for Jasmine
- *
- * @constructor
- */
-jasmine.Env = function() {
-  this.currentSpec = null;
-  this.currentSuite = null;
-  this.currentRunner_ = new jasmine.Runner(this);
-
-  this.reporter = new jasmine.MultiReporter();
-
-  this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
-  this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
-  this.lastUpdate = 0;
-  this.specFilter = function() {
-    return true;
-  };
-
-  this.nextSpecId_ = 0;
-  this.nextSuiteId_ = 0;
-  this.equalityTesters_ = [];
-
-  // wrap matchers
-  this.matchersClass = function() {
-    jasmine.Matchers.apply(this, arguments);
-  };
-  jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
-
-  jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
-};
-
-
-jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
-jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
-jasmine.Env.prototype.setInterval = jasmine.setInterval;
-jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
-
-/**
- * @returns an object containing jasmine version build info, if set.
- */
-jasmine.Env.prototype.version = function () {
-  if (jasmine.version_) {
-    return jasmine.version_;
-  } else {
-    throw new Error('Version not set');
-  }
-};
-
-/**
- * @returns string containing jasmine version build info, if set.
- */
-jasmine.Env.prototype.versionString = function() {
-  if (jasmine.version_) {
-    var version = this.version();
-    return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
-  } else {
-    return "version unknown";
-  }
-};
-
-/**
- * @returns a sequential integer starting at 0
- */
-jasmine.Env.prototype.nextSpecId = function () {
-  return this.nextSpecId_++;
-};
-
-/**
- * @returns a sequential integer starting at 0
- */
-jasmine.Env.prototype.nextSuiteId = function () {
-  return this.nextSuiteId_++;
-};
-
-/**
- * Register a reporter to receive status updates from Jasmine.
- * @param {jasmine.Reporter} reporter An object which will receive status updates.
- */
-jasmine.Env.prototype.addReporter = function(reporter) {
-  this.reporter.addReporter(reporter);
-};
-
-jasmine.Env.prototype.execute = function() {
-  this.currentRunner_.execute();
-};
-
-jasmine.Env.prototype.describe = function(description, specDefinitions) {
-  var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
-
-  var parentSuite = this.currentSuite;
-  if (parentSuite) {
-    parentSuite.add(suite);
-  } else {
-    this.currentRunner_.add(suite);
-  }
-
-  this.currentSuite = suite;
-
-  var declarationError = null;
-  try {
-    specDefinitions.call(suite);
-  } catch(e) {
-    declarationError = e;
-  }
-
-  this.currentSuite = parentSuite;
-
-  if (declarationError) {
-    this.it("encountered a declaration exception", function() {
-      throw declarationError;
-    });
-  }
-
-  return suite;
-};
-
-jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
-  if (this.currentSuite) {
-    this.currentSuite.beforeEach(beforeEachFunction);
-  } else {
-    this.currentRunner_.beforeEach(beforeEachFunction);
-  }
-};
-
-jasmine.Env.prototype.currentRunner = function () {
-  return this.currentRunner_;
-};
-
-jasmine.Env.prototype.afterEach = function(afterEachFunction) {
-  if (this.currentSuite) {
-    this.currentSuite.afterEach(afterEachFunction);
-  } else {
-    this.currentRunner_.afterEach(afterEachFunction);
-  }
-
-};
-
-jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
-  return {
-    execute: function() {
-    }
-  };
-};
-
-jasmine.Env.prototype.it = function(description, func) {
-  var spec = new jasmine.Spec(this, this.currentSuite, description);
-  this.currentSuite.add(spec);
-  this.currentSpec = spec;
-
-  if (func) {
-    spec.runs(func);
-  }
-
-  return spec;
-};
-
-jasmine.Env.prototype.xit = function(desc, func) {
-  return {
-    id: this.nextSpecId(),
-    runs: function() {
-    }
-  };
-};
-
-jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
-  if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
-    return true;
-  }
-
-  a.__Jasmine_been_here_before__ = b;
-  b.__Jasmine_been_here_before__ = a;
-
-  var hasKey = function(obj, keyName) {
-    return obj != null && obj[keyName] !== jasmine.undefined;
-  };
-
-  for (var property in b) {
-    if (!hasKey(a, property) && hasKey(b, property)) {
-      mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
-    }
-  }
-  for (property in a) {
-    if (!hasKey(b, property) && hasKey(a, property)) {
-      mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
-    }
-  }
-  for (property in b) {
-    if (property == '__Jasmine_been_here_before__') continue;
-    if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
-      mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
-    }
-  }
-
-  if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
-    mismatchValues.push("arrays were not the same length");
-  }
-
-  delete a.__Jasmine_been_here_before__;
-  delete b.__Jasmine_been_here_before__;
-  return (mismatchKeys.length == 0 && mismatchValues.length == 0);
-};
-
-jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
-  mismatchKeys = mismatchKeys || [];
-  mismatchValues = mismatchValues || [];
-
-  for (var i = 0; i < this.equalityTesters_.length; i++) {
-    var equalityTester = this.equalityTesters_[i];
-    var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
-    if (result !== jasmine.undefined) return result;
-  }
-
-  if (a === b) return true;
-
-  if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
-    return (a == jasmine.undefined && b == jasmine.undefined);
-  }
-
-  if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
-    return a === b;
-  }
-
-  if (a instanceof Date && b instanceof Date) {
-    return a.getTime() == b.getTime();
-  }
-
-  if (a instanceof jasmine.Matchers.Any) {
-    return a.matches(b);
-  }
-
-  if (b instanceof jasmine.Matchers.Any) {
-    return b.matches(a);
-  }
-
-  if (jasmine.isString_(a) && jasmine.isString_(b)) {
-    return (a == b);
-  }
-
-  if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
-    return (a == b);
-  }
-
-  if (typeof a === "object" && typeof b === "object") {
-    return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
-  }
-
-  //Straight check
-  return (a === b);
-};
-
-jasmine.Env.prototype.contains_ = function(haystack, needle) {
-  if (jasmine.isArray_(haystack)) {
-    for (var i = 0; i < haystack.length; i++) {
-      if (this.equals_(haystack[i], needle)) return true;
-    }
-    return false;
-  }
-  return haystack.indexOf(needle) >= 0;
-};
-
-jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
-  this.equalityTesters_.push(equalityTester);
-};
-/** No-op base class for Jasmine reporters.
- *
- * @constructor
- */
-jasmine.Reporter = function() {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecResults = function(spec) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.log = function(str) {
-};
-
-/**
- * Blocks are functions with executable code that make up a spec.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {Function} func
- * @param {jasmine.Spec} spec
- */
-jasmine.Block = function(env, func, spec) {
-  this.env = env;
-  this.func = func;
-  this.spec = spec;
-};
-
-jasmine.Block.prototype.execute = function(onComplete) {  
-  try {
-    this.func.apply(this.spec);
-  } catch (e) {
-    this.spec.fail(e);
-  }
-  onComplete();
-};
-/** JavaScript API reporter.
- *
- * @constructor
- */
-jasmine.JsApiReporter = function() {
-  this.started = false;
-  this.finished = false;
-  this.suites_ = [];
-  this.results_ = {};
-};
-
-jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
-  this.started = true;
-  var suites = runner.topLevelSuites();
-  for (var i = 0; i < suites.length; i++) {
-    var suite = suites[i];
-    this.suites_.push(this.summarize_(suite));
-  }
-};
-
-jasmine.JsApiReporter.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
-  var isSuite = suiteOrSpec instanceof jasmine.Suite;
-  var summary = {
-    id: suiteOrSpec.id,
-    name: suiteOrSpec.description,
-    type: isSuite ? 'suite' : 'spec',
-    children: []
-  };
-  
-  if (isSuite) {
-    var children = suiteOrSpec.children();
-    for (var i = 0; i < children.length; i++) {
-      summary.children.push(this.summarize_(children[i]));
-    }
-  }
-  return summary;
-};
-
-jasmine.JsApiReporter.prototype.results = function() {
-  return this.results_;
-};
-
-jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
-  return this.results_[specId];
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
-  this.finished = true;
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
-  this.results_[spec.id] = {
-    messages: spec.results().getItems(),
-    result: spec.results().failedCount > 0 ? "failed" : "passed"
-  };
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.log = function(str) {
-};
-
-jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
-  var results = {};
-  for (var i = 0; i < specIds.length; i++) {
-    var specId = specIds[i];
-    results[specId] = this.summarizeResult_(this.results_[specId]);
-  }
-  return results;
-};
-
-jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
-  var summaryMessages = [];
-  var messagesLength = result.messages.length;
-  for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
-    var resultMessage = result.messages[messageIndex];
-    summaryMessages.push({
-      text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
-      passed: resultMessage.passed ? resultMessage.passed() : true,
-      type: resultMessage.type,
-      message: resultMessage.message,
-      trace: {
-        stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
-      }
-    });
-  }
-
-  return {
-    result : result.result,
-    messages : summaryMessages
-  };
-};
-
-/**
- * @constructor
- * @param {jasmine.Env} env
- * @param actual
- * @param {jasmine.Spec} spec
- */
-jasmine.Matchers = function(env, actual, spec, opt_isNot) {
-  this.env = env;
-  this.actual = actual;
-  this.spec = spec;
-  this.isNot = opt_isNot || false;
-  this.reportWasCalled_ = false;
-};
-
-// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
-jasmine.Matchers.pp = function(str) {
-  throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
-};
-
-// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
-jasmine.Matchers.prototype.report = function(result, failing_message, details) {
-  throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
-};
-
-jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
-  for (var methodName in prototype) {
-    if (methodName == 'report') continue;
-    var orig = prototype[methodName];
-    matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
-  }
-};
-
-jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
-  return function() {
-    var matcherArgs = jasmine.util.argsToArray(arguments);
-    var result = matcherFunction.apply(this, arguments);
-
-    if (this.isNot) {
-      result = !result;
-    }
-
-    if (this.reportWasCalled_) return result;
-
-    var message;
-    if (!result) {
-      if (this.message) {
-        message = this.message.apply(this, arguments);
-        if (jasmine.isArray_(message)) {
-          message = message[this.isNot ? 1 : 0];
-        }
-      } else {
-        var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
-        message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
-        if (matcherArgs.length > 0) {
-          for (var i = 0; i < matcherArgs.length; i++) {
-            if (i > 0) message += ",";
-            message += " " + jasmine.pp(matcherArgs[i]);
-          }
-        }
-        message += ".";
-      }
-    }
-    var expectationResult = new jasmine.ExpectationResult({
-      matcherName: matcherName,
-      passed: result,
-      expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
-      actual: this.actual,
-      message: message
-    });
-    this.spec.addMatcherResult(expectationResult);
-    return jasmine.undefined;
-  };
-};
-
-
-
-
-/**
- * toBe: compares the actual to the expected using ===
- * @param expected
- */
-jasmine.Matchers.prototype.toBe = function(expected) {
-  return this.actual === expected;
-};
-
-/**
- * toNotBe: compares the actual to the expected using !==
- * @param expected
- * @deprecated as of 1.0. Use not.toBe() instead.
- */
-jasmine.Matchers.prototype.toNotBe = function(expected) {
-  return this.actual !== expected;
-};
-
-/**
- * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
- *
- * @param expected
- */
-jasmine.Matchers.prototype.toEqual = function(expected) {
-  return this.env.equals_(this.actual, expected);
-};
-
-/**
- * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
- * @param expected
- * @deprecated as of 1.0. Use not.toNotEqual() instead.
- */
-jasmine.Matchers.prototype.toNotEqual = function(expected) {
-  return !this.env.equals_(this.actual, expected);
-};
-
-/**
- * Matcher that compares the actual to the expected using a regular expression.  Constructs a RegExp, so takes
- * a pattern or a String.
- *
- * @param expected
- */
-jasmine.Matchers.prototype.toMatch = function(expected) {
-  return new RegExp(expected).test(this.actual);
-};
-
-/**
- * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
- * @param expected
- * @deprecated as of 1.0. Use not.toMatch() instead.
- */
-jasmine.Matchers.prototype.toNotMatch = function(expected) {
-  return !(new RegExp(expected).test(this.actual));
-};
-
-/**
- * Matcher that compares the actual to jasmine.undefined.
- */
-jasmine.Matchers.prototype.toBeDefined = function() {
-  return (this.actual !== jasmine.undefined);
-};
-
-/**
- * Matcher that compares the actual to jasmine.undefined.
- */
-jasmine.Matchers.prototype.toBeUndefined = function() {
-  return (this.actual === jasmine.undefined);
-};
-
-/**
- * Matcher that compares the actual to null.
- */
-jasmine.Matchers.prototype.toBeNull = function() {
-  return (this.actual === null);
-};
-
-/**
- * Matcher that boolean not-nots the actual.
- */
-jasmine.Matchers.prototype.toBeTruthy = function() {
-  return !!this.actual;
-};
-
-
-/**
- * Matcher that boolean nots the actual.
- */
-jasmine.Matchers.prototype.toBeFalsy = function() {
-  return !this.actual;
-};
-
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was called.
- */
-jasmine.Matchers.prototype.toHaveBeenCalled = function() {
-  if (arguments.length > 0) {
-    throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
-  }
-
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy " + this.actual.identity + " to have been called.",
-      "Expected spy " + this.actual.identity + " not to have been called."
-    ];
-  };
-
-  return this.actual.wasCalled;
-};
-
-/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
-jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was not called.
- *
- * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
- */
-jasmine.Matchers.prototype.wasNotCalled = function() {
-  if (arguments.length > 0) {
-    throw new Error('wasNotCalled does not take arguments');
-  }
-
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy " + this.actual.identity + " to not have been called.",
-      "Expected spy " + this.actual.identity + " to have been called."
-    ];
-  };
-
-  return !this.actual.wasCalled;
-};
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
- *
- * @example
- *
- */
-jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
-  var expectedArgs = jasmine.util.argsToArray(arguments);
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-  this.message = function() {
-    if (this.actual.callCount == 0) {
-      // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
-      return [
-        "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
-        "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
-      ];
-    } else {
-      return [
-        "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
-        "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
-      ];
-    }
-  };
-
-  return this.env.contains_(this.actual.argsForCall, expectedArgs);
-};
-
-/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
-
-/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasNotCalledWith = function() {
-  var expectedArgs = jasmine.util.argsToArray(arguments);
-  if (!jasmine.isSpy(this.actual)) {
-    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
-  }
-
-  this.message = function() {
-    return [
-      "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
-      "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
-    ]
-  };
-
-  return !this.env.contains_(this.actual.argsForCall, expectedArgs);
-};
-
-/**
- * Matcher that checks that the expected item is an element in the actual Array.
- *
- * @param {Object} expected
- */
-jasmine.Matchers.prototype.toContain = function(expected) {
-  return this.env.contains_(this.actual, expected);
-};
-
-/**
- * Matcher that checks that the expected item is NOT an element in the actual Array.
- *
- * @param {Object} expected
- * @deprecated as of 1.0. Use not.toNotContain() instead.
- */
-jasmine.Matchers.prototype.toNotContain = function(expected) {
-  return !this.env.contains_(this.actual, expected);
-};
-
-jasmine.Matchers.prototype.toBeLessThan = function(expected) {
-  return this.actual < expected;
-};
-
-jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
-  return this.actual > expected;
-};
-
-/**
- * Matcher that checks that the expected exception was thrown by the actual.
- *
- * @param {String} expected
- */
-jasmine.Matchers.prototype.toThrow = function(expected) {
-  var result = false;
-  var exception;
-  if (typeof this.actual != 'function') {
-    throw new Error('Actual is not a function');
-  }
-  try {
-    this.actual();
-  } catch (e) {
-    exception = e;
-  }
-  if (exception) {
-    result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
-  }
-
-  var not = this.isNot ? "not " : "";
-
-  this.message = function() {
-    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
-      return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' ');
-    } else {
-      return "Expected function to throw an exception.";
-    }
-  };
-
-  return result;
-};
-
-jasmine.Matchers.Any = function(expectedClass) {
-  this.expectedClass = expectedClass;
-};
-
-jasmine.Matchers.Any.prototype.matches = function(other) {
-  if (this.expectedClass == String) {
-    return typeof other == 'string' || other instanceof String;
-  }
-
-  if (this.expectedClass == Number) {
-    return typeof other == 'number' || other instanceof Number;
-  }
-
-  if (this.expectedClass == Function) {
-    return typeof other == 'function' || other instanceof Function;
-  }
-
-  if (this.expectedClass == Object) {
-    return typeof other == 'object';
-  }
-
-  return other instanceof this.expectedClass;
-};
-
-jasmine.Matchers.Any.prototype.toString = function() {
-  return '<jasmine.any(' + this.expectedClass + ')>';
-};
-
-/**
- * @constructor
- */
-jasmine.MultiReporter = function() {
-  this.subReporters_ = [];
-};
-jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
-
-jasmine.MultiReporter.prototype.addReporter = function(reporter) {
-  this.subReporters_.push(reporter);
-};
-
-(function() {
-  var functionNames = [
-    "reportRunnerStarting",
-    "reportRunnerResults",
-    "reportSuiteResults",
-    "reportSpecStarting",
-    "reportSpecResults",
-    "log"
-  ];
-  for (var i = 0; i < functionNames.length; i++) {
-    var functionName = functionNames[i];
-    jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
-      return function() {
-        for (var j = 0; j < this.subReporters_.length; j++) {
-          var subReporter = this.subReporters_[j];
-          if (subReporter[functionName]) {
-            subReporter[functionName].apply(subReporter, arguments);
-          }
-        }
-      };
-    })(functionName);
-  }
-})();
-/**
- * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
- *
- * @constructor
- */
-jasmine.NestedResults = function() {
-  /**
-   * The total count of results
-   */
-  this.totalCount = 0;
-  /**
-   * Number of passed results
-   */
-  this.passedCount = 0;
-  /**
-   * Number of failed results
-   */
-  this.failedCount = 0;
-  /**
-   * Was this suite/spec skipped?
-   */
-  this.skipped = false;
-  /**
-   * @ignore
-   */
-  this.items_ = [];
-};
-
-/**
- * Roll up the result counts.
- *
- * @param result
- */
-jasmine.NestedResults.prototype.rollupCounts = function(result) {
-  this.totalCount += result.totalCount;
-  this.passedCount += result.passedCount;
-  this.failedCount += result.failedCount;
-};
-
-/**
- * Adds a log message.
- * @param values Array of message parts which will be concatenated later.
- */
-jasmine.NestedResults.prototype.log = function(values) {
-  this.items_.push(new jasmine.MessageResult(values));
-};
-
-/**
- * Getter for the results: message & results.
- */
-jasmine.NestedResults.prototype.getItems = function() {
-  return this.items_;
-};
-
-/**
- * Adds a result, tracking counts (total, passed, & failed)
- * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
- */
-jasmine.NestedResults.prototype.addResult = function(result) {
-  if (result.type != 'log') {
-    if (result.items_) {
-      this.rollupCounts(result);
-    } else {
-      this.totalCount++;
-      if (result.passed()) {
-        this.passedCount++;
-      } else {
-        this.failedCount++;
-      }
-    }
-  }
-  this.items_.push(result);
-};
-
-/**
- * @returns {Boolean} True if <b>everything</b> below passed
- */
-jasmine.NestedResults.prototype.passed = function() {
-  return this.passedCount === this.totalCount;
-};
-/**
- * Base class for pretty printing for expectation results.
- */
-jasmine.PrettyPrinter = function() {
-  this.ppNestLevel_ = 0;
-};
-
-/**
- * Formats a value in a nice, human-readable string.
- *
- * @param value
- */
-jasmine.PrettyPrinter.prototype.format = function(value) {
-  if (this.ppNestLevel_ > 40) {
-    throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
-  }
-
-  this.ppNestLevel_++;
-  try {
-    if (value === jasmine.undefined) {
-      this.emitScalar('undefined');
-    } else if (value === null) {
-      this.emitScalar('null');
-    } else if (value === jasmine.getGlobal()) {
-      this.emitScalar('<global>');
-    } else if (value instanceof jasmine.Matchers.Any) {
-      this.emitScalar(value.toString());
-    } else if (typeof value === 'string') {
-      this.emitString(value);
-    } else if (jasmine.isSpy(value)) {
-      this.emitScalar("spy on " + value.identity);
-    } else if (value instanceof RegExp) {
-      this.emitScalar(value.toString());
-    } else if (typeof value === 'function') {
-      this.emitScalar('Function');
-    } else if (typeof value.nodeType === 'number') {
-      this.emitScalar('HTMLNode');
-    } else if (value instanceof Date) {
-      this.emitScalar('Date(' + value + ')');
-    } else if (value.__Jasmine_been_here_before__) {
-      this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
-    } else if (jasmine.isArray_(value) || typeof value == 'object') {
-      value.__Jasmine_been_here_before__ = true;
-      if (jasmine.isArray_(value)) {
-        this.emitArray(value);
-      } else {
-        this.emitObject(value);
-      }
-      delete value.__Jasmine_been_here_before__;
-    } else {
-      this.emitScalar(value.toString());
-    }
-  } finally {
-    this.ppNestLevel_--;
-  }
-};
-
-jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
-  for (var property in obj) {
-    if (property == '__Jasmine_been_here_before__') continue;
-    fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false);
-  }
-};
-
-jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
-
-jasmine.StringPrettyPrinter = function() {
-  jasmine.PrettyPrinter.call(this);
-
-  this.string = '';
-};
-jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
-
-jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
-  this.append(value);
-};
-
-jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
-  this.append("'" + value + "'");
-};
-
-jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
-  this.append('[ ');
-  for (var i = 0; i < array.length; i++) {
-    if (i > 0) {
-      this.append(', ');
-    }
-    this.format(array[i]);
-  }
-  this.append(' ]');
-};
-
-jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
-  var self = this;
-  this.append('{ ');
-  var first = true;
-
-  this.iterateObject(obj, function(property, isGetter) {
-    if (first) {
-      first = false;
-    } else {
-      self.append(', ');
-    }
-
-    self.append(property);
-    self.append(' : ');
-    if (isGetter) {
-      self.append('<getter>');
-    } else {
-      self.format(obj[property]);
-    }
-  });
-
-  this.append(' }');
-};
-
-jasmine.StringPrettyPrinter.prototype.append = function(value) {
-  this.string += value;
-};
-jasmine.Queue = function(env) {
-  this.env = env;
-  this.blocks = [];
-  this.running = false;
-  this.index = 0;
-  this.offset = 0;
-  this.abort = false;
-};
-
-jasmine.Queue.prototype.addBefore = function(block) {
-  this.blocks.unshift(block);
-};
-
-jasmine.Queue.prototype.add = function(block) {
-  this.blocks.push(block);
-};
-
-jasmine.Queue.prototype.insertNext = function(block) {
-  this.blocks.splice((this.index + this.offset + 1), 0, block);
-  this.offset++;
-};
-
-jasmine.Queue.prototype.start = function(onComplete) {
-  this.running = true;
-  this.onComplete = onComplete;
-  this.next_();
-};
-
-jasmine.Queue.prototype.isRunning = function() {
-  return this.running;
-};
-
-jasmine.Queue.LOOP_DONT_RECURSE = true;
-
-jasmine.Queue.prototype.next_ = function() {
-  var self = this;
-  var goAgain = true;
-
-  while (goAgain) {
-    goAgain = false;
-    
-    if (self.index < self.blocks.length && !this.abort) {
-      var calledSynchronously = true;
-      var completedSynchronously = false;
-
-      var onComplete = function () {
-        if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
-          completedSynchronously = true;
-          return;
-        }
-
-        if (self.blocks[self.index].abort) {
-          self.abort = true;
-        }
-
-        self.offset = 0;
-        self.index++;
-
-        var now = new Date().getTime();
-        if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
-          self.env.lastUpdate = now;
-          self.env.setTimeout(function() {
-            self.next_();
-          }, 0);
-        } else {
-          if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
-            goAgain = true;
-          } else {
-            self.next_();
-          }
-        }
-      };
-      self.blocks[self.index].execute(onComplete);
-
-      calledSynchronously = false;
-      if (completedSynchronously) {
-        onComplete();
-      }
-      
-    } else {
-      self.running = false;
-      if (self.onComplete) {
-        self.onComplete();
-      }
-    }
-  }
-};
-
-jasmine.Queue.prototype.results = function() {
-  var results = new jasmine.NestedResults();
-  for (var i = 0; i < this.blocks.length; i++) {
-    if (this.blocks[i].results) {
-      results.addResult(this.blocks[i].results());
-    }
-  }
-  return results;
-};
-
-
-/**
- * Runner
- *
- * @constructor
- * @param {jasmine.Env} env
- */
-jasmine.Runner = function(env) {
-  var self = this;
-  self.env = env;
-  self.queue = new jasmine.Queue(env);
-  self.before_ = [];
-  self.after_ = [];
-  self.suites_ = [];
-};
-
-jasmine.Runner.prototype.execute = function() {
-  var self = this;
-  if (self.env.reporter.reportRunnerStarting) {
-    self.env.reporter.reportRunnerStarting(this);
-  }
-  self.queue.start(function () {
-    self.finishCallback();
-  });
-};
-
-jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
-  beforeEachFunction.typeName = 'beforeEach';
-  this.before_.splice(0,0,beforeEachFunction);
-};
-
-jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
-  afterEachFunction.typeName = 'afterEach';
-  this.after_.splice(0,0,afterEachFunction);
-};
-
-
-jasmine.Runner.prototype.finishCallback = function() {
-  this.env.reporter.reportRunnerResults(this);
-};
-
-jasmine.Runner.prototype.addSuite = function(suite) {
-  this.suites_.push(suite);
-};
-
-jasmine.Runner.prototype.add = function(block) {
-  if (block instanceof jasmine.Suite) {
-    this.addSuite(block);
-  }
-  this.queue.add(block);
-};
-
-jasmine.Runner.prototype.specs = function () {
-  var suites = this.suites();
-  var specs = [];
-  for (var i = 0; i < suites.length; i++) {
-    specs = specs.concat(suites[i].specs());
-  }
-  return specs;
-};
-
-jasmine.Runner.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.Runner.prototype.topLevelSuites = function() {
-  var topLevelSuites = [];
-  for (var i = 0; i < this.suites_.length; i++) {
-    if (!this.suites_[i].parentSuite) {
-      topLevelSuites.push(this.suites_[i]);
-    }
-  }
-  return topLevelSuites;
-};
-
-jasmine.Runner.prototype.results = function() {
-  return this.queue.results();
-};
-/**
- * Internal representation of a Jasmine specification, or test.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {jasmine.Suite} suite
- * @param {String} description
- */
-jasmine.Spec = function(env, suite, description) {
-  if (!env) {
-    throw new Error('jasmine.Env() required');
-  }
-  if (!suite) {
-    throw new Error('jasmine.Suite() required');
-  }
-  var spec = this;
-  spec.id = env.nextSpecId ? env.nextSpecId() : null;
-  spec.env = env;
-  spec.suite = suite;
-  spec.description = description;
-  spec.queue = new jasmine.Queue(env);
-
-  spec.afterCallbacks = [];
-  spec.spies_ = [];
-
-  spec.results_ = new jasmine.NestedResults();
-  spec.results_.description = description;
-  spec.matchersClass = null;
-};
-
-jasmine.Spec.prototype.getFullName = function() {
-  return this.suite.getFullName() + ' ' + this.description + '.';
-};
-
-
-jasmine.Spec.prototype.results = function() {
-  return this.results_;
-};
-
-/**
- * All parameters are pretty-printed and concatenated together, then written to the spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
-jasmine.Spec.prototype.log = function() {
-  return this.results_.log(arguments);
-};
-
-jasmine.Spec.prototype.runs = function (func) {
-  var block = new jasmine.Block(this.env, func, this);
-  this.addToQueue(block);
-  return this;
-};
-
-jasmine.Spec.prototype.addToQueue = function (block) {
-  if (this.queue.isRunning()) {
-    this.queue.insertNext(block);
-  } else {
-    this.queue.add(block);
-  }
-};
-
-/**
- * @param {jasmine.ExpectationResult} result
- */
-jasmine.Spec.prototype.addMatcherResult = function(result) {
-  this.results_.addResult(result);
-};
-
-jasmine.Spec.prototype.expect = function(actual) {
-  var positive = new (this.getMatchersClass_())(this.env, actual, this);
-  positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
-  return positive;
-};
-
-/**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
-jasmine.Spec.prototype.waits = function(timeout) {
-  var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
-  this.addToQueue(waitsFunc);
-  return this;
-};
-
-/**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
-jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
-  var latchFunction_ = null;
-  var optional_timeoutMessage_ = null;
-  var optional_timeout_ = null;
-
-  for (var i = 0; i < arguments.length; i++) {
-    var arg = arguments[i];
-    switch (typeof arg) {
-      case 'function':
-        latchFunction_ = arg;
-        break;
-      case 'string':
-        optional_timeoutMessage_ = arg;
-        break;
-      case 'number':
-        optional_timeout_ = arg;
-        break;
-    }
-  }
-
-  var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
-  this.addToQueue(waitsForFunc);
-  return this;
-};
-
-jasmine.Spec.prototype.fail = function (e) {
-  var expectationResult = new jasmine.ExpectationResult({
-    passed: false,
-    message: e ? jasmine.util.formatException(e) : 'Exception'
-  });
-  this.results_.addResult(expectationResult);
-};
-
-jasmine.Spec.prototype.getMatchersClass_ = function() {
-  return this.matchersClass || this.env.matchersClass;
-};
-
-jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
-  var parent = this.getMatchersClass_();
-  var newMatchersClass = function() {
-    parent.apply(this, arguments);
-  };
-  jasmine.util.inherit(newMatchersClass, parent);
-  jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
-  this.matchersClass = newMatchersClass;
-};
-
-jasmine.Spec.prototype.finishCallback = function() {
-  this.env.reporter.reportSpecResults(this);
-};
-
-jasmine.Spec.prototype.finish = function(onComplete) {
-  this.removeAllSpies();
-  this.finishCallback();
-  if (onComplete) {
-    onComplete();
-  }
-};
-
-jasmine.Spec.prototype.after = function(doAfter) {
-  if (this.queue.isRunning()) {
-    this.queue.add(new jasmine.Block(this.env, doAfter, this));
-  } else {
-    this.afterCallbacks.unshift(doAfter);
-  }
-};
-
-jasmine.Spec.prototype.execute = function(onComplete) {
-  var spec = this;
-  if (!spec.env.specFilter(spec)) {
-    spec.results_.skipped = true;
-    spec.finish(onComplete);
-    return;
-  }
-
-  this.env.reporter.reportSpecStarting(this);
-
-  spec.env.currentSpec = spec;
-
-  spec.addBeforesAndAftersToQueue();
-
-  spec.queue.start(function () {
-    spec.finish(onComplete);
-  });
-};
-
-jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
-  var runner = this.env.currentRunner();
-  var i;
-
-  for (var suite = this.suite; suite; suite = suite.parentSuite) {
-    for (i = 0; i < suite.before_.length; i++) {
-      this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
-    }
-  }
-  for (i = 0; i < runner.before_.length; i++) {
-    this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
-  }
-  for (i = 0; i < this.afterCallbacks.length; i++) {
-    this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
-  }
-  for (suite = this.suite; suite; suite = suite.parentSuite) {
-    for (i = 0; i < suite.after_.length; i++) {
-      this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
-    }
-  }
-  for (i = 0; i < runner.after_.length; i++) {
-    this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
-  }
-};
-
-jasmine.Spec.prototype.explodes = function() {
-  throw 'explodes function should not have been called';
-};
-
-jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
-  if (obj == jasmine.undefined) {
-    throw "spyOn could not find an object to spy upon for " + methodName + "()";
-  }
-
-  if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
-    throw methodName + '() method does not exist';
-  }
-
-  if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
-    throw new Error(methodName + ' has already been spied upon');
-  }
-
-  var spyObj = jasmine.createSpy(methodName);
-
-  this.spies_.push(spyObj);
-  spyObj.baseObj = obj;
-  spyObj.methodName = methodName;
-  spyObj.originalValue = obj[methodName];
-
-  obj[methodName] = spyObj;
-
-  return spyObj;
-};
-
-jasmine.Spec.prototype.removeAllSpies = function() {
-  for (var i = 0; i < this.spies_.length; i++) {
-    var spy = this.spies_[i];
-    spy.baseObj[spy.methodName] = spy.originalValue;
-  }
-  this.spies_ = [];
-};
-
-/**
- * Internal representation of a Jasmine suite.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {String} description
- * @param {Function} specDefinitions
- * @param {jasmine.Suite} parentSuite
- */
-jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
-  var self = this;
-  self.id = env.nextSuiteId ? env.nextSuiteId() : null;
-  self.description = description;
-  self.queue = new jasmine.Queue(env);
-  self.parentSuite = parentSuite;
-  self.env = env;
-  self.before_ = [];
-  self.after_ = [];
-  self.children_ = [];
-  self.suites_ = [];
-  self.specs_ = [];
-};
-
-jasmine.Suite.prototype.getFullName = function() {
-  var fullName = this.description;
-  for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
-    fullName = parentSuite.description + ' ' + fullName;
-  }
-  return fullName;
-};
-
-jasmine.Suite.prototype.finish = function(onComplete) {
-  this.env.reporter.reportSuiteResults(this);
-  this.finished = true;
-  if (typeof(onComplete) == 'function') {
-    onComplete();
-  }
-};
-
-jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
-  beforeEachFunction.typeName = 'beforeEach';
-  this.before_.unshift(beforeEachFunction);
-};
-
-jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
-  afterEachFunction.typeName = 'afterEach';
-  this.after_.unshift(afterEachFunction);
-};
-
-jasmine.Suite.prototype.results = function() {
-  return this.queue.results();
-};
-
-jasmine.Suite.prototype.add = function(suiteOrSpec) {
-  this.children_.push(suiteOrSpec);
-  if (suiteOrSpec instanceof jasmine.Suite) {
-    this.suites_.push(suiteOrSpec);
-    this.env.currentRunner().addSuite(suiteOrSpec);
-  } else {
-    this.specs_.push(suiteOrSpec);
-  }
-  this.queue.add(suiteOrSpec);
-};
-
-jasmine.Suite.prototype.specs = function() {
-  return this.specs_;
-};
-
-jasmine.Suite.prototype.suites = function() {
-  return this.suites_;
-};
-
-jasmine.Suite.prototype.children = function() {
-  return this.children_;
-};
-
-jasmine.Suite.prototype.execute = function(onComplete) {
-  var self = this;
-  this.queue.start(function () {
-    self.finish(onComplete);
-  });
-};
-jasmine.WaitsBlock = function(env, timeout, spec) {
-  this.timeout = timeout;
-  jasmine.Block.call(this, env, null, spec);
-};
-
-jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
-
-jasmine.WaitsBlock.prototype.execute = function (onComplete) {
-  this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
-  this.env.setTimeout(function () {
-    onComplete();
-  }, this.timeout);
-};
-/**
- * A block which waits for some condition to become true, with timeout.
- *
- * @constructor
- * @extends jasmine.Block
- * @param {jasmine.Env} env The Jasmine environment.
- * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
- * @param {Function} latchFunction A function which returns true when the desired condition has been met.
- * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
- * @param {jasmine.Spec} spec The Jasmine spec.
- */
-jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
-  this.timeout = timeout || env.defaultTimeoutInterval;
-  this.latchFunction = latchFunction;
-  this.message = message;
-  this.totalTimeSpentWaitingForLatch = 0;
-  jasmine.Block.call(this, env, null, spec);
-};
-jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
-
-jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
-
-jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
-  this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
-  var latchFunctionResult;
-  try {
-    latchFunctionResult = this.latchFunction.apply(this.spec);
-  } catch (e) {
-    this.spec.fail(e);
-    onComplete();
-    return;
-  }
-
-  if (latchFunctionResult) {
-    onComplete();
-  } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
-    var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
-    this.spec.fail({
-      name: 'timeout',
-      message: message
-    });
-
-    this.abort = true;
-    onComplete();
-  } else {
-    this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
-    var self = this;
-    this.env.setTimeout(function() {
-      self.execute(onComplete);
-    }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
-  }
-};
-// Mock setTimeout, clearTimeout
-// Contributed by Pivotal Computer Systems, www.pivotalsf.com
-
-jasmine.FakeTimer = function() {
-  this.reset();
-
-  var self = this;
-  self.setTimeout = function(funcToCall, millis) {
-    self.timeoutsMade++;
-    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
-    return self.timeoutsMade;
-  };
-
-  self.setInterval = function(funcToCall, millis) {
-    self.timeoutsMade++;
-    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
-    return self.timeoutsMade;
-  };
-
-  self.clearTimeout = function(timeoutKey) {
-    self.scheduledFunctions[timeoutKey] = jasmine.undefined;
-  };
-
-  self.clearInterval = function(timeoutKey) {
-    self.scheduledFunctions[timeoutKey] = jasmine.undefined;
-  };
-
-};
-
-jasmine.FakeTimer.prototype.reset = function() {
-  this.timeoutsMade = 0;
-  this.scheduledFunctions = {};
-  this.nowMillis = 0;
-};
-
-jasmine.FakeTimer.prototype.tick = function(millis) {
-  var oldMillis = this.nowMillis;
-  var newMillis = oldMillis + millis;
-  this.runFunctionsWithinRange(oldMillis, newMillis);
-  this.nowMillis = newMillis;
-};
-
-jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
-  var scheduledFunc;
-  var funcsToRun = [];
-  for (var timeoutKey in this.scheduledFunctions) {
-    scheduledFunc = this.scheduledFunctions[timeoutKey];
-    if (scheduledFunc != jasmine.undefined &&
-        scheduledFunc.runAtMillis >= oldMillis &&
-        scheduledFunc.runAtMillis <= nowMillis) {
-      funcsToRun.push(scheduledFunc);
-      this.scheduledFunctions[timeoutKey] = jasmine.undefined;
-    }
-  }
-
-  if (funcsToRun.length > 0) {
-    funcsToRun.sort(function(a, b) {
-      return a.runAtMillis - b.runAtMillis;
-    });
-    for (var i = 0; i < funcsToRun.length; ++i) {
-      try {
-        var funcToRun = funcsToRun[i];
-        this.nowMillis = funcToRun.runAtMillis;
-        funcToRun.funcToCall();
-        if (funcToRun.recurring) {
-          this.scheduleFunction(funcToRun.timeoutKey,
-              funcToRun.funcToCall,
-              funcToRun.millis,
-              true);
-        }
-      } catch(e) {
-      }
-    }
-    this.runFunctionsWithinRange(oldMillis, nowMillis);
-  }
-};
-
-jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
-  this.scheduledFunctions[timeoutKey] = {
-    runAtMillis: this.nowMillis + millis,
-    funcToCall: funcToCall,
-    recurring: recurring,
-    timeoutKey: timeoutKey,
-    millis: millis
-  };
-};
-
-/**
- * @namespace
- */
-jasmine.Clock = {
-  defaultFakeTimer: new jasmine.FakeTimer(),
-
-  reset: function() {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.defaultFakeTimer.reset();
-  },
-
-  tick: function(millis) {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.defaultFakeTimer.tick(millis);
-  },
-
-  runFunctionsWithinRange: function(oldMillis, nowMillis) {
-    jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
-  },
-
-  scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
-    jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
-  },
-
-  useMock: function() {
-    if (!jasmine.Clock.isInstalled()) {
-      var spec = jasmine.getEnv().currentSpec;
-      spec.after(jasmine.Clock.uninstallMock);
-
-      jasmine.Clock.installMock();
-    }
-  },
-
-  installMock: function() {
-    jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
-  },
-
-  uninstallMock: function() {
-    jasmine.Clock.assertInstalled();
-    jasmine.Clock.installed = jasmine.Clock.real;
-  },
-
-  real: {
-    setTimeout: jasmine.getGlobal().setTimeout,
-    clearTimeout: jasmine.getGlobal().clearTimeout,
-    setInterval: jasmine.getGlobal().setInterval,
-    clearInterval: jasmine.getGlobal().clearInterval
-  },
-
-  assertInstalled: function() {
-    if (!jasmine.Clock.isInstalled()) {
-      throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
-    }
-  },
-
-  isInstalled: function() {
-    return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
-  },
-
-  installed: null
-};
-jasmine.Clock.installed = jasmine.Clock.real;
-
-//else for IE support
-jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
-  if (jasmine.Clock.installed.setTimeout.apply) {
-    return jasmine.Clock.installed.setTimeout.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.setTimeout(funcToCall, millis);
-  }
-};
-
-jasmine.getGlobal().setInterval = function(funcToCall, millis) {
-  if (jasmine.Clock.installed.setInterval.apply) {
-    return jasmine.Clock.installed.setInterval.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.setInterval(funcToCall, millis);
-  }
-};
-
-jasmine.getGlobal().clearTimeout = function(timeoutKey) {
-  if (jasmine.Clock.installed.clearTimeout.apply) {
-    return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.clearTimeout(timeoutKey);
-  }
-};
-
-jasmine.getGlobal().clearInterval = function(timeoutKey) {
-  if (jasmine.Clock.installed.clearTimeout.apply) {
-    return jasmine.Clock.installed.clearInterval.apply(this, arguments);
-  } else {
-    return jasmine.Clock.installed.clearInterval(timeoutKey);
-  }
-};
-
-
-jasmine.version_= {
-  "major": 1,
-  "minor": 0,
-  "build": 0,
-  "revision": 1284494074
-};
diff --git a/js/lib/sencha-jasmine/matchers/Controller.js b/js/lib/sencha-jasmine/matchers/Controller.js
deleted file mode 100644
index f26044b..0000000
--- a/js/lib/sencha-jasmine/matchers/Controller.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Sencha-specific matchers for convenient testing of Controller expectations
- */
-beforeEach(function() {
-    this.addMatchers({
-        toHaveRendered: function(expected) {
-            
-        }
-    });
-});
\ No newline at end of file
diff --git a/js/lib/sencha-jasmine/matchers/Model.js b/js/lib/sencha-jasmine/matchers/Model.js
deleted file mode 100644
index 0c91149..0000000
--- a/js/lib/sencha-jasmine/matchers/Model.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Sencha-specific matchers for convenient testing of Model expectations
- */
-beforeEach(function() {
-    this.addMatchers({
-        /**
-         * Sample usage:
-         * expect('User').toHaveMany('Product');
-         */
-        toHaveMany: function(expected) {
-            if (typeof this.actual == 'string') {
-                this.actual = Ext.ModelManager.types[this.actual].prototype;
-            }
-            
-            var associations = this.actual.associations.items,
-                length       = associations.length,
-                association, i;
-            
-            for (i = 0; i < length; i++) {
-                association = associations[i];
-                
-                if (association.associatedName == expected && association.type == 'hasMany') {
-                    return true;
-                }
-            }
-            
-            return false;
-        },
-        
-        /**
-         * Sample usage:
-         * expect('Product').toBelongTo('User')
-         */
-        toBelongTo: function(expected) {
-            if (typeof this.actual == 'string') {
-                this.actual = Ext.ModelManager.types[this.actual].prototype;
-            }
-            
-            var associations = this.actual.associations.items,
-                length       = associations.length,
-                association, i;
-            
-            for (i = 0; i < length; i++) {
-                association = associations[i];
-                
-                if (association.associatedName == expected && association.type == 'belongsTo') {
-                    return true;
-                }
-            }
-            
-            return false;
-        }
-    });
-});
\ No newline at end of file
diff --git a/js/lib/sencha-jasmine/sencha-jasmine.css b/js/lib/sencha-jasmine/sencha-jasmine.css
deleted file mode 100644
index 784d48f..0000000
--- a/js/lib/sencha-jasmine/sencha-jasmine.css
+++ /dev/null
@@ -1,226 +0,0 @@
-body {
-    font-family:"Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
-    margin:0;
-}
-
-.jasmine_reporter > * {
-    margin:10px;
-}
-
-.run_spec {
-    float:right;
-    font-size:10px;
-}
-
-/*banner*/
-.banner {
-    position:relative;
-    background:#fff;
-    -webkit-box-shadow:0 0 10px #ccc;
-    padding:4px 0 6px 6px;
-    margin:0 0 10px 0;
-}
-.banner .logo {
-    width:120px;
-    height:50px;
-
-    background:url(http://www.sencha.com/assets/images/logo-sencha-sm.png) no-repeat;
-}
-.banner .options {
-    position:absolute;
-    top:3px;
-    right:3px;
-    color:#666;
-    font-size:10px;
-}
-.banner .options .show {
-    text-align:right;
-}
-.banner .options .show > * {
-    display:inline-block;
-}
-.banner .options .show label {
-    margin-right:3px;
-}
-
-/*runner*/
-.runner,
-.suite {
-    display:block;
-
-    text-shadow:0 1px 0 #fff;
-
-    border:1px solid #bbb;
-    border-radius:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#eee), to(#d1d1d1));
-
-    -webkit-box-shadow:0 0 10px #ccc;
-
-    padding:6px;
-}
-.runner a,
-.suite a {
-    display:inline-block;
-
-    color:#eee;
-    font-size:11px;
-    text-decoration:none;
-    text-shadow:0 -1px 0 #000;
-
-    border:1px solid #111;
-    border-radius:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#555), to(#212121));
-
-    -webkit-background-clip: padding-box;
-
-    padding:1px 4px 2px 4px;
-}
-.runner .finished-at {
-    font-size:10px;
-
-    padding-top:1px;
-    padding-left:6px;
-}
-
-.runner.running {
-    text-shadow:0 1px 0 #EDECCA;
-
-    border-color:#D1CF84;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#EDE613), to(#DBD61F));
-}
-.runner.running a {
-    display:none;
-}
-
-.runner.failed a,
-.suite.failed a {
-    border-color:#660000;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#dd0000), to(#880000));
-}
-
-.runner.passed a,
-.suite.passed a {
-    border-color:#006600;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#00aa00), to(#006600));
-}
-
-/*suite*/
-.suite a.run_spec {
-    display:none;
-}
-.suite > a.description {
-    color:#000;
-    font-size:18px;
-    text-shadow:0 1px 0 #fff;
-
-    border:0;
-    background:transparent;
-}
-.suite .suite > a.description {
-    font-size:14px;
-}
-.suite.failed {
-    border-color:#E0C1C5;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#FFF7F8), to(#F0DADD));
-}
-.suite.failed a.description {
-    color:#440000;
-}
-.suite .suite {
-    margin:5px;
-}
-
-/*spec*/
-.spec {
-    margin: 5px;
-    padding-left: 1em;
-    clear: both;
-
-    border:1px solid #ccc;
-    border-radius:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-
-    background:#fff;
-
-    -webkit-box-shadow:inset 0 0 10px #ddd;
-
-    -webkit-background-clip:padding-box;
-
-    padding:10px;
-}
-.spec a.description {
-    display:block;
-
-    border:0;
-
-    background:transparent;
-
-    padding:0;
-
-    color:#000 !important;
-    font-size:16px;
-    text-shadow:none;
-}
-.spec .messages {
-    border:1px dashed #ccc;
-    border-radius:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-
-    background:#f1f1f1;
-
-    margin:10px 0 0 0;
-    padding:5px;
-
-    font-size:11px;
-    line-height:15px;
-}
-
-.passed,
-.skipped {
-    display:none;
-}
-
-.runner.passed,
-.runner.skipped {
-    display:block;
-}
-
-.suite.passed {
-    border-color:#AEBFA6;
-
-    background:-webkit-gradient(linear, left top, left bottom, from(#ECF2E9), to(#C8DBBF));
-}
-
-.show-passed .passed,
-.show-skipped .skipped {
-    display:block;
-}
-
-.stackTrace {
-  white-space: pre;
-  font-size: .8em;
-  margin-left: 10px;
-  max-height: 5em;
-  overflow: auto;
-  border: 1px inset red;
-  padding: 1em;
-  background: #eef;
-}
-
-
-#jasmine_content {
-  position:fixed;
-  right: 100%;
-}
\ No newline at end of file
diff --git a/js/lib/sencha-jasmine/sencha-jasmine.js b/js/lib/sencha-jasmine/sencha-jasmine.js
deleted file mode 100644
index c670d5c..0000000
--- a/js/lib/sencha-jasmine/sencha-jasmine.js
+++ /dev/null
@@ -1,88 +0,0 @@
-jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
-  var showPassed, showSkipped;
-
-  this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
-      this.createDom('div', { className: 'banner' },
-        this.createDom('div', { className: 'logo' }),
-        this.createDom('div', { className: 'options' },
-            this.createDom('div', { className: 'show' },
-                this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
-                showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' })
-            ),
-            this.createDom('div', { className: 'show' },
-                this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped"),
-                showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' })
-            ),
-            this.createDom('div', { className: 'show' },
-                this.createDom('label', { "for": "__jasmine_TrivialReporter_automaticReload__" }," automatic reload"),
-                automaticReload = this.createDom('input',
-                    (window.location.hash == "#reload") ? {id: "__jasmine_TrivialReporter_automaticReload__", type: 'checkbox', checked: true } : {id: "__jasmine_TrivialReporter_automaticReload__", type: 'checkbox'}
-                )
-            )
-            )
-          ),
-
-      this.runnerDiv = this.createDom('div', { className: 'runner running' },
-          this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
-          this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
-          this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
-      );
-
-  this.document.body.appendChild(this.outerDiv);
-
-  var suites = runner.suites();
-  for (var i = 0; i < suites.length; i++) {
-    var suite = suites[i];
-    var suiteDiv = this.createDom('div', { className: 'suite' },
-        this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
-        this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
-    this.suiteDivs[suite.id] = suiteDiv;
-    var parentDiv = this.outerDiv;
-    if (suite.parentSuite) {
-      parentDiv = this.suiteDivs[suite.parentSuite.id];
-    }
-    parentDiv.appendChild(suiteDiv);
-  }
-
-  this.startedAt = new Date();
-
-  var self = this;
-  showPassed.onchange = function(evt) {
-    if (evt.target.checked) {
-      self.outerDiv.className += ' show-passed';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
-    }
-  };
-
-  showSkipped.onchange = function(evt) {
-    if (evt.target.checked) {
-      self.outerDiv.className += ' show-skipped';
-    } else {
-      self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
-    }
-  };
-
-  automaticReload.onchange = function(evt) {
-      if (evt.target.checked) {
-        window.location.hash = "#reload";
-        window.location.reload();
-      } else {
-        window.location.hash = "";
-        window.location.reload();
-      }
-    };
-};
-
-if (window.location.hash == "#reload") {
-    var interval = setInterval(function() {
-        var isRunning = jasmine.getEnv().currentRunner_.queue.isRunning();
-        if (!isRunning) {
-            clearInterval(interval);
-        
-            setTimeout(function() {
-                window.location.reload();
-            }, 5000);
-        };
-    }, 1500);
-};
\ No newline at end of file
diff --git a/js/test/unit/.htaccess b/js/test/unit/.htaccess
deleted file mode 100644
index 832ea9b..0000000
--- a/js/test/unit/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-ExpiresActive On
-ExpiresDefault "access"
\ No newline at end of file
diff --git a/js/test/unit/SpecOptions.js b/js/test/unit/SpecOptions.js
deleted file mode 100644
index acf0c05..0000000
--- a/js/test/unit/SpecOptions.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * This file is included by your test/unit/index.html file and is used to apply settings before 
- * the tests are run.
- */
-
-Ext.ns('fixtures');
-
-//Stops the Application from being booted up automatically
-Ext.Application.prototype.bindReady = Ext.emptyFn;
diff --git a/js/test/unit/index.html b/js/test/unit/index.html
deleted file mode 100644
index d3ad4cc..0000000
--- a/js/test/unit/index.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-  "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>Sencha - Jasmine Test Runner</title>
-    <link rel="stylesheet" type="text/css" href="../../lib/sencha-jasmine/sencha-jasmine.css" />
-    
-    <script type="text/javascript" src="../../lib/touch/ext-touch-debug.js"></script>
-    
-    <script type="text/javascript" src="../../lib/jasmine/jasmine.js"></script>
-    <script type="text/javascript" src="../../lib/jasmine/jasmine-html.js"></script>
-    <script type="text/javascript" src="../../lib/sencha-jasmine/sencha-jasmine.js"></script>
-    <script type="text/javascript" src="../../lib/sencha-jasmine/matchers/Model.js"></script>
-    <script type="text/javascript" src="../../lib/sencha-jasmine/matchers/Controller.js"></script>
-    
-    <script type="text/javascript" src="SpecOptions.js"></script>
-</head>
-<body>
-    
-    <!-- include source files here... -->
-    <div id="sourceFiles">
-        <script type="text/javascript" src="../../app/app.js"></script>
-        
-        <div id="app-models">
-                  
-        </div>
-        
-        <div id="app-controllers">
-            
-        </div>
-        
-        <div id="app-views">
-            
-        </div>
-        
-        <div id="app-stores">
-            
-        </div>
-    </div>
-    
-    <!-- include fixture files here -->
-    <div id="fixtures">
-        
-    </div>
-    
-    <!-- include spec files here... -->
-    <div id="specFiles">
-        <script type="text/javascript" src="app.js"></script>
-        
-        <div id="spec-models">
-            
-        </div>
-        
-        <div id="spec-controllers">
-            
-        </div>
-        
-        <div id="spec-views">
-            
-        </div>
-    </div>
-    
-    <script type="text/javascript">
-      jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
-      jasmine.getEnv().execute();
-    </script>
-    
-</body>
-</html>
\ No newline at end of file
--
libgit2 0.21.2