keep keep keep keep keep replace replace keep keep keep

/*
 * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
 */
define(function(require, exports, module) {

    // TODO: Determine proper public/private API for this module, splitting into separate modules as needed

    var NativeFileSystem = {

        /** showOpenDialog
         *
         * @param {bool} allowMultipleSelection
         * @param {bool} chooseDirectories
         * @param {string} title
         * @param {string} initialPath
         * @param {string[]} fileTypes
         * @param {function} resultCallback
         * @constructor
         */
        showOpenDialog: function (  allowMultipleSelection,
                                    chooseDirectories,
                                    title,
                                    initialPath,
                                    fileTypes,
                                    successCallback,
                                    errorCallback )
        {
            if( !successCallback )
                return;

            var files = brackets.fs.showOpenDialog( allowMultipleSelection,
                chooseDirectories,
                title,
                initialPath,
                fileTypes,
                function( err, data ) {
                    if( ! err )
                        successCallback( data );
                    else if (errorCallback)
                        errorCallback(NativeFileSystem._nativeToFileError(err));
                });
        },

        /** requestNativeFileSystem
         *
         * @param {string} path
         * @param {function} successCallback
         * @param {function} errorCallback
         */
        requestNativeFileSystem: function( path, successCallback, errorCallback ){
            brackets.fs.stat(path, function( err, data ){
                if( !err ){
                    var root = new NativeFileSystem.DirectoryEntry( path );
                    successCallback( root );
                }
                else if (errorCallback) {
                    errorCallback(NativeFileSystem._nativeToFileError(err));
                }
            });
        },

        _nativeToFileError: function(nativeErr) {
            // The HTML file spec says SECURITY_ERR is a catch-all to be used in situations
            // not covered by other error codes.
            var error = FileError.SECURITY_ERR;

            switch (nativeErr) {
                // We map ERR_UNKNOWN and ERR_INVALID_PARAMS to SECURITY_ERR,
                // since there aren't specific mappings for these.
                case brackets.fs.ERR_UNKNOWN:
                case brackets.fs.ERR_INVALID_PARAMS:
                    error = FileError.SECURITY_ERR;
                    break;
                case brackets.fs.ERR_NOT_FOUND:
                    error = FileError.NOT_FOUND_ERR;
                    break;
                case brackets.fs.ERR_CANT_READ:
                    error = FileError.NOT_READABLE_ERR;
                    break;
                // It might seem like you should use FileError.ENCODING_ERR for this,
                // but according to the spec that's for malformed URLs.
                case brackets.fs.ERR_UNSUPPORTED_ENCODING:
                    error = FileError.SECURITY_ERR;
                    break;
                case brackets.fs.ERR_CANT_WRITE:
                    error = FileError.NO_MODIFICATION_ALLOWED_ERR;
                    break;
                case brackets.fs.ERR_OUT_OF_SPACE:
                    error = FileError.QUOTA_EXCEEDED_ERR;
                    break;
                case brackets.fs.PATH_EXISTS_ERR:
                    error = FileError.PATH_EXISTS_ERR;
                    break;
            }
            return new NativeFileSystem.FileError(error);
        }
    };

    /** class: Entry
     *
     * @param {string} name
     * @param {string} isFile
     * @constructor
     */
    NativeFileSystem.Entry = function( fullPath, isDirectory) {
        this.isDirectory = isDirectory;
        this.isFile = !isDirectory;
        // IMPLEMENT LATER void      getMetadata (MetadataCallback successCallback, optional ErrorCallback errorCallback);
        this.fullPath = fullPath;

        // Extract name from fullPath
        this.name = null; // default if extraction fails
        if( fullPath ){
            var pathParts = fullPath.split( "/" );
            if( pathParts.length > 0 )
                this.name = pathParts.pop();
        }

        // IMPLEMENT LATER var filesystem;
        // IMPLEMENT LATER void      moveTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
        // IMPLEMENT LATER void      copyTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
        // IMPLEMENT LATER DOMString toURL (optional DOMString mimeType);
        // IMPLEMENT LATER void      remove (VoidCallback successCallback, optional ErrorCallback errorCallback);
        // IMPLEMENT LATER void      getParent (EntryCallback successCallback, optional ErrorCallback errorCallback);
    };

    /**
     * This interface represents a file on a file system.
     *
     * @param {string} name
     * @constructor
     * @extends {Entry}
     */
    NativeFileSystem.FileEntry = function( name ) {
        NativeFileSystem.Entry.call(this, name, false);

        // TODO: make FileEntry actually inherit from Entry by modifying prototype. I don't know how to do this yet.

    };

    /**
     * Creates a new FileWriter associated with the file that this FileEntry represents.
     *
     * @param {function(_FileWriter)} successCallback
     * @param {function(FileError)} errorCallback
     */
    NativeFileSystem.FileEntry.prototype.createWriter = function( successCallback, errorCallback ) {
        var fileEntry = this;

        // [NoInterfaceObject]
        // interface FileWriter : FileSaver
        var _FileWriter = function( data ) {
            NativeFileSystem.FileSaver.call(this, data);

            // _FileWriter private memeber vars
            this._length = 0;
            this._position = 0;

            // initialize file length
            // TODO (jasonsj): handle async
            var self = this;

            brackets.fs.readFile( fileEntry.fullPath, "utf8", function(err, contents) {
                self._err = err;

                if ( contents )
                    self._length = contents.length;
            });
        };

        _FileWriter.prototype.length = function( ) {
            return this._length;
        };

        _FileWriter.prototype.position = function( ) {
            return this._position;
        };

        // TODO (jasonsj): handle Blob data instead of string
        _FileWriter.prototype.write = function( data ) {
            if ( data === undefined )
                throw new Error();

            if ( this.readyState === NativeFileSystem.FileSaver.WRITING )
                throw new NativeFileSystem.FileException( NativeFileSystem.FileException.INVALID_STATE_ERR );

            this._readyState = NativeFileSystem.FileSaver.WRITING;

            if ( this.onwritestart ) {
                // TODO (jasonsj): progressevent
                this.onwritestart();
            }

            var self = this;

            brackets.fs.writeFile( fileEntry.fullPath, data, "utf8", function( err ) {
                var fileError = null;

                if ( ( err != brackets.fs.NO_ERROR ) && self.onerror ) {
                    fileError = NativeFileSystem._nativeToFileError( err );

                    // TODO (jasonsj): set readonly FileSaver.error attribute
                    // self._error = fileError;

                    self.onerror ( fileError );

                    // TODO (jasonsj): partial write, update length and position
                }
                else {
                    // TODO (jasonsj): After changing data argument to Blob, use
                    // Blob.size to update position and length upon successful
                    // completion of a write.

                    // self.position = ;
                    // self.length = ;
                }

                // DONE is set regardless of error
                this._readyState = NativeFileSystem.FileSaver.DONE;

                if ( self.onwrite ) {
                    // TODO (jasonsj): progressevent
                    self.onwrite();
                }

                if ( self.onwriteend ) {
                    // TODO (jasonsj): progressevent
                    self.onwriteend();
                }
            });
        };

        _FileWriter.prototype.seek = function( offset ) {
        };

        _FileWriter.prototype.truncate = function( size ) {
        };

        var fileWriter = new _FileWriter();

        if ( fileWriter._err && ( errorCallback !== undefined ) ) {
            errorCallback( NativeFileSystem._nativeToFileError( fileWriter._err ) );
        }
        else if ( successCallback !== undefined ) {
            successCallback( fileWriter );
        }
    };

    /**
     * This interface extends the FileException interface described in to add
     * several new error codes. Any errors that need to be reported synchronously,
     * including all that occur during use of the synchronous filesystem methods,
     * are reported using the FileException exception.
     *
     * @param {number} code The code attribute, on getting, must return one of the
     * constants of the FileException exception, which must be the most appropriate
     * code from the table below.
     */
    NativeFileSystem.FileException = function ( code ){
        this.code = code || 0;
    };

    // FileException constants
    Object.defineProperties(NativeFileSystem.FileException,
        { NOT_FOUND_ERR:                { value: 1, writable: false }
        , SECURITY_ERR:                 { value: 2, writable: false }
        , ABORT_ERR:                    { value: 3, writable: false }
        , NOT_READABLE_ERR:             { value: 4, writable: false }
        , ENCODING_ERR:                 { value: 5, writable: false }
        , NO_MODIFICATION_ALLOWED_ERR:  { value: 6, writable: false }
        , INVALID_STATE_ERR:            { value: 7, writable: false }
        , SYNTAX_ERR:                   { value: 8, writable: false }
        , QUOTA_EXCEEDED_ERR:           { value: 10, writable: false }
    });

    /**
     * This interface provides methods to monitor the asynchronous writing of blobs
     * to disk using progress events and event handler attributes.
     *
     * This interface is specified to be used within the context of the global
     * object (Window) and within Web Workers.
     *
     * @param {Blob} data
     * @constructor
     */
    NativeFileSystem.FileSaver = function( data ) {
        // FileSaver private member vars
        this._data = data;
        this._readyState = NativeFileSystem.FileSaver.INIT;
        this._error = null;
    };

    // FileSaver constants
    Object.defineProperties(NativeFileSystem.FileSaver,
        { INIT:     { value: 1, writable: false }
        , WRITING:  { value: 2, writable: false }
        , DONE:     { value: 3, writable: false }
    });

    // FileSaver methods

    /**
     *
     */
    NativeFileSystem.FileSaver.prototype.readyState = function() {
        return this._readyState;
    }

    // TODO (jasonsj): http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void
    NativeFileSystem.FileSaver.prototype.abort = function() {
        // If readyState is DONE or INIT, terminate this overall series of steps without doing anything else..
        if (_readyState == FileSaver.INIT || _readyState == FileSaver.DONE)
        return;

        // Terminate any steps having to do with writing a file.

        // Set the error attribute to a FileError object with the code ABORT_ERR.
        _error = new NativeFileSystem.FileError(FileError.ABORT_ERR);

        // Set readyState to DONE.
        _readyState = FileSaver.DONE;

        // Dispatch a progress event called abort
        // Dispatch a progress event called writeend
        // Stop dispatching any further progress events.
        // Terminate this overall set of steps.

        return err;
    };

    /**
     * Obtains the File objecte for a FileEntry object
     *
     * @param {function} successCallback
     * @param {function} errorCallback
     */
    NativeFileSystem.FileEntry.prototype.file = function( successCallback, errorCallback ){
        var newFile = new NativeFileSystem.File( this );
        successCallback( newFile );

        // TODO Ty: error handling
        // errorCallback
    };

    /*
    TODO Jason
    NativeFileSystem.FileEntry.prototype.createfileerror = function( successCallback, errorCallback ){
    };
    */

    /**
     * This interface represents a directory on a file system.
     *
     * @constructor
     * @param {string} name
     * @extends {Entry}
     */
    NativeFileSystem.DirectoryEntry = function( name ) {
        NativeFileSystem.Entry.call(this, name, true);

        // TODO: make DirectoryEntry actually inherit from Entry by modifying prototype. I don't know how to do this yet.

        // IMPLEMENT LATERvoid            getDirectory (DOMString path, optional Flags options, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
        // IMPLEMENT LATERvoid            removeRecursively (VoidCallback successCallback, optional ErrorCallback errorCallback);
    };

    NativeFileSystem.DirectoryEntry.prototype.createReader = function() {
        var dirReader = new NativeFileSystem.DirectoryReader();
        dirReader._directory = this;

        return dirReader;
    };

    /**
     * Creates or looks up a file.
     *
     * @param {string} path Either an absolute path or a relative path from this
     *        DirectoryEntry to the file to be looked up or created. It is an error
     *        to attempt to create a file whose immediate parent does not yet
     *        exist.
     * @param {Object.<string, boolean>} options
     * @param {function(number)} successCallback
     * @param {function(number)} errorCallback
     */
    NativeFileSystem.DirectoryEntry.prototype.getFile = function( path, options, successCallback, errorCallback ) {
        // TODO (jasonsj): handle absolute paths
        var fileFullPath = this.fullPath + "/" + path;

        var createFileEntry = function () {
            if ( successCallback ) {
                successCallback( new NativeFileSystem.FileEntry( fileFullPath ) );
            }
        }

        var createFileError = function ( err ) {
            if ( errorCallback ) {
                errorCallback( NativeFileSystem._nativeToFileError( err ) );
            }
        }

        // Use stat() to check if file exists
        brackets.fs.stat( fileFullPath, function( err, stats ) {
            if ( ( err === brackets.fs.NO_ERROR ) ) {
                // NO_ERROR implies the path already exists

                // throw error if the file the path is a directory
                if ( stats.isDirectory() ) {
                    if ( errorCallback ) {
                        errorCallback( new NativeFileSystem.FileError( FileError.TYPE_MISMATCH_ERR ) );
                    }

                    return;
                }

                // throw error if the file exists but create is exclusive
                if ( options.create && options.exclusive ) {
                    if ( errorCallback ) {
                        errorCallback( new NativeFileSystem.FileError( FileError.PATH_EXISTS_ERR ) );
                    }

                    return;
                }

                // Create a file entry for the existing file. If create == true,
                // a file entry is created without error.
                createFileEntry();
            } else if ( err === brackets.fs.ERR_NOT_FOUND ) {
                // ERR_NOT_FOUND implies we write a new, empty file

                // create the file
                if ( options.create ) {
                    brackets.fs.writeFile( fileFullPath, "", "utf8", function( err ) {
                        if ( err )
                            createFileError( err );
                        else
                            createFileEntry();
                    });

                    return;
                }

                // throw error if file not found and the create == false
                if ( errorCallback ) {
                    errorCallback( new NativeFileSystem.FileError( FileError.NOT_FOUND_ERR ) );
                }
            } else {
                // all other brackets.fs.stat() errors
                createFileError( err );
            }
        });
    };

    /** class: DirectoryReader
     */
    NativeFileSystem.DirectoryReader = function() {

    };

    /** readEntries
     *
     * @param {function} successCallback
     * @param {function} errorCallback
     * @returns {Entry[]}
     */
    NativeFileSystem.DirectoryReader.prototype.readEntries = function( successCallback, errorCallback ){
        var rootPath = this._directory.fullPath;
        var jsonList = brackets.fs.readdir( rootPath, function( err, filelist ) {
            if( ! err ){
                // Create entries for each name
                var entries = [];
    			var statErr;
    			for( var i = 0; i < filelist.length; i++ ){
    				var item = filelist[i];
                    var itemFullPath = rootPath + "/" + item;

                    brackets.fs.stat( itemFullPath, function( statErr, statData) {

                        if( !statErr ){
                            if( statData.isDirectory() )
                                entries.push( new NativeFileSystem.DirectoryEntry( itemFullPath ) );
                            else if( statData.isFile() )
                                entries.push( new NativeFileSystem.FileEntry( itemFullPath ) );
                        }
                        else if (errorCallback) {
                            errorCallback(NativeFileSystem._nativeToFileError(statErr));
                        }

                    });

    				// exit loop if there is an error
    				if( statErr )
    					break;
                }

    			if( !statErr )
    				successCallback( entries );
    			else
    				 errorCallback(NativeFileSystem._nativeToFileError(statErr));
            }
            else if (errorCallback) {
                errorCallback(NativeFileSystem._nativeToFileError(err));
            }
        });
    };

    /** class: FileReader
     *
     * @extends {EventTarget}
     */
    NativeFileSystem.FileReader = function() {
        // Todo Ty: this classes should extend EventTarget

        // async read methods
        // IMPLEMENT LATER void readAsArrayBuffer(Blob blob);
        // IMPLEMENT LATER void readAsBinaryString(Blob blob);
        // IMPLEMENT LATER void readAsDataURL(Blob blob);

        // IMPLEMENT LATER void abort();

        // states
        this.EMPTY = 0;
        this.LOADING = 1;
        this.DONE = 2;

        // readyState is read only
        this.readyState = this.EMPTY;

        // File or Blob data
        // IMPLEMENT LATER readonly attribute any result;
        // IMPLEMENT LATER readonly attribute DOMError error;

        // event handler attributes
        this.onloadstart = null;
        this.onprogress = null;
        this.onload = null;
        this.onabort = null;
        this.onerror = null;
        this.onloadend = null;

    };

    /** readAsText
     *
     * @param {Blob} blob
     * @param {string} encoding
     */
    NativeFileSystem.FileReader.prototype.readAsText = function( blob, encoding) {
        var self = this;

        if( !encoding )
            encoding = "utf-8";

        if( this.readyState == this.LOADING )
            throw new InvalidateStateError();

        this.readyState = this.LOADING;

        if( this.onloadstart )
            this.onloadstart(); // todo params

        brackets.fs.readFile( blob._fullPath, encoding, function( err, data) {

            // TODO: the event objects passed to these event handlers is fake and incomplete right now
            var fakeEvent =
                { loaded: 0
                , total: 0
                };

            // The target for this event is the FileReader and the data/err result is stored in the FileReader
            fakeEvent.target = this;
            this.result = data;
            this.error = NativeFileSystem._nativeToFileError(err);;

            if( err ){
                this.readyState = this.DONE;
                if( self.onerror ){
                    self.onerror(fakeEvent);
                }
            }
            else{
                this.readyState = this.DONE;

                // TODO: this should be the file/blob size, but we don't have code to get that yet, so for know assume a file size of 1
                // and since we read the file in one go, assume 100% after the first read
                fakeEvent.loaded = 1;
                fakeEvent.total = 1;

                if( self.onprogress )
                    self.onprogress(fakeEvent);

                // TODO: this.onabort not currently supported since our native implementation doesn't support it
                // if( self.onabort )
                //    self.onabort(fakeEvent);

                if( self.onload )
                    self.onload( fakeEvent );

                if( self.onloadend )
                    self.onloadend();
            }

        });
    };

    /** class: Blob
     *
     * @constructor
     * param {Entry} entry
     */
    NativeFileSystem.Blob = function ( fullPath ){
        this._fullPath = fullPath;

        // IMPLEMENT LATER readonly attribute unsigned long long size;
        // IMPLEMENT LATER readonly attribute DOMString type;

        //slice Blob into byte-ranged chunks

        // IMPLEMENT LATER Blob slice(optional long long start,
        //           optional long long end,
        //           optional DOMString contentType);
    };

    /** class: File
     *
     * @constructor
     * param {Entry} entry
     * @extends {Blob}
     */
    NativeFileSystem.File = function ( entry ){
        NativeFileSystem.Blob.call( this, entry.fullPath );

        // IMPLEMENT LATER get name() { return this.entry.name; }
        // IMPLEMENT LATER get lastModifiedDate() { return } use stat to get mod date
    };

    /** class: FileError
     *
     * Implementation of HTML file API error code return class. Note that we don't
     * actually define the error codes here--we rely on the browser's built-in FileError
     * class's constants. In other words, external clients of this API should always
     * use FileError.<constant-name>, not NativeFileSystem.FileError.<constant-name>.
     *
     * @constructor
     * @param {number} code The error code to return with this FileError. Must be
     * one of the codes defined in the FileError class.
     */
    NativeFileSystem.FileError = function( code ) {
        this.code = code || 0;
    };

    // Define public API
    exports.NativeFileSystem = NativeFileSystem;
});


