<commit_before>/*****************************************************************************/
/* Imports */
/*****************************************************************************/
var extend = Iron.utils.extend;
var debug = Iron.utils.debug('iron-component');
var camelCase = Iron.utils.camelCase;
var defaultValue = Iron.utils.defaultValue;
var assert = Iron.utils.assert;

/*****************************************************************************/
/* Private */
/*****************************************************************************/
var registerComponentHelper = function (name, Comp) {
  var tmpl = new Template(name, function () {
    var opts = Component.getInclusionArguments(this);
    var content = this.templateContentBlock;
    var elseContent = this.templateElseBlock;
    var instance = new Comp(_.extend(opts || {}, {
      content: content,
      elseContent: elseContent
    }));
    return instance.createView();
  });

  UI.registerHelper(name, tmpl);
};

var findFirstComponentOfType = function (type, view) {
  assert(typeof type === 'string', "type must be a string");
  assert(view instanceof Blaze.View, "view must be a Blaze.View");

  while (view) {
    if (view.name === type)
      return view.__component__;
    else
      view = view.parentView;
  }

  return null;
};

var registerComponentMethod = function (method, Comp) {
  var type = Comp.name;
  var helperName = type + '_' + method;

  UI.registerHelper(helperName, function (/* args, options */) {
    var view = Blaze.currentView;

    var cmp = findFirstComponentOfType(type, view);
    assert(cmp, "Couldn't find a component of type " + JSON.stringify(type) + " in view tree.");

    var func = cmp.methods && cmp.methods[method];
    assert(func, "The " + JSON.stringify(type) + " component does not have a method " + JSON.stringify(method) + ".");

    var args = _.toArray(arguments);
    var lastArg = args[args.length - 1];
    var options;

    if (typeOf(lastArg) === '[object Object]') {
      options = args.pop().hash;
      args.push(options);
    }

    return func.apply(cmp, args);
  });
};

var typeOf = function (value) {
  return Object.prototype.toString.call(value);
};

/*****************************************************************************/
/* Component */
/*****************************************************************************/
Component = function (options) {
  this.options = options = options || {};
  this._data = options.data;
  this._dataDep = new Deps.Dependency;
  this._hooks = {};
  this.state = new ReactiveDict;

  // has the Blaze.View been created?
  this.isCreated = false;

  // has the Blaze.View been destroyed and not created again?
  this.isDestroyed = false;

  this.init(this.options);
};

Component.prototype.template = null;

Component.prototype.init = function (options) {};

/**
 * Insert the Layout view into the dom.
 */
Component.prototype.insert = function (options) {
  options = options || {};

  if (this.isInserted)
    return;
  this.isInserted = true;

  var el = options.el || document.body;
  var $el = $(el);

  if ($el.length === 0)
    throw new Error("No element to insert layout into. Is your element defined? Try a Meteor.startup callback.");

  if (!this.view)
    this.createView(options);

  Blaze.render(this.view, $el[0], options.nextNode, options.parentView);
  return this;
};

/**
 * Get or set the data context.
 */
Component.prototype.data = function (value) {
  if (arguments.length === 1 && value !== this._data) {
    this._data = value;
    this._dataDep.changed();
    return;
  }

  this._dataDep.depend();
  return typeof this._data === 'function' ? this._data() : this._data;
};

Component.prototype.createView = function (options) {
  var self = this;

  if (this.isCreated) {
    throw new Error("Component view is already created");
  }

  this.isCreated = true;
  this.isDestroyed = false;

  var view = Blaze.View('Component', function () {
    var thisView = this;

    return Blaze.With(function () {
      // NOTE: This will rerun anytime the data function invalidates this
      // computation OR if created from an inclusion helper (see note below) any
      // time any of the argument functions invlidate the computation. For
      // example, when the template changes this function will rerun also. But
      // it's probably generally ok. The more serious use case is to not
      // re-render the entire template every time the data context changes.
      var result = self.data();

      if (typeof result !== 'undefined')
        // looks like data was set directly on this dynamic template
        return result;
      else
        // return the first parent data context that is not inclusion arguments
        return Component.getParentDataContext(thisView);
    }, function () {
      return self._renderView();
    });
  });

  // wire up the view lifecycle callbacks
  /*
  _.each(['onCreated', 'onMaterialized', 'onRendered', 'onDestroyed'], function (hook) {
    view[hook](function () {
      // "this" is the view instance
      self._runHooks(hook, this);
    });
  });
  */

  view._onViewRendered(function () {
    // avoid inserting the view twice by accident.
    self.isInserted = true;

    // following the lead of template.js in core
    if (view.renderCount !== 1)
      return;

    _.each(self.constructor._eventMaps, function (m) {
      Blaze._addEventMap(view, m, view);
    });
  });

  view._templateInstance = new Blaze.TemplateInstance(view);
  view.templateInstance = function () {
    // Update data, firstNode, and lastNode, and return the TemplateInstance
    // object.
    var inst = view._templateInstance;

    inst.data = Blaze.getData(view);

    if (view._domrange && !view.isDestroyed) {
      inst.firstNode = view._domrange.firstNode();
      inst.lastNode = view._domrange.lastNode();
    } else {
      // on 'created' or 'destroyed' callbacks we don't have a DomRange
      inst.firstNode = null;
      inst.lastNode = null;
    }

    return inst;
  };

  this.view = view;
  view.__component__ = this;
  // so helper lookup works as expected
  view.template = this;
  view.name = this.constructor.name;

  return view;
};

/**
 * Destroy the component.
 */
Component.prototype.destroy = function () {
  if (this.isCreated) {
    Blaze.remove(this.view);
    this.view = null;
    this.isDestroyed = true;
    this.isCreated = false;
  }
};

Component.prototype.lookupTemplate = function () {
  var self = this;
  var template = this.template;
  var tmpl = null;

  // is it a template name like "MyTemplate"?
  if (typeof template === 'string') {
    tmpl = Template[template];

    if (!tmpl)
      // as a fallback double check the user didn't actually define
      // a camelCase version of the template.
      tmpl = Template[camelCase(template)];

    if (!tmpl)
      throw new Error("Couldn't find a template named " + JSON.stringify(template) + " or " + JSON.stringify(camelCase(template))+ ". Are you sure you defined it?");

    tmpl = Spacebars.include(
      tmpl,
      function contentBlock () { return self.options.content; },
      function elseBlock () { return self.options.elseContent; }
    );

  } else if (typeOf(template) === '[object Object]') {
    // or maybe a view already?
    tmpl = template;
  } else if (typeof self.options.content !== 'undefined') {
    // or maybe its block content like
    // {{#DynamicTemplate}}
    //  Some block
    // {{/DynamicTemplate}}
    tmpl = self.options.content;
    tmpl.template = self;
  }

  return tmpl;
};

Component.prototype._renderView = function () {
  var tmpl = this.render();

  if (tmpl.template) {
    _.extend(tmpl.template, this.constructor._helpers);
  }

  return tmpl;
};

Component.prototype.render = function () {
  return this.lookupTemplate();
};

Component.prototype.call = function (prop) {
  var args = _.toArray(arguments).slice(1);
  return this.apply(prop, args);
};

Component.prototype.apply = function (prop, args) {
  var func = Component.lookup(this.view, prop);
  var thisArg = Component.getDataContext(this.view) || {};
  assert(typeof func === 'function', "Couldn't find a function named " + JSON.stringify(prop));
  return func.apply(thisArg, args);
};

/**
 * View lifecycle hooks.
 * XXX update for new blaze
 */
_.each([], function (hook) {
  Component.prototype[hook] = function (cb) {
    var hooks = this._hooks[hook] = this._hooks[hook] || [];
    hooks.push(cb);
    return this;
  };
});

Component.prototype._runHooks = function (name, view) {
  var hooks = this._hooks[name] || [];
  var hook;

  for (var i = 0; i < hooks.length; i++) {
    hook = hooks[i];
    // keep the "thisArg" pointing to the view, but make the first parameter to
    // the callback teh dynamic template instance.
    hook.call(view, this);
  }
};

/*****************************************************************************/
/* Component Static Methods */
/*****************************************************************************/
//XXX how do we use extends with harmony?
//XXX need a way to plug into the extension time or ctor time
Component.create = function (definition) {
  var klass = this.extend(definition);

  if (definition.events) {
    klass.events(definition.events);
    delete definition.events;
  }

  // register helper
  if (definition.name) {
    klass.type = definition.name;
    klass.prototype.type = definition.name;
    registerComponentHelper(definition.name, klass);
  }

  if (definition.methods) {
    _.each(_.keys(definition.methods), function (key) {
      registerComponentMethod(key, klass);
    });
  }

  return klass;
};

Component.methods = function (methodsMap) {
  var self = this;
  var methods = self.prototype.methods = self.prototype.methods || {};
  _.extend(methods, methodsMap);
  _.each(_.keys(methodsMap), function (key) {
    registerComponentMethod(key, self);
  });
};

Component.extend = function (definition) {
  return extend(this, definition);
};

/**
 * Register a global UI helper for the component.
 */
Component.registerHelper = function () {
  check(this.name, String);
  registerComponentHelper(this.name, this);
  return this;
};

// XXX This needs to be rewritten becuase none of this stuff
// works anymore. maybe we can borrow constructView from
// Template.prototype?
Component.events = function (events) {
  var maps = defaultValue(this, '_eventMaps', []);

  var boundMap = {};

  for (var key in events) {
    boundMap[key] = (function (key, handler) {
      return function (e) {
        var view = this;
        var component = view.__component__;
        var args = Array.prototype.slice.call(arguments);
        var tmplInstance = view.templateInstance();
        return handler.call(component, e, tmplInstance);
      };
    })(key, events[key]);
  }

  maps.push(boundMap);

  return this;
};

Component.helpers = function (helpers) {
  var helperMap = defaultValue(this, '_helpers', {});

  for (var key in helpers) {
    check(helpers[key], Function);
    helperMap[key] = (function (key) {
      return function () {
        var cmp = Component.findFirstComponent(Blaze.getView());
        check(cmp, Iron.Component);
        return helpers[key].apply(cmp, arguments);
      };
    }(key));
  }

  return this;
};

/**
 * Get the first parent data context that are not inclusion arguments
 * (see above function). Note: This function can create reactive dependencies.
 */
Component.getParentDataContext = function (view) {
  return Component.getDataContext(view && view.parentView);
};

Component.getDataContext = function (view) {
  while (view) {
    if (view.name === 'with' && !view.__isTemplateWith)
      return view.dataVar.get();
    else
      view = view.parentView;
  }

  return null;
};

/**
 * Get inclusion arguments, if any, from a view.
 *
 * Uses the __isTemplateWith property set when a parent view is used
 * specificially for a data context with inclusion args.
 *
 * Inclusion arguments are arguments provided in a template like this:
 * {{> yield "inclusionArg"}}
 * or
 * {{> yield region="inclusionArgValue"}}
 */
