<commit_before>// Copyright (c) 2015 Greenheart Games Pty. Ltd. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

// The source code can be found in https://github.com/greenheartgames/greenworks
var fs = require('fs');

var greenworks;

if (process.platform == 'darwin') {
  if (process.arch == 'x64')
    greenworks = require('./lib/greenworks-osx64');
} else if (process.platform == 'win32') {
  if (process.arch == 'x64')
    greenworks = require('./lib/greenworks-win64');
  else if (process.arch == 'ia32')
    greenworks = require('./lib/greenworks-win32');
} else if (process.platform == 'linux') {
  if (process.arch == 'x64')
    greenworks = require('./lib/greenworks-linux64');
  else if (process.arch == 'ia32')
    greenworks = require('./lib/greenworks-linux32');
}

function error_process(err, error_callback) {
  if (err && error_callback)
    error_callback(err);
}

greenworks.ugcGetItems = function(options, ugc_matching_type, ugc_query_type,
    success_callback, error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = ugc_query_type;
    ugc_query_type = ugc_matching_type;
    ugc_matching_type = options;
    options = {
      'app_id': greenworks.getAppId(),
      'page_num': 1
    }
  }
  greenworks._ugcGetItems(options, ugc_matching_type, ugc_query_type,
      success_callback, error_callback);
}

greenworks.ugcGetUserItems = function(options, ugc_matching_type,
    ugc_list_sort_order, ugc_list, success_callback, error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = ugc_list;
    ugc_list = ugc_list_sort_order;
    ugc_list_sort_order = ugc_matching_type;
    ugc_matching_type = options;
    options = {
      'app_id': greenworks.getAppId(),
      'page_num': 1
    }
  }
  greenworks._ugcGetUserItems(options, ugc_matching_type, ugc_list_sort_order,
      ugc_list, success_callback, error_callback);
}

greenworks.ugcSynchronizeItems = function (options, sync_dir, success_callback,
    error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = sync_dir;
    sync_dir = options;
    options = {
      'app_id': greenworks.getAppId(),
      'page_num': 1
    }
  }
  greenworks._ugcSynchronizeItems(options, sync_dir, success_callback,
      error_callback);
}

greenworks.publishWorkshopFile = function(options, file_path, image_path, title,
    description, success_callback, error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = description;
    description = title;
    title = image_path;
    image_path = file_path;
    file_path = options;
    options = {
      'app_id': greenworks.getAppId(),
      'tags': []
    }
  }
  greenworks._publishWorkshopFile(options, file_path, image_path, title,
      description, success_callback, error_callback);
}

greenworks.updatePublishedWorkshopFile = function(options,
    published_file_handle, file_path, image_path, title, description,
    success_callback, error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = description;
    description = title;
    title = image_path;
    image_path = file_path;
    file_path = published_file_handle;
    published_file_handle = options;
    options = {
      'tags': [] // No tags are set
    }
  }
  greenworks._updatePublishedWorkshopFile(options, published_file_handle,
     file_path, image_path, title, description, success_callback,
     error_callback);
}

// An utility function for publish related APIs.
// It processes remains steps after saving files to Steam Cloud.
function file_share_process(file_name, image_name, next_process_func,
    error_callback, progress_callback) {
  if (progress_callback)
    progress_callback("Completed on saving files on Steam Cloud.");
  greenworks.fileShare(file_name, function() {
    greenworks.fileShare(image_name, function() {
      next_process_func();
    }, function(err) { error_process(err, error_callback); });
  }, function(err) { error_process(err, error_callback); });
}

// Publishing user generated content(ugc) to Steam contains following steps:
// 1. Save file and image to Steam Cloud.
// 2. Share the file and image.
// 3. publish the file to workshop.
greenworks.ugcPublish = function(file_name, title, description, image_name,
    success_callback, error_callback, progress_callback) {
  var publish_file_process = function() {
    if (progress_callback)
      progress_callback("Completed on sharing files.");
    greenworks.publishWorkshopFile(file_name, image_name, title, description,
        function(publish_file_id) { success_callback(publish_file_id); },
        function(err) { error_process(err, error_callback); });
  };
  greenworks.saveFilesToCloud([file_name, image_name], function() {
    file_share_process(file_name, image_name, publish_file_process,
        error_callback, progress_callback);
  }, function(err) { error_process(err, error_callback); });
}

// Update publish ugc steps:
// 1. Save new file and image to Steam Cloud.
// 2. Share file and images.
// 3. Update published file.
greenworks.ugcPublishUpdate = function(published_file_id, file_name, title,
    description, image_name, success_callback, error_callback,
    progress_callback) {
  var update_published_file_process = function() {
    if (progress_callback)
      progress_callback("Completed on sharing files.");
    greenworks.updatePublishedWorkshopFile(published_file_id,
        file_name, image_name, title, description,
        function() { success_callback(); },
        function(err) { error_process(err, error_callback); });
  };

  greenworks.saveFilesToCloud([file_name, image_name], function() {
    file_share_process(file_name, image_name, update_published_file_process,
        error_callback, progress_callback);
  }, function(err) { error_process(err, error_callback); });
}

// Greenworks Utils APIs implmentation.
greenworks.Utils.move = function(source_dir, target_dir, success_callback,
    error_callback) {
  fs.rename(source_dir, target_dir, function(err) {
    if (err) {
      if (error_callback) error_callback(err);
      return;
    }
    if (success_callback)
      success_callback();
  });
}

greenworks.init = function() {
  if (this.initAPI()) return true;
  if (!this.isSteamRunning())
    throw new Error("Steam initialization failed. Steam is not running.");
  var appId;
  try {
    appId = fs.readFileSync('steam_appid.txt', 'utf8');
  } catch (e) {
    throw new Error("Steam initialization failed. Steam is running," +
                    "but steam_appid.txt is missing. Expected to find it in: " +
                    require('path').resolve('steam_appid.txt'));
  }
  if (!/^\d+ *\r?\n?$/.test(appId)) {
    throw new Error("Steam initialization failed. " +
                    "steam_appid.txt appears to be invalid; " +
                    "it should contain a numeric ID: " + appId);
  }
  throw new Error("Steam initialization failed, but Steam is running, " +
                  "and steam_appid.txt is present and valid." +
                  "Maybe that's not really YOUR app ID? " + appId.trim());
}

var EventEmitter = require('events').EventEmitter;
greenworks.__proto__ = EventEmitter.prototype;
EventEmitter.call(greenworks);

greenworks._steam_events.on = function () {
  greenworks.emit.apply(greenworks, arguments);
};

process.versions['greenworks'] = greenworks._version;

module.exports = greenworks;
<commit_msg>Update greenworks.js<commit_after>// Copyright (c) 2015 Greenheart Games Pty. Ltd. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

// The source code can be found in https://github.com/greenheartgames/greenworks
var fs = require('fs');

var greenworks;

if (process.platform == 'darwin') {
  if (process.arch == 'x64')
    greenworks = require(__dirname + '/lib/greenworks-osx64');
} else if (process.platform == 'win32') {
  if (process.arch == 'x64')
    greenworks = require(__dirname + '/lib/greenworks-win64');
  else if (process.arch == 'ia32')
    greenworks = require(__dirname + '/lib/greenworks-win32');
} else if (process.platform == 'linux') {
  if (process.arch == 'x64')
    greenworks = require(__dirname + '/lib/greenworks-linux64');
  else if (process.arch == 'ia32')
    greenworks = require(__dirname + '/lib/greenworks-linux32');
}

function error_process(err, error_callback) {
  if (err && error_callback)
    error_callback(err);
}

greenworks.ugcGetItems = function(options, ugc_matching_type, ugc_query_type,
    success_callback, error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = ugc_query_type;
    ugc_query_type = ugc_matching_type;
    ugc_matching_type = options;
    options = {
      'app_id': greenworks.getAppId(),
      'page_num': 1
    }
  }
  greenworks._ugcGetItems(options, ugc_matching_type, ugc_query_type,
      success_callback, error_callback);
}

greenworks.ugcGetUserItems = function(options, ugc_matching_type,
    ugc_list_sort_order, ugc_list, success_callback, error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = ugc_list;
    ugc_list = ugc_list_sort_order;
    ugc_list_sort_order = ugc_matching_type;
    ugc_matching_type = options;
    options = {
      'app_id': greenworks.getAppId(),
      'page_num': 1
    }
  }
  greenworks._ugcGetUserItems(options, ugc_matching_type, ugc_list_sort_order,
      ugc_list, success_callback, error_callback);
}

greenworks.ugcSynchronizeItems = function (options, sync_dir, success_callback,
    error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = sync_dir;
    sync_dir = options;
    options = {
      'app_id': greenworks.getAppId(),
      'page_num': 1
    }
  }
  greenworks._ugcSynchronizeItems(options, sync_dir, success_callback,
      error_callback);
}

greenworks.publishWorkshopFile = function(options, file_path, image_path, title,
    description, success_callback, error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = description;
    description = title;
    title = image_path;
    image_path = file_path;
    file_path = options;
    options = {
      'app_id': greenworks.getAppId(),
      'tags': []
    }
  }
  greenworks._publishWorkshopFile(options, file_path, image_path, title,
      description, success_callback, error_callback);
}

greenworks.updatePublishedWorkshopFile = function(options,
    published_file_handle, file_path, image_path, title, description,
    success_callback, error_callback) {
  if (typeof options !== 'object') {
    error_callback = success_callback;
    success_callback = description;
    description = title;
    title = image_path;
    image_path = file_path;
    file_path = published_file_handle;
    published_file_handle = options;
    options = {
      'tags': [] // No tags are set
    }
  }
  greenworks._updatePublishedWorkshopFile(options, published_file_handle,
     file_path, image_path, title, description, success_callback,
     error_callback);
}

// An utility function for publish related APIs.
// It processes remains steps after saving files to Steam Cloud.
function file_share_process(file_name, image_name, next_process_func,
    error_callback, progress_callback) {
  if (progress_callback)
    progress_callback("Completed on saving files on Steam Cloud.");
  greenworks.fileShare(file_name, function() {
    greenworks.fileShare(image_name, function() {
      next_process_func();
    }, function(err) { error_process(err, error_callback); });
  }, function(err) { error_process(err, error_callback); });
}

// Publishing user generated content(ugc) to Steam contains following steps:
// 1. Save file and image to Steam Cloud.
// 2. Share the file and image.
// 3. publish the file to workshop.
greenworks.ugcPublish = function(file_name, title, description, image_name,
    success_callback, error_callback, progress_callback) {
  var publish_file_process = function() {
    if (progress_callback)
      progress_callback("Completed on sharing files.");
    greenworks.publishWorkshopFile(file_name, image_name, title, description,
        function(publish_file_id) { success_callback(publish_file_id); },
        function(err) { error_process(err, error_callback); });
  };
  greenworks.saveFilesToCloud([file_name, image_name], function() {
    file_share_process(file_name, image_name, publish_file_process,
        error_callback, progress_callback);
  }, function(err) { error_process(err, error_callback); });
}

