This content was loaded via ajax.

Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.

Mauris vitae ante. Curabitur augue. Nulla purus nibh, lobortis ut, feugiat at, aliquam id, purus. Sed venenatis, lorem venenatis volutpat commodo, purus quam lacinia justo, mattis interdum pede pede a odio. Fusce nibh. Morbi nisl mauris, dapibus in, tristique eget, accumsan et, pede. Donec mauris risus, pulvinar ut, faucibus eu, mollis in, nunc. In augue massa, commodo a, cursus vehicula, varius eu, dui. Suspendisse sodales suscipit lorem. Morbi malesuada, eros quis condimentum dignissim, lectus nibh tristique urna, non bibendum diam massa vel risus. Morbi suscipit. Proin egestas, eros at scelerisque scelerisque, dolor lacus fringilla lacus, ut ullamcorper mi magna at quam. Aliquam sed elit. Aliquam turpis purus, congue quis, iaculis id, ullamcorper sit amet, justo. Maecenas sed mauris. Proin magna justo, interdum in, tincidunt eu, viverra eu, turpis. Suspendisse mollis. In magna. Phasellus pellentesque, urna pellentesque convallis pellentesque, augue sem blandit pede, at rhoncus libero nisl a odio.

Sed vitae nibh non magna semper tempor. Duis dolor. Nam congue laoreet arcu. Fusce lobortis enim quis ligula. Maecenas commodo odio id mi. Maecenas scelerisque tellus eu odio. Etiam dolor purus, lacinia a, imperdiet in, aliquam et, eros. In pellentesque. Nullam ac massa. Integer et turpis. Ut quam augue, congue non, imperdiet id, eleifend ac, nisi. Etiam ac arcu. Cras iaculis accumsan erat. Nullam vulputate sapien nec nisi pretium rhoncus. Aliquam a nibh. Vivamus est ante, fermentum a, tincidunt ut, imperdiet nec, velit. Aenean non tortor. Sed nec mauris eget tellus condimentum rutrum.


keep keep keep keep replace replace replace replace replace keep keep

var promise = SpecRunnerUtils.openProjectFiles([]);

waitsForDone(promise, "open project files");

<!doctype html>

	<meta charset="utf-8">
	<title>jQuery UI Spinner - Default functionality</title>
	<link rel="stylesheet" href="../../themes/base/jquery.ui.all.css">

	<link rel="stylesheet" href="../demos.css">

	Currency to donate
	<select id="currency" name="currency">
		<option value="en-US">US $</option>
		<option value="de-DE">EUR €</option>
		<option value="ja-JP">YEN ¥</option>
	</select>

	Amount to donate:
	<input id="spinner" name="spinner" value="5">

Example of a donation form, with currency selection and amout spinner.


/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * 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.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $, window, setTimeout */
/*unittests: QuickOpen*/

/*
 * Displays an auto suggest pop-up list of files to allow the user to quickly navigate to a file and lines
 * within a file.
 * Uses FileIndexManger to supply the file list.
 *
 * TODO (issue 333) - currently jquery smart auto complete is used for the pop-up list. While it mostly works
 * it has several issues, so it should be replace with an alternative. Issues:
 * - the pop-up position logic has flaws that require CSS workarounds
 * - the pop-up properties cannot be modified once the object is constructed
 */