Component.getInclusionArguments = function (view) {
  var parent = view && view.parentView;

  if (!parent)
    return null;

  if (parent.__isTemplateWith)
    return parent.dataVar.get();

  return null;
};

/**
 * Given a view, return a function that can be used to access argument values at
 * the time the view was rendered. There are two key benefits:
 *
 * 1. Save the argument data at the time of rendering. When you use lookup(...)
 *    it starts from the current data context which can change.
 * 2. Defer creating a dependency on inclusion arguments until later.
 *
 * Example:
 *
 *   {{> MyTemplate template="MyTemplate"
 *   var args = Component.args(view);
 *   var tmplValue = args('template');
 *     => "MyTemplate"
 */
Component.args = function (view) {
  return function (key) {
    var data = Component.getInclusionArguments(view);

    if (data) {
      if (key)
        return data[key];
      else
        return data;
    }

    return null;
  };
};

Component.lookup = function (view, prop) {
  var template;

  while (view) {
    template = view.template;

    if (template && template[prop])
      return template[prop];
    else
      view = view.parentView;
  }

  return undefined;
};

Component.findFirstComponent = function (view) {
  assert(view instanceof Blaze.View, "view must be a Blaze.View");

  while (view) {
    if (view.__component__)
      return view.__component__;
    else
      view = view.parentView;
  }

  return null;
};

/*****************************************************************************/
/* Global Helpers */
/*****************************************************************************/
UI.registerHelper('getState', function (key) {
  var cmp = Component.findFirstComponent(Blaze.getView());
  return cmp.state.get(key);
});

/*****************************************************************************/
/* Namespacing */
/*****************************************************************************/
Iron.Component = Component;
<commit_msg>add component methods to lookup chain<commit_after>/*****************************************************************************/
/* Imports */
/*****************************************************************************/
var extend = Iron.utils.extend;
var debug = Iron.utils.debug('iron-component');
var camelCase = Iron.utils.camelCase;
var defaultValue = Iron.utils.defaultValue;
var assert = Iron.utils.assert;

/*****************************************************************************/
/* Private */
/*****************************************************************************/
var registerComponentHelper = function (name, Comp) {
  var tmpl = new Template(name, function () {
    var opts = Component.getInclusionArguments(this);
    var content = this.templateContentBlock;
    var elseContent = this.templateElseBlock;
    var instance = new Comp(_.extend(opts || {}, {
      content: content,
      elseContent: elseContent
    }));
    return instance.createView();
  });

  UI.registerHelper(name, tmpl);
};

var findFirstComponentOfType = function (type, view) {
  assert(typeof type === 'string', "type must be a string");
  assert(view instanceof Blaze.View, "view must be a Blaze.View");

  while (view) {
    if (view.name === type)
      return view.__component__;
    else
      view = view.parentView;
  }

  return null;
};

var findFirstComponent = function (view) {
  assert(view instanceof Blaze.View, "view must be a Blaze.View");

  while (view) {
    if (typeof view.__component__ !== 'undefined')
      return view.__component__;
    else
      view = view.parentView;
  }

  return null;
};

var typeOf = function (value) {
  return Object.prototype.toString.call(value);
};

/*****************************************************************************/
/* Core Overrides */
/*****************************************************************************/
/**
 * Overrides Blaze.View lookup method to also look for component methods.
 */
var lookup = Blaze.View.prototype.lookup;
Blaze.View.prototype.lookup = function (name, _options) {
  // we need to get the current view which might be lower
  // in the rendered view heirarchy than this view. The reason
  // is so that we can support templates like this:
  //
  // <template name="Outer">
  //   {{#StripeForm}}
  //    {{> errors}}
  //   {{/StripeForm}}
  // </template>
  //
  // The StripeForm component will never show up in the chain if we don't
  // use Blaze.getView() since "this" is actually Outer.
  var component = findFirstComponent(Blaze.getView());

  if (component && component[name]) {
    return function () {
      return component[name].apply(component, arguments);
    };
  } else {
    return lookup.apply(this, arguments);
  }
};

/*****************************************************************************/
/* Component */
/*****************************************************************************/
Component = function (options) {
  this.options = options = options || {};
  this._data = options.data;
  this._dataDep = new Deps.Dependency;
  this._hooks = {};
  this.state = new ReactiveDict;

  // has the Blaze.View been created?
  this.isCreated = false;

  // has the Blaze.View been destroyed and not created again?
  this.isDestroyed = false;

  this.init(this.options);
};

Component.prototype.template = null;

Component.prototype.init = function (options) {};

/**
 * Insert the Layout view into the dom.
 */
Component.prototype.insert = function (options) {
  options = options || {};

  if (this.isInserted)
    return;
  this.isInserted = true;

  var el = options.el || document.body;
  var $el = $(el);

  if ($el.length === 0)
    throw new Error("No element to insert layout into. Is your element defined? Try a Meteor.startup callback.");

  if (!this.view)
    this.createView(options);

  Blaze.render(this.view, $el[0], options.nextNode, options.parentView);
  return this;
};

/**
 * Get or set the data context.
 */
Component.prototype.data = function (value) {
  if (arguments.length === 1 && value !== this._data) {
    this._data = value;
    this._dataDep.changed();
    return;
  }

  this._dataDep.depend();
  return typeof this._data === 'function' ? this._data() : this._data;
};

Component.prototype.createView = function (options) {
  var self = this;

  if (this.isCreated) {
    throw new Error("Component view is already created");
  }

  this.isCreated = true;
  this.isDestroyed = false;

  var view = Blaze.View('Component', function () {
    var thisView = this;

    return Blaze.With(function () {
      // NOTE: This will rerun anytime the data function invalidates this
      // computation OR if created from an inclusion helper (see note below) any
      // time any of the argument functions invlidate the computation. For
      // example, when the template changes this function will rerun also. But
      // it's probably generally ok. The more serious use case is to not
      // re-render the entire template every time the data context changes.
      var result = self.data();

      if (typeof result !== 'undefined')
        // looks like data was set directly on this dynamic template
        return result;
      else
        // return the first parent data context that is not inclusion arguments
        return Component.getParentDataContext(thisView);
    }, function () {
      return self._renderView();
    });
  });

  // wire up the view lifecycle callbacks
  /*
  _.each(['onCreated', 'onMaterialized', 'onRendered', 'onDestroyed'], function (hook) {
    view[hook](function () {
      // "this" is the view instance
      self._runHooks(hook, this);
    });
  });
  */

  view._onViewRendered(function () {
    // avoid inserting the view twice by accident.
    self.isInserted = true;

    // following the lead of template.js in core
    if (view.renderCount !== 1)
      return;

    _.each(self.constructor._eventMaps, function (m) {
      Blaze._addEventMap(view, m, view);
    });
  });

  view._templateInstance = new Blaze.TemplateInstance(view);
  view.templateInstance = function () {
    // Update data, firstNode, and lastNode, and return the TemplateInstance
    // object.
    var inst = view._templateInstance;

    inst.data = Blaze.getData(view);

    if (view._domrange && !view.isDestroyed) {
      inst.firstNode = view._domrange.firstNode();
      inst.lastNode = view._domrange.lastNode();
    } else {
      // on 'created' or 'destroyed' callbacks we don't have a DomRange
      inst.firstNode = null;
      inst.lastNode = null;
    }

    return inst;
  };

  this.view = view;
  view.__component__ = this;
  // so helper lookup works as expected
  view.template = this;
  view.name = this.constructor.name;

  return view;
};

/**
 * Destroy the component.
 */
Component.prototype.destroy = function () {
  if (this.isCreated) {
    Blaze.remove(this.view);
    this.view = null;
    this.isDestroyed = true;
    this.isCreated = false;
  }
};

Component.prototype.lookupTemplate = function () {
  var self = this;
  var template = this.template;
  var tmpl = null;

  // is it a template name like "MyTemplate"?
  if (typeof template === 'string') {
    tmpl = Template[template];

    if (!tmpl)
      // as a fallback double check the user didn't actually define
      // a camelCase version of the template.
      tmpl = Template[camelCase(template)];

    if (!tmpl)
      throw new Error("Couldn't find a template named " + JSON.stringify(template) + " or " + JSON.stringify(camelCase(template))+ ". Are you sure you defined it?");

    tmpl = Spacebars.include(
      tmpl,
      function contentBlock () { return self.options.content; },
      function elseBlock () { return self.options.elseContent; }
    );

  } else if (typeOf(template) === '[object Object]') {
    // or maybe a view already?
    tmpl = template;
  } else if (typeof self.options.content !== 'undefined') {
    // or maybe its block content like
    // {{#DynamicTemplate}}
    //  Some block
    // {{/DynamicTemplate}}
    tmpl = self.options.content;
    tmpl.template = self;
  }

  return tmpl;
};

Component.prototype._renderView = function () {
  var tmpl = this.render();

  if (tmpl.template) {
    _.extend(tmpl.template, this.constructor._helpers);
  }

  return tmpl;
};

Component.prototype.render = function () {
  return this.lookupTemplate();
};

Component.prototype.call = function (prop) {
  var args = _.toArray(arguments).slice(1);
  return this.apply(prop, args);
};

Component.prototype.apply = function (prop, args) {
  var func = Component.lookup(this.view, prop);
  var thisArg = Component.getDataContext(this.view) || {};
  assert(typeof func === 'function', "Couldn't find a function named " + JSON.stringify(prop));
  return func.apply(thisArg, args);
};

/**
 * View lifecycle hooks.
 * XXX update for new blaze
 */
_.each([], function (hook) {
  Component.prototype[hook] = function (cb) {
    var hooks = this._hooks[hook] = this._hooks[hook] || [];
    hooks.push(cb);
    return this;
  };
});

Component.prototype._runHooks = function (name, view) {
  var hooks = this._hooks[name] || [];
  var hook;

  for (var i = 0; i < hooks.length; i++) {
    hook = hooks[i];
    // keep the "thisArg" pointing to the view, but make the first parameter to
    // the callback teh dynamic template instance.
    hook.call(view, this);
  }
};

/*****************************************************************************/
/* Component Static Methods */
/*****************************************************************************/
Component.extend = function (definition) {
  return extend(this, definition);
};

/**
 * Register a global UI helper for the component.
 */
Component.registerHelper = function () {
  check(this.name, String);
  registerComponentHelper(this.name, this);
  return this;
};

/**
 * Allow components to define their own events.
 */
Component.events = function (events) {
  var maps = defaultValue(this, '_eventMaps', []);

  var boundMap = {};

  for (var key in events) {
    boundMap[key] = (function (key, handler) {
      return function (e) {
        var view = this;
        var component = view.__component__;
        var args = Array.prototype.slice.call(arguments);
        var tmplInstance = view.templateInstance();
        return handler.call(component, e, tmplInstance);
      };
    })(key, events[key]);
  }

  maps.push(boundMap);

  return this;
};

/**
 * Get the first parent data context that are not inclusion arguments
 * (see above function). Note: This function can create reactive dependencies.
 */
Component.getParentDataContext = function (view) {
  return Component.getDataContext(view && view.parentView);
};