// Update publish ugc steps:
// 1. Save new file and image to Steam Cloud.
// 2. Share file and images.
// 3. Update published file.
greenworks.ugcPublishUpdate = function(published_file_id, file_name, title,
    description, image_name, success_callback, error_callback,
    progress_callback) {
  var update_published_file_process = function() {
    if (progress_callback)
      progress_callback("Completed on sharing files.");
    greenworks.updatePublishedWorkshopFile(published_file_id,
        file_name, image_name, title, description,
        function() { success_callback(); },
        function(err) { error_process(err, error_callback); });
  };

  greenworks.saveFilesToCloud([file_name, image_name], function() {
    file_share_process(file_name, image_name, update_published_file_process,
        error_callback, progress_callback);
  }, function(err) { error_process(err, error_callback); });
}

// Greenworks Utils APIs implmentation.
greenworks.Utils.move = function(source_dir, target_dir, success_callback,
    error_callback) {
  fs.rename(source_dir, target_dir, function(err) {
    if (err) {
      if (error_callback) error_callback(err);
      return;
    }
    if (success_callback)
      success_callback();
  });
}

greenworks.init = function() {
  if (this.initAPI()) return true;
  if (!this.isSteamRunning())
    throw new Error("Steam initialization failed. Steam is not running.");
  var appId;
  try {
    appId = fs.readFileSync('steam_appid.txt', 'utf8');
  } catch (e) {
    throw new Error("Steam initialization failed. Steam is running," +
                    "but steam_appid.txt is missing. Expected to find it in: " +
                    require('path').resolve('steam_appid.txt'));
  }
  if (!/^\d+ *\r?\n?$/.test(appId)) {
    throw new Error("Steam initialization failed. " +
                    "steam_appid.txt appears to be invalid; " +
                    "it should contain a numeric ID: " + appId);
  }
  throw new Error("Steam initialization failed, but Steam is running, " +
                  "and steam_appid.txt is present and valid." +
                  "Maybe that's not really YOUR app ID? " + appId.trim());
}

var EventEmitter = require('events').EventEmitter;
greenworks.__proto__ = EventEmitter.prototype;
EventEmitter.call(greenworks);

greenworks._steam_events.on = function () {
  greenworks.emit.apply(greenworks, arguments);
};

process.versions['greenworks'] = greenworks._version;

module.exports = greenworks;
<|endoftext|>


<commit_before>"use strict";

const
    IO_PATH = "../ArnaudBuchholz.github.io/",
    fs = require("fs"),
    copy = {
        publishVersionPlato: {},
        publishVersion: {},
        publishVersionDoc: {},
        publishTest: {},
        publishTestRequire: {},
        publishTestData: {},
        instrumentSourcesJson: {
            expand: true,
            cwd: "./src/",
            src: "**/*.json",
            dest: "./tmp/coverage/instrument/src/"
        }
    };

if (fs.existsSync(IO_PATH)) {
    Object.assign(copy, {
        publishVersionPlato: {
            expand: true,
            cwd: "./tmp/plato/",
            src: "**/*.*",
            dest: IO_PATH + "gpf/plato/"
        },
        publishVersion: {
            expand: true,
            cwd: "./build/",
            src: ["gpf.js", "gpf-debug.js", "tests.js"],
            dest: IO_PATH + "gpf/" + configuration.pkg.version + "/"
        },
        publishVersionDoc: {
            expand: true,
            cwd: "./tmp/doc/public",
            src: "**/*.*",
            dest: IO_PATH + "gpf/doc/"
        },
        publishTest: {
            expand: true,
            cwd: "./test/host/",
            src: ["test.html", "bdd.js"],
            dest: IO_PATH + "gpf/"
        },
        publishTestRequire: {
            expand: true,
            cwd: "./test/require/",
            src: "**/*.*",
            dest: IO_PATH + "gpf/test-resources/require"
        },
        publishTestData: {
            expand: true,
            cwd: "./test/data/",
            src: "**/*.*",
            dest: IO_PATH + "gpf/test-resources/data"
        }
    });
}

