<commit_before>import BaseService from "./base"
import WinJS from "winjs";

export default class extends BaseService {
  constructor(application) {
    super(application);

    this._onNavigatingBinding = this._onNavigating.bind(this);
    this._onNavigatedBinding = this._onNavigated.bind(this);
    this._onBeforeNavigateBinding = this._onBeforeNavigate.bind(this);

    this._onResizedBinding = this._onResized.bind(this);
    this._onPopStateBinding = this._onPopState.bind(this);
    this._lastNavigationPromise = WinJS.Promise.as();

    // TODO: pull the default element from the app config
    this._element = document.createElement("div");
  }

  loadComponent(options, callback) {
    var that = this;
    super.loadComponent(options, function(err) {
      if (err)
        return callback(err);

      WinJS.Navigation.addEventListener("navigating",
        that._onNavigatingBinding);
      WinJS.Navigation.addEventListener("navigated",
        that._onNavigatedBinding);
      WinJS.Navigation.addEventListener("beforenavigate",
        that._onBeforeNavigateBinding);

      window.addEventListener("resize", that._onResizedBinding);
      window.addEventListener("popstate", that._onPopStateBinding);

      return callback();
    });
  }

  _onPopState(event) {
    var messageService = this.application.container.getService("message");
    messageService.send("navigateBackMessage");
  }

  onNavigateBackMessage(type, args) {
    if (this.viewModel && this.viewModel.overrideBackNavigation) {
      log.info("NavigationService: back navigation cancelled based on current vm getBackNavigationDisabled value");
      return;
    }
    args = args || {};
    var steps = args.steps || 1;
    return WinJS.Navigation.back(steps);
  }

  onNavigateToMessage(type, args) {
    var that = this;
    var viewKey = args.viewKey;
    var state = args.state;
    var viewTemplateUri = this.application.configuration.get("pages:" + viewKey + ":template");
    var viewClassDef = that.application.container.getViewDef(viewKey);
    var vmInstance = that.application.container.getViewModel(viewKey);
    if (viewTemplateUri && viewClassDef && vmInstance) {
      vmInstance.key = viewKey;
      vmInstance.data = args.state;

      if (this.viewModel)
        this.viewModel.onNavigateFrom();

      if (window["history"] && !vmInstance.isModal) {
        window.history.pushState({
          context: state,
          key: viewKey
        }, viewKey, "#" + viewKey);
      }

      WinJS.Navigation.navigate(viewTemplateUri, vmInstance);
    }
  }

  _onBeforeNavigate(args) {
    if (this.viewModel && this.viewModel.overrideBackNavigation) {
      log.info("NavigationService: back navigation cancelled based on current vm getBackNavigationDisabled value");
      args.preventDefault();
    }
  }

  _onNavigating(args) {
    var that = this;
    var messageService = this.application.container.getService("message");
    var newElement = this.createDefaultPageElement();
    this._element.appendChild(newElement);
    this._lastNavigationPromise.cancel();

    function cleanup() {
      if (args.detail.delta == -1) {
        if (that.view)
          that.application.container.delViewInstance(that.view.viewModel.key, that.view);
        if (that.viewModel) {
          that.application.container.delViewModelInstance(that.viewModel.key, that.viewModel);
        }

        if (that.view && that.viewModel)
           that.viewModel.dispose();
      }
      if (that._element.childElementCount > 1) {

        var oldElement = that._element.firstElementChild;

        // Cleanup and remove previous element
        if (oldElement.winControl) {
          oldElement.winControl.dispose();
        }
        oldElement.parentNode.removeChild(oldElement);
        oldElement.innerText = "";

        WinJS.Utilities.disposeSubTree(oldElement);
      }
    };

    var handleRenderError = function(err) {
      messageService.send("applicationErrorMessage", err);
    };

    if (that.viewModel && that.viewModel.isModal) {
      WinJS.Navigation.history.backStack.pop();
    }

    // TODO: archive the old view/viewModel
    this._lastNavigationPromise = WinJS.Promise.as().then(cleanup, cleanup).then(function() {
      messageService.send("navigatingMessage", args);
      return WinJS.UI.Pages.render(args.detail.location,
        newElement,
        args.detail.state).then(null, handleRenderError)
    });
    args.detail.setPromise(this._lastNavigationPromise);
  }

  _onNavigated() {
    var messageService = this.application.container.getService("message");
    messageService.send("navigatedMessage");

    this.viewModel.onNavigateTo();
  }

  _onResized() {
    if (this.view && this.view.updateLayout)
      this.view.updateLayout();
  }

  get rootElement() {
    return this._element;
  }

  createDefaultPageElement() {
    var element = document.createElement("div");
    element.setAttribute("dir", window.getComputedStyle(this._element, null).direction);
    element.style.position = "absolute";
    element.style.width = "100%";
    element.style.height = "100%";
    return element;
  }

  get view() {
    if (this.viewElement && this.viewElement.winControl)
      return this.viewElement.winControl
    return null;
  }

  get viewElement() {
    return this._element.firstElementChild;
  }

  get viewModel() {
    if (this.view) {
      if (this.view.viewModel)
        return this.view.viewModel;
    }
    return null;
  }

  unloadComponent(options, callback) {
    var that = this;
    super.unloadComponent(options, function(err) {
      if (err)
        return callback(err);

      WinJS.Navigation.removeEventListener("navigating",
        that._onNavigatingBinding);
      WinJS.Navigation.removeEventListener("navigated",
        that._onNavigatedBinding);
      WinJS.Navigation.removeEventListener("beforenavigate",
        that._onBeforeNavigateBinding);

      window.removeEventListener("resize", that._onResizedBinding);
      window.removeEventListener("popstate", that._onPopStateBinding)

      if (that._element)
        WinJS.Utilities.disposeSubTree(that._element);

      return callback();
    });
  }
}
<commit_msg>BugFix for backstack history managmenet<commit_after>import BaseService from "./base"
import WinJS from "winjs";

export default class extends BaseService {
  constructor(application) {
    super(application);

    this._onNavigatingBinding = this._onNavigating.bind(this);
    this._onNavigatedBinding = this._onNavigated.bind(this);
    this._onBeforeNavigateBinding = this._onBeforeNavigate.bind(this);

    this._onResizedBinding = this._onResized.bind(this);
    this._onPopStateBinding = this._onPopState.bind(this);
    this._lastNavigationPromise = WinJS.Promise.as();

    // TODO: pull the default element from the app config
    this._element = document.createElement("div");
  }

  loadComponent(options, callback) {
    var that = this;
    super.loadComponent(options, function(err) {
      if (err)
        return callback(err);

      WinJS.Navigation.addEventListener("navigating",
        that._onNavigatingBinding);
      WinJS.Navigation.addEventListener("navigated",
        that._onNavigatedBinding);
      WinJS.Navigation.addEventListener("beforenavigate",
        that._onBeforeNavigateBinding);

      window.addEventListener("resize", that._onResizedBinding);
      window.addEventListener("popstate", that._onPopStateBinding);

      return callback();
    });
  }

  _onPopState(event) {
    var messageService = this.application.container.getService("message");

    // Manage backstack
    var steps = 0;
    for (var i = WinJS.Navigation.history.backStack.length - 1; i >= 0; i--) {
      var item = WinJS.Navigation.history.backStack[i];
      if (item && item.state && item.state.isModal)
        steps++;
    }

    messageService.send("navigateBackMessage", {
      steps: steps
    });
  }

  onNavigateBackMessage(type, args) {
    var that = this;
    if (this.viewModel && this.viewModel.overrideBackNavigation) {
      log.info("NavigationService: back navigation cancelled based on current vm getBackNavigationDisabled value");
      return;
    }
    args = args || {};
    var steps = args.steps || 1;
    return WinJS.Navigation.back(steps);
  }

  onNavigateToMessage(type, args) {
    var that = this;

    var viewKey = args.viewKey;
    var state = args.state;
    var viewTemplateUri = this.application.configuration.get("pages:" + viewKey + ":template");
    var viewClassDef = that.application.container.getViewDef(viewKey);
    var vmInstance = that.application.container.getViewModel(viewKey);
    if (viewTemplateUri && viewClassDef && vmInstance) {
      vmInstance.key = viewKey;
      vmInstance.data = args.state;

      if (this.viewModel)
        this.viewModel.onNavigateFrom();

      WinJS.Navigation.navigate(viewTemplateUri, vmInstance);
    }
  }

  _onBeforeNavigate(args) {
    if (this.viewModel && this.viewModel.overrideBackNavigation) {
      log.info("NavigationService: back navigation cancelled based on current vm getBackNavigationDisabled value");
      args.preventDefault();
    }
  }

  /*
    Called on both Forward and Back navigation
  */
  _onNavigating(args) {
    var that = this;
    args.detail.delta = args.detail.delta || 0;
    var messageService = this.application.container.getService("message");
    var newElement = this.createDefaultPageElement();
    this._element.appendChild(newElement);
    this._lastNavigationPromise.cancel();

    function cleanup() {
      if (args.detail.delta < 0) {
        if (that.view)
          that.application.container.delViewInstance(that.view.viewModel.key, that.view);
        if (that.viewModel) {
          that.application.container.delViewModelInstance(that.viewModel.key, that.viewModel);
        }

        if (that.view && that.viewModel)
          that.viewModel.dispose();
      }
      if (that._element.childElementCount > 1) {

        var oldElement = that._element.firstElementChild;

        // Cleanup and remove previous element
        if (oldElement.winControl) {
          oldElement.winControl.dispose();
        }
        oldElement.parentNode.removeChild(oldElement);
        oldElement.innerText = "";

        WinJS.Utilities.disposeSubTree(oldElement);
      }
    };

    var handleRenderError = function(err) {
      messageService.send("applicationErrorMessage", err);
    };

    // TODO: archive the old view/viewModel
    this._lastNavigationPromise = WinJS.Promise.as().then(cleanup, cleanup).then(function() {
      messageService.send("navigatingMessage", args);
      return WinJS.UI.Pages.render(args.detail.location,
        newElement,
        args.detail.state).then(function() {

        if (args.detail.delta >= 0) {

          // Push the new view on state if last view is not modal
          var lastNavigationItem = WinJS.Navigation.history.backStack[WinJS.Navigation.history.backStack.length - 1];
          if (lastNavigationItem && lastNavigationItem.state && !lastNavigationItem.state.isModal) {
            window.history.pushState(args.detail.state.key, args.detail.state.key, "#" + args.detail.state.key)
          }
          else{
            // Update most recent history entry
            window.history.replaceState(args.detail.state.key, args.detail.state.key, "#" + args.detail.state.key)
          }
        }

      }, handleRenderError)
    });
    args.detail.setPromise(this._lastNavigationPromise);
  }

  _onNavigated(args) {
    var that = this;
    var messageService = this.application.container.getService("message");
    messageService.send("navigatedMessage");
    this.viewModel.onNavigateTo();
  }

  _onResized() {
    if (this.view && this.view.updateLayout)
      this.view.updateLayout();
  }

  get rootElement() {
    return this._element;
  }

  createDefaultPageElement() {
    var element = document.createElement("div");
    element.setAttribute("dir", window.getComputedStyle(this._element, null).direction);
    element.style.position = "absolute";
    element.style.width = "100%";
    element.style.height = "100%";
    return element;
  }

  get view() {
    if (this.viewElement && this.viewElement.winControl)
      return this.viewElement.winControl
    return null;
  }

  get viewElement() {
    return this._element.firstElementChild;
  }

  get viewModel() {
    if (this.view) {
      if (this.view.viewModel)
        return this.view.viewModel;
    }
    return null;
  }

  unloadComponent(options, callback) {
    var that = this;
    super.unloadComponent(options, function(err) {
      if (err)
        return callback(err);

      WinJS.Navigation.removeEventListener("navigating",
        that._onNavigatingBinding);
      WinJS.Navigation.removeEventListener("navigated",
        that._onNavigatedBinding);
      WinJS.Navigation.removeEventListener("beforenavigate",
        that._onBeforeNavigateBinding);

      window.removeEventListener("resize", that._onResizedBinding);
      window.removeEventListener("popstate", that._onPopStateBinding)

      if (that._element)
        WinJS.Utilities.disposeSubTree(that._element);

      return callback();
    });
  }
}
<|endoftext|>


