L.Control.Scale = L.Control.extend({
	options: {
		position: 'bottomleft',
		maxWidth: 100,
		metric: true,
		imperial: true,
		updateWhenIdle: false
	},

	onAdd: function (map) {
		this._map = map;

		var className = 'leaflet-control-scale',
		    container = L.DomUtil.create('div', className),
		    options = this.options;

		if (options.metric) {
			this._mScale = L.DomUtil.create('div', className + '-line', container);
		}
		if (options.imperial) {
			this._iScale = L.DomUtil.create('div', className + '-line', container);
		}

		map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
		this._update();

		return container;
	},

	onRemove: function (map) {
		map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
	},

	_update: function () {
		var bounds = this._map.getBounds(),
		    centerLat = bounds.getCenter().lat,
		    halfWorldMeters = new L.LatLng(centerLat, 0).distanceTo(new L.LatLng(centerLat, 180)),
		    dist = halfWorldMeters * (bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 180,

		    size = this._map.getSize(),
		    options = this.options,
		    maxMeters = 0;

		if (size.x > 0) {
			maxMeters = dist * (options.maxWidth / size.x);
		}

		if (options.metric && maxMeters) {
			this._updateMetric(maxMeters);
		}

		if (options.imperial && maxMeters) {
			this._updateImperial(maxMeters);
		}
	},

	_updateMetric: function (maxMeters) {
		var meters = this._getRoundNum(maxMeters);

		this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px';
		this._mScale.innerHTML = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';
	},

	_updateImperial: function (maxMeters) {
		var maxFeet = maxMeters * 3.2808399,
			scale = this._iScale,
			maxMiles, miles, feet;

		if (maxFeet > 5280) {
			maxMiles = maxFeet / 5280;
			miles = this._getRoundNum(maxMiles);

			scale.style.width = this._getScaleWidth(miles / maxMiles) + 'px';
			scale.innerHTML = miles + ' mi';

		} else {
			feet = this._getRoundNum(maxFeet);

			scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px';
			scale.innerHTML = feet + ' ft';
		}
	},

	_getScaleWidth: function (ratio) {
		return Math.round(this.options.maxWidth * ratio) - 10;
	},

	_getRoundNum: function (num) {
		var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
		    d = num / pow10;

		d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1;

		return pow10 * d;
	}
});

L.control.scale = function (options) {
	return new L.Control.Scale(options);
};


this._zoomToIfClose && this._zoomToIfClose(center, zoom) :

keep keep keep keep keep replace keep keep keep

if (done) {
clearTimeout(this._sizeTimer);
return this;
}

<!DOCTYPE html>

	<title>Leaflet debug page</title>

	<link rel="stylesheet" href="../../dist/leaflet.css" />

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

    <button onclick="group.removeLayer(path)">Remove path</button>
    <button onclick="group.removeLayer(circle)">Remove circle</button>
    <button onclick="group.clearLayers()">Remove all layers</button>


describe("Transformation", function() {
	var t, p;

	beforeEach(function() {
		t = new L.Transformation(1, 2, 3, 4);
		p = new L.Point(10, 20);
	});

	it("#transform should perform a transformation", function() {
		var p2 = t.transform(p, 2);
		expect(p2).toEqual(new L.Point(24, 128));
	});

	it("#untransform should perform a reverse transformation", function() {
		var p2 = t.transform(p, 2);
		var p3 = t.untransform(p2, 2);
		expect(p3).toEqual(p);
	});
});


keep keep keep keep replace replace replace replace keep keep keep keep

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

    // Load dependent modules
    var DocumentManager     = require("DocumentManager")
	, CommandManager        = require("CommandManager")
	, Commands              = require("Commands")
	,	EditorManager		= require("EditorManager")
    ,   NativeFileSystem    = require("NativeFileSystem").NativeFileSystem
    ;

    // Initialize: register listeners
    $(DocumentManager).on("currentDocumentChange", _onCurrentDocumentChange);

    function _onCurrentDocumentChange(event) {
        console.log("Current document changed!  --> "+DocumentManager.getCurrentDocument());
    }

    $(DocumentManager).on("workingSetAdd", function(event, addedDoc) {
        console.log("Working set ++ " + addedDoc);
        //console.log("  set: " + DocumentManager.getWorkingSet().join());

		_addDoc( addedDoc )

    });
    $(DocumentManager).on("workingSetRemove", function(event, removedDoc) {
        console.log("Working set -- " + removedDoc);
        //console.log("  set: " + DocumentManager.getWorkingSet().join());

		_removeDoc( removedDoc );
    });

    $(DocumentManager).on("dirtyFlagChange", function(event, doc ) {
        console.log("Dirty flag change: " + doc);

		_dirtyFlagChanged( doc );
    });

	/** Each list item in the working set stores a references to the related document in the list item's data.
	 *  Use listIem.data( _DOCUMENT_KEY ) to get the document reference
	 */
	var _DOCUMENT_KEY = "document";

	function _addDoc( doc ) {
		// Add new item to bottom of list
		var link = $("").attr( "href", "#" ).text( doc.file.name );
		var newItem = $("

").addClass("working-set-list-item").append( link );

		// TODO: Ask NJ which way is better
		//var newItem = $("
" + doc.file.name +  "
");

		newItem.data( _DOCUMENT_KEY, doc );

		$("#open-files-container").children("ul").append(newItem);

		newItem.click( function() {
			_openDoc( doc );
		});

		_updateFileStatusIcon( newItem, doc.isDirty, false);

		newItem.hover(
			// hover in
	        function() {
				_updateFileStatusIcon( $(this), doc.isDirty, true);
	        },
			// hover out
	        function() {
				_updateFileStatusIcon( $(this), doc.isDirty, false);
	        }
	    );
	}

    function _updateFileStatusIcon(listElement, isDirty, canClose) {
       var found = listElement.find(".file-status-icon");
       var fileStatusIcon = found.length != 0 ? $(found[0]) : null;
       var showIcon = isDirty || canClose;

       // remove icon if its not needed
       if (!showIcon && fileStatusIcon) {
           fileStatusIcon.remove();
           fileStatusIcon = null;
       }
       // create icon if its needed and doesn't exist
       else if (showIcon && !fileStatusIcon) {
           fileStatusIcon = $("

");
           fileStatusIcon.addClass("file-status-icon");
           listElement.prepend(fileStatusIcon);

		   fileStatusIcon.click( function() {
			   var doc = listElement.data( _DOCUMENT_KEY )
			   CommandManager.execute(Commands.FILE_CLOSE, doc.file.fullPath );
		   });
       }

       // Set icon's class
       if (fileStatusIcon) {
           fileStatusIcon.toggleClass("dirty", isDirty);
           fileStatusIcon.toggleClass("canClose", canClose);
       }
   }

   function _openDoc( doc ) {
	   CommandManager.execute(Commands.FILE_OPEN, doc.file.fullPath);

    }

   function _closeDoc( doc ) {
	   CommandManager.execute(Commands.FILE_CLOSE, doc.file.fullPath );
   }

   function _findListItemFromDocument( doc ) {
	   if( doc ){
		   $("#open-files-container").children().forEach( function( element, index, array ){
			   if(element.data( _DOCUMENT_KEY ) === doc)
			   	return element;
		   });
	   }

	   return null;
   }

	function _removeDoc( doc ) {
 	   var listIem = _findListItemFromDocument( doc );
 	   if(listIem){
 		   listItem.remove();
 	   }
	}

	function _dirtyFlagChanged( doc ){
		$("#" + doc.file.fullPath).find(".file-status-icon");
	}

	function _rebuild() {

	}

});


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Jasmine Spec Runner</title>

  <link rel="stylesheet" type="text/css" href="../jasmine.css">
  <script type="text/javascript" src="../jasmine.js"></script>
  <script type="text/javascript" src="../jasmine-html.js"></script>

  <!-- include spec files here... -->
  <script type="text/javascript" src="spec/SpecHelper.js"></script>
  <script type="text/javascript" src="spec/PlayerSpec.js"></script>

  <!-- include source files here... -->
  <script type="text/javascript" src="src/Player.js"></script>
  <script type="text/javascript" src="src/Song.js"></script>

  <script type="text/javascript">
    (function() {
      var jasmineEnv = jasmine.getEnv();
      jasmineEnv.updateInterval = 1000;

      var trivialReporter = new jasmine.TrivialReporter();

      jasmineEnv.addReporter(trivialReporter);

      jasmineEnv.specFilter = function(spec) {
        return trivialReporter.specFilter(spec);
      };

      var currentWindowOnload = window.onload;

      window.onload = function() {
        if (currentWindowOnload) {
          currentWindowOnload();
        }
        execJasmine();
      };

      function execJasmine() {
        jasmineEnv.execute();
      }

    })();
  </script>

</head>

<body>
</body>
</html>


Inconsolata by Raph Levien

Retrieved from: http://www.levien.com/type/myfonts/inconsolata.html

License: Open Font License
  http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&item_id=OFL&_sc=1


/* ============================================================
 * bootstrap-buttons.js v1.4.0
 * http://twitter.github.com/bootstrap/javascript.html#buttons
 * ============================================================
 * 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"

  function setState(el, state) {
    var d = 'disabled'
      , $el = $(el)
      , data = $el.data()

    state = state + 'Text'
    data.resetText || $el.data('resetText', $el.html())

    $el.html( data[state] || $.fn.button.defaults[state] )

    setTimeout(function () {
      state == 'loadingText' ?
        $el.addClass(d).attr(d, d) :
        $el.removeClass(d).removeAttr(d)
    }, 0)
  }

  function toggle(el) {
    $(el).toggleClass('active')
  }

  $.fn.button = function(options) {
    return this.each(function () {
      if (options == 'toggle') {
        return toggle(this)
      }
      options && setState(this, options)
    })
  }

  $.fn.button.defaults = {
    loadingText: 'loading...'
  }

  $(function () {
    $('body').delegate('.btn[data-toggle]', 'click', function () {
      $(this).button('toggle')
    })
  })

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


// default to the file the editor is showing

keep keep keep replace replace replace keep keep keep


/* Brackets / CodeMirror Code Formatting */

.CodeMirror-scroll {
    background-color: @background-color-3;
    .code-font();
}

.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;}
}