module.exports = copy;
<commit_msg>Simplify publish (#237)<commit_after>"use strict";

const PUBLISH_PATH = "tmp/ArnaudBuchholz.github.io/";

module.exports = {
    publishVersionPlato: {
        expand: true,
        cwd: "./tmp/plato/",
        src: "**/*.*",
        dest: PUBLISH_PATH + "gpf/plato/"
    },
    publishVersion: {
        expand: true,
        cwd: "./build/",
        src: ["gpf.js", "gpf-debug.js", "tests.js"],
        dest: PUBLISH_PATH + "gpf/" + configuration.pkg.version + "/"
    },
    publishVersionDoc: {
        expand: true,
        cwd: "./tmp/doc/public",
        src: "**/*.*",
        dest: PUBLISH_PATH + "gpf/doc/"
    },
    publishTest: {
        expand: true,
        cwd: "./test/host/",
        src: ["test.html", "bdd.js"],
        dest: PUBLISH_PATH + "gpf/"
    },
    publishTestRequire: {
        expand: true,
        cwd: "./test/require/",
        src: "**/*.*",
        dest: PUBLISH_PATH + "gpf/test-resources/require"
    },
    publishTestData: {
        expand: true,
        cwd: "./test/data/",
        src: "**/*.*",
        dest: PUBLISH_PATH + "gpf/test-resources/data"
    },
    instrumentSourcesJson: {
        expand: true,
        cwd: "./src/",
        src: "**/*.json",
        dest: "./tmp/coverage/instrument/src/"
    }
};
<|endoftext|>


<commit_before>/*
---

name: View

description: Provides the base class for every objects that are displayed
             through an element.

license: MIT-style license.

authors:
	- Jean-Philippe Dery (jeanphilippe.dery@gmail.com)

requires:
	- Core/Class
	- Core/Class.Extras
	- Core/Array
	- Core/String
	- Core/Number
	- Core/Function
	- Core/Object
	- Core/Event
	- Core/DOMReady
	- Core/Element
	- Core/Element.Style
	- Core/Element.Event
	- Core/Element.Dimensions
	- More/Element.Shortcuts
	- Class-Extras/Class.Binds
	- Class-Extras/Class.Singleton
	- Event.ViewLoad
	- Event.ViewReady
	- Object.Extras
	- Element.Properties.Name
	- Element.Properties.Role
	- Element.Properties.Options
	- Element.Ingest
	- Element.Styles
	- String.Extras
	- Array.Extras
	- Class.Instanciate
	- Class.Mutators.Roles
	- ViewRoles

provides:
	- View

...
*/

if (!window.Moobile) window.Moobile = {};

Moobile.View = new Class({

	Implements: [
		Events,
		Options,
		Class.Binds
	],

	Roles: Moobile.ViewRoles,

	rolePerformers: [],

	window: null,

	name: null,

	ready: false,

	element: null,

	content: null,

	childViews: [],

	parentView: null,

	options: {
		className: 'view',
		element: 'div'
	},

	initialize: function(element, options, name) {
		this.name = name || null;
		this.setOptions(options);
		this.setElement(element);
		this.attachRoles();
		this.build();
		return this;
	},

	startup: function() {

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

		this.ready = true;

		this.setup();
		this.attachEvents();

		this.fireEvent('viewready');

		return this;
	},

	destroy: function() {

		if (this.ready == false)
			return this;

		this.detachEvents();
		this.destroyChildViews();
		this.teardown();

		this.removeFromParentView();

		this.element.destroy();
		this.element = null;
		this.content = null;
		this.window = null;

		this.ready = false;

		return this;
	},

	build: function() {

		var content = this.getRolePerformer('content');
		if (content == null) {
			content = new Element('div');
			content.ingest(this.element);
			content.inject(this.element);
		}

		this.content = this.applyRole(content, 'content');

		var className = this.options.className;
		if (className) {
			this.element.addClass(className);
			this.content.addClass(className + '-content');
		}

		return this;
	},

	setup: function() {
		return this;
	},

	teardown: function() {
		return this;
	},

	attachRoles: function() {
		this.element.getChildren().each(this.bound('attachRole'));
		return this;
	},

	attachRole: function(element) {

		var name = element.get('data-role');
		if (name) {

			this.rolePerformers.push(element);

			var role = this.getRole(name);
			if (role) {

				this.applyRole(element, role);

				if (role.stop) {
					return this;
				}
			}
		}

		element.getChildren().each(this.bound('attachRole'));

		return this;
	},

	applyRole: function(element, role) {

		var result = element.retrieve('moobile:element-role');
		if (result) {
			return result;
		}

		if (typeof role == 'string') {
			role = this.getRole(role);
		}

		if (role && role.apply) {

			var instance = role.apply.call(this, element);
			if (instance instanceof Moobile.View) {
				this.addChildView(instance);
			}

			element.store('moobile:element-role', instance);

			return instance;
		}

		return null;
	},

	getRolePerformer: function(role) {
		return this.getRolePerformers(role)[0] || null;
	},

	getRolePerformers: function(role) {
		return role
			? this.rolePerformers.filter(function(element) { return element.get('data-role') == role; })
			: this.rolePerformers;
	},

	getRole: function(name) {
		return this.$roles[name] || null;
	},

	attachEvents: function() {
		this.element.addEvent('swipe', this.bound('onViewSwipe'));
		this.element.addEvent('click', this.bound('onViewClick'));
		this.element.addEvent('mouseup', this.bound('onViewMouseUp'))
		this.element.addEvent('mousedown', this.bound('onViewMouseDown'));
		return this;
	},

	detachEvents: function() {
		this.element.removeEvent('swipe', this.bound('onViewSwipe'));
		this.element.removeEvent('click', this.bound('onViewClick'));
		this.element.removeEvent('mouseup', this.bound('onViewMouseUp'));
		this.element.removeEvent('mousedown', this.bound('onViewMouseDown'));
		return this;
	},

	addChildView: function(view, where, context) {

		if (this.ready == false) {
			this.addEvent('viewready:once', function() {
				this.addChildView(view, where, context);
			}.bind(this));
			return this;
		}

		var exists = this.childViews.contains(view);
		if (exists == true)
			return this;

		var element = view.getElement();

		var contains = this.element.contains(element);
		if (contains == false) {
			if (context) {
				element.inject(context, where);
			} else {
				switch (where) {
					case 'header': this.element.grab(element, 'top');    break;
					case 'footer': this.element.grab(element, 'bottom'); break;
					default:	   this.content.grab(element, where);	 break;
				}
			}
		}

		this.willAddChildView(view);
		view.parentViewWillChange(this);
		view.setParentView(this);
		view.setWindow(this.window);
		this.childViews.push(view);

		view.parentViewDidChange(this);
		view.startup();
		this.didAddChildView(view);

		Object.defineMember(this, view, view.name);

		return this;
	},

	getChildView: function(name) {
		return this.childViews.find(function(childView) {
			return childView.getName() == name;
		});
	},

	getChildViewAt: function(index) {
		return this.childViews[index] || null;
	},

	replaceChildView: function(replace, view) {
		return this.addChildView(view, 'before', replace).removeChildView(replace);
	},

	removeChildView: function(view) {

		var exists = this.childViews.contains(view);
		if (exists == false)
			return this;

		var element = view.getElement();

		this.willRemoveChildView(view);
		view.parentViewWillChange(null);
		view.setParentView(null);
		view.setWindow(null);
		view.parentViewDidChange(null);
		element.dispose();
		this.childViews.erase(view);
		this.didRemoveChildView(view);

		return this;
	},

	removeFromParentView: function() {
		var parent = this.parentView || this.window;
		if (parent) parent.removeChildView(this);
		return this;
	},

	destroyChildViews: function() {
		this.childViews.each(this.bound('destroyChildView'));
		this.childViews.empty();
		return this;
	},

	destroyChildView: function(view) {
		view.destroy();
		view = null;
		return this;
	},

	show: function() {
		this.willShow();
		this.element.show();
		this.didShow();
		return this;
	},

	hide: function() {
		this.willHide();
		this.element.hide();
		this.didHide();
		return this;
	},

	setWindow: function(window) {
		this.window = window;
		return this;
	},

	getWindow: function(window) {
		return this.window;
	},

	getName: function() {
		return this.name;
	},

	isReady: function() {
		return this.ready;
	},

	setElement: function(element) {

		if (this.element == null) {
			this.element = document.id(element) || new Element(this.options.element);
			return this;
		}

		throw new Error('The element cannot be redefined');

		return this;
	},

	getElement: function(selector) {
		return selector ? this.element.getElement(selector) : this.element;
	},

	getElements: function(selector) {
		return selector ? this.element.getElements(selector) : this.element.getChildren();
	},

	getContent: function() {
		return this.content;
	},

	setParentView: function(parentView) {
		this.parentView = parentView;
		return this;
	},

	getParentView: function() {
		return this.parentView;
	},

	getChildViews: function() {
		return this.childViews;
	},

	get: function(name) {

		switch (name) {
			case 'html':
			case 'text':
				return this.content.get(name);
			default:
				return this.element.get(name);
		}

		return t;
	},

	set: function(name, value) {

		switch (name) {
			case 'html':
			case 'text':
				this.content.set(name, value);
				break;
			default:
				this.element.set(name, value);
				break;
		}

		return this;
	},

	addClass: function(name) {
		this.element.addClass(name);
		return this;
	},

	removeClass: function(name) {
		this.element.removeClass(name);
		return this;
	},

	toggleClass: function(name) {
		this.element.toggleClass(name);
		return this;
	},

	setStyle: function(style, value) {
		this.element.setStyle(style, value);
		return this;
	},

	setStyles: function(styles) {
		this.element.setStyles(styles);
		return this;
	},

	getStyle: function(style) {
		return this.element.getStyle(style);
	},

	getStyles: function(styles) {
		return this.element.getStyles(styles);
	},

	removeStyle: function(style) {
		this.element.removeStyle(style);
		return this;
	},

	removeStyles: function(styles) {
		this.element.removeStyles(styles);
		return this;
	},

	getSize: function() {
		return this.element.getSize();
	},

	parentViewWillChange: function(parentView) {
		return this;
	},

	parentViewDidChange: function(parentView) {
		return this;
	},

	willAddChildView: function(childView) {
		return this;
	},

	didAddChildView: function(childView) {
		return this;
	},

	willRemoveChildView: function(childView) {
		return this;
	},

	didRemoveChildView: function(childView) {
		return this;
	},

	willAddChildElement: function(childElement) {
		return this;
	},

	didAddChildElement: function(childElement) {
		return this;
	},

	willRemoveChildElement: function(childElement) {
		return this;
	},

	didRemoveChildElement: function(childElement) {
		return this;
	},

	willShow: function() {
		return this;
	},

	didShow: function() {
		return this;
	},

	willHide: function() {
		return this;
	},

	didHide: function() {
		return this;
	},

	onViewSwipe: function(e) {
		e.target = this;
		this.fireEvent('swipe', e);
		return this;
	},

	onViewClick: function(e) {
		e.target = this;
		this.fireEvent('click', e);
		return this;
	},

	onViewMouseUp: function(e) {
		e.target = this;
		this.fireEvent('mouseup', e);
		return this;
	},

	onViewMouseDown: function(e) {
		e.target = this;
		this.fireEvent('mousedown', e);
		return this;
	},

	toElement: function() {
		return this.element;
	}

});<commit_msg>Removed *style method from the View class<commit_after>/*
---

name: View

description: Provides the base class for every objects that are displayed
             through an element.

license: MIT-style license.

authors:
	- Jean-Philippe Dery (jeanphilippe.dery@gmail.com)

requires:
	- Core/Class
	- Core/Class.Extras
	- Core/Array
	- Core/String
	- Core/Number
	- Core/Function
	- Core/Object
	- Core/Event
	- Core/DOMReady
	- Core/Element
	- Core/Element.Style
	- Core/Element.Event
	- Core/Element.Dimensions
	- More/Element.Shortcuts
	- Class-Extras/Class.Binds
	- Class-Extras/Class.Singleton
	- Event.ViewLoad
	- Event.ViewReady
	- Object.Extras
	- Element.Properties.Name
	- Element.Properties.Role
	- Element.Properties.Options
	- Element.Ingest
	- Element.Styles
	- String.Extras
	- Array.Extras
	- Class.Instanciate
	- Class.Mutators.Roles
	- ViewRoles

provides:
	- View

...
*/

if (!window.Moobile) window.Moobile = {};

Moobile.View = new Class({

	Implements: [
		Events,
		Options,
		Class.Binds
	],

	Roles: Moobile.ViewRoles,

	rolePerformers: [],

	window: null,

	name: null,

	ready: false,

	element: null,

	content: null,

	childViews: [],

	parentView: null,

	options: {
		className: 'view',
		element: 'div'
	},

	initialize: function(element, options, name) {
		this.name = name || null;
		this.setOptions(options);
		this.setElement(element);
		this.attachRoles();
		this.build();
		return this;
	},

	startup: function() {

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

		this.ready = true;

		this.setup();
		this.attachEvents();

		this.fireEvent('viewready');

		return this;
	},

	destroy: function() {

		if (this.ready == false)
			return this;

		this.detachEvents();
		this.destroyChildViews();
		this.teardown();

		this.removeFromParentView();

		this.element.destroy();
		this.element = null;
		this.content = null;
		this.window = null;

		this.ready = false;

		return this;
	},

	build: function() {

		var content = this.getRolePerformer('content');
		if (content == null) {
			content = new Element('div');
			content.ingest(this.element);
			content.inject(this.element);
		}

		this.content = this.applyRole(content, 'content');

		var className = this.options.className;
		if (className) {
			this.element.addClass(className);
			this.content.addClass(className + '-content');
		}

		return this;
	},

	setup: function() {
		return this;
	},

	teardown: function() {
		return this;
	},

	attachRoles: function() {
		this.element.getChildren().each(this.bound('attachRole'));
		return this;
	},

	attachRole: function(element) {

		var name = element.get('data-role');
		if (name) {

			this.rolePerformers.push(element);

			var role = this.getRole(name);
			if (role) {

				this.applyRole(element, role);

				if (role.stop) {
					return this;
				}
			}
		}

		element.getChildren().each(this.bound('attachRole'));

		return this;
	},

	applyRole: function(element, role) {

		var result = element.retrieve('moobile:element-role');
		if (result) {
			return result;
		}

		if (typeof role == 'string') {
			role = this.getRole(role);
		}

		if (role && role.apply) {

			var instance = role.apply.call(this, element);
			if (instance instanceof Moobile.View) {
				this.addChildView(instance);
			}

			element.store('moobile:element-role', instance);

			return instance;
		}

		return null;
	},

	getRolePerformer: function(role) {
		return this.getRolePerformers(role)[0] || null;
	},

	getRolePerformers: function(role) {
		return role
			? this.rolePerformers.filter(function(element) { return element.get('data-role') == role; })
			: this.rolePerformers;
	},

	getRole: function(name) {
		return this.$roles[name] || null;
	},

	attachEvents: function() {
		this.element.addEvent('swipe', this.bound('onViewSwipe'));
		this.element.addEvent('click', this.bound('onViewClick'));
		this.element.addEvent('mouseup', this.bound('onViewMouseUp'))
		this.element.addEvent('mousedown', this.bound('onViewMouseDown'));
		return this;
	},

	detachEvents: function() {
		this.element.removeEvent('swipe', this.bound('onViewSwipe'));
		this.element.removeEvent('click', this.bound('onViewClick'));
		this.element.removeEvent('mouseup', this.bound('onViewMouseUp'));
		this.element.removeEvent('mousedown', this.bound('onViewMouseDown'));
		return this;
	},

	addChildView: function(view, where, context) {

		if (this.ready == false) {
			this.addEvent('viewready:once', function() {
				this.addChildView(view, where, context);
			}.bind(this));
			return this;
		}

		var exists = this.childViews.contains(view);
		if (exists == true)
			return this;

		var element = view.getElement();

		var contains = this.element.contains(element);
		if (contains == false) {
			if (context) {
				element.inject(context, where);
			} else {
				switch (where) {
					case 'header': this.element.grab(element, 'top');    break;
					case 'footer': this.element.grab(element, 'bottom'); break;
					default:	   this.content.grab(element, where);	 break;
				}
			}
		}

		this.willAddChildView(view);
		view.parentViewWillChange(this);
		view.setParentView(this);
		view.setWindow(this.window);
		this.childViews.push(view);

		view.parentViewDidChange(this);
		view.startup();
		this.didAddChildView(view);

		Object.defineMember(this, view, view.name);

		return this;
	},

	getChildView: function(name) {
		return this.childViews.find(function(childView) {
			return childView.getName() == name;
		});
	},

	getChildViewAt: function(index) {
		return this.childViews[index] || null;
	},

	replaceChildView: function(replace, view) {
		return this.addChildView(view, 'before', replace).removeChildView(replace);
	},

	removeChildView: function(view) {

		var exists = this.childViews.contains(view);
		if (exists == false)
			return this;

		var element = view.getElement();

		this.willRemoveChildView(view);
		view.parentViewWillChange(null);
		view.setParentView(null);
		view.setWindow(null);
		view.parentViewDidChange(null);
		element.dispose();
		this.childViews.erase(view);
		this.didRemoveChildView(view);

		return this;
	},

	removeFromParentView: function() {
		var parent = this.parentView || this.window;
		if (parent) parent.removeChildView(this);
		return this;
	},

	destroyChildViews: function() {
		this.childViews.each(this.bound('destroyChildView'));
		this.childViews.empty();
		return this;
	},

	destroyChildView: function(view) {
		view.destroy();
		view = null;
		return this;
	},

	show: function() {
		this.willShow();
		this.element.show();
		this.didShow();
		return this;
	},

	hide: function() {
		this.willHide();
		this.element.hide();
		this.didHide();
		return this;
	},

	setWindow: function(window) {
		this.window = window;
		return this;
	},

	getWindow: function(window) {
		return this.window;
	},

	getName: function() {
		return this.name;
	},

	isReady: function() {
		return this.ready;
	},

	setElement: function(element) {

		if (this.element == null) {
			this.element = document.id(element) || new Element(this.options.element);
			return this;
		}

		throw new Error('The element cannot be redefined');

		return this;
	},

	getElement: function(selector) {
		return selector ? this.element.getElement(selector) : this.element;
	},

	getElements: function(selector) {
		return selector ? this.element.getElements(selector) : this.element.getChildren();
	},

	getContent: function() {
		return this.content;
	},

	setParentView: function(parentView) {
		this.parentView = parentView;
		return this;
	},

	getParentView: function() {
		return this.parentView;
	},

	getChildViews: function() {
		return this.childViews;
	},

	get: function(name) {

		switch (name) {
			case 'html':
			case 'text':
				return this.content.get(name);
			default:
				return this.element.get(name);
		}

		return t;
	},

	set: function(name, value) {

		switch (name) {
			case 'html':
			case 'text':
				this.content.set(name, value);
				break;
			default:
				this.element.set(name, value);
				break;
		}

		return this;
	},

	addClass: function(name) {
		this.element.addClass(name);
		return this;
	},

	removeClass: function(name) {
		this.element.removeClass(name);
		return this;
	},

	toggleClass: function(name) {
		this.element.toggleClass(name);
		return this;
	},

	getSize: function() {
		return this.element.getSize();
	},

	parentViewWillChange: function(parentView) {
		return this;
	},

	parentViewDidChange: function(parentView) {
		return this;
	},

	willAddChildView: function(childView) {
		return this;
	},

	didAddChildView: function(childView) {
		return this;
	},

	willRemoveChildView: function(childView) {
		return this;
	},

	didRemoveChildView: function(childView) {
		return this;
	},

	willAddChildElement: function(childElement) {
		return this;
	},

	didAddChildElement: function(childElement) {
		return this;
	},

	willRemoveChildElement: function(childElement) {
		return this;
	},

	didRemoveChildElement: function(childElement) {
		return this;
	},

	willShow: function() {
		return this;
	},

	didShow: function() {
		return this;
	},

	willHide: function() {
		return this;
	},

	didHide: function() {
		return this;
	},

	onViewSwipe: function(e) {
		e.target = this;
		this.fireEvent('swipe', e);
		return this;
	},

	onViewClick: function(e) {
		e.target = this;
		this.fireEvent('click', e);
		return this;
	},

	onViewMouseUp: function(e) {
		e.target = this;
		this.fireEvent('mouseup', e);
		return this;
	},

	onViewMouseDown: function(e) {
		e.target = this;
		this.fireEvent('mousedown', e);
		return this;
	},

	toElement: function() {
		return this.element;
	}

});<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');

var paths = gulp.paths;

var $ = require('gulp-load-plugins')({
  pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del']
});

gulp.task('partials', function () {
  return gulp.src([
    paths.src + '/{app,components}/**/*.html',
    paths.tmp + '/{app,components}/**/*.html'
  ])
    .pipe($.minifyHtml({
      empty: true,
      spare: true,
      quotes: true
    }))
    .pipe($.angularTemplatecache('templateCacheHtml.js', {
      module: 'oregamiClientApp'
    }))
    .pipe(gulp.dest(paths.tmp + '/partials/'));
});

gulp.task('html', ['inject', 'partials'], function () {
  var partialsInjectFile = gulp.src(paths.tmp + '/partials/templateCacheHtml.js', { read: false });
  var partialsInjectOptions = {
    starttag: '<!-- inject:partials -->',
    ignorePath: paths.tmp + '/partials',
    addRootSlash: false
  };

  var htmlFilter = $.filter('*.html');
  var jsFilter = $.filter('**/*.js');
  var cssFilter = $.filter('**/*.css');
  var assets;

  return gulp.src(paths.tmp + '/serve/*.html')
    .pipe($.inject(partialsInjectFile, partialsInjectOptions))
    .pipe(assets = $.useref.assets())
    .pipe($.rev())
    .pipe(jsFilter)
    .pipe($.ngAnnotate())
    .pipe($.uglify({preserveComments: $.uglifySaveLicense}))
    .pipe(jsFilter.restore())
    .pipe(cssFilter)
    .pipe($.csso())
    .pipe(cssFilter.restore())
    .pipe(assets.restore())
    .pipe($.useref())
    .pipe($.revReplace())
    .pipe(htmlFilter)
    .pipe($.minifyHtml({
      empty: true,
      spare: true,
      quotes: true
    }))
    .pipe(htmlFilter.restore())
    .pipe(gulp.dest(paths.dist + '/'))
    .pipe($.size({ title: paths.dist + '/', showFiles: true }));
});

gulp.task('images', function () {
  return gulp.src(paths.src + '/assets/images/**/*')
    .pipe(gulp.dest(paths.dist + '/assets/images/'));
});

gulp.task('fonts', function () {
  return gulp.src($.mainBowerFiles())
    .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
    .pipe($.flatten())
    .pipe(gulp.dest(paths.dist + '/fonts/'));
});

gulp.task('misc', function () {
  return gulp.src(paths.src + '/**/*.ico')
    .pipe(gulp.dest(paths.dist + '/'));
});

gulp.task('clean', function (done) {
  $.del([paths.dist + '/', paths.tmp + '/'], done);
});

gulp.task('build', ['html', 'images', 'fonts', 'misc']);
<commit_msg>gulp task "language"<commit_after>'use strict';

var gulp = require('gulp');

var paths = gulp.paths;

var $ = require('gulp-load-plugins')({
  pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del']
});

gulp.task('partials', function () {
  return gulp.src([
    paths.src + '/{app,components}/**/*.html',
    paths.tmp + '/{app,components}/**/*.html'
  ])
    .pipe($.minifyHtml({
      empty: true,
      spare: true,
      quotes: true
    }))
    .pipe($.angularTemplatecache('templateCacheHtml.js', {
      module: 'oregamiClientApp'
    }))
    .pipe(gulp.dest(paths.tmp + '/partials/'));
});

gulp.task('html', ['inject', 'partials'], function () {
  var partialsInjectFile = gulp.src(paths.tmp + '/partials/templateCacheHtml.js', { read: false });
  var partialsInjectOptions = {
    starttag: '<!-- inject:partials -->',
    ignorePath: paths.tmp + '/partials',
    addRootSlash: false
  };

  var htmlFilter = $.filter('*.html');
  var jsFilter = $.filter('**/*.js');
  var cssFilter = $.filter('**/*.css');
  var assets;

  return gulp.src(paths.tmp + '/serve/*.html')
    .pipe($.inject(partialsInjectFile, partialsInjectOptions))
    .pipe(assets = $.useref.assets())
    .pipe($.rev())
    .pipe(jsFilter)
    .pipe($.ngAnnotate())
    .pipe($.uglify({preserveComments: $.uglifySaveLicense}))
    .pipe(jsFilter.restore())
    .pipe(cssFilter)
    .pipe($.csso())
    .pipe(cssFilter.restore())
    .pipe(assets.restore())
    .pipe($.useref())
    .pipe($.revReplace())
    .pipe(htmlFilter)
    .pipe($.minifyHtml({
      empty: true,
      spare: true,
      quotes: true
    }))
    .pipe(htmlFilter.restore())
    .pipe(gulp.dest(paths.dist + '/'))
    .pipe($.size({ title: paths.dist + '/', showFiles: true }));
});

gulp.task('images', function () {
  return gulp.src(paths.src + '/assets/images/**/*')
    .pipe(gulp.dest(paths.dist + '/assets/images/'));
});

gulp.task('language', function () {
  return gulp.src(paths.src + '/assets/language/**/*')
    .pipe(gulp.dest(paths.dist + '/assets/language/'));
});

gulp.task('fonts', function () {
  return gulp.src($.mainBowerFiles())
    .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
    .pipe($.flatten())
    .pipe(gulp.dest(paths.dist + '/fonts/'));
});

gulp.task('misc', function () {
  return gulp.src(paths.src + '/**/*.ico')
    .pipe(gulp.dest(paths.dist + '/'));
});

gulp.task('clean', function (done) {
  $.del([paths.dist + '/', paths.tmp + '/'], done);
});

gulp.task('build', ['html', 'images', 'language', 'fonts', 'misc']);
<|endoftext|>


<commit_before>//noAuth spec

var CoursePage = function() {

	this.get = function() {
		browser.get(browser.baseUrl + '/#!/courses');
	};

	this.btn_addCourse =
		element(by.buttonText('Add New Course'));

	// Course items
	this.course_title = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
			.get(ind)
			.element(by.tagName('h1'))
			.element(by.tagName('a'));
	};
	this.course_description = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
			.get(ind).element(by.tagName('h4'));
	};
	this.btn_purchase = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
		.get(ind)
		.element(by.buttonText('Purchase'));
	}
	this.btn_edit = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
		.get(ind)
		.element(by.buttonText('Edit'));
	}
	this.btn_delete = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
		.get(ind)
		.element(by.buttonText('Delete'));
	}

	// <--- Modal items --->

	this.modal = function() {
		return element(by.className('modal-content'));
	}
	this.modal_open = function(ind) {
		this.course_title(ind).click();
	}
	this.modal_btnClose = this.modal()
		.element(by.id('exit'));

	this.modal_close = function() {
		this.modal_btnClose.click();
	}
	this.modal_title = function() {
		return this.modal()
		.element(by.className('modal-header'))
		.element(by.tagName('h3'))
		.getText();
	}

	this.modal_videoLink = function() {
		return this.modal()
		.element(by.tagName('iframe'))
		.getAttribute('src');
	}
	this.modal_description = function() {
		return this.modal()
		.element.all(by.css('.list-group li'))
		.get(0).getText();
	}
	this.modal_instructor = function() {
		return this.modal()
		.element.all(by.css('.list-group li'))
		.get(1).getText();
	}
	this.modal_price = function() {
		return this.modal()
		.element.all(by.css('.list-group li'))
		.get(2).element(by.tagName('b')).getText();
	}

	this.modal_clickPurchase = function() {
		this.modal()
		.element(by.buttonText('Purchase')).click();
	}
};