<commit_before>/**
 * @fileoverview Provides a function that synchronizes two arrays, arr1 and
 * arr2. arr2 is a subset of arr1, it includes the elements of arr1 that passes
 * the filter. When elements are added to/removed from arr1, arr2 is updated to
 * include the elements of arr1 that pass the filter. When the order of
 * elements in arr2 changes, arr1 is reordered to have the same order as arr2.
 *
 * This can for example be used to synchronize the array of layers in the map
 * with the array of selected layers, where layers may be added to/removed from
 * the map, and the order of selected layers may change.
 *
 * Example:
 *
 * var dereg = ngeoArraySync(map.getLayers().getArray(), selectedLayers, scope,
 *     function(layer) {
 *       // exclude the layer at index 0 in the map
 *       return map.getLayers().indexOf(layer) !== 0;
 *     });
 *
 * This will return a function that can be called to cancel synchronization.
 *
 */

goog.provide('ngeo.ArraySync');

goog.require('goog.asserts');
goog.require('ngeo');

/**
 * @typedef {function(Array.<*>, Array.<*>, angular.Scope,
 *     function(*):boolean)}
 */
ngeo.ArraySync;

/**
 * @param {Array.<T>} arr1 Array 1.
 * @param {Array.<T>} arr2 Array 2.
 * @param {angular.Scope} scope Angular scope. Used to watch arr1 and arr2
 *     using $watchCollection.
 * @param {function(T):boolean} filter Filter function.
 * @return {function()} Function to call to stop synchronization
 * @template T
 */
ngeo.arraySync = function(arr1, arr2, scope, filter) {

  // Update arr2 when elements are added to, or removed from, arr1.

  var dereg1 = scope.$watchCollection(function() {
    return arr1;
  }, function() {
    var i, ii, j;
    for (i = 0, ii = arr1.length, j = 0; i < ii; ++i) {
      if (filter(arr1[i])) {
        arr2[j++] = arr1[i];
      }
    }
    arr2.length = j;
  });

  // Update arr1 when the order of elements changes in arr2.

  /**
   * @type {Array.<number>}
   */
  var indices = [];

  var dereg2 = scope.$watchCollection(function() {
    return arr2;
  }, function() {
    // find the positions in arr1 of the elements that pass the
    // filter
    var i, ii, j;
    for (i = 0, ii = arr1.length, j = 0; i < ii; ++i) {
      if (filter(arr1[i])) {
        indices[j++] = i;
      }
    }
    indices.length = j;
    // now reorder arr1
    goog.asserts.assert(indices.length == arr2.length);
    for (i = 0, ii = arr2.length; i < ii; ++i) {
      arr1[indices[i]] = arr2[i];
    }
  });

  return function() {
    dereg1();
    dereg2();
  };
};

ngeoModule.value('ngeoArraySync', ngeo.arraySync);
<commit_msg>Don't let compiler type check the arguments for arraysync filter<commit_after>/**
 * @fileoverview Provides a function that synchronizes two arrays, arr1 and
 * arr2. arr2 is a subset of arr1, it includes the elements of arr1 that passes
 * the filter. When elements are added to/removed from arr1, arr2 is updated to
 * include the elements of arr1 that pass the filter. When the order of
 * elements in arr2 changes, arr1 is reordered to have the same order as arr2.
 *
 * This can for example be used to synchronize the array of layers in the map
 * with the array of selected layers, where layers may be added to/removed from
 * the map, and the order of selected layers may change.
 *
 * Example:
 *
 * var dereg = ngeoArraySync(map.getLayers().getArray(), selectedLayers, scope,
 *     function(layer) {
 *       // exclude the layer at index 0 in the map
 *       return map.getLayers().indexOf(layer) !== 0;
 *     });
 *
 * This will return a function that can be called to cancel synchronization.
 *
 */

goog.provide('ngeo.ArraySync');

goog.require('goog.asserts');
goog.require('ngeo');

/**
 * @typedef {function(Array.<*>, Array.<*>, angular.Scope,
 *     function(?):boolean)}
 */
ngeo.ArraySync;

/**
 * @param {Array.<T>} arr1 Array 1.
 * @param {Array.<T>} arr2 Array 2.
 * @param {angular.Scope} scope Angular scope. Used to watch arr1 and arr2
 *     using $watchCollection.
 * @param {function(T):boolean} filter Filter function.
 * @return {function()} Function to call to stop synchronization
 * @template T
 */
ngeo.arraySync = function(arr1, arr2, scope, filter) {

  // Update arr2 when elements are added to, or removed from, arr1.

  var dereg1 = scope.$watchCollection(function() {
    return arr1;
  }, function() {
    var i, ii, j;
    for (i = 0, ii = arr1.length, j = 0; i < ii; ++i) {
      if (filter(arr1[i])) {
        arr2[j++] = arr1[i];
      }
    }
    arr2.length = j;
  });

  // Update arr1 when the order of elements changes in arr2.

  /**
   * @type {Array.<number>}
   */
  var indices = [];

  var dereg2 = scope.$watchCollection(function() {
    return arr2;
  }, function() {
    // find the positions in arr1 of the elements that pass the
    // filter
    var i, ii, j;
    for (i = 0, ii = arr1.length, j = 0; i < ii; ++i) {
      if (filter(arr1[i])) {
        indices[j++] = i;
      }
    }
    indices.length = j;
    // now reorder arr1
    goog.asserts.assert(indices.length == arr2.length);
    for (i = 0, ii = arr2.length; i < ii; ++i) {
      arr1[indices[i]] = arr2[i];
    }
  });

  return function() {
    dereg1();
    dereg2();
  };
};

ngeoModule.value('ngeoArraySync', ngeo.arraySync);
<|endoftext|>


<commit_before>// const IronTree = require('@denq/iron-tree');
const IronTree = require('iron-tree');
const defaultOptions = {
  key_id: 'id' ,
  key_parent: 'parent' ,
  key_child: 'child',
  empty_children: false,
};

// function sortBy(propertyA, propertyB) {
//   return function(a, b) {
//     if (a.get(propertyB) < b.get(propertyB)) {
//       if (a.get(propertyA) > b.get(propertyA)) {
//         return 1;
//       }
//       return -1;
//     } else {
//       if (a.get(propertyA) < b.get(propertyA)) {
//         return -1;
//       }
//       return 1;
//     }
//   };
// };
function sortBy(collection, propertyA, propertyB) {
    return collection.sort(function(a, b) {
        if (a[propertyB] < b[propertyB]) {
            if (a[propertyA] > b[propertyA]) {
                return 1;
            }
            return -1;
        } else {
            if (a[propertyA] < b[propertyA]) {
                return -1;
            }
            return 1;
        }
    });
};

module.exports = class LTT{

  constructor(list, options = {}) {
    options = Object.assign(options, defaultOptions);
    this.options = options;
    const { key_id, key_parent } = options;

    const tree = new IronTree({ [key_id]: 0 });
    sortBy(list, key_parent, key_id);
    list.forEach((item, index) => {
      tree.add((parentNode) => {
        return parentNode.get(key_id) === item[key_parent];
      }, item);
    });

    this.tree = tree;
  }

  GetTree() {
    const { key_child, empty_children } = this.options;
    return this.tree.toJson({
      key_children: key_child,
      empty_children,
    })[key_child];
  }

}
<commit_msg>All test pass with 'iron tree'<commit_after>// const IronTree = require('@denq/iron-tree');
const IronTree = require('iron-tree');
const defaultOptions = {
  key_id: 'id' ,
  key_parent: 'parent' ,
  key_child: 'child',
  empty_children: false,
};

function sortBy(collection, propertyA, propertyB) {
  return collection.sort(function(a, b) {
    if (a[propertyB] < b[propertyB]) {
      if (a[propertyA] > b[propertyA]) {
        return 1;
      }
      return -1;
    } else {
      if (a[propertyA] < b[propertyA]) {
        return -1;
      }
      return 1;
    }
  });
};

module.exports = class LTT{

  constructor(list, options = {}) {
    options = Object.assign({}, defaultOptions, options);
    this.options = options;
    const { key_id, key_parent } = options;

    sortBy(list, key_parent, key_id);
    const tree = new IronTree({ [key_id]: 0 });
    list.forEach((item, index) => {
      tree.add((parentNode) => {
        return parentNode.get(key_id) === item[key_parent];
      }, item);
    });

    this.tree = tree;
  }

  GetTree() {
    const { key_child, empty_children } = this.options;
    return this.tree.toJson({
      key_children: key_child,
      empty_children: false,
    })[key_child];
  }

}
<|endoftext|>


<commit_before>//////////////////////////////////
//MagJS
//////////////////////////////////
/**!
 * @name mag.js - Copyright (c) 2013, 2014 Michael Glazer
 * @description MagnumJS core code library
 * @author Michael Glazer
 * @date 4/14/14
 * @plunker - http://embed.plnkr.co/ZqpuhSsnMPcCNz9vufay/preview
 * @version 0.1 - Alpha - 0.2.1
 * @license MIT https://github.com/magnumjs/mag.js/blob/master/LICENSE
 * @link https://github.com/magnumjs
 */