Component.getDataContext = function (view) {
  while (view) {
    if (view.name === 'with' && !view.__isTemplateWith)
      return view.dataVar.get();
    else
      view = view.parentView;
  }

  return null;
};

/**
 * Get inclusion arguments, if any, from a view.
 *
 * Uses the __isTemplateWith property set when a parent view is used
 * specificially for a data context with inclusion args.
 *
 * Inclusion arguments are arguments provided in a template like this:
 * {{> yield "inclusionArg"}}
 * or
 * {{> yield region="inclusionArgValue"}}
 */
Component.getInclusionArguments = function (view) {
  var parent = view && view.parentView;

  if (!parent)
    return null;

  if (parent.__isTemplateWith)
    return parent.dataVar.get();

  return null;
};

/**
 * Given a view, return a function that can be used to access argument values at
 * the time the view was rendered. There are two key benefits:
 *
 * 1. Save the argument data at the time of rendering. When you use lookup(...)
 *    it starts from the current data context which can change.
 * 2. Defer creating a dependency on inclusion arguments until later.
 *
 * Example:
 *
 *   {{> MyTemplate template="MyTemplate"
 *   var args = Component.args(view);
 *   var tmplValue = args('template');
 *     => "MyTemplate"
 */
Component.args = function (view) {
  return function (key) {
    var data = Component.getInclusionArguments(view);

    if (data) {
      if (key)
        return data[key];
      else
        return data;
    }

    return null;
  };
};

Component.lookup = function (view, prop) {
  var template;
  var origView = view;

  while (view) {
    template = view.template;

    if (template && template[prop])
      return template[prop];
    else
      view = view.parentView;
  }

  if (Package['iron:controller']) {
    return Blaze._withCurrentView(origView, function () {
      var controller = Iron.controller();

      if (controller)
        return controller[prop];
    });
  }

  return undefined;
};

Component.findFirstComponent = function (view) {
  assert(view instanceof Blaze.View, "view must be a Blaze.View");

  while (view) {
    if (view.__component__)
      return view.__component__;
    else
      view = view.parentView;
  }

  return null;
};

/*****************************************************************************/
/* Global Helpers */
/*****************************************************************************/
UI.registerHelper('getState', function (key) {
  var cmp = Component.findFirstComponent(Blaze.getView());
  return cmp.state.get(key);
});

/*****************************************************************************/
/* Namespacing */
/*****************************************************************************/
Iron.Component = Component;
<|endoftext|>


<commit_before>// Backbone React Component
// ========================
//
//     Backbone.React.Component v0.7.2
//
//     (c) 2014 "Magalhas" José Magalhães <magalhas@gmail.com>
//     Backbone.React.Component can be freely distributed under the MIT license.
//
//
// `Backbone.React.Component` is a mixin that glues [Backbone](http://backbonejs.org/)
// models and collections into [React](http://facebook.github.io/react/) components.
//
// When the component is mounted, a wrapper starts listening to models and
// collections changes to automatically set your component props and achieve UI
// binding through reactive updates.
//
//
//
// Basic Usage
//
//     var MyComponent = React.createClass({
//       mixins: [Backbone.React.Component.mixin],
//       render: function () {
//         return
{this.props.foo}
;
//       }
//     });
//     var model = new Backbone.Model({foo: 'bar'});
//     React.render(<MyComponent model={model} />, document.body);

(function (root, factory) {
  // Universal module definition
  if (typeof define === 'function' && define.amd)
    define(['react', 'backbone', 'underscore'], factory);
  else if (typeof module !== 'undefined' && module.exports) {
    var React = require('react');
    var Backbone = require('backbone');
    var _ = require('underscore');
    module.exports = factory(React, Backbone, _);
  } else
    factory(root.React, root.Backbone, root._);
}(this, function (React, Backbone, _) {
  'use strict';
  if (!Backbone.React) {
    Backbone.React = {};
  }
  if (!Backbone.React.Component) {
    Backbone.React.Component = {};
  }
  // Mixin used in all component instances. Exported through `Backbone.React.Component.mixin`.
  Backbone.React.Component.mixin = {
    // Sets `this.el` and `this.$el` when the component mounts.
    componentDidMount: function () {
      this.setElement(this.getDOMNode());
    },
    // Sets `this.el` and `this.$el` when the component updates.
    componentDidUpdate: function () {
      this.setElement(this.getDOMNode());
    },
    // When the component mounts, instance a `Wrapper` to take care
    // of models and collections binding with `this.props`.
    componentWillMount: function () {
      if (!this.wrapper) {
        this.wrapper = new Wrapper(this, this.props);
      }
    },
    // When the component unmounts, dispose listeners and delete
    // `this.wrapper` reference.
    componentWillUnmount: function () {
      if (this.wrapper) {
        this.wrapper.stopListening();
        delete this.wrapper;
      }
    },
    // In order to allow passing nested models and collections as reference we
    // filter `nextProps.model` and `nextProps.collection`.
    componentWillReceiveProps: function (nextProps) {
      var model = nextProps.model;
      var collection = nextProps.collection;

      var key;

      if (this.wrapper.model && model) {
        delete nextProps.model;
        if (this.wrapper.model.attributes) {
          this.wrapper.setProps(model, void 0, nextProps);
        } else {
          for (key in model) {
            this.wrapper.setProps(model[key], key, nextProps);
          }
        }
      }
      if (this.wrapper.collection && collection && !(collection instanceof Array)) {
        delete nextProps.collection;
        if (this.wrapper.collection.models) {
          this.wrapper.setProps(collection, void 0, nextProps);
        } else {
          for (key in collection) {
            this.wrapper.setProps(collection[key], key, nextProps);
          }
        }
      }
    },
    // Shortcut to `this.$el.find`. Inspired by `Backbone.View`.
    $: function () {
      return this.$el && this.$el.find.apply(this.$el, arguments);
    },
    // Crawls up to the owner of the component searching for a collection.
    getCollection: function () {
      var owner = this;
      var lookup = owner.wrapper;
      while (!lookup.collection) {
        owner = owner._owner;
        if (!owner) {
          throw new Error('Collection not found');
        }
        lookup = owner.wrapper;
      }
      return lookup.collection;
    },
    // Crawls up to the owner of the component searching for a model.
    getModel: function () {
      var owner = this;
      var lookup = owner.wrapper;
      while (!lookup.model) {
        owner = owner._owner;
        if (!owner) {
          throw new Error('Model not found');
        }
        lookup = owner.wrapper;
      }
      return lookup.model;
    },
    // Crawls `this._owner` recursively until it finds the owner of `this`
    // component. In case of being a parent component (no owners) it returns itself.
    getOwner: function () {
      var owner = this;
      while (owner._owner) {
        owner = owner._owner;
      }
      return owner;
    },
    // Sets a DOM element to render/mount this component on this.el and this.$el.
    setElement: function (el) {
      if (el && Backbone.$ && el instanceof Backbone.$) {
        if (el.length > 1) {
          throw new Error('You can only assign one element to a component');
        }
        this.el = el[0];
        this.$el = el;
      } else if (el) {
        this.el = el;
        if (Backbone.$) {
          this.$el = Backbone.$(el);
        }
      }
      return this;
    }
  };
  // Binds models and collections to a `React.Component`. It mixes `Backbone.Events`.
  function Wrapper (component, props) {
    props = props || {};
    var model = props.model, collection = props.collection;
    // Check if `props.model` is a `Backbone.Model` or an hashmap of them
    if (typeof model !== 'undefined' && (model.attributes ||
        typeof model === 'object' && _.values(model)[0].attributes)) {
      delete props.model;
      // The model(s) bound to this component
      this.model = model;
      // Set model(s) attributes on `props` for the first render
      this.setPropsBackbone(model, void 0, props);
    }
    // Check if `props.collection` is a `Backbone.Collection` or an hashmap of them
    if (typeof collection !== 'undefined' && (collection.models ||
        typeof collection === 'object' && _.values(collection)[0].models)) {
      delete props.collection;
      // The collection(s) bound to this component
      this.collection = collection;
      // Set collection(s) models on props for the first render
      this.setPropsBackbone(collection, void 0, props);
    }
    // 1:1 relation with the `component`
    this.component = component;
    // Start listeners if this is a root node and if there's DOM
    if (!component._owner && typeof document !== 'undefined') {
      this.startModelListeners();
      this.startCollectionListeners();
    }
  }
  // Mixing `Backbone.Events` into `Wrapper.prototype`
  _.extend(Wrapper.prototype, Backbone.Events, {
    // Sets `this.props` when a model/collection request results in error. It delegates
    // to `this.setProps`. It listens to `Backbone.Model#error` and `Backbone.Collection#error`.
    onError: function (modelOrCollection, res, options) {
      // Set props only if there's no silent option
      if (!options.silent)
        this.setProps({
          isRequesting: false,
          hasError: true,
          error: res
        });
    },
    // Sets `this.props` when a model/collection request starts. It delegates to
    // `this.setProps`. It listens to `Backbone.Model#request` and `Backbone.Collection#request`.
    onRequest: function (modelOrCollection, xhr, options) {
      // Set props only if there's no silent option
      if (!options.silent)
        this.setProps({
          isRequesting: true,
          hasError: false
        });
    },
    // Sets `this.props` when a model/collection syncs. It delegates to `this.setProps`.
    // It listens to `Backbone.Model#sync` and `Backbone.Collection#sync`
    onSync: function (modelOrCollection, res, options) {
      // Set props only if there's no silent option
      if (!options.silent)
        this.setProps({isRequesting: false});
    },
    // Used internally to set `this.collection` or `this.model` on `this.props`. Delegates to
    // `this.setProps`. It listens to `Backbone.Collection` events such as `add`, `remove`,
    // `change`, `sort`, `reset` and to `Backbone.Model` `change`.
    setPropsBackbone: function (modelOrCollection, key, target) {
      if (!(modelOrCollection.models || modelOrCollection.attributes)) {
        for (key in modelOrCollection)
            this.setPropsBackbone(modelOrCollection[key], key, target);
        return;
      }
      this.setProps.apply(this, arguments);
    },
    // Sets a model, collection or object into props by delegating to `this.setProps`.
    setProps: function (modelOrCollection, key, target) {
      var props = {};
      var newProps = modelOrCollection.toJSON ? modelOrCollection.toJSON() : modelOrCollection;

      if (key) {
        props[key] = newProps;
      } else if (modelOrCollection instanceof Backbone.Collection) {
        props.collection = newProps;
      } else {
        props = newProps;
      }

      if (target) {
        _.extend(target, props);
      } else {
        this.nextProps = _.extend(this.nextProps || {}, props);
        _.defer(_.bind(function () {
          if (this.nextProps) {
            if (this.component) {
              this.component.setProps(this.nextProps);
            }
            delete this.nextProps;
          }
        }, this));
      }
    },
    // Binds the component to any collection changes.
    startCollectionListeners: function (collection, key) {
      if (!collection) collection = this.collection;
      if (collection) {
        if (collection.models)
          this
            .listenTo(collection, 'add remove change sort reset',
              _.partial(this.setPropsBackbone, collection, key, void 0))
            .listenTo(collection, 'error', this.onError)
            .listenTo(collection, 'request', this.onRequest)
            .listenTo(collection, 'sync', this.onSync);
        else if (typeof collection === 'object')
          for (key in collection)
            if (collection.hasOwnProperty(key))
              this.startCollectionListeners(collection[key], key);
      }
    },
    // Binds the component to any model changes.
    startModelListeners: function (model, key) {
      if (!model) model = this.model;
      if (model) {
        if (model.attributes)
          this
            .listenTo(model, 'change',
              _.partial(this.setPropsBackbone, model, key, void 0))
            .listenTo(model, 'error', this.onError)
            .listenTo(model, 'request', this.onRequest)
            .listenTo(model, 'sync', this.onSync);
        else if (typeof model === 'object')
          for (key in model)
            this.startModelListeners(model[key], key);
      }
    }
  });

  // Expose `Backbone.React.Component.mixin`.
  return Backbone.React.Component.mixin;
}));
//
<commit_msg>cleanup code on the umd<commit_after>// Backbone React Component
// ========================
//
//     Backbone.React.Component v0.7.2
//
//     (c) 2014 "Magalhas" José Magalhães <magalhas@gmail.com>
//     Backbone.React.Component can be freely distributed under the MIT license.
//
//
// `Backbone.React.Component` is a mixin that glues [Backbone](http://backbonejs.org/)
// models and collections into [React](http://facebook.github.io/react/) components.
//
// When the component is mounted, a wrapper starts listening to models and
// collections changes to automatically set your component props and achieve UI
// binding through reactive updates.
//
//
//
// Basic Usage
//
//     var MyComponent = React.createClass({
//       mixins: [Backbone.React.Component.mixin],
//       render: function () {
//         return
{this.props.foo}
;
//       }
//     });
//     var model = new Backbone.Model({foo: 'bar'});
//     React.render(<MyComponent model={model} />, document.body);

