<commit_before>$(function () {

    module("collapse")

      test("should provide no conflict", function () {
        var collapse = $.fn.collapse.noConflict()
        ok(!$.fn.collapse, 'collapse was set back to undefined (org value)')
        $.fn.collapse = collapse
      })

      test("should be defined on jquery object", function () {
        ok($(document.body).collapse, 'collapse method is defined')
      })

      test("should return element", function () {
        ok($(document.body).collapse()[0] == document.body, 'document.body returned')
      })

      test("should show a collapsed element", function () {
        var el = $('

').collapse('show')
        ok(el.hasClass('in'), 'has class in')
        ok(/height/.test(el.attr('style')), 'has height set')
      })

      test("should hide a collapsed element", function () {
        var el = $('

').collapse('hide')
        ok(!el.hasClass('in'), 'does not have class in')
        ok(/height/.test(el.attr('style')), 'has height set')
      })

      test("should not fire shown when show is prevented", function () {
        $.support.transition = false
        stop()
        $('
')
          .on('show.bs.collapse', function (e) {
            e.preventDefault();
            ok(true);
            start();
          })
          .on('shown.bs.collapse', function () {
            ok(false);
          })
          .collapse('show')
      })

      test("should reset style to auto after finishing opening collapse", function () {
        $.support.transition = false
        stop()
        $('
')
          .on('show.bs.collapse', function () {
            ok(this.style.height == '0px')
          })
          .on('shown.bs.collapse', function () {
            ok(this.style.height == 'auto')
            start()
          })
          .collapse('show')
      })

      test("should add active class to target when collapse shown", function () {
        $.support.transition = false
        stop()

        var target = $('')
          .appendTo($('#qunit-fixture'))

        var collapsible = $('

')
          .appendTo($('#qunit-fixture'))
          .on('show.bs.collapse', function () {
            ok(!target.hasClass('collapsed'))
            start()
          })

        target.click()
      })

      test("should remove active class to target when collapse hidden", function () {
        $.support.transition = false
        stop()

        var target = $('')
          .appendTo($('#qunit-fixture'))

        var collapsible = $('

')
          .appendTo($('#qunit-fixture'))
          .on('hide.bs.collapse', function () {
            ok(target.hasClass('collapsed'))
            start()
          })

        target.click()
      })

      test("should remove active class from inactive accordion targets", function () {
        $.support.transition = false
        stop()

        var accordion = $('

')
          .appendTo($('#qunit-fixture'))

        var target1 = $('')
          .appendTo(accordion.find('.accordion-group').eq(0))

        var collapsible1 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(0))

        var target2 = $('')
          .appendTo(accordion.find('.accordion-group').eq(1))

        var collapsible2 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(1))

        var target3 = $('')
          .appendTo(accordion.find('.accordion-group').eq(2))

        var collapsible3 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(2))
          .on('show.bs.collapse', function () {
            ok(target1.hasClass('collapsed'))
            ok(target2.hasClass('collapsed'))
            ok(!target3.hasClass('collapsed'))

            start()
          })

        target3.click()
      })

})
<commit_msg>failing test for dot in data-parent<commit_after>$(function () {

    module("collapse")

      test("should provide no conflict", function () {
        var collapse = $.fn.collapse.noConflict()
        ok(!$.fn.collapse, 'collapse was set back to undefined (org value)')
        $.fn.collapse = collapse
      })

      test("should be defined on jquery object", function () {
        ok($(document.body).collapse, 'collapse method is defined')
      })

      test("should return element", function () {
        ok($(document.body).collapse()[0] == document.body, 'document.body returned')
      })

      test("should show a collapsed element", function () {
        var el = $('

').collapse('show')
        ok(el.hasClass('in'), 'has class in')
        ok(/height/.test(el.attr('style')), 'has height set')
      })

      test("should hide a collapsed element", function () {
        var el = $('

').collapse('hide')
        ok(!el.hasClass('in'), 'does not have class in')
        ok(/height/.test(el.attr('style')), 'has height set')
      })

      test("should not fire shown when show is prevented", function () {
        $.support.transition = false
        stop()
        $('
')
          .on('show.bs.collapse', function (e) {
            e.preventDefault();
            ok(true);
            start();
          })
          .on('shown.bs.collapse', function () {
            ok(false);
          })
          .collapse('show')
      })

      test("should reset style to auto after finishing opening collapse", function () {
        $.support.transition = false
        stop()
        $('
')
          .on('show.bs.collapse', function () {
            ok(this.style.height == '0px')
          })
          .on('shown.bs.collapse', function () {
            ok(this.style.height == 'auto')
            start()
          })
          .collapse('show')
      })

      test("should add active class to target when collapse shown", function () {
        $.support.transition = false
        stop()

        var target = $('')
          .appendTo($('#qunit-fixture'))

        var collapsible = $('

')
          .appendTo($('#qunit-fixture'))
          .on('show.bs.collapse', function () {
            ok(!target.hasClass('collapsed'))
            start()
          })

        target.click()
      })

      test("should remove active class to target when collapse hidden", function () {
        $.support.transition = false
        stop()

        var target = $('')
          .appendTo($('#qunit-fixture'))

        var collapsible = $('

')
          .appendTo($('#qunit-fixture'))
          .on('hide.bs.collapse', function () {
            ok(target.hasClass('collapsed'))
            start()
          })

        target.click()
      })

      test("should remove active class from inactive accordion targets", function () {
        $.support.transition = false
        stop()

        var accordion = $('

')
          .appendTo($('#qunit-fixture'))

        var target1 = $('')
          .appendTo(accordion.find('.accordion-group').eq(0))

        var collapsible1 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(0))

        var target2 = $('')
          .appendTo(accordion.find('.accordion-group').eq(1))

        var collapsible2 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(1))

        var target3 = $('')
          .appendTo(accordion.find('.accordion-group').eq(2))

        var collapsible3 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(2))
          .on('show.bs.collapse', function () {
            ok(target1.hasClass('collapsed'))
            ok(target2.hasClass('collapsed'))
            ok(!target3.hasClass('collapsed'))

            start()
          })

        target3.click()
      })

      test("should allow dots in data-parent", function () {
        $.support.transition = false
        stop()

        var accordion = $('

')
          .appendTo($('#qunit-fixture'))

        var target1 = $('')
          .appendTo(accordion.find('.accordion-group').eq(0))

        var collapsible1 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(0))

        var target2 = $('')
          .appendTo(accordion.find('.accordion-group').eq(1))

        var collapsible2 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(1))

        var target3 = $('')
          .appendTo(accordion.find('.accordion-group').eq(2))

        var collapsible3 = $('

')
          .appendTo(accordion.find('.accordion-group').eq(2))
          .on('show.bs.collapse', function () {
            ok(target1.hasClass('collapsed'))
            ok(target2.hasClass('collapsed'))
            ok(!target3.hasClass('collapsed'))

            start()
          })

        target3.click()
      })

})
<|endoftext|>


<commit_before>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";

/**
 * Various hacks to try to get mobile browsers to do what I want but that
 * probably wouldn't be needed if I actually understood the platform.
 *
 * @module MobileHacks
 */
define(function() {

  var $ = function(id) {
    return document.getElementById(id);
  };

  /**
   * resets the height of any element with CSS class "fixeight"
   * by setting its hight to the cliehgtHeight of its parent
   *
   * The problem this is trying to solve is sometimes you have
   * an element set to 100% but when the phone rotates
   * the browser does not reset the size of the element even
   * though it's parent has been resized.
   *
   * This will be called automatically when the phone rotates
   * or the window is resized but I found I often needed to
   * call it manually at the start of a controller
   *
   * @memberOf module:MobileHacks
   */
  var fixHeightHack = function() {
    // Also fix all fucked up sizing
    var elements = document.querySelectorAll(".fixheight");
    for (var ii = 0; ii < elements.length; ++ii) {
      var element = elements[ii];
      var parent = element.parentNode;
      if (parseInt(element.style.height) != parent.clientHeight) {
        element.style.height = parent.clientHeight + "px";
      }
    }
  };

  var fixupAfterSizeChange = function() {
    window.scrollTo(0, 0);
    fixHeightHack();
    window.scrollTo(0, 0);
  };

  // When the device re-orients, at least on iOS, the page is scrolled down :(
  window.addEventListener('orientationchange', fixupAfterSizeChange, false);
  window.addEventListener('resize', fixupAfterSizeChange, false);

  // Prevents the browser from sliding the page when the user slides their finger.
  // At least on iOS.
  var stopSliding = function() {
    if (!document.body) {
      setTimeout(stopSliding, 4);
    } else {
      document.body.addEventListener('touchmove', function(e) {
        e.preventDefault();
      }, false);
    }
  };
  stopSliding();

  // This DOESN'T WORK! I'm leaving it here so I can revisit it.
  // The issue is all kinds of things mess up. Events are not rotated,
  // the page does strange things.
  var forceLandscape = function() {
    // Note: This code is for games that require a certain orientation
    // on phones only. I'm making the assuption that tablets don't need
    // this.
    //
    // The issue I ran into is I tried to show several people games
    // and they had their phone orientation locked to portrait. Having
    // to go unlock just to play the game was frustrating. So, for
    // controllers than require landscape just try to make the page
    // show up in landscape. They'll understand they need to turn the phone.
    //
    // If the orientation is unlocked they'll turn and the page will
    // switch to landscape. If the orientation is locked then turning
    // the phone will not switch to landscape NOR will we get an orientation
    // event.
    var everything = $("hft-everything");
    var detectPortrait = function() {
      if (screen.width < screen.height) {
        everything.className = "hft-portrait-to-landscape";
        everything.style.width = window.innerHeight + "px";
        everything.style.height = window.innerWidth + "px";

        var viewport = document.querySelector("meta[name=viewport]");
        viewport.setAttribute('content', 'width=device-height, initial-scale=1.0, maximum-scale=1, user-scalable=no, minimal-ui');
      } else {
        everything.className = "";
      }
    };

    detectPortrait();
    window.addEventListener('resize', detectPortrait, false);
  };

  window.scrollTo(0, 0);

  return {
    fixHeightHack: fixHeightHack,
    forceLandscape: forceLandscape,
  };
});

<commit_msg>add MobileHacks.adjustCSSBasedOnPhone<commit_after>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";

/**
 * Various hacks to try to get mobile browsers to do what I want but that
 * probably wouldn't be needed if I actually understood the platform.
 *
 * @module MobileHacks
 */
define(function() {

  var $ = function(id) {
    return document.getElementById(id);
  };

  // shit hacks for iOS8 because iOS8 barfs toolbars on the screen and
  // (a) the user can NOT dismiss them and (b) there is no way for the
  // webpage to see they exist. This only happens on iPhone 4/4s/5/s.
  var isIOS;
  var shittyOldIPhoneWithShittyIOS8Plus = function() {
    var iPhone4 = (window.screen.height == (960 / 2));
    var iPhone5 = (window.screen.height == (1136 / 2));
    var iOS8Plus = function() {
      if (/iP(hone|od|ad)/.test(navigator.platform)) {
        // supports iOS 2.0 and later: <http://bit.ly/TJjs1V>
        var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
        isIOS = true;
        return parseInt(v[1], 10) >= 8;
      }
    }();
    return iOS8Plus && (iPhone4 || iPhone5);
  }();

  var isIOS8OrNewerAndiPhone4OrIPhone5 = function() {
    return shittyOldIPhoneWithShittyIOS8Plus;
  };

  /**
   * resets the height of any element with CSS class "fixeight"
   * by setting its hight to the cliehgtHeight of its parent
   *
   * The problem this is trying to solve is sometimes you have
   * an element set to 100% but when the phone rotates
   * the browser does not reset the size of the element even
   * though it's parent has been resized.
   *
   * This will be called automatically when the phone rotates
   * or the window is resized but I found I often needed to
   * call it manually at the start of a controller
   *
   * @memberOf module:MobileHacks
   */
  var fixHeightHack = function() {
    // Also fix all fucked up sizing
    var elements = document.querySelectorAll(".fixheight");
    for (var ii = 0; ii < elements.length; ++ii) {
      var element = elements[ii];
      var parent = element.parentNode;
      if (parseInt(element.style.height) != parent.clientHeight) {
        element.style.height = parent.clientHeight + "px";
      }
    }
  };

  var adjustCSSBasedOnPhone = function(perPhoneClasses) {
    perPhoneClasses.forEach(function(phone) {
      if (phone.test()) {
        Array.prototype.forEach.call(document.styleSheets, function(sheet) {
          var classes = sheet.rules || document.sheet.cssRules;
          Array.prototype.forEach.call(classes, function(c) {
            var adjustments = phone.styles[c.selectorText];
            if (adjustments) {
              Object.keys(adjustments).forEach(function(key) {
//console.log(key + ": old " + c.style[key]);
                if (c.style.setProperty) {
                  c.style.setProperty(key, adjustments[key]);
                } else {
                  c.style[key] = adjustments[key];
                }
//console.log(key + ": new " + c.style[key]);
              });
            }
          });
        });
      }
    });
  };

  var fixupAfterSizeChange = function() {
    window.scrollTo(0, 0);
    fixHeightHack();
    window.scrollTo(0, 0);
  };

  // When the device re-orients, at least on iOS, the page is scrolled down :(
  window.addEventListener('orientationchange', fixupAfterSizeChange, false);
  window.addEventListener('resize', fixupAfterSizeChange, false);

  // Prevents the browser from sliding the page when the user slides their finger.
  // At least on iOS.
  var stopSliding = function() {
    if (!document.body) {
      setTimeout(stopSliding, 4);
    } else {
      document.body.addEventListener('touchmove', function(e) {
        e.preventDefault();
      }, false);
    }
  };
  stopSliding();

  // This DOESN'T WORK! I'm leaving it here so I can revisit it.
  // The issue is all kinds of things mess up. Events are not rotated,
  // the page does strange things.
  var forceLandscape = function() {
    // Note: This code is for games that require a certain orientation
    // on phones only. I'm making the assuption that tablets don't need
    // this.
    //
    // The issue I ran into is I tried to show several people games
    // and they had their phone orientation locked to portrait. Having
    // to go unlock just to play the game was frustrating. So, for
    // controllers than require landscape just try to make the page
    // show up in landscape. They'll understand they need to turn the phone.
    //
    // If the orientation is unlocked they'll turn and the page will
    // switch to landscape. If the orientation is locked then turning
    // the phone will not switch to landscape NOR will we get an orientation
    // event.
    var everything = $("hft-everything");
    var detectPortrait = function() {
      if (screen.width < screen.height) {
        everything.className = "hft-portrait-to-landscape";
        everything.style.width = window.innerHeight + "px";
        everything.style.height = window.innerWidth + "px";

        var viewport = document.querySelector("meta[name=viewport]");
        viewport.setAttribute('content', 'width=device-height, initial-scale=1.0, maximum-scale=1, user-scalable=no, minimal-ui');
      } else {
        everything.className = "";
      }
    };

    detectPortrait();
    window.addEventListener('resize', detectPortrait, false);
  };

  window.scrollTo(0, 0);

  return {
    fixHeightHack: fixHeightHack,
    forceLandscape: forceLandscape,
    adjustCSSBasedOnPhone: adjustCSSBasedOnPhone,
    isIOS8OrNewerAndiPhone4OrIPhone5: isIOS8OrNewerAndiPhone4OrIPhone5,
  };
});

<|endoftext|>


<commit_before>/**
 *	global.js
 * 	Global footer file
 *
 *  @project    < write project name here >
 *  @date       < put date here >
 *  @author  	< author name >
 * 	@site       < site name >
 */

 (function($, ns, window, document, undefined){

	"use strict";

	var _global = function(){
		this.init = function(){
			initEventListeners();
			initEventTriggers();
		};

		/**
		 *	add all event listeners
		 */
		var initEventListeners = function(){

		};

		/**
		 *	put all event triggers, plugin initializations
		 */
		var initEventTriggers = function(){

		};

		/**
		 * Initialize this object when document ready event is triggered
		 */
		$.subscribe(ns.events.INIT_MODULES, this.init);
	};

	NameSpace.global = new _global();

})((typeof jQuery !== "undefined") ? jQuery : null, NameSpace || {}, window, window.document);<commit_msg>updated with comments<commit_after>/**
 *	global.js
 * 	Global footer file
 *
 *  @project    < write project name here >
 *  @date       < put date here >
 *  @author  	< author name >
 * 	@site       < site name >
 */

 (function($, ns, window, document, undefined){

	"use strict";

	var _global = function(){
		this.init = function(){
			initEventListeners();
			initEventTriggers();
		};

		/**
		 *	add all event listeners
		 */
		var initEventListeners = function(){

		};

		/**
		 *	put all event triggers, plugin initializations
		 */
		var initEventTriggers = function(){

		};

		/**
		 * Initialize this object when document ready event is triggered
		 */
		$.subscribe(ns.events.INIT_MODULES, this.init);
	};

	ns.global = new _global();

})((typeof jQuery !== "undefined") ? jQuery : null, NameSpace || {}, window, window.document);<|endoftext|>


<commit_before>import Ember from "ember";
import ArrayController from 'ember-legacy-controllers/array';

var controller = ArrayController.extend({
    taskController: Ember.inject.controller('task'),
    applicationController: Ember.inject.controller('application'),
    sortProperties: ['urgency:desc'],
    sortAscending: false,
    defaultFilter: {
        fields: {
            'status': 'pending'
        },
        description: [],
        tags: [],
    },
    ajaxRequest: function(params) {
        return this.get('applicationController').ajaxRequest(params);
    },
    refresh: function(){
        // First, request a synchronous sync
        return this.ajaxRequest({
            url: this.get('applicationController').urls.sync,
            type: 'POST',
        }).then(function(){
            // Then, request a new list from the endpoint to make sure
            // we gather any new tasks, too.
            this.store.findAll('task').then(function(){
                // Refresh each entry to see if it has been closed.
                this.get('content').forEach(function(model){
                    try {
                        model.reload();
                    } catch(e) {
                        // pass
                    }
                }.bind(this));
            }.bind(this));
        }.bind(this), function(msg){
            this.get('applicationController').error_message(
                `An error was encountered while ` +
                `attempting to synchronize your task list: ${msg}`
            );
        }.bind(this));
    },
    collectionObserver: function() {
        // If the collection has changed, and we're currently on the tasks
        // view, transition to showing the first task.
        var path = this.get('applicationController').getHandlerPath();
        if(path === 'application.tasks.tasks.index') {
            Ember.run.debounce(this, 'transitionToFirstTask', 100);
        }
    }.observes('model.length'),
    transitionToFirstTask: function() {
        var task = this.get('pendingTasks.firstObject');
        if(task) {
            this.transitionToRoute('task', task);
        }
    },
    enteredFilters: Ember.computed('filterString', function() {
        var value = this.get('filterString');
        var filters = JSON.parse(
            JSON.stringify(this.get('defaultFilter'))
        );

        if(!value) {
            return filters;
        }

        var raw_tokens = value.split(' ');
        $.each(raw_tokens, function(idx, value) {
            var colon = value.indexOf(':');
            if(value.slice(0, 1) === '+') {
                filters.tags.push(value.slice(1));
            } else if (colon > -1) {
                var key = value.slice(0, colon);
                var sliced_value = value.slice(colon + 1);
                filters.fields[key] = sliced_value;
            } else {
                filters.description.push(value);
            }
        });
        return filters;
    }),
    unsortedPendingTasks: Ember.computed('enteredFilters', 'model.@each.status', function() {
        var filters = this.get('enteredFilters');
        var result = this.get('model').filter(function(item, idx, enumerable) {
            var ok = true;

            Object.getOwnPropertyNames(filters.fields).forEach(function(field) {
                var filter_value = filters.fields[field];
                var item_value = item.get(field);
                if(item_value instanceof Date) {
                    item_value = moment(item_value).format('YYYY-MM-DDTHH:mm:ssZ');
                    if(filter_value === 'today') {
                        filter_value = moment().format('YYYY-MM-DD');
                    } else if(filter_value === 'tomorrow') {
                        filter_value = moment().add(1, 'days').format('YYYY-MM-DD');
                    }
                }

                try {
                    if(!item_value || item_value.indexOf(filter_value) !== 0) {
                        ok = false;
                    }
                }catch(e) {
                    // This means we tried to filter a non-string value :-|
                    ok = false;
                }
            });
            if(!ok) {
                return ok;
            }

            filters.tags.forEach(function(tag) {
                if(item.get('tags').indexOf(tag) < 0) {
                    ok = false;
                }
            });
            if(!ok) {
                return ok;
            }

            var description = filters.description.join(' ');
            if(description && item.get('description').indexOf(description) < 0) {
                ok = false;
            }

            return ok;
        });

        return result;
    }),
    pendingTasks: Ember.computed.sort('unsortedPendingTasks', 'sortProperties'),
    actions: {
        prev_task: function() {
            var current_id = this.get('taskController.model.id');
            var array = this.get('pendingTasks');
            var last_task = null;
            var target_task = null;
            array.forEach(function(item, idx, enumerable){
                if(item.get('id') === current_id) {
                    target_task = last_task;
                }
                last_task = item;
            }.bind(this));
            if(target_task) {
                this.transitionToRoute('task', target_task);
            }
        },
        next_task: function() {
            var current_id = this.get('taskController.model.id');
            var array = this.get('pendingTasks');
            var found_my_id = false;
            var target_task = null;
            array.forEach(function(item, idx, enumerable){
                if(found_my_id && target_task == null) {
                    target_task = item;
                }
                if(item.get('id') === current_id) {
                    found_my_id = true;
                }
            }.bind(this));
            if(target_task) {
                this.transitionToRoute('task', target_task);
            }
        }
    }
});

export default controller;
<commit_msg>[#258] Do not attempt to check tags if none exist.<commit_after>import Ember from "ember";
import ArrayController from 'ember-legacy-controllers/array';

var controller = ArrayController.extend({
    taskController: Ember.inject.controller('task'),
    applicationController: Ember.inject.controller('application'),
    sortProperties: ['urgency:desc'],
    sortAscending: false,
    defaultFilter: {
        fields: {
            'status': 'pending'
        },
        description: [],
        tags: [],
    },
    ajaxRequest: function(params) {
        return this.get('applicationController').ajaxRequest(params);
    },
    refresh: function(){
        // First, request a synchronous sync
        return this.ajaxRequest({
            url: this.get('applicationController').urls.sync,
            type: 'POST',
        }).then(function(){
            // Then, request a new list from the endpoint to make sure
            // we gather any new tasks, too.
            this.store.findAll('task').then(function(){
                // Refresh each entry to see if it has been closed.
                this.get('content').forEach(function(model){
                    try {
                        model.reload();
                    } catch(e) {
                        // pass
                    }
                }.bind(this));
            }.bind(this));
        }.bind(this), function(msg){
            this.get('applicationController').error_message(
                `An error was encountered while ` +
                `attempting to synchronize your task list: ${msg}`
            );
        }.bind(this));
    },
    collectionObserver: function() {
        // If the collection has changed, and we're currently on the tasks
        // view, transition to showing the first task.
        var path = this.get('applicationController').getHandlerPath();
        if(path === 'application.tasks.tasks.index') {
            Ember.run.debounce(this, 'transitionToFirstTask', 100);
        }
    }.observes('model.length'),
    transitionToFirstTask: function() {
        var task = this.get('pendingTasks.firstObject');
        if(task) {
            this.transitionToRoute('task', task);
        }
    },
    enteredFilters: Ember.computed('filterString', function() {
        var value = this.get('filterString');
        var filters = JSON.parse(
            JSON.stringify(this.get('defaultFilter'))
        );

        if(!value) {
            return filters;
        }

        var raw_tokens = value.split(' ');
        $.each(raw_tokens, function(idx, value) {
            var colon = value.indexOf(':');
            if(value.slice(0, 1) === '+') {
                filters.tags.push(value.slice(1));
            } else if (colon > -1) {
                var key = value.slice(0, colon);
                var sliced_value = value.slice(colon + 1);
                filters.fields[key] = sliced_value;
            } else {
                filters.description.push(value);
            }
        });
        return filters;
    }),
    unsortedPendingTasks: Ember.computed('enteredFilters', 'model.@each.status', function() {
        var filters = this.get('enteredFilters');
        var result = this.get('model').filter(function(item, idx, enumerable) {
            var ok = true;

            Object.getOwnPropertyNames(filters.fields).forEach(function(field) {
                var filter_value = filters.fields[field];
                var item_value = item.get(field);
                if(item_value instanceof Date) {
                    item_value = moment(item_value).format('YYYY-MM-DDTHH:mm:ssZ');
                    if(filter_value === 'today') {
                        filter_value = moment().format('YYYY-MM-DD');
                    } else if(filter_value === 'tomorrow') {
                        filter_value = moment().add(1, 'days').format('YYYY-MM-DD');
                    }
                }

                try {
                    if(!item_value || item_value.indexOf(filter_value) !== 0) {
                        ok = false;
                    }
                }catch(e) {
                    // This means we tried to filter a non-string value :-|
                    ok = false;
                }
            });
            if(!ok) {
                return ok;
            }

            filters.tags.forEach(function(tag) {
                if(!item.get('tags') || item.get('tags').indexOf(tag) < 0) {
                    ok = false;
                }
            });
            if(!ok) {
                return ok;
            }

            var description = filters.description.join(' ');
            if(description && item.get('description').indexOf(description) < 0) {
                ok = false;
            }

            return ok;
        });

        return result;
    }),
    pendingTasks: Ember.computed.sort('unsortedPendingTasks', 'sortProperties'),
    actions: {
        prev_task: function() {
            var current_id = this.get('taskController.model.id');
            var array = this.get('pendingTasks');
            var last_task = null;
            var target_task = null;
            array.forEach(function(item, idx, enumerable){
                if(item.get('id') === current_id) {
                    target_task = last_task;
                }
                last_task = item;
            }.bind(this));
            if(target_task) {
                this.transitionToRoute('task', target_task);
            }
        },
        next_task: function() {
            var current_id = this.get('taskController.model.id');
            var array = this.get('pendingTasks');
            var found_my_id = false;
            var target_task = null;
            array.forEach(function(item, idx, enumerable){
                if(found_my_id && target_task == null) {
                    target_task = item;
                }
                if(item.get('id') === current_id) {
                    found_my_id = true;
                }
            }.bind(this));
            if(target_task) {
                this.transitionToRoute('task', target_task);
            }
        }
    }
});

export default controller;
<|endoftext|>


<commit_before>angular.module('material.core')
.factory('$mdConstant', MdConstantFactory);

/**
 * Factory function that creates the grab-bag $mdConstant service.
 * @ngInject
 */
function MdConstantFactory($sniffer) {

  var webkit = /webkit/i.test($sniffer.vendorPrefix);
  function vendorProperty(name) {
    return webkit ?  ('webkit' + name.charAt(0).toUpperCase() + name.substring(1)) : name;
  }

  return {
    KEY_CODE: {
      COMMA: 188,
      SEMICOLON : 186,
      ENTER: 13,
      ESCAPE: 27,
      SPACE: 32,
      PAGE_UP: 33,
      PAGE_DOWN: 34,
      END: 35,
      HOME: 36,
      LEFT_ARROW : 37,
      UP_ARROW : 38,
      RIGHT_ARROW : 39,
      DOWN_ARROW : 40,
      TAB : 9,
      BACKSPACE: 8,
      DELETE: 46
    },
    CSS: {
      /* Constants */
      TRANSITIONEND: 'transitionend' + (webkit ? ' webkitTransitionEnd' : ''),
      ANIMATIONEND: 'animationend' + (webkit ? ' webkitAnimationEnd' : ''),

      TRANSFORM: vendorProperty('transform'),
      TRANSFORM_ORIGIN: vendorProperty('transformOrigin'),
      TRANSITION: vendorProperty('transition'),
      TRANSITION_DURATION: vendorProperty('transitionDuration'),
      ANIMATION_PLAY_STATE: vendorProperty('animationPlayState'),
      ANIMATION_DURATION: vendorProperty('animationDuration'),
      ANIMATION_NAME: vendorProperty('animationName'),
      ANIMATION_TIMING: vendorProperty('animationTimingFunction'),
      ANIMATION_DIRECTION: vendorProperty('animationDirection')
    },
    /**
     * As defined in core/style/variables.scss
     *
     * $layout-breakpoint-xs:     600px !default;
     * $layout-breakpoint-sm:     960px !default;
     * $layout-breakpoint-md:     1280px !default;
     * $layout-breakpoint-lg:     1920px !default;
     *
     */
    MEDIA: {
      'xs'        : '(max-width: 599px)'                         ,
      'gt-xs'     : '(min-width: 600px)'                         ,
      'sm'        : '(min-width: 600px) and (max-width: 959px)'  ,
      'gt-sm'     : '(min-width: 960px)'                         ,
      'md'        : '(min-width: 960px) and (max-width: 1279px)' ,
      'gt-md'     : '(min-width: 1280px)'                        ,
      'lg'        : '(min-width: 1280px) and (max-width: 1919px)',
      'gt-lg'     : '(min-width: 1920px)'                        ,
      'xl'        : '(min-width: 1920px)'                        ,
      'landscape' : '(orientation: landscape)'                   ,
      'portrait'  : '(orientation: portrait)'                    ,
      'print' : 'print'
    },
    MEDIA_PRIORITY: [
      'xl',
      'gt-lg',
      'lg',
      'gt-md',
      'md',
      'gt-sm',
      'sm',
      'gt-xs',
      'xs',
      'landscape',
      'portrait',
      'print'
    ]
  };
}
<commit_msg>fix(constants): prefixes for properties should be correct.<commit_after>angular.module('material.core')
.factory('$mdConstant', MdConstantFactory);

/**
 * Factory function that creates the grab-bag $mdConstant service.
 * @ngInject
 */
function MdConstantFactory($sniffer) {

  var vendorPrefix = $sniffer.vendorPrefix;
  var isWebkit = /webkit/i.test(vendorPrefix);
  var SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g;
  var prefixTestEl = document.createElement('div');

  function vendorProperty(name) {
    // Add a dash between the prefix and name, to be able to transform the string into camelcase.
    var prefixedName = vendorPrefix + '-' + name;
    var ucPrefix = camelCase(prefixedName);
    var lcPrefix = ucPrefix.charAt(0).toLowerCase() + ucPrefix.substring(1);

    return hasStyleProperty(name)     ? name     :       // The current browser supports the un-prefixed property
           hasStyleProperty(ucPrefix) ? ucPrefix :       // The current browser only supports the prefixed property.
           hasStyleProperty(lcPrefix) ? lcPrefix : name; // Some browsers are only supporting the prefix in lowercase.
  }

  function hasStyleProperty(property) {
    return angular.isDefined(prefixTestEl.style[property]);
  }

  function camelCase(input) {
    return input.replace(SPECIAL_CHARS_REGEXP, function(matches, separator, letter, offset) {
      return offset ? letter.toUpperCase() : letter;
    });
  }

  return {
    KEY_CODE: {
      COMMA: 188,
      SEMICOLON : 186,
      ENTER: 13,
      ESCAPE: 27,
      SPACE: 32,
      PAGE_UP: 33,
      PAGE_DOWN: 34,
      END: 35,
      HOME: 36,
      LEFT_ARROW : 37,
      UP_ARROW : 38,
      RIGHT_ARROW : 39,
      DOWN_ARROW : 40,
      TAB : 9,
      BACKSPACE: 8,
      DELETE: 46
    },
    CSS: {
      /* Constants */
      TRANSITIONEND: 'transitionend' + (isWebkit ? ' webkitTransitionEnd' : ''),
      ANIMATIONEND: 'animationend' + (isWebkit ? ' webkitAnimationEnd' : ''),

      TRANSFORM: vendorProperty('transform'),
      TRANSFORM_ORIGIN: vendorProperty('transformOrigin'),
      TRANSITION: vendorProperty('transition'),
      TRANSITION_DURATION: vendorProperty('transitionDuration'),
      ANIMATION_PLAY_STATE: vendorProperty('animationPlayState'),
      ANIMATION_DURATION: vendorProperty('animationDuration'),
      ANIMATION_NAME: vendorProperty('animationName'),
      ANIMATION_TIMING: vendorProperty('animationTimingFunction'),
      ANIMATION_DIRECTION: vendorProperty('animationDirection')
    },
    /**
     * As defined in core/style/variables.scss
     *
     * $layout-breakpoint-xs:     600px !default;
     * $layout-breakpoint-sm:     960px !default;
     * $layout-breakpoint-md:     1280px !default;
     * $layout-breakpoint-lg:     1920px !default;
     *
     */
    MEDIA: {
      'xs'        : '(max-width: 599px)'                         ,
      'gt-xs'     : '(min-width: 600px)'                         ,
      'sm'        : '(min-width: 600px) and (max-width: 959px)'  ,
      'gt-sm'     : '(min-width: 960px)'                         ,
      'md'        : '(min-width: 960px) and (max-width: 1279px)' ,
      'gt-md'     : '(min-width: 1280px)'                        ,
      'lg'        : '(min-width: 1280px) and (max-width: 1919px)',
      'gt-lg'     : '(min-width: 1920px)'                        ,
      'xl'        : '(min-width: 1920px)'                        ,
      'landscape' : '(orientation: landscape)'                   ,
      'portrait'  : '(orientation: portrait)'                    ,
      'print' : 'print'
    },
    MEDIA_PRIORITY: [
      'xl',
      'gt-lg',
      'lg',
      'gt-md',
      'md',
      'gt-sm',
      'sm',
      'gt-xs',
      'xs',
      'landscape',
      'portrait',
      'print'
    ]
  };
}
<|endoftext|>


<commit_before>angular.module('UIWidgets', ['toastr'])
    .controller("HtmlSidebarToolController", function ($scope, $http, $timeout) {

        $scope.editAction = function (wdg) {
            $('#sidebarEditForm').modal('show');

            var grid = $('.grid-stack').data('gridstack');
            grid.movable('.grid-stack-item', false);
        };
    })

    .controller("HtmlSidebarController", function ($scope, $http, $timeout) {

        $scope.init = function (wdg) {
            $scope.widget = wdg;
        };

        $scope.refresh = function (wdg) {
            $http.get('/api/widget/' + wdg._id)

                .success(function (data) {
                    if (data.widget) {
                        $scope.widget = data.widget;
                    }
                })

                .error(function (errors) {
                    console.log(errors);
                });
        };
    })

    .controller("EditHtmlController", function ($scope, $http, $timeout, toastr) {
        $scope.isLoading = false;

        $scope.init = function (wdg) {
            $scope.originalWidget = wdg;
            $scope.widgetData = angular.copy(wdg);
        };

        $scope.saveWidget = function () {
            $scope.isLoading = true;

            $http.put('/api/widget/' + $scope.widgetData._id + '/edit', $scope.widgetData)

                .success(function (res) {
                    if (res.result) {
                        toastr.success('Successfully Saved');
                    }

                    $scope.isLoading = false;
                    $('#sidebarEditForm').modal('hide');

                    $scope.errors = [];

                    var grid = $('.grid-stack').data('gridstack');
                    grid.movable('.grid-stack-item', true);

                    $scope.originalWidget.options.content = res.widget.options.content;
                    $scope.originalWidget.widget = res.widget.widget;
                })

                .error(function (res) {
                    $scope.errors = res.errors;
                    $scope.isLoading = false;
                    toastr.error('Save Failed');

                    var grid = $('.grid-stack').data('gridstack');
                    grid.movable('.grid-stack-item', true);
                });
        };

        $scope.cancel = function () {
            var grid = $('.grid-stack').data('gridstack');
            grid.movable('.grid-stack-item', true);
        }
    });
<commit_msg>fix cannot edit on new install<commit_after>angular.module('UIWidgets', ['toastr'])
    .controller("HtmlSidebarToolController", function ($scope, $http, $timeout) {

        $scope.editAction = function (wdg) {
            $('#sidebarEditForm').modal('show');

            var grid = $('.grid-stack').data('gridstack');
            grid.movable('.grid-stack-item', false);
        };
    })

    .controller("HtmlSidebarController", function ($scope, $http, $timeout) {

        $scope.init = function (wdg) {
            $scope.widget = wdg;
        };

        $scope.refresh = function (wdg) {
            $http.get('/api/widget/' + wdg._id)

                .success(function (data) {
                    if (data.widget) {
                        $scope.widget = data.widget;
                    }
                })

                .error(function (errors) {
                    console.log(errors);
                });
        };
    })

    .controller("EditHtmlController", function ($scope, $http, $timeout, toastr) {
        $scope.isLoading = false;

        $scope.init = function (wdg) {
            $scope.originalWidget = wdg;
            $scope.widgetData = angular.copy(wdg);
        };

        $scope.saveWidget = function () {
            $scope.isLoading = true;

            $http.put('/api/widget/' + $scope.widgetData._id + '/edit', $scope.widgetData)

                .success(function (res) {
                    if (res.result) {
                        toastr.success('Successfully Saved');
                    }

                    $scope.isLoading = false;
                    $('#sidebarEditForm').modal('hide');

                    $scope.errors = [];

                    var grid = $('.grid-stack').data('gridstack');
                    grid.movable('.grid-stack-item', true);

                    if (!$scope.originalWidget.options)
                        $scope.originalWidget.options = {};

                    $scope.originalWidget.options.content = res.widget.options.content;
                    $scope.originalWidget.widget = res.widget.widget;
                })

                .error(function (res) {
                    $scope.errors = res.errors;
                    $scope.isLoading = false;
                    toastr.error('Save Failed');

                    var grid = $('.grid-stack').data('gridstack');
                    grid.movable('.grid-stack-item', true);
                });
        };

        $scope.cancel = function () {
            var grid = $('.grid-stack').data('gridstack');
            grid.movable('.grid-stack-item', true);
        }
    });
<|endoftext|>


<commit_before>L.Shapefile =L.GeoJSON.extend({
    initialize: function (file, options) {
        if(typeof cw !== 'undefined'){
            this.worker = cw(function(data,cb){
                importScripts('shp.js');
	            shp(data).then(cb);
            });
        }
        L.GeoJSON.prototype.initialize.call(this,{features:[]},options);
        this.addFileData(file);
    },
    addFileData:function(file){
        var self = this;
        self.fire('data:loading');
        if(typeof file !== 'string' && !('byteLength' in file)){
            var data = self.addData(file);
            self.fire('data:loaded');
            return data;
        }
        if(self.worker){
            self.worker.data(cw.makeUrl(file)).then(function(data){
                self.addData(data);
                self.fire('data:loaded');
                self.worker.close();
            });
        }else{
            shp(file).then(function(data){
                self.addData(data);
                self.fire('data:loaded');
            });
        }
        return this;
    }
});

L.shapefile= function(a,b){
    return new L.Shapefile(a,b);
}
<commit_msg>Add optional importUrl to Shapefile signature<commit_after>L.Shapefile =L.GeoJSON.extend({
    initialize: function (file, options, importUrl) {
        if(typeof cw !== 'undefined'){
            if (typeof importUrl === 'undefined') {
            	importUrl = 'shp.js';
            }
            this.worker = cw(function(data,cb){
                importScripts(importUrl);
	            shp(data).then(cb);
            });
        }
        L.GeoJSON.prototype.initialize.call(this,{features:[]},options);
        this.addFileData(file);
    },
    addFileData:function(file){
        var self = this;
        self.fire('data:loading');
        if(typeof file !== 'string' && !('byteLength' in file)){
            var data = self.addData(file);
            self.fire('data:loaded');
            return data;
        }
        if(self.worker){
            self.worker.data(cw.makeUrl(file)).then(function(data){
                self.addData(data);
                self.fire('data:loaded');
                self.worker.close();
            });
        }else{
            shp(file).then(function(data){
                self.addData(data);
                self.fire('data:loaded');
            });
        }
        return this;
    }
});

L.shapefile= function(a,b,c){
    return new L.Shapefile(a,b,c);
}
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    main.consumes = [
        "c9", "Editor", "editors", "util", "settings", "Menu", "ui",
        "preferences", "layout", "tabManager", "tree"
    ];
    main.provides = ["preview"];
    return main;

    // @todo - Add XML Plugin
    // @todo - Add JSON Plugin
    // @todo - Add Coffee Plugin
    // @todo - Add Jade Plugin
    // @todo - Add HTML/CSS/JS (auto-updating) Plugin
    // @todo - Add additional functionality, such as popout (levels, in editor, pane, browser pane)
    // @todo - Fix the activate/deactivate events on session. They leak / are not cleaned up

    function main(options, imports, register) {
        var Editor   = imports.Editor;
        var editors  = imports.editors;
        var c9       = imports.c9;
        var ui       = imports.ui;
        var util     = imports.util;
        var settings = imports.settings;
        var layout   = imports.layout;
        var tree     = imports.tree;
        var tabs     = imports.tabManager;
        var prefs    = imports.preferences;
        var Menu     = imports.Menu;

        var extensions = [];
        var counter    = 0;

        /***** Initialization *****/

        var handle     = editors.register("preview", "Preview",
                                           Preview, extensions);
        var handleEmit = handle.getEmitter();

        var previewers = {};
        var menu;

        function load(){
            var parent = layout.findParent({ name: "preview" });
            var button = !options.hideButton && new ui.button({
                skin     : "c9-toolbarbutton-glossy",
                "class"  : "preview",
                tooltip  : "Preview the current document",
                caption  : "Preview",
                disabled : true,
                onclick  : function() {
                    var tab = tabs.focussedTab;
                    if (tab && tab.editor.type === "preview" || !tab.path)
                        return;

                    // Find a good location to open preview side-by-side
                    var pane;
                    var otherPreview = search();
                    if (otherPreview && tab.pane != otherPreview) {
                        pane = otherPreview;
                    }
                    else {
                        var nodes = tab.pane.group;
                        if (!nodes)
                            pane = tab.pane.hsplit(true);
                        else {
                            pane = nodes[nodes.indexOf(tab.pane) === 0 ? 1 : 0];
                        }
                    }

                    // Open Preview
                    openPreview(tab.path, pane);
                }
            });
            button && ui.insertByIndex(parent, button, 10, handle);

            tabs.on("focus", function(e){
                var disabled = typeof e.tab.path != "string";
                button && button.setAttribute("disabled", disabled);
            }, handle);

            tabs.on("tabDestroy", function(e){
                if (e.last && button)
                    button.disable();
            }, handle);

            settings.on("read", function(e){
                settings.setDefaults("user/preview", [
                    ["running_app", "false"],
                    ["default", options.defaultPreviewer || "raw"]
                ]);
            }, handle);

            // Preferences
            prefs.add({
                "Run" : {
                    position : 600,
                    "Preview" : {
                        position : 200,
                        "Preview Running Apps" : {
                            type : "checkbox",
                            path : "user/preview/@running_app",
                            position : 4000
                        },
                        "Default Previewer" : {
                            type : "dropdown",
                            path : "user/preview/@default",
                            position : 5000,
                            items : [
                                // @todo this should come from plugin api
                                { caption: "Raw", value: "preview.raw" },
                                { caption: "Browser", value: "preview.browser" }
                            ]
                        },
                    }
                }
            }, handle);

            // Context menu for tree
            var itemCtxTreePreview = new apf.item({
                caption : "Preview",
                isAvailable : function(){
                    return tree.selectedNode && !tree.selectedNode.isFolder;
                },
                onclick : function(){
                    openPreview(tree.selected);
                }
            });
            tree.getElement("mnuCtxTree", function(mnuCtxTree) {
                ui.insertByIndex(mnuCtxTree, itemCtxTreePreview, 160, handle);
            });

            menu = new Menu({}, handle);
        }

        var drawn = false;
        function drawHandle(){
            if (drawn) return;
            drawn = true;

            // Import Skin
            ui.insertSkin({
                name         : "previewskin",
                data         : require("text!./skin.xml"),
                "media-path" : options.staticPrefix + "/images/",
                "icon-path"  : options.staticPrefix + "/images/"
            }, handle);

            // Import CSS
            var css = require("text!./style.css");
            ui.insertCss(css, options.staticPrefix, handle);

            handleEmit("draw", null, true);
        }

        //Search through pages
        function search(){
            var pane;
            tabs.getTabs().every(function(tab){
                if (tab.editorType == "preview") {
                    pane = tab.pane;
                    return false;
                }
                return true;
            });
            return pane;
        }

        function registerPlugin(plugin, matcher){
            previewers[plugin.name] = {
                plugin  : plugin,
                matcher : matcher
            };
        }

        function unregisterPlugin(plugin){
            delete previewers[plugin.name];
        }

        function openPreview(path, pane){
            tabs.open({
                name       : "preview-" + path,
                editorType : "preview",
                pane       : pane,
                active     : true,
                document   : {
                    preview : {
                        path : path
                    }
                }
            }, function(){});
        }

        function findPreviewer(path, id){
            if (id) return previewers[id].plugin;
            else if (path) {
                for (id in previewers) {
                    if (previewers[id].matcher(path))
                        return previewers[id].plugin;
                }
            }

            id = settings.get("user/preview/@default");
            return previewers[id].plugin;
        }

        /**
         * The preview handle, responsible for managing preview plugins.
         * This is the object you get when you request the preview
         * service in your plugin.
         *
         * Example:
         *
         *     define(function(require, exports, module) {
         *         main.consumes = ["preview"];
         *         main.provides = ["myplugin"];
         *         return main;
         *
         *         function main(options, imports, register) {
         *             var preview = imports.preview;
         *
         *             var previewer = preview.findPreviewer("preview.browser");
         *         });
         *     });
         *
         * @class preview
         * @extends Plugin
         * @singleton
         */
        handle.freezePublicAPI({
            /**
             * The menu shown to select the previewer
             * @property {Menu} previewMenu
             */
            get previewMenu(){ return menu; },

            /**
             * Adds a previewer to the list of known previewers.
             *
             * *N.B. The {@link Previewer} base class already calls this method.*
             *
             * @param {Previewer} previewer  the previewer to register.
             * @private
             */
            register : registerPlugin,

            /**
             * Removes a previewer from the list of known previewers.
             *
             * *N.B. The {@link Previewer} base class already calls this method.*
             *
             * @param {Previewer} previewer  the previewer to unregister.
             * @private
             */
            unregister : unregisterPlugin,

            /**
             * Retrieves a previewer based on a file path or id.
             * @param {String} path  The path of the file that is to be previewed
             * @param {String} id    The unique name of the previewer to retrieve
             * @return {Previewer}
             */
            findPreviewer : findPreviewer,
        });

        handle.on("load", load);

        function Preview(){
            var plugin = new Editor("Ajax.org", main.consumes, extensions);
            //var emit   = plugin.getEmitter();

            var currentDocument, currentSession;
            var container, txtPreview, btnMode;

            plugin.on("draw", function(e){
                drawHandle();

                // Create UI elements
                var bar = e.tab.appendChild(new ui.vsplitbox({
                    anchors    : "0 0 0 0",
                    childNodes : [
                        new ui.hsplitbox({
                            "class"    : "toolbar-top previewbar",
                            height     : 35,
                            edge       : "4",
                            padding    : 3,
                            childNodes : [
                                new ui.button({
                                    skin    : "btn-preview-nav",
                                    skinset : "previewskin",
                                    "class" : "refresh",
                                    width   : "30",
                                    onclick : function(e){ reload(); }
                                }),
                                new ui.hsplitbox({
                                    padding    : 3,
                                    childNodes : [
                                        new ui.bar({
                                            id         : "locationbar",
                                            "class"    : "locationbar",
                                            childNodes : [
                                                new ui.textbox({
                                                    id          : "txtPreview",
                                                    class       : "ace_searchbox tb_textbox searchbox searchTxt tb_console",
                                                    value       : "",
                                                    focusselect : true
                                                }),
                                                new ui.button({
                                                    id      : "btnMode",
                                                    submenu : menu.aml,
                                                    icon    : "page_white.png",
                                                    skin    : "btn-preview-choice",
                                                    skinset : "previewskin",
                                                    caption : "browser"
                                                })
                                            ]
                                        }),
                                        new ui.button({
                                            skin    : "btn-preview-nav",
                                            skinset : "previewskin",
                                            width   : 30,
                                            "class" : "popout",
                                            onclick : function(e){ popout(); }
                                        })
                                    ]
                                })
                            ]
                        }),
                        new ui.bar({
                            id : "container"
                        })
                    ]
                }));
                plugin.addElement(bar);

                btnMode    = plugin.getElement("btnMode");
                txtPreview = plugin.getElement("txtPreview");
                container  = plugin.getElement("container").$int;

                txtPreview.$input.onkeydown = function(e){
                    if (e.keyCode == 13) {
                        currentSession.previewer.navigate({ url: this.value });
                        txtPreview.blur();
                    }
                }
            })

            /***** Method *****/

            function reload(){
                var session = currentSession;
                if (session)
                    session.previewer.reload();
            }

            function popout(){
                currentSession.previewer.popout();
            }

            function setPreviewer(id){
                var session = currentSession;
                if (session) {
                    // Check if previewer is available
                    if (!previewers[id])
                        return layout.showError("Could not find previewer:" + id);

                    // If this previewer is already active, do nothing
                    if (session.previewer.name == id)
                        return;

                    var doc   = currentDocument;
                    var state = plugin.getState(doc);

                    // Unload the previous previewer
                    if (session.previewer) {
                        session.cleanUp();
                        session.previewer.unloadDocument(doc);
                    }

                    // Enable the new previewer
                    var previewer = previewers[id].plugin;
                    session.previewer = previewer;

                    previewer.loadDocument(doc, plugin, state);
                    previewer.activateDocument(doc);
                    previewer.navigate({ url: session.path });
                }
            }

            function setLocation(value){
                txtPreview.setValue(value);
            }

            function setButtonStyle(caption, icon) {
                btnMode.setCaption(caption);
                btnMode.setIcon(icon);
            }

            /***** Lifecycle *****/

            plugin.on("load", function(){
            });
            plugin.on("documentLoad", function(e){
                var doc     = e.doc;
                var session = doc.getSession();

                doc.tab.backgroundColor = "rgb(41, 41, 41)";
                doc.tab.className.add("dark");

                // session.path = session.path || e.state.path;
                session.initPath = session.path || e.state.path;

                session.previewer = findPreviewer(session.initPath, (e.state || 0).previewer);
                session.previewer.loadDocument(doc, plugin);

                tabs.on("open", function(e){
                    if (!session.previewTab && e.options.path == session.path) {
                        session.previewTab = e.tab;
                        session.previewer.navigate({ url : session.path, tab: e.tab });
                    }
                }, session);
            });
            plugin.on("documentActivate", function(e){
                if (currentDocument)
                    currentSession.previewer.deactivateDocument(currentDocument);

                currentDocument = e.doc;
                currentSession  = e.doc.getSession();

                var previewer = currentSession.previewer;
                previewer.activateDocument(currentDocument);

                // @todo shouldn't previewTab be set here?
                if (currentSession.initPath) {
                    previewer.navigate({ url: currentSession.initPath });
                    delete currentSession.initPath;
                }
            });
            plugin.on("documentUnload", function(e){
                var session = e.doc.getSession();
                session.previewer.navigate(e.doc, true); // Remove the listener
                session.previewer.unloadDocument(e.doc);

                if (session == currentSession) {
                    currentDocument = null;
                    currentSession  = null;
                }
            });
            plugin.on("getState", function(e){
                var state = e.state;
                var session = e.doc.getSession();

                state.path      = session.path;
                state.previewer = session.previewer.name;

                session.previewer.getState(e.doc, state);
            });
            plugin.on("setState", function(e){
                var state   = e.state;
                var session = e.doc.getSession();

                session.path      = state.path;
                // session.previewer = state.previewer;

                session.previewer.setState(e.doc, state);
            });
            plugin.on("clear", function(){
            });
            plugin.on("focus", function(e){
                if (currentSession)
                    currentSession.previewer.focus(e);
            });
            plugin.on("blur", function(e){
                if (currentSession)
                    currentSession.previewer.blur(e);
            });
            plugin.on("enable", function(){
            });
            plugin.on("disable", function(){
            });
            plugin.on("unload", function(){
                // unload all previewers?
            });

            /***** Register and define API *****/

            /**
             * Preview pane for previewing files and content in a Cloud9 tab.
             *
             * There are a few default previewers (i.e.
             * {@link preview.browser browser}, {@link preview.raw raw},
             * {@link preview.markdown markdown}).
             *
             * It's easy to make additional previewers. See {@link Previewer}.
             *
             * Plugins can open a preview tab using the {@link tab} API:
             *
             *     tabManager.open({
             *         editorType : "preview",
             *         active     : true,
             *         document   : {
             *             preview : {
             *                 path: "https://c9.io"
             *             }
             *         }
             *     }, function(err, tab) {});
             *
             * Alternatively, use an urlView to open just the page without
             * the browser controls and URL bar:
             *
             *     tabManager.open({
             *         value      : "http://www.c9.io",
             *         editorType : "urlview",
             *         active     : true,
             *         document   : {
             *             urlview : {
             *                 backgroundColor : "#FF0000",
             *                 dark            : true
             *             }
             *         }
             *     }, function(err, tab) {})
             **/
            plugin.freezePublicAPI({
                /**
                 * The HTML element to attach your custom previewer to.
                 * @property {HTMLElement} container
                 */
                get container(){ return container; },

                /**
                 * Trigger a reload of the content displayed in the previewer.
                 */
                reload : reload,

                /**
                 * Pop the previewer out of the Cloud9 tab into a new window.
                 * @ignore Not implemented
                 */
                popout : popout,

                /**
                 * Change to a different previewer for the displayed content.
                 * @param {String} name  The name of the previewer to show (e.g. "previewer.browser").
                 */
                setPreviewer : setPreviewer,

                /**
                 * Set the value of the location bar of the preview pane.
                 * @param {String} value  The value of the location bar.
                 */
                setLocation : setLocation,

                /**
                 * Set the icon and label of the button in the preview bar that
                 * allows users to choose which previewer to use.
                 * @param {String} caption  The caption of the button.
                 * @param {String} icon     The icon of the button.
                 */
                setButtonStyle : setButtonStyle
            });

            plugin.load("preview" + counter++);

            return plugin;
        }

        register(null, {
            preview: handle
        });
    }
});<commit_msg>Fixes +193<commit_after>define(function(require, exports, module) {
    main.consumes = [
        "c9", "Editor", "editors", "util", "settings", "Menu", "ui",
        "preferences", "layout", "tabManager", "tree"
    ];
    main.provides = ["preview"];
    return main;

    // @todo - Add XML Plugin
    // @todo - Add JSON Plugin
    // @todo - Add Coffee Plugin
    // @todo - Add Jade Plugin
    // @todo - Add HTML/CSS/JS (auto-updating) Plugin
    // @todo - Add additional functionality, such as popout (levels, in editor, pane, browser pane)
    // @todo - Fix the activate/deactivate events on session. They leak / are not cleaned up

    function main(options, imports, register) {
        var Editor   = imports.Editor;
        var editors  = imports.editors;
        var c9       = imports.c9;
        var ui       = imports.ui;
        var util     = imports.util;
        var settings = imports.settings;
        var layout   = imports.layout;
        var tree     = imports.tree;
        var tabs     = imports.tabManager;
        var prefs    = imports.preferences;
        var Menu     = imports.Menu;

        var extensions = [];
        var counter    = 0;

        /***** Initialization *****/

        var handle     = editors.register("preview", "Preview",
                                           Preview, extensions);
        var handleEmit = handle.getEmitter();

        var previewers = {};
        var menu;

        function load(){
            var parent = layout.findParent({ name: "preview" });
            var button = !options.hideButton && new ui.button({
                skin     : "c9-toolbarbutton-glossy",
                "class"  : "preview",
                tooltip  : "Preview the current document",
                caption  : "Preview",
                disabled : true,
                onclick  : function() {
                    var tab = tabs.focussedTab;
                    if (tab && tab.editor.type === "preview" || !tab.path)
                        return;

                    // Find a good location to open preview side-by-side
                    var pane;
                    var otherPreview = search();
                    if (otherPreview && tab.pane != otherPreview) {
                        pane = otherPreview;
                    }
                    else {
                        var nodes = tab.pane.group;
                        if (!nodes)
                            pane = tab.pane.hsplit(true);
                        else {
                            pane = nodes[nodes.indexOf(tab.pane) === 0 ? 1 : 0];
                        }
                    }

                    // Open Preview
                    openPreview(tab.path, pane);
                }
            });
            button && ui.insertByIndex(parent, button, 10, handle);

            tabs.on("focus", function(e){
                var disabled = typeof e.tab.path != "string";
                button && button.setAttribute("disabled", disabled);
            }, handle);

            tabs.on("tabDestroy", function(e){
                if (e.last && button)
                    button.disable();
            }, handle);

            settings.on("read", function(e){
                settings.setDefaults("user/preview", [
                    ["running_app", "false"],
                    ["default", options.defaultPreviewer || "raw"]
                ]);
            }, handle);

            // Preferences
            prefs.add({
                "Run" : {
                    position : 600,
                    "Preview" : {
                        position : 200,
                        "Preview Running Apps" : {
                            type : "checkbox",
                            path : "user/preview/@running_app",
                            position : 4000
                        },
                        "Default Previewer" : {
                            type : "dropdown",
                            path : "user/preview/@default",
                            position : 5000,
                            items : [
                                // @todo this should come from plugin api
                                { caption: "Raw", value: "preview.raw" },
                                { caption: "Browser", value: "preview.browser" }
                            ]
                        },
                    }
                }
            }, handle);

            // Context menu for tree
            var itemCtxTreePreview = new apf.item({
                caption : "Preview",
                isAvailable : function(){
                    return tree.selectedNode && !tree.selectedNode.isFolder;
                },
                onclick : function(){
                    openPreview(tree.selected);
                }
            });
            tree.getElement("mnuCtxTree", function(mnuCtxTree) {
                ui.insertByIndex(mnuCtxTree, itemCtxTreePreview, 160, handle);
            });

            menu = new Menu({}, handle);
        }

        var drawn = false;
        function drawHandle(){
            if (drawn) return;
            drawn = true;

            // Import Skin
            ui.insertSkin({
                name         : "previewskin",
                data         : require("text!./skin.xml"),
                "media-path" : options.staticPrefix + "/images/",
                "icon-path"  : options.staticPrefix + "/images/"
            }, handle);

            // Import CSS
            var css = require("text!./style.css");
            ui.insertCss(css, options.staticPrefix, handle);

            handleEmit("draw", null, true);
        }

        //Search through pages
        function search(){
            var pane;
            tabs.getTabs().every(function(tab){
                if (tab.editorType == "preview") {
                    pane = tab.pane;
                    return false;
                }
                return true;
            });
            return pane;
        }

        function registerPlugin(plugin, matcher){
            previewers[plugin.name] = {
                plugin  : plugin,
                matcher : matcher
            };
        }

        function unregisterPlugin(plugin){
            delete previewers[plugin.name];
        }

        function openPreview(path, pane){
            tabs.open({
                name       : "preview-" + path,
                editorType : "preview",
                pane       : pane,
                active     : true,
                document   : {
                    preview : {
                        path : path
                    }
                }
            }, function(){});
        }

        function findPreviewer(path, id){
            if (id) return previewers[id].plugin;
            else if (path) {
                for (id in previewers) {
                    if (previewers[id].matcher(path))
                        return previewers[id].plugin;
                }
            }

            id = settings.get("user/preview/@default");
            return previewers[id].plugin;
        }

        /**
         * The preview handle, responsible for managing preview plugins.
         * This is the object you get when you request the preview
         * service in your plugin.
         *
         * Example:
         *
         *     define(function(require, exports, module) {
         *         main.consumes = ["preview"];
         *         main.provides = ["myplugin"];
         *         return main;
         *
         *         function main(options, imports, register) {
         *             var preview = imports.preview;
         *
         *             var previewer = preview.findPreviewer("preview.browser");
         *         });
         *     });
         *
         * @class preview
         * @extends Plugin
         * @singleton
         */
        handle.freezePublicAPI({
            /**
             * The menu shown to select the previewer
             * @property {Menu} previewMenu
             */
            get previewMenu(){ return menu; },

            /**
             * Adds a previewer to the list of known previewers.
             *
             * *N.B. The {@link Previewer} base class already calls this method.*
             *
             * @param {Previewer} previewer  the previewer to register.
             * @private
             */
            register : registerPlugin,

            /**
             * Removes a previewer from the list of known previewers.
             *
             * *N.B. The {@link Previewer} base class already calls this method.*
             *
             * @param {Previewer} previewer  the previewer to unregister.
             * @private
             */
            unregister : unregisterPlugin,

            /**
             * Retrieves a previewer based on a file path or id.
             * @param {String} path  The path of the file that is to be previewed
             * @param {String} id    The unique name of the previewer to retrieve
             * @return {Previewer}
             */
            findPreviewer : findPreviewer,
        });

        handle.on("load", load);

        function Preview(){
            var plugin = new Editor("Ajax.org", main.consumes, extensions);
            //var emit   = plugin.getEmitter();

            var currentDocument, currentSession;
            var container, txtPreview, btnMode;

            plugin.on("draw", function(e){
                drawHandle();

                // Create UI elements
                var bar = e.tab.appendChild(new ui.vsplitbox({
                    anchors    : "0 0 0 0",
                    childNodes : [
                        new ui.hsplitbox({
                            "class"    : "toolbar-top previewbar",
                            height     : 35,
                            edge       : "4",
                            padding    : 3,
                            childNodes : [
                                new ui.button({
                                    skin    : "btn-preview-nav",
                                    skinset : "previewskin",
                                    "class" : "refresh",
                                    width   : "30",
                                    onclick : function(e){ reload(); }
                                }),
                                new ui.hsplitbox({
                                    padding    : 3,
                                    childNodes : [
                                        new ui.bar({
                                            id         : "locationbar",
                                            "class"    : "locationbar",
                                            childNodes : [
                                                new ui.textbox({
                                                    id          : "txtPreview",
                                                    class       : "ace_searchbox tb_textbox searchbox searchTxt tb_console",
                                                    value       : "",
                                                    focusselect : true
                                                }),
                                                new ui.button({
                                                    id      : "btnMode",
                                                    submenu : menu.aml,
                                                    icon    : "page_white.png",
                                                    skin    : "btn-preview-choice",
                                                    skinset : "previewskin",
                                                    caption : "browser"
                                                })
                                            ]
                                        }),
                                        new ui.button({
                                            skin    : "btn-preview-nav",
                                            skinset : "previewskin",
                                            width   : 30,
                                            "class" : "popout",
                                            onclick : function(e){ popout(); }
                                        })
                                    ]
                                })
                            ]
                        }),
                        new ui.bar({
                            id : "container"
                        })
                    ]
                }));
                plugin.addElement(bar);

                btnMode    = plugin.getElement("btnMode");
                txtPreview = plugin.getElement("txtPreview");
                container  = plugin.getElement("container").$int;

                txtPreview.$input.onkeydown = function(e){
                    if (e.keyCode == 13) {
                        currentSession.previewer.navigate({ url: this.value });
                        txtPreview.blur();
                    }
                }

                txtPreview.addEventListener("contextmenu", function(e){
                    e.cancelBubble = true;
                    return true;
                });
            })

            /***** Method *****/

            function reload(){
                var session = currentSession;
                if (session)
                    session.previewer.reload();
            }

            function popout(){
                currentSession.previewer.popout();
            }

            function setPreviewer(id){
                var session = currentSession;
                if (session) {
                    // Check if previewer is available
                    if (!previewers[id])
                        return layout.showError("Could not find previewer:" + id);

                    // If this previewer is already active, do nothing
                    if (session.previewer.name == id)
                        return;

                    var doc   = currentDocument;
                    var state = plugin.getState(doc);

                    // Unload the previous previewer
                    if (session.previewer) {
                        session.cleanUp();
                        session.previewer.unloadDocument(doc);
                    }

                    // Enable the new previewer
                    var previewer = previewers[id].plugin;
                    session.previewer = previewer;

                    previewer.loadDocument(doc, plugin, state);
                    previewer.activateDocument(doc);
                    previewer.navigate({ url: session.path });
                }
            }

            function setLocation(value){
                txtPreview.setValue(value);
            }

            function setButtonStyle(caption, icon) {
                btnMode.setCaption(caption);
                btnMode.setIcon(icon);
            }

            /***** Lifecycle *****/

            plugin.on("load", function(){
            });
            plugin.on("documentLoad", function(e){
                var doc     = e.doc;
                var session = doc.getSession();

                doc.tab.backgroundColor = "rgb(41, 41, 41)";
                doc.tab.className.add("dark");

                // session.path = session.path || e.state.path;
                session.initPath = session.path || e.state.path;

                session.previewer = findPreviewer(session.initPath, (e.state || 0).previewer);
                session.previewer.loadDocument(doc, plugin);

                tabs.on("open", function(e){
                    if (!session.previewTab && e.options.path == session.path) {
                        session.previewTab = e.tab;
                        session.previewer.navigate({ url : session.path, tab: e.tab });
                    }
                }, session);
            });
            plugin.on("documentActivate", function(e){
                if (currentDocument)
                    currentSession.previewer.deactivateDocument(currentDocument);

                currentDocument = e.doc;
                currentSession  = e.doc.getSession();

                var previewer = currentSession.previewer;
                previewer.activateDocument(currentDocument);

                // @todo shouldn't previewTab be set here?
                if (currentSession.initPath) {
                    previewer.navigate({ url: currentSession.initPath });
                    delete currentSession.initPath;
                }
            });
            plugin.on("documentUnload", function(e){
                var session = e.doc.getSession();
                session.previewer.navigate(e.doc, true); // Remove the listener
                session.previewer.unloadDocument(e.doc);

                if (session == currentSession) {
                    currentDocument = null;
                    currentSession  = null;
                }
            });
            plugin.on("getState", function(e){
                var state = e.state;
                var session = e.doc.getSession();

                state.path      = session.path;
                state.previewer = session.previewer.name;

                session.previewer.getState(e.doc, state);
            });
            plugin.on("setState", function(e){
                var state   = e.state;
                var session = e.doc.getSession();

                session.path      = state.path;
                // session.previewer = state.previewer;

                session.previewer.setState(e.doc, state);
            });
            plugin.on("clear", function(){
            });
            plugin.on("focus", function(e){
                if (currentSession)
                    currentSession.previewer.focus(e);
            });
            plugin.on("blur", function(e){
                if (currentSession)
                    currentSession.previewer.blur(e);
            });
            plugin.on("enable", function(){
            });
            plugin.on("disable", function(){
            });
            plugin.on("unload", function(){
                // unload all previewers?
            });

            /***** Register and define API *****/

            /**
             * Preview pane for previewing files and content in a Cloud9 tab.
             *
             * There are a few default previewers (i.e.
             * {@link preview.browser browser}, {@link preview.raw raw},
             * {@link preview.markdown markdown}).
             *
             * It's easy to make additional previewers. See {@link Previewer}.
             *
             * Plugins can open a preview tab using the {@link tab} API:
             *
             *     tabManager.open({
             *         editorType : "preview",
             *         active     : true,
             *         document   : {
             *             preview : {
             *                 path: "https://c9.io"
             *             }
             *         }
             *     }, function(err, tab) {});
             *
             * Alternatively, use an urlView to open just the page without
             * the browser controls and URL bar:
             *
             *     tabManager.open({
             *         value      : "http://www.c9.io",
             *         editorType : "urlview",
             *         active     : true,
             *         document   : {
             *             urlview : {
             *                 backgroundColor : "#FF0000",
             *                 dark            : true
             *             }
             *         }
             *     }, function(err, tab) {})
             **/
            plugin.freezePublicAPI({
                /**
                 * The HTML element to attach your custom previewer to.
                 * @property {HTMLElement} container
                 */
                get container(){ return container; },

                /**
                 * Trigger a reload of the content displayed in the previewer.
                 */
                reload : reload,

                /**
                 * Pop the previewer out of the Cloud9 tab into a new window.
                 * @ignore Not implemented
                 */
                popout : popout,

                /**
                 * Change to a different previewer for the displayed content.
                 * @param {String} name  The name of the previewer to show (e.g. "previewer.browser").
                 */
                setPreviewer : setPreviewer,

                /**
                 * Set the value of the location bar of the preview pane.
                 * @param {String} value  The value of the location bar.
                 */
                setLocation : setLocation,

                /**
                 * Set the icon and label of the button in the preview bar that
                 * allows users to choose which previewer to use.
                 * @param {String} caption  The caption of the button.
                 * @param {String} icon     The icon of the button.
                 */
                setButtonStyle : setButtonStyle
            });

            plugin.load("preview" + counter++);

            return plugin;
        }

        register(null, {
            preview: handle
        });
    }
});<|endoftext|>