!function(e,t){var s="warn";window.log=function(){var e=[].shift.apply(arguments),t=Array.prototype.slice.call(arguments);e==s&&console&&console[s](t.join(","))},e.reserved=["__requires","__instance"],e.aspect={injectors:[],namespace:null,add:function(t,s,n){e.aspect.injectors.push({type:t,name:s,fun:n})},attach:function(){for(var t in e.aspect.injectors){var s=e.aspect.injectors[t];e.aspect[s.type]&&e.aspect[s.type](s.name,s.fun)}},around:function(t,s){var n=e.aspect.namespace;for(var i in e.aspect.namespace)"function"==typeof n[i]&&i.match(t)&&!function(e,t,n){n[t]=function(){return s.call(n,{fn:e,fnName:t,arguments:arguments})}}(n[i],i,n)},before:function(t,s){e.aspect.around(t,function(t){return s.apply(e.aspect.namespace,t.arguments),e.aspect.next(t)})},after:function(t,s){e.aspect.around(t,function(t){var n=e.aspect.next(t);return s.apply(e.aspect.namespace,t.arguments),n})},next:function(t){return t.fn.apply(e.aspect.namespace,t.arguments)}},e.inject=function(t){e.aspect.namespace=t,e.aspect.attach()},e.module=function(s,n){function i(e){var t;if("function"!=typeof e){t=e,mfun=t.pop();var s=""+mfun,n=s.substring(s.indexOf("{")+1,s.lastIndexOf("}"));e=Function(t.join(),n)}return[e,t]}log("info","module name:"+s),this.modules=this.modules||{};var r=this.modules[s];if(r&&(!n||n&&0==n.length))return r;var a={namespace:t,dependencies:{},waiting:[],findArgs:function(e){if("function"==typeof e){var t=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,s=/,/,n=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,i=(""+e).replace(n,""),r=i.match(t),a=r[1].split(s).map(function(e){return e.trim()});return a}},getInstance:function(e){return this.instances=this.instances||{},this.instances[this.namespace]=this.instances[this.namespace]||{},this.instances[this.namespace][e]?this.instances[this.namespace][e]:t},setInstance:function(e,t){this.instances[this.namespace][e]=t},process:function(e,t,s){function n(e,t,s){function n(){return e.apply(s||this,t)}return n.prototype=e.prototype,new n}var i=this.findArgs(e),r=t||i;if(s){var a=this.getInstance(s);return a?a:(a=n(e,this.getArrayDependencies(r)),this.setInstance(s,a),a)}if(this.isRegistered(r))e.apply(e,this.getArrayDependencies(r));else{var c={target:e,args:r};this.waiting.push(c)}},isRegistered:function(e){var t=!0;log("info","isRegistered args:",e);for(var s in e){var n=e[s];if(!this.getDependencies()[n]){log("warn","Dependency not registered when called:",n),t=!1;break}}return t},getArrayDependencies:function(e){var t=this.getDependencies(),s=this;return e.map(function(e){return t[e]&&t[e].__requires&&(log("info","this dependency has dependencies: "+e),log("info","requires: "+t[e].__requires)),t[e]&&t[e].__instance?s.process(t[e],null,e):t[e]})},getDependencies:function(e){return this.dependencies[e||this.namespace]||{}},register:function(e,t,s){var n=this.findArgs(t);log("info",e+" requires "+n),this.getDependencies()[e]=t,s&&(this.getDependencies()[e].__instance=s),this.getDependencies()[e].__requires=n,this.service()},service:function(){for(var e in this.waiting){var t=this.waiting[e];this.isRegistered(t.args)&&(t.target.apply(t.target,this.getArrayDependencies(t.args)),delete this.waiting[e])}}};if(a.namespace=s,a.dependencies[s]={},n){var c=function(e){for(var t=[],s=0,n=e.length;n>s;s++){var i=e[s];if(this.modules[i]){var r=this.modules[i];t.push(r);for(var c in r.services)a.register(c,r.services[c],1);for(var o in r.factories)a.register(o,r.factories[o]())}}}.bind(this);c(n)}return this.modules[s]=new function(){this.name=s,this.config=function(e){a.process(e)},this.service=function(e,t){this.services=this.services||{},this.services[e]=this.services[e]||t,a.register(e,t,1)},this.factory=function(e,t){this.factories=this.factories||{},this.factories[e]=this.factories[e]||t,a.register(e,this.factories[e]())},this.control=function(e,t){this.controls=this.controls||{},a.register("Scope",this.getScope(e));var s=i(t);this.fire("mag.control.process.begin",[e]),a.process(s[0],s[1]),this.fire("mag.control.process.end",[e])},this.getScope=function(e){return this.controls=this.controls||{},this.controls[e]=this.controls[e]||{}},this.observers={},this.on=function(e,t){for(e=e.split(/\s+/);eventName=e.shift();)this.observers[eventName]||(this.observers[eventName]=[]),this.observers[eventName].push(t)},this.fire=function(e,t){if(this.observers[e])for(var s=0;s<this.observers[e].length;s++)this.observers[e][s].apply(this,t)},e.inject(this)}}}(window.mag={});!function(){var e=Object.prototype.toString;mag.template.serve=function(e){mag.aspect.next(e);var t=e.arguments[0],n=this.getScope(t),s=this;this.on("propertyChanged",function(){mag.template.parse(s,t,n)}),mag.template.parse(s,t,n)},mag.template.parse=function(t,n,s){log("info","template parse start"+n);var i=document.getElementById(n);t.fire("mag.template.begin",[n]),this.templates=this.templates||{},this.templates[n]=this.templates[n]||i?i:0,this.template=this.templates[n];var i=this.template;if(i&&""!=this.template){var r=i.parentNode;i.parentNode.removeChild(i);var a=mag.reserved;this.applyVar=function(e,t,n){if(e.nodeType){var s=e.getElementsByClassName(t),i=s.length;for(1>i&&this.setVar(e,t,n);i--;)this.setVar(e,t,n,s,i)}},this.setVar=function(e,t,n,s,i){var r="function"==typeof n[t]?n[t].call(this):n[t];this.pattern=this.pattern||RegExp("\\[\\[(.*?)\\]\\]","g"),e.innerHTML=e.innerHTML.replace(this.pattern,function(e,n){return r&&t==n&&-1===a.indexOf(t)?r:e}),r&&s&&-1===a.indexOf(t)&&""==s[i].innerText&&(s[i].innerText=r)},this.applyVars=function(e,t){for(var n in t)this.applyVar(e,n,t)},this.parser=function(t,n){for(var s in n)if("[object Array]"===e.call(n[s])){var i=t.getElementsByClassName(s);if(!i[0])return;for(var r=i[0].cloneNode(!0),a=n[s],o=0;o<a.length;o++){var c=r.cloneNode(!0);a[o],this.applyVars(c,a[o]),i[0].parentNode.appendChild(c)}i[0].parentNode.removeChild(i[0])}else this.applyVar(t,s,n)},this.parser(i,s),t.fire("mag.template.end",[n]),r.appendChild(i)}},mag.aspect.add("around","control",mag.template.serve)}(window.mag=window.mag||{},mag.template={});Object.prototype.watch||Object.defineProperty(Object.prototype,"__watch",{enumerable:!1,configurable:!0,writable:!1,value:function(e,t){var n=this[e],s=n,i=function(){return s},r=function(i){n=s;var r=this;return t.call(r,e,n,i),s};delete this[e]&&(Object.defineProperty?Object.defineProperty(this,e,{get:i,set:r}):Object.prototype.__defineGetter__&&Object.prototype.__defineSetter__&&(Object.prototype.__defineGetter__.call(this,e,i),Object.prototype.__defineSetter__.call(this,e,r)))}}),function(e,t){mag.watch.throttle=function(e,t,n){t||(t=250);var s,i;return function(){var r=n||this,a=+new Date,o=arguments;s&&s+t>a?(clearTimeout(i),i=setTimeout(function(){s=a,e.apply(r,o)},t)):(s=a,e.apply(r,o))}},mag.watch.serve=function(e){var n=this;this.getScope(e),this.controls.__watch(e,mag.watch.throttle(function(e,s,i){JSON.stringify(s)!==JSON.stringify({})&&JSON.stringify(s)!==JSON.stringify({ignoreKey:t})&&n.fire("propertyChanged",[e,s,i])},250,n))},mag.aspect.add("before","control",mag.watch.serve)}(window.mag=window.mag||{},mag.watch={});
<commit_msg>Update mag.full-0.2.min.js<commit_after>//////////////////////////////////
//MagJS
//////////////////////////////////
/**!
 * @name mag.js - Copyright (c) 2013, 2014 Michael Glazer
 * @description MagnumJS core code library
 * @requires - jQuery http://www.jquery.com
 * @author Michael Glazer
 * @date 4/16/2014
 * @version Alpha - 0.2.15
 * @license MIT https://github.com/magnumjs/mag.js/blob/master/LICENSE
 * @link https://github.com/magnumjs
 */
 !function(e,t){var s="warn";window.log=function(){var e=[].shift.apply(arguments),t=Array.prototype.slice.call(arguments);e==s&&console&&console[s](t.join(","))},e.reserved=["__requires","__instance"],e.aspect={injectors:[],namespace:null,add:function(t,s,n){e.aspect.injectors.push({type:t,name:s,fun:n})},attach:function(){for(var t in e.aspect.injectors){var s=e.aspect.injectors[t];e.aspect[s.type]&&e.aspect[s.type](s.name,s.fun)}},around:function(t,s){var n=e.aspect.namespace;for(var i in e.aspect.namespace)"function"==typeof n[i]&&i.match(t)&&!function(e,t,n){n[t]=function(){return s.call(n,{fn:e,fnName:t,arguments:arguments})}}(n[i],i,n)},before:function(t,s){e.aspect.around(t,function(t){return s.apply(e.aspect.namespace,t.arguments),e.aspect.next(t)})},after:function(t,s){e.aspect.around(t,function(t){var n=e.aspect.next(t);return s.apply(e.aspect.namespace,t.arguments),n})},next:function(t){return t.fn.apply(e.aspect.namespace,t.arguments)}},e.inject=function(t){e.aspect.namespace=t,e.aspect.attach()},e.module=function(s,n){function i(e){var t;if("function"!=typeof e){t=e,mfun=t.pop();var s=""+mfun,n=s.substring(s.indexOf("{")+1,s.lastIndexOf("}"));e=Function(t.join(),n)}return[e,t]}log("info","module name:"+s),this.modules=this.modules||{};var r=this.modules[s];if(r&&(!n||n&&0==n.length))return r;var a={namespace:t,dependencies:{},waiting:[],findArgs:function(e){if("function"==typeof e){var t=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,s=/,/,n=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,i=(""+e).replace(n,""),r=i.match(t),a=r[1].split(s).map(function(e){return e.trim()});return a}},getInstance:function(e){return this.instances=this.instances||{},this.instances[this.namespace]=this.instances[this.namespace]||{},this.instances[this.namespace][e]?this.instances[this.namespace][e]:t},setInstance:function(e,t){this.instances[this.namespace][e]=t},process:function(e,t,s){function n(e,t,s){function n(){return e.apply(s||this,t)}return n.prototype=e.prototype,new n}var i=this.findArgs(e),r=t||i;if(s){var a=this.getInstance(s);return a?a:(a=n(e,this.getArrayDependencies(r)),this.setInstance(s,a),a)}if(this.isRegistered(r))e.apply(e,this.getArrayDependencies(r));else{var c={target:e,args:r};this.waiting.push(c)}},isRegistered:function(e){var t=!0;log("info","isRegistered args:",e);for(var s in e){var n=e[s];if(!this.getDependencies()[n]){log("info","Dependency not registered when called:",n),t=!1;break}}return t},getArrayDependencies:function(e){var t=this.getDependencies(),s=this;return e.map(function(e){return t[e]&&t[e].__requires&&(log("info","this dependency has dependencies: "+e),log("info","requires: "+t[e].__requires)),t[e]&&t[e].__instance?s.process(t[e],null,e):t[e]})},getDependencies:function(e){return this.dependencies[e||this.namespace]||{}},register:function(e,t,s){var n=this.findArgs(t);log("info",e+" requires "+n),this.getDependencies()[e]=t,s&&(this.getDependencies()[e].__instance=s),this.getDependencies()[e].__requires=n,this.service()},service:function(){for(var e in this.waiting){var t=this.waiting[e];this.isRegistered(t.args)&&(t.target.apply(t.target,this.getArrayDependencies(t.args)),delete this.waiting[e])}}};if(a.namespace=s,a.dependencies[s]={},n){var c=function(e){for(var t=[],s=0,n=e.length;n>s;s++){var i=e[s];if(this.modules[i]){var r=this.modules[i];t.push(r);for(var c in r.services)a.register(c,r.services[c],1);for(var o in r.factories)a.register(o,r.factories[o]())}}}.bind(this);c(n)}return this.modules[s]=new function(){this.name=s,this.config=function(e){a.process(e)},this.service=function(e,t){this.services=this.services||{},this.services[e]=this.services[e]||t,a.register(e,t,1)},this.factory=function(e,t){this.factories=this.factories||{},this.factories[e]=this.factories[e]||t,a.register(e,this.factories[e]())},this.control=function(e,t){this.controls=this.controls||{},a.register("Scope",this.getScope(e));var s=i(t);this.fire("mag.control.process.begin",[e]),a.process(s[0],s[1]),this.fire("mag.control.process.end",[e])},this.getScope=function(e){return this.controls=this.controls||{},this.controls[e]=this.controls[e]||{}},this.observers={},this.on=function(e,t){for(e=e.split(/\s+/);eventName=e.shift();)this.observers[eventName]||(this.observers[eventName]=[]),this.observers[eventName].push(t)},this.fire=function(e,t){if(this.observers[e])for(var s=0;s<this.observers[e].length;s++)this.observers[e][s].apply(this,t)},e.inject(this)}}}(window.mag={});!function(e,t,n,s){function r(e){this.selectorDataKey=u,this.nodeContext=e||s}function a(e){var t=e.childNodes,n=[];for(i=0;i<t.length;i+=1)t[i].nodeType===c&&n.push(t[i]);return n}function o(e,t,n){var s=" "+e.className+" ",i="data-"+n||"bind",r=e.attributes;if(r.length>0)for(var a=0,o=r.length;o>a;a++)if(0===e.attributes[a].nodeName.indexOf(i)){e.attributes[a].nodeName.indexOf(i);var c=r[a].nodeName.substr(i.length+1);return e.setAttribute("mag-event",c),!0}return e.id===t||s.indexOf(" "+t+" ")>-1||e.name===t||e.nodeName.toLowerCase()===t.toLowerCase()||e.getAttribute(i)===t}var c=1,u="bind";e.domElement=function(e){var t=new r(e);return t},r.prototype.getSelectorDataKey=function(e){return this.selectorDataKey=e||this.selectorDataKey},r.prototype.findElementsByKey=function(e,t){var n=this.matchingElements(t||this.nodeContext,e);return n},r.prototype.findElementsByKeys=function(e,t){var n=[];for(var s in e){var i=this.matchingElements(t||this.nodeContext,s);if(i){var r={key:s,elements:i};n.push(r)}}return n},r.prototype.matchingElements=function(e,t,n){var s=a(e),i=[],r=t;for(c=0;c<s.length;c+=1)o(s[c],r,this.getSelectorDataKey())&&i.push(s[c]);for(var c=0;c<s.length;c++){var u=this.matchingElements(s[c],t,!0);if(u&&u.length>0){i=i.concat(u);break}}return n||i.length?i:!1}}(window.mag=window.mag||{},mag.domElement={},window,document);!function(){var e=Object.prototype.toString;mag.template.serve=function(e){var t=e.arguments[0];mag.template.preParser(this,t),mag.aspect.next(e);var n=this.getScope(t),s=this;this.on("propertyChanged",function(){mag.template.parse(s,t,n)}),mag.template.parse(s,t,n)},mag.template.preParser=function(e,t){log("info","template parse start"+t);var n=document.getElementById(t);e.fire("mag.template.begin",[t]),this.templates=this.templates||{},this.templates[t]=this.templates[t]||n?n:0,this.template=this.templates[t];var n=this.template;if(!n||""==this.template)return!1;var s=n.parentNode;return n.parentNode.removeChild(n),this.node=n,this.parent=s,{node:n,parent:s}},mag.template.parse=function(t,n,s){if(this.node){var i=this.node,r=this.parent,a=mag.reserved;this.applyVar=function(e,t,n){if(e.nodeType){var s=e.getElementsByClassName(t),i=s.length;for(1>i&&this.setVar(e,t,n);i--;)this.setVar(e,t,n,s,i)}},this.setVar=function(e,t,n,s,i){function r(e,t,n){var s="function"==typeof e[t]?e[t].call(n||this):e[t];return s}this.pattern=this.pattern||RegExp("\\[\\[(.*?)\\]\\]","g"),e.innerHTML=e.innerHTML.replace(this.pattern,function(e,s){return t==s&&-1===a.indexOf(t)?r(n,t):e}),s&&-1===a.indexOf(t)&&""==s[i].innerText&&(s[i].innerText=r(n,t,this))},this.applyVars=function(e,t){for(var n in t)this.applyVar(e,n,t)},this.parser=function(t,n){for(var s in n)if("[object Array]"===e.call(n[s])){var i=t.getElementsByClassName(s);if(!i[0])return;for(var r=i[0].cloneNode(!0),a=n[s],o=0;o<a.length;o++){var c=r.cloneNode(!0);a[o],this.applyVars(c,a[o]),i[0].parentNode.appendChild(c)}i[0].parentNode.removeChild(i[0])}else this.applyVar(t,s,n)},this.parser(i,s),t.fire("mag.template.end",[n]),r.appendChild(i)}},mag.aspect.add("around","control",mag.template.serve)}(window.mag=window.mag||{},mag.template={});Object.prototype.watch||Object.defineProperty(Object.prototype,"__watch",{enumerable:!1,configurable:!0,writable:!1,value:function(e,t){var n=this[e],i=n,s=function(){return i},r=function(s){n=i;var r=this;return t.call(r,e,n,s),i};delete this[e]&&(Object.defineProperty?Object.defineProperty(this,e,{get:s,set:r}):Object.prototype.__defineGetter__&&Object.prototype.__defineSetter__&&(Object.prototype.__defineGetter__.call(this,e,s),Object.prototype.__defineSetter__.call(this,e,r)))}}),function(e,t){mag.watch.throttle=function(e,t,n){t||(t=250);var i,s;return function(){var r=n||this,a=+new Date,o=arguments;i&&i+t>a?(clearTimeout(s),s=setTimeout(function(){i=a,e.apply(r,o)},t)):(i=a,e.apply(r,o))}},mag.watch.serve=function(e){var n=this;this.getScope(e),this.controls.__watch(e,mag.watch.throttle(function(e,i,s){JSON.stringify(i)!==JSON.stringify({})&&JSON.stringify(i)!==JSON.stringify({ignoreKey:t})&&n.fire("propertyChanged",[e,i,s])},250,n))},mag.aspect.add("before","control",mag.watch.serve)}(window.mag=window.mag||{},mag.watch={});!function(e,t){t.server=function(t){var n=e.domElement(e.template.template);n.getSelectorDataKey("event");for(var i in t){var r=t[i];if("function"==typeof r){var s=n.findElementsByKey(i);if(s[0]){var a=s[0].getAttribute("mag-event");a&&s[0].addEventListener(a,r.bind(t),!1)}}}},t.serve=function(t){var n=this.getScope(t);this.on("mag.template.end",function(){e.uiEvent.server(n)})},e.aspect.add("before","control",t.serve)}(window.mag=window.mag||{},mag.uiEvent={});