(function (root, factory) {
  // Universal module definition
  if (typeof define === 'function' && define.amd) {
    define(['react', 'backbone', 'underscore'], factory);
  } else if (typeof module !== 'undefined' && module.exports) {
    module.exports = factory(require('react'), require('backbone'), require('underscore'));
  } else {
    factory(root.React, root.Backbone, root._);
  }
}(this, function (React, Backbone, _) {
  'use strict';
  if (!Backbone.React) {
    Backbone.React = {};
  }
  if (!Backbone.React.Component) {
    Backbone.React.Component = {};
  }
  // Mixin used in all component instances. Exported through `Backbone.React.Component.mixin`.
  Backbone.React.Component.mixin = {
    // Sets `this.el` and `this.$el` when the component mounts.
    componentDidMount: function () {
      this.setElement(this.getDOMNode());
    },
    // Sets `this.el` and `this.$el` when the component updates.
    componentDidUpdate: function () {
      this.setElement(this.getDOMNode());
    },
    // When the component mounts, instance a `Wrapper` to take care
    // of models and collections binding with `this.props`.
    componentWillMount: function () {
      if (!this.wrapper) {
        this.wrapper = new Wrapper(this, this.props);
      }
    },
    // When the component unmounts, dispose listeners and delete
    // `this.wrapper` reference.
    componentWillUnmount: function () {
      if (this.wrapper) {
        this.wrapper.stopListening();
        delete this.wrapper;
      }
    },
    // In order to allow passing nested models and collections as reference we
    // filter `nextProps.model` and `nextProps.collection`.
    componentWillReceiveProps: function (nextProps) {
      var model = nextProps.model;
      var collection = nextProps.collection;

      var key;

      if (this.wrapper.model && model) {
        delete nextProps.model;
        if (this.wrapper.model.attributes) {
          this.wrapper.setProps(model, void 0, nextProps);
        } else {
          for (key in model) {
            this.wrapper.setProps(model[key], key, nextProps);
          }
        }
      }
      if (this.wrapper.collection && collection && !(collection instanceof Array)) {
        delete nextProps.collection;
        if (this.wrapper.collection.models) {
          this.wrapper.setProps(collection, void 0, nextProps);
        } else {
          for (key in collection) {
            this.wrapper.setProps(collection[key], key, nextProps);
          }
        }
      }
    },
    // Shortcut to `this.$el.find`. Inspired by `Backbone.View`.
    $: function () {
      return this.$el && this.$el.find.apply(this.$el, arguments);
    },
    // Crawls up to the owner of the component searching for a collection.
    getCollection: function () {
      var owner = this;
      var lookup = owner.wrapper;
      while (!lookup.collection) {
        owner = owner._owner;
        if (!owner) {
          throw new Error('Collection not found');
        }
        lookup = owner.wrapper;
      }
      return lookup.collection;
    },
    // Crawls up to the owner of the component searching for a model.
    getModel: function () {
      var owner = this;
      var lookup = owner.wrapper;
      while (!lookup.model) {
        owner = owner._owner;
        if (!owner) {
          throw new Error('Model not found');
        }
        lookup = owner.wrapper;
      }
      return lookup.model;
    },
    // Crawls `this._owner` recursively until it finds the owner of `this`
    // component. In case of being a parent component (no owners) it returns itself.
    getOwner: function () {
      var owner = this;
      while (owner._owner) {
        owner = owner._owner;
      }
      return owner;
    },
    // Sets a DOM element to render/mount this component on this.el and this.$el.
    setElement: function (el) {
      if (el && Backbone.$ && el instanceof Backbone.$) {
        if (el.length > 1) {
          throw new Error('You can only assign one element to a component');
        }
        this.el = el[0];
        this.$el = el;
      } else if (el) {
        this.el = el;
        if (Backbone.$) {
          this.$el = Backbone.$(el);
        }
      }
      return this;
    }
  };
  // Binds models and collections to a `React.Component`. It mixes `Backbone.Events`.
  function Wrapper (component, props) {
    props = props || {};
    var model = props.model, collection = props.collection;
    // Check if `props.model` is a `Backbone.Model` or an hashmap of them
    if (typeof model !== 'undefined' && (model.attributes ||
        typeof model === 'object' && _.values(model)[0].attributes)) {
      delete props.model;
      // The model(s) bound to this component
      this.model = model;
      // Set model(s) attributes on `props` for the first render
      this.setPropsBackbone(model, void 0, props);
    }
    // Check if `props.collection` is a `Backbone.Collection` or an hashmap of them
    if (typeof collection !== 'undefined' && (collection.models ||
        typeof collection === 'object' && _.values(collection)[0].models)) {
      delete props.collection;
      // The collection(s) bound to this component
      this.collection = collection;
      // Set collection(s) models on props for the first render
      this.setPropsBackbone(collection, void 0, props);
    }
    // 1:1 relation with the `component`
    this.component = component;
    // Start listeners if this is a root node and if there's DOM
    if (!component._owner && typeof document !== 'undefined') {
      this.startModelListeners();
      this.startCollectionListeners();
    }
  }
  // Mixing `Backbone.Events` into `Wrapper.prototype`
  _.extend(Wrapper.prototype, Backbone.Events, {
    // Sets `this.props` when a model/collection request results in error. It delegates
    // to `this.setProps`. It listens to `Backbone.Model#error` and `Backbone.Collection#error`.
    onError: function (modelOrCollection, res, options) {
      // Set props only if there's no silent option
      if (!options.silent)
        this.setProps({
          isRequesting: false,
          hasError: true,
          error: res
        });
    },
    // Sets `this.props` when a model/collection request starts. It delegates to
    // `this.setProps`. It listens to `Backbone.Model#request` and `Backbone.Collection#request`.
    onRequest: function (modelOrCollection, xhr, options) {
      // Set props only if there's no silent option
      if (!options.silent)
        this.setProps({
          isRequesting: true,
          hasError: false
        });
    },
    // Sets `this.props` when a model/collection syncs. It delegates to `this.setProps`.
    // It listens to `Backbone.Model#sync` and `Backbone.Collection#sync`
    onSync: function (modelOrCollection, res, options) {
      // Set props only if there's no silent option
      if (!options.silent)
        this.setProps({isRequesting: false});
    },
    // Used internally to set `this.collection` or `this.model` on `this.props`. Delegates to
    // `this.setProps`. It listens to `Backbone.Collection` events such as `add`, `remove`,
    // `change`, `sort`, `reset` and to `Backbone.Model` `change`.
    setPropsBackbone: function (modelOrCollection, key, target) {
      if (!(modelOrCollection.models || modelOrCollection.attributes)) {
        for (key in modelOrCollection)
            this.setPropsBackbone(modelOrCollection[key], key, target);
        return;
      }
      this.setProps.apply(this, arguments);
    },
    // Sets a model, collection or object into props by delegating to `this.setProps`.
    setProps: function (modelOrCollection, key, target) {
      var props = {};
      var newProps = modelOrCollection.toJSON ? modelOrCollection.toJSON() : modelOrCollection;

      if (key) {
        props[key] = newProps;
      } else if (modelOrCollection instanceof Backbone.Collection) {
        props.collection = newProps;
      } else {
        props = newProps;
      }

      if (target) {
        _.extend(target, props);
      } else {
        this.nextProps = _.extend(this.nextProps || {}, props);
        _.defer(_.bind(function () {
          if (this.nextProps) {
            if (this.component) {
              this.component.setProps(this.nextProps);
            }
            delete this.nextProps;
          }
        }, this));
      }
    },
    // Binds the component to any collection changes.
    startCollectionListeners: function (collection, key) {
      if (!collection) collection = this.collection;
      if (collection) {
        if (collection.models)
          this
            .listenTo(collection, 'add remove change sort reset',
              _.partial(this.setPropsBackbone, collection, key, void 0))
            .listenTo(collection, 'error', this.onError)
            .listenTo(collection, 'request', this.onRequest)
            .listenTo(collection, 'sync', this.onSync);
        else if (typeof collection === 'object')
          for (key in collection)
            if (collection.hasOwnProperty(key))
              this.startCollectionListeners(collection[key], key);
      }
    },
    // Binds the component to any model changes.
    startModelListeners: function (model, key) {
      if (!model) model = this.model;
      if (model) {
        if (model.attributes)
          this
            .listenTo(model, 'change',
              _.partial(this.setPropsBackbone, model, key, void 0))
            .listenTo(model, 'error', this.onError)
            .listenTo(model, 'request', this.onRequest)
            .listenTo(model, 'sync', this.onSync);
        else if (typeof model === 'object')
          for (key in model)
            this.startModelListeners(model[key], key);
      }
    }
  });

  // Expose `Backbone.React.Component.mixin`.
  return Backbone.React.Component.mixin;
}));
//
<|endoftext|>


<commit_before>'use strict';