define(function (require, exports, module) {
    "use strict";

    var FileIndexManager    = require("project/FileIndexManager"),
        DocumentManager     = require("document/DocumentManager"),
        EditorManager       = require("editor/EditorManager"),
        CommandManager      = require("command/CommandManager"),
        Strings             = require("strings"),
        StringUtils         = require("utils/StringUtils"),
        Commands            = require("command/Commands"),
        ProjectManager      = require("project/ProjectManager"),
        KeyEvent            = require("utils/KeyEvent"),
        ModalBar            = require("widgets/ModalBar").ModalBar;

    /** @type Array.<QuickOpenPlugin> */
    var plugins = [];

    /** @type {QuickOpenPlugin} */
    var currentPlugin = null;

    /** @type Array.<FileInfo>*/
    var fileList;

    /** @type $.Promise */
    var fileListPromise;

    /**
     * Remembers the current document that was displayed when showDialog() was called
     * The current document is restored if the user presses escape
     * @type {string} full path
     */
    var origDocPath;

    /**
     * Remembers the selection in the document origDocPath that was present when showDialog() was called.
     * Focusing on an item can cause the current and and/or selection to change, so this variable restores it.
     * The cursor position is restored if the user presses escape.
     * @type ?{start:{line:number, ch:number}, end:{line:number, ch:number}}
     */
    var origSelection;

    /** @type {boolean} */
    var dialogOpen = false;

    /**
     * The currently open quick open dialog.
     */
    var _curDialog;

    /** Object representing a search result with associated metadata (added as extra ad hoc fields) */
    function SearchResult(label) {
        this.label = label;
    }

    /**
     * Defines API for new QuickOpen plug-ins
     */
    function QuickOpenPlugin(name, fileTypes, done, search, match, itemFocus, itemSelect, resultsFormatter) {
        this.name = name;
        this.fileTypes = fileTypes;
        this.done = done;
        this.search = search;
        this.match = match;
        this.itemFocus = itemFocus;
        this.itemSelect = itemSelect;
        this.resultsFormatter = resultsFormatter;
    }

    /**
     * Creates and registers a new QuickOpenPlugin
     *
     * @param { name: string,
     *          fileTypes:Array.<string>,
     *          done: function(),
     *          search: function(string):Array.<SearchResult|string>,
     *          match: function(string):boolean,
     *          itemFocus: function(?SearchResult|string),
     *          itemSelect: funciton(?SearchResult|string),
     *          resultsFormatter: ?function(SearchResult|string, string):string
     *        } pluginDef
     *
     * Parameter Documentation:
     *
     * name - plug-in name
     * fileTypes - file types array. Example: ["js", "css", "txt"]. An empty array
     *      indicates all file types.
     * done - called when quick open is complete. Plug-in should clear its internal state.
     * search - takes a query string and returns an array of strings that match the query.
     * match - takes a query string and returns true if this plug-in wants to provide
     *      results for this query.
     * itemFocus - performs an action when a result has been highlighted (via arrow keys, mouseover, etc.).
     *      The highlighted search result item (as returned by search()) is passed as an argument.
     * itemSelect - performs an action when a result is chosen.
     *      The selected search result item (as returned by search()) is passed as an argument.
     * resultFormatter - takes a query string and an item string and returns
     *      a <LI> item to insert into the displayed search results. If null, default is provided.
     *
     * If itemFocus() makes changes to the current document or cursor/scroll position and then the user
     * cancels Quick Open (via Esc), those changes are automatically reverted.
     */
    function addQuickOpenPlugin(pluginDef) {
        plugins.push(new QuickOpenPlugin(
            pluginDef.name,
            pluginDef.fileTypes,
            pluginDef.done,
            pluginDef.search,
            pluginDef.match,
            pluginDef.itemFocus,
            pluginDef.itemSelect,
            pluginDef.resultsFormatter
        ));
    }

    /**
     * QuickNavigateDialog class
     * @constructor
     */
    function QuickNavigateDialog() {
        this.$searchField = undefined; // defined when showDialog() is called

        // Bind event handlers
        this._handleItemSelect         = this._handleItemSelect.bind(this);
        this._handleItemFocus          = this._handleItemFocus.bind(this);
        this._handleKeyUp              = this._handleKeyUp.bind(this);
        this._handleResultsReady       = this._handleResultsReady.bind(this);
        this._handleShowResults        = this._handleShowResults.bind(this);
        this._handleBlur               = this._handleBlur.bind(this);
        this._handleDocumentMouseDown  = this._handleDocumentMouseDown.bind(this);

        // Bind callbacks from smart-autocomplete
        this._filterCallback           = this._filterCallback.bind(this);
        this._resultsFormatterCallback = this._resultsFormatterCallback.bind(this);
    }

    function _filenameFromPath(path, includeExtension) {
        var end;
        if (includeExtension) {
            end = path.length;
        } else {
            end = path.lastIndexOf(".");
            if (end === -1) {
                end = path.length;
            }
        }
        return path.slice(path.lastIndexOf("/") + 1, end);
    }

    /**
     * Attempts to extract a line number from the query where the line number
     * is followed by a colon. Callers should explicitly test result with isNaN()
     *
     * @param {string} query string to extract line number from
     * @returns {number} line number. Returns NaN to indicate no line number was found
     */
    function extractLineNumber(query) {
        // only match : at beginning of query for now
        // TODO: match any location of : when QuickOpen._handleItemFocus() is modified to
        // dynamic open files
        if (query.indexOf(":") !== 0) {
            return NaN;
        }

        var result = NaN;
        var regInfo = query.match(/(!?:)(\d+)/); // colon followed by a digit
        if (regInfo) {
            result = regInfo[2] - 1;
        }

        return result;
    }

    /** Returns the last return value of _filterCallback(), which Smart Autocomplete helpfully caches */
    function getLastFilterResult() {
        var cachedResult = $("input#quickOpenSearch").data("smart-autocomplete").rawResults;
        return cachedResult || [];
    }

    /**
     * Converts from list item DOM node to search provider list object
     * @param {jQueryObject} domItem
     * @return {SearchResult|string} value returned from search()
     */
    function domItemToSearchResult(domItem) {
        if (!domItem) {
            return null;
        }

        // Smart Autocomplete uses this assumption internally: index of DOM node in results list container
        // exactly matches index of search result in list returned by _filterCallback()
        var index = $(domItem).index();

        var lastFilterResult = getLastFilterResult();
        return lastFilterResult[index];
    }

    /**
     * Navigates to the appropriate file and file location given the selected item
     * and closes the dialog.
     *
     * Note, if selectedItem is null quick search should inspect $searchField for text
     * that may have not matched anything in in the list, but may have information
     * for carrying out an action (e.g. go to line).
     */
    QuickNavigateDialog.prototype._handleItemSelect = function (e, selectedDOMItem) {

        // This is a work-around to select first item when a selection event occurs
        // (usually from pressing the enter key) and no item is selected in the list.
        // This is a work-around since  Smart auto complete doesn't select the first item
        if (!selectedDOMItem) {
            selectedDOMItem = $(".smart_autocomplete_container > li:first-child").get(0);
        }

        var selectedItem = domItemToSearchResult(selectedDOMItem);

        // Delegate to current plugin
        if (currentPlugin) {
            currentPlugin.itemSelect(selectedItem);
        } else {

            // extract line number, if any
            var query = this.$searchField.val(),
                gotoLine = extractLineNumber(query);

            // Navigate to file and line number
            var fullPath = selectedItem && selectedItem.fullPath;
            if (fullPath) {
                CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: fullPath})
                    .done(function () {
                        if (!isNaN(gotoLine)) {
                            var editor = EditorManager.getCurrentFullEditor();
                            editor.setCursorPos(gotoLine, 0, true);
                        }
                    });
            } else if (!isNaN(gotoLine)) {
                EditorManager.getCurrentFullEditor().setCursorPos(gotoLine, 0, true);
            }
        }

        this._close();
        EditorManager.focusEditor();
    };

    /**
     * Opens the file specified by selected item if there is no current plug-in, otherwise defers handling
     * to the currentPlugin
     */
    QuickNavigateDialog.prototype._handleItemFocus = function (e, selectedDOMItem) {
        var selectedItem = domItemToSearchResult(selectedDOMItem);

        if (currentPlugin) {
            currentPlugin.itemFocus(selectedItem);
        }
        // TODO: Disable opening files on focus for now since this causes focus related bugs between
        // the editor and the search field.
        // Also, see related code in _handleItemFocus
        /*
        else {
            var fullPath = selectedItem.fullPath;
            if (fullPath) {
                CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath, focusEditor: false});
            }
        }
        */

    };

    /**
     * Called before Smart Autocomplete processes the key, but after the DOM textfield ($searchField) updates its value.
     * After this, Smart Autocomplete doesn't call _handleFilter() & re-render the list until a setTimeout(0) later.
     */
    QuickNavigateDialog.prototype._handleKeyUp = function (e) {
        // Cancel the search on Esc key, and finish the search on Enter key
        if (e.keyCode === KeyEvent.DOM_VK_RETURN || e.keyCode === KeyEvent.DOM_VK_ESCAPE) {
            // Smart Autocomplete also handles Enter; but it does so without a timeout, which causes #1855.
            // Since our listener was added first (see showDialog()), we can steal the Enter event and block
            // Smart Autocomplete from buggily acting on it.
            e.stopImmediatePropagation();
            e.preventDefault();

            // Process on a timeout since letter keys are handled that way and we don't want to get ahead
            // of processing letters that were typed before the Enter key. The ideal order of events is:
            //   letter keydown/keyup, letter key processed async, enter keydown/keyup, enter key processed async
            // However, we might get 'enter keyup' before 'letter key processed async'. The letter key's
            // timeout will always run before ours since it was registered first.
            var self = this;
            setTimeout(function () {
                if (e.keyCode === KeyEvent.DOM_VK_ESCAPE) {
                    // Restore original document & selection / scroll pos
                    if (origDocPath) {
                        CommandManager.execute(Commands.FILE_OPEN, {fullPath: origDocPath})
                            .done(function () {
                                if (origSelection) {
                                    EditorManager.getCurrentFullEditor().setSelection(origSelection.start, origSelection.end, true);
                                }
                            });
                    }

                    self._close();

                } else if (e.keyCode === KeyEvent.DOM_VK_RETURN) {
                    self._handleItemSelect(null, $(".smart_autocomplete_highlight").get(0));  // calls _close() too
                }
            }, 0);

        }
    };

    /**
     * Checks if the given query string is a line number query that is either empty (the number hasn't been typed yet)
     * or is a valid line number within the visible range of the current full editor.
     * @param {string} query The query to check.
     * @return {boolean} true if the given query is a valid line number query.
     */
    QuickNavigateDialog.prototype._isValidLineNumberQuery = function (query) {
        // Empty query returns NaN from extractLineNumber, but we want to treat it as valid for UI purposes.
        if (query === ":") {
            return true;
        }

        var lineNum = extractLineNumber(query),
            editor = EditorManager.getCurrentFullEditor();

        // We could just use 0 and lineCount() here, but in future we might want this logic to work for inline editors as well.
        return (!isNaN(lineNum) && editor && lineNum >= editor.getFirstVisibleLine() && lineNum <= editor.getLastVisibleLine());
    };

    /**
     * Called synchronously after _handleFilter(), but before the cached "last result" is updated and before the DOM
     * list items are re-rendered. Both happen synchronously just after we return. Called even when results is empty.
     */
    QuickNavigateDialog.prototype._handleResultsReady = function (e, results) {
        // Give visual clue when there are no results
        var isNoResults = (results.length === 0 && !this._isValidLineNumberQuery(this.$searchField.val()));
        this.$searchField.toggleClass("no-results", isNoResults);
    };

    /**
     * Called synchronously after all other processing is done (_handleFilter(), updating cached "last result" and
     * re-rendering DOM list items). NOT called if the last filter action had 0 results.
     */
    QuickNavigateDialog.prototype._handleShowResults = function (e, results) {
        // Scroll to top result (unless some other item has been highlighted by user)
        if ($(".smart_autocomplete_highlight").length === 0) {
            this._handleItemFocus(null, $(".smart_autocomplete_container > li:first-child").get(0));
        }
    };

    /**
     * Closes the search dialog and notifies all quick open plugins that
     * searching is done.
     */
    QuickNavigateDialog.prototype._close = function () {
        if (!dialogOpen) {
            return;
        }
        dialogOpen = false;

        var i;
        for (i = 0; i < plugins.length; i++) {
            var plugin = plugins[i];
            plugin.done();
        }

        // Ty TODO: disabled for now while file switching is disabled in _handleItemFocus
        //JSLintUtils.setEnabled(true);

        // Make sure Smart Autocomplete knows its popup is getting closed (in cases where there's no
        // editor to give focus to below, it won't notice otherwise).
        this.$searchField.trigger("lostFocus");

        EditorManager.focusEditor();

        // Closing the dialog is a little tricky (see #1384): some Smart Autocomplete code may run later (e.g.
        // (because it's a later handler of the event that just triggered _close()), and that code expects to
        // find metadata that it stuffed onto the DOM node earlier. But $.remove() strips that metadata.
        // So we wait until after this call chain is complete before actually closing the dialog.
        var self = this;
        setTimeout(function () {
            self.modalBar.close();
        }, 0);

        $(".smart_autocomplete_container").remove();

        $(window.document).off("mousedown", this._handleDocumentMouseDown);
    };

    /**
     * Helper functions for stringMatch score calculation.
     */

    /**
     * The current scoring gives a boost for matches in the "most specific" (generally farthest right)
     * segment of the string being tested against the query.
     */
    function _adjustScoreForSegment(segmentCounter, score) {
        if (segmentCounter === 0) {
            // Multiplier used for matches within the most-specific part of the name (filename, for example)
            return score * 3;
        } else {
            return score;
        }
    }

    /**
     * Additional points are added when multiple characters in the string
     * being tested match against query characters.
     */
    function _boostForMatches(sequentialMatches) {
        // Multiplier for the number of sequential matched characters
        return sequentialMatches * sequentialMatches * 5;
    }

    /**
     * The score is boosted for matches that occur at the beginning
     * of a segment of string that is being tested against the query.
     */
    function _boostForPathSegmentStart(sequentialMatches) {
        // Multiplier for sequential matched characters at the beginning
        // of a delimited section (after a '/' in a path, for example)
        return sequentialMatches * sequentialMatches * 5;
    }

    /**
    * Upper case characters are boosted to help match MixedCase strings better.
    */
    function _boostForUpperCase(c) {
        return c.toUpperCase() === c ? 50 : 0;
    }

   /**
    * Performs matching of a string based on a query, and scores
    * the result based on specificity (assuming that the rightmost
    * side of the input is the most specific) and how clustered the
    * query characters are in the input string. The matching is
    * case-insensitive, but case is taken into account in the scoring.
    *
    * If the query characters cannot be found in order (but not necessarily all together),
    * undefined is returned.
    *
    * The returned SearchResult has a matchGoodness score that can be used
    * for sorting. It also has a stringRanges array, each entry with
    * "text", "matched" and "segment". If you string the "text" properties together, you will
    * get the original str. Using the matched property, you can highlight
    * the string matches. The segment property tells you the most specific (rightmost)
    * segment covered by the range, though there may be more than one segment covered.
    * Segments are currently determined by "/"s.
    *
    * Use basicMatchSort() to sort the filtered results taking this ranking into account.
    * The label of the SearchResult is set to 'str'.
    * @param {!string} str
    * @param {!string} query
    * @return {?SearchResult}
    */
    function stringMatch(str, query) {
        var result;

        // start at the end and work backward, because we give preference
        // to matches in the name (last) segment
        var strCounter = str.length - 1;

        // stringRanges are used to keep track of which parts of
        // the input str matched the query
        var stringRanges = [];

        // segmentCounter tracks which "segment" (delimited section) of the
        // str we are in so that we can treat certain (generally most-specific) segments
        // specially.
        var segmentCounter = 0;

        // Keeps track of the most specific segment that the current stringRange
        // is associated with.
        var rangeSegment = 0;

        // addToStringRanges is used when we transition between matched and unmatched
        // parts of the string.
        function addToStringRanges(numberOfCharacters, matched) {
            var segment = rangeSegment;
            rangeSegment = segmentCounter;
            stringRanges.unshift({
                text: str.substr(strCounter + 1, numberOfCharacters),
                matched: matched,
                segment: segment
            });
        }

        // No query? Short circuit the normal work done and just
        // return a single range that covers the whole string.
        if (!query) {
            result = new SearchResult(str);
            result.matchGoodness = 0;
            strCounter = -1;
            addToStringRanges(str.length, false);
            result.stringRanges = stringRanges;
            return result;
        }

        var queryChars = query.toLowerCase().split("");

        // start at the end of the query
        var queryCounter = queryChars.length - 1;

        var score = 0;

        // sequentialMatches is positive when we are stepping through matched
        // characters and negative when stepping through unmatched characters
        var sequentialMatches = 0;

        while (strCounter >= 0 && queryCounter >= 0) {
            var curChar = str.charAt(strCounter);

            // Ideally, this function will work with different delimiters used in
            // different contexts. For now, this is used for paths delimited by '/'.
            if (curChar === '/') {
                // Beginning of segment, apply boost for a matching
                // string of characters, if there is one
                if (sequentialMatches > 0) {
                    score += _boostForPathSegmentStart(sequentialMatches);
                }

                score = _adjustScoreForSegment(segmentCounter, score);
                segmentCounter++;
            }

            if (queryChars[queryCounter] === curChar.toLowerCase()) {

                score += _boostForUpperCase(curChar);

                // are we ending a string of unmatched characters?
                if (sequentialMatches < 0) {
                    addToStringRanges(-sequentialMatches, false);
                    sequentialMatches = 0;
                }

                // matched character, chalk up another match
                // and move both counters back a character
                sequentialMatches++;
                queryCounter--;
                strCounter--;
            } else {
                // are we ending a string of matched characters?
                if (sequentialMatches > 0) {
                    addToStringRanges(sequentialMatches, true);
                    score += _boostForMatches(sequentialMatches);
                    sequentialMatches = 0;
                }
                // character didn't match, apply sequential matches
                // to score and keep looking
                strCounter--;
                sequentialMatches--;
            }
        }

        // if there are still query characters left, we don't
        // have a match
        if (queryCounter >= 0) {
            return undefined;
        }

        if (sequentialMatches) {
            addToStringRanges(Math.abs(sequentialMatches), sequentialMatches > 0);
        }

        if (strCounter >= 0) {
            stringRanges.unshift({
                text: str.substring(0, strCounter + 1),
                matched: false,
                segment: rangeSegment
            });
        }

        // now, we need to apply any score we've accumulated
        // before we ran out of query characters
        score += _boostForMatches(sequentialMatches);

        if (sequentialMatches && strCounter >= 0) {
            if (str.charAt(strCounter) === '/') {
                score += _boostForPathSegmentStart(sequentialMatches);
            }
        }
        score = _adjustScoreForSegment(segmentCounter, score);

        // Produce a SearchResult that is augmented with matchGoodness
        // (used for sorting) and stringRanges (used for highlighting
        // matched areas of the string)
        result = new SearchResult(str);
        result.matchGoodness = -1 * score;
        result.stringRanges = stringRanges;
        return result;
    }

    /**
     * Sorts an array of SearchResult objects on a primary field, followed by secondary fields
     * in case of ties. 'fields' maps field name to priority, where 0 is the primary field. E.g.:
     *      multiFieldSort(bugList, { milestone: 0, severity: 1 });
     * Would sort a bug list by milestone, and within each milestone sort bugs by severity.
     *
     * Any fields that have a string value are compared case-insensitively. Fields used should be
     * present on all SearchResult objects (no optional/undefined fields).
     *
     * @param {!Array.<SearchResult>} searchResults
     * @param {!Object.<string, number>} fields
     */
    function multiFieldSort(searchResults, fields) {
        // Move field names into an array, with primary field first
        var fieldNames = [];
        $.each(fields, function (key, priority) {
            fieldNames[priority] = key;
        });

        searchResults.sort(function (a, b) {
            var priority;
            for (priority = 0; priority < fieldNames.length; priority++) {
                var fieldName = fieldNames[priority];
                var valueA = a[fieldName];
                var valueB = b[fieldName];
                if (typeof valueA === "string") {
                    valueA = valueA.toLowerCase();
                    valueB = valueB.toLowerCase();
                }

                if (valueA < valueB) {
                    return -1;
                } else if (valueA > valueB) {
                    return 1;
                }
                // otherwise, move on to next sort priority
            }
            return 0; // all sort fields are equal
        });
    }

    /**
     * Sorts search results generated by stringMatch(): results are sorted into several
     * tiers based on how well they matched the search query, then sorted alphabetically
     * within each tier.
     */
    function basicMatchSort(searchResults) {
        multiFieldSort(searchResults, { matchGoodness: 0, label: 1 });
    }

    /**
     * Returns true if the query string doesn't match the query text field. This can happen when _handleFilter()
     * runs slow (either synchronously or async as in searchFileList()). Several key events queue up before filtering
     * is done, and each sets a timeout. After all the key events are handled, we wind up with a queue of timeouts
     * waiting to run, once per key event. All but the last one reflect a stale value of the text field.
     * @param {string} query
     * @return {boolean}
     */
    function queryIsStale(query) {
        var currentQuery = $("input#quickOpenSearch").val();
        return currentQuery !== query;
    }

    function searchFileList(query) {
        // FileIndexManager may still be loading asynchronously - if so, can't return a result yet
        if (!fileList) {
            // Smart Autocomplete allows us to return a Promise instead...
            var asyncResult = new $.Deferred();
            fileListPromise.done(function () {
                // ...but it's not very robust. If a previous Promise is obsoleted by the query string changing, it
                // keeps listening to it anyway. So the last Promise to resolve "wins" the UI update even if it's for
                // a stale query. Guard from that by checking that filter text hasn't changed while we were waiting:
                if (!queryIsStale(query)) {
                    // We're still the current query. Synchronously re-run the search call and resolve with its results
                    asyncResult.resolve(searchFileList(query));
                } else {
                    asyncResult.reject();
                }
            });
            return asyncResult.promise();
        }

        // First pass: filter based on search string; convert to SearchResults containing extra info
        // for sorting & display
        var filteredList = $.map(fileList, function (fileInfo) {
            // Is it a match at all?
            // match query against the full path (with gaps between query characters allowed)
            var searchResult = stringMatch(ProjectManager.makeProjectRelativeIfPossible(fileInfo.fullPath), query);
            if (searchResult) {
                searchResult.label = fileInfo.name;
                searchResult.fullPath = fileInfo.fullPath;
                searchResult.filenameWithoutExtension = _filenameFromPath(fileInfo.name, false);
            }
            return searchResult;
        });

        // Sort by "match goodness" tier first, then within each tier sort alphabetically - first by filename
        // sans extension, (so that "abc.js" comes before "abc-d.js"), then by filename, and finally (for
        // identically-named files) by full path
        multiFieldSort(filteredList, { matchGoodness: 0, filenameWithoutExtension: 1, label: 2, fullPath: 3 });

        return filteredList;
    }

    /**
     * Handles changes to the current query in the search field.
     * @param {string} query The new query.
     * @return {Array} The filtered list of results.
     */
    QuickNavigateDialog.prototype._filterCallback = function (query) {
        // If previous filter calls ran slow, we may have accumulated several query change events in the meantime.
        // Only respond to the one that's current. Note that this only works because we're called on a timeout after
        // the key event; checking DURING the key event itself would never yield a future value for the input field.
        if (queryIsStale(query)) {
            return getLastFilterResult();
        }

        // Reflect current search mode in UI
        this._updateDialogLabel(query);

        // "Go to line" mode is special-cased
        var gotoLine = extractLineNumber(query);
        if (!isNaN(gotoLine)) {
            var from = {line: gotoLine, ch: 0};
            var to = {line: gotoLine, ch: 99999};

            EditorManager.getCurrentFullEditor().setSelection(from, to, true);
        }

        // Try to invoke a search plugin
        var curDoc = DocumentManager.getCurrentDocument();
        if (curDoc) {
            var filename = _filenameFromPath(curDoc.file.fullPath, true);
            var extension = filename.slice(filename.lastIndexOf(".") + 1, filename.length);

            var i;
            for (i = 0; i < plugins.length; i++) {
                var plugin = plugins[i];
                var extensionMatch = plugin.fileTypes.indexOf(extension) !== -1 || plugin.fileTypes.length === 0;
                if (extensionMatch &&  plugin.match && plugin.match(query)) {
                    currentPlugin = plugin;
                    return plugin.search(query);
                }
            }
        }

        // No matching plugin: use default file search mode
        currentPlugin = null;
        return searchFileList(query);
    };

    /**
     * Formats item's label as properly escaped HTML text, highlighting sections that match 'query'.
     * If item is a SearchResult generated by stringMatch(), uses its metadata about which string ranges
     * matched; else formats the label with no highlighting.
     * @param {!string|SearchResult} item
     * @param {?string} matchClass CSS class for highlighting matched text
     * @param {?function(number, string):string} rangeFilter
     * @return {!string} bolded, HTML-escaped result
     */
    function highlightMatch(item, matchClass, rangeFilter) {
        var label = item.label || item;
        matchClass = matchClass || "quicksearch-namematch";

        var stringRanges = item.stringRanges;
        if (!stringRanges) {
            // If result didn't come from stringMatch(), highlight nothing
            stringRanges = [{
                text: label,
                matched: false,
                segment: 0
            }];
        }

        var displayName = "";

        // Put the path pieces together, highlighting the matched parts
        stringRanges.forEach(function (range) {
            if (range.matched) {
                displayName += "<span class='" + matchClass + "'>";
            }

            var rangeText = rangeFilter ? rangeFilter(range.segment, range.text) : range.text;
            displayName += StringUtils.breakableUrl(StringUtils.htmlEscape(rangeText));

            if (range.matched) {
                displayName += "</span>";
            }
        });
        return displayName;
    }

    function defaultResultsFormatter(item, query) {
        query = query.slice(query.indexOf("@") + 1, query.length);

        var displayName = highlightMatch(item);
        return "<li>" + displayName + "</li>";
    }

    function _filenameResultsFormatter(item, query) {
        // For main label, we just want filename: drop most of the string
        function fileNameFilter(segment, rangeText) {
            if (segment === 0) {
                var rightmostSlash = rangeText.lastIndexOf('/');
                return rangeText.substring(rightmostSlash + 1);  // safe even if rightmostSlash is -1
            } else {
                return "";
            }
        }
        var displayName = highlightMatch(item, null, fileNameFilter);
        var displayPath = highlightMatch(item, "quicksearch-pathmatch");

        return "<li>" + displayName + "<br /><span class='quick-open-path'>" + displayPath + "</span></li>";
    }

    /**
     * Formats the entry for the given item to be displayed in the dropdown.
     * @param {Object} item The item to be displayed.
     * @return {string} The HTML to be displayed.
     */
    QuickNavigateDialog.prototype._resultsFormatterCallback = function (item) {
        var query = this.$searchField.val();

        var formatter;

        if (currentPlugin) {
            // Plugins use their own formatter or the default formatter
            formatter = currentPlugin.resultsFormatter || defaultResultsFormatter;
        } else {
            // No plugin: default file search mode uses a special formatter
            formatter = _filenameResultsFormatter;
        }
        return formatter(item, query);
    };

    /**
     * Sets the value in the search field, updating the current mode and label based on the
     * given prefix.
     * @param {string} prefix The prefix that determines which mode we're in: must be empty (for file search),
     *      "@" for go to definition, or ":" for go to line.
     * @param {string} initialString The query string to search for (without the prefix).
     */
    QuickNavigateDialog.prototype.setSearchFieldValue = function (prefix, initialString) {
        prefix = prefix || "";
        initialString = initialString || "";
        initialString = prefix + initialString;

        var $field = this.$searchField;
        $field.val(initialString);
        $field.get(0).setSelectionRange(prefix.length, initialString.length);

        // Kick smart-autocomplete to update (it only listens for keyboard events)
        // (due to #1855, this will only pop up results list; it won't auto-"focus" the first result)
        $field.trigger("keyIn", [initialString]);

        this._updateDialogLabel(initialString);
    };

    /**
     * Sets the dialog label based on the type of the given query.
     * @param {string} query The user's current query.
     */
    QuickNavigateDialog.prototype._updateDialogLabel = function (query) {
        var prefix = (query.length > 0 ? query.charAt(0) : "");

        // Update the dialog label based on the current prefix.
        var dialogLabel = "";
        switch (prefix) {
        case ":":
            dialogLabel = Strings.CMD_GOTO_LINE;
            break;
        case "@":
            dialogLabel = Strings.CMD_GOTO_DEFINITION;
            break;
        default:
            dialogLabel = Strings.CMD_QUICK_OPEN;
            break;
        }
        $(".find-dialog-label", this.dialog).text(dialogLabel);
    };

    /**
     * Close the dialog when the user clicks outside of it. Smart-autocomplete listens for this and automatically closes its popup,
     * but we want to close the whole search "dialog." (And we can't just piggyback on the popup closing event, since there are cases
     * where the popup closes that we want the dialog to remain open (e.g. deleting search term via backspace).
     */
    QuickNavigateDialog.prototype._handleDocumentMouseDown = function (e) {
        if (this.modalBar.getRoot().find(e.target).length === 0 && $(".smart_autocomplete_container").find(e.target).length === 0) {
            this._close();
        } else {
            // Allow clicks in the search field to propagate. Clicks in the menu should be
            // blocked to prevent focus from leaving the search field.
            if ($("input#quickOpenSearch").get(0) !== e.target) {
                e.preventDefault();
                e.stopPropagation();
            }
        }
    };

    /**
     * Close the dialog when it loses focus.
     */
    QuickNavigateDialog.prototype._handleBlur = function (e) {
        this._close();
    };

    /**
     * Shows the search dialog and initializes the auto suggestion list with filenames from the current project
     */
    QuickNavigateDialog.prototype.showDialog = function (prefix, initialString) {
        if (dialogOpen) {
            return;
        }
        dialogOpen = true;

        // Global listener to hide search bar & popup
        $(window.document).on("mousedown", this._handleDocumentMouseDown);

        // Ty TODO: disabled for now while file switching is disabled in _handleItemFocus
        // To improve performance during list selection disable JSLint until a document is chosen or dialog is closed
        //JSLintUtils.setEnabled(false);

        // Record current document & cursor pos so we can restore it if search is canceled
        var curDoc = DocumentManager.getCurrentDocument();
        origDocPath = curDoc ? curDoc.file.fullPath : null;
        if (curDoc) {
            origSelection = EditorManager.getCurrentFullEditor().getSelection();
        } else {
            origSelection = null;
        }

        // Show the search bar ("dialog")
        var dialogHTML = "<div align='right'><span class='find-dialog-label'></span>: <input type='text' autocomplete='off' id='quickOpenSearch' style='width: 30em'></div>";
        this.modalBar = new ModalBar(dialogHTML, false);
        this.$searchField = $("input#quickOpenSearch");

        // The various listeners registered below fire in this order:
        //   keydown, (async gap), keyup, (async gap), filter, resultsReady, showResults/noResults
        // The later events *always* come after the keydown & keyup (they're triggered on a timeout from keyup). But
        // because of the async gaps, a keydown for the *next* key typed might come *before* they run:
        //   keydown, (async gap), keyup, (async gap), keydown #2, (async gap), filter, resultsReady, showResults/noResults
        // The staleness check in _filterCallback() and the forced async wait in _handleKeyUp() are due to this.

        this.$searchField.bind({
            resultsReady: this._handleResultsReady,
            showResults: this._handleShowResults,
            itemSelect: this._handleItemSelect,
            itemFocus: this._handleItemFocus,
            keyup: this._handleKeyUp,   // it's important we register this BEFORE calling smartAutoComplete(); see handler for details
            blur: this._handleBlur   // can't use lostFocus since smart autocomplete fires it immediately in response to the shortcut's keyup
        });

        this.$searchField.smartAutoComplete({
            source: [],
            maxResults: 20,
            minCharLimit: 0,
            autocompleteFocused: true,
            forceSelect: false,
            typeAhead: false,   // won't work right now because smart auto complete
                                // using internal raw results instead of filtered results for matching
            filter: this._filterCallback,
            resultFormatter: this._resultsFormatterCallback
        });

        this.setSearchFieldValue(prefix, initialString);

        // Start fetching the file list, which will be needed the first time the user enters an un-prefixed query. If FileIndexManager's
        // caches are out of date, this list might take some time to asynchronously build. See searchFileList() for how this is handled.
        fileList = null;
        fileListPromise = FileIndexManager.getFileInfoList("all")
            .done(function (files) {
                fileList = files;
                fileListPromise = null;
            });
    };

    function getCurrentEditorSelectedText() {
        var currentEditor = EditorManager.getActiveEditor();
        return (currentEditor && currentEditor.getSelectedText()) || "";
    }

    /**
     * Opens the Quick Open bar prepopulated with the given prefix (to select a mode) and optionally
     * with the given query text too. Updates text field contents if Quick Open already open.
     * @param {?string} prefix
     * @param {?string} initialString
     */
    function beginSearch(prefix, initialString) {
        if (dialogOpen) {
            _curDialog.setSearchFieldValue(prefix, initialString);
        } else {
            _curDialog = new QuickNavigateDialog();
            _curDialog.showDialog(prefix, initialString);
        }
    }

    function doFileSearch() {
        beginSearch("", getCurrentEditorSelectedText());
    }

    function doGotoLine() {
        // TODO: Brackets doesn't support disabled menu items right now, when it does goto line and
        // goto definition should be disabled when there is not a current document
        if (DocumentManager.getCurrentDocument()) {
            beginSearch(":", "");
        }
    }

    // TODO: should provide a way for QuickOpenJSSymbol to create this function as a plug-in
    function doDefinitionSearch() {
        if (DocumentManager.getCurrentDocument()) {
            beginSearch("@", getCurrentEditorSelectedText());
        }
    }

    // TODO: allow QuickOpenJS to register it's own commands and key bindings
    CommandManager.register(Strings.CMD_QUICK_OPEN,         Commands.NAVIGATE_QUICK_OPEN,       doFileSearch);
    CommandManager.register(Strings.CMD_GOTO_DEFINITION,    Commands.NAVIGATE_GOTO_DEFINITION,  doDefinitionSearch);
    CommandManager.register(Strings.CMD_GOTO_LINE,          Commands.NAVIGATE_GOTO_LINE,        doGotoLine);

    exports.beginSearch         = beginSearch;
    exports.addQuickOpenPlugin  = addQuickOpenPlugin;
    exports.SearchResult        = SearchResult;
    exports.stringMatch         = stringMatch;
    exports.basicMatchSort      = basicMatchSort;
    exports.multiFieldSort      = multiFieldSort;
    exports.highlightMatch      = highlightMatch;
});