<|endoftext|>


<commit_before>/**
 * Opciones de capa.
 * Esta clase no tiene constructor.
 * @class TC.cfg.LayerOptions
 * @static
 */
/**
 * Identificador único de capa.
 * @property id
 * @type string|undefined
 */
/**
 * Título de capa. Este valor se mostrará en la tabla de contenidos y la leyenda.
 * @property title
 * @type string|undefined
 */
/**
 * Tipo de capa. Si no se especifica se considera que la capa es WMS. La lista de valores posibles está definida en {{#crossLink "TC.consts.LayerType"}}{{/crossLink}}.
 * @property type
 * @type string|undefined
 */
/**
 * Tipo MIME del formato de archivo de imagen a obtener del servicio. Si esta propiedad no está definida, se comprobará si la capa es un mapa de fondo
 * (consultar propiedad {{#crossLink "TC.cfg.LayerOptions/isBase:property"}}{{/crossLink}}). En caso afirmativo, el formato elegido será "image/jpeg",
 * de lo contrario el formato será "image/png".
 * @property format
 * @type string|undefined
 */
/**
 * La capa se muestra por defecto si forma parte de los mapas de fondo.
 * @property isDefault
 * @type boolean|undefined
 */
/**
 * La capa es un mapa de fondo.
 * @property isBase
 * @type boolean|undefined
 */
/**
 * Aplicable a capas de tipo WMS y KML. La capa no muestra la jerarquía de grupos de capas en la tabla de contenidos ni en la leyenda.
 * @property hideTree
 * @type boolean|undefined
 */
/**
 * La capa no muestra su título cuando es añadida al control de capas de trabajo.
 * @property hideTitle
 * @type boolean|undefined
 * @default false
 */
/**
 * La capa no aparece en la tabla de contenidos ni en la leyenda. De este modo se puede añadir una superposición de capas de trabajo que el usuario la perciba como parte del mapa de fondo.
 * @property stealth
 * @type boolean|undefined
 */
/**
 * URL de una imagen en miniatura a mostrar en el selector de mapas de fondo.
 * @property thumbnail
 * @type string|undefined
 */
/**
 * Opciones de clustering de puntos.
 * @property cluster
 * @type TC.cfg.ClusterOptions|undefined
 */

/**
 * Árbol de elementos de capa.
 * Esta clase no tiene constructor.
 * @class TC.layer.LayerTree
 * @static
 */
/**
 * Nombre de capa en servicios WMS o WMTS.
 * @property name
 * @type string|undefined
 */
/**
 * Título de capa. Es un texto descriptivo para el usuario.
 * @property title
 * @type string|undefined
 */
/**
 * Identificador único de la capa.
 * @property uid
 * @type string|undefined
 */
/**
 * URL de la imagen con la leyenda de la capa.
 * @property legend
 * @type string|undefined
 */
/**
 * Lista de nodos hijos del nodo actual.
 * @property children
 * @type array|undefined
 */

/**
 * Capa de mapa. Esta clase no debería instanciarse directamente, sino mediante alguna de las clases que heredan de ella.
 * @class TC.Layer
 * @constructor
 * @async
 * @param {TC.cfg.LayerOptions} [options] Objeto de opciones de configuración de la capa.
 */
TC.Layer = function (options) {
    ///
    ///Constructor
    ///
    ///<param name="options" type="object">Objeto de opciones de capa.</param>
    ///<returns type="TC.Layer"></returns>
    var _layer = this;

    /**
     * Objeto de opciones de capa.
     * @property options
     * @type TC.cfg.LayerOptions
     * @default {}
     */
    _layer.options = options || {};
    $.extend(_layer, _layer.options);

    /**
     * Identificador de capa, debe ser único en el mapa. Si no se asigna en las opciones del constructor, se genera uno automáticamente.
     * @property id
     * @type string
     */
    _layer.id = _layer.options.id || TC.getUID();

    /**
     * Objeto del mapa al que pertenece la capa.
     * @property map
     * @type TC.Map|undefined
     */
    _layer.map = _layer.options.map;
    /**
     * Tipo de capa.
     * @property type
     * @type TC.consts.LayerType
     */
    _layer.type = _layer.options.type || TC.Consts.layerType.WMS;

    /**
     * Fragmento HTML para utilizar como leyenda.
     * @property customLegend
     * @type string
     */
    _layer.customLegend = _layer.options.customLegend;
    var defaultFormat = _layer.options.isBase ? TC.Consts.mimeType.JPEG : TC.Consts.mimeType.PNG;
    _layer.options.format = _layer.options.format || defaultFormat;

    if (_layer.options.hideTree === undefined) {
        _layer.options.hideTree = true;
    }

    if (_layer.options.hideTitle === undefined) {
        _layer.options.hideTitle = false;
    }

    _layer._cache = {
        visibilityStates: {}
    };

    /**
     * Árbol de los componentes de la capa. Estos componentes son distintos según el tipo de capa: así, en una capa WMS son las distintas capas del servicio,
     * en una capa KML son carpetas.
     * @property tree
     * @type TC.layer.LayerTree|null
     */
    _layer.tree = null;

    /**
     * Objeto envoltorio de la capa nativa de OpenLayers.
     * @property wrap
     * @type TC.wrap.Layer|null
     */
    _layer.wrap = null;
};

TC.Layer.state = {
    IDLE: 'idle',
    LOADING: 'loading'
};

/**
 * Establece la visibilidad de la capa en el mapa.
 * @method setVisibility
 * @param {boolean} visible true si se quiere mostrar la capa, false si se quiere ocultarla.
 */
TC.Layer.prototype.setVisibility = function (visible) {
    this.wrap.setVisibility(visible);
};

/**
 * Obtiene la visibilidad actual de la capa en el mapa.
 * @method getVisibility
 * @return {boolean} true si la capa está visible, false si está oculta.
 */
TC.Layer.prototype.getVisibility = function () {
    var layer = this;
    var result = false;
    if (layer.map) {
        if (!layer.isBase || layer.map.getBaseLayer() === layer) {
            result = layer.wrap.getVisibility();
        }
    }
    return result;
};

/**
 * Obtiene la opacidad actual de la capa en el mapa.
 * @method getOpacity
 * @return {number}.
 */
TC.Layer.prototype.getOpacity = function () {
    var layer = this;
    var result = false;
    if (layer.map) {
        if (!layer.isBase || layer.map.getBaseLayer() === layer) {
            result = layer.wrap.getLayer().getOpacity();
        }
    }
    return result;
};

/**
 * Establece la opacidad de la capa en el mapa. Hay que tener en cuenta que establecer opacidad 0 a una capa no es
 * equivalente que llamar a TC.Layer.{{#crossLink "TC.Layer/setVisibility:method"}}{{/crossLink}} con el valor del parámetro false.
 * @method setOpacity
 * @param {number} opacity Valor entre 0 (capa transparente) y 1 (capa opaca).
 * @param {boolean} mute Indica si al establecer opacidad no se lanza evento LAYEROPACITY.
 */
TC.Layer.prototype.setOpacity = function (opacity, mute) {
    var layer = this;
    $.when(this.wrap.getLayer()).then(function (olLayer) {
        olLayer.setOpacity(opacity);
        layer.opacity = opacity;
        if (layer.map && !mute) {
            layer.map.$events.trigger($.Event(TC.Consts.event.LAYEROPACITY, { layer: layer, opacity: opacity }));
        }
    });
};

/**
 * Determina si la capa se puede mostrar en el CRS especificado.
 * @method isCompatible
 * @param {string} crs Cadena con el well-known ID (WKID) del CRS.
 * @return {boolean}
 */
TC.Layer.prototype.isCompatible = function (crs) {
    return true;
};

/**
 * Determina si la capa tiene nombres válidos.
 * @method isValidFromNames
 * @return {boolean}
 */
TC.Layer.prototype.isValidFromNames = function () {
    return true;
};

/**
 * Determina si la capa es de tipo raster.
 * @method isRaster
 * @return {boolean}
 */