* @param {function(...)} successCallback

/*!
 * Bootstrap @VERSION
 *
 * Copyright 2011 Twitter, Inc
 * Licensed under the Apache License v2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world @twitter by @mdo and @fat.
 * Date: @DATE
 */

// CSS Reset
@import "reset.less";

// Core variables and mixins
@import "variables.less"; // Modify this for custom colors, font-sizes, etc
@import "mixins.less";

// Grid system and page structure
@import "scaffolding.less";

// Styled patterns and elements
@import "type.less";
@import "forms.less";
@import "tables.less";
@import "patterns.less";

// Brackets-specific styles
@import "brackets.less";
@import "jsTreeTheme.less";


This directory is marked read only when tests are run. Attempts to write files here should fail.


/* ==========================================================
 * bootstrap-twipsy.js v1.4.0
 * http://twitter.github.com/bootstrap/javascript.html#twipsy
 * Adapted from the original jQuery.tipsy by Jason Frame
 * ==========================================================
 * Copyright 2011 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */

!function( $ ) {

  "use strict"

 /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
  * ======================================================= */

  var transitionEnd

  $(document).ready(function () {

    $.support.transition = (function () {
      var thisBody = document.body || document.documentElement
        , thisStyle = thisBody.style
        , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
      return support
    })()

    // set CSS transition event type
    if ( $.support.transition ) {
      transitionEnd = "TransitionEnd"
      if ( $.browser.webkit ) {
      	transitionEnd = "webkitTransitionEnd"
      } else if ( $.browser.mozilla ) {
      	transitionEnd = "transitionend"
      } else if ( $.browser.opera ) {
      	transitionEnd = "oTransitionEnd"
      }
    }

  })

 /* TWIPSY PUBLIC CLASS DEFINITION
  * ============================== */

  var Twipsy = function ( element, options ) {
    this.$element = $(element)
    this.options = options
    this.enabled = true
    this.fixTitle()
  }

  Twipsy.prototype = {

    show: function() {
      var pos
        , actualWidth
        , actualHeight
        , placement
        , $tip
        , tp

      if (this.hasContent() && this.enabled) {
        $tip = this.tip()
        this.setContent()

        if (this.options.animate) {
          $tip.addClass('fade')
        }

        $tip
          .remove()
          .css({ top: 0, left: 0, display: 'block' })
          .prependTo(document.body)

        pos = $.extend({}, this.$element.offset(), {
          width: this.$element[0].offsetWidth
        , height: this.$element[0].offsetHeight
        })

        actualWidth = $tip[0].offsetWidth
        actualHeight = $tip[0].offsetHeight

        placement = maybeCall(this.options.placement, this, [ $tip[0], this.$element[0] ])

        switch (placement) {
          case 'below':
            tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}
            break
          case 'above':
            tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}
            break
          case 'left':
            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset}
            break
          case 'right':
            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset}
            break
        }

        $tip
          .css(tp)
          .addClass(placement)
          .addClass('in')
      }
    }

  , setContent: function () {
      var $tip = this.tip()
      $tip.find('.twipsy-inner')[this.options.html ? 'html' : 'text'](this.getTitle())
      $tip[0].className = 'twipsy'
    }

  , hide: function() {
      var that = this
        , $tip = this.tip()

      $tip.removeClass('in')

      function removeElement () {
        $tip.remove()
      }

      $.support.transition && this.$tip.hasClass('fade') ?
        $tip.bind(transitionEnd, removeElement) :
        removeElement()
    }

  , fixTitle: function() {
      var $e = this.$element
      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
        $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
      }
    }

  , hasContent: function () {
      return this.getTitle()
    }

  , getTitle: function() {
      var title
        , $e = this.$element
        , o = this.options

        this.fixTitle()

        if (typeof o.title == 'string') {
          title = $e.attr(o.title == 'title' ? 'data-original-title' : o.title)
        } else if (typeof o.title == 'function') {
          title = o.title.call($e[0])
        }

        title = ('' + title).replace(/(^\s*|\s*$)/, "")

        return title || o.fallback
    }

  , tip: function() {
      return this.$tip = this.$tip || $('
').html(this.options.template)
    }

  , validate: function() {
      if (!this.$element[0].parentNode) {
        this.hide()
        this.$element = null
        this.options = null
      }
    }

  , enable: function() {
      this.enabled = true
    }

  , disable: function() {
      this.enabled = false
    }

  , toggleEnabled: function() {
      this.enabled = !this.enabled
    }

  , toggle: function () {
      this[this.tip().hasClass('in') ? 'hide' : 'show']()
    }

  }

 /* TWIPSY PRIVATE METHODS
  * ====================== */

   function maybeCall ( thing, ctx, args ) {
     return typeof thing == 'function' ? thing.apply(ctx, args) : thing
   }

 /* TWIPSY PLUGIN DEFINITION
  * ======================== */

  $.fn.twipsy = function (options) {
    $.fn.twipsy.initWith.call(this, options, Twipsy, 'twipsy')
    return this
  }

  $.fn.twipsy.initWith = function (options, Constructor, name) {
    var twipsy
      , binder
      , eventIn
      , eventOut

    if (options === true) {
      return this.data(name)
    } else if (typeof options == 'string') {
      twipsy = this.data(name)
      if (twipsy) {
        twipsy[options]()
      }
      return this
    }

    options = $.extend({}, $.fn[name].defaults, options)

    function get(ele) {
      var twipsy = $.data(ele, name)

      if (!twipsy) {
        twipsy = new Constructor(ele, $.fn.twipsy.elementOptions(ele, options))
        $.data(ele, name, twipsy)
      }

      return twipsy
    }

    function enter() {
      var twipsy = get(this)
      twipsy.hoverState = 'in'

      if (options.delayIn == 0) {
        twipsy.show()
      } else {
        twipsy.fixTitle()
        setTimeout(function() {
          if (twipsy.hoverState == 'in') {
            twipsy.show()
          }
        }, options.delayIn)
      }
    }

    function leave() {
      var twipsy = get(this)
      twipsy.hoverState = 'out'
      if (options.delayOut == 0) {
        twipsy.hide()
      } else {
        setTimeout(function() {
          if (twipsy.hoverState == 'out') {
            twipsy.hide()
          }
        }, options.delayOut)
      }
    }

    if (!options.live) {
      this.each(function() {
        get(this)
      })
    }

    if (options.trigger != 'manual') {
      binder   = options.live ? 'live' : 'bind'
      eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus'
      eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'
      this[binder](eventIn, enter)[binder](eventOut, leave)
    }

    return this
  }

  $.fn.twipsy.Twipsy = Twipsy

  $.fn.twipsy.defaults = {
    animate: true
  , delayIn: 0
  , delayOut: 0
  , fallback: ''
  , placement: 'above'
  , html: false
  , live: false
  , offset: 0
  , title: 'title'
  , trigger: 'hover'
  , template: '

'
  }

  $.fn.twipsy.rejectAttrOptions = [ 'title' ]

  $.fn.twipsy.elementOptions = function(ele, options) {
    var data = $(ele).data()
      , rejects = $.fn.twipsy.rejectAttrOptions
      , i = rejects.length

    while (i--) {
      delete data[rejects[i]]
    }

    return $.extend({}, options, data)
  }

}( window.jQuery || window.ender );