keep keep replace replace keep keep keep

/*
 * Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
 *
 * 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.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, describe, it, expect, beforeEach, afterEach, waitsFor, runs, window, $, jasmine, setTimeout */
/*unittests: QuickOpen*/

define(function (require, exports, module) {
    'use strict';

    var Commands              = require("command/Commands"),
        KeyEvent              = require("utils/KeyEvent"),
        SpecRunnerUtils       = require("spec/SpecRunnerUtils");

    describe("QuickOpen", function () {
        var testPath = SpecRunnerUtils.getTestPath("/spec/QuickOpen-test-files");
        var brackets, test$, executeCommand, EditorManager, DocumentManager;

        beforeEach(function () {

            runs(function () {
                SpecRunnerUtils.createTestWindowAndRun(this, function (testWindow) {
                    brackets = testWindow.brackets;
                    test$ = testWindow.$;
                    executeCommand = testWindow.executeCommand;
                    EditorManager = brackets.test.EditorManager;
                    DocumentManager = brackets.test.DocumentManager;
                });
            });

        });

        afterEach(function () {
            SpecRunnerUtils.closeTestWindow();
        });

        function getSearchBar() {
            return test$(".modal-bar");
        }
        function getSearchField() {
            return test$(".modal-bar input[type='text']");
        }

        function expectSearchBarOpen() {
            expect(getSearchBar()[0]).toBeDefined();
        }
        function expectSearchBarClosed() {
            expect(getSearchBar()[0]).not.toBeDefined();
        }

        function enterSearchText(str, timeoutLength) {
            timeoutLength = timeoutLength || 10;

            expectSearchBarOpen();
            var input = getSearchField()[0];

            // We need to simulate typing into the field in order to get the QuickOpen matching code to
            // run.
            var i;
            for (i = 0; i < str.length; i++) {
                SpecRunnerUtils.simulateKeyEvent(KeyEvent["DOM_VK_" + str[i]], "keydown", input);
            }

            // We still set the input value as well because that is read by other code.
            // setTimeout is used to turn the event loop so that the search text is not placed in
            // the text field until after the keydown code has received the events.
            //
            // timeoutLength is configurable because some uses may take longer than others
            setTimeout(function () {
                getSearchField().val(str);
            }, timeoutLength);
        }

        function pressEnter() {
            expectSearchBarOpen();

            // Using keyup here because of inside knowledge of how the events are processed
            // on the QuickOpen input.
            SpecRunnerUtils.simulateKeyEvent(KeyEvent.DOM_VK_RETURN, "keyup", getSearchField()[0]);
        }

        it("can open a file and jump to a line, centering that line on the screen", function () {
            var hostOpened = false;
            var err = false;
            var workingSet = [];

            SpecRunnerUtils.loadProjectInTestWindow(testPath);

            runs(function () {
                SpecRunnerUtils.openProjectFiles(workingSet).done(function (documents) {
                    hostOpened = true;
                }).fail(function () {
                    err = true;
                });
            });

            waitsFor(function () { return hostOpened && !err; }, "window opening timeout", 1000);

            runs(function () {
                executeCommand(Commands.NAVIGATE_QUICK_OPEN);

                // need to set the timeout length here to ensure that it has a chance to load the file
                // list.
                enterSearchText("lines", 100);
            });

            waitsFor(function () {
                return getSearchField().val() === "lines";
            }, "filename entry timeout", 1000);

            runs(function () {
                pressEnter();
            });

            waitsFor(function () {
                return EditorManager.getCurrentFullEditor() !== null;
            }, "file opening timeout", 3000);

            runs(function () {
                // Make sure we've opened the right file. It should open the longer one, because
                // of the scoring in the StringMatch algorithm.
                expect(DocumentManager.getCurrentDocument().file.name).toEqual("lotsOfLines.html");
                executeCommand(Commands.NAVIGATE_GOTO_LINE);
                enterSearchText(":50");
            });

            waitsFor(function () {
                return getSearchField().val() === ":50";
            }, "goto line entry timeout", 1000);

            var eventLooped = false;
            runs(function () {
                pressEnter();
                setTimeout(function () {
                    eventLooped = true;
                }, 10);
            });

            waitsFor(function () { return eventLooped; });

            runs(function () {
                var editor = EditorManager.getCurrentFullEditor();
                var scrollPos = editor.getScrollPos();

                // The user enters a 1-based number, but the reported position
                // is 0 based, so we check for 49.
                expect(editor).toHaveCursorPosition(49, 0);

                // We expect the result to be scrolled roughly to the middle of the window.
                expect(scrollPos.y).toBeGreaterThan(400);
                expect(scrollPos.y).toBeLessThan(500);

                eventLooped = false;
                setTimeout(function () {
                    eventLooped = true;
                }, 10);
            });

            waitsFor(function () { return eventLooped; });
        });

    });
});