angular.module('classBrowserUHApp.offeredClass', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/offeredClass', {
        templateUrl: 'views/offeredClass/offeredClass.html',
        controller: 'OfferedClassCtrl'
    });
}])
.controller('OfferedClassCtrl', ['$scope', '$http', '$q', '$rootScope', '$parse', '$window', function ($scope, $http, $q, $rootScope, $parse, $window) {
    var setScopeVariableFromJSON = function(filePath, scopeVariable) {
        $rootScope.httpService.getData(filePath).then(function(result) {
            $parse(scopeVariable).assign($scope, result);
        });
    };

    var initializeAllJSONAndScopeNames = function(name) {
        $rootScope.httpService.getData('resources/allScopeVariables.json').then(function(result) {
            $scope.allJSONAndScopeNames = result[name];
            $scope.allJSONAndScopeNames.forEach(function(e) {
                setScopeVariableFromJSON(e.path, e.scopeName);
            });
        });
    };

    initializeAllJSONAndScopeNames("offeredClass");

    $scope.validValues = ['a', 'A','1','2', '3', '4', '5', '6', '7', '8', '9', '0'];

    $scope.deleteModel = function() {
        [].slice.call(arguments).forEach(function(arg) {
            delete $scope[arg];
        });
    };

    $scope.clearForms = function() {
        var clearFormDialogConfirmation = $window.confirm('Are you sure you want to clear the entire form?');

        if (clearFormDialogConfirmation) {
            $scope.allJSONAndScopeNames.forEach(function(e) {
                $scope.deleteModel(e.modelName);
            });
        }
    };

    $scope.findClasses = function(isValidForm) {
        if(isValidForm) {
            $scope.isDataLoading = true;
            $scope.isError = false;
            $scope.hasNoResults = false;

            console.log("Finding classes...");
            $scope.showResults = true;

            var generateMessage = function(model, type, parameter, secondParameter) {
                if(model == undefined || model.length == 0) {
                    return "";
                }
                if($rootScope.types.get(model) == $rootScope.types.object) {
                    return "" + type + ": " + model[parameter] + " " + model[secondParameter] + "
";
                }
                else {
                    return " " + type + ": " + _.pluck(model, parameter).join(', ') + "
";
                }
            };

            $scope.allJSONAndScopeNames.forEach(function(e) {
                var obj = $scope.$eval(e.modelName);
                console.log(e.parameter + "=" + obj[e.parameter]);
            });

            // $scope.parametersMessage = generateMessage($scope.termModel, 'Terms', 'semester', 'year');
            $scope.parametersMessage = generateMessageForAllModels();
        }
        else {
            alert("Please select a class term.");
        }
    };

    var generateMessageForAllModels = function() {
        var message = "";
        $scope.allJSONAndScopeNames.forEach(function(e) {
            if($scope.$eval(e.modelName) != undefined) {
                message += "" + e.uiParameter + ": ";
                var apiParameter = e.apiParameter;
                var modelValue = $scope.$eval(e.modelName);

                if($rootScope.types.get(modelValue) === $rootScope.types.array) {

                    for(var i = 0; i < modelValue.length; i++) {
                        console.log(modelValue[i]);
                        modelValue[i] = modelValue[i][apiParameter];
                    }
                    var allParameterValuesForGivenmodel = modelValue.join(", ");
                    message += allParameterValuesForGivenmodel;
                }
                else {
                    message += $scope.$eval(e.modelName)[apiParameter];
                }
                message += "
";
            }
            else {
                message += e.modelName + " is undefined
";
            }
        });
        return message;
    };

    $scope.goBack = function() {
        console.log('Going back to offered class search page.');
        $scope.showResults = false;

        $scope.allJSONAndScopeNames.forEach(function(e) {
            deleteModel(e.modelName);
        });

        deleteModel('parametersMessage');

    };

    $scope.termModel = {"term":2000,"year":2016,"semester":"Fall"};
    $scope.formatModel = [{"format":"Hybrid","isOrNot":"Is"},{"format":"Face to Face","isOrNot":"Not"}];
    $scope.statusModel = {"status":"Closed"};
    $scope.sessionModel = [{"session":4,"sessionTitle":"Session 4"},{"session":2,"sessionTitle":"Session 2"}];
    $scope.departmentModel = [{"departmentName":"AFSC","departmentFullName":"Air Force Science"},{"departmentName":"ARAB","departmentFullName":"Arabic"}];
    $scope.buildingModel = [{"buildingID":517,"buildingAbbreviation":"A","buildingName":"Cullen Performance Hall"}];
    $scope.locationModel = [{"location":"UH-Sugar Land"},{"location":"UH-San Antonio-Conrad Hilton"},{"location":"UH"}];
    $scope.componentModel = [{"component":"LEC","componentName":"Lecture"}];
    $scope.creditHourModel = [{"creditHours":4}];
    $scope.weekendUModel = {"weekendU":"No"};
    $scope.coreCategoriesModel = [{"categoryNumber":2,"categoryName":"Mathematics"}];
    $scope.isCoreModel = {"core":"No"};
    $scope.syllabusModel = {"syllabus":"No"};
    $scope.classDaysModel = [{"day":"Monday","isOrNot":"Is"},{"day":"Sunday","isOrNot":"Is"},{"day":"Tuesday","isOrNot":"Not"}];
    $scope.courseNumberModel = 2410;

}]);
<commit_msg>Referenced correct deleteModel function.<commit_after>'use strict';

angular.module('classBrowserUHApp.offeredClass', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/offeredClass', {
        templateUrl: 'views/offeredClass/offeredClass.html',
        controller: 'OfferedClassCtrl'
    });
}])
.controller('OfferedClassCtrl', ['$scope', '$http', '$q', '$rootScope', '$parse', '$window', function ($scope, $http, $q, $rootScope, $parse, $window) {
    var setScopeVariableFromJSON = function(filePath, scopeVariable) {
        $rootScope.httpService.getData(filePath).then(function(result) {
            $parse(scopeVariable).assign($scope, result);
        });
    };

    var initializeAllJSONAndScopeNames = function(name) {
        $rootScope.httpService.getData('resources/allScopeVariables.json').then(function(result) {
            $scope.allJSONAndScopeNames = result[name];
            $scope.allJSONAndScopeNames.forEach(function(e) {
                setScopeVariableFromJSON(e.path, e.scopeName);
            });
        });
    };

    initializeAllJSONAndScopeNames("offeredClass");

    $scope.validValues = ['a', 'A','1','2', '3', '4', '5', '6', '7', '8', '9', '0'];

    $scope.deleteModel = function() {
        [].slice.call(arguments).forEach(function(arg) {
            delete $scope[arg];
        });
    };

    $scope.clearForms = function() {
        var clearFormDialogConfirmation = $window.confirm('Are you sure you want to clear the entire form?');

        if (clearFormDialogConfirmation) {
            $scope.allJSONAndScopeNames.forEach(function(e) {
                $scope.deleteModel(e.modelName);
            });
        }
    };

    $scope.findClasses = function(isValidForm) {
        if(isValidForm) {
            $scope.isDataLoading = true;
            $scope.isError = false;
            $scope.hasNoResults = false;

            console.log("Finding classes...");
            $scope.showResults = true;

            var generateMessage = function(model, type, parameter, secondParameter) {
                if(model == undefined || model.length == 0) {
                    return "";
                }
                if($rootScope.types.get(model) == $rootScope.types.object) {
                    return "" + type + ": " + model[parameter] + " " + model[secondParameter] + "
";
                }
                else {
                    return " " + type + ": " + _.pluck(model, parameter).join(', ') + "
";
                }
            };

            $scope.allJSONAndScopeNames.forEach(function(e) {
                var obj = $scope.$eval(e.modelName);
                console.log(e.parameter + "=" + obj[e.parameter]);
            });

            // $scope.parametersMessage = generateMessage($scope.termModel, 'Terms', 'semester', 'year');
            $scope.parametersMessage = generateMessageForAllModels();
        }
        else {
            alert("Please select a class term.");
        }
    };

    var generateMessageForAllModels = function() {
        var message = "";
        $scope.allJSONAndScopeNames.forEach(function(e) {
            if($scope.$eval(e.modelName) != undefined) {
                message += "" + e.uiParameter + ": ";
                var apiParameter = e.apiParameter;
                var modelValue = $scope.$eval(e.modelName);

                if($rootScope.types.get(modelValue) === $rootScope.types.array) {

                    for(var i = 0; i < modelValue.length; i++) {
                        console.log(modelValue[i]);
                        modelValue[i] = modelValue[i][apiParameter];
                    }
                    var allParameterValuesForGivenmodel = modelValue.join(", ");
                    message += allParameterValuesForGivenmodel;
                }
                else {
                    message += $scope.$eval(e.modelName)[apiParameter];
                }
                message += "
";
            }
            else {
                message += e.modelName + " is undefined
";
            }
        });
        return message;
    };

    $scope.goBack = function() {
        console.log('Going back to offered class search page.');
        $scope.showResults = false;

        $scope.allJSONAndScopeNames.forEach(function(e) {
            $scope.deleteModel(e.modelName);
        });

        $scope.deleteModel('parametersMessage');

    };

    $scope.termModel = {"term":2000,"year":2016,"semester":"Fall"};
    $scope.formatModel = [{"format":"Hybrid","isOrNot":"Is"},{"format":"Face to Face","isOrNot":"Not"}];
    $scope.statusModel = {"status":"Closed"};
    $scope.sessionModel = [{"session":4,"sessionTitle":"Session 4"},{"session":2,"sessionTitle":"Session 2"}];
    $scope.departmentModel = [{"departmentName":"AFSC","departmentFullName":"Air Force Science"},{"departmentName":"ARAB","departmentFullName":"Arabic"}];
    $scope.buildingModel = [{"buildingID":517,"buildingAbbreviation":"A","buildingName":"Cullen Performance Hall"}];
    $scope.locationModel = [{"location":"UH-Sugar Land"},{"location":"UH-San Antonio-Conrad Hilton"},{"location":"UH"}];
    $scope.componentModel = [{"component":"LEC","componentName":"Lecture"}];
    $scope.creditHourModel = [{"creditHours":4}];
    $scope.weekendUModel = {"weekendU":"No"};
    $scope.coreCategoriesModel = [{"categoryNumber":2,"categoryName":"Mathematics"}];
    $scope.isCoreModel = {"core":"No"};
    $scope.syllabusModel = {"syllabus":"No"};
    $scope.classDaysModel = [{"day":"Monday","isOrNot":"Is"},{"day":"Sunday","isOrNot":"Is"},{"day":"Tuesday","isOrNot":"Not"}];
    $scope.courseNumberModel = 2410;

}]);
<|endoftext|>


<commit_before>'use strict';