/* =========================================================
 * bootstrap-modal.js v1.4.0
 * http://twitter.github.com/bootstrap/javascript.html#modal
 * =========================================================
 * 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"
      }
    }

  })

 /* MODAL PUBLIC CLASS DEFINITION
  * ============================= */

  var Modal = function ( content, options ) {
    this.settings = $.extend({}, $.fn.modal.defaults, options)
    this.$element = $(content)
      .delegate('.close', 'click.modal', $.proxy(this.hide, this))

    if ( this.settings.show ) {
      this.show()
    }

    return this
  }

  Modal.prototype = {

      toggle: function () {
        return this[!this.isShown ? 'show' : 'hide']()
      }

    , show: function () {
        var that = this
        this.isShown = true
        this.$element.trigger('show')

        escape.call(this)
        backdrop.call(this, function () {
          var transition = $.support.transition && that.$element.hasClass('fade')

          that.$element
            .appendTo(document.body)
            .show()

          if (transition) {
            that.$element[0].offsetWidth // force reflow
          }

          that.$element.addClass('in')

          transition ?
            that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) :
            that.$element.trigger('shown')

        })

        return this
      }

    , hide: function (e) {
        e && e.preventDefault()

        if ( !this.isShown ) {
          return this
        }

        var that = this
        this.isShown = false

        escape.call(this)

        this.$element
          .trigger('hide')
          .removeClass('in')

        $.support.transition && this.$element.hasClass('fade') ?
          hideWithTransition.call(this) :
          hideModal.call(this)

        return this
      }

  }

 /* MODAL PRIVATE METHODS
  * ===================== */

  function hideWithTransition() {
    // firefox drops transitionEnd events :{o
    var that = this
      , timeout = setTimeout(function () {
          that.$element.unbind(transitionEnd)
          hideModal.call(that)
        }, 500)

    this.$element.one(transitionEnd, function () {
      clearTimeout(timeout)
      hideModal.call(that)
    })
  }

  function hideModal (that) {
    this.$element
      .hide()
      .trigger('hidden')

    backdrop.call(this)
  }

  function backdrop ( callback ) {
    var that = this
      , animate = this.$element.hasClass('fade') ? 'fade' : ''
    if ( this.isShown && this.settings.backdrop ) {
      var doAnimate = $.support.transition && animate

      this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
        .appendTo(document.body)

      if ( this.settings.backdrop != 'static' ) {
        this.$backdrop.click($.proxy(this.hide, this))
      }

      if ( doAnimate ) {
        this.$backdrop[0].offsetWidth // force reflow
      }

      this.$backdrop.addClass('in')

      doAnimate ?
        this.$backdrop.one(transitionEnd, callback) :
        callback()

    } else if ( !this.isShown && this.$backdrop ) {
      this.$backdrop.removeClass('in')

      $.support.transition && this.$element.hasClass('fade')?
        this.$backdrop.one(transitionEnd, $.proxy(removeBackdrop, this)) :
        removeBackdrop.call(this)

    } else if ( callback ) {
       callback()
    }
  }

  function removeBackdrop() {
    this.$backdrop.remove()
    this.$backdrop = null
  }

  function escape() {
    var that = this
    if ( this.isShown && this.settings.keyboard ) {
      $(document).bind('keyup.modal', function ( e ) {
        if ( e.which == 27 ) {
          that.hide()
        }
      })
    } else if ( !this.isShown ) {
      $(document).unbind('keyup.modal')
    }
  }

 /* MODAL PLUGIN DEFINITION
  * ======================= */

  $.fn.modal = function ( options ) {
    var modal = this.data('modal')

    if (!modal) {

      if (typeof options == 'string') {
        options = {
          show: /show|toggle/.test(options)
        }
      }

      return this.each(function () {
        $(this).data('modal', new Modal(this, options))
      })
    }

    if ( options === true ) {
      return modal
    }

    if ( typeof options == 'string' ) {
      modal[options]()
    } else if ( modal ) {
      modal.toggle()
    }

    return this
  }

  $.fn.modal.Modal = Modal

  $.fn.modal.defaults = {
    backdrop: false
  , keyboard: false
  , show: false
  }

 /* MODAL DATA- IMPLEMENTATION
  * ========================== */

  $(document).ready(function () {
    $('body').delegate('[data-controls-modal]', 'click', function (e) {
      e.preventDefault()
      var $this = $(this).data('show', true)
      $('#' + $this.attr('data-controls-modal')).modal( $this.data() )
    })
  })

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


/* ============================================================
 * bootstrap-dropdown.js v1.4.0
 * http://twitter.github.com/bootstrap/javascript.html#dropdown
 * ============================================================
 * 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"

  /* DROPDOWN PLUGIN DEFINITION
   * ========================== */

  $.fn.dropdown = function ( selector ) {
    return this.each(function () {
      $(this).delegate(selector || d, 'click', function (e) {
        var li = $(this).parent('li')
          , isActive = li.hasClass('open')

        clearMenus()
        !isActive && li.toggleClass('open')
        return false
      })
    })
  }

  /* APPLY TO STANDARD DROPDOWN ELEMENTS
   * =================================== */

  var d = 'a.menu, .dropdown-toggle'

  function clearMenus() {
    $(d).parent('li').removeClass('open')
  }

  $(function () {
    $('html').bind("click", clearMenus)
    $('body').dropdown( '[data-dropdown] a.menu, [data-dropdown] .dropdown-toggle' )
  })

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


console.log("Current document changed!  --> "+DocumentManager.getCurrentDocument());

$(DocumentManager).on("workingSetAdd", function(event, addedDoc) {

//console.log("  set: " + DocumentManager.getWorkingSet().join());

//console.log("Working set ++ " + addedDoc);


jasmine.HtmlReporterHelpers = {};

jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
  var el = document.createElement(type);

  for (var i = 2; i < arguments.length; i++) {
    var child = arguments[i];

    if (typeof child === 'string') {
      el.appendChild(document.createTextNode(child));
    } else {
      if (child) {
        el.appendChild(child);
      }
    }
  }

  for (var attr in attrs) {
    if (attr == "className") {
      el[attr] = attrs[attr];
    } else {
      el.setAttribute(attr, attrs[attr]);
    }
  }

  return el;
};

jasmine.HtmlReporterHelpers.getSpecStatus = function(child) {
  var results = child.results();
  var status = results.passed() ? 'passed' : 'failed';
  if (results.skipped) {
    status = 'skipped';
  }

  return status;
};

jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
  var parentDiv = this.dom.summary;
  var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
  var parent = child[parentSuite];

  if (parent) {
    if (typeof this.views.suites[parent.id] == 'undefined') {
      this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
    }
    parentDiv = this.views.suites[parent.id].element;
  }

  parentDiv.appendChild(childElement);
};

jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
  for(var fn in jasmine.HtmlReporterHelpers) {
    ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
  }
};

jasmine.HtmlReporter = function(_doc) {
  var self = this;
  var doc = _doc || window.document;

  var reporterView;

  var dom = {};

  // Jasmine Reporter Public Interface
  self.logRunningSpecs = false;

  self.reportRunnerStarting = function(runner) {
    var specs = runner.specs() || [];

    if (specs.length == 0) {
      return;
    }

    createReporterDom(runner.env.versionString());
    doc.body.appendChild(dom.reporter);

    reporterView = new jasmine.HtmlReporter.ReporterView(dom);
    reporterView.addSpecs(specs, self.specFilter);
  };

  self.reportRunnerResults = function(runner) {
    reporterView.complete();
  };

  self.reportSuiteResults = function(suite) {
    reporterView.suiteComplete(suite);
  };

  self.reportSpecStarting = function(spec) {
    if (self.logRunningSpecs) {
      self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
    }
  };

  self.reportSpecResults = function(spec) {
    reporterView.specComplete(spec);
  };

  self.log = function() {
    var console = jasmine.getGlobal().console;
    if (console && console.log) {
      if (console.log.apply) {
        console.log.apply(console, arguments);
      } else {
        console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
      }
    }
  };

  self.specFilter = function(spec) {
    if (!focusedSpecName()) {
      return true;
    }

    return spec.getFullName().indexOf(focusedSpecName()) === 0;
  };

  return self;

  function focusedSpecName() {
    var specName;

    (function memoizeFocusedSpec() {
      if (specName) {
        return;
      }

      var paramMap = [];
      var params = doc.location.search.substring(1).split('&');

      for (var i = 0; i < params.length; i++) {
        var p = params[i].split('=');
        paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
      }

      specName = paramMap.spec;
    })();

    return specName;
  }

  function createReporterDom(version) {
    dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
      dom.banner = self.createDom('div', { className: 'banner' },
        self.createDom('span', { className: 'title' }, "Jasmine "),
        self.createDom('span', { className: 'version' }, version)),

      dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
      dom.alert = self.createDom('div', {className: 'alert'}),
      dom.results = self.createDom('div', {className: 'results'},
        dom.summary = self.createDom('div', { className: 'summary' }),
        dom.details = self.createDom('div', { id: 'details' }))
    );
  }
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporterHelpers = {};

jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
  var el = document.createElement(type);

  for (var i = 2; i < arguments.length; i++) {
    var child = arguments[i];

    if (typeof child === 'string') {
      el.appendChild(document.createTextNode(child));
    } else {
      if (child) {
        el.appendChild(child);
      }
    }
  }

  for (var attr in attrs) {
    if (attr == "className") {
      el[attr] = attrs[attr];
    } else {
      el.setAttribute(attr, attrs[attr]);
    }
  }

  return el;
};

jasmine.HtmlReporterHelpers.getSpecStatus = function(child) {
  var results = child.results();
  var status = results.passed() ? 'passed' : 'failed';
  if (results.skipped) {
    status = 'skipped';
  }

  return status;
};

jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
  var parentDiv = this.dom.summary;
  var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
  var parent = child[parentSuite];

  if (parent) {
    if (typeof this.views.suites[parent.id] == 'undefined') {
      this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
    }
    parentDiv = this.views.suites[parent.id].element;
  }

  parentDiv.appendChild(childElement);
};

jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
  for(var fn in jasmine.HtmlReporterHelpers) {
    ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
  }
};

jasmine.HtmlReporter.ReporterView = function(dom) {
  this.startedAt = new Date();
  this.runningSpecCount = 0;
  this.completeSpecCount = 0;
  this.passedCount = 0;
  this.failedCount = 0;
  this.skippedCount = 0;

  this.createResultsMenu = function() {
    this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
      this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
      ' | ',
      this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));

    this.summaryMenuItem.onclick = function() {
      dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
    };

    this.detailsMenuItem.onclick = function() {
      showDetails();
    };
  };

  this.addSpecs = function(specs, specFilter) {
    this.totalSpecCount = specs.length;

    this.views = {
      specs: {},
      suites: {}
    };

    for (var i = 0; i < specs.length; i++) {
      var spec = specs[i];
      this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
      if (specFilter(spec)) {
        this.runningSpecCount++;
      }
    }
  };

  this.specComplete = function(spec) {
    this.completeSpecCount++;

    if (isUndefined(this.views.specs[spec.id])) {
      this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
    }

    var specView = this.views.specs[spec.id];

    switch (specView.status()) {
      case 'passed':
        this.passedCount++;
        break;

      case 'failed':
        this.failedCount++;
        break;

      case 'skipped':
        this.skippedCount++;
        break;
    }

    specView.refresh();
    this.refresh();
  };

  this.suiteComplete = function(suite) {
    var suiteView = this.views.suites[suite.id];
    if (isUndefined(suiteView)) {
      return;
    }
    suiteView.refresh();
  };

  this.refresh = function() {

    if (isUndefined(this.resultsMenu)) {
      this.createResultsMenu();
    }

    // currently running UI
    if (isUndefined(this.runningAlert)) {
      this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
      dom.alert.appendChild(this.runningAlert);
    }
    this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);

    // skipped specs UI
    if (isUndefined(this.skippedAlert)) {
      this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
    }

    this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";

    if (this.skippedCount === 1 && isDefined(dom.alert)) {
      dom.alert.appendChild(this.skippedAlert);
    }

    // passing specs UI
    if (isUndefined(this.passedAlert)) {
      this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
    }
    this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);

    // failing specs UI
    if (isUndefined(this.failedAlert)) {
      this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
    }
    this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);

    if (this.failedCount === 1 && isDefined(dom.alert)) {
      dom.alert.appendChild(this.failedAlert);
      dom.alert.appendChild(this.resultsMenu);
    }

    // summary info
    this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
    this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
  };

  this.complete = function() {
    dom.alert.removeChild(this.runningAlert);

    this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";

    if (this.failedCount === 0) {
      dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
    } else {
      showDetails();
    }

    dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
  };

  return this;

  function showDetails() {
    if (dom.reporter.className.search(/showDetails/) === -1) {
      dom.reporter.className += " showDetails";
    }
  }

  function isUndefined(obj) {
    return typeof obj === 'undefined';
  }

  function isDefined(obj) {
    return !isUndefined(obj);
  }

  function specPluralizedFor(count) {
    var str = count + " spec";
    if (count > 1) {
      str += "s"
    }
    return str;
  }

};

jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);

jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
  this.spec = spec;
  this.dom = dom;
  this.views = views;

  this.symbol = this.createDom('li', { className: 'pending' });
  this.dom.symbolSummary.appendChild(this.symbol);

  this.summary = this.createDom('div', { className: 'specSummary' },
      this.createDom('a', {
        className: 'description',
        href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
        title: this.spec.getFullName()
      }, this.spec.description)
  );

  this.detail = this.createDom('div', { className: 'specDetail' },
      this.createDom('a', {
        className: 'description',
        href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
        title: this.spec.getFullName()
      }, this.spec.getFullName())
  );
};

jasmine.HtmlReporter.SpecView.prototype.status = function() {
  return this.getSpecStatus(this.spec);
};

jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
  this.symbol.className = this.status();

  switch (this.status()) {
    case 'skipped':
      break;

    case 'passed':
      this.appendSummaryToSuiteDiv();
      break;

    case 'failed':
      this.appendSummaryToSuiteDiv();
      this.appendFailureDetail();
      break;
  }
};

jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
  this.summary.className += ' ' + this.status();
  this.appendToSummary(this.spec, this.summary);
};

jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
  this.detail.className += ' ' + this.status();

  var resultItems = this.spec.results().getItems();
  var messagesDiv = this.createDom('div', { className: 'messages' });

  for (var i = 0; i < resultItems.length; i++) {
    var result = resultItems[i];

    if (result.type == 'log') {
      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
    } else if (result.type == 'expect' && result.passed && !result.passed()) {
      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));

      if (result.trace.stack) {
        messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
      }
    }
  }

  if (messagesDiv.childNodes.length > 0) {
    this.detail.appendChild(messagesDiv);
    this.dom.details.appendChild(this.detail);
  }
};

jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
  this.suite = suite;
  this.dom = dom;
  this.views = views;

  this.element = this.createDom('div', { className: 'suite' },
      this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
  );

  this.appendToSummary(this.suite, this.element);
};

jasmine.HtmlReporter.SuiteView.prototype.status = function() {
  return this.getSpecStatus(this.suite);
};

jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
  this.element.className += " " + this.status();
};

jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);

/* @deprecated Use jasmine.HtmlReporter instead
 */
jasmine.TrivialReporter = function(doc) {
  this.document = doc || document;
  this.suiteDivs = {};
  this.logRunningSpecs = false;
};

jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
  var el = document.createElement(type);

  for (var i = 2; i < arguments.length; i++) {
    var child = arguments[i];

    if (typeof child === 'string') {
      el.appendChild(document.createTextNode(child));
    } else {
      if (child) { el.appendChild(child); }
    }
  }

  for (var attr in attrs) {
    if (attr == "className") {
      el[attr] = attrs[attr];
    } else {
      el.setAttribute(attr, attrs[attr]);
    }
  }

  return el;
};

jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
  var showPassed, showSkipped;

  this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' },
      this.createDom('div', { className: 'banner' },
        this.createDom('div', { className: 'logo' },
            this.createDom('span', { className: 'title' }, "Jasmine"),
            this.createDom('span', { className: 'version' }, runner.env.versionString())),
        this.createDom('div', { className: 'options' },
            "Show ",
            showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
            this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
            showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
            this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
            )
          ),

      this.runnerDiv = this.createDom('div', { className: 'runner running' },
          this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
          this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
          this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
      );

  this.document.body.appendChild(this.outerDiv);

  var suites = runner.suites();
  for (var i = 0; i < suites.length; i++) {
    var suite = suites[i];
    var suiteDiv = this.createDom('div', { className: 'suite' },
        this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
        this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
    this.suiteDivs[suite.id] = suiteDiv;
    var parentDiv = this.outerDiv;
    if (suite.parentSuite) {
      parentDiv = this.suiteDivs[suite.parentSuite.id];
    }
    parentDiv.appendChild(suiteDiv);
  }

  this.startedAt = new Date();

  var self = this;
  showPassed.onclick = function(evt) {
    if (showPassed.checked) {
      self.outerDiv.className += ' show-passed';
    } else {
      self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
    }
  };

  showSkipped.onclick = function(evt) {
    if (showSkipped.checked) {
      self.outerDiv.className += ' show-skipped';
    } else {
      self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
    }
  };
};

jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
  var results = runner.results();
  var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
  this.runnerDiv.setAttribute("class", className);
  //do it twice for IE
  this.runnerDiv.setAttribute("className", className);
  var specs = runner.specs();
  var specCount = 0;
  for (var i = 0; i < specs.length; i++) {
    if (this.specFilter(specs[i])) {
      specCount++;
    }
  }
  var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
  message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
  this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);

  this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
};

jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
  var results = suite.results();
  var status = results.passed() ? 'passed' : 'failed';
  if (results.totalCount === 0) { // todo: change this to check results.skipped
    status = 'skipped';
  }
  this.suiteDivs[suite.id].className += " " + status;
};

jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
  if (this.logRunningSpecs) {
    this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
  }
};

jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
  var results = spec.results();
  var status = results.passed() ? 'passed' : 'failed';
  if (results.skipped) {
    status = 'skipped';
  }
  var specDiv = this.createDom('div', { className: 'spec '  + status },
      this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
      this.createDom('a', {
        className: 'description',
        href: '?spec=' + encodeURIComponent(spec.getFullName()),
        title: spec.getFullName()
      }, spec.description));

  var resultItems = results.getItems();
  var messagesDiv = this.createDom('div', { className: 'messages' });
  for (var i = 0; i < resultItems.length; i++) {
    var result = resultItems[i];

    if (result.type == 'log') {
      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
    } else if (result.type == 'expect' && result.passed && !result.passed()) {
      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));

      if (result.trace.stack) {
        messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
      }
    }
  }

  if (messagesDiv.childNodes.length > 0) {
    specDiv.appendChild(messagesDiv);
  }

  this.suiteDivs[spec.suite.id].appendChild(specDiv);
};