<!doctype html>

	<meta charset="utf-8">
	<title>Compound Visual Test : All Widgets in Dialog</title>
	<link rel="stylesheet" href="../visual.css">
	<link rel="stylesheet" href="../../../themes/base/jquery.ui.all.css">

Accordion Header 1

			Accordion Content 1

Accordion Header 2

			Accordion Content 2

Accordion Header 3

			Accordion Content 3

	<input id="autocomplete">
	<button>A Button</button>
	<input id="datepicker">
	<button>Another button</button>

		Progress: <input title="The progress we made so far" id="progress">

First

Second

Third

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Phasellus mattis tincidunt nibh.

Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.

	Yay, another dialog.


<!doctype html>

	<meta charset="utf-8">
	<title>jQuery UI Effects Test Suite</title>
	<link rel="stylesheet" href="effects.css">

Blind up

Blind down

Blind left

Blind right

Bounce 3 times

Clip horizontally

Clip vertically

Drop down

Drop up

Drop left

Drop right

Explode in 9 pieces

Explode in 36 pieces

Fade

Fold

Highlight

Pulsate 2 times

Puff

Scale

Shake

Size Default Show/Hide

Size Toggle

Slide down

Slide up

Slide left

Slide right

Transfer to first element

addClass

removeClass

toggleClass