angular.module('classBrowserUHApp.offeredClass', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/offeredClass', {
        templateUrl: 'views/offeredClass/offeredClass.html',
        controller: 'OfferedClassCtrl'
    });
}])
.controller('OfferedClassCtrl', ['$scope', '$http', '$q', '$rootScope', '$parse', '$window', function ($scope, $http, $q, $rootScope, $parse, $window) {
    var setScopeVariableFromJSON = function(filePath, scopeVariable) {
        $rootScope.httpService.getData(filePath).then(function(result) {
            $parse(scopeVariable).assign($scope, result);
        });
    };

    var initializeAllJSONAndScopeNames = function(name) {
        $rootScope.httpService.getData('resources/allScopeVariables.json').then(function(result) {
            $scope.allJSONAndScopeNames = result[name];
            $scope.allJSONAndScopeNames.forEach(function(e) {
                setScopeVariableFromJSON(e.path, e.scopeName);
            });
        });
    };

    initializeAllJSONAndScopeNames("offeredClass");

    $scope.validValues = ['A','1','2', '3', '4', '5', '6', '7', '8', '9', '0'];

    $scope.deleteModel = function() {
        [].slice.call(arguments).forEach(function(arg) {
            delete $scope[arg];
        });
    };

    $scope.clearForms = function() {
        var clearFormDialogConfirmation = $window.confirm('Are you sure you want to clear the entire form?');

        if (clearFormDialogConfirmation) {
            clearAllModels();
            $scope.deleteModel('warningMessage', 'hasNoResults', 'isError');
        }
    };

    $scope.findClasses = function(isValidForm) {
        if(isValidForm) {
            $scope.isDataLoading = true;
            $scope.hasNoResults = false;
            $scope.isError = false;
            $scope.parametersMessage = generateMessageForAllModels();

            var setRowCollectionFromData = function(data) {
                $scope.rowCollection = [];
                $scope.numberOfRows = 0;
                data.forEach(function(aRow) {
                    $scope.numberOfRows += aRow.numberOfRows;
                    $scope.rowCollection = $scope.rowCollection.concat(aRow.result);
                });
            };

            var onError = function(err) {
                console.log('Unable to get the data given error: ' + err);
                $scope.isError = true;
            };

            var finallyDo = function() {
                $scope.isDataLoading = false;

                if($scope.numberOfRows == 0 && !$scope.isError) {
                    $scope.hasNoResults = true;
                    $scope.warningMessage = "There are no classes found with the categories you have selected. Please try again.";
                }
                else if(!$scope.isError) {
                    console.log($scope.rowCollection);
                    $scope.showResults = true;
                }
            };

            getAllData()
                .then(setRowCollectionFromData)
                .catch(onError)
                .finally(finallyDo);
        }
        else {
            alert("Please select a class term.");
        }
    };

    var getAllData = function() {
        var apiURLs = getAllAPIUrls();
        var promises = [];

        _.each(apiURLs, function(apiURL) {
            promises.push($rootScope.httpService.getData(apiURL));
        });

        return $q.all(promises);
    };

    var generateBaseURL = function() {
        var baseURLWithoutTerm = $scope.apiUrl + "/classes/term=";
        baseURLWithoutTerm += $scope.$eval('termModel')['term'];
        baseURLWithoutTerm += "?";
        return baseURLWithoutTerm;
    };

    var generateAllParameters = function() {
        var allParameters = [];
        $scope.allJSONAndScopeNames.forEach(function(aScopeVariable) {
            if(aScopeVariable.modelName != 'termModel') {
                var modelValue = $scope.$eval(aScopeVariable.modelName);
                if (modelValue != undefined) {
                    if (isNotArray(modelValue)) {
                        modelValue = [modelValue];
                    }

                    var currentParameters = [];
                    modelValue.forEach(function (aModel) {
                        if (aModel["isOrNot"] != undefined) {
                            currentParameters.push(aModel[aScopeVariable.apiParameterValueFromModel].split(" ").join("-") +
                                "=" + (aModel["isOrNot"] == "Is"));
                        }
                        else {
                            currentParameters.push(aScopeVariable.apiParameterInEndpoint + "=" + aModel[aScopeVariable.apiParameterValueFromModel]);
                        }
                    });
                    allParameters.push(currentParameters);
                }
            }
        });
        return allParameters;
    };

    var getAllAPIUrls = function() {
        var baseURL = generateBaseURL();
        var allParameters = generateAllParameters();
        var allAPIUrls = allParameters
            .reduce($rootScope.cartesianProductService.productAdd, [""]);

        return $rootScope.apiURLService.appendParametersAndReturnAPIUrls(allAPIUrls, baseURL);
    };

    var generateMessageForAllModels = function() {
        var message = "";

        $scope.allJSONAndScopeNames.forEach(function(aScopeVariable) {
            if($scope.$eval(aScopeVariable.modelName) != undefined) {
                var modelValue = $scope.$eval(aScopeVariable.modelName);
                var allDisplayParameters = aScopeVariable.displayParameters.split(", ");
                var allMessagesForModel = getAllMessagesForModelAndParameters(modelValue, allDisplayParameters);

                message += "" + aScopeVariable.uiParameter + ": ";
                message += allMessagesForModel.join(", ");
                message += "
";
            }
        });

        return message;
    };

    var isNotArray = function(models) {
        return $rootScope.types.get(models) !== $rootScope.types.array;
    };

    var getAllMessagesForModelAndParameters = function(models, parameters) {
        if(isNotArray(models)) {
            models = [models];
        }

        var allMessages = [];
        models.forEach(function(model) {
            var aMessageForModel = "";
            parameters.forEach(function(parameter) {
                aMessageForModel = aMessageForModel + model[parameter] + " ";
            });
            allMessages.push(aMessageForModel.trim());
        });
        return allMessages;
    };

    $scope.goBack = function() {
        console.log('Going back to offered class search page.');
        $scope.showResults = false;
    };

    $scope.printDates = function(startDate, endDate) {
        return startDate.replace("-", "/") + " to " + endDate.replace("-", "/");
    };

    $scope.selectTestModels = function() {
        clearAllModels();
        $scope.termModel = {"term": 2000, "year": 2016, "semester": "Fall"};
        $scope.formatModel = [{"format": "Hybrid", "isOrNot": "Is"}, {"format": "Face to Face", "isOrNot": "Not"}];
        $scope.statusModel = {"status": "Closed"};
        $scope.sessionModel = [{"session": 4, "sessionTitle": "Session 4"}, {
            "session": 2,
            "sessionTitle": "Session 2"
        }];
        $scope.subjectModel = [{"subject": "AFSC", "subjectFullName": "Air Force Science"}, {
            "subject": "ARAB",
            "subjectFullName": "Arabic"
        }];
        $scope.buildingModel = [{"buildingID": 517, "building": "A", "buildingName": "Cullen Performance Hall"}];
        $scope.locationModel = [{"location": "UH-Sugar Land"}, {"location": "UH-San Antonio-Conrad Hilton"}, {"location": "UH"}];
        $scope.componentModel = [{"component": "LEC", "componentName": "Lecture"}];
        $scope.creditHourModel = [{"credit-hours": 4}];
        $scope.weekendUModel = {"weekendU": "No"};
        $scope.coreCategoriesModel = [{"categoryNumber": 2, "categoryName": "Mathematics"}];
        $scope.isCoreModel = {"is-core": "No"};
        $scope.syllabusModel = {"syllabus": "No"};
        $scope.classDaysModel = [{"day": "Monday", "isOrNot": "Is"}, {
            "day": "Sunday",
            "isOrNot": "Is"
        }, {"day": "Tuesday", "isOrNot": "Not"}];
        $scope.courseNumberModel = {"courseNumber": 2410};
    };

    $scope.selectTestModelsTwo = function() {
        clearAllModels();
        $scope.termModel = {"term": 2000, "year": 2016, "semester": "Fall"};
        $scope.weekendUModel = {"weekendU": "Yes"};

    };

    $scope.selectTestModelsThree = function() {
        clearAllModels();
        $scope.termModel = {"term": 2000, "year": 2016, "semester": "Fall"};
        $scope.isCoreModel = {"is-core": "Yes"};
        $scope.formatModel = [{"format": "Online", "isOrNot": "Is"}];
    };

    $scope.selectTestModelsOneClassResult = function() {
        clearAllModels();
        $scope.termModel = {"term": 2000, "year": 2016, "semester": "Fall"};
        $scope.formatModel = [{"format": "Online", "isOrNot": "Is"}];
        $scope.sessionModel = [{"session": 6, "sessionTitle": "Session 6"}];
        $scope.subjectModel = [{"subject": "SOC", "subjectFullName": "Sociology"}];

    };

    var clearAllModels = function() {
        $scope.allJSONAndScopeNames.forEach(function(e) {
            $scope.deleteModel(e.modelName);
        });
    };

    $scope.getSyllabus = function(syllabus) {
        if(syllabus == 'Unavailable') {
            return "Syllabus Not Available.";
        }
        else {
            return "<button type='button' class='btn btn-primary'>Syllabus</button>";
        }
    };

    $scope.openSyllabusInNewWindow = function(syllabusLink) {
        if(syllabusLink != 'Unavailable') {
            $window.open(syllabusLink, '_blank');
        }
    };

    $scope.getClassDays = function(classDays) {
        var classDaysString = "";

        var allClassDays = [
                {
                    "classDay": "monday",
                    "classAbbreviation": "Mo"
                },
                {
                    "classDay": "tuesday",
                    "classAbbreviation": "Tu"
                },
                {
                    "classDay": "wednesday",
                    "classAbbreviation": "We"
                },
                {
                    "classDay": "thursday",
                    "classAbbreviation": "Th"
                },
                {
                    "classDay": "friday",
                    "classAbbreviation": "Fr"
                },
                {
                    "classDay": "saturday",
                    "classAbbreviation": "Sa"
                },
                {
                    "classDay": "sunday",
                    "classAbbreviation": "Su"
                }
            ];

        allClassDays.forEach(function(e) {
            // console.log(classDays);
            // console.log(classDays["classDay"]);
            // console.log(classDays.classDay);
            // console.log(e);
            // if(classDays[e]) {
            //     console.log("falls on class day");
            // }
            // else {
            //     console.log("erfghiu");
            // }
        });

        if(classDays.monday) {
            classDaysString += "Mo";
        }

        return classDaysString;
    }
}]);
<commit_msg>Implemented getClassDays.<commit_after>'use strict';