jasmine.TrivialReporter.prototype.log = function() {
  var console = jasmine.getGlobal().console;
  if (console && console.log) {
    if (console.log.apply) {
      console.log.apply(console, arguments);
    } else {
      console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
    }
  }
};

jasmine.TrivialReporter.prototype.getLocation = function() {
  return this.document.location;
};

jasmine.TrivialReporter.prototype.specFilter = function(spec) {
  var paramMap = {};
  var params = this.getLocation().search.substring(1).split('&');
  for (var i = 0; i < params.length; i++) {
    var p = params[i].split('=');
    paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
  }

  if (!paramMap.spec) {
    return true;
  }
  return spec.getFullName().indexOf(paramMap.spec) === 0;
};


/* ==========================================================
 * bootstrap-alerts.js v1.4.0
 * http://twitter.github.com/bootstrap/javascript.html#alerts
 * ==========================================================
 * 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"
       }
     }

   })

 /* ALERT CLASS DEFINITION
  * ====================== */

  var Alert = function ( content, options ) {
    if (options == 'close') return this.close.call(content)
    this.settings = $.extend({}, $.fn.alert.defaults, options)
    this.$element = $(content)
      .delegate(this.settings.selector, 'click', this.close)
  }

  Alert.prototype = {

    close: function (e) {
      var $element = $(this)
        , className = 'alert-message'

      $element = $element.hasClass(className) ? $element : $element.parent()

      e && e.preventDefault()
      $element.removeClass('in')

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

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

  }

 /* ALERT PLUGIN DEFINITION
  * ======================= */

  $.fn.alert = function ( options ) {

    if ( options === true ) {
      return this.data('alert')
    }

    return this.each(function () {
      var $this = $(this)
        , data

      if ( typeof options == 'string' ) {

        data = $this.data('alert')

        if (typeof data == 'object') {
          return data[options].call( $this )
        }

      }

      $(this).data('alert', new Alert( this, options ))

    })
  }

  $.fn.alert.defaults = {
    selector: '.close'
  }

  $(document).ready(function () {
    new Alert($('body'), {
      selector: '.alert-message[data-alert] .close'
    })
  })

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


/* =============================================================
 * bootstrap-scrollspy.js v1.4.0
 * http://twitter.github.com/bootstrap/javascript.html#scrollspy
 * =============================================================
 * 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"

  var $window = $(window)

  function ScrollSpy( topbar, selector ) {
    var processScroll = $.proxy(this.processScroll, this)
    this.$topbar = $(topbar)
    this.selector = selector || 'li > a'
    this.refresh()
    this.$topbar.delegate(this.selector, 'click', processScroll)
    $window.scroll(processScroll)
    this.processScroll()
  }

  ScrollSpy.prototype = {

      refresh: function () {
        this.targets = this.$topbar.find(this.selector).map(function () {
          var href = $(this).attr('href')
          return /^#\w/.test(href) && $(href).length ? href : null
        })

        this.offsets = $.map(this.targets, function (id) {
          return $(id).offset().top
        })
      }

    , processScroll: function () {
        var scrollTop = $window.scrollTop() + 10
          , offsets = this.offsets
          , targets = this.targets
          , activeTarget = this.activeTarget
          , i

        for (i = offsets.length; i--;) {
          activeTarget != targets[i]
            && scrollTop >= offsets[i]
            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
            && this.activateButton( targets[i] )
        }
      }

    , activateButton: function (target) {
        this.activeTarget = target

        this.$topbar
          .find(this.selector).parent('.active')
          .removeClass('active')

        this.$topbar
          .find(this.selector + '[href="' + target + '"]')
          .parent('li')
          .addClass('active')
      }

  }

  /* SCROLLSPY PLUGIN DEFINITION
   * =========================== */

  $.fn.scrollSpy = function( options ) {
    var scrollspy = this.data('scrollspy')

    if (!scrollspy) {
      return this.each(function () {
        $(this).data('scrollspy', new ScrollSpy( this, options ))
      })
    }

    if ( options === true ) {
      return scrollspy
    }

    if ( typeof options == 'string' ) {
      scrollspy[options]()
    }

    return this
  }

  $(document).ready(function () {
    $('body').scrollSpy('[data-scrollspy] li > a')
  })

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


/** Each list item in the working set stores a references to the related document in the list item's data.

*  Use listIem.data( _DOCUMENT_KEY ) to get the document reference

$(DocumentManager).on("currentDocumentChange", function(event, doc ) {

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

// TODO: break out the definition of brackets into a separate module from the application controller logic
define(function(require, exports, module) {
    // Load dependent non-module scripts
    require("widgets/bootstrap-dropdown");
    require("widgets/bootstrap-modal");

    // Load dependent modules
    var PreferencesManager      = require("PreferencesManager")
    ,   ProjectManager          = require("ProjectManager")
    ,   EditorManager           = require("EditorManager")
	,   WorkingSetView          = require("WorkingSetView")
    ,   FileCommandHandlers     = require("FileCommandHandlers")
    ,   KeyBindingManager       = require("KeyBindingManager").KeyBindingManager
    ,   KeyMap                  = require("KeyBindingManager").KeyMap
    ,   Commands                = require("Commands")
    ;

    // Define core brackets namespace
    brackets = window.brackets || {};

    // TODO: Make sure the "test" object is not included in final builds
    // All modules that need to be tested from the context of the application
    // must to be added to this object. The unit tests cannot just pull
    // in the modules since they would run in context of the unit test window,
    // and would not have access to the app html/css.
    brackets.test =
        { ProjectManager        : ProjectManager
        , FileCommandHandlers   : FileCommandHandlers
        , Commands              : Commands
        , CommandManager        : require("CommandManager")
        };

    brackets.inBrowser = !brackets.hasOwnProperty("fs");

    brackets.DIALOG_BTN_CANCEL = "cancel";
    brackets.DIALOG_BTN_OK = "ok";
    brackets.DIALOG_BTN_DONTSAVE = "dontsave";

    brackets.DIALOG_ID_ERROR = "error-dialog";
    brackets.DIALOG_ID_SAVE_CLOSE = "save-close-dialog";

    /**
     * General purpose modal dialog. Assumes that the HTML for the dialog contains elements with "title"
     * and "message" classes, as well as a number of elements with "dialog-button" class, each of which has
     * a "data-button-id".
     *
     * @param {string} id The ID of the dialog node in the HTML.
     * @param {string} title The title of the error dialog. Can contain HTML markup.
     * @param {string} message The message to display in the error dialog. Can contain HTML markup.
     * @return {Deferred} a $.Deferred() that will be resolved with the ID of the clicked button when the dialog
     *     is dismissed.
     */
    brackets.showModalDialog = function(id, title, message, callback) {
        var result = $.Deferred();
        var dlg = $("#" + id);

        // Set title and message
        $(".dialog-title", dlg).html(title);
        $(".dialog-message", dlg).html(message);

        // Click handler for buttons
        dlg.on("click", ".dialog-button", function(e) {
            result.resolve($(this).attr("data-button-id"));
            dlg.modal(true).hide();
        });

        // Enter/Return handler for the primary button. Need to
        // add both keydown and keyup handlers here to make sure
        // the enter key was pressed while the dialog was showing.
        // Otherwise, if a keydown or keypress from somewhere else
        // triggered an alert, the keyup could immediately dismiss it.
        var enterKeyPressed = false;
        $(document).on("keydown.modal", function(e) {
            if (e.keyCode === 13) {
                enterKeyPressed = true;
            }
        }).on("keyup.modal", function(e) {
            if (e.keyCode === 13 && enterKeyPressed) {
                var primaryBtn = dlg.find(".primary");
                if (primaryBtn) {
                    result.resolve(primaryBtn.attr("data-button-id"));
                    dlg.modal(true).hide();
                }
            }
            enterKeyPressed = false;
        });

        // Run the dialog
        dlg.modal(
            { backdrop: "static"
            , show: true
            }
        ).on("hide", function(e) {
            // Remove all handlers in the .modal namespace
            $(document).off(".modal");
        });
        return result;
    };

    $(document).ready(function() {

        EditorManager.setEditorArea( $('#editorHolder') );

        initProject();
        initMenus();
        initCommandHandlers();
        initKeyBindings();

        function initProject() {
            ProjectManager.loadProject();

            // Open project button
            $("#btn-open-project").click(function() {
                ProjectManager.openProject();
            });

            // Handle toggling top level disclosure arrows of file list area
            $("#open-files-disclosure-arrow").click(function(){
                $(this).toggleClass( "disclosure-arrow-closed");
                $("#open-files-container").toggle();
            });
            // Display close "x" icon when user hovers over working set file
            $(".working-set-list-item").hover(
                function() {
                    $(this).prepend("

");
                },
                function() {
                    $(this).children(".file-status-icon").remove();
                }
            );

            $(".file-status-icon").click( function() {
                // close file
            });

        }

        function initMenus() {
            // Implements the File menu items
            $("#menu-file-new").click(function() {
                CommandManager.execute(Commands.FILE_NEW);
            });
            $("#menu-file-open").click(function() {
                CommandManager.execute(Commands.FILE_OPEN);
            });
            $("#menu-file-close").click(function() {
                CommandManager.execute(Commands.FILE_CLOSE);
            });
            $("#menu-file-save").click(function() {
                CommandManager.execute(Commands.FILE_SAVE);
            });

            // Implements the 'Run Tests' menu to bring up the Jasmine unit test window
            var testWindow = null;
            $("#menu-debug-runtests").click(function(){
                if (!(testWindow === null)) {
                    try {
                        testWindow.location.reload();
                    } catch(e) {
                        testWindow = null;  // the window was probably closed
                    }
                }

                if (testWindow === null) {
                    testWindow = window.open("../test/SpecRunner.html");
                    testWindow.location.reload(); // if it was opened before, we need to reload because it will be cached
                }
            });

            // Other debug menu items
            $("#menu-debug-wordwrap").click(function() {
                editor.setOption("lineWrapping", !(editor.getOption("lineWrapping")));
            });
        }

        function initCommandHandlers() {
            FileCommandHandlers.init( $("#main-toolbar .title") );
        }

        function initKeyBindings() {
            // Register keymaps and install the keyboard handler
            // TODO: show keyboard equivalents in the menus
            var _globalKeymap = new KeyMap(
                { "Ctrl-O": Commands.FILE_OPEN
                , "Ctrl-S": Commands.FILE_SAVE
                , "Ctrl-W": Commands.FILE_CLOSE
                }
            );
            KeyBindingManager.installKeymap(_globalKeymap);

            $(document.body).keydown(function(event) {
                var keyDescriptor = [];
                if (event.metaKey || event.ctrlKey) {
                    keyDescriptor.push("Ctrl");
                }
                if (event.altKey) {
                    keyDescriptor.push("Alt");
                }
                if (event.shiftKey) {
                    keyDescriptor.push("Shift");
                }
                keyDescriptor.push(String.fromCharCode(event.keyCode).toUpperCase());
                if (KeyBindingManager.handleKey(keyDescriptor.join("-"))) {
                    event.preventDefault();
                }
            });
        }
    });

    $(window).unload(function () {
        PreferencesManager.savePreferences();
    });
});