hide/show (jQuery)


function simpleFunction() {
    alert("foo");
}//END simpleFunction

function nestedBraces() {
    var x;
    if (x) {
        alert("foo");
    }
}//END nestedBraces

function nestedFunction() {
    var x;
    var myFunc = function () {
        alert("foo");
    };
}//END nestedFunction

function endBraceInString() {
    alert("this is a brace: }");
}//END endBraceInString

function endBraceInSingleQuoteString() {
    alert('this is a brace: }');
}//END endBraceInSingleQuoteString

function endBraceInLineComment() {
    // this is a brace: }
}//END endBraceInLineComment

function endBraceInBlockComment() {
    /* this is a brace: } */
}//END endBraceInBlockComment

function endBraceInMultilineBlockComment() {
    /*
        this is a brace: }
    */
}//END endBraceInMultilineBlockComment

function endBraceInRegexp() {
    /this is a brace \}/.exec("foo");
}//END endBraceInRegexp

function singleLine() { alert("foo"); }//END singleLine

function singleLineWithFakeBrace() { alert("this is a brace: }"); }//END singleLineWithFakeBrace

function itsComplicated() {
    var x;

    if (x) {
        /*
            here's a brace: {
            { and more braces }
        */
        {
            /some \} brace/;
        }
        // if (foo) { bar; }
        // if (foo) {
        //     bar;
        // }
    }

    alert("brace }");
    alert('{braces}');
}//END itsComplicated


keep keep keep keep replace keep keep keep keep


<!DOCTYPE html>

	<meta charset="utf-8">
	<title>jQuery UI Demos</title>
	<link rel="stylesheet" href="../themes/base/jquery.ui.all.css">
	<link rel="stylesheet" href="demos.css">