angular.module('classBrowserUHApp.offeredClass', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/offeredClass', {
        templateUrl: 'views/offeredClass/offeredClass.html',
        controller: 'OfferedClassCtrl'
    });
}])
.controller('OfferedClassCtrl', ['$scope', '$http', '$q', '$rootScope', '$parse', '$window', function ($scope, $http, $q, $rootScope, $parse, $window) {
    var setScopeVariableFromJSON = function(filePath, scopeVariable) {
        $rootScope.httpService.getData(filePath).then(function(result) {
            $parse(scopeVariable).assign($scope, result);
        });
    };

    var initializeAllJSONAndScopeNames = function(name) {
        $rootScope.httpService.getData('resources/allScopeVariables.json').then(function(result) {
            $scope.allJSONAndScopeNames = result[name];
            $scope.allJSONAndScopeNames.forEach(function(e) {
                setScopeVariableFromJSON(e.path, e.scopeName);
            });
        });
    };

    initializeAllJSONAndScopeNames("offeredClass");

    $scope.validValues = ['A','1','2', '3', '4', '5', '6', '7', '8', '9', '0'];

    $scope.deleteModel = function() {
        [].slice.call(arguments).forEach(function(arg) {
            delete $scope[arg];
        });
    };

    $scope.clearForms = function() {
        var clearFormDialogConfirmation = $window.confirm('Are you sure you want to clear the entire form?');

        if (clearFormDialogConfirmation) {
            clearAllModels();
            $scope.deleteModel('warningMessage', 'hasNoResults', 'isError');
        }
    };

    $scope.findClasses = function(isValidForm) {
        if(isValidForm) {
            $scope.isDataLoading = true;
            $scope.hasNoResults = false;
            $scope.isError = false;
            $scope.parametersMessage = generateMessageForAllModels();

            var setRowCollectionFromData = function(data) {
                $scope.rowCollection = [];
                $scope.numberOfRows = 0;
                data.forEach(function(aRow) {
                    $scope.numberOfRows += aRow.numberOfRows;
                    $scope.rowCollection = $scope.rowCollection.concat(aRow.result);
                });
            };

            var onError = function(err) {
                console.log('Unable to get the data given error: ' + err);
                $scope.isError = true;
            };

            var finallyDo = function() {
                $scope.isDataLoading = false;

                if($scope.numberOfRows == 0 && !$scope.isError) {
                    $scope.hasNoResults = true;
                    $scope.warningMessage = "There are no classes found with the categories you have selected. Please try again.";
                }
                else if(!$scope.isError) {
                    $scope.showResults = true;
                }
            };

            getAllData()
                .then(setRowCollectionFromData)
                .catch(onError)
                .finally(finallyDo);
        }
        else {
            alert("Please select a class term.");
        }
    };

    var getAllData = function() {
        var apiURLs = getAllAPIUrls();
        var promises = [];

        _.each(apiURLs, function(apiURL) {
            promises.push($rootScope.httpService.getData(apiURL));
        });

        return $q.all(promises);
    };

    var generateBaseURL = function() {
        var baseURLWithoutTerm = $scope.apiUrl + "/classes/term=";
        baseURLWithoutTerm += $scope.$eval('termModel')['term'];
        baseURLWithoutTerm += "?";
        return baseURLWithoutTerm;
    };

    var generateAllParameters = function() {
        var allParameters = [];
        $scope.allJSONAndScopeNames.forEach(function(aScopeVariable) {
            if(aScopeVariable.modelName != 'termModel') {
                var modelValue = $scope.$eval(aScopeVariable.modelName);
                if (modelValue != undefined) {
                    if (isNotArray(modelValue)) {
                        modelValue = [modelValue];
                    }

                    var currentParameters = [];
                    modelValue.forEach(function (aModel) {
                        if (aModel["isOrNot"] != undefined) {
                            currentParameters.push(aModel[aScopeVariable.apiParameterValueFromModel].split(" ").join("-") +
                                "=" + (aModel["isOrNot"] == "Is"));
                        }
                        else {
                            currentParameters.push(aScopeVariable.apiParameterInEndpoint + "=" + aModel[aScopeVariable.apiParameterValueFromModel]);
                        }
                    });
                    allParameters.push(currentParameters);
                }
            }
        });
        return allParameters;
    };

    var getAllAPIUrls = function() {
        var baseURL = generateBaseURL();
        var allParameters = generateAllParameters();
        var allAPIUrls = allParameters
            .reduce($rootScope.cartesianProductService.productAdd, [""]);

        return $rootScope.apiURLService.appendParametersAndReturnAPIUrls(allAPIUrls, baseURL);
    };

    var generateMessageForAllModels = function() {
        var message = "";

        $scope.allJSONAndScopeNames.forEach(function(aScopeVariable) {
            if($scope.$eval(aScopeVariable.modelName) != undefined) {
                var modelValue = $scope.$eval(aScopeVariable.modelName);
                var allDisplayParameters = aScopeVariable.displayParameters.split(", ");
                var allMessagesForModel = getAllMessagesForModelAndParameters(modelValue, allDisplayParameters);

                message += "" + aScopeVariable.uiParameter + ": ";
                message += allMessagesForModel.join(", ");
                message += "
";
            }
        });

        return message;
    };

    var isNotArray = function(models) {
        return $rootScope.types.get(models) !== $rootScope.types.array;
    };

    var getAllMessagesForModelAndParameters = function(models, parameters) {
        if(isNotArray(models)) {
            models = [models];
        }

        var allMessages = [];
        models.forEach(function(model) {
            var aMessageForModel = "";
            parameters.forEach(function(parameter) {
                aMessageForModel = aMessageForModel + model[parameter] + " ";
            });
            allMessages.push(aMessageForModel.trim());
        });
        return allMessages;
    };

    $scope.goBack = function() {
        console.log('Going back to offered class search page.');
        $scope.showResults = false;
    };

    $scope.printDates = function(startDate, endDate) {
        return startDate.replace("-", "/") + " to " + endDate.replace("-", "/");
    };

    $scope.selectTestModels = function() {
        clearAllModels();
        $scope.termModel = {"term": 2000, "year": 2016, "semester": "Fall"};
        $scope.formatModel = [{"format": "Hybrid", "isOrNot": "Is"}, {"format": "Face to Face", "isOrNot": "Not"}];
        $scope.statusModel = {"status": "Closed"};
        $scope.sessionModel = [{"session": 4, "sessionTitle": "Session 4"}, {
            "session": 2,
            "sessionTitle": "Session 2"
        }];
        $scope.subjectModel = [{"subject": "AFSC", "subjectFullName": "Air Force Science"}, {
            "subject": "ARAB",
            "subjectFullName": "Arabic"
        }];
        $scope.buildingModel = [{"buildingID": 517, "building": "A", "buildingName": "Cullen Performance Hall"}];
        $scope.locationModel = [{"location": "UH-Sugar Land"}, {"location": "UH-San Antonio-Conrad Hilton"}, {"location": "UH"}];
        $scope.componentModel = [{"component": "LEC", "componentName": "Lecture"}];
        $scope.creditHourModel = [{"credit-hours": 4}];
        $scope.weekendUModel = {"weekendU": "No"};
        $scope.coreCategoriesModel = [{"categoryNumber": 2, "categoryName": "Mathematics"}];
        $scope.isCoreModel = {"is-core": "No"};
        $scope.syllabusModel = {"syllabus": "No"};
        $scope.classDaysModel = [{"day": "Monday", "isOrNot": "Is"}, {
            "day": "Sunday",
            "isOrNot": "Is"
        }, {"day": "Tuesday", "isOrNot": "Not"}];
        $scope.courseNumberModel = {"courseNumber": 2410};
    };

    $scope.selectTestModelsTwo = function() {
        clearAllModels();
        $scope.termModel = {"term": 2000, "year": 2016, "semester": "Fall"};
        $scope.weekendUModel = {"weekendU": "Yes"};

    };

    $scope.selectTestModelsThree = function() {
        clearAllModels();
        $scope.termModel = {"term": 2000, "year": 2016, "semester": "Fall"};
        $scope.isCoreModel = {"is-core": "Yes"};
        $scope.formatModel = [{"format": "Online", "isOrNot": "Is"}];
    };

    $scope.selectTestModelsOneClassResult = function() {
        clearAllModels();
        $scope.termModel = {"term": 2000, "year": 2016, "semester": "Fall"};
        $scope.formatModel = [{"format": "Online", "isOrNot": "Is"}];
        $scope.sessionModel = [{"session": 6, "sessionTitle": "Session 6"}];
        $scope.subjectModel = [{"subject": "SOC", "subjectFullName": "Sociology"}];

    };

    var clearAllModels = function() {
        $scope.allJSONAndScopeNames.forEach(function(e) {
            $scope.deleteModel(e.modelName);
        });
    };

    $scope.getSyllabus = function(syllabus) {
        if(syllabus == 'Unavailable') {
            return "Syllabus Not Available.";
        }
        else {
            return "<button type='button' class='btn btn-primary'>Syllabus</button>";
        }
    };

    $scope.openSyllabusInNewWindow = function(syllabusLink) {
        if(syllabusLink != 'Unavailable') {
            $window.open(syllabusLink, '_blank');
        }
    };

    $scope.getClassDays = function(classDays) {
        var classDaysString = "";
        var allClassDays = $scope.classDays.dayAbbreviations;

        allClassDays.forEach(function(day) {
            if(classDays[day.classDay]) {
                classDaysString += day.classDayAbbreviation;
            }
        });

        return classDaysString != "" ? classDaysString : "No Class Days";
    }
}]);
<|endoftext|>