TC.Layer.prototype.isRaster = function () {
    var result = true;
    var _layer = this;
    switch (_layer.type) {
        case TC.Consts.layerType.VECTOR:
        case TC.Consts.layerType.KML:
        case TC.Consts.layerType.WFS:
        case TC.Consts.layerType.GROUP:
            result = false;
            break;
        default:
            break;
    }
    return result;
};

/**
 * Determina si la capa es visible a la resolución actual. Para ello consulta el documento de capabilities en los casos en que exista.
 * @method isVisibleByScale
 * @return {boolean}
 */
TC.Layer.prototype.isVisibleByScale = function (name) {
    return true;
};

/**
 * Determina si una capa del servicio está establecida en el mapa como visible.
 * @method isVisibleByName
 * @return {boolean}
 */
TC.Layer.prototype.isVisibleByName = function (name) {
    return true;
};

/**
 *
Devuelve un árbol de información de la capa. Como mínimo devuelve un nodo raíz con el título de la capa.

 *
En capas de servicios WMS es la jerarquía de capas obtenida del documento capabilities. Dependiendo del valor de la propiedad TC.cfg.LayerOptions.{{#crossLink "TC.cfg.LayerOptions/hideTree:property"}}{{/crossLink}},
 * puede mostrar un árbol de todas las capas del servicio o solo un árbol de las capas visibles inicialmente.

 *
En capas de documentos KML cada nodo es una carpeta del documento.

 *
Si la propiedad TC.cfg.LayerOptions.{{#crossLink "TC.cfg.LayerOptions/stealth:property"}}{{/crossLink}} está establecida a true, este método devuelve null.

 * @method getTree
 * @return {TC.layer.LayerTree}
 */
TC.Layer.prototype.getTree = function () {
    var _layer = this;
    var result = { name: _layer.name, title: _layer.title };
    return result;
};

/**
 * Devuelve un nodo del árbol de información de la capa.
 * @method findNode
 * @param {string} id Identificador del nodo.
 * @param {TC.layer.LayerTree} parent Nodo desde el que se comienza la búsqueda.
 * @return {TC.layer.LayerTree} Si no se encuentra el nodo el método devuelve null.
 */
TC.Layer.prototype.findNode = function findNode(id, parent) {
    var result = null;
    if (parent.uid == id) {
        result = parent;
    }
    else {
        for (var i = 0; i < parent.children.length; i++) {
            var r = findNode(id, parent.children[i]);
            if (r) {
                result = r;
                break;
            }
        }
    }
    return result;
};

/**
 * Establece la visibilidad en el mapa de un elemento asociado a un nodo de árbol de la capa. Dependiendo del tipo de capa este elemento
 * es una entidad u otra, así, en capas de tipo WMS son capas de servicio, en KML son carpetas y en capas vectoriales genéricas son grupos de marcadores.
 * @method setNodeVisibility
 * @param {string} id Identificador del nodo.
 * @param {boolean} visible true si se quiere mostrar el elemento, false si se quiere ocultar.
 */
TC.Layer.prototype.setNodeVisibility = function (id, visible) {
    this.setVisibility(visible);
};

/**
 * Obtiene la visibilidad en el mapa de un elemento asociado a un nodo de árbol de la capa. Dependiendo del tipo de capa este elemento
 * es una entidad u otra, así, en capas de tipo WMS son capas de servicio, en KML son carpetas y en capas vectoriales genéricas son grupos de marcadores.
 * @method getNodeVisibility
 * @param {string} id Identificador del nodo.
 * @return {TC.consts.Visibility}
 */
TC.Layer.prototype.getNodeVisibility = function (id) {
    return TC.Consts.visibility.VISIBLE;
};

TC.Layer.prototype.getResolutions = function () {
    if (this.wrap.getResolutions) {
        return this.wrap.getResolutions();
    }
    else {
        return [];
    }
};

TC.Layer.prototype.setProjection = function () {
};
<commit_msg>Use getLayer asyncronously<commit_after>/**
 * Opciones de capa.
 * Esta clase no tiene constructor.
 * @class TC.cfg.LayerOptions
 * @static
 */
/**
 * Identificador único de capa.
 * @property id
 * @type string|undefined
 */
/**
 * Título de capa. Este valor se mostrará en la tabla de contenidos y la leyenda.
 * @property title
 * @type string|undefined
 */
/**
 * Tipo de capa. Si no se especifica se considera que la capa es WMS. La lista de valores posibles está definida en {{#crossLink "TC.consts.LayerType"}}{{/crossLink}}.
 * @property type
 * @type string|undefined
 */
/**
 * Tipo MIME del formato de archivo de imagen a obtener del servicio. Si esta propiedad no está definida, se comprobará si la capa es un mapa de fondo
 * (consultar propiedad {{#crossLink "TC.cfg.LayerOptions/isBase:property"}}{{/crossLink}}). En caso afirmativo, el formato elegido será "image/jpeg",
 * de lo contrario el formato será "image/png".
 * @property format
 * @type string|undefined
 */
/**
 * La capa se muestra por defecto si forma parte de los mapas de fondo.
 * @property isDefault
 * @type boolean|undefined
 */
/**
 * La capa es un mapa de fondo.
 * @property isBase
 * @type boolean|undefined
 */
/**
 * Aplicable a capas de tipo WMS y KML. La capa no muestra la jerarquía de grupos de capas en la tabla de contenidos ni en la leyenda.
 * @property hideTree
 * @type boolean|undefined
 */
/**
 * La capa no muestra su título cuando es añadida al control de capas de trabajo.
 * @property hideTitle
 * @type boolean|undefined
 * @default false
 */
/**
 * La capa no aparece en la tabla de contenidos ni en la leyenda. De este modo se puede añadir una superposición de capas de trabajo que el usuario la perciba como parte del mapa de fondo.
 * @property stealth
 * @type boolean|undefined
 */
/**
 * URL de una imagen en miniatura a mostrar en el selector de mapas de fondo.
 * @property thumbnail
 * @type string|undefined
 */
/**
 * Opciones de clustering de puntos.
 * @property cluster
 * @type TC.cfg.ClusterOptions|undefined
 */

/**
 * Árbol de elementos de capa.
 * Esta clase no tiene constructor.
 * @class TC.layer.LayerTree
 * @static
 */
/**
 * Nombre de capa en servicios WMS o WMTS.
 * @property name
 * @type string|undefined
 */
/**
 * Título de capa. Es un texto descriptivo para el usuario.
 * @property title
 * @type string|undefined
 */
/**
 * Identificador único de la capa.
 * @property uid
 * @type string|undefined
 */
/**
 * URL de la imagen con la leyenda de la capa.
 * @property legend
 * @type string|undefined
 */
/**
 * Lista de nodos hijos del nodo actual.
 * @property children
 * @type array|undefined
 */

/**
 * Capa de mapa. Esta clase no debería instanciarse directamente, sino mediante alguna de las clases que heredan de ella.
 * @class TC.Layer
 * @constructor
 * @async
 * @param {TC.cfg.LayerOptions} [options] Objeto de opciones de configuración de la capa.
 */
TC.Layer = function (options) {
    ///
    ///Constructor
    ///
    ///<param name="options" type="object">Objeto de opciones de capa.</param>
    ///<returns type="TC.Layer"></returns>
    var _layer = this;

    /**
     * Objeto de opciones de capa.
     * @property options
     * @type TC.cfg.LayerOptions
     * @default {}
     */
    _layer.options = options || {};
    $.extend(_layer, _layer.options);

    /**
     * Identificador de capa, debe ser único en el mapa. Si no se asigna en las opciones del constructor, se genera uno automáticamente.
     * @property id
     * @type string
     */
    _layer.id = _layer.options.id || TC.getUID();

    /**
     * Objeto del mapa al que pertenece la capa.
     * @property map
     * @type TC.Map|undefined
     */
    _layer.map = _layer.options.map;
    /**
     * Tipo de capa.
     * @property type
     * @type TC.consts.LayerType
     */
    _layer.type = _layer.options.type || TC.Consts.layerType.WMS;

    /**
     * Fragmento HTML para utilizar como leyenda.
     * @property customLegend
     * @type string
     */
    _layer.customLegend = _layer.options.customLegend;
    var defaultFormat = _layer.options.isBase ? TC.Consts.mimeType.JPEG : TC.Consts.mimeType.PNG;
    _layer.options.format = _layer.options.format || defaultFormat;

    if (_layer.options.hideTree === undefined) {
        _layer.options.hideTree = true;
    }

    if (_layer.options.hideTitle === undefined) {
        _layer.options.hideTitle = false;
    }

    _layer._cache = {
        visibilityStates: {}
    };

    /**
     * Árbol de los componentes de la capa. Estos componentes son distintos según el tipo de capa: así, en una capa WMS son las distintas capas del servicio,
     * en una capa KML son carpetas.
     * @property tree
     * @type TC.layer.LayerTree|null
     */
    _layer.tree = null;

    /**
     * Objeto envoltorio de la capa nativa de OpenLayers.
     * @property wrap
     * @type TC.wrap.Layer|null
     */
    _layer.wrap = null;
};

TC.Layer.state = {
    IDLE: 'idle',
    LOADING: 'loading'
};

/**
 * Establece la visibilidad de la capa en el mapa.
 * @method setVisibility
 * @param {boolean} visible true si se quiere mostrar la capa, false si se quiere ocultarla.
 */
TC.Layer.prototype.setVisibility = function (visible) {
    this.wrap.setVisibility(visible);
};

/**
 * Obtiene la visibilidad actual de la capa en el mapa.
 * @method getVisibility
 * @return {boolean} true si la capa está visible, false si está oculta.
 */
TC.Layer.prototype.getVisibility = function () {
    var layer = this;
    var result = false;
    if (layer.map) {
        if (!layer.isBase || layer.map.getBaseLayer() === layer) {
            result = layer.wrap.getVisibility();
        }
    }
    return result;
};

/**
 * Obtiene la opacidad actual de la capa en el mapa.
 * @method getOpacity
 * @return {number}.
 */
TC.Layer.prototype.getOpacity = function () {
    var layer = this;
    var result = false;
    if (layer.map) {
        if (!layer.isBase || layer.map.getBaseLayer() === layer) {
            result = layer.wrap.layer.getOpacity();
        }
    }
    return result;
};

/**
 * Establece la opacidad de la capa en el mapa. Hay que tener en cuenta que establecer opacidad 0 a una capa no es
 * equivalente que llamar a TC.Layer.{{#crossLink "TC.Layer/setVisibility:method"}}{{/crossLink}} con el valor del parámetro false.
 * @method setOpacity
 * @param {number} opacity Valor entre 0 (capa transparente) y 1 (capa opaca).
 * @param {boolean} mute Indica si al establecer opacidad no se lanza evento LAYEROPACITY.
 */
TC.Layer.prototype.setOpacity = function (opacity, mute) {
    var layer = this;
    this.wrap.getLayer().then(function (olLayer) {
        olLayer.setOpacity(opacity);
        layer.opacity = opacity;
        if (layer.map && !mute) {
            layer.map.trigger(TC.Consts.event.LAYEROPACITY, { layer: layer, opacity: opacity });
        }
    });
};

/**
 * Determina si la capa se puede mostrar en el CRS especificado.
 * @method isCompatible
 * @param {string} crs Cadena con el well-known ID (WKID) del CRS.
 * @return {boolean}
 */
TC.Layer.prototype.isCompatible = function (crs) {
    return true;
};

/**
 * Determina si la capa tiene nombres válidos.
 * @method isValidFromNames
 * @return {boolean}
 */
TC.Layer.prototype.isValidFromNames = function () {
    return true;
};

/**
 * Determina si la capa es de tipo raster.
 * @method isRaster
 * @return {boolean}
 */
TC.Layer.prototype.isRaster = function () {
    var result = true;
    var _layer = this;
    switch (_layer.type) {
        case TC.Consts.layerType.VECTOR:
        case TC.Consts.layerType.KML:
        case TC.Consts.layerType.WFS:
        case TC.Consts.layerType.GROUP:
            result = false;
            break;
        default:
            break;
    }
    return result;
};

/**
 * Determina si la capa es visible a la resolución actual. Para ello consulta el documento de capabilities en los casos en que exista.
 * @method isVisibleByScale
 * @return {boolean}
 */
TC.Layer.prototype.isVisibleByScale = function (name) {
    return true;
};