Interactions

Draggable

Droppable

Resizable

Selectable

Sortable

Widgets

Accordion

Autocomplete

Button

Datepicker

Dialog

Menu

Progressbar

Slider

Spinner

Tabs

Tooltip

Effects

Color Animation

Toggle Class

Add Class

Remove Class

Switch Class

Effect

Toggle

Hide

Show

Utilities

Position

Widget

About jQuery UI

Getting Started

Upgrade Guide

Changelog

Roadmap

Subversion Access

UI Developer Guidelines

Theming

Theming jQuery UI

jQuery UI CSS Framework

ThemeRoller application

Theme Switcher Widget

Instructions

						These demos showcase some common uses of each jQuery UI plugin. Simply copy and paste code from the demos to get started. Have fun playing with them.


/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * 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.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, describe, it, xit, expect, beforeEach, afterEach, waitsFor, runs, $, brackets, waitsForDone */

define(function (require, exports, module) {
    "use strict";

    var CommandManager,         // loaded from brackets.test
        EditorManager,          // loaded from brackets.test
        FileIndexManager,       // loaded from brackets.test
        PerfUtils,              // loaded from brackets.test
        JSUtils,                // loaded from brackets.test

        FileUtils           = brackets.getModule("file/FileUtils"),
        NativeFileSystem    = brackets.getModule("file/NativeFileSystem").NativeFileSystem,
        SpecRunnerUtils     = brackets.getModule("spec/SpecRunnerUtils"),
        UnitTestReporter    = brackets.getModule("test/UnitTestReporter");

    var extensionPath = FileUtils.getNativeModuleDirectoryPath(module),
        testPath = extensionPath + "/unittest-files/syntax",
        tempPath = SpecRunnerUtils.getTempDirectory(),
        testWindow,
        initInlineTest;

    function rewriteProject(spec) {
        var result = new $.Deferred(),
            infos = {},
            options = {
                parseOffsets    : true,
                infos           : infos,
                removePrefix    : true
            };

        SpecRunnerUtils.copyPath(testPath, tempPath, options).done(function () {
            spec.infos = infos;
            result.resolve();
        }).fail(function () {
            result.reject();
        });

        return result.promise();
    }

    /**
     * Performs setup for an inline editor test. Parses offsets (saved to Spec.offsets) for all files in
     * the test project (testPath) and saves files back to disk without offset markup.
     * When finished, open an editor for the specified project relative file path
     * then attempts opens an inline editor at the given offset. Installs an after()
     * function restore all file content back to original state with offset markup.
     *
     * @param {!string} openFile Project relative file path to open in a main editor.
     * @param {!number} openOffset The offset index location within openFile to open an inline editor.
     * @param {?boolean} expectInline Use false to verify that an inline editor should not be opened. Omit otherwise.
     */
    var _initInlineTest = function (openFile, openOffset, expectInline, workingSet) {
        var allFiles,
            inlineOpened = null,
            spec = this;

        workingSet = workingSet || [];
        expectInline = (expectInline !== undefined) ? expectInline : true;

        runs(function () {
            waitsForDone(rewriteProject(spec), "rewriteProject");
        });

        SpecRunnerUtils.loadProjectInTestWindow(tempPath);

        runs(function () {
            workingSet.push(openFile);
            waitsForDone(SpecRunnerUtils.openProjectFiles(workingSet), "openProjectFiles");
        });

        if (openOffset !== undefined) {
            runs(function () {
                // open inline editor at specified offset index
                waitsForDone(SpecRunnerUtils.toggleQuickEditAtOffset(
                    EditorManager.getCurrentFullEditor(),
                    spec.infos[openFile].offsets[openOffset]
                ), "toggleQuickEditAtOffset");
            });
        }
    };

    describe("JSQuickEdit", function () {

        /*
         *
         */
        describe("javaScriptFunctionProvider", function () {

            beforeEach(function () {
                initInlineTest = _initInlineTest.bind(this);
                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {
                    testWindow          = w;
                    EditorManager       = testWindow.brackets.test.EditorManager;
                    CommandManager      = testWindow.brackets.test.CommandManager;
                    FileIndexManager    = testWindow.brackets.test.FileIndexManager;
                    JSUtils             = testWindow.brackets.test.JSUtils;
                });

                this.addMatchers({

                    toHaveInlineEditorRange: function (range) {
                        var i = 0,
                            editor = this.actual,
                            hidden,
                            lineCount = editor.lineCount(),
                            shouldHide = [],
                            shouldShow = [],
                            startLine = range.startLine,
                            endLine = range.endLine,
                            visibleRangeCheck;

                        for (i = 0; i < lineCount; i++) {
                            hidden = editor._codeMirror.getLineHandle(i).hidden || false;

                            if (i < startLine) {
                                if (!hidden) {
                                    shouldHide.push(i); // lines above start line should be hidden
                                }
                            } else if ((i >= startLine) && (i <= endLine)) {
                                if (hidden) {
                                    shouldShow.push(i); // lines in the range should be visible
                                }
                            } else if (i > endLine) {
                                if (!hidden) {
                                    shouldHide.push(i); // lines below end line should be hidden
                                }
                            }
                        }

                        visibleRangeCheck = (editor._visibleRange.startLine === startLine)
                            && (editor._visibleRange.endLine === endLine);

                        this.message = function () {
                            var msg = "";

                            if (shouldHide.length > 0) {
                                msg += "Expected inline editor to hide [" + shouldHide.toString() + "].\n";
                            }

                            if (shouldShow.length > 0) {
                                msg += "Expected inline editor to show [" + shouldShow.toString() + "].\n";
                            }

                            if (!visibleRangeCheck) {
                                msg += "Editor._visibleRange ["
                                    + editor._visibleRange.startLine + ","
                                    + editor._visibleRange.endLine + "] should be ["
                                    + startLine + "," + endLine + "].";
                            }

                            return msg;
                        };

                        return (shouldHide.length === 0)
                            && (shouldShow.length === 0)
                            && visibleRangeCheck;
                    }
                });
            });

            afterEach(function () {
                //debug visual confirmation of inline editor
                //waits(1000);

                // revert files to original content with offset markup
                SpecRunnerUtils.closeTestWindow();
            });

            it("should ignore tokens that are not function calls or references", function () {
                var editor,
                    extensionRequire,
                    jsQuickEditMain,
                    tokensFile = "tokens.js",
                    promise,
                    offsets;

                initInlineTest(tokensFile);

                runs(function () {
                    extensionRequire = testWindow.brackets.getModule("utils/ExtensionLoader").getRequireContextForExtension("JavaScriptQuickEdit");
                    jsQuickEditMain = extensionRequire("main");
                    editor = EditorManager.getCurrentFullEditor();
                    offsets = this.infos[tokensFile];

                    // regexp token
                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[0]);
                    expect(promise).toBeNull();

                    // multi-line comment
                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[1]);
                    expect(promise).toBeNull();

                    // single-line comment
                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[2]);
                    expect(promise).toBeNull();

                    // string, double quotes
                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[3]);
                    expect(promise).toBeNull();

                    // string, single quotes
                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[4]);
                    expect(promise).toBeNull();
                });
            });

            it("should open a function with  form: function functionName()", function () {
                initInlineTest("test1main.js", 0);

                runs(function () {
                    var inlineWidget = EditorManager.getCurrentFullEditor().getInlineWidgets()[0];
                    var inlinePos = inlineWidget.editors[0].getCursorPos();

                    // verify cursor position in inline editor
                    expect(inlinePos).toEqual(this.infos["test1inline.js"].offsets[0]);
                });
            });

            it("should open a function with  form: functionName = function()", function () {
                initInlineTest("test1main.js", 1);

                runs(function () {
                    var inlineWidget = EditorManager.getCurrentFullEditor().getInlineWidgets()[0];
                    var inlinePos = inlineWidget.editors[0].getCursorPos();

                    // verify cursor position in inline editor
                    expect(inlinePos).toEqual(this.infos["test1inline.js"].offsets[1]);
                });
            });

            it("should open a function with  form: functionName: function()", function () {
                initInlineTest("test1main.js", 2);

                runs(function () {
                    var inlineWidget = EditorManager.getCurrentFullEditor().getInlineWidgets()[0];
                    var inlinePos = inlineWidget.editors[0].getCursorPos();

                    // verify cursor position in inline editor
                    expect(inlinePos).toEqual(this.infos["test1inline.js"].offsets[2]);
                });
            });
        });

        describe("Performance suite", function () {

            this.category = "performance";

            var testPath = extensionPath + "/unittest-files/jquery-ui";

            beforeEach(function () {
                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {
                    testWindow = w;
                    CommandManager      = testWindow.brackets.test.CommandManager;
                    EditorManager       = testWindow.brackets.test.EditorManager;
                    PerfUtils           = testWindow.brackets.test.PerfUtils;
                });
            });

            afterEach(function () {
                SpecRunnerUtils.closeTestWindow();
            });

            it("should open inline editors", function () {
                SpecRunnerUtils.loadProjectInTestWindow(testPath);

                var extensionRequire,
                    JavaScriptQuickEdit,
                    i,
                    perfMeasurements;

                runs(function () {
                    perfMeasurements = [
                        {
                            measure: PerfUtils.JAVASCRIPT_INLINE_CREATE,
                            children: [
                                {
                                    measure: PerfUtils.FILE_INDEX_MANAGER_SYNC
                                },
                                {
                                    measure: PerfUtils.JAVASCRIPT_FIND_FUNCTION,
                                    children: [
                                        {
                                            measure: PerfUtils.JSUTILS_GET_ALL_FUNCTIONS,
                                            children: [
                                                {
                                                    measure: PerfUtils.DOCUMENT_MANAGER_GET_DOCUMENT_FOR_PATH,
                                                    name: "Document creation during this search",
                                                    operation: "sum"
                                                },
                                                {
                                                    measure: PerfUtils.JSUTILS_REGEXP,
                                                    operation: "sum"
                                                }
                                            ]
                                        },
                                        {
                                            measure: PerfUtils.JSUTILS_END_OFFSET,
                                            operation: "sum"
                                        }
                                    ]
                                }
                            ]
                        }
                    ];
                });

                runs(function () {
                    extensionRequire = testWindow.brackets.getModule("utils/ExtensionLoader").getRequireContextForExtension("JavaScriptQuickEdit");
                    JavaScriptQuickEdit = extensionRequire("main");

                    waitsForDone(SpecRunnerUtils.openProjectFiles(["ui/jquery.effects.core.js"]), "openProjectFiles");
                });

                var runCreateInlineEditor = function () {
                    waitsForDone(
                        JavaScriptQuickEdit._createInlineEditor(EditorManager.getCurrentFullEditor(), "extend"),
                        "createInlineEditor"
                    );
                };

                function logPerf() {
                    var reporter = UnitTestReporter.getActiveReporter();
                    reporter.logTestWindow(perfMeasurements);
                    reporter.clearTestWindow();
                }

                // repeat 5 times
                for (i = 0; i < 5; i++) {
                    runs(runCreateInlineEditor);
                    runs(logPerf);
                }
            });

        });
    });
});


// Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
//
// 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.

/* Brackets / CodeMirror Code Formatting */

/*
 * TODO This can be removed next time we update CodeMirror2.
 * Marijn made this change to codemirror.css, but I need it now
 * in order to make font resizing work.
 */
.CodeMirror pre {
    line-height: inherit;
    padding: 0 @code-padding;
}

.CodeMirror-scroll {
    background-color: @background-color-3;
}

.platform-mac .CodeMirror {
    .code-font-mac();
}

.platform-win .CodeMirror {
    .code-font-win();
}

@code-padding: 1.2em;

.cm-s-default {
    .CodeMirror-cursor {
        .code-cursor();
    }

    span.cm-keyword {color: @accent-keyword;}
    span.cm-atom {color: @accent-atom;}
    span.cm-number {color: @accent-number;}
    span.cm-def {color: @accent-def;}
    span.cm-variable {color: @accent-variable;}
    span.cm-variable-2 {color: @accent-variable-2;}
    span.cm-variable-3 {color: @accent-variable-3;}
    span.cm-property {color: @accent-property;}
    span.cm-operator {color: @accent-operator;}
    span.cm-comment {color: @accent-comment;}
    span.cm-string {color: @accent-string;}
    span.cm-string-2 {color: @accent-string-2;}
    span.cm-meta {color: @accent-meta;}
    span.cm-error {color: @accent-error;}
    span.cm-qualifier {color: @accent-qualifier;}
    span.cm-builtin {color: @accent-builtin;}
    span.cm-bracket {color: @accent-bracket;}
    span.cm-tag {color: @accent-tag;}
    span.cm-attribute {color: @accent-attribute;}
    span.cm-header {color: @accent-header;}
    span.cm-quote {color: @accent-quote;}
    span.cm-hr {color: @accent-hr;}
    span.cm-link {color: @accent-link;}
    span.cm-rangeinfo {color: @accent-rangeinfo;}
    span.cm-minus {color: @accent-minus;}
    span.cm-plus {color: @accent-plus;}

    span.CodeMirror-matchingbracket {color: @accent-bracket !important; background-color: @background-color-2;}
    span.CodeMirror-nonmatchingbracket {color: @accent-bracket !important;}

    .CodeMirror-lines {
        padding: @code-padding 0;
    }
    .CodeMirror-gutters {
        background-color: @background-color-3;
        border-right: none;
        padding-top: @code-padding;
        padding-bottom: @code-padding;
        min-width: 2.5em;
    }
    .CodeMirror-linenumber {
        color: @accent-comment;
        min-width: 2.5em;
        /*font-size: 0.9em;*/  /* restore after SourceCodePro font fix? */
        padding-top: 0px;
        padding-bottom: 0px;
    }
}

/*
    CodeMirror's use of descendant selectors for certain styling causes problems when editors are
    nested because, for items in the inner editor, the left-hand clause in the selector will now
    match either the actual containing CodeMirror instance *OR* the outer "host" CodeMirror instance.

    TODO (issue #324): We'll still have problems if editors can be nested more than one level deep,
    or if any other descendant-selector-driven CM styles can differ between inner & outer editors
    (potential problem areas include line wrap and coloring theme: basically, anything in codemirror.css
    that uses a descandant selector where the CSS class name to the left of the space is something
    other than a vanilla .CodeMirror)
 */
.CodeMirror {
    .CodeMirror pre.CodeMirror-cursor {
        visibility: hidden;
    }
    .CodeMirror .CodeMirror-focused pre.CodeMirror-cursor {
        visibility: visible;
    }

    .CodeMirror div.CodeMirror-selected {
        background: #d9d9d9;
    }
    .CodeMirror .CodeMirror-focused div.CodeMirror-selected {
        background: #d2dcf8;
    }
    .CodeMirror .CodeMirror-gutters {
        background: transparent;
        border-right: none;
    }

    .CodeMirror-scroll {
        outline: none;
    }
}

/*
 * Temporarily override bold and italic syntax highlighting until
 * SourceCodePro supports them in a fixed pitch
 */
span.cm-em {
    font-style: normal;
}
span.cm-header, span.cm-strong {
    font-weight: normal;
}
span.cm-emstrong {
    font-style: normal;
    font-weight: normal;
}


// We expect the result to be scrolled roughly to the middle of the window.

keep keep keep keep keep replace replace replace replace replace keep


/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * 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.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define: false, describe: false, it: false, expect: false, beforeEach: false, afterEach: false, waitsFor: false, runs: false */
define(function (require, exports, module) {
    'use strict';

    // Load dependent modules
    var PreferencesManager      = require("preferences/PreferencesManager"),
        PreferenceStorage       = require("preferences/PreferenceStorage").PreferenceStorage,
        SpecRunnerUtils         = require("spec/SpecRunnerUtils");

    var CLIENT_ID = "PreferencesManager-test";

    describe("PreferenceStorage", function () {

        it("should read initial preferences from JSON", function () {
            var store = new PreferenceStorage(CLIENT_ID, {"foo": "bar", hello: "world"});
            expect(store.getValue("foo")).toBe("bar");
            expect(store.getValue("hello")).toBe("world");
        });

        it("should store values as JSON", function () {
            var json = {};
            var store = new PreferenceStorage(CLIENT_ID, json);
            store.setValue("foo", 42);

            expect(json.foo).toEqual(42);
            expect(store.getValue("foo")).toBe(42);
        });

        it("should output preferences as JSON", function () {
            var store = new PreferenceStorage(CLIENT_ID, {});
            store.setValue("foo", 42);
            var json = store.getAllValues();

            expect(json.foo).toEqual(42);
        });

        it("should remove values", function () {
            var store = new PreferenceStorage(CLIENT_ID, {"foo": "bar"});
            expect(store.getValue("foo")).toBe("bar");

            store.remove("foo");
            expect(store.getValue("foo")).toBe(undefined);
        });

        it("should use setAllValues to append multiple new name/value pairs", function () {
            var initial = {"foo": "bar"};
            var store = new PreferenceStorage(CLIENT_ID, initial);

            // append
            store.setAllValues({"hello": ["world", "!"], "goodbye": 42}, true);
            expect(store.getValue("foo")).toBe("bar");
            expect(store.getValue("hello")).toEqual(["world", "!"]);
            expect(store.getValue("goodbye")).toBe(42);

            // overwrite
            store.setAllValues({"winning": false}, false);
            expect(store.getValue("foo")).toBe(undefined);
            expect(store.getValue("hello")).toBe(undefined);
            expect(store.getValue("goodbye")).toBe(undefined);
            expect(store.getValue("winning")).toBe(false);
        });

        it("should throw errors for invalid values", function () {
            var store = new PreferenceStorage(CLIENT_ID, {"foo": 42});
            var error = null;

            expect(store.getValue("foo")).toBe(42);
            // function data is not valid JSON
            store.setValue("foo", function () {});
            expect(store.getValue("foo")).toBe(42);

            // number key is not valid JSON
            store.setValue(42, "bar");
            expect(store.getValue(42)).toBe(undefined);
        });

    });

    describe("PreferencesManager", function () {

        beforeEach(function () {
            // SpecRunner.js already initializes the unit test instance of
            // PreferencesManager to use the unit test key. All we need to do
            // here is reset to clear callbacks and in-memory preferences.
            PreferencesManager._reset();
        });

        it("should use default preferences", function () {
            var store = PreferencesManager.getPreferenceStorage(CLIENT_ID, {foo: "default"});
            expect(store.getValue("foo")).toEqual("default");
        });
    });
});