describe('Course page as noAuth user', function() {
	var coursePage = new CoursePage();
	it('Initialize test', function() {
		coursePage.get();
	});
	describe('Add course button', function() {
		it('Sh- not be visible', function() {
			expect(
				coursePage.btn_addCourse
				.isDisplayed())
			.toBeFalsy();
		});
	});
	// ASSUMPTION:
	//	There is >= 1 course viewable by noAuth user
	// 	Otherwise, tests will fail
	describe('Course0 edit button', function() {
		it('Sh- not be visible', function() {
			expect(
				coursePage.btn_edit(0)
				.isDisplayed())
			.toBeFalsy();
		});
	});
	describe('Course0 delete button', function() {
		it('Sh- not be visible', function() {
			expect(
				coursePage.btn_delete(0)
				.isDisplayed())
			.toBeFalsy();
		});
	});
	describe('Clicking purchase', function() {
		it('Perform click', function() {
			coursePage.btn_purchase(0).click();
		});
		it('Sh- direct to signin page', function() {
			expect(
				browser.getCurrentUrl())
			.toBe(browser.baseUrl + '/#!/signin');
		});
	});
	describe('/create page', function() {
		it('Sh- not be accessible', function() {
			coursePage.get();
			browser.get(browser.baseUrl + '/#!/courses/create');
			expect(
				browser.getCurrentUrl())
			.toBe(browser.baseUrl + '/#!/courses');
		});
	});
	describe('Course0 modal', function() {
		it('Open modal', function() {
			coursePage.get();
			coursePage.modal_open(0);
		});
		describe('Modal0 title', function(){
			it('Sh- match the h1 title text for course0', function() {
				expect(
					coursePage.modal_title())
				.toBe('Karate');
			});
		});
		describe('Click modal purchase', function() {
			it('Perform click', function() {
				coursePage.modal_clickPurchase();
			});
			it('Sh- direct to signin page', function() {
				expect(
					browser.getCurrentUrl())
				.toBe(browser.baseUrl + '/#!/signin');
			});
		});
		it('Close modal', function() {
			coursePage.modal_close();
		});
	});
});<commit_msg>Jk on "finalized". Added noAuth courseID tests<commit_after>//noAuth spec