/**
 * Determina si una capa del servicio está establecida en el mapa como visible.
 * @method isVisibleByName
 * @return {boolean}
 */
TC.Layer.prototype.isVisibleByName = function (name) {
    return true;
};

/**
 *
Devuelve un árbol de información de la capa. Como mínimo devuelve un nodo raíz con el título de la capa.

 *
En capas de servicios WMS es la jerarquía de capas obtenida del documento capabilities. Dependiendo del valor de la propiedad TC.cfg.LayerOptions.{{#crossLink "TC.cfg.LayerOptions/hideTree:property"}}{{/crossLink}},
 * puede mostrar un árbol de todas las capas del servicio o solo un árbol de las capas visibles inicialmente.

 *
En capas de documentos KML cada nodo es una carpeta del documento.

 *
Si la propiedad TC.cfg.LayerOptions.{{#crossLink "TC.cfg.LayerOptions/stealth:property"}}{{/crossLink}} está establecida a true, este método devuelve null.

 * @method getTree
 * @return {TC.layer.LayerTree}
 */
TC.Layer.prototype.getTree = function () {
    var _layer = this;
    var result = { name: _layer.name, title: _layer.title };
    return result;
};

/**
 * Devuelve un nodo del árbol de información de la capa.
 * @method findNode
 * @param {string} id Identificador del nodo.
 * @param {TC.layer.LayerTree} parent Nodo desde el que se comienza la búsqueda.
 * @return {TC.layer.LayerTree} Si no se encuentra el nodo el método devuelve null.
 */
TC.Layer.prototype.findNode = function findNode(id, parent) {
    var result = null;
    if (parent.uid == id) {
        result = parent;
    }
    else {
        for (var i = 0; i < parent.children.length; i++) {
            var r = findNode(id, parent.children[i]);
            if (r) {
                result = r;
                break;
            }
        }
    }
    return result;
};

/**
 * Establece la visibilidad en el mapa de un elemento asociado a un nodo de árbol de la capa. Dependiendo del tipo de capa este elemento
 * es una entidad u otra, así, en capas de tipo WMS son capas de servicio, en KML son carpetas y en capas vectoriales genéricas son grupos de marcadores.
 * @method setNodeVisibility
 * @param {string} id Identificador del nodo.
 * @param {boolean} visible true si se quiere mostrar el elemento, false si se quiere ocultar.
 */
TC.Layer.prototype.setNodeVisibility = function (id, visible) {
    this.setVisibility(visible);
};

/**
 * Obtiene la visibilidad en el mapa de un elemento asociado a un nodo de árbol de la capa. Dependiendo del tipo de capa este elemento
 * es una entidad u otra, así, en capas de tipo WMS son capas de servicio, en KML son carpetas y en capas vectoriales genéricas son grupos de marcadores.
 * @method getNodeVisibility
 * @param {string} id Identificador del nodo.
 * @return {TC.consts.Visibility}
 */
TC.Layer.prototype.getNodeVisibility = function (id) {
    return TC.Consts.visibility.VISIBLE;
};

TC.Layer.prototype.getResolutions = function () {
    if (this.wrap.getResolutions) {
        return this.wrap.getResolutions();
    }
    else {
        return [];
    }
};

TC.Layer.prototype.setProjection = function () {
};
<|endoftext|>


<commit_before>var Conversion = function(id) {
    this.id = id;
    this.status = ko.observable();
    this.url = ko.observable();
    this.errorMsg = ko.observable();
    this.isExpanded = ko.observable(false);
    this.tracks = ko.observableArray();
};

Conversion.prototype.expand = function() {
    this.isExpanded(true);
};<commit_msg>Conversions are now expanded by default<commit_after>var Conversion = function(id) {
    this.id = id;
    this.status = ko.observable();
    this.url = ko.observable();
    this.errorMsg = ko.observable();
    this.isExpanded = ko.observable(true);
    this.tracks = ko.observableArray();
};

Conversion.prototype.expand = function() {
    this.isExpanded(true);
};<|endoftext|>