/* Variables.less
 * Variables to customize the look and feel of Bootstrap
 * ----------------------------------------------------- */

// Links
@linkColor:         #0069d6;
@linkColorHover:    darken(@linkColor, 15);

// Grays
@black:             #000;
@grayDark:          lighten(@black, 25%);
@gray:              lighten(@black, 50%);
@grayLight:         lighten(@black, 75%);
@grayLighter:       lighten(@black, 90%);
@white:             #fff;

// Accent Colors
@blue:              #049CDB;
@blueDark:          #0064CD;
@green:             #46a546;
@red:               #9d261d;
@yellow:            #ffc40d;
@orange:            #f89406;
@pink:              #c3325f;
@purple:            #7a43b6;

// Baseline grid
@basefont:          13px;
@baseline:          18px;

// Griditude
// Modify the grid styles in mixins.less
@gridColumns:       16;
@gridColumnWidth:   40px;
@gridGutterWidth:   20px;
@extraSpace:        (@gridGutterWidth * 2); // For our grid calculations
@siteWidth:         (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1));

// Color Scheme
// Use this to roll your own color schemes if you like (unused by Bootstrap by default)
@baseColor:         @blue;                  // Set a base color
@complement:        spin(@baseColor, 180);  // Determine a complementary color
@split1:            spin(@baseColor, 158);  // Split complements
@split2:            spin(@baseColor, -158);
@triad1:            spin(@baseColor, 135);  // Triads colors
@triad2:            spin(@baseColor, -135);
@tetra1:            spin(@baseColor, 90);   // Tetra colors
@tetra2:            spin(@baseColor, -90);
@analog1:           spin(@baseColor, 22);   // Analogs colors
@analog2:           spin(@baseColor, -22);

// More variables coming soon:
// - @basefont to @baseFontSize
// - @baseline to @baseLineHeight
// - @baseFontFamily
// - @primaryButtonColor
// - anything else? File an issue on GitHub


beforeEach(function() {
  this.addMatchers({
    toBePlaying: function(expectedSong) {
      var player = this.actual;
      return player.currentlyPlayingSong === expectedSong &&
             player.isPlaying;
    }
  });
});


var listItem = _findListItemFromDocument( doc );


#!/bin/bash
BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

echo $BASEDIR

# open the Jasmine SpecRunner
open ${BASEDIR}/../../bin/mac/Brackets.app --args file:///${BASEDIR}/SpecRunner.html


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

/**
 * EditorManager owns the UI for the editor area and working set list. This essentially mirrors
 * the model in DocumentManager, which maintains a list of 'open' documents  (the working set) and
 * a 'current document' (what is shown in the editor area).
 */
define(function(require, exports, module) {

    // Load dependent modules
    var DocumentManager     = require("DocumentManager")
    ,   NativeFileSystem    = require("NativeFileSystem").NativeFileSystem
    ;

    // Initialize: register listeners
    $(DocumentManager).on("currentDocumentChange", _onCurrentDocumentChange);

    var _editorHolder = null;
    var _currentEditor = null;

    function _onCurrentDocumentChange(event) {
        console.log("Current document changed!  --> "+DocumentManager.getCurrentDocument());

        var doc = DocumentManager.getCurrentDocument();

        if (doc) {
            _showEditor(doc);
        } else {
            _showNoEditor();
        }
    }

    $(DocumentManager).on("workingSetAdd", function(event, addedDoc) {
        console.log("Working set ++ " + addedDoc);
        //console.log("  set: " + DocumentManager.getWorkingSet().join());

    });

    $(DocumentManager).on("workingSetRemove", function(event, removedDoc) {
        console.log("Working set -- " + removedDoc);
        //console.log("  set: " + DocumentManager.getWorkingSet().join());

    });

    $(DocumentManager).on("dirtyFlagChange", function(event, doc ) {
        console.log("Dirty flag change: " + doc);

    });

    /**
     * Designates the DOM node that will contain the currently active editor instance. EditorManager
     * will own the content of this DOM node.
     * @param {jQueryObject} holder
     */
    function setEditorArea(holder) {
        if (_currentEditor)
            throw new Error("Cannot change editor area after an editor has already been created!");

        _editorHolder = holder;
    }

    function createEditor(text) {
        var editor = CodeMirror(_editorHolder.get(0));

        // Apply NJ's editor-resizing fix
        // FIXME: is it bad to resize ALL editors, even invisible ones?
        // FIXME: remove listener when editor is destroyed
        var _resizeTimeout = null;
        $(window).resize(_updateEditorSize);

        function _updateEditorSize() {
            // Don't refresh every single time.
            if (!_resizeTimeout) {
                _resizeTimeout = setTimeout(function() {
                    editor.refresh();
                    _resizeTimeout = null;
                }, 100);
            }
            $('.CodeMirror-scroll', _editorHolder)
                .height(_editorHolder.height());
        }
        _updateEditorSize();

        // Initially populate with text. This will send a spurious change event, but that's ok
        // because no one's listening yet (and we clear the undo stack below)
        editor.setValue(text);

        // Make sure we can't undo back to the empty state before setValue()
        editor.clearHistory();

        return editor;
    }

    function destroyEditor(editor) {
        if (_currentEditor == editor)
            throw new Error("Shouldn't destroy the visible editor. See DocumentManager.closeDocument()");

        // Destroy the editor widget: CodeMirror docs for getWrapperElement() say all you have to do
        // is "Remove this from your tree to delete an editor instance."
        _editorHolder.get(0).removeChild( editor.getWrapperElement() );
    }

    function _showEditor(document) {
        // Hide whatever was visible before
        if (_currentEditor == null) {
            $("#notEditor").css("display","none");
        } else {
            $(_currentEditor.getWrapperElement()).css("display","none");
        }

        // Show new editor
        _currentEditor = document._editor;
        $(_currentEditor.getWrapperElement()).css("display", "");
    }
    function _showNoEditor() {
        if (_currentEditor != null) {
            $(_currentEditor.getWrapperElement()).css("display","none");
            _currentEditor = null;
            $("#notEditor").css("display","");
        }
    }

    function focusEditor() {
        if (_currentEditor != null)
            _currentEditor.focus();
    }

    // Define public API
    exports.setEditorArea = setEditorArea;
    exports.createEditor = createEditor;
    exports.destroyEditor = destroyEditor;
    exports.focusEditor = focusEditor;

});


define(function(require, exports, module) {

    var EditorUtils = require("EditorUtils");

    describe("Editor", function(){
        var content = 'Brackets is going to be awesome!\n';

        describe("CodeMirror", function() {
            var myCodeMirror;

            beforeEach(function() {
                // init CodeMirror instance
                $("body").append("<div id='editor'/>");
                myCodeMirror = CodeMirror($("#editor").get(0), {
                    value: content
                });
            });

            afterEach(function() {
                $("#editor").remove();
                myCodeMirror = null;
            });

            it("should initialize with content", function() {
                // verify editor content
                expect(myCodeMirror.getValue()).toEqual(content);
            });

            describe("Modes", function() {
                it("should switch to the HTML mode for files ending in .html", function() {
                    // verify editor content
                    EditorUtils.setModeFromFileExtension(myCodeMirror, "file:///only/testing/the/path.html");
                    expect(myCodeMirror.getOption("mode")).toEqual("htmlmixed");
                });

                it("should switch modes even if the url has a query string", function() {
                    // verify editor content
                    EditorUtils.setModeFromFileExtension(myCodeMirror, "http://only.org/testing/the/path.css?v=2");
                    expect(myCodeMirror.getOption("mode")).toEqual("css");
                });

                it("should accecpt just a file name too", function() {
                    // verify editor content
                    EditorUtils.setModeFromFileExtension(myCodeMirror, "path.js");
                    expect(myCodeMirror.getOption("mode")).toEqual("javascript");
                });

                it("should default to plaintext for unknown file extensions", function() {
                    // verify editor content
                    EditorUtils.setModeFromFileExtension(myCodeMirror, "test.foo");
                    expect(myCodeMirror.getOption("mode")).toEqual("");
                });
            });
        });
    });
});