var CoursePage = function() {

	this.get = function() {
		browser.get(browser.baseUrl + '/#!/courses');
	};

	this.btn_addCourse =
		element(by.buttonText('Add New Course'));

	// Course items
	this.course_title = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
			.get(ind)
			.element(by.tagName('h1'))
			.element(by.tagName('a'));
	};
	this.course_description = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
			.get(ind).element(by.tagName('h4'));
	};
	this.btn_purchase = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
		.get(ind)
		.element(by.buttonText('Purchase'));
	}
	this.btn_edit = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
		.get(ind)
		.element(by.buttonText('Edit'));
	}
	this.btn_delete = function(ind) {
		return element.all(by.repeater('course in coursesCtrl.courses'))
		.get(ind)
		.element(by.buttonText('Delete'));
	}

	// <--- Modal items --->

	this.modal = function() {
		return element(by.className('modal-content'));
	}
	this.modal_open = function(ind) {
		this.course_title(ind).click();
	}
	this.modal_btnClose = this.modal()
		.element(by.id('exit'));

	this.modal_close = function() {
		this.modal_btnClose.click();
	}
	this.modal_title = function() {
		return this.modal()
		.element(by.className('modal-header'))
		.element(by.tagName('h3'))
		.getText();
	}

	this.modal_videoLink = function() {
		return this.modal()
		.element(by.tagName('iframe'))
		.getAttribute('src');
	}
	this.modal_description = function() {
		return this.modal()
		.element.all(by.css('.list-group li'))
		.get(0).getText();
	}
	this.modal_instructor = function() {
		return this.modal()
		.element.all(by.css('.list-group li'))
		.get(1).getText();
	}
	this.modal_price = function() {
		return this.modal()
		.element.all(by.css('.list-group li'))
		.get(2).element(by.tagName('b')).getText();
	}

	this.modal_clickPurchase = function() {
		this.modal()
		.element(by.buttonText('Purchase')).click();
	}
};

describe('Course page as noAuth user', function() {
	var coursePage = new CoursePage();
	it('Initialize test', function() {
		coursePage.get();
	});
	describe('Add course button', function() {
		it('Sh- not be visible', function() {
			expect(
				coursePage.btn_addCourse
				.isDisplayed())
			.toBeFalsy();
		});
	});
	// ASSUMPTION:
	//	There is >= 1 course viewable by noAuth user
	// 	Otherwise, tests will fail
	describe('Course0 edit button', function() {
		it('Sh- not be visible', function() {
			expect(
				coursePage.btn_edit(0)
				.isDisplayed())
			.toBeFalsy();
		});
	});
	describe('Course0 delete button', function() {
		it('Sh- not be visible', function() {
			expect(
				coursePage.btn_delete(0)
				.isDisplayed())
			.toBeFalsy();
		});
	});
	describe('Clicking purchase', function() {
		it('Perform click', function() {
			coursePage.btn_purchase(0).click();
		});
		it('Sh- direct to signin page', function() {
			expect(
				browser.getCurrentUrl())
			.toBe(browser.baseUrl + '/#!/signin');
		});
	});
	describe('/create page', function() {
		it('Sh- not be accessible', function() {
			coursePage.get();
			browser.get(browser.baseUrl + '/#!/courses/create');
			expect(
				browser.getCurrentUrl())
			.toBe(browser.baseUrl + '/#!/courses');
		});
	});
	describe('/course/ page',function () {
		it('Sh- direct to course error page', function() {
			//Assuming user will be directed to course error page
			browser.get(browser.baseUrl + '/#!/course/');
			expect(
				browser.getCurrentUrl())
			.toBe(browser.baseUrl + '/#!/error/course');
		});
	});
	describe('Accessing invalid course id', function() {
		it('Sh- direct to course error page', function() {
			coursePage.get();
			browser.get(browser.baseUrl + '/#!/course/NEVERGONNAGIVEYOUUP');
			expect(
				browser.getCurrentUrl())
			.toBe(browser.baseUrl + '/#!/error/course');
		});
	});
	describe('Course0 modal', function() {
		it('Open modal', function() {
			coursePage.get();
			coursePage.modal_open(0);
		});
		describe('Modal0 title', function(){
			it('Sh- match the h1 title text for course0', function() {
				expect(
					coursePage.modal_title())
				.toBe('Karate');
			});
		});
		describe('Click modal purchase', function() {
			it('Perform click', function() {
				coursePage.modal_clickPurchase();
			});
			it('Sh- direct to signin page', function() {
				expect(
					browser.getCurrentUrl())
				.toBe(browser.baseUrl + '/#!/signin');
			});
		});
		it('Close modal', function() {
			coursePage.modal_close();
		});
	});
});<|endoftext|>


<commit_before>var test = require('mocha').it,
  expect = require('chai').expect;

test('fromEnglish: "zero" through "nine"', function(){
  expect(fromEnglish).to.exist;
  expect(fromEnglish("zero")).to.equal(0);
  expect(fromEnglish("one")).to.equal(1);
  // more tests here, please...
}); // END test(fromEnglish)

/**
 * @param {String} word representing an English number
 * @return {Number} value corresponding to `word`
 */
function fromEnglish(word){
  // fill this in after writing tests...
} // END fromEnglish

test('plus: ("zero", "zero") through ("zero", "nine")', function(){
  expect(plus).to.exist;
  expect(plus("zero", "zero")).to.equal(0);
  expect(plus("zero", "one")).to.equal(1); // change just one thing!
  expect(plus("zero", "two")).to.equal(FILL_ME_IN); // ha!
  // write more tests like those...
}); // END test(plus)

/**
 * @param {String} A representing an English number word
 * @param {String} B representing an English number word
 * @return {Number} the value of `A` added to `B`
 */
function plus(A, B){
  // write those tests first, please...
} // END plus

test('minus: ("zero", "zero") through ("zero", "nine")', function(){
  expect(minus).to.exist;
  expect(minus("zero", "zero")).to.equal(0);
  expect(minus("zero", "one")).to.equal(-1);
  // etc, etc, etc
}); // END test(minus)

// What about multiplication? Division? Exponents?
<commit_msg>fromEnglish passed test<commit_after>var test = require('mocha').it,
  expect = require('chai').expect;

test('fromEnglish: "zero" through "nine"', function(){
  expect(fromEnglish).to.exist;
  expect(fromEnglish("zero")).to.equal(0);
  expect(fromEnglish("one")).to.equal(1);
  expect(fronEnglish("two")).to.equal(2);
  expect(fromEnglish("three")).to.equal(3);
  expect(fromEnglish("four")).to.equal(4);
  expect(fromEnglish("five")).to.equal(5);
  expect(fromEnglish("six")).to.equal(6);
  expect(fromEnglish("seven")).to.equal(7);
  expect(fromEnglish("eight")).to.equal(8);
  expect(fromEnglish("nine")).to.equal(9);
}); // END test(fromEnglish)

/**
 * @param {String} word representing an English number
 * @return {Number} value corresponding to `word`
 */
function fromEnglish(word){
  if (word == "zero") {
  word == 0;
  } else if (word == "one"){
    word == 1;
  } else if (word == "two") {
    word == 2;
  } else if (word == "three") {
    word == 3;
  } else if (word == "four") {
    word == 4;
  } else if (word == "five") {
    word == 5;
  } else if (word == "six") {
    word == 6;
  } else if (word == "seven") {
  word == 7;
  } else if (word == "eight") {
    word == 8;
  } else if (word == "nine") {
    word == 9
  };
};
} // END fromEnglish

test('plus: ("zero", "zero") through ("zero", "nine")', function(){
  expect(plus).to.exist;
  expect(plus("zero", "zero")).to.equal(0);
  expect(plus("zero", "one")).to.equal(1); // change just one thing!
  expect(plus("zero", "two")).to.equal(2); // ha!
  expect(plus("zero", "three")).to.equal(3);
  expect(plus("zero", "four")).to.equal(4);
  expect(plus("zero", "five")).to.equal(5);
  expect(plus("zero", "six")).to.equal(6);
  expect(plus("zero", "seven")).to.equal(7);
  expect(plus("zero", "eight")).to.equal(8);
  expect(plus("zero", "nine")).to.equal(9);
  // write more tests like those...
}); // END test(plus)
/**
 * @param {String} A representing an English number word
 * @param {String} B representing an English number word
 * @return {Number} the value of `A` added to `B`
 */
function plus(A, B){
  // write those tests first, please...
} // END plus

test('minus: ("zero", "zero") through ("zero", "nine")', function(){
  expect(minus).to.exist;
  expect(minus("zero", "zero")).to.equal(0);
  expect(minus("zero", "one")).to.equal(-1);
  // etc, etc, etc
}); // END test(minus)

// What about multiplication? Division? Exponents?
<|endoftext|>