<commit_before>angular.module('FRCdozer')
.controller('frcCtrl',['$scope','$http','$stateParams',function($scope,$http,$stateParams) {
    $scope.subs = []; //stores matches for current game
    $scope.sub = {};
    $scope.matches = [];
    $scope.match = {};
    $scope.add = {} //stores un-posted add
    $scope.game = {}; //stores game that operations are being done on
    $scope.curGame = {}; //game that is currently active, to show in table
    $scope.games = []; //stores all games
    $scope.sample = {};
    $scope.teams = [];
    $scope.team={};
    $scope.filt="";
    $scope.revr=false;
    $scope.connected = false;
    $scope.newTeam;
    $scope.getDate = function (id) {
      if (id) {
        var date = new Date(parseInt(id.substring(0, 8), 16) * 1000);
        console.log(date);
        return date;
      }
    };
    function discon () {
      $scope.$apply(function() {
        $scope.connected=false;
      });
    }
    function con() {
      $scope.$apply(function() {
        $scope.connected=true;
      });
    }
    /*
    $scope.socket
      .on('connect', con)
      .on('reconnect',con)
      .on('connect_timeout', discon)
      .on('reconnecting', discon)
      .on('reconnect_error',discon)
      .on('reconnect_failed',discon)
      .on('newMatch', function(x){$scope.appendMatch(x);})
      .on('delMatch', function(x){$scope.removeMatch(x);})
      .on('editMatch',function(x){$scope.changeMatch(x);})
      .on('editGame',function(x){$scope.changeGame(x);})
      .on('error',function(x){console.log(x);});
    */
    $scope.sort = function (prop) {
      if ($scope.filt === prop) $scope.revr=!$scope.revr;
      else {
        $scope.filt=prop;
        $scope.revr=true;
      }
    };
    $scope.changeGame = function (game) {
      //$scope.$apply(function() {
        $scope.curGame = game;
      //});
    };
    $scope.appendSub = function (sub) {
      //$scope.$apply(function() {
        $scope.subs.push(sub);
        $scope.getTeams(true,[sub],true);
        $scope.sortMatches();
      //});
    };
    $scope.removeSub = function (id) {
      var a,b,c;
      for (x in $scope.subs) if (id === $scope.subs[x]._id) {
        a=x;
        var team =  $scope.subs[x].team;
        for (y in $scope.teams) if ($scope.teams[y].team===team) {
          b=y;
          var m = $scope.teams[y].subs;
          for (z in m) if (m[z]._id = id) {
            c=z;
            break;
          }
          break;
        }
        break;
      };
      //$scope.$apply(function() {
        $scope.subs.splice(a,1);
        $scope.teams[b].subs.splice(c,1);
        $scope.sortMatches();
      //});
    };
    $scope.changeSub = function (sub) {
      for (x in $scope.subs) if (sub._id === $scope.subs[x]._id) {
        //$scope.$apply(function() {
          $scope.subs[x]=sub;
          $scope.getTeams(true);
        //});
        break;
      }
      $scope.sortMatches();
    };
    $scope.getMatch = function (match) {
      for (x in $scope.matches) if ($scope.matches[x].match = match) return $scope.matches[x];
    };
    $scope.getCurSubs = function (def) {
      if (!def) return $http.get ('/api/match');
      else {
        $http.get ('/api/match')
          .success(function (data) {
            $scope.subs=data;
          });
      }
    };
    /*
    $scope.getCurGame = function (def) {
      if (!def) return $http.get('/api/game');
      else {
        $http.get('/api/game')
        .success(function (data) {
          $scope.curGame=data;
        });
      }
    }; */
    $scope.sortMatches = function (subs) { //sorts array of submissions, or the scope submissions, into matches
      var subs = subs || $scope.subs;
      var matches = [];
      z: for (x in subs) {
        for (y in matches) if (matches[y].match === subs[x].match) {
              matches[y].subs.push(subs[x]);
              continue z;
        }
        matches.push({match:subs[x].match || "n/a",subs:[subs[x]]});
      }
      $scope.matches = matches;
    };
    $scope.getGame = function (id,call) {
      $http.get('/api/game/'+id)
        .success(function (data) {
          call (null,data);
        })
        .error(function (data) {
          call(data,null);
        });
    };
    $scope.editGame = function (id,params,call) {
      $http.put('/api/game/'+id,params)
        .success(function (data) {
          call(null,data); //call(error,content)
        })
        .error(function (data) {
          call(data,null);
        });
    };
    $scope.createGame = function (param,call) {
      $http.post('/api/game',params)
        .success(function (data) {
          call(null,data);
        })
        .error(function (data) {
          call(data,null);
        });
    };
    $scope.deleteGame = function (id,call) {
      $http.delete('/api/game/'+id)
        .success(function (data) {
          call(null,data)
        })
        .error(function (data) {
          call(data,null);
        })
    };
    $scope.getSub = function (id) {
      for (x in $scope.subs) if ($scope.subs[x]._id === id) {
        return $scope.subs[x];
      }
    };
    $scope.getTeam = function (team) {
      team = Number(team);
      for (x in $scope.teams) if (Number($scope.teams[x].team) === team){
          return $scope.teams[x];
          break;
      }
    }
    $scope.editSub = function (x) {
      //if ($scope.connected) $scope.socket.emit('editMatch',{_id:x._id,team:x.team,elements:x.elements});
      //else $http.put('/api/match/'+x._id,x);
      var req = $http.put('/api/game/'+$scope.curGame._id+'/sub/'+x._id,x);
      if (!$scope.connected) req.success(function (data) {
          $scope.changeSub(data);
      });
    };
    $scope.addSub = function (elements) {
      //if ($scope.connected) $scope.socket.emit('newMatch',elements);
      //else
      var req = $http.post ('/api/game/'+$scope.curGame._id+'/sub',elements);
      if (!$scope.connected) req.success(function (data) {
          $scope.appendSub(data);
          $scope.add={};
      });
    };
    $scope.delSub = function (id) {
      //if ($scope.connected) $scope.socket.emit('delMatch',id);
      //else
      var req = $http.delete ('/api/game/'+$scope.curGame._id+'/sub/'+id);
      if (!$scope.connected) req.success(function() {
      		$scope.removeSub(id);
      });
    };
    $scope.editGame = function (x) {
      //if ($scope.connected) $scope.socket.emit('editGame',angular.toJson(x));
      //else
      $http.put('/api/game/'+x._id,x);
    };
    $scope.getValue = function (sub,calc) {
      sub = sub || {};
      calc = calc || [];
      var val = 0;
      for (x in calc) val=val+(Number(sub[calc[x].name])*calc[x].worth || 0);
      return Math.round(val*100)/100;
    };
    $scope.getTeams = function (def,mats,noReset) {
      var teams = noReset ?  $scope.teams : [];
      var subs = subs || $scope.subs;
      mSearch: for (x in subs) { //sorts matches into teams
        for (y in teams) {
          if (teams[y].team === subs[x].team) {
            teams[y].subs.push(subs[x]);
            continue mSearch;
          }
        }
        teams.push({team:subs[x].team,subs:[subs[x]],averages:{}});
      }
      if (!def) return teams;
      else $scope.teams = teams;
    };
    $scope.getAverage = function (prop,subs) {
      var avr = 0;
      for (x in subs) avr = avr+(Number(subs[x].elements[prop])||0);
      avr = avr / (subs.length);
      avr = Math.round(avr*100)/100;
      return avr;
    };
    function socketConf () {
      $scope.socket = io('/game?name='+$scope.curGame.name)
        .on('message', function (data) {console.log(data);})
        .on('connect', con)
        .on('reconnect',con)
        .on('connect_timeout', discon)
        .on('reconnecting', discon)
        .on('reconnect_error',discon)
        .on('reconnect_failed',discon)
        .on('newSub', function(x){$scope.$apply(function () {$scope.appendSub(x);});})
        .on('delSub', function(x){$scope.$apply(function () {$scope.removeSub(x._id);});})
        .on('editSub',function(x){$scope.$apply(function () {$scope.changeSub(x);});})
        .on('editGame',function(x){$scope.$apply(function () {$scope.changeGame(x);});})
        .on('error',function(x){console.log(x);});
    }
    $scope.init = function () {
      $scope.getGame($stateParams.name, function (err,data) { //'5495eb1b46fea7c15102dc7f'
        if (data) {
          $scope.curGame = data;
          $scope.subs = data.submissions;
          $scope.getTeams(true);
          $scope.sortMatches();
          socketConf();
        }
      });
    };
    $scope.init();
}]);
<commit_msg>removed log<commit_after>angular.module('FRCdozer')
.controller('frcCtrl',['$scope','$http','$stateParams',function($scope,$http,$stateParams) {
    $scope.subs = []; //stores matches for current game
    $scope.sub = {};
    $scope.matches = [];
    $scope.match = {};
    $scope.add = {} //stores un-posted add
    $scope.game = {}; //stores game that operations are being done on
    $scope.curGame = {}; //game that is currently active, to show in table
    $scope.games = []; //stores all games
    $scope.sample = {};
    $scope.teams = [];
    $scope.team={};
    $scope.filt="";
    $scope.revr=false;
    $scope.connected = false;
    $scope.newTeam;
    $scope.getDate = function (id) {
      if (id) {
        var date = new Date(parseInt(id.substring(0, 8), 16) * 1000);
        return date;
      }
    };
    function discon () {
      $scope.$apply(function() {
        $scope.connected=false;
      });
    }
    function con() {
      $scope.$apply(function() {
        $scope.connected=true;
      });
    }
    /*
    $scope.socket
      .on('connect', con)
      .on('reconnect',con)
      .on('connect_timeout', discon)
      .on('reconnecting', discon)
      .on('reconnect_error',discon)
      .on('reconnect_failed',discon)
      .on('newMatch', function(x){$scope.appendMatch(x);})
      .on('delMatch', function(x){$scope.removeMatch(x);})
      .on('editMatch',function(x){$scope.changeMatch(x);})
      .on('editGame',function(x){$scope.changeGame(x);})
      .on('error',function(x){console.log(x);});
    */
    $scope.sort = function (prop) {
      if ($scope.filt === prop) $scope.revr=!$scope.revr;
      else {
        $scope.filt=prop;
        $scope.revr=true;
      }
    };
    $scope.changeGame = function (game) {
      //$scope.$apply(function() {
        $scope.curGame = game;
      //});
    };
    $scope.appendSub = function (sub) {
      //$scope.$apply(function() {
        $scope.subs.push(sub);
        $scope.getTeams(true,[sub],true);
        $scope.sortMatches();
      //});
    };
    $scope.removeSub = function (id) {
      var a,b,c;
      for (x in $scope.subs) if (id === $scope.subs[x]._id) {
        a=x;
        var team =  $scope.subs[x].team;
        for (y in $scope.teams) if ($scope.teams[y].team===team) {
          b=y;
          var m = $scope.teams[y].subs;
          for (z in m) if (m[z]._id = id) {
            c=z;
            break;
          }
          break;
        }
        break;
      };
      //$scope.$apply(function() {
        $scope.subs.splice(a,1);
        $scope.teams[b].subs.splice(c,1);
        $scope.sortMatches();
      //});
    };
    $scope.changeSub = function (sub) {
      for (x in $scope.subs) if (sub._id === $scope.subs[x]._id) {
        //$scope.$apply(function() {
          $scope.subs[x]=sub;
          $scope.getTeams(true);
        //});
        break;
      }
      $scope.sortMatches();
    };
    $scope.getMatch = function (match) {
      for (x in $scope.matches) if ($scope.matches[x].match = match) return $scope.matches[x];
    };
    $scope.getCurSubs = function (def) {
      if (!def) return $http.get ('/api/match');
      else {
        $http.get ('/api/match')
          .success(function (data) {
            $scope.subs=data;
          });
      }
    };
    /*
    $scope.getCurGame = function (def) {
      if (!def) return $http.get('/api/game');
      else {
        $http.get('/api/game')
        .success(function (data) {
          $scope.curGame=data;
        });
      }
    }; */
    $scope.sortMatches = function (subs) { //sorts array of submissions, or the scope submissions, into matches
      var subs = subs || $scope.subs;
      var matches = [];
      z: for (x in subs) {
        for (y in matches) if (matches[y].match === subs[x].match) {
              matches[y].subs.push(subs[x]);
              continue z;
        }
        matches.push({match:subs[x].match || "n/a",subs:[subs[x]]});
      }
      $scope.matches = matches;
    };
    $scope.getGame = function (id,call) {
      $http.get('/api/game/'+id)
        .success(function (data) {
          call (null,data);
        })
        .error(function (data) {
          call(data,null);
        });
    };
    $scope.editGame = function (id,params,call) {
      $http.put('/api/game/'+id,params)
        .success(function (data) {
          call(null,data); //call(error,content)
        })
        .error(function (data) {
          call(data,null);
        });
    };
    $scope.createGame = function (param,call) {
      $http.post('/api/game',params)
        .success(function (data) {
          call(null,data);
        })
        .error(function (data) {
          call(data,null);
        });
    };
    $scope.deleteGame = function (id,call) {
      $http.delete('/api/game/'+id)
        .success(function (data) {
          call(null,data)
        })
        .error(function (data) {
          call(data,null);
        })
    };
    $scope.getSub = function (id) {
      for (x in $scope.subs) if ($scope.subs[x]._id === id) {
        return $scope.subs[x];
      }
    };
    $scope.getTeam = function (team) {
      team = Number(team);
      for (x in $scope.teams) if (Number($scope.teams[x].team) === team){
          return $scope.teams[x];
          break;
      }
    }
    $scope.editSub = function (x) {
      //if ($scope.connected) $scope.socket.emit('editMatch',{_id:x._id,team:x.team,elements:x.elements});
      //else $http.put('/api/match/'+x._id,x);
      var req = $http.put('/api/game/'+$scope.curGame._id+'/sub/'+x._id,x);
      if (!$scope.connected) req.success(function (data) {
          $scope.changeSub(data);
      });
    };
    $scope.addSub = function (elements) {
      //if ($scope.connected) $scope.socket.emit('newMatch',elements);
      //else
      var req = $http.post ('/api/game/'+$scope.curGame._id+'/sub',elements);
      if (!$scope.connected) req.success(function (data) {
          $scope.appendSub(data);
          $scope.add={};
      });
    };
    $scope.delSub = function (id) {
      //if ($scope.connected) $scope.socket.emit('delMatch',id);
      //else
      var req = $http.delete ('/api/game/'+$scope.curGame._id+'/sub/'+id);
      if (!$scope.connected) req.success(function() {
      		$scope.removeSub(id);
      });
    };
    $scope.editGame = function (x) {
      //if ($scope.connected) $scope.socket.emit('editGame',angular.toJson(x));
      //else
      $http.put('/api/game/'+x._id,x);
    };
    $scope.getValue = function (sub,calc) {
      sub = sub || {};
      calc = calc || [];
      var val = 0;
      for (x in calc) val=val+(Number(sub[calc[x].name])*calc[x].worth || 0);
      return Math.round(val*100)/100;
    };
    $scope.getTeams = function (def,mats,noReset) {
      var teams = noReset ?  $scope.teams : [];
      var subs = subs || $scope.subs;
      mSearch: for (x in subs) { //sorts matches into teams
        for (y in teams) {
          if (teams[y].team === subs[x].team) {
            teams[y].subs.push(subs[x]);
            continue mSearch;
          }
        }
        teams.push({team:subs[x].team,subs:[subs[x]],averages:{}});
      }
      if (!def) return teams;
      else $scope.teams = teams;
    };
    $scope.getAverage = function (prop,subs) {
      var avr = 0;
      for (x in subs) avr = avr+(Number(subs[x].elements[prop])||0);
      avr = avr / (subs.length);
      avr = Math.round(avr*100)/100;
      return avr;
    };
    function socketConf () {
      $scope.socket = io('/game?name='+$scope.curGame.name)
        .on('message', function (data) {console.log(data);})
        .on('connect', con)
        .on('reconnect',con)
        .on('connect_timeout', discon)
        .on('reconnecting', discon)
        .on('reconnect_error',discon)
        .on('reconnect_failed',discon)
        .on('newSub', function(x){$scope.$apply(function () {$scope.appendSub(x);});})
        .on('delSub', function(x){$scope.$apply(function () {$scope.removeSub(x._id);});})
        .on('editSub',function(x){$scope.$apply(function () {$scope.changeSub(x);});})
        .on('editGame',function(x){$scope.$apply(function () {$scope.changeGame(x);});})
        .on('error',function(x){console.log(x);});
    }
    $scope.init = function () {
      $scope.getGame($stateParams.name, function (err,data) { //'5495eb1b46fea7c15102dc7f'
        if (data) {
          $scope.curGame = data;
          $scope.subs = data.submissions;
          $scope.getTeams(true);
          $scope.sortMatches();
          socketConf();
        }
      });
    };
    $scope.init();
}]);
<|endoftext|>