function _findListItemFromDocument( doc ) {


/* Reset.less
 * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here	that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc).
 * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */

// ERIC MEYER RESET
// --------------------------------------------------

html, body { margin: 0; padding: 0; }
h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, cite, code, del, dfn, em, img, q, s, samp, small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, form, label, legend, button, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-weight: normal; font-style: normal; font-size: 100%; line-height: 1; font-family: inherit; }
table { border-collapse: collapse; border-spacing: 0; }
ol, ul { list-style: none; }
q:before, q:after, blockquote:before, blockquote:after { content: ""; }

// Normalize.css
// Pulling in select resets form the normalize.css project
// --------------------------------------------------

// Display in IE6-9 and FF3
// -------------------------
// Source: http://github.com/necolas/normalize.css
html {
  overflow-y: scroll;
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
      -ms-text-size-adjust: 100%;
}
// Focus states
a:focus {
  outline: thin dotted;
}
// Hover & Active
a:hover,
a:active {
  outline: 0;
}

// Display in IE6-9 and FF3
// -------------------------
// Source: http://github.com/necolas/normalize.css
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section {
  display: block;
}

// Display block in IE6-9 and FF3
// -------------------------
// Source: http://github.com/necolas/normalize.css
audio,
canvas,
video {
  display: inline-block;
  *display: inline;
  *zoom: 1;
}

// Prevents modern browsers from displaying 'audio' without controls
// -------------------------
// Source: http://github.com/necolas/normalize.css
audio:not([controls]) {
    display: none;
}

// Prevents sub and sup affecting line-height in all browsers
// -------------------------
// Source: http://github.com/necolas/normalize.css
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}
sup {
  top: -0.5em;
}
sub {
  bottom: -0.25em;
}

// Img border in a's and image quality
// -------------------------
// Source: http://github.com/necolas/normalize.css
img {
    border: 0;
    -ms-interpolation-mode: bicubic;
}

// Forms
// -------------------------
// Source: http://github.com/necolas/normalize.css

// Font size in all browsers, margin changes, misc consistency
button,
input,
select,
textarea {
  font-size: 100%;
  margin: 0;
  vertical-align: baseline;
  *vertical-align: middle;
}
button,
input {
  line-height: normal; // FF3/4 have !important on line-height in UA stylesheet
  *overflow: visible; // Inner spacing ie IE6/7
}
button::-moz-focus-inner,
input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
  border: 0;
  padding: 0;
}
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
  cursor: pointer; // Cursors on all buttons applied consistently
  -webkit-appearance: button; // Style clicable inputs in iOS
}
input[type="search"] { // Appearance in Safari/Chrome
  -webkit-appearance: textfield;
  -webkit-box-sizing: content-box;
     -moz-box-sizing: content-box;
          box-sizing: content-box;
}
input[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
}
textarea {
  overflow: auto; // Remove vertical scrollbar in IE6-9
  vertical-align: top; // Readability and alignment cross-browser
}


function Player() {
}
Player.prototype.play = function(song) {
  this.currentlyPlayingSong = song;
  this.isPlaying = true;
};

Player.prototype.pause = function() {
  this.isPlaying = false;
};

Player.prototype.resume = function() {
  if (this.isPlaying) {
    throw new Error("song is already playing");
  }

  this.isPlaying = true;
};

Player.prototype.makeFavorite = function() {
  this.currentlyPlayingSong.persistFavoriteStatus(true);
};