<!doctype html>

	<meta charset="utf-8">
	<title>jQuery UI Tooltip Test Suite</title>

	<link rel="stylesheet" href="../../../external/qunit.css">

jQuery UI Tooltip Test Suite

	anchor
	<input title="inputtitle">
	aria-describedby
	span


<!DOCTYPE html>

	<meta charset="utf-8">
	<title>jQuery UI Sortable - Portlets</title>
	<link rel="stylesheet" href="../../themes/base/jquery.ui.all.css">

	<link rel="stylesheet" href="../demos.css">

Feeds

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

News

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

Shopping

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

Links

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

Images

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

	Enable portlets (styled divs) as sortables and use the connectWith
	option to allow sorting between columns.


waitsFor(function () { return eventLooped; });

keep replace replace keep keep keep keep

/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * 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.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global require, define, $, beforeEach, afterEach, jasmine, brackets, PathUtils */

// Set the baseUrl to brackets/src
require.config({
    baseUrl: "../src",
    paths: {
        "test"      : "../test",
        "perf"      : "../test/perf",
        "spec"      : "../test/spec",
        "text"      : "thirdparty/text",
        "i18n"      : "thirdparty/i18n"
    }
});

define(function (require, exports, module) {
    'use strict';

    // Utility dependency
    var AppInit                 = require("utils/AppInit"),
        Global                  = require("utils/Global"),
        SpecRunnerUtils         = require("spec/SpecRunnerUtils"),
        ExtensionLoader         = require("utils/ExtensionLoader"),
        Async                   = require("utils/Async"),
        FileUtils               = require("file/FileUtils"),
        Menus                   = require("command/Menus"),
        NativeFileSystem        = require("file/NativeFileSystem").NativeFileSystem,
        UrlParams               = require("utils/UrlParams").UrlParams,
        UnitTestReporter        = require("test/UnitTestReporter").UnitTestReporter,
        BootstrapReporterView   = require("test/BootstrapReporterView").BootstrapReporterView;

    // Load modules that self-register and just need to get included in the main project
    require("document/ChangedDocumentTracker");
    require("thirdparty/smart-auto-complete/jquery.smart_autocomplete");

    // TODO (#2155): These are used by extensions via brackets.getModule(), so tests that run those
    // extensions need these to be required up front. We need a better solution for this eventually.
    require("utils/ExtensionUtils");

    // Load both top-level suites. Filtering is applied at the top-level as a filter to BootstrapReporter.
    require("test/UnitTestSuite");
    require("test/PerformanceTestSuite");

    var suite,
        params = new UrlParams(),
        reporter,
        reporterView;

    params.parse();

    function _loadExtensionTests(suite) {
        // augment jasmine to identify extension unit tests
        var addSuite = jasmine.Runner.prototype.addSuite;
        jasmine.Runner.prototype.addSuite = function (suite) {
            suite.category = "extension";
            addSuite.call(this, suite);
        };

        var bracketsPath = FileUtils.getNativeBracketsDirectoryPath(),
            paths = ["default"];

        // load dev and user extensions only when running the extension test suite
        if (suite === "ExtensionTestSuite") {
            paths.push("dev");
            paths.push(ExtensionLoader.getUserExtensionPath());
        }

        // This returns path to test folder, so convert to src
        bracketsPath = bracketsPath.replace(/\/test$/, "/src");

        return Async.doInParallel(paths, function (dir) {
            var extensionPath = dir;

            // If the item has "/" in it, assume it is a full path. Otherwise, load
            // from our source path + "/extensions/".
            if (dir.indexOf("/") === -1) {
                extensionPath = bracketsPath + "/extensions/" + dir;
            }

            return ExtensionLoader.testAllExtensionsInNativeDirectory(extensionPath);
        });
    }

    function _documentReadyHandler() {
        if (brackets.app.showDeveloperTools) {
            $("#show-dev-tools").click(function () {
                brackets.app.showDeveloperTools();
            });
        } else {
            $("#show-dev-tools").remove();
        }

        $("#reload").click(function () {
            window.location.reload(true);
        });

        $("#" + suite).closest("li").toggleClass("active", true);

        AppInit._dispatchReady(AppInit.APP_READY);

        jasmine.getEnv().execute();
    }

    /**
     * Listener for UnitTestReporter "runnerEnd" event. Attached only if
     * "resultsPath" URL parameter exists. Does not overwrite existing file.
     * Writes UnitTestReporter spec results as formatted JSON.
     * @param {!$.Event} event
     * @param {!UnitTestReporter} reporter
     */
    function _runnerEndHandler(event, reporter) {
        var resultsPath = params.get("resultsPath"),
            json = reporter.toJSON(),
            deferred = new $.Deferred();

        // check if the file already exists
        brackets.fs.stat(resultsPath, function (err, stat) {
            if (err === brackets.fs.ERR_NOT_FOUND) {
                // file not found, write the new file with JSON content
                brackets.fs.writeFile(resultsPath, json, NativeFileSystem._FSEncodings.UTF8, function (err) {
                    if (err) {
                        deferred.reject();
                    } else {
                        deferred.resolve();
                    }
                });
            } else {
                // file exists, do not overwrite
                deferred.reject();
            }
        });

        deferred.always(function () { window.close(); });
    }

    function init() {
        suite = params.get("suite") || localStorage.getItem("SpecRunner.suite") || "UnitTestSuite";

        // Create a top-level filter to show/hide performance and extensions tests
        var isPerfSuite = (suite === "PerformanceTestSuite"),
            isExtSuite = (suite === "ExtensionTestSuite");

        var topLevelFilter = function (spec) {
            var suite = spec.suite;

            // unit test suites have no category
            if (!isPerfSuite && !isExtSuite) {
                if (spec.category !== undefined) {
                    // if an individualy spec has a category, filter it out
                    return false;
                }

                while (suite) {
                    if (suite.category !== undefined) {
                        // any suite in the hierarchy may specify a category
                        return false;
                    }

                    suite = suite.parentSuite;
                }

                return true;
            }

            var category = (isPerfSuite) ? "performance" : "extension";

            if (spec.category === category) {
                return true;
            }

            while (suite) {
                if (suite.category === category) {
                    return true;
                }

                suite = suite.parentSuite;
            }

            return false;
        };

        /*
         * TODO (jason-sanjose): extension unit tests should only load the
         * extension and the extensions dependencies. We should not load
         * unrelated extensions. Currently, this solution is all or nothing.
         */

        // configure spawned test windows to load extensions
        SpecRunnerUtils.setLoadExtensionsInTestWindow(isExtSuite);

        _loadExtensionTests(suite).done(function () {
            var jasmineEnv = jasmine.getEnv();

            // Initiailize unit test preferences for each spec
            beforeEach(function () {
                // Unique key for unit testing
                localStorage.setItem("preferencesKey", SpecRunnerUtils.TEST_PREFERENCES_KEY);
            });

            afterEach(function () {
                // Clean up preferencesKey
                localStorage.removeItem("preferencesKey");
            });

            jasmineEnv.updateInterval = 1000;

            // Create the reporter, which is really a model class that just gathers
            // spec and performance data.
            reporter = new UnitTestReporter(jasmineEnv, topLevelFilter, params.get("spec"));

            // Optionally emit JSON for automated runs
            if (params.get("resultsPath")) {
                $(reporter).on("runnerEnd", _runnerEndHandler);
            }

            jasmineEnv.addReporter(reporter);

            // Create the view that displays the data from the reporter. (Usually in
            // Jasmine this is part of the reporter, but we separate them out so that
            // we can more easily grab just the model data for output during automatic
            // testing.)
            reporterView = new BootstrapReporterView(document, reporter);

            // remember the suite for the next unit test window launch
            localStorage.setItem("SpecRunner.suite", suite);

            $(window.document).ready(_documentReadyHandler);
        });
    }

    init();
});


/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * 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.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $, window */

 /**
  * This is JavaScript API exposed to the native shell when Brackets is run in a native shell rather than a browser.
  */
define(function (require, exports, module) {
    "use strict";

    // Load dependent modules
    var CommandManager     = require("command/CommandManager");

    /**
     * The native function BracketsShellAPI::DispatchBracketsJSCommand calls this function in order to enable
     * calling Brackets commands from the native shell.
     */
    function executeCommand(eventName) {
        var promise = CommandManager.execute(eventName);
        return (promise && promise.state() === "rejected") ? false : true;
    }

    exports.executeCommand = executeCommand;
});


@ECHO OFF

REM - Check for parameter
IF %1.==. GOTO Error

REM - Remove 'dev' directory
ECHO Removing %1\dev
rmdir %1\dev

GOTO Exit

:Error
ECHO Usage: restore_installed_build.bat application_path
ECHO Restore Brackets to use the installed HTML/CSS/JS files.
ECHO Parameters: application_path - path that contains the Brackets application
ECHO Example: restore_installed_build.bat "c:\Program Files (x86)\Brackets Sprint 14"

:Exit


<!doctype html>

	<meta charset="utf-8">
	<title>jQuery UI Sortable Test Suite</title>

	<link rel="stylesheet" href="../../../external/qunit.css">

jQuery UI Sortable Test Suite

Item 1

Item 2

Item 3

Item 4

Item 5