<commit_before>'use strict';
var queries = angular.module('cliffhanger.queries', ['ngRoute', 'ngSanitize', 'ngCsv']);
queries.controller('QueryWizardCtrl', function ($scope, $uibModalInstance, $log, datasets, queryService) {
    $scope.query = {}; //container for query
    $scope.alerts = [];
    $scope.tableResult = {};
    $scope.selected = {};
    $scope.step = 1; //which step in the modal is on
    $scope.maxSteps = 5; //number of steps in modal
    $scope.datasets = datasets;
    $scope.tags = []; //TODO load based upon datasets
    $scope.addJoinColumn = false; //whether to include joined column in select
    $scope.selectedDatasets = []; //datasets selected to be joined
    $scope.selectedTags = []; //selected join tags
    $scope.selectedColumns = []; //select columns for query
    //for save query dropdown
    $scope.isCollapsed = true;
    $scope.download = false;
    $scope.loadingPreview = false;
    //method responsible for handling changes due to checkboxes
    //d -> item selected/deselected
    //selections -> array to add/remove item
    $scope.change = function (d, selections) {
            if (d.selected) {
                selections.push(d);
            } else {
                for (var i = 0; i < selections.length; i++) {
                    $log.debug(selections[i]);
                    if (selections[i].name == d.name) {
                        selections.splice(i, 1);
                    }
                }
            }
            $log.debug(selections);
        }
        //method responsible for handling changes due to checkboxes
        //d -> item selected/deselected
        //selections -> array to add/remove item
    $scope.changeColumns = function (column, selections, dataset) {
            if (column.selected) {
                column.db_table_name = dataset.db_table_name;
                selections.push(column);
            } else {
                for (var i = 0; i < selections.length; i++) {
                    $log.debug(selections[i]);
                    if (selections[i].name == column.name) {
                        selections.splice(i, 1);
                    }
                }
            }
            $log.debug(selections);
        }
        //load the joinable tags only in the selected datasets
    $scope.loadTags = function () {
            for (var i = 0; i < $scope.selectedDatasets[0].tags.length; i++) {
                var tagA = $scope.selectedDatasets[0].tags[i];
                for (var j = 0; j < $scope.selectedDatasets[1].tags.length; j++) {
                    var tagB = $scope.selectedDatasets[1].tags[j];
                    //if tags match, aren't EMPTY and are not a duplicate
                    if (tagA.name == tagB.name && tagA.name != '<EMPTY>' && $scope.tags.indexOf(tagA) == -1) {
                        $scope.tags.push(tagA);
                        break;
                    }
                }
            }
            $log.debug($scope.tags);
        }
        //advance the modal to the next step
    $scope.next = function () {
        $scope.step++;
        if ($scope.step == 2) {
            $scope.loadTags();
        } else if ($scope.step == 4) $scope.buildQuery();
        else if ($scope.step == 5) {
            $scope.runQuery($scope.query);
        }
    };
    //go back a step in the modal
    $scope.previous = function () {
        $scope.step--;
        if ($scope.step < $scope.maxSteps) {
            $scope.progressType = null;
            $scope.tableResult = null;
        }
    };

    $scope.selectAllFromDataset = function (dataset) {
        if ($scope.selected[dataset.name]) {
            for (var i = 0; i < dataset.attributes.length; i++) {
                var a = dataset.attributes[i];
                a.selected = true;
            }
        } else {
            for (var i = 0; i < dataset.attributes.length; i++) {
                var a = dataset.attributes[i];
                a.selected = false;
            }
        }
    }

    //dismiss the modal
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
    //add where and limit clause to SQL query string
    $scope.addToQuery = function () {
        if (($scope.statement.where == null && $scope.statement.limit == null) || ($scope.statement.where == "" && $scope.statement.limit == "") || ($scope.statement.where == null && $scope.statement.limit == "") || ($scope.statement.where == "" && $scope.statement.limit == null)) {
            $scope.query = $scope.query.replace(";", "");
            $scope.statement.text = ";";
        }
        //adding both WHERE and LIMIT statement
        else if ($scope.statement.where != null && $scope.statement.limit != null) {
            $scope.query = $scope.query.replace(";", "");
            $scope.statement.text = "\nWHERE " + $scope.statement.where + "\n" + "LIMIT " + $scope.statement.limit + ";";
        }
        //adding WHERE and not LIMIT
        else if (($scope.statement.where != null && $scope.statement.limit == null) || ($scope.statement.where != null && $scope.statement.limit == "")) {
            $scope.query = $scope.query.replace(";", "");
            $scope.statement.text = "\nWHERE " + $scope.statement.where + ";";
        }
        //adding LIMIT and not WHERE
        else if (($scope.statement.where == null && $scope.statement.limit != null) || ($scope.statement.where == "" && $scope.statement.limit != null)) {
            $scope.query = $scope.query.replace(";", "");
            $scope.statement.text = "\nLIMIT " + $scope.statement.limit + ";";
        }
        $log.debug($scope.statement);
    };
    //build a new query given the user's choices
    $scope.buildQuery = function () {
        //query input packaged
        var queryInput = {
            datasets: $scope.selectedDatasets,
            joinTag: $scope.selectedTags,
            addJoinColumn: $scope.addJoinColumn,
            columns: $scope.selectedColumns
        }
        queryService.buildQuery(queryInput).then(function (response) {
            //success callback
            if (response.status == 'Success') {
                $scope.query = response.data;
                $scope.progressType = 'success';
                //failure callback
            } else {
                $scope.progressType = 'danger';
                $scope.buildQueryError = true;
                $log.error(response.data);
            }
        });
    };
    //complete the modal
    $scope.save = function () {
        if ($scope.statement.text != null) {
            $scope.newQuery.sqlString = $scope.query + $scope.statement.text;
        } else {
            $scope.newQuery.sqlString = $scope.query;
        }
        queryService.saveQuery($scope.newQuery).then(function (data) {
            if (data.status == 'Success') {
                $log.debug(data);
            } else {
                $scope.alerts.push({
                    msg: data,
                    type: 'danger'
                });
            }
        }, function (data) {
            $scope.alerts.push({
                msg: 'Failed to create Query',
                type: 'danger'
            });
        })
    };
    $scope.runQuery = function () {
        $scope.loadingPreview = true;
        var query = $scope.query;
        queryService.runQuery(query).then(function (response) { //success callback
                $scope.loadingPreview = false;
                $scope.tableResult = response;
                $scope.progressType = 'success';
            }, //failure to connect
            function (data) {
                $scope.loadingPreview = false;
                $scope.progressType = 'danger';
                $scope.runQueryError = true;
                $log.error('Failed to connect to server');
            });
    };
});
<commit_msg>fixed select all bugs<commit_after>'use strict';
var queries = angular.module('cliffhanger.queries', ['ngRoute', 'ngSanitize', 'ngCsv']);
queries.controller('QueryWizardCtrl', function ($scope, $uibModalInstance, $log, datasets, queryService) {
    $scope.query = {}; //container for query
    $scope.alerts = [];
    $scope.tableResult = {};
    $scope.selected = {};
    $scope.step = 1; //which step in the modal is on
    $scope.maxSteps = 5; //number of steps in modal
    $scope.datasets = datasets;
    $scope.tags = []; //TODO load based upon datasets
    $scope.addJoinColumn = false; //whether to include joined column in select
    $scope.selectedDatasets = []; //datasets selected to be joined
    $scope.selectedTags = []; //selected join tags
    $scope.selectedColumns = []; //select columns for query
    //for save query dropdown
    $scope.isCollapsed = true;
    $scope.download = false;
    $scope.loadingPreview = false;
    //method responsible for handling changes due to checkboxes
    //d -> item selected/deselected
    //selections -> array to add/remove item
    $scope.change = function (d, selections) {
            if (d.selected) {
                selections.push(d);
            } else {
                for (var i = 0; i < selections.length; i++) {
                    $log.debug(selections[i]);
                    if (selections[i].name == d.name) {
                        selections.splice(i, 1);
                    }
                }
            }
            $log.debug(selections);
        }
        //method responsible for handling changes due to checkboxes
        //d -> item selected/deselected
        //selections -> array to add/remove item
    $scope.changeColumns = function (column, selections, dataset) {
            if (column.selected) {
                column.db_table_name = dataset.db_table_name;
                selections.push(column);
            } else {
                for (var i = 0; i < selections.length; i++) {
                    $log.debug(selections[i]);
                    if (selections[i].name == column.name) {
                        selections.splice(i, 1);
                    }
                }
            }
            $log.debug(selections);
        }
        //load the joinable tags only in the selected datasets
    $scope.loadTags = function () {
            for (var i = 0; i < $scope.selectedDatasets[0].tags.length; i++) {
                var tagA = $scope.selectedDatasets[0].tags[i];
                for (var j = 0; j < $scope.selectedDatasets[1].tags.length; j++) {
                    var tagB = $scope.selectedDatasets[1].tags[j];
                    //if tags match, aren't EMPTY and are not a duplicate
                    if (tagA.name == tagB.name && tagA.name != '<EMPTY>' && $scope.tags.indexOf(tagA) == -1) {
                        $scope.tags.push(tagA);
                        break;
                    }
                }
            }
            $log.debug($scope.tags);
        }
        //advance the modal to the next step
    $scope.next = function () {
        $scope.step++;
        if ($scope.step == 2) {
            $scope.loadTags();
        } else if ($scope.step == 4) $scope.buildQuery();
        else if ($scope.step == 5) {
            $scope.runQuery($scope.query);
        }
    };
    //go back a step in the modal
    $scope.previous = function () {
        $scope.step--;
        if ($scope.step < $scope.maxSteps) {
            $scope.progressType = null;
            $scope.tableResult = null;
        }
    };

    $scope.selectAllFromDataset = function (dataset) {

        for (var i = 0; i < dataset.attributes.length; i++) {
            var a = dataset.attributes[i];
            if ($scope.selected[dataset.name]) {
                if (a.tag.name != $scope.selectedTags[0].name) {
                    a.db_table_name = dataset.db_table_name;
                    a.selected = true;
                    $scope.selectedColumns.push(a);
                }
            } else {
                a.selected = false;
                for (var j = 0; j < $scope.selectedColumns.length; j++) {
                    if ($scope.selectedColumns[j].name == a.name) {
                        $scope.selectedColumns.splice(j, 1);
                    }
                }
            }
        }
    }

    //dismiss the modal
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
    //add where and limit clause to SQL query string
    $scope.addToQuery = function () {
        if (($scope.statement.where == null && $scope.statement.limit == null) || ($scope.statement.where == "" && $scope.statement.limit == "") || ($scope.statement.where == null && $scope.statement.limit == "") || ($scope.statement.where == "" && $scope.statement.limit == null)) {
            $scope.query = $scope.query.replace(";", "");
            $scope.statement.text = ";";
        }
        //adding both WHERE and LIMIT statement
        else if ($scope.statement.where != null && $scope.statement.limit != null) {
            $scope.query = $scope.query.replace(";", "");
            $scope.statement.text = "\nWHERE " + $scope.statement.where + "\n" + "LIMIT " + $scope.statement.limit + ";";
        }
        //adding WHERE and not LIMIT
        else if (($scope.statement.where != null && $scope.statement.limit == null) || ($scope.statement.where != null && $scope.statement.limit == "")) {
            $scope.query = $scope.query.replace(";", "");
            $scope.statement.text = "\nWHERE " + $scope.statement.where + ";";
        }
        //adding LIMIT and not WHERE
        else if (($scope.statement.where == null && $scope.statement.limit != null) || ($scope.statement.where == "" && $scope.statement.limit != null)) {
            $scope.query = $scope.query.replace(";", "");
            $scope.statement.text = "\nLIMIT " + $scope.statement.limit + ";";
        }
        $log.debug($scope.statement);
    };
    //build a new query given the user's choices
    $scope.buildQuery = function () {
        //query input packaged
        var queryInput = {
            datasets: $scope.selectedDatasets,
            joinTag: $scope.selectedTags,
            addJoinColumn: $scope.addJoinColumn,
            columns: $scope.selectedColumns
        }
        queryService.buildQuery(queryInput).then(function (response) {
            //success callback
            if (response.status == 'Success') {
                $scope.query = response.data;
                $scope.progressType = 'success';
                //failure callback
            } else {
                $scope.progressType = 'danger';
                $scope.buildQueryError = true;
                $log.error(response.data);
            }
        });
    };
    //complete the modal
    $scope.save = function () {
        if ($scope.statement.text != null) {
            $scope.newQuery.sqlString = $scope.query + $scope.statement.text;
        } else {
            $scope.newQuery.sqlString = $scope.query;
        }
        queryService.saveQuery($scope.newQuery).then(function (data) {
            if (data.status == 'Success') {
                $log.debug(data);
            } else {
                $scope.alerts.push({
                    msg: data,
                    type: 'danger'
                });
            }
        }, function (data) {
            $scope.alerts.push({
                msg: 'Failed to create Query',
                type: 'danger'
            });
        })
    };
    $scope.runQuery = function () {
        $scope.loadingPreview = true;
        var query = $scope.query;
        queryService.runQuery(query).then(function (response) { //success callback
                $scope.loadingPreview = false;
                $scope.tableResult = response;
                $scope.progressType = 'success';
            }, //failure to connect
            function (data) {
                $scope.loadingPreview = false;
                $scope.progressType = 'danger';
                $scope.runQueryError = true;
                $log.error('Failed to connect to server');
            });
    };
});
<|endoftext|>