$("#open-files-container").children().forEach( function( element, index, array ){

if(element.data( _DOCUMENT_KEY ) === doc)

keep replace replace replace keep keep keep

var items = $("#open-files-container").children("ul").children();

if(listItem.data( _DOCUMENT_KEY ) === doc){

/*
 * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
 */
define(function(require, exports, module) {
    // Load dependent modules
    var CommandManager      = require("CommandManager")
    ,   Commands            = require("Commands")
    ,   NativeFileSystem    = require("NativeFileSystem").NativeFileSystem
    ,   ProjectManager      = require("ProjectManager")
    ,   DocumentManager     = require("DocumentManager")
    ,   EditorManager       = require("EditorManager")
    ,   EditorUtils         = require("EditorUtils")
    ,   Strings             = require("strings");
    ;

    /**
     * Handlers for commands related to file handling (opening, saving, etc.)
     */

    /** @type {jQueryObject} */
    var _title;
    /** @type {string} */
    var _currentFilePath;  // TODO: eliminate this and just use getCurrentDocument().file.fullPath
    /** @type {string} */
    var _currentTitlePath;

    function init(title) {
        _title = title;

        // Register global commands
        CommandManager.register(Commands.FILE_OPEN, handleFileOpen);
		CommandManager.register(Commands.FILE_ADD_TO_WORKING_SET, handleFileAddToWoringSet);
        // TODO: For now, hook up File > New to the "new in project" handler. Eventually
        // File > New should open a new blank tab, and handleFileNewInProject should
        // be called from a "+" button in the project
        CommandManager.register(Commands.FILE_NEW, handleFileNewInProject);
        CommandManager.register(Commands.FILE_SAVE, handleFileSave);
        CommandManager.register(Commands.FILE_CLOSE, handleFileClose);

        $(DocumentManager).on("dirtyFlagChange", handleDirtyChange);
        $(DocumentManager).on("currentDocumentChange", handleCurrentDocumentChange);
    };

    function handleCurrentDocumentChange(event) {
        var newDocument = DocumentManager.getCurrentDocument();

        if (newDocument != null) {
            var fullPath = newDocument.file.fullPath;

            _currentFilePath = _currentTitlePath = fullPath;

            // In the main toolbar, show the project-relative path (if the file is inside the current project)
            // or the full absolute path (if it's not in the project).
            _currentTitlePath = ProjectManager.makeProjectRelativeIfPossible(fullPath);

        } else {
            _currentFilePath = _currentTitlePath = null;
        }

        // Update title text & "dirty dot" display
        updateTitle();
    }

    function handleDirtyChange(event, changedDoc) {
        if (changedDoc.file.fullPath == _currentFilePath) {
            updateTitle();
        }
    }

    function updateTitle() {
        var currentDoc = DocumentManager.getCurrentDocument();
        if (currentDoc) {
            _title.text( _currentTitlePath + (currentDoc.isDirty ? " \u2022" : "") );
        } else {
            _title.text("");
        }
    }

	function handleFileAddToWoringSet(fullPath){
		handleFileOpen(fullPath);
		DocumentManager.addToWorkingSet(fullPath);
	}

    function handleFileOpen(fullPath) {
        var result = doOpenWithOptionalPath(fullPath);
        result.always(function() {
            EditorManager.focusEditor();
        });
        return result;
    }

    function doOpenWithOptionalPath(fullPath) {
        var result;
        if (!fullPath) {
            // Prompt the user with a dialog
            // TODO: we're relying on this to not be asynchronous--is that safe?
            NativeFileSystem.showOpenDialog(false, false, Strings.OPEN_FILE, ProjectManager.getProjectRoot().fullPath,
                ["htm", "html", "js", "css"], function(files) {
                    if (files.length > 0) {
                        result = doOpen(files[0]);
                        return;
                    }
                });
        }
        else {
            result = doOpen(fullPath);
        }
        if (!result)
            result = (new $.Deferred()).reject();
        return result;
    }

    function doOpen(fullPath) {
        var result = new $.Deferred();
        if (!fullPath) {
            console.log("doOpen() called without fullPath");
            return result.reject();
        }

        // TODO: we should implement something like NativeFileSystem.resolveNativeFileSystemURL() (similar
        // to what's in the standard file API) to get a FileEntry, rather than manually constructing it
        var fileEntry = new NativeFileSystem.FileEntry(fullPath);

        var document = DocumentManager.getDocument(fileEntry);
        if (document != null) {
            // File already open - don't need to load it, just switch to it in the UI
            DocumentManager.showInEditor(document);
            result.resolve();

        } else {
            // File wasn't open before, so we must load its contents into a new document
            var reader = new NativeFileSystem.FileReader();

            fileEntry.file(function(file) {
                reader.onload = function(event) {
                    // Create a new editor initialized with the file's content, and bind it to a Document
                    var newEditor = EditorManager.createEditor(event.target.result);
                    EditorUtils.setModeFromFileExtension(newEditor, fullPath);
                    document = new DocumentManager.Document(fileEntry, newEditor);

                    // Switch to new document in the UI
                    DocumentManager.showInEditor(document);
                    result.resolve();
                };

                reader.onerror = function(event) {
                    showFileOpenError(event.target.error.code, fullPath);
                    result.reject();
                }

                reader.readAsText(file, "utf8");
            },
            function fileEntry_onerror(event) {
                showFileOpenError(event.target.error.code, fullPath);
                result.reject();
            });
        }

        return result;
    }

    function handleFileNewInProject() {
        // Determine the directory to put the new file
        // If a file is currently selected, put it next to it.
        // If a directory is currently selected, put it in it.
        // If nothing is selected, put it at the root of the project
        var baseDir,
            selected = ProjectManager.getSelectedItem() || ProjectManager.getProjectRoot();

        baseDir = selected.fullPath;
        if (selected.isFile)
            baseDir = baseDir.substr(0, baseDir.lastIndexOf("/"));

        // Create the new node. The createNewItem function does all the heavy work
        // of validating file name, creating the new file and selecting.
        // TODO: Use a unique name like Untitled-1, Untitled-2, etc.
        return ProjectManager.createNewItem(baseDir, "Untitled.js", false);
    }

    function handleFileSave() {
        var result = new $.Deferred();
        var docToSave = DocumentManager.getCurrentDocument();
        if (docToSave && docToSave.isDirty) {
            // TODO: we should implement something like NativeFileSystem.resolveNativeFileSystemURL() (similar
            // to what's in the standard file API) to get a FileEntry, rather than manually constructing it
            var fileEntry = new NativeFileSystem.FileEntry(_currentFilePath);

            fileEntry.createWriter(
                function(writer) {
                    writer.onwriteend = function() {
                        docToSave.markClean();
                        result.resolve();
                    }
                    writer.onerror = function(event) {
                        showSaveFileError(event.target.error.code, _currentFilePath);
                        result.reject();
                    }

                    // TODO (jasonsj): Blob instead of string
                    writer.write( docToSave.getText() );
                },
                function(event) {
                    showSaveFileError(event.target.error.code, _currentFilePath);
                    result.reject();
                }
            );
        }
        else {
            result.resolve();
        }
        result.always(function() {
            EditorManager.focusEditor();
        });
        return result;
    }

    function handleFileClose() {
        // TODO: quit and open different project should show similar confirmation dialog
        var result = new $.Deferred();
        var docToClose = DocumentManager.getCurrentDocument();
        if (docToClose && docToClose.isDirty) {
            brackets.showModalDialog(
                  brackets.DIALOG_ID_SAVE_CLOSE
                , Strings.SAVE_CLOSE_TITLE
                , Strings.format(Strings.SAVE_CLOSE_MESSAGE, _currentTitlePath)
            ).done(function(id) {
                if (id === brackets.DIALOG_BTN_CANCEL) {
                    result.reject();
                }
                else {
                    if (id === brackets.DIALOG_BTN_OK) {
                        CommandManager
                            .execute(Commands.FILE_SAVE)
                            .done(function() {
                                doCloseWithOptionalPath();
                                result.resolve();
                            })
                            .fail(function() {
                                result.reject();
                            });
                    }
                    else {
                        // This is the "Don't Save" case--we can just go ahead and close the file.
                        doCloseWithOptionalPath();
                        result.resolve();
                    }
                }
            });
            result.always(function() {
                EditorManager.focusEditor();
            });
        }
        else {
            doCloseWithOptionalPath();
            EditorManager.focusEditor();
            result.resolve();
        }
        return result;
    }

	function doCloseWithOptionalPath(fullPath) {
		var result;
		if (!fullPath) {
			// default to the file the editor is showing
			fullPath = _currentFilePath;
		}
		else {
			result = doClose(fullPath);
		}
        if (!result)
            result = (new $.Deferred()).reject();
        return result;

	}

    function doClose() {
        var fileEntry = new NativeFileSystem.FileEntry(_currentFilePath);

        var docToClose = DocumentManager.getCurrentDocument();

        // altho old doc is going away, we should fix its dirty bit in case anyone hangs onto a ref to it
        // TODO: can this be removed?
        docToClose.markClean();

        // This selects a different document if the working set has any other options
        DocumentManager.closeDocument(docToClose);

        EditorManager.focusEditor();
    }

    function showFileOpenError(code, path) {
        brackets.showModalDialog(
              brackets.DIALOG_ID_ERROR
            , Strings.ERROR_OPENING_FILE_TITLE
            , Strings.format(
                    Strings.ERROR_OPENING_FILE
                  , path
                  , getErrorString(code))
        );
    }

    function showSaveFileError(code, path) {
        brackets.showModalDialog(
              brackets.DIALOG_ID_ERROR
            , Strings.ERROR_SAVING_FILE_TITLE
            , Strings.format(
                    Strings.ERROR_SAVING_FILE
                  , path
                  , getErrorString(code))
        );
    }

    function getErrorString(code) {
        // There are a few error codes that we have specific error messages for. The rest are
        // displayed with a generic "(error N)" message.
        var result;

        if (code == FileError.NOT_FOUND_ERR)
            result = Strings.NOT_FOUND_ERR;
        else if (code == FileError.NOT_READABLE_ERR)
            result = Strings.NOT_READABLE_ERR;
        else if (code == FileError.NO_MODIFICATION_ALLOWED_ERR)
            result = Strings.NO_MODIFICATION_ALLOWED_ERR;
        else
            result = Strings.format(Strings.GENERIC_ERROR, code);

        return result;
    }

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


describe("Player", function() {
  var player;
  var song;

  beforeEach(function() {
    player = new Player();
    song = new Song();
  });

  it("should be able to play a Song", function() {
    player.play(song);
    expect(player.currentlyPlayingSong).toEqual(song);

    //demonstrates use of custom matcher
    expect(player).toBePlaying(song);
  });

  describe("when song has been paused", function() {
    beforeEach(function() {
      player.play(song);
      player.pause();
    });

    it("should indicate that the song is currently paused", function() {
      expect(player.isPlaying).toBeFalsy();

      // demonstrates use of 'not' with a custom matcher
      expect(player).not.toBePlaying(song);
    });

    it("should be possible to resume", function() {
      player.resume();
      expect(player.isPlaying).toBeTruthy();
      expect(player.currentlyPlayingSong).toEqual(song);
    });
  });

  // demonstrates use of spies to intercept and test method calls
  it("tells the current song if the user has made it a favorite", function() {
    spyOn(song, 'persistFavoriteStatus');

    player.play(song);
    player.makeFavorite();

    expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true);
  });

  //demonstrates use of expected exceptions
  describe("#resume", function() {
    it("should throw an exception if song is already playing", function() {
      player.play(song);

      expect(function() {
        player.resume();
      }).toThrow("song is already playing");
    });
  });
});


});
}
return null;
}
function _removeDoc( doc ) {


/* Typography.less
 * Headings, body text, lists, code, and more for a versatile and durable typography system
 * ---------------------------------------------------------------------------------------- */

// BODY TEXT
// ---------

p {
  #font > .shorthand(normal,@basefont,@baseline);
  margin-bottom: @baseline / 2;
  small {
    font-size: @basefont - 2;
    color: @grayLight;
  }
}

// HEADINGS
// --------

h1, h2, h3, h4, h5, h6 {
  font-weight: bold;
  color: @grayDark;
  small {
    color: @grayLight;
  }
}
h1 {
  margin-bottom: @baseline;
  font-size: 30px;
  line-height: @baseline * 2;
  small {
    font-size: 18px;
  }
}
h2 {
  font-size: 24px;
  line-height: @baseline * 2;
  small {
    font-size: 14px;
  }
}
h3, h4, h5, h6 {
  line-height: @baseline * 2;
}
h3 {
  font-size: 18px;
  small {
    font-size: 14px;
  }
}
h4 {
  font-size: 16px;
  small {
    font-size: 12px;
  }
}
h5 {
  font-size: 14px;
}
h6 {
  font-size: 13px;
  color: @grayLight;
  text-transform: uppercase;
}

// COLORS
// ------

// Unordered and Ordered lists
ul, ol {
  margin: 0 0 @baseline 25px;
}
ul ul,
ul ol,
ol ol,
ol ul {
  margin-bottom: 0;
}
ul {
  list-style: disc;
}
ol {
  list-style: decimal;
}
li {
  line-height: @baseline;
  color: @gray;
}
ul.unstyled {
  list-style: none;
  margin-left: 0;
}

// Description Lists
dl {
  margin-bottom: @baseline;
  dt, dd {
    line-height: @baseline;
  }
  dt {
    font-weight: bold;
  }
  dd {
    margin-left: @baseline / 2;
  }
}

// MISC
// ----

// Horizontal rules
hr {
  margin: 20px 0 19px;
  border: 0;
  border-bottom: 1px solid #eee;
}

// Emphasis
strong {
  font-style: inherit;
  font-weight: bold;
}
em {
  font-style: italic;
  font-weight: inherit;
  line-height: inherit;
}
.muted {
  color: @grayLight;
}

// Blockquotes
blockquote {
  margin-bottom: @baseline;
  border-left: 5px solid #eee;
  padding-left: 15px;
  p {
    #font > .shorthand(300,14px,@baseline);
    margin-bottom: 0;
  }
  small {
    display: block;
    #font > .shorthand(300,12px,@baseline);
    color: @grayLight;
    &:before {
      content: '\2014 \00A0';
    }
  }
}

// Addresses
address {
  display: block;
  line-height: @baseline;
  margin-bottom: @baseline;
}

// Inline and block code styles
code, pre {
  padding: 0 3px 2px;
  font-family: Monaco, Andale Mono, Courier New, monospace;
  font-size: 12px;
  .border-radius(3px);
}
code {
  background-color: lighten(@orange, 40%);
  color: rgba(0,0,0,.75);
  padding: 1px 3px;
}
pre {
  background-color: #f5f5f5;
  display: block;
  padding: (@baseline - 1) / 2;
  margin: 0 0 @baseline;
  line-height: @baseline;
  font-size: 12px;
  border: 1px solid #ccc;
  border: 1px solid rgba(0,0,0,.15);
  .border-radius(3px);
  white-space: pre;
  white-space: pre-wrap;
  word-wrap: break-word;

}


keep keep keep replace replace keep keep keep keep

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

    // Load dependent modules
    var DocumentManager     = require("DocumentManager")
	, CommandManager        = require("CommandManager")
	, Commands              = require("Commands")
	,	EditorManager		= require("EditorManager")
    ,   NativeFileSystem    = require("NativeFileSystem").NativeFileSystem
    ;

    // Initialize: register listeners
    $(DocumentManager).on("currentDocumentChange", _onCurrentDocumentChange);

    function _onCurrentDocumentChange(event) {
        console.log("Current document changed!  --> "+DocumentManager.getCurrentDocument());
    }

    $(DocumentManager).on("workingSetAdd", function(event, addedDoc) {
        console.log("Working set ++ " + addedDoc);
        //console.log("  set: " + DocumentManager.getWorkingSet().join());

		_addDoc( addedDoc )

    });
    $(DocumentManager).on("workingSetRemove", function(event, removedDoc) {
        console.log("Working set -- " + removedDoc);
        //console.log("  set: " + DocumentManager.getWorkingSet().join());

		_removeDoc( removedDoc );
    });

    $(DocumentManager).on("dirtyFlagChange", function(event, doc ) {
        console.log("Dirty flag change: " + doc);

		_dirtyFlagChanged( doc );
    });

	/** Each list item in the working set stores a references to the related document in the list item's data.
	 *  Use listIem.data( _DOCUMENT_KEY ) to get the document reference
	 */
	var _DOCUMENT_KEY = "document";

	function _addDoc( doc ) {
		// Add new item to bottom of list
		var link = $("").attr( "href", "#" ).text( doc.file.name );
		var newItem = $("

").addClass("working-set-list-item").append( link );

		// TODO: Ask NJ which way is better
		//var newItem = $("
" + doc.file.name +  "
");

		newItem.data( _DOCUMENT_KEY, doc );

		$("#open-files-container").children("ul").append(newItem);

		newItem.click( function() {
			_openDoc( doc );
		});

		_updateFileStatusIcon( newItem, doc.isDirty, false);

		newItem.hover(
			// hover in
	        function() {
				_updateFileStatusIcon( $(this), doc.isDirty, true);
	        },
			// hover out
	        function() {
				_updateFileStatusIcon( $(this), doc.isDirty, false);
	        }
	    );
	}

    function _updateFileStatusIcon(listElement, isDirty, canClose) {
       var found = listElement.find(".file-status-icon");
       var fileStatusIcon = found.length != 0 ? $(found[0]) : null;
       var showIcon = isDirty || canClose;

       // remove icon if its not needed
       if (!showIcon && fileStatusIcon) {
           fileStatusIcon.remove();
           fileStatusIcon = null;
       }
       // create icon if its needed and doesn't exist
       else if (showIcon && !fileStatusIcon) {
           fileStatusIcon = $("

");
           fileStatusIcon.addClass("file-status-icon");
           listElement.prepend(fileStatusIcon);

		   fileStatusIcon.click( function() {
			   var doc = listElement.data( _DOCUMENT_KEY )
			   CommandManager.execute(Commands.FILE_CLOSE, doc.file.fullPath );
		   });
       }

       // Set icon's class
       if (fileStatusIcon) {
           fileStatusIcon.toggleClass("dirty", isDirty);
           fileStatusIcon.toggleClass("canClose", canClose);
       }
   }

   function _openDoc( doc ) {
	   CommandManager.execute(Commands.FILE_OPEN, doc.file.fullPath);

    }

   function _closeDoc( doc ) {
	   CommandManager.execute(Commands.FILE_CLOSE, doc.file.fullPath );
   }

   function _findListItemFromDocument( doc ) {
	   if( doc ){
		   $("#open-files-container").children().forEach( function( element, index, array ){
			   if(element.data( _DOCUMENT_KEY ) === doc)
			   	return element;
		   });
	   }

	   return null;
   }

	function _removeDoc( doc ) {
 	   var listIem = _findListItemFromDocument( doc );
 	   if(listIem){
 		   listItem.remove();
 	   }
	}

	function _dirtyFlagChanged( doc ){
		$("#" + doc.file.fullPath).find(".file-status-icon");
	}

	function _rebuild() {

	}

});


# input filenames
BRACKETS_LESS = ../brackets.less

# output filenames
BRACKETS_CSS = ../brackets.css
BRACKETS_CSS_MIN = ../brackets.min.css

DATE=$(shell DATE)
LESS_COMPRESSOR ?= `which lessc`
WATCHR ?= `which watchr`

build:
	@@if test ! -z ${LESS_COMPRESSOR}; then \
		sed -e 's/@DATE/'"${DATE}"'/' <${BRACKETS_LESS} >${BRACKETS_LESS}.tmp; \
		lessc ${BRACKETS_LESS}.tmp > ${BRACKETS_CSS}; \
		lessc ${BRACKETS_LESS}.tmp > ${BRACKETS_CSS_MIN} --compress; \
		rm -f ${BRACKETS_LESS}.tmp; \
		echo "brackets-app css successfully built! - `date`"; \
	else \
		echo "You must have the LESS compiler installed in order to build Bootstrap."; \
		echo "You can install it by running: npm install less -g"; \
	fi

watch:
	@@if test ! -z ${WATCHR}; then \
	  echo "Watching less files..."; \
	  watchr -e "watch('lib/.*\.less') { system 'make' }"; \
	else \
		echo "You must have the watchr installed in order to watch Bootstrap less files."; \
		echo "You can install it by running: gem install watchr"; \
	fi

.PHONY: build watch


/*
 * jsTree classic theme 1.0
 * Supported features: dots/no-dots, icons/no-icons, focused, loading
 * Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search
 */

.jstree-classic li,
.jstree-classic ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; }
.jstree-classic li { background-position:-90px 0; background-repeat:repeat-y;  }
.jstree-classic li.jstree-last { background:transparent; }
.jstree-classic .jstree-open > ins { background-position:-72px 0; }
.jstree-classic .jstree-closed > ins { background-position:-54px 0; }
.jstree-classic .jstree-leaf > ins { background-position:-36px 0; }