<commit_before>angular.module('FRCdozer')
.controller('frcCtrl',['$scope','$http',function($scope,$http) {
    $scope.matches= undefined; //stores matches for current game
    $scope.match=[]; //stores single match that operations are currently being done on
    $scope.add = {} //stores un-posted add
    $scope.game = {}; //stores game that operations are being done on
    $scope.curGame = {}; //game that is currently active, to show in table
    $scope.games = []; //stores all games
    $scope.sample = {};
    $scope.teams = [];
    $scope.team={};
    $scope.sTrue = true;
    $scope.sFalse = false;
    $scope.filt="";
    $scope.revr=false;
    $scope.socket = io();
    $scope.connected = false;
    $scope.socket
      .on('connect', function () {$scope.connected=true;})
      .on('connect_timeout', function () {$scope.connected=false;})
      .on('newMatch', function(x){$scope.appendMatch(x);})
      .on('delMatch', function (id) {$scope.removeMatch(id)})
      .on('editMatch',function(mat){$scope.changeMatch(mat);});
    $scope.sort = function (prop) {
      if ($scope.filt === prop) $scope.revr=!$scope.revr;
      else {
        $scope.filt=prop;
        $scope.revr=true;
      }
    };
    $scope.appendMatch = function (match) {
      $scope.$apply(function() {
        $scope.matches.push(match);
        $scope.getTeams(true);
      });
    };
    $scope.removeMatch = function (id) {
      for (x in $scope.matches) if (id === $scope.matches[x]._id) {
        $scope.$apply(function() {
          $scope.matches.splice(x,1);
          $scope.getTeams(true);
        });
        break;
      };
    };
    $scope.changeMatch = function (match) {
      for (x in $scope.matches) if (match._id === $scope.matches[x]._id) {
        $scope.$apply(function() {
          $scope.matches[x]=match;
          $scope.getTeams(true);
        });
        break;
      }
    }
    $scope.getMatches = function (def) {
      if (!def) return $http.get ('/api/match');
      else {
        $http.get ('/api/match')
          .success(function (data) {
            $scope.matches=data;
          });
      }
    };
    $scope.getCurGame = function (def) {
      if (!def) return $http.get('/api/game');
      else {
        $http.get('/api/game')
        .success(function (data) {
          $scope.curGame=data;
        });
      }
    };
    $scope.getGame = function (id,def) {
      if (!def) return $http.get('/api/game/'+id);
      else {
        $http.get('/api/game/'+id)
        .success(function (data) {
          $scope.game = data;
        });
      }
    };
    $scope.getMatch = function (id) {
      for (x in $scope.matches) if ($scope.matches[x]._id === id) {
        return $scope.matches[x];
      }
    };
    $scope.getTeam = function (team) {
      team = Number(team);
      for (x in $scope.teams) if (Number($scope.teams[x].team) === team){
          return $scope.teams[x];
          break;
      }
    }
    $scope.editMatch = function (id,params,def) {
      if (!def) return $http.put('/api/match/'+id,params);
      else {
        $http.put('/api/match/'+id,{team:params.team,elements:params.elements})
        .success(function (data) {
          $scope.getMatches();
        });
      }
    };
    $scope.addMatch = function (elements,def) {
      if (!def) return $http.post ('/api/match',elements);
      else {
        $http.post ('/api/match',elements)
        .success(function (data) {
          $scope.add = {};
          //$scope.getMatches(true);
        });
      }
    };
    $scope.delMatch = function (id,def) {
      if (!def) return $http.delete ('/api/match/'+id);
      else {
        $http.delete ('/api/match/'+id)
        .success(function (data) {
          //$scope.getMatches(true);
        });
      }
    };
    $scope.editGame = function (id,elements,def) {
      if (!def) return $http.put('/api/game/'+id,elements);
      else {
        $http.put('/api/game/'+id,elements)
        .success(function (data) {
          $scope.game = data;
        })
      }
    };
    $scope.getValue = function (matchx,calc) {
      matchx = matchx || {};
      calc = calc || [];
      var val = 0;
      for (x in calc) val=val+(Number(matchx[calc[x].name])*calc[x].worth || 0);
      return Math.round(val*100)/100;
    };
    $scope.getTeams = function (def,mats,noReset) {
      var teams = [];
      mats = mats || $scope.matches;
      mSearch: for (x in mats) { //sorts matches into teams
        for (y in teams) {
          if (teams[y].team === mats[x].team) {
            teams[y].matches.push(mats[x].elements);
            continue mSearch;
          }
        }
        teams.push({team:mats[x].team,matches:[mats[x].elements],averages:{}});
      }
      if (!def) return teams;
      else $scope.teams = teams;
    };
    $scope.getAverage = function (prop,mats) {
      var avr = 0;
      for (x in mats) avr = Math.round(((avr+(Number(mats[x][prop])||0))/(x+1))*100)/100;
      return avr;
    };
    $scope.init = function () {
      $scope.getCurGame().success(function (data) {
        $scope.curGame=data;
        $scope.getMatches().success(function (data2) {
          $scope.matches=data2;
          $scope.getTeams(true);
        });
      });
    };
    $scope.init();
}]);
<commit_msg>Made connection indicator work and be more accurate<commit_after>angular.module('FRCdozer')
.controller('frcCtrl',['$scope','$http',function($scope,$http) {
    $scope.matches= undefined; //stores matches for current game
    $scope.match=[]; //stores single match that operations are currently being done on
    $scope.add = {} //stores un-posted add
    $scope.game = {}; //stores game that operations are being done on
    $scope.curGame = {}; //game that is currently active, to show in table
    $scope.games = []; //stores all games
    $scope.sample = {};
    $scope.teams = [];
    $scope.team={};
    $scope.sTrue = true;
    $scope.sFalse = false;
    $scope.filt="";
    $scope.revr=false;
    $scope.socket = io();
    $scope.connected = false;
    function discon () {
      $scope.$apply(function() {
        $scope.connected=false;
      });
      console.log('disconnected');
    }
    function con() {
      $scope.$apply(function() {
        $scope.connected=true;
      });
      console.log('connected');
    }
    $scope.socket
      .on('connect', con)
      .on('reconnect',con)
      .on('connect_timeout', discon)
      .on('reconnecting', discon)
      .on('reconnect_error',discon)
      .on('reconnect_failed',discon)
      .on('newMatch', discon)
      .on('delMatch', discon)
      .on('editMatch',discon);
    $scope.sort = function (prop) {
      if ($scope.filt === prop) $scope.revr=!$scope.revr;
      else {
        $scope.filt=prop;
        $scope.revr=true;
      }
    };
    $scope.appendMatch = function (match) {
      $scope.$apply(function() {
        $scope.matches.push(match);
        $scope.getTeams(true);
      });
    };
    $scope.removeMatch = function (id) {
      for (x in $scope.matches) if (id === $scope.matches[x]._id) {
        $scope.$apply(function() {
          $scope.matches.splice(x,1);
          $scope.getTeams(true);
        });
        break;
      };
    };
    $scope.changeMatch = function (match) {
      for (x in $scope.matches) if (match._id === $scope.matches[x]._id) {
        $scope.$apply(function() {
          $scope.matches[x]=match;
          $scope.getTeams(true);
        });
        break;
      }
    }
    $scope.getMatches = function (def) {
      if (!def) return $http.get ('/api/match');
      else {
        $http.get ('/api/match')
          .success(function (data) {
            $scope.matches=data;
          });
      }
    };
    $scope.getCurGame = function (def) {
      if (!def) return $http.get('/api/game');
      else {
        $http.get('/api/game')
        .success(function (data) {
          $scope.curGame=data;
        });
      }
    };
    $scope.getGame = function (id,def) {
      if (!def) return $http.get('/api/game/'+id);
      else {
        $http.get('/api/game/'+id)
        .success(function (data) {
          $scope.game = data;
        });
      }
    };
    $scope.getMatch = function (id) {
      for (x in $scope.matches) if ($scope.matches[x]._id === id) {
        return $scope.matches[x];
      }
    };
    $scope.getTeam = function (team) {
      team = Number(team);
      for (x in $scope.teams) if (Number($scope.teams[x].team) === team){
          return $scope.teams[x];
          break;
      }
    }
    $scope.editMatch = function (id,params,def) {
      if (!def) return $http.put('/api/match/'+id,params);
      else {
        $http.put('/api/match/'+id,{team:params.team,elements:params.elements})
        .success(function (data) {
          $scope.getMatches();
        });
      }
    };
    $scope.addMatch = function (elements,def) {
      if (!def) return $http.post ('/api/match',elements);
      else {
        $http.post ('/api/match',elements)
        .success(function (data) {
          $scope.add = {};
          //$scope.getMatches(true);
        });
      }
    };
    $scope.delMatch = function (id,def) {
      if (!def) return $http.delete ('/api/match/'+id);
      else {
        $http.delete ('/api/match/'+id)
        .success(function (data) {
          //$scope.getMatches(true);
        });
      }
    };
    $scope.editGame = function (id,elements,def) {
      if (!def) return $http.put('/api/game/'+id,elements);
      else {
        $http.put('/api/game/'+id,elements)
        .success(function (data) {
          $scope.game = data;
        })
      }
    };
    $scope.getValue = function (matchx,calc) {
      matchx = matchx || {};
      calc = calc || [];
      var val = 0;
      for (x in calc) val=val+(Number(matchx[calc[x].name])*calc[x].worth || 0);
      return Math.round(val*100)/100;
    };
    $scope.getTeams = function (def,mats,noReset) {
      var teams = [];
      mats = mats || $scope.matches;
      mSearch: for (x in mats) { //sorts matches into teams
        for (y in teams) {
          if (teams[y].team === mats[x].team) {
            teams[y].matches.push(mats[x].elements);
            continue mSearch;
          }
        }
        teams.push({team:mats[x].team,matches:[mats[x].elements],averages:{}});
      }
      if (!def) return teams;
      else $scope.teams = teams;
    };
    $scope.getAverage = function (prop,mats) {
      var avr = 0;
      for (x in mats) avr = Math.round(((avr+(Number(mats[x][prop])||0))/(x+1))*100)/100;
      return avr;
    };
    $scope.init = function () {
      $scope.getCurGame().success(function (data) {
        $scope.curGame=data;
        $scope.getMatches().success(function (data2) {
          $scope.matches=data2;
          $scope.getTeams(true);
        });
      });
    };
    $scope.init();
}]);
<|endoftext|>


<commit_before>'use strict';

var app = app || {};

(function(module){

  let latitude = 0;
  let longitude = 0;

  function getLocation(){
    if (navigator.geolocation){
      navigator.geolocation.getCurrentPosition(function (position){
        latitude = position.coords.latitude;
        longitude = position.coords.longitude;
        console.log(latitude, longitude);
      });
    } else {
      alert(`Sorry your browser does not support geolocationing`);
    }
  }
  getLocation();

  var stylesArray = [{
    featureType: 'all',
    stylers: [{
      hue: '#00ffe6'
    },
    {
      saturation: -20
    }
    ]
  },
  {
    featureType: 'road',
    elementType: 'geometry',
    stylers: [{
      lightness: 100
    },
    {
      visibility: 'simplified'
    }
    ]
  },
  {
    featureType: 'road',
    elementType: 'labels',
    stylers: [{
      visibility: 'off'
    }]
  }
  ];

  var mapOptions = {
    zoom: 15,
    styles: stylesArray,

    center: new google.maps.LatLng( latitude, longitude),

    mapTypeId: google.maps.MapTypeId.STREET,
    zoomControl: true,
    zoomControlOptions: {
      position: google.maps.ControlPosition.RIGHT_CENTER
    }
  }

  var map = new google.maps.Map(document.getElementById('map'), mapOptions);

google.maps.event.addDomListener(window, 'resize', function() {
  var center = map.getCenter();
  google.maps.event.trigger(map, 'resize');
  map.setCenter(center);
});

  $.get('/search')
.then((data) => {

    data.forEach(function(store) {

      var markerOptions = {
        position: new google.maps.LatLng(parseFloat(store.latitude),parseFloat(store.longitude)),
        map: map
      };
      var marker = new google.maps.Marker(markerOptions);
      marker.setMap(map);

    var infoWindowOptions = {
      content: 'Name: ' + store.name + ' \n Inspection result: ' + store.inspection_result
    };

      var infoWindow = new google.maps.InfoWindow(infoWindowOptions);
      google.maps.event.addListener(marker,'click',function(e){

        infoWindow.open(map, marker);
      });
    })
  })

//----------------------map icons---------------------------------------------//

   var iconBase = '/../images/';
   var icons = {
    good: {
    icon: iconBase + 'happy.png'
     },
     bad: {
     icon: iconBase + 'sick.png'
     }
  };

    var features = [
          {
            position: new google.maps.LatLng(47.618217, -122.351832),
            type: 'good'
          }, {
            position: new google.maps.LatLng(47.628217, -122.371832),
            type: 'bad'
          }
        ];

        // Create markers.
        features.forEach(function(feature) {
          var marker = new google.maps.Marker({
            position: feature.position,
            icon: icons[feature.type].icon,
            map: map
          });
        }); //

})(app);
<commit_msg>dont know<commit_after>'use strict';

var app = app || {};

(function(module){

  let latitude = 0;
  let longitude = 0;

  function getLocation(){
    if (navigator.geolocation){
      navigator.geolocation.getCurrentPosition(function (position){
        latitude = position.coords.latitude;
        longitude = position.coords.longitude;
        console.log(latitude, longitude);
      });
    } else {
      alert(`Sorry your browser does not support geolocationing`);
    }
  }
  getLocation();

  var stylesArray = [{
    featureType: 'all',
    stylers: [{
      hue: '#00ffe6'
    },
    {
      saturation: -20
    }
    ]
  },
  {
    featureType: 'road',
    elementType: 'geometry',
    stylers: [{
      lightness: 100
    },
    {
      visibility: 'simplified'
    }
    ]
  },
  {
    featureType: 'road',
    elementType: 'labels',
    stylers: [{
      visibility: 'off'
    }]
  }
  ];

  var mapOptions = {
    zoom: 15,
    styles: stylesArray,

    center: new google.maps.LatLng( latitude, longitude),

    mapTypeId: google.maps.MapTypeId.STREET,
    zoomControl: true,
    zoomControlOptions: {
      position: google.maps.ControlPosition.RIGHT_CENTER
    }
  }

  var map = new google.maps.Map(document.getElementById('map'), mapOptions);

google.maps.event.addDomListener(window, 'resize', function() {
  var center = map.getCenter();
  google.maps.event.trigger(map, 'resize');
  map.setCenter(center);
});

  $.get('/search')
.then((data) => {

    data.forEach(function(store) {

      var markerOptions = {
        position: new google.maps.LatLng(parseFloat(store.latitude),parseFloat(store.longitude)),
        map: map
      };
      var marker = new google.maps.Marker(markerOptions);
      marker.setMap(map);

    var infoWindowOptions = {
      content: 'Name: ' + store.name + ' \n Inspection result: ' + store.inspection_result
    };

      var infoWindow = new google.maps.InfoWindow(infoWindowOptions);
      google.maps.event.addListener(marker,'click',function(e){

        infoWindow.open(map, marker);
      });
    })
  })

//----------------------map icons---------------------------------------------//

   var iconBase = '/../images/';
   var icons = {
    good: {
    icon: iconBase + 'happy.png'
     },
     bad: {
     icon: iconBase + 'sick.png'
     }
  };

    var features = [
          {
            position: new google.maps.LatLng(47.618217, -122.351832),
            type: 'good'
          }, {
            position: new google.maps.LatLng(47.628217, -122.371832),
            type: 'bad'
          }
        ];

        // Create markers.
        features.forEach(function(feature) {
          var marker = new google.maps.Marker({
            position: feature.position,
            icon: icons[feature.type].icon,
            map: map
          });
        }); //

})(app);
<|endoftext|>