<commit_before>const fs = require('fs-extra')
const less = require('less')
const path = require('path')
const glob = require('glob')

let main_output_dir = path.resolve(__dirname, '../dist/css')
fs.mkdirSync(main_output_dir, { recursive: true })

// /*
//  * Copy support files
//  */
// fs.copySync('src/css/icons', path.join(main_output_dir, 'icons'), err => {
//     console.error(err);
//     return 1;
// });

// /*
//  * Compile base CSS
//  */
// let p = path.resolve(__dirname, '../src/less/TL.Timeline.less')
// let file_content = fs.readFileSync(p, 'utf-8')
// less.render(file_content, {
//     filename: p
// }).then(
//     (output) => {
//         var basename = path.basename(p, '.less')
//         var output_css = path.join(main_output_dir, `timeline.css`)
//         fs.writeFileSync(path.join(output_css), output.css)
//         console.log(`FONT CSS compiled ${p}`)
//     }
// )

/*
 * Compile font files
 */
const font_src_dir = path.resolve(__dirname, '../src/less/fonts')
const font_output_dir = path.resolve(__dirname, '../dist/css/fonts')
fs.mkdirSync(font_output_dir, { recursive: true })
glob.sync(path.join(font_src_dir, "font.*.less")).forEach((p) => {
    let file_content = fs.readFileSync(p, 'utf-8')
    less.render(file_content, {
        filename: p
    }).then(
        (output) => {
            var basename = path.basename(p, '.less')
            var output_css = path.join(font_output_dir, `${basename}.css`)
            fs.writeFileSync(path.join(output_css), output.css)
            console.log(`FONT CSS compiled ${p}`)
        },
        (error) => {
            console.log(`fonts: error compiling ${p}`, error)
        }
    )
})

/*
 * Compile themes
 */
const theme_src_dir = path.resolve(__dirname, '../src/less/themes')
const theme_output_dir = path.resolve(__dirname, '../dist/css/themes')
fs.mkdirSync(theme_output_dir, { recursive: true })
glob.sync(path.join(theme_src_dir, "**/TL.Theme.*.less")).forEach((p) => {
    let file_content = fs.readFileSync(p, 'utf-8')
    less.render(file_content, {
        filename: p
    }).then(
        (output) => {
            var theme_name = p.split('/').slice(-2, -1)
            var output_css = path.join(theme_output_dir, `timeline.theme.${theme_name}.css`)
            fs.writeFileSync(output_css, output.css)
            console.log(`THEME CSS compiled ${p}`)
        },
        (error) => {
            console.log(`themes: error compiling ${p}`, error)
        }
    )
})<commit_msg>be more flexible about whether dir exists<commit_after>const fs = require('fs-extra')
const less = require('less')
const path = require('path')
const glob = require('glob')

let main_output_dir = path.resolve(__dirname, '../dist/css')
fs.ensureDirSync(main_output_dir, { recursive: true })

// /*
//  * Copy support files
//  */
// fs.copySync('src/css/icons', path.join(main_output_dir, 'icons'), err => {
//     console.error(err);
//     return 1;
// });

// /*
//  * Compile base CSS
//  */
// let p = path.resolve(__dirname, '../src/less/TL.Timeline.less')
// let file_content = fs.readFileSync(p, 'utf-8')
// less.render(file_content, {
//     filename: p
// }).then(
//     (output) => {
//         var basename = path.basename(p, '.less')
//         var output_css = path.join(main_output_dir, `timeline.css`)
//         fs.writeFileSync(path.join(output_css), output.css)
//         console.log(`FONT CSS compiled ${p}`)
//     }
// )

/*
 * Compile font files
 */
const font_src_dir = path.resolve(__dirname, '../src/less/fonts')
const font_output_dir = path.resolve(__dirname, '../dist/css/fonts')
fs.ensureDirSync(font_output_dir, { recursive: true })
glob.sync(path.join(font_src_dir, "font.*.less")).forEach((p) => {
    let file_content = fs.readFileSync(p, 'utf-8')
    less.render(file_content, {
        filename: p
    }).then(
        (output) => {
            var basename = path.basename(p, '.less')
            var output_css = path.join(font_output_dir, `${basename}.css`)
            fs.writeFileSync(path.join(output_css), output.css)
            console.log(`FONT CSS compiled ${p}`)
        },
        (error) => {
            console.log(`fonts: error compiling ${p}`, error)
        }
    )
})

/*
 * Compile themes
 */
const theme_src_dir = path.resolve(__dirname, '../src/less/themes')
const theme_output_dir = path.resolve(__dirname, '../dist/css/themes')
fs.ensureDirSync(theme_output_dir, { recursive: true })
glob.sync(path.join(theme_src_dir, "**/TL.Theme.*.less")).forEach((p) => {
    let file_content = fs.readFileSync(p, 'utf-8')
    less.render(file_content, {
        filename: p
    }).then(
        (output) => {
            var theme_name = p.split('/').slice(-2, -1)
            var output_css = path.join(theme_output_dir, `timeline.theme.${theme_name}.css`)
            fs.writeFileSync(output_css, output.css)
            console.log(`THEME CSS compiled ${p}`)
        },
        (error) => {
            console.log(`themes: error compiling ${p}`, error)
        }
    )
})<|endoftext|>


<commit_before>define(['Animated_GIF'], function (Animated_GIF) {
  'use strict';

  function VideoShooter (videoElement) {
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    context.scale(-1, 1); // mirror flip preview back to the normal direction

    canvas.width = videoElement.width;
    canvas.height = videoElement.height;

    this.getShot = function (callback, numFrames, interval) {
      numFrames = numFrames !== undefined ? numFrames : 3;
      interval = interval !== undefined ? interval : 0.1; // In seconds

      var pendingFrames = numFrames;
      var ag = new Animated_GIF({ workerPath: 'javascripts/lib/Animated_GIF/quantizer.js' });
      ag.setSize(canvas.width, canvas.height);
      ag.setDelay(interval);

      captureFrame();

      function captureFrame() {
          ag.addFrame(videoElement);
          pendingFrames--;

          if(pendingFrames > 0) {
              setTimeout(captureFrame, interval * 1000); // timeouts are in milliseconds
          } else {
              ag.getBase64GIF(function(image) {
                  var img = document.createElement('img');
                  img.src = image;
                  document.body.appendChild(img);
                  callback(image);
              });
          }
      }

    };
  };

  return VideoShooter;
});
<commit_msg>Fixes #48. Update videoShooter.js to use 2 spaces indents instead of mixed<commit_after>define(['Animated_GIF'], function (Animated_GIF) {
  'use strict';

  function VideoShooter (videoElement) {
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    context.scale(-1, 1); // mirror flip preview back to the normal direction

    canvas.width = videoElement.width;
    canvas.height = videoElement.height;

    this.getShot = function (callback, numFrames, interval) {
      numFrames = numFrames !== undefined ? numFrames : 3;
      interval = interval !== undefined ? interval : 0.1; // In seconds

      var pendingFrames = numFrames;
      var ag = new Animated_GIF({ workerPath: 'javascripts/lib/Animated_GIF/quantizer.js' });
      ag.setSize(canvas.width, canvas.height);
      ag.setDelay(interval);

      captureFrame();

      function captureFrame() {
        ag.addFrame(videoElement);
        pendingFrames--;

        if(pendingFrames > 0) {
          setTimeout(captureFrame, interval * 1000); // timeouts are in milliseconds
        } else {
          ag.getBase64GIF(function(image) {
            var img = document.createElement('img');
            img.src = image;
            document.body.appendChild(img);
            callback(image);
          });
        }
      }
    };
  };

  return VideoShooter;
});
<|endoftext|>


<commit_before>/*
 * grunt-file-compare
 * https://github.com/Risto-Stevcev/grunt-file-compare
 *
 * Copyright (c) 2015 Risto Stevcev
 * Licensed under the BSD license
 */

module.exports = function(grunt) {
  grunt.registerMultiTask('file_compare', 'Grunt task to check if a set of files are equal', function() {
    function CompareError(message) {
      this.name = 'CompareError'
      this.message = message || ''
      var error = new Error(message)
      error.name = this.name
      this.stack = error.stack
    }
    CompareError.prototype = Object.create(Error.prototype)

    var done = this.async()
    var options = this.options({
      compareBinary: 'diff'
    })

    this.files.forEach(function(file, index, files) {
      if (options.compareBinary === 'diff')
        file.src.unshift('-q')  // quiet mode

      grunt.util.spawn({
        cmd: options.compareBinary,
        args: file.src
      }, function(error, result, code) {
        if (error)
          grunt.fail.fatal(new CompareError(result.stdout))

        if (index === files.length - 1)
          done()
      })
    })
  })
}
<commit_msg>Adding more verbose error output because grunt.fail.fatal does not print error messages or their stack trace.<commit_after>/*
 * grunt-file-compare
 * https://github.com/Risto-Stevcev/grunt-file-compare
 *
 * Copyright (c) 2015 Risto Stevcev
 * Licensed under the BSD license
 */

module.exports = function(grunt) {
  grunt.registerMultiTask('file_compare', 'Grunt task to check if a set of files are equal', function() {
    var done = this.async()
    var options = this.options({
      compareBinary: 'diff'
    })

    this.files.forEach(function(file, index, files) {
      if (options.compareBinary === 'diff')
        file.src.unshift('-q')  // quiet mode

      grunt.util.spawn({
        cmd: options.compareBinary,
        args: file.src
      }, function(error, result, code) {
        if (error) {
          grunt.log.error(result.stdout)
          grunt.fail.fatal('File compare failed.')
        }

        if (index === files.length - 1)
          done()
      })
    })
  })
}
<|endoftext|>


<commit_before>/*
* Repertoire abstract ajax model, for use with widget framework
*
* Copyright (c) 2009 MIT Hyperstudio
* Christopher York, 11/2009
*
* Requires jquery 1.3.2+
* Support: Firefox 3+ & Safari 4+.  IE emphatically not supported.
*/

//= require "global"
//= require "widget"
//= require "events"

//= require <jquery>