.jstree-classic .jstree-hovered { background:#e7f4f9; border:1px solid #e7f4f9; padding:0 2px 0 1px; }
.jstree-classic .jstree-clicked { background:navy; border:1px solid navy; padding:0 2px 0 1px; color:white; }
.jstree-classic a .jstree-icon { background-position:-56px -19px; }
.jstree-classic .jstree-open > a .jstree-icon { background-position:-56px -36px; }
.jstree-classic a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; }

.jstree-classic.jstree-focused { background:white; }

.jstree-classic .jstree-no-dots li,
.jstree-classic .jstree-no-dots .jstree-leaf > ins { background:transparent; }
.jstree-classic .jstree-no-dots .jstree-open > ins { background-position:-18px 0; }
.jstree-classic .jstree-no-dots .jstree-closed > ins { background-position:0 0; }

.jstree-classic .jstree-no-icons a .jstree-icon { display:none; }

.jstree-classic .jstree-search { font-style:italic; }

.jstree-classic .jstree-no-icons .jstree-checkbox { display:inline-block; }
.jstree-classic .jstree-no-checkboxes .jstree-checkbox { display:none !important; }
.jstree-classic .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; }
.jstree-classic .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; }
.jstree-classic .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; }
.jstree-classic .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; }
.jstree-classic .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; }
.jstree-classic .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; }

#vakata-dragged.jstree-classic ins { background:transparent !important; }
#vakata-dragged.jstree-classic .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; }
#vakata-dragged.jstree-classic .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; }
#jstree-marker.jstree-classic { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; }

.jstree-classic a.jstree-search { color:aqua; }
.jstree-classic .jstree-locked a { color:silver; cursor:default; }

#vakata-contextmenu.jstree-classic-context,
#vakata-contextmenu.jstree-classic-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; }
#vakata-contextmenu.jstree-classic-context li { }
#vakata-contextmenu.jstree-classic-context a { color:black; }
#vakata-contextmenu.jstree-classic-context a:hover,
#vakata-contextmenu.jstree-classic-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; }
#vakata-contextmenu.jstree-classic-context li.jstree-contextmenu-disabled a,
#vakata-contextmenu.jstree-classic-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; }
#vakata-contextmenu.jstree-classic-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; }
#vakata-contextmenu.jstree-classic-context li ul { margin-left:-4px; }

/* IE6 BEGIN */
.jstree-classic li,
.jstree-classic ins,
#vakata-dragged.jstree-classic .jstree-invalid,
#vakata-dragged.jstree-classic .jstree-ok,
#jstree-marker.jstree-classic { _background-image:url("d.gif"); }
.jstree-classic .jstree-open ins { _background-position:-72px 0; }
.jstree-classic .jstree-closed ins { _background-position:-54px 0; }
.jstree-classic .jstree-leaf ins { _background-position:-36px 0; }
.jstree-classic .jstree-open a ins.jstree-icon { _background-position:-56px -36px; }
.jstree-classic .jstree-closed a ins.jstree-icon { _background-position:-56px -19px; }
.jstree-classic .jstree-leaf a ins.jstree-icon { _background-position:-56px -19px; }
#vakata-contextmenu.jstree-classic-context ins { _display:none; }
#vakata-contextmenu.jstree-classic-context li { _zoom:1; }
.jstree-classic .jstree-undetermined a .jstree-checkbox { _background-position:-20px -19px; }
.jstree-classic .jstree-checked a .jstree-checkbox { _background-position:-38px -19px; }
.jstree-classic .jstree-unchecked a .jstree-checkbox { _background-position:-2px -19px; }
/* IE6 END */


// Display close "x" icon when user hovers over working set file

keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace keep


// Set the baseUrl to brackets/src
require.config({
    baseUrl: "../src"
});

define(function(require, exports, module) {
    // Utility dependency
    require("spec/SpecRunnerUtils.js");

    // Load test specs
    require("spec/Editor-test.js");
    require("spec/NativeFileSystem-test.js");
    require("spec/LowLevelFileIO-test.js");
    require("spec/ProjectManager-test.js");
    require("spec/FileCommandHandlers-test.js");
});