NativeFileSystem.DirectoryReader.prototype.readEntries = function( successCallback, errorCallback ){

var rootPath = this._directory.fullPath;

keep keep keep replace replace replace keep keep keep


/*
 * Tables.less
 * Tables for, you guessed it, tabular data
 * ---------------------------------------- */

// BASELINE STYLES
// ---------------

table {
  width: 100%;
  margin-bottom: @baseline;
  padding: 0;
  font-size: @basefont;
  border-collapse: collapse;
  th,
  td {
    padding: 10px 10px 9px;
    line-height: @baseline;
    text-align: left;
  }
  th {
    padding-top: 9px;
    font-weight: bold;
    vertical-align: middle;
  }
  td {
    vertical-align: top;
    border-top: 1px solid #ddd;
  }
  // When scoped to row, fix th in tbody
  tbody th {
    border-top: 1px solid #ddd;
    vertical-align: top;
  }
}

// CONDENSED VERSION
// -----------------
.condensed-table {
  th,
  td {
    padding: 5px 5px 4px;
  }
}

// BORDERED VERSION
// ----------------

.bordered-table {
  border: 1px solid #ddd;
  border-collapse: separate; // Done so we can round those corners!
  *border-collapse: collapse; /* IE7, collapse table to remove spacing */
  .border-radius(4px);
  th + th,
  td + td,
  th + td {
    border-left: 1px solid #ddd;
  }
  thead tr:first-child th:first-child,
  tbody tr:first-child td:first-child {
    .border-radius(4px 0 0 0);
  }
  thead tr:first-child th:last-child,
  tbody tr:first-child td:last-child {
    .border-radius(0 4px 0 0);
  }
  tbody tr:last-child td:first-child {
    .border-radius(0 0 0 4px);
  }
  tbody tr:last-child td:last-child {
    .border-radius(0 0 4px 0);
  }
}

// TABLE CELL SIZES
// ----------------

// This is a duplication of the main grid .columns() mixin, but subtracts 20px to account for input padding and border
.tableColumns(@columnSpan: 1) {
  width: ((@gridColumnWidth - 20) * @columnSpan) + ((@gridColumnWidth - 20) * (@columnSpan - 1));
}
table {
  // Default columns
  .span1     { .tableColumns(1); }
  .span2     { .tableColumns(2); }
  .span3     { .tableColumns(3); }
  .span4     { .tableColumns(4); }
  .span5     { .tableColumns(5); }
  .span6     { .tableColumns(6); }
  .span7     { .tableColumns(7); }
  .span8     { .tableColumns(8); }
  .span9     { .tableColumns(9); }
  .span10    { .tableColumns(10); }
  .span11    { .tableColumns(11); }
  .span12    { .tableColumns(12); }
  .span13    { .tableColumns(13); }
  .span14    { .tableColumns(14); }
  .span15    { .tableColumns(15); }
  .span16    { .tableColumns(16); }
}

// ZEBRA-STRIPING
// --------------

// Default zebra-stripe styles (alternating gray and transparent backgrounds)
.zebra-striped {
  tbody {
    tr:nth-child(odd) td,
    tr:nth-child(odd) th {
      background-color: #f9f9f9;
    }
    tr:hover td,
    tr:hover th {
      background-color: #f5f5f5;
    }
  }
}

table {
  // Tablesorting styles w/ jQuery plugin
  .header {
    cursor: pointer;
    &:after {
      content: "";
      float: right;
      margin-top: 7px;
      border-width: 0 4px 4px;
      border-style: solid;
      border-color: #000 transparent;
      visibility: hidden;
    }
  }
  // Style the sorted column headers (THs)
  .headerSortUp,
  .headerSortDown {
    background-color: rgba(141,192,219,.25);
    text-shadow: 0 1px 1px rgba(255,255,255,.75);
  }
  // Style the ascending (reverse alphabetical) column header
  .header:hover {
    &:after {
      visibility:visible;
    }
  }
  // Style the descending (alphabetical) column header
  .headerSortDown,
  .headerSortDown:hover {
    &:after {
      visibility:visible;
      .opacity(60);
    }
  }
  // Style the ascending (reverse alphabetical) column header
  .headerSortUp {
    &:after {
      border-bottom: none;
      border-left: 4px solid transparent;
      border-right: 4px solid transparent;
      border-top: 4px solid #000;
      visibility:visible;
      .box-shadow(none); //can't add boxshadow to downward facing arrow :(
      .opacity(60);
    }
  }
  // Blue Table Headings
  .blue {
    color: @blue;
    border-bottom-color: @blue;
  }
  .headerSortUp.blue,
  .headerSortDown.blue {
    background-color: lighten(@blue, 40%);
  }
  // Green Table Headings
  .green {
    color: @green;
    border-bottom-color: @green;
  }
  .headerSortUp.green,
  .headerSortDown.green {
    background-color: lighten(@green, 40%);
  }
  // Red Table Headings
  .red {
    color: @red;
    border-bottom-color: @red;
  }
  .headerSortUp.red,
  .headerSortDown.red {
    background-color: lighten(@red, 50%);
  }
  // Yellow Table Headings
  .yellow {
    color: @yellow;
    border-bottom-color: @yellow;
  }
  .headerSortUp.yellow,
  .headerSortDown.yellow {
    background-color: lighten(@yellow, 40%);
  }
  // Orange Table Headings
  .orange {
    color: @orange;
    border-bottom-color: @orange;
  }
  .headerSortUp.orange,
  .headerSortDown.orange {
    background-color: lighten(@orange, 40%);
  }
  // Purple Table Headings
  .purple {
    color: @purple;
    border-bottom-color: @purple;
  }
  .headerSortUp.purple,
  .headerSortDown.purple {
    background-color: lighten(@purple, 40%);
  }
}


This content was generated from LowLevelFileIO-test.js


* @param {...} Arguments to be substituted into the string

/*
 * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
 */

define(function(require, exports, module) {

    /**
     * Format a string by replacing placeholder symbols with passed in arguments.
     *
     * Example: var formatted = Strings.format("Hello {0}", "World");
     *
     * @param {string} str The base string
     * @param {string} ... Arguments to be substituted into the string
     *
     * @return {string} Formatted string
     */
    function format(str) {
        var args = arguments;
        return str.replace(/{(\d+)}/g, function(match, num) {
            // args[0] is the string, so we need to adjust index values here
            // "num" is a string
            var i = Number(num);
            return typeof args[i + 1] !== 'undefined' ? args[i + 1] : match;
        });
    }

    // Define public API
    exports.format                            = format;

    // General file io error strings
    exports.GENERIC_ERROR                     = "(error {0})";
    exports.NOT_FOUND_ERR                     = "The file could not be found.";
    exports.NOT_READABLE_ERR                  = "The file could not be read.";
    exports.NO_MODIFICATION_ALLOWED_ERR       = "The target directory cannot be modified.";

    // Project error strings
    exports.ERROR_LOADING_PROJECT             = "Error loading project";
    exports.OPEN_DIALOG_ERROR                 = "An error occurred when showing the open file dialog. (error {0})";
    exports.REQUEST_NATIVE_FILE_SYSTEM_ERROR  = "An error occurred when trying to load the directory \"{0}\". (error {1})";
    exports.READ_DIRECTORY_ENTRIES_ERROR      = "An error occurred when reading the contents of the directory \"{0}\". (error {1})";

    // File open/save error string
    exports.ERROR_OPENING_FILE_TITLE          = "Error opening file";
    exports.ERROR_OPENING_FILE                = "An error occurred when trying to open the file \"{0}\". {1}";
    exports.ERROR_SAVING_FILE_TITLE           = "Error saving file";
    exports.ERROR_SAVING_FILE                 = "An error occurred when trying to save the file \"{0}\". {1}";
    exports.INVALID_FILENAME_TITLE            = "Invalid file name";
    exports.INVALID_FILENAME_MESSAGE          = "Filenames cannot contain the following characters: /?*:;{}<>\\|";
    exports.FILE_ALREADY_EXISTS               = "The file \"{0}\" already exists.";

    exports.SAVE_CLOSE_TITLE                  = "Save Changes";
    exports.SAVE_CLOSE_MESSAGE                = "Do you want to save the changes you made in the document \"{0}\"?";

    exports.OPEN_FILE                         = "Open File";
});


[submodule "src/thirdparty/CodeMirror2"]
	path = src/thirdparty/CodeMirror2
	url = git@github.com:adobe/CodeMirror2.git


define(function(require, exports, module) {

    function getTestRoot() {
        // /path/to/brackets/test/SpecRunner.html
        var path = window.location.href;
        path = path.substr("file://".length);
        path = path.substr(0,path.lastIndexOf("/"));

        return path;
    }

    function getTestPath(path) {
        return getTestRoot() + path;
    }

    function getBracketsSourceRoot() {
        var path = window.location.href;
        path = path.substr("file://".length).split("/");
        path = path.slice(0, length - 2);
        path.push("src");
        return path.join("/");
    }

    exports.getTestRoot             = getTestRoot;
    exports.getTestPath             = getTestPath;
    exports.getBracketsSourceRoot   = getBracketsSourceRoot;
});


- [FEATURE] Lock modes in Postgres now support `OF table`

- [FEATURE] New transaction lock modes `FOR KEY SHARE` and `NO KEY UPDATE` for Postgres 9.3+

- [FEATURE/REFACTOR] Rewritten scopes with complete support for includes and scopes across associations

- [BUG] .get() now passes along options correctly when using a custom getter

sequelize

Multi dialect ORM for Node.JS

mysql
sqlite
postgresql
postgres
mssql
orm
nodejs
object relational mapper


'use strict';

/* jshint -W030 */
var chai = require('chai')
  , Sequelize = require('../../index')
  , Promise = Sequelize.Promise
  , expect = chai.expect
  , Support = require(__dirname + '/support')
  , DataTypes = require(__dirname + '/../../lib/data-types')
  , _ = require('lodash')
  , dialect = Support.getTestDialect();

var sortById = function(a, b) {
  return a.id < b.id ? -1 : 1;
};

describe(Support.getTestDialectTeaser('Include'), function() {
  describe('find', function() {
    it('should support an empty belongsTo include', function() {
      var Company = this.sequelize.define('Company', {})
        , User = this.sequelize.define('User', {});

      User.belongsTo(Company, {as: 'Employer'});

      return this.sequelize.sync({force: true}).then(function() {
        return User.create();
      }).then(function() {
        return User.find({
          include: [{model: Company, as: 'Employer'}]
        }).then(function(user) {
          expect(user).to.be.ok;
        });
      });
    });

    it('should support a belongsTo association reference', function () {
      var Company = this.sequelize.define('Company', {})
        , User = this.sequelize.define('User', {})
        , Employer = User.belongsTo(Company, {as: 'Employer'});

      return this.sequelize.sync({force: true}).then(function() {
        return User.create();
      }).then(function () {
        return User.findOne({
          include: [Employer]
        }).then(function (user) {
          expect(user).to.be.ok;
        });
      });
    });

    it('should support a belongsTo association reference with a where', function () {
      var Company = this.sequelize.define('Company', {name: DataTypes.STRING})
        , User = this.sequelize.define('User', {})
        , Employer = User.belongsTo(Company, {as: 'Employer', foreignKey: 'employerId'});

      return this.sequelize.sync({force: true}).then(function() {
        return Company.create({
          name: 'CyberCorp'
        }).then(function (company) {
          return User.create({
            employerId: company.get('id')
          });
        });
      }).then(function () {
        return User.findOne({
          include: [
            {association: Employer, where: {name: 'CyberCorp'}}
          ]
        }).then(function (user) {
          expect(user).to.be.ok;
        });
      });
    });

    it('should support a empty hasOne include', function() {
      var Company = this.sequelize.define('Company', {})
        , Person = this.sequelize.define('Person', {});

      Company.hasOne(Person, {as: 'CEO'});

      return this.sequelize.sync({force: true}).then(function() {
        return Company.create().then(function() {
          return Company.find({
            include: [{model: Person, as: 'CEO'}]
          }).then(function(company) {
            expect(company).to.be.ok;
          });
        });
      });
    });

    it('should support a hasOne association reference', function () {
      var Company = this.sequelize.define('Company', {})
        , Person = this.sequelize.define('Person', {})
        , CEO = Company.hasOne(Person, {as: 'CEO'});

      return this.sequelize.sync({force: true}).then(function() {
        return Company.create();
      }).then(function () {
        return Company.find({
          include: [CEO]
        });
      }).then(function (user) {
        expect(user).to.be.ok;
      });
    });

    it('should support including a belongsTo association rather than a model/as pair', function() {
      var Company = this.sequelize.define('Company', {})
        , Person = this.sequelize.define('Person', {});

      Person.relation = {
        Employer: Person.belongsTo(Company, {as: 'employer'})
      };

      return this.sequelize.sync({force: true}).then(function() {
        return Promise.join(
          Person.create(),
          Company.create()
        ).spread(function(person, company) {
          return person.setEmployer(company);
        });
      }).then(function() {
        return Person.find({
          include: [Person.relation.Employer]
        }).then(function(person) {
          expect(person).to.be.ok;
          expect(person.employer).to.be.ok;
        });
      });
    });

    it('should support a hasMany association reference', function () {
      var User = this.sequelize.define('user', {})
        , Task = this.sequelize.define('task', {})
        , Tasks = User.hasMany(Task);

      Task.belongsTo(User);

      return this.sequelize.sync({force: true}).then(function () {
        return User.create().then(function (user) {
          return user.createTask();
        }).then(function () {
          return User.find({
            include: [Tasks]
          });
        }).then(function (user) {
          expect(user).to.be.ok;
          expect(user.tasks).to.be.ok;
        });
      });
    });

    it('should support a hasMany association reference with a where condition', function () {
      var User = this.sequelize.define('user', {})
        , Task = this.sequelize.define('task', {title: DataTypes.STRING})
        , Tasks = User.hasMany(Task);

      Task.belongsTo(User);

      return this.sequelize.sync({force: true}).then(function () {
        return User.create().then(function (user) {
          return Promise.join(
            user.createTask({
              title: 'trivial'
            }),
            user.createTask({
              title: 'pursuit'
            })
          );
        }).then(function () {
          return User.find({
            include: [
              {association: Tasks, where: {title: 'trivial'}}
            ]
          });
        }).then(function (user) {
          expect(user).to.be.ok;
          expect(user.tasks).to.be.ok;
          expect(user.tasks.length).to.equal(1);
        });
      });
    });

    it('should support a belongsToMany association reference', function () {
      var User = this.sequelize.define('user', {})
        , Group = this.sequelize.define('group', {})
        , Groups
        , Users;

      Groups = User.belongsToMany(Group, { through: 'UserGroup' });
      Users = Group.belongsToMany(User), { through: 'UserGroup' };

      return this.sequelize.sync({force: true}).then(function () {
        return User.create().then(function (user) {
          return user.createGroup();
        });
      }).then(function () {
        return User.find({
          include: [Groups]
        }).then(function (user) {
          expect(user).to.be.ok;
          expect(user.groups).to.be.ok;
        });
      });
    });

    it('should support a simple nested belongsTo -> belongsTo include', function() {
      var Task = this.sequelize.define('Task', {})
        , User = this.sequelize.define('User', {})
        , Group = this.sequelize.define('Group', {});

      Task.belongsTo(User);
      User.belongsTo(Group);

      return this.sequelize.sync({force: true}).then(function() {
        return Promise.props({
          task: Task.create(),
          user: User.create(),
          group: Group.create()
        }).then(function (props) {
          return Promise.join(
            props.task.setUser(props.user),
            props.user.setGroup(props.group)
          ).return(props);
        }).then(function (props) {
          return Task.findOne({
            where: {
              id: props.task.id
            },
            include: [
              {model: User, include: [
                {model: Group}
              ]}
            ]
          }).then(function(task) {
            expect(task.User).to.be.ok;
            expect(task.User.Group).to.be.ok;
          });
        });
      });
    });

    it('should support a simple sibling set of belongsTo include', function() {
      var Task = this.sequelize.define('Task', {})
        , User = this.sequelize.define('User', {})
        , Group = this.sequelize.define('Group', {});

      Task.belongsTo(User);
      Task.belongsTo(Group);

      return this.sequelize.sync({force: true}).then(function() {
        return Task.create({
          User: {},
          Group: {}
        }, {
          include: [User, Group]
        });
      }).then(function(task) {
        return Task.find({
          where: {
            id: task.id
          },
          include: [
            {model: User},
            {model: Group}
          ]
        });
      }).then(function(task) {
        expect(task.User).to.be.ok;
        expect(task.Group).to.be.ok;
      });
    });

    it('should support a simple nested hasOne -> hasOne include', function() {
      var Task = this.sequelize.define('Task', {})
        , User = this.sequelize.define('User', {})
        , Group = this.sequelize.define('Group', {});

      User.hasOne(Task);
      Group.hasOne(User);
      User.belongsTo(Group);

      return this.sequelize.sync({force: true}).then(function() {
        return User.create({
          Task: {},
          Group: {}
        }, {
          include: [Task, Group]
        });
      }).then(function(user) {
        return Group.find({
          where: {
            id: user.Group.id
          },
          include: [
            {model: User, include: [
              {model: Task}
            ]}
          ]
        });
      }).then(function(group) {
        expect(group.User).to.be.ok;
        expect(group.User.Task).to.be.ok;
      });
    });

    it('should support a simple nested hasMany -> belongsTo include', function() {
      var Task = this.sequelize.define('Task', {})
        , User = this.sequelize.define('User', {})
        , Project = this.sequelize.define('Project', {});

      User.hasMany(Task);
      Task.belongsTo(Project);

      return this.sequelize.sync({force: true}).then(function() {
        return Project.bulkCreate([{ id: 1 }, { id: 2 }]);
      }).then(function () {
        return User.create({
          Tasks: [
            {ProjectId: 1},
            {ProjectId: 2},
            {ProjectId: 1},
            {ProjectId: 2}
          ]
        }, {
          include: [Task]
        });
      }).then(function (user) {
        return User.find({
          where: {
            id: user.id
          },
          include: [
            {model: Task, include: [
              {model: Project}
            ]}
          ]
        });
      }).then(function(user) {
        expect(user.Tasks).to.be.ok;
        expect(user.Tasks.length).to.equal(4);

        user.Tasks.forEach(function(task) {
          expect(task.Project).to.be.ok;
        });
      });
    });

    it('should support a simple nested belongsTo -> hasMany include', function() {
      var Task = this.sequelize.define('Task', {})
        , Worker = this.sequelize.define('Worker', {})
        , Project = this.sequelize.define('Project', {});

      Worker.belongsTo(Project);
      Project.hasMany(Worker);
      Project.hasMany(Task);

      return this.sequelize.sync({force: true}).then(function() {
        return Project.create({
          Workers: [{}],
          Tasks: [{}, {}, {}, {}]
        }, {
          include: [Worker, Task]
        });
      }).then(function (project) {
        return Worker.find({
          where: {
            id: project.Workers[0].id
          },
          include: [
            {model: Project, include: [
              {model: Task}
            ]}
          ]
        });
      }).then(function(worker) {
        expect(worker.Project).to.be.ok;
        expect(worker.Project.Tasks).to.be.ok;
        expect(worker.Project.Tasks.length).to.equal(4);
      });
    });

    it('should support a simple nested hasMany <-> hasMany include', function() {
      var User = this.sequelize.define('User', {})
        , Product = this.sequelize.define('Product', {
            title: DataTypes.STRING
          })
        , Tag = this.sequelize.define('Tag', {
            name: DataTypes.STRING
          });

      User.hasMany(Product);
      Product.hasMany(Tag);
      Tag.hasMany(Product);

      return this.sequelize.sync({force: true}).then(function() {
        return Promise.all([
          User.create({
            id: 1,
            Products: [
              {title: 'Chair'},
              {title: 'Desk'},
              {title: 'Dress'},
              {title: 'Bed'}
            ]
          }, {
            include: [Product]
          }).then(function() {
            return Product.findAll({order: [['id']]});
          }),
          Tag.bulkCreate([
            {name: 'A'},
            {name: 'B'},
            {name: 'C'}
          ]).then(function() {
            return Tag.findAll({order: [['id']]});
          })
        ]);
      }).spread(function (products, tags) {
        return Promise.all([
          products[0].setTags([tags[0], tags[2]]),
          products[1].setTags([tags[1]]),
          products[2].setTags([tags[0], tags[1], tags[2]])
        ]);
      }).then(function () {
        return User.find({
          where: {
            id: 1
          },
          include: [
            {model: Product, include: [
              {model: Tag}
            ]}
          ],
          order: [
            User.rawAttributes.id,
            [Product, 'id']
          ]
        });
      }).then(function(user) {
        expect(user.Products.length).to.equal(4);
        expect(user.Products[0].Tags.length).to.equal(2);
        expect(user.Products[1].Tags.length).to.equal(1);
        expect(user.Products[2].Tags.length).to.equal(3);
        expect(user.Products[3].Tags.length).to.equal(0);
      });
    });

    it('should support an include with multiple different association types', function() {
      var User = this.sequelize.define('User', {})
        , Product = this.sequelize.define('Product', {
            title: DataTypes.STRING
          })
        , Tag = this.sequelize.define('Tag', {
            name: DataTypes.STRING
          })
        , Price = this.sequelize.define('Price', {
            value: DataTypes.FLOAT
          })
        , Group = this.sequelize.define('Group', {
            name: DataTypes.STRING
          })
        , GroupMember = this.sequelize.define('GroupMember', {

          })
        , Rank = this.sequelize.define('Rank', {
            name: DataTypes.STRING,
            canInvite: {
              type: DataTypes.INTEGER,
              defaultValue: 0
            },
            canRemove: {
              type: DataTypes.INTEGER,
              defaultValue: 0
            }
          });

      User.hasMany(Product);
      Product.belongsTo(User);

      Product.hasMany(Tag);
      Tag.hasMany(Product);
      Product.belongsTo(Tag, {as: 'Category'});

      Product.hasMany(Price);
      Price.belongsTo(Product);

      User.hasMany(GroupMember, {as: 'Memberships'});
      GroupMember.belongsTo(User);
      GroupMember.belongsTo(Rank);
      GroupMember.belongsTo(Group);
      Group.hasMany(GroupMember, {as: 'Memberships'});

      return this.sequelize.sync({force: true}).then(function() {
        return Promise.all([
          Product.create({
            id: 1,
            title: 'Chair',
            Prices: [{ value: 5 }, { value: 10 }  ]
          }, { include: [Price]}),
          Product.create({
            id: 2,
            title: 'Desk',
            Prices: [{ value: 5 }, { value: 10 }, { value: 15 }, { value: 20 }]
          }, { include: [Price]}),
          User.create({
            id: 1,
            Memberships: [
              { id: 1, Group: {name: 'Developers'}, Rank: {name: 'Admin', canInvite: 1, canRemove: 1}},
              { id: 2, Group: {name: 'Designers'}, Rank: {name: 'Member', canInvite: 1, canRemove: 0}}
            ]
          }, {
            include: { model: GroupMember, as: 'Memberships', include: [Group, Rank]}
          }),
          Tag.bulkCreate([
            {name: 'A'},
            {name: 'B'},
            {name: 'C'}
          ]).then(function() {
            return Tag.findAll();
          })
        ]);
      }).spread(function (product1, product2, user, tags) {
        return Promise.all([
          user.setProducts([product1, product2]),
          product1.setTags([tags[0], tags[2]]),
          product2.setTags([tags[1]]),
          product1.setCategory(tags[1])
        ]);
      }).then(function () {
        return User.find({
          where: {id: 1},
          include: [
            {model: GroupMember, as: 'Memberships', include: [
              Group,
              Rank
            ]},
            {model: Product, include: [
              Tag,
              {model: Tag, as: 'Category'},
              Price
            ]}
          ]
        });
      }).then(function(user) {
          user.Memberships.sort(sortById);
          expect(user.Memberships.length).to.equal(2);
          expect(user.Memberships[0].Group.name).to.equal('Developers');
          expect(user.Memberships[0].Rank.canRemove).to.equal(1);
          expect(user.Memberships[1].Group.name).to.equal('Designers');
          expect(user.Memberships[1].Rank.canRemove).to.equal(0);

          user.Products.sort(sortById);
          expect(user.Products.length).to.equal(2);
          expect(user.Products[0].Tags.length).to.equal(2);
          expect(user.Products[1].Tags.length).to.equal(1);
          expect(user.Products[0].Category).to.be.ok;
          expect(user.Products[1].Category).not.to.be.ok;

          expect(user.Products[0].Prices.length).to.equal(2);
          expect(user.Products[1].Prices.length).to.equal(4);
      });
    });

    it('should support specifying attributes', function() {
      var Project = this.sequelize.define('Project', {
        title: Sequelize.STRING
      });

      var Task = this.sequelize.define('Task', {
        title: Sequelize.STRING,
        description: Sequelize.TEXT
      });

      Project.hasMany(Task);
      Task.belongsTo(Project);

      return this.sequelize.sync({force: true}).then(function() {
        return Task.create({
          title: 'FooBar',
          Project: {title: 'BarFoo'}
        }, {
          include: [Project]
        });
      }).then(function() {
        return Task.findAll({
          attributes: ['title'],
          include: [
            {model: Project, attributes: ['title']}
          ]
        });
      }).then(function(tasks) {
        expect(tasks[0].title).to.equal('FooBar');
        expect(tasks[0].Project.title).to.equal('BarFoo');

        expect(_.omit(tasks[0].get(), 'Project')).to.deep.equal({ title: 'FooBar' });
        expect(tasks[0].Project.get()).to.deep.equal({ title: 'BarFoo'});
      });
    });

    it('should support Sequelize.literal and renaming of attributes in included model attributes', function() {
      var Post = this.sequelize.define('Post', {});
      var PostComment = this.sequelize.define('PostComment', {
        someProperty: Sequelize.VIRTUAL, // Since we specify the AS part as a part of the literal string, not with sequelize syntax, we have to tell sequelize about the field
        comment_title: Sequelize.STRING
      });

      Post.hasMany(PostComment);

      return this.sequelize.sync({ force: true }).then(function() {
        return Post.create({});
      }).then(function(post) {
        return post.createPostComment({
          comment_title: 'WAT'
        });
      }).then(function() {
        var findAttributes;
        if (dialect === 'mssql') {
          findAttributes = [
            Sequelize.literal('CAST(CASE WHEN EXISTS(SELECT 1) THEN 1 ELSE 0 END AS BIT) AS "PostComments.someProperty"'),
            [Sequelize.literal('CAST(CASE WHEN EXISTS(SELECT 1) THEN 1 ELSE 0 END AS BIT)'), 'someProperty2']
          ];
        } else {
          findAttributes = [
            Sequelize.literal('EXISTS(SELECT 1) AS "PostComments.someProperty"'),
            [Sequelize.literal('EXISTS(SELECT 1)'), 'someProperty2']
          ];
        }
        findAttributes.push(['comment_title', 'commentTitle']);

        return Post.findAll({
          include: [
            {
              model: PostComment,
              attributes: findAttributes
            }
          ]
        });
      }).then(function(posts) {
        expect(posts[0].PostComments[0].get('someProperty')).to.be.ok;
        expect(posts[0].PostComments[0].get('someProperty2')).to.be.ok;
        expect(posts[0].PostComments[0].get('commentTitle')).to.equal('WAT');
      });
    });

    it('should support self associated hasMany (with through) include', function() {
      var Group = this.sequelize.define('Group', {
        name: DataTypes.STRING
      });

      Group.hasMany(Group, { through: 'groups_outsourcing_companies', as: 'OutsourcingCompanies'});

      return this.sequelize.sync({force: true}).bind({}).then(function() {
        return Group.bulkCreate([
          {name: 'SoccerMoms'},
          {name: 'Coca Cola'},
          {name: 'Dell'},
          {name: 'Pepsi'}
        ]);
      }).then(function() {
        return Group.findAll();
      }).then(function(groups) {
        this.groups = groups;
        return groups[0].setOutsourcingCompanies(groups.slice(1));
      }).then(function() {
        return Group.find({
          where: {
            id: this.groups[0].id
          },
          include: [{model: Group, as: 'OutsourcingCompanies'}]
        });
      }).then(function(group) {
        expect(group.OutsourcingCompanies).to.have.length(3);
      });
    });

    it('should support including date fields, with the correct timeszone', function() {
      var User = this.sequelize.define('user', {
          dateField: Sequelize.DATE
        }, {timestamps: false})
        , Group = this.sequelize.define('group', {
          dateField: Sequelize.DATE
        }, {timestamps: false});

      User.hasMany(Group);
      Group.hasMany(User);

      return this.sequelize.sync({ force: true }).bind({}).then(function() {
        return Promise.all([
          User.create({ dateField: Date.UTC(2014, 1, 20) }),
          Group.create({ dateField: Date.UTC(2014, 1, 20) })
          ]);
      }).spread(function(user, group) {
        this.user = user;
        return user.addGroup(group);
      }).then(function() {
        return User.find({
          where: {
            id: this.user.id
          },
          include: [Group]
        });
      }).then(function(user) {
        expect(user.dateField.getTime()).to.equal(Date.UTC(2014, 1, 20));
        expect(user.groups[0].dateField.getTime()).to.equal(Date.UTC(2014, 1, 20));
      });
    });

    it('should support include when retrieving associated objects', function() {
      var User = this.sequelize.define('user', {
          name: DataTypes.STRING
        })
        , Group = this.sequelize.define('group', {
          name: DataTypes.STRING
        })
        , UserGroup = this.sequelize.define('user_group', {
          vip: DataTypes.INTEGER
        });

      User.hasMany(Group);
      Group.belongsTo(User);
      User.hasMany(Group, {
        through: UserGroup,
        as: 'Clubs'
      });
      Group.hasMany(User, {
        through: UserGroup,
        as: 'Members'
      });

      return this.sequelize.sync({ force: true }).bind({}).then(function() {
        return Promise.all([
          User.create({ name: 'Owner' }),
          User.create({ name: 'Member' }),
          Group.create({ name: 'Group' })
        ]);
      }).spread(function (owner, member, group) {
        this.owner = owner;
        this.member = member;
        this.group = group;
        return owner.addGroup(group);
      }).then(function() {
        return this.group.addMember(this.member);
      }).then(function() {
        return this.owner.getGroups({
          include: [{
            model: User,
            as: 'Members'
          }]
        });
      }).then(function(groups) {
        expect(groups.length).to.equal(1);
        expect(groups[0].Members[0].name).to.equal('Member');
      });
    });
  });

  var createUsersAndItems = function () {
   var User = this.sequelize.define('User', {})
    , Item = this.sequelize.define('Item', {'test': DataTypes.STRING});

    User.hasOne(Item);
    Item.belongsTo(User);

    this.User = User;
    this.Item = Item;

    return this.sequelize.sync({ force: true }).then(function() {
      return Promise.all([
        User.bulkCreate([{}, {}, {}]).then(function() {
          return User.findAll();
        }),
        Item.bulkCreate([
          {'test': 'abc'},
          {'test': 'def'},
          {'test': 'ghi'}
        ]).then(function() {
          return Item.findAll();
        })
      ]);
    }).spread(function (users, items) {
      return Promise.all([
        users[0].setItem(items[0]),
        users[1].setItem(items[1]),
        users[2].setItem(items[2])
      ]);
    });
  };

  describe('where', function() {
    beforeEach(function () {
      return createUsersAndItems.bind(this)();
    });

    it('should support Sequelize.and()', function() {
      return this.User.findAll({
        include: [
          {model: this.Item, where: Sequelize.and({ test: 'def' })}
        ]
      }).then(function(result) {
        expect(result.length).to.eql(1);
        expect(result[0].Item.test).to.eql('def');
      });
    });

    it('should support Sequelize.or()', function() {
      return expect(this.User.findAll({
        include: [
          {model: this.Item, where: Sequelize.or({
            test: 'def'
          }, {
            test: 'abc'
          })}
        ]
      })).to.eventually.have.length(2);
    });
  });

  describe('findAndCountAll', function() {
    it('should include associations to findAndCountAll', function() {
      return createUsersAndItems.bind(this)().bind(this).then(function () {
        return this.User.findAndCountAll({
          include: [
            {model: this.Item, where: {
              test: 'def'
            }}
          ]
        });
      }).then(function(result) {
        expect(result.count).to.eql(1);

        expect(result.rows.length).to.eql(1);
        expect(result.rows[0].Item.test).to.eql('def');
      });
    });
  });

  describe('association getter', function() {
    it('should support getting an include on a N:M association getter', function() {
      var Question = this.sequelize.define('Question', {})
        , Answer = this.sequelize.define('Answer', {})
        , Questionnaire = this.sequelize.define('Questionnaire', {});

      Question.hasMany(Answer);
      Answer.hasMany(Question);

      Questionnaire.hasMany(Question);
      Question.belongsTo(Questionnaire);

      return this.sequelize.sync({force: true}).then(function() {
        return Questionnaire.create();
      }).then(function(questionnaire) {
        return questionnaire.getQuestions({
          include: Answer
        });
      });
    });
  });
});


module.exports = function(sequelize, DataTypes) {
  return sequelize.define("Project", {
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  })
}


keep keep keep replace keep keep keep keep keep

Multi dialect ORM for Node.JS


'use strict';

/* jshint -W030 */
var chai = require('chai')
  , expect = chai.expect
  , Support = require(__dirname + '/../../support')
  , DataTypes = require(__dirname + '/../../../../lib/data-types')
  , dialect = Support.getTestDialect()
  , dbFile = __dirname + '/test.sqlite'
  , storages = [dbFile];

if (dialect === 'sqlite') {
  describe('[SQLITE Specific] DAOFactory', function() {
    after(function() {
      this.sequelize.options.storage = ':memory:';
    });

    beforeEach(function() {
      this.sequelize.options.storage = dbFile;
      this.User = this.sequelize.define('User', {
        age: DataTypes.INTEGER,
        name: DataTypes.STRING,
        bio: DataTypes.TEXT
      });
      return this.User.sync({ force: true });
    });

    storages.forEach(function(storage) {
      describe('with storage "' + storage + '"', function() {
        after(function() {
          if (storage === dbFile) {
            require('fs').writeFileSync(dbFile, '');
          }
        });

        describe('create', function() {
          it('creates a table entry', function() {
            var self = this;
            return this.User.create({ age: 21, name: 'John Wayne', bio: 'noot noot' }).then(function(user) {
              expect(user.age).to.equal(21);
              expect(user.name).to.equal('John Wayne');
              expect(user.bio).to.equal('noot noot');

              return self.User.findAll().then(function(users) {
                var usernames = users.map(function(user) {
                  return user.name;
                });
                expect(usernames).to.contain('John Wayne');
              });
            });
          });

          it('should allow the creation of an object with options as attribute', function() {
            var Person = this.sequelize.define('Person', {
              name: DataTypes.STRING,
              options: DataTypes.TEXT
            });

            return Person.sync({ force: true }).then(function() {
              var options = JSON.stringify({ foo: 'bar', bar: 'foo' });

              return Person.create({
                name: 'John Doe',
                options: options
              }).then(function(people) {
                expect(people.options).to.deep.equal(options);
              });
            });
          });

          it('should allow the creation of an object with a boolean (true) as attribute', function() {
            var Person = this.sequelize.define('Person', {
              name: DataTypes.STRING,
              has_swag: DataTypes.BOOLEAN
            });

            return Person.sync({ force: true }).then(function() {
              return Person.create({
                name: 'John Doe',
                has_swag: true
              }).then(function(people) {
                expect(people.has_swag).to.be.ok;
              });
            });
          });

          it('should allow the creation of an object with a boolean (false) as attribute', function() {
            var Person = this.sequelize.define('Person', {
              name: DataTypes.STRING,
              has_swag: DataTypes.BOOLEAN
            });

            return Person.sync({ force: true }).then(function() {
              return Person.create({
                name: 'John Doe',
                has_swag: false
              }).then(function(people) {
                expect(people.has_swag).to.not.be.ok;
              });
            });
          });
        });

        describe('.find', function() {
          beforeEach(function() {
            return this.User.create({name: 'user', bio: 'footbar'});
          });

          it('finds normal lookups', function() {
            return this.User.find({ where: { name: 'user' } }).then(function(user) {
              expect(user.name).to.equal('user');
            });
          });

          it.skip('should make aliased attributes available', function() {
            return this.User.find({ where: { name: 'user' }, attributes: ['id', ['name', 'username']] }).then(function(user) {
              expect(user.username).to.equal('user');
            });
          });
        });

        describe('.all', function() {
          beforeEach(function() {
            return this.User.bulkCreate([
              {name: 'user', bio: 'foobar'},
              {name: 'user', bio: 'foobar'}
            ]);
          });

          it('should return all users', function() {
            return this.User.findAll().then(function(users) {
              expect(users).to.have.length(2);
            });
          });
        });

        describe('.min', function() {
          it('should return the min value', function() {
            var self = this
              , users = [];

            for (var i = 2; i < 5; i++) {
              users[users.length] = {age: i};
            }

            return this.User.bulkCreate(users).then(function() {
              return self.User.min('age').then(function(min) {
                expect(min).to.equal(2);
              });
            });
          });
        });

        describe('.max', function() {
          it('should return the max value', function() {
            var self = this
              , users = [];

            for (var i = 2; i <= 5; i++) {
              users[users.length] = {age: i};
            }

            return this.User.bulkCreate(users).then(function() {
              return self.User.max('age').then(function(min) {
                expect(min).to.equal(5);
              });
            });
          });
        });
      });
    });
  });
}


test*.js
*.swp
.idea
.DS_STORE
node_modules
npm-debug.log
*~
test/binary/tmp/*
test/tmp/*
test/dialects/sqlite/test.sqlite
test/sqlite/test.sqlite
coverage-*
site


/*jslint node:true */
"use strict";

var Sequelize = require('sequelize');

// initialize database connection
var sequelize = new Sequelize('testsequelize', 'testsequelize', 'testsequelize', {
    dialect: 'postgres',
    port: 5432,
    define: {
        freezeTableName: true
    }
});

// load models
var models = [
    'Trainer',
    'Series',
    'Video'
];

models.forEach(function(model) {
    module.exports[model] = sequelize.import(__dirname + '/' + model);
});

// describe relationships
(function(m) {
    m.Series.hasOne(m.Video);
    m.Trainer.hasMany(m.Series);
})(module.exports);

// export connection
module.exports.sequelize = sequelize;