//
// Abstract model for ajax widgets.  This class includes convenience methods for listening to
// events on models, for jquery ajax calls, and for param encoding in Merb's style.
//
// Handles:
//       - change publication and observing
//       - url/query-string construction
//
// Usage. The model provides a facade to your ajax webservice, and may hold state for a widget.
//        In some cases (e.g. working with large server-side datasets), it may be appropriate to
//        cache data in the model and fetch it as needed from the webservice.
//
// Using the ajax param encoders.  These convenience methods help you construct the url and
//        assemble params for an ajax call.  It's not required to use them, although they make life
//        easier.
//
// self.items = function(callback) {
//   var url = self.default_url(['projects', 'results']);
//   self.fetch(params, url, 'html', callback);
// }
//
repertoire.model = function(options) {
  // this object is an abstract class
  var self = {};

  // default: no options specified
  options = options || {};

  // mixin event handler functionality
  repertoire.events(self);

  //
  // Update the data model given the current state
  //
  // You may either pre-process the state and write your own webservice access methods
  // or use self.fetch for a generic webservice, e.g.
  //
  // self.update = function(state, callback) {
  //   var url = self.default_url(['projects', 'results']);
  //   self.fetch(state, url, 'html', callback);
  // }
  //
  self.update = function(state, callback) {
    throw "Abstract function: redefine self.update() in your data model."
  };

  //
  // Utility method to issue an ajax HTTP GET to fetch data from a webservice
  //
  //   params:   params to send as http query line
  //   url:      url of webservice to access
  //   type:     type of data returned (e.g. 'json', 'html')
  //   callback: function to call with returned data
  //
  self.fetch = function(params, url, type, callback, $elem, async) {
    if (async == null)
      async = true;

    var spinnerClass = options.spinner || 'loading';
    if ($elem)
      $elem.addClass(spinnerClass);
    $.ajax({
      async:    async,
      url:      url,
      data:     self.to_query_string(params),
      type:     'GET',
      dataType: type,
      // content negotiation problems may require:
      /* beforeSend: function(xhr) { xhr.setRequestHeader("Accept", "application/json") } */
      success:  callback,
      error:    function(request, textStatus, errorThrown) {
          if ($elem)
            $elem.html(options.error || 'Could not load');
      },
      complete: function () {
          if ($elem)
            $elem.removeClass(spinnerClass);
      }
    });
  };

  //
  // Format a webservice url, preferring options.url if possible
  //
  self.default_url = function(default_parts, ext) {
    var path_prefix = options.path_prefix || '';
    var parts       = default_parts.slice();

    parts.unshift(path_prefix);
    url = options.url || parts.join('/')

    if (ext)
      url += '.' + ext;

    return url;
  }

  //
  // Convert a structure of params to a URL query string suitable for use in an HTTP GET request, compliant with Merb's format.
  //
  //   An example:
  //
  //   Merb::Parse.params_to_query_string(:filter => {:year => [1593, 1597], :genre => ['Tragedy', 'Comedy'] }, :search => 'William')
  //   ==> "filter[genre][]=Tragedy&filter[genre][]=Comedy&filter[year][]=1593&filter[year][]=1597&search=William"
  //
  self.to_query_string = function(value, prefix) {
    var vs = [];
    prefix = prefix || '';
    if (value instanceof Array) {
      jQuery.each(value, function(i, v) {
        vs.push(self.to_query_string(v, prefix + '[]'));
      });
      return vs.join('&');
    } else if (typeof(value) == "object") {
      jQuery.each(value, function(k, v) {
        vs.push(self.to_query_string(v, (prefix.length > 0) ? (prefix + '[' + escape(k) + ']') : escape(k)));
      });
      // minor addition to merb: discard empty value lists { e.g. discipline: [] }
      vs = array_filter(vs, function(x) { return x !== ""; });
      return vs.join('&');
    } else {
      return prefix + '=' + escape(value);
    }
  };

  // Apparently IE doesn't support the filter function? -DD via Brett
  var array_filter = function (thisArray, fun) {
    var len = thisArray.length;
      if (typeof fun != "function")
        throw new TypeError();

      var res = new Array();
      var thisp = arguments[1];

      for (var i = 0; i < len; i++) {
        if (i in thisArray) {
          var val = thisArray[i]; // in case fun mutates this
          if (fun.call(thisp, val, i, thisArray))
            res.push(val);
	}
      }

      return res;
  };

  // end of model factory function
  return self;
}<commit_msg>Changed calls to JavaScript escape() function to encodeURIComponent()--UTF-8 strings were not getting properly encoded on the browser side, and this broke faceting (and would break who knows what else...).<commit_after>/*
* Repertoire abstract ajax model, for use with widget framework
*
* Copyright (c) 2009 MIT Hyperstudio
* Christopher York, 11/2009
*
* Requires jquery 1.3.2+
* Support: Firefox 3+ & Safari 4+.  IE emphatically not supported.
*/

//= require "global"
//= require "widget"
//= require "events"

//= require <jquery>

//
// Abstract model for ajax widgets.  This class includes convenience methods for listening to
// events on models, for jquery ajax calls, and for param encoding in Merb's style.
//
// Handles:
//       - change publication and observing
//       - url/query-string construction
//
// Usage. The model provides a facade to your ajax webservice, and may hold state for a widget.
//        In some cases (e.g. working with large server-side datasets), it may be appropriate to
//        cache data in the model and fetch it as needed from the webservice.
//
// Using the ajax param encoders.  These convenience methods help you construct the url and
//        assemble params for an ajax call.  It's not required to use them, although they make life
//        easier.
//
// self.items = function(callback) {
//   var url = self.default_url(['projects', 'results']);
//   self.fetch(params, url, 'html', callback);
// }
//
repertoire.model = function(options) {
  // this object is an abstract class
  var self = {};

  // default: no options specified
  options = options || {};

  // mixin event handler functionality
  repertoire.events(self);

  //
  // Update the data model given the current state
  //
  // You may either pre-process the state and write your own webservice access methods
  // or use self.fetch for a generic webservice, e.g.
  //
  // self.update = function(state, callback) {
  //   var url = self.default_url(['projects', 'results']);
  //   self.fetch(state, url, 'html', callback);
  // }
  //
  self.update = function(state, callback) {
    throw "Abstract function: redefine self.update() in your data model."
  };

  //
  // Utility method to issue an ajax HTTP GET to fetch data from a webservice
  //
  //   params:   params to send as http query line
  //   url:      url of webservice to access
  //   type:     type of data returned (e.g. 'json', 'html')
  //   callback: function to call with returned data
  //
  self.fetch = function(params, url, type, callback, $elem, async) {
    if (async == null)
      async = true;

    var spinnerClass = options.spinner || 'loading';
    if ($elem)
      $elem.addClass(spinnerClass);
    $.ajax({
      async:    async,
      url:      url,
      data:     self.to_query_string(params),
      type:     'GET',
      dataType: type,
      // content negotiation problems may require:
      /* beforeSend: function(xhr) { xhr.setRequestHeader("Accept", "application/json") } */
      success:  callback,
      error:    function(request, textStatus, errorThrown) {
          if ($elem)
            $elem.html(options.error || 'Could not load');
      },
      complete: function () {
          if ($elem)
            $elem.removeClass(spinnerClass);
      }
    });
  };

  //
  // Format a webservice url, preferring options.url if possible
  //
  self.default_url = function(default_parts, ext) {
    var path_prefix = options.path_prefix || '';
    var parts       = default_parts.slice();

    parts.unshift(path_prefix);
    url = options.url || parts.join('/')

    if (ext)
      url += '.' + ext;

    return url;
  }

  //
  // Convert a structure of params to a URL query string suitable for use in an HTTP GET request, compliant with Merb's format.
  //
  //   An example:
  //
  //   Merb::Parse.params_to_query_string(:filter => {:year => [1593, 1597], :genre => ['Tragedy', 'Comedy'] }, :search => 'William')
  //   ==> "filter[genre][]=Tragedy&filter[genre][]=Comedy&filter[year][]=1593&filter[year][]=1597&search=William"
  //
  self.to_query_string = function(value, prefix) {
    var vs = [];
    prefix = prefix || '';
    if (value instanceof Array) {
      jQuery.each(value, function(i, v) {
        vs.push(self.to_query_string(v, prefix + '[]'));
      });
      return vs.join('&');
    } else if (typeof(value) == "object") {
      jQuery.each(value, function(k, v) {
        vs.push(self.to_query_string(v, (prefix.length > 0) ? (prefix + '[' + encodeURIComponent(k) + ']') : encodeURIComponent(k)));
      });
      // minor addition to merb: discard empty value lists { e.g. discipline: [] }
      vs = array_filter(vs, function(x) { return x !== ""; });
      return vs.join('&');
    } else {
      return prefix + '=' + encodeURIComponent(value);
    }
  };

  // Apparently IE doesn't support the filter function? -DD via Brett
  var array_filter = function (thisArray, fun) {
    var len = thisArray.length;
      if (typeof fun != "function")
        throw new TypeError();

      var res = new Array();
      var thisp = arguments[1];

      for (var i = 0; i < len; i++) {
        if (i in thisArray) {
          var val = thisArray[i]; // in case fun mutates this
          if (fun.call(thisp, val, i, thisArray))
            res.push(val);
	}
      }

      return res;
  };

  // end of model factory function
  return self;
}<|endoftext|>


<commit_before>'use strict';

/**
 * @constructor
 * @param {Object.<string,*>} obj
 */
starChat.Channel = function (obj) {
    var name = obj.name;
    name = name.replace(/^\s*(.*?)\s*$/, '$1').replace(/(?![\n\r\t])[\x00-\x1f\x7f]/mg, '');
    name = name.substring(0, 32);
    this.name_               = name;
    this.users_              = [];
    this.messagesByTimeSpan_ = {};
    this.firstMessage_       = null;
    this.update(obj);
};

/**
 * @param {!string} name
 * @return {starChat.Channel}
 */
starChat.Channel.find = (function () {
    var cache = {};
    return function (name) {
        if (name in cache) {
            return cache[name];
        }
        return cache[name] = new starChat.Channel({
            name: name
        });
    };
})();

/**
 * @param {Object.<string,*>} obj
 */
starChat.Channel.prototype.update = function (obj) {
    if ('topic' in obj) {
        this.topic_ = obj.topic;
    }
    if ('privacy' in obj) {
        this.privacy_ = obj.privacy;
    }
};

/**
 * @return {string}
 */
starChat.Channel.prototype.name = function () {
    return this.name_;
};

/**
 * @param {Object.<string,*>=} topic
 * @return {starChat.Channel|Object.<string,*>}
 */
starChat.Channel.prototype.topic = function (topic) {
    if (topic !== void(0)) {
        this.topic_ = topic;
        return this;
    } else {
        return this.topic_;
    }
};

/**
 * @param {string=} privacy
 * @return {starChat.Channel|string}
 */
starChat.Channel.prototype.privacy = function (privacy) {
    if (privacy !== void(0)) {
        if (privacy == 'public' || privacy == 'private') {
            this.privacy_ = privacy;
        }
        return this;
    } else {
        return this.privacy_;
    }
};

starChat.Channel.prototype.users = function () {
    return this.users_;
};

starChat.Channel.prototype.addUser = function (name) {
    var r = $.grep(this.users_, function (user) {
        return user.name() === name;
    });
    if (r.length === 0) {
        this.users_.push(starChat.User.find(name));
    }
};

starChat.Channel.prototype.removeUser = function (name) {
    var idx = -1;
    for (var i = 0; i < this.users_.length; i++) {
        if (this.users_[i].name() === name) {
            idx = i;
            break;
        }
    }
    if (idx !== -1) {
        this.users_.splice(idx, 1);
    }
};

starChat.Channel.prototype.firstMessage = function () {
    return this.firstMessage_;
};

starChat.Channel.prototype.messagesByTimespan = function (startTime, endTime) {
    var key = startTime + ',' + endTime;
    if (key in this.messagesByTimeSpan_) {
        return this.messagesByTimeSpan_[key];
    } else {
        return [];
    }
};

/**
 * @param {!starChat.Session} session
 * @param {function(number)=} callback
 */
starChat.Channel.prototype.load = function (session, callback) {
    var url = '/channels/' + encodeURIComponent(this.name());
    var self = this;
    starChat.ajaxRequest(session, url, 'GET', null, function (sessionId, url, method, data) {
        self.topic(data.topic);
        if ('privacy' in data) {
            self.privacy(data.privacy);
        }
        if (callback !== void(0)) {
            callback(sessionId);
        }
    });
};

/**
 * @param {!starChat.Session} session
 * @param {function(number)=} callback
 */
starChat.Channel.prototype.loadUsers = function (session, callback) {
    var url = '/channels/' + encodeURIComponent(this.name()) + '/users';
    var self = this;
    starChat.ajaxRequest(session, url, 'GET', null, function (sessionId, url, method, data) {
        self.users_ = data.map(function (obj) {
            var user = starChat.User.find(obj.name);
            user.update(obj);
            return user;
        });
        if (callback !== void(0)) {
            callback(sessionId);
        }
    });
};

// TODO: Array -> Array.<starChat.Message>
/**
 * @param {!starChat.Session} session
 * @param {function(number, Array)=} callback
 */
starChat.Channel.prototype.loadFirstMessage = function (session, callback) {
    var url = '/channels/' + encodeURIComponent(this.name()) + '/messages/by_index/0,1';
    var self = this;
    starChat.ajaxRequest(session, url, 'GET', null, function (sessionId, url, method, data) {
        self.firstMessage_ = data[0];
        if (callback !== void(0)) {
            callback(sessionId, data);
        }
    });
};

// TODO: Array -> Array.<starChat.Message>
/**
 * @param {!starChat.Session} session
 * @param {number} startTime
 * @param {number} endTime
 * @param {function(number, Array)=} callback
 */
starChat.Channel.prototype.loadMessagesByTimeSpan = function (session, startTime, endTime, callback) {
    var url = '/channels/' + encodeURIComponent(this.name()) + '/messages/by_time_span/' +
        encodeURIComponent(string(startTime)) + ',' + encodeURIComponent(string(endTime));
    var self = this;
    starChat.ajaxRequest(session, url, 'GET', null, function (sessionId, url, method, data) {
        var key = startTime + ',' + endTime;
        self.messagesByTimeSpan_[key] = data;
        if (callback !== void(0)) {
            callback(sessionId, data);
        }
    });
};

// TODO: Is the callback type OK?
/**
 * @param {!starChat.Session} session
 * @param {function(number, string)=} callback
 */
starChat.Channel.prototype.generateKey = function (session, callback) {
    var url = '/channels/' + encodeURIComponent(this.name()) + '/keys';
    var self = this;
    starChat.ajaxRequest(session, url, 'POST', null, function (sessionId, url, method, data) {
        if (callback !== void(0)) {
            callback(sessionId, data.key);
        }
    });
};

/**
 * @param {!starChat.Session} session
 * @param {function(number)=} callback
 */
starChat.Channel.prototype.save = (function () {
    var lastTopicBody = null;
    return function (session, callback) {
        var url = '/channels/' + encodeURIComponent(this.name());
        var params = {};
        if (this.topic()) {
            var topicBody = this.topic().body;
            topicBody = topicBody.replace(/^\s*(.*?)\s*$/, '$1').replace(/(?![\n\r\t])[\x00-\x1f\x7f]/mg, '');
            topicBody = topicBody.substring(0, 1024);
            if (lastTopicBody !== topicBody) {
                params.topic = {
                    body: topicBody
                }
                lastTopicBody = topicBody
            }
        }
        params.privacy = this.privacy();
        starChat.ajaxRequest(session, url, 'PUT', params, function (sessionId, url, method, data) {
            if (callback !== void(0)) {
                callback(sessionId);
            }
        });
    };
})();
<commit_msg>Bug fix: replaced string with String<commit_after>'use strict';

/**
 * @constructor
 * @param {Object.<string,*>} obj
 */
starChat.Channel = function (obj) {
    var name = obj.name;
    name = name.replace(/^\s*(.*?)\s*$/, '$1').replace(/(?![\n\r\t])[\x00-\x1f\x7f]/mg, '');
    name = name.substring(0, 32);
    this.name_               = name;
    this.users_              = [];
    this.messagesByTimeSpan_ = {};
    this.firstMessage_       = null;
    this.update(obj);
};

/**
 * @param {!string} name
 * @return {starChat.Channel}
 */
starChat.Channel.find = (function () {
    var cache = {};
    return function (name) {
        if (name in cache) {
            return cache[name];
        }
        return cache[name] = new starChat.Channel({
            name: name
        });
    };
})();

/**
 * @param {Object.<string,*>} obj
 */
starChat.Channel.prototype.update = function (obj) {
    if ('topic' in obj) {
        this.topic_ = obj.topic;
    }
    if ('privacy' in obj) {
        this.privacy_ = obj.privacy;
    }
};

/**
 * @return {string}
 */
starChat.Channel.prototype.name = function () {
    return this.name_;
};

/**
 * @param {Object.<string,*>=} topic
 * @return {starChat.Channel|Object.<string,*>}
 */
starChat.Channel.prototype.topic = function (topic) {
    if (topic !== void(0)) {
        this.topic_ = topic;
        return this;
    } else {
        return this.topic_;
    }
};

/**
 * @param {string=} privacy
 * @return {starChat.Channel|string}
 */
starChat.Channel.prototype.privacy = function (privacy) {
    if (privacy !== void(0)) {
        if (privacy == 'public' || privacy == 'private') {
            this.privacy_ = privacy;
        }
        return this;
    } else {
        return this.privacy_;
    }
};

starChat.Channel.prototype.users = function () {
    return this.users_;
};

starChat.Channel.prototype.addUser = function (name) {
    var r = $.grep(this.users_, function (user) {
        return user.name() === name;
    });
    if (r.length === 0) {
        this.users_.push(starChat.User.find(name));
    }
};

starChat.Channel.prototype.removeUser = function (name) {
    var idx = -1;
    for (var i = 0; i < this.users_.length; i++) {
        if (this.users_[i].name() === name) {
            idx = i;
            break;
        }
    }
    if (idx !== -1) {
        this.users_.splice(idx, 1);
    }
};

starChat.Channel.prototype.firstMessage = function () {
    return this.firstMessage_;
};

starChat.Channel.prototype.messagesByTimespan = function (startTime, endTime) {
    var key = startTime + ',' + endTime;
    if (key in this.messagesByTimeSpan_) {
        return this.messagesByTimeSpan_[key];
    } else {
        return [];
    }
};

/**
 * @param {!starChat.Session} session
 * @param {function(number)=} callback
 */
starChat.Channel.prototype.load = function (session, callback) {
    var url = '/channels/' + encodeURIComponent(this.name());
    var self = this;
    starChat.ajaxRequest(session, url, 'GET', null, function (sessionId, url, method, data) {
        self.topic(data.topic);
        if ('privacy' in data) {
            self.privacy(data.privacy);
        }
        if (callback !== void(0)) {
            callback(sessionId);
        }
    });
};

/**
 * @param {!starChat.Session} session
 * @param {function(number)=} callback
 */
starChat.Channel.prototype.loadUsers = function (session, callback) {
    var url = '/channels/' + encodeURIComponent(this.name()) + '/users';
    var self = this;
    starChat.ajaxRequest(session, url, 'GET', null, function (sessionId, url, method, data) {
        self.users_ = data.map(function (obj) {
            var user = starChat.User.find(obj.name);
            user.update(obj);
            return user;
        });
        if (callback !== void(0)) {
            callback(sessionId);
        }
    });
};

// TODO: Array -> Array.<starChat.Message>
/**
 * @param {!starChat.Session} session
 * @param {function(number, Array)=} callback
 */
starChat.Channel.prototype.loadFirstMessage = function (session, callback) {
    var url = '/channels/' + encodeURIComponent(this.name()) + '/messages/by_index/0,1';
    var self = this;
    starChat.ajaxRequest(session, url, 'GET', null, function (sessionId, url, method, data) {
        self.firstMessage_ = data[0];
        if (callback !== void(0)) {
            callback(sessionId, data);
        }
    });
};

// TODO: Array -> Array.<starChat.Message>
/**
 * @param {!starChat.Session} session
 * @param {number} startTime
 * @param {number} endTime
 * @param {function(number, Array)=} callback
 */
starChat.Channel.prototype.loadMessagesByTimeSpan = function (session, startTime, endTime, callback) {
    var url = '/channels/' + encodeURIComponent(this.name()) + '/messages/by_time_span/' +
        encodeURIComponent(String(startTime)) + ',' + encodeURIComponent(String(endTime));
    var self = this;
    starChat.ajaxRequest(session, url, 'GET', null, function (sessionId, url, method, data) {
        var key = startTime + ',' + endTime;
        self.messagesByTimeSpan_[key] = data;
        if (callback !== void(0)) {
            callback(sessionId, data);
        }
    });
};

// TODO: Is the callback type OK?
/**
 * @param {!starChat.Session} session
 * @param {function(number, string)=} callback
 */
starChat.Channel.prototype.generateKey = function (session, callback) {
    var url = '/channels/' + encodeURIComponent(this.name()) + '/keys';
    var self = this;
    starChat.ajaxRequest(session, url, 'POST', null, function (sessionId, url, method, data) {
        if (callback !== void(0)) {
            callback(sessionId, data.key);
        }
    });
};

/**
 * @param {!starChat.Session} session
 * @param {function(number)=} callback
 */
starChat.Channel.prototype.save = (function () {
    var lastTopicBody = null;
    return function (session, callback) {
        var url = '/channels/' + encodeURIComponent(this.name());
        var params = {};
        if (this.topic()) {
            var topicBody = this.topic().body;
            topicBody = topicBody.replace(/^\s*(.*?)\s*$/, '$1').replace(/(?![\n\r\t])[\x00-\x1f\x7f]/mg, '');
            topicBody = topicBody.substring(0, 1024);
            if (lastTopicBody !== topicBody) {
                params.topic = {
                    body: topicBody
                }
                lastTopicBody = topicBody
            }
        }
        params.privacy = this.privacy();
        starChat.ajaxRequest(session, url, 'PUT', params, function (sessionId, url, method, data) {
            if (callback !== void(0)) {
                callback(sessionId);
            }
        });
    };
})();
<|endoftext|>