<commit_before>describe("Unit tests for webapp custom field model.", function() {
	it("Check custom field correct url.", function() {
		var webappName = "Test webapp",
			expectedEndpoint = "/api/v2/admin/sites/current/webapps/" + webappName + "/fields",
			expectedId = 5,
			field = new BCAPI.Models.WebApp.CustomField(webappName, {id: expectedId});

		expect(field.endpoint()).toBe(expectedEndpoint);
		expect(field.get("id")).toBe(expectedId);
	});

	it("Check custom field instantiation ok with number id.", function() {
		var webappName = "Test webapp",
			expectedId = 63563,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			field = new BCAPI.Models.WebApp.CustomField(webappName, values);

		_assertCustomFieldValues(field, values);
	});

	it("Check custom field instantiation ok with string id that is a number.", function() {
		var webappName = "Test webapp",
			expectedId = "63563",
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			field = new BCAPI.Models.WebApp.CustomField(webappName, values);

		_assertCustomFieldValues(field, values);
	});

	it("Check custom field instantiation ok with string id that is a number with spaces.", function() {
		var webappName = "Test webapp",
			expectedId = "  63563 ",
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			field = new BCAPI.Models.WebApp.CustomField(webappName, values);

		_assertCustomFieldValues(field, values);
	});

	it("Check custom field instantiation failure with string id that is a number with spaces.", function() {
		var webappName = "Test webapp",
			expectedId = "  63 563 ",
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with negative id", function() {
		var webappName = "Test webapp",
			expectedId = -1223,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with negative id as string", function() {
		var webappName = "Test webapp",
			expectedId = "-1223",
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with null id", function() {
		var webappName = "Test webapp",
			expectedId = null,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with NaN id", function() {
		var webappName = "Test webapp",
			expectedId = NaN,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with undefined id", function() {
		var webappName = "Test webapp",
			expectedId = undefined,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with missing id", function() {
		var webappName = "Test webapp",
			values = {"name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with missing attributes", function() {
		var webappName = "Test webapp",
			values = null;

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field set ok.", function() {
		var webappName = "Test webapp",
			expectedId = 63563,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			field = new BCAPI.Models.WebApp.CustomField(webappName, {id: 5});

		field.set(values);

		_assertCustomFieldValues(field, values);
	});

	it("Check save for new custom field", function() {
		var webappName = "Test webapp",
			expectedId = 63563,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			rootUrl = "http://test.localhost.com",
			expectedUrl = rootUrl + "/api/v2/admin/sites/current/webapps/" + webappName + "/fields",
			siteToken = "12345xaz",
			field = new BCAPI.Models.WebApp.CustomField(webappName, values),
			successCalled = false;

		BCAPI.Mocks.Helper.Site(siteToken, rootUrl);

		var successHandler = function(model, response, options) {
			expect(model.get("id")).toBe(values.id);
			expect(model.get("name")).toBe(values.name);
			expect(model.get("type")).toBe(values.type);
			expect(model.get("required")).toBe(values.required);
			expect(model.get("order")).toBe(values.order);
			expect(model.get("dataSourceName")).toBe(values.dataSourceName);
			expect(model.get("listItems")).toBe(values.listItems);

			successCalled = true;
		};

		spyOn($, "ajax").andCallFake(function(request) {
			expect(request.url).toBe(expectedUrl);
			expect(request.type).toBe("POST");
			expect(request.headers.Authorization).toBe(siteToken);

			request.success(field);

			return $.Deferred();
		});

		field.save({ success: successHandler });

		waitsFor(function() { return successCalled; }, "Success handler not called.", 50);
	});

	it("Check save for existing custom field", function() {
		var webappName = "Test webapp",
			expectedId = 63563,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			rootUrl = "http://test.localhost.com",
			expectedUrl = rootUrl + "/api/v2/admin/sites/current/webapps/" + webappName + "/fields/" + expectedId,
			siteToken = "12345xaz",
			field = new BCAPI.Models.WebApp.CustomField(webappName, values, false),
			successCalled = false;

		BCAPI.Mocks.Helper.Site(siteToken, rootUrl);

		var successHandler = function(model, response, options) {
			expect(model.get("id")).toBe(values.id);
			expect(model.get("name")).toBe(values.name);
			expect(model.get("type")).toBe(values.type);
			expect(model.get("required")).toBe(values.required);
			expect(model.get("order")).toBe(values.order);
			expect(model.get("dataSourceName")).toBe(values.dataSourceName);
			expect(model.get("listItems")).toBe(values.listItems);

			successCalled = true;
		};

		spyOn($, "ajax").andCallFake(function(request) {
			expect(request.url).toBe(expectedUrl);
			expect(request.type).toBe("PUT");
			expect(request.headers.Authorization).toBe(siteToken);

			request.success(field);

			return $.Deferred();
		});

		field.save({ success: successHandler });

		waitsFor(function() { return successCalled; }, "Success handler not called.", 50);
	});

	/**
	 * This method assert that field properties equals given values.
	 */
	function _assertCustomFieldValues(field, values) {
		for(var key in values) {
			expect(field.get(key)).toBe(values[key]);
		}
	}
});<commit_msg>added license header<commit_after>/*
*
* Copyright (c) 2012-2014 Adobe Systems Incorporated. All rights reserved.

* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
describe("Unit tests for webapp custom field model.", function() {
	it("Check custom field correct url.", function() {
		var webappName = "Test webapp",
			expectedEndpoint = "/api/v2/admin/sites/current/webapps/" + webappName + "/fields",
			expectedId = 5,
			field = new BCAPI.Models.WebApp.CustomField(webappName, {id: expectedId});

		expect(field.endpoint()).toBe(expectedEndpoint);
		expect(field.get("id")).toBe(expectedId);
	});

	it("Check custom field instantiation ok with number id.", function() {
		var webappName = "Test webapp",
			expectedId = 63563,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			field = new BCAPI.Models.WebApp.CustomField(webappName, values);

		_assertCustomFieldValues(field, values);
	});

	it("Check custom field instantiation ok with string id that is a number.", function() {
		var webappName = "Test webapp",
			expectedId = "63563",
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			field = new BCAPI.Models.WebApp.CustomField(webappName, values);

		_assertCustomFieldValues(field, values);
	});

	it("Check custom field instantiation ok with string id that is a number with spaces.", function() {
		var webappName = "Test webapp",
			expectedId = "  63563 ",
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			field = new BCAPI.Models.WebApp.CustomField(webappName, values);

		_assertCustomFieldValues(field, values);
	});

	it("Check custom field instantiation failure with string id that is a number with spaces.", function() {
		var webappName = "Test webapp",
			expectedId = "  63 563 ",
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with negative id", function() {
		var webappName = "Test webapp",
			expectedId = -1223,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with negative id as string", function() {
		var webappName = "Test webapp",
			expectedId = "-1223",
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with null id", function() {
		var webappName = "Test webapp",
			expectedId = null,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with NaN id", function() {
		var webappName = "Test webapp",
			expectedId = NaN,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with undefined id", function() {
		var webappName = "Test webapp",
			expectedId = undefined,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with missing id", function() {
		var webappName = "Test webapp",
			values = {"name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]};

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field instantiation failure with missing attributes", function() {
		var webappName = "Test webapp",
			values = null;

		expect(function() {new BCAPI.Models.WebApp.CustomField(webappName, values)}).toThrow()
	});

	it("Check custom field set ok.", function() {
		var webappName = "Test webapp",
			expectedId = 63563,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			field = new BCAPI.Models.WebApp.CustomField(webappName, {id: 5});

		field.set(values);

		_assertCustomFieldValues(field, values);
	});

	it("Check save for new custom field", function() {
		var webappName = "Test webapp",
			expectedId = 63563,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			rootUrl = "http://test.localhost.com",
			expectedUrl = rootUrl + "/api/v2/admin/sites/current/webapps/" + webappName + "/fields",
			siteToken = "12345xaz",
			field = new BCAPI.Models.WebApp.CustomField(webappName, values),
			successCalled = false;

		BCAPI.Mocks.Helper.Site(siteToken, rootUrl);

		var successHandler = function(model, response, options) {
			expect(model.get("id")).toBe(values.id);
			expect(model.get("name")).toBe(values.name);
			expect(model.get("type")).toBe(values.type);
			expect(model.get("required")).toBe(values.required);
			expect(model.get("order")).toBe(values.order);
			expect(model.get("dataSourceName")).toBe(values.dataSourceName);
			expect(model.get("listItems")).toBe(values.listItems);

			successCalled = true;
		};

		spyOn($, "ajax").andCallFake(function(request) {
			expect(request.url).toBe(expectedUrl);
			expect(request.type).toBe("POST");
			expect(request.headers.Authorization).toBe(siteToken);

			request.success(field);

			return $.Deferred();
		});

		field.save({ success: successHandler });

		waitsFor(function() { return successCalled; }, "Success handler not called.", 50);
	});

	it("Check save for existing custom field", function() {
		var webappName = "Test webapp",
			expectedId = 63563,
			values = {"id": expectedId,
					  "name": "Custom field 1",
					  "type": "Boolean",
					  "required": true,
					  "order": 5,
					  "dataSourceName": "Simple Data Source",
					  "listItems": [1, 2, 3]},
			rootUrl = "http://test.localhost.com",
			expectedUrl = rootUrl + "/api/v2/admin/sites/current/webapps/" + webappName + "/fields/" + expectedId,
			siteToken = "12345xaz",
			field = new BCAPI.Models.WebApp.CustomField(webappName, values, false),
			successCalled = false;

		BCAPI.Mocks.Helper.Site(siteToken, rootUrl);

		var successHandler = function(model, response, options) {
			expect(model.get("id")).toBe(values.id);
			expect(model.get("name")).toBe(values.name);
			expect(model.get("type")).toBe(values.type);
			expect(model.get("required")).toBe(values.required);
			expect(model.get("order")).toBe(values.order);
			expect(model.get("dataSourceName")).toBe(values.dataSourceName);
			expect(model.get("listItems")).toBe(values.listItems);

			successCalled = true;
		};

		spyOn($, "ajax").andCallFake(function(request) {
			expect(request.url).toBe(expectedUrl);
			expect(request.type).toBe("PUT");
			expect(request.headers.Authorization).toBe(siteToken);

			request.success(field);

			return $.Deferred();
		});

		field.save({ success: successHandler });

		waitsFor(function() { return successCalled; }, "Success handler not called.", 50);
	});

	/**
	 * This method assert that field properties equals given values.
	 */
	function _assertCustomFieldValues(field, values) {
		for(var key in values) {
			expect(field.get(key)).toBe(values[key]);
		}
	}
});
<|endoftext|>


<commit_before>var sprintf = require('sprintf');

function PluginError(message) {
  var args = [message];

  if (arguments.length > 1) {
    for (var i = 1, len = arguments.length; i < len; i++)
      args.push(arguments[i]);
  }

  var formatted = sprintf.apply(null, args);

  return new Error(formatted);
}

module.exports = PluginError;<commit_msg>PluginError refactoring<commit_after>var format = require('util').format;

function PluginError(message) {
  var args = [message];

  if (arguments.length > 1) {
    for (var i = 1, len = arguments.length; i < len; i++)
      args.push(arguments[i]);
  }

  var formatted = format.apply(null, args);

  return new Error(formatted);
}

module.exports = PluginError;<|endoftext|>


<commit_before>'use strict';

// libs
require('dotenv').config();
const test = require('ava');
const chai = require('chai');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');
const underscore = require('underscore');

const logger = require('../../../../lib/logger');
const newrelic = require('newrelic');
const stubs = require('../../../helpers/stubs');

const mockPayload = {
  broadcastId: stubs.getBroadcastId(),
  campaignId: stubs.getCampaignId(),
};

// setup "x.should.y" assertion style
chai.should();
chai.use(sinonChai);

// module to be tested
const analyticsHelper = require('../../../../lib/helpers/analytics');

// sinon sandbox object
const sandbox = sinon.sandbox.create();

// Setup!
test.beforeEach(() => {
  stubs.stubLogger(sandbox, logger);
  sandbox.stub(newrelic, 'addCustomAttributes')
    .returns(underscore.noop);
});

// Cleanup!
test.afterEach(() => {
  // reset stubs, spies, and mocks
  sandbox.restore();
});

test('addCustomAttributes should call newrelic.addCustomAttributes', () => {
  analyticsHelper.addCustomAttributes(mockPayload);
  newrelic.addCustomAttributes.should.have.been.called;
});

test('addCustomAttributes should call logger.debug', () => {
  analyticsHelper.addCustomAttributes(mockPayload);
  logger.debug.should.have.been.called;
});

test('addTwilioError should call addCustomAttributes', () => {
  sandbox.stub(analyticsHelper, 'addCustomAttributes')
    .returns(underscore.noop);
  const error = stubs.twilio.getPostMessageError();
  analyticsHelper.addTwilioError(error);
  analyticsHelper.addCustomAttributes.should.have.been.called;
});
<commit_msg>chore (test): Added tests for analyticsHelper.getErrorNoticeableMethod<commit_after>'use strict';

// libs
require('dotenv').config();
const test = require('ava');
const chai = require('chai');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');
const underscore = require('underscore');

const logger = require('../../../../lib/logger');
const newrelic = require('newrelic');
const stubs = require('../../../helpers/stubs');

const mockPayload = {
  broadcastId: stubs.getBroadcastId(),
  campaignId: stubs.getCampaignId(),
};

// setup "x.should.y" assertion style
chai.should();
chai.use(sinonChai);

// module to be tested
const analyticsHelper = require('../../../../lib/helpers/analytics');

// sinon sandbox object
const sandbox = sinon.sandbox.create();

// Setup!
test.beforeEach(() => {
  stubs.stubLogger(sandbox, logger);
  sandbox.stub(newrelic, 'addCustomAttributes')
    .returns(underscore.noop);
  sandbox.stub(newrelic, 'noticeError')
    .returns(underscore.noop);
});

// Cleanup!
test.afterEach(() => {
  // reset stubs, spies, and mocks
  sandbox.restore();
});

test('addCustomAttributes should call newrelic.addCustomAttributes', () => {
  analyticsHelper.addCustomAttributes(mockPayload);
  newrelic.addCustomAttributes.should.have.been.called;
});

test('addCustomAttributes should call logger.debug', () => {
  analyticsHelper.addCustomAttributes(mockPayload);
  logger.debug.should.have.been.called;
});

test('addTwilioError should call addCustomAttributes', () => {
  sandbox.stub(analyticsHelper, 'addCustomAttributes')
    .returns(underscore.noop);
  const error = stubs.twilio.getPostMessageError();
  analyticsHelper.addTwilioError(error);
  analyticsHelper.addCustomAttributes.should.have.been.called;
});

test('getErrorNoticeableMethod should return a function that calls newrelic.noticeError if an Error is passed as argument', () => {
  const dummyFunction = () => true;
  const decoratedDummyFunction = analyticsHelper.getErrorNoticeableMethod(dummyFunction);
  decoratedDummyFunction(new Error('boom!'));
  newrelic.noticeError.should.have.been.called;
});

test('getErrorNoticeableMethod should return a function that doesn\'t call newrelic.noticeError if no Error is passed as argument', () => {
  const dummyFunction = () => true;
  const decoratedDummyFunction = analyticsHelper.getErrorNoticeableMethod(dummyFunction);
  decoratedDummyFunction('hi', 'my', 'name', 'is');
  newrelic.noticeError.should.not.have.been.called;
});
<|endoftext|>


<commit_before>// try to find the most reasonable prefix to use

module.exports = findPrefix

var fs = require("graceful-fs")
  , path = require("path")
  , npm = require("../npm.js")

function findPrefix (p, cb) {
  p = path.resolve(p)
  if (npm.config.get("global")) return cb(null, p)
  // if there's no node_modules folder, then
  // walk up until we hopefully find one.
  // if none anywhere, then use cwd.
  var walkedUp = false
  while (path.basename(p) === "node_modules") {
    p = path.dirname(p)
    walkedUp = true
  }
  if (walkedUp) return cb(null, p)

  findPrefix_(p, p, cb)
}

function findPrefix_ (p, original, cb) {
  if (p === "/"
      || (process.platform === "win32" && p.match(/^[a-zA-Z]:(\\|\/)?$/))) {
    return cb(null, original)
  }
  fs.readdir(p, function (er, files) {
    // an error right away is a bad sign.
    if (er && p === original) return cb(er)

    // walked up too high or something.
    if (er) return cb(null, original)

    if (files.indexOf("node_modules") !== -1
        || files.indexOf("package.json") !== -1) {
      return cb(null, p)
    }

    return findPrefix_(path.dirname(p), original, cb)
  })
}
<commit_msg>Fix #1602 Fix #1603 APIs must be either always sync, or always async<commit_after>// try to find the most reasonable prefix to use

module.exports = findPrefix

var fs = require("graceful-fs")
  , path = require("path")
  , npm = require("../npm.js")

function findPrefix (p, cb_) {
  function cb (er, p) {
    process.nextTick(function () {
      cb_(er, p)
    })
  }

  p = path.resolve(p)
  if (npm.config.get("global")) return cb(null, p)
  // if there's no node_modules folder, then
  // walk up until we hopefully find one.
  // if none anywhere, then use cwd.
  var walkedUp = false
  while (path.basename(p) === "node_modules") {
    p = path.dirname(p)
    walkedUp = true
  }
  if (walkedUp) return cb(null, p)

  findPrefix_(p, p, cb)
}

function findPrefix_ (p, original, cb) {
  if (p === "/"
      || (process.platform === "win32" && p.match(/^[a-zA-Z]:(\\|\/)?$/))) {
    return cb(null, original)
  }
  fs.readdir(p, function (er, files) {
    // an error right away is a bad sign.
    if (er && p === original) return cb(er)

    // walked up too high or something.
    if (er) return cb(null, original)

    if (files.indexOf("node_modules") !== -1
        || files.indexOf("package.json") !== -1) {
      return cb(null, p)
    }

    return findPrefix_(path.dirname(p), original, cb)
  })
}
<|endoftext|>


<commit_before>/**!
 * AjaxEdit v0.0.1
 *
 * Lightweight jQuery plugin used to edit HTML regions without reloading
 * the page.
 *
 * Author: Baptiste Fontaine
 * Licence: MIT
 * Repository: github.com/bfontaine/AjaxEdit
 *
 **/
;(function( $ ) {

    var defaultOptions = {

            /* Define when the element will be set to editable mode.
             * Possible values:
             *      - 'hoverButton': A button labelled "Edit" will appear
             *                       when the user put the cursor over the
             *                       element. If they click on the button,
             *                       the element will become editable. This
             *                       is the default.
             *
             *      - Any other value will be threated as an event on the
             *        element, e.g. "dblclick".
             *
             * This can be a list with multiple values.
             */
            editOn: 'hoverButton',

            /* This option allows you to have different names for the fields
             * in your API.
             */
            fields: {
                html: 'html',
                text: 'text'
            },

            // buttons' labels
            buttons: {
                edit:   'Edit',
                save:   'Save',
                cancel: 'Cancel'
            },

            // if this is set to true, the fields' text values will
            // be preloaded. If this is set to false, their text values
            // will be loaded only if the user try to edit them.
            preload: false

        },

        // This Error is raised when no URL is provided for
        // GETting/POSTing the content
        noURLException = new Error( 'No URL provided.' );

    // attach an "Edit" button to the element, which will be made
    // visible when the user move their mouse over the element
    function attachHoverButton( $el, label, callback ) {

        var $editButton = $( '<input>' )
                            .attr( 'type', 'button' )
                            .addClass( 'ajaxedit-button' )
                            .text( label )
                            .click( callback );

        $el.hover(
            function() { $editButton.appendTo( $el ); },
            function() { $editButton.detach(); }
        );

    }

    // AjaxEdit main function
    $.fn.ajaxedit = function( opts ) {

        if ( arguments.length === 0 ) {

            throw noURLException;

        }

        // if the argument is a string, we assume that
        // this is the API endpoint (URL)
        if ( typeof opts === 'string' ) {

            opts = $.extend( true, {}, defaultOptions, { url: opts } );

        }
        // else, this is an object where keys/values are options
        else if ( typeof opts === 'object' ) {

            opts = $.extend( true, {}, defaultOptions, opts );

        }

        if (!opts.hasOwnProperty('url')) {

            throw noURLException;

        }

        var fields = [];

        if ( this.length === 1 && this.attr('data-name') ) {

            fields.push( this );

        }
        else {

            this.each( function( i, e ) {

                var $e = $(e);

                if ( $e.attr( 'data-name' ) ) {

                    // if this element is editable, don't search for fields in it
                    fields.push($e);

                }
                else {

                    // otherwise, pick its children
                    fields = fields.concat( $e.find( '[data-name]' ) );

                }

            });

        }

        // if there is no editable elements, don't do anything
        if ( fields.length === 0 ) {

            return this;

        }

        // List of events triggered when the user wants to edit an element
        var editOn = ($.type( opts.editOn ) === 'array')
                        ? opts.editOn
                        : [ opts.editOn ];

        $.each( fields, function( i, $field ) {

            // this is the function which will be called when the user
            // try to edit the field
            var callback = function( $el ) {

                // if the field is currently being edited, don't do anything
                if ( $el.data( 'edited' ) ) {
                    return;
                }

                $el.data( 'edited', true );

                // TODO

            };

            // For each 'edit' event, bind the event to the callback
            $.each( editOn, function( i, ev ) {

                // special 'event' : The "Edit" button
                if ( ev === 'hoverButton' ) {

                    attachHoverButton( $field, opts.buttons.edit, callback );

                }
                else {

                    $field.bind( ev, callback );

                }

            });

            // The field is ready to be edited
            $field
                .attr( 'contenteditable', false )
                .trigger( 'EditReady' );

        });

        return this;

    };

})( jQuery );
<commit_msg>Edit callback fixed.<commit_after>/**!
 * AjaxEdit v0.0.1
 *
 * Lightweight jQuery plugin used to edit HTML regions without reloading
 * the page.
 *
 * Author: Baptiste Fontaine
 * Licence: MIT
 * Repository: github.com/bfontaine/AjaxEdit
 *
 **/
;(function( $ ) {

    var defaultOptions = {

            /* Define when the element will be set to editable mode.
             * Possible values:
             *      - 'hoverButton': A button labelled "Edit" will appear
             *                       when the user put the cursor over the
             *                       element. If they click on the button,
             *                       the element will become editable. This
             *                       is the default.
             *
             *      - Any other value will be threated as an event on the
             *        element, e.g. "dblclick".
             *
             * This can be a list with multiple values.
             */
            editOn: 'hoverButton',

            /* This option allows you to have different names for the fields
             * in your API.
             */
            fields: {
                html: 'html',
                text: 'text'
            },

            // buttons' labels
            buttons: {
                edit:   'Edit',
                save:   'Save',
                cancel: 'Cancel'
            },

            // if this is set to true, the fields' text values will
            // be preloaded. If this is set to false, their text values
            // will be loaded only if the user try to edit them.
            preload: false

        },

        // This Error is raised when no URL is provided for
        // GETting/POSTing the content
        noURLException = new Error( 'No URL provided.' );

    // attach an "Edit" button to the element, which will be made
    // visible when the user move their mouse over the element
    function attachHoverButton( $el, label, callback ) {

        var $editButton = $( '<input>' )
                            .attr( 'type', 'button' )
                            .addClass( 'ajaxedit-button' )
                            .text( label )
                            .click( callback );

        $el.hover(
            function() { $editButton.appendTo( $el ); },
            function() { $editButton.detach(); }
        );

    }

    // AjaxEdit main function
    $.fn.ajaxedit = function( opts ) {

        if ( arguments.length === 0 ) {

            throw noURLException;

        }

        // if the argument is a string, we assume that
        // this is the API endpoint (URL)
        if ( typeof opts === 'string' ) {

            opts = $.extend( true, {}, defaultOptions, { url: opts } );

        }
        // else, this is an object where keys/values are options
        else if ( typeof opts === 'object' ) {

            opts = $.extend( true, {}, defaultOptions, opts );

        }

        if (!opts.hasOwnProperty('url')) {

            throw noURLException;

        }

        var fields = [];

        if ( this.length === 1 && this.attr('data-name') ) {

            fields.push( this );

        }
        else {

            this.each( function( i, e ) {

                var $e = $(e);

                if ( $e.attr( 'data-name' ) ) {

                    // if this element is editable, don't search for fields in it
                    fields.push($e);

                }
                else {

                    // otherwise, pick its children
                    fields = fields.concat( $e.find( '[data-name]' ) );

                }

            });

        }

        // if there is no editable elements, don't do anything
        if ( fields.length === 0 ) {

            return this;

        }

        // List of events triggered when the user wants to edit an element
        var editOn = ($.type( opts.editOn ) === 'array')
                        ? opts.editOn
                        : [ opts.editOn ];

        $.each( fields, function( i, $field ) {

            // this is the function which will be called when the user
            // try to edit the field
            var callback = function() {

                var $el = $(this);

                // if the field is currently being edited, don't do anything
                if ( $el.data( 'edited' ) ) {
                    return;
                }

                $el.data( 'edited', true );

                // TODO

            };

            // For each 'edit' event, bind the event to the callback
            $.each( editOn, function( i, ev ) {

                // special 'event': The "Edit" button
                if ( ev === 'hoverButton' ) {

                    attachHoverButton( $field, opts.buttons.edit, callback );

                }
                else {

                    $field.bind( ev, callback );

                }

            });

            // The field is ready to be edited
            $field
                .attr( 'contenteditable', false )
                .trigger( 'EditReady' );

        });

        return this;

    };

})( jQuery );
<|endoftext|>


<commit_before>/* eslint-disable no-new */
const NewClaim = require('../../../../app/services/domain/new-claim')
const ValidationError = require('../../../../app/services/errors/validation-error')
const dateFormatter = require('../../../../app/services/date-formatter')
const booleanSelectEnum = require('../../../../app/constants/boolean-select-enum')
const expect = require('chai').expect

var claim

describe('services/domain/new-claim', function () {
  const VALID_REFERENCE = 'APVS123'
  const VALID_DAY = dateFormatter.now().date()
  const VALID_MONTH = dateFormatter.now().month() + 1 // Needed for zero indexed month
  const VALID_YEAR = dateFormatter.now().year()
  const VALID_CHILD_VISITOR = booleanSelectEnum.YES
  const IS_PAST_CLAIM = false
  const IS_ADVANCE_CLAIM = true

  var expectedDateOfJourney = dateFormatter.build(VALID_DAY, VALID_MONTH, VALID_YEAR)

  it('should construct a domain object given valid input', function () {
    claim = new NewClaim(
      VALID_REFERENCE,
      VALID_DAY,
      VALID_MONTH,
      VALID_YEAR,
      IS_PAST_CLAIM
    )
    expect(claim.reference).to.equal(VALID_REFERENCE)
    expect(claim.dateOfJourney).to.be.within(
      expectedDateOfJourney.subtract(1, 'seconds').toDate(),
      expectedDateOfJourney.add(1, 'seconds').toDate()
    )
    expect(claim.isAdvanceClaim).to.equal(IS_PAST_CLAIM)
  })

  it('should throw ValidationError if given invalid input', function () {
    expect(function () {
      new NewClaim('', '', '', '', false, IS_PAST_CLAIM)
    }).to.throw(ValidationError)
  })

  it('should not throw a ValidationError if is repeat duplicate claim', function () {
    expect(function () {
      claim = new NewClaim(VALID_REFERENCE, VALID_DAY, VALID_MONTH, VALID_YEAR, '', true, IS_PAST_CLAIM)
    }).to.not.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date in the future for past claims', function () {
    var futureDate = dateFormatter.now().add(1, 'days')
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        futureDate.date(),
        futureDate.month() + 1,
        futureDate.year(),
        IS_PAST_CLAIM
      )
    }).to.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date more than 60 days away for a past claim', function () {
    var dateFurtherThan60Days = dateFormatter.now().subtract(61, 'days') // 30 rather than 29 as locally fails in BST, server runs GMT
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        dateFurtherThan60Days.date(),
        dateFurtherThan60Days.month() + 1,
        dateFurtherThan60Days.year(),
        IS_PAST_CLAIM
      )
    }).to.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date more than 60 days away for an advance claim', function () {
    var dateFurtherThan60Days = dateFormatter.now().add(61, 'days') // 30 rather than 29 as locally fails in BST, server runs GMT
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        dateFurtherThan60Days.date(),
        dateFurtherThan60Days.month() + 1,
        dateFurtherThan60Days.year(),
        IS_ADVANCE_CLAIM
      )
    }).to.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date in the future for an advance claims', function () {
    var pastDate = dateFormatter.now().add(-1)
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        pastDate.date(),
        pastDate.month() + 1,
        pastDate.year(),
        VALID_CHILD_VISITOR,
        false,
        IS_ADVANCE_CLAIM
      )
    }).to.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date less than 5 days away for an advance claims', function () {
    var futureDate = dateFormatter.now().add(4, 'days')
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        futureDate.date(),
        futureDate.month() + 1,
        futureDate.year(),
        VALID_CHILD_VISITOR,
        false,
        IS_ADVANCE_CLAIM
      )
    }).to.throw(ValidationError)
  })
})
<commit_msg>APVS0130: Fixing unit tests that fail when server is using BST rather than GMT<commit_after>/* eslint-disable no-new */
const NewClaim = require('../../../../app/services/domain/new-claim')
const ValidationError = require('../../../../app/services/errors/validation-error')
const dateFormatter = require('../../../../app/services/date-formatter')
const booleanSelectEnum = require('../../../../app/constants/boolean-select-enum')
const expect = require('chai').expect

var claim

describe('services/domain/new-claim', function () {
  const VALID_REFERENCE = 'APVS123'
  const VALID_DAY = dateFormatter.now().date()
  const VALID_MONTH = dateFormatter.now().month() + 1 // Needed for zero indexed month
  const VALID_YEAR = dateFormatter.now().year()
  const VALID_CHILD_VISITOR = booleanSelectEnum.YES
  const IS_PAST_CLAIM = false
  const IS_ADVANCE_CLAIM = true

  var expectedDateOfJourney = dateFormatter.build(VALID_DAY, VALID_MONTH, VALID_YEAR)

  it('should construct a domain object given valid input', function () {
    claim = new NewClaim(
      VALID_REFERENCE,
      VALID_DAY,
      VALID_MONTH,
      VALID_YEAR,
      IS_PAST_CLAIM
    )
    expect(claim.reference).to.equal(VALID_REFERENCE)
    expect(claim.dateOfJourney).to.be.within(
      expectedDateOfJourney.subtract(1, 'seconds').toDate(),
      expectedDateOfJourney.add(1, 'seconds').toDate()
    )
    expect(claim.isAdvanceClaim).to.equal(IS_PAST_CLAIM)
  })

  it('should throw ValidationError if given invalid input', function () {
    expect(function () {
      new NewClaim('', '', '', '', false, IS_PAST_CLAIM)
    }).to.throw(ValidationError)
  })

  it('should not throw a ValidationError if is repeat duplicate claim', function () {
    expect(function () {
      claim = new NewClaim(VALID_REFERENCE, VALID_DAY, VALID_MONTH, VALID_YEAR, '', true, IS_PAST_CLAIM)
    }).to.not.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date in the future for past claims', function () {
    var futureDate = dateFormatter.now().add(1, 'days')
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        futureDate.date(),
        futureDate.month() + 1,
        futureDate.year(),
        IS_PAST_CLAIM
      )
    }).to.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date more than 60 days away for a past claim', function () {
    var dateFurtherThan60Days = dateFormatter.now().subtract(62, 'days') // 62 rather than 61 as locally fails in BST, server runs GMT
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        dateFurtherThan60Days.date(),
        dateFurtherThan60Days.month() + 1,
        dateFurtherThan60Days.year(),
        IS_PAST_CLAIM
      )
    }).to.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date more than 60 days away for an advance claim', function () {
    var dateFurtherThan60Days = dateFormatter.now().add(62, 'days') // 62 rather than 61 as locally fails in BST, server runs GMT
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        dateFurtherThan60Days.date(),
        dateFurtherThan60Days.month() + 1,
        dateFurtherThan60Days.year(),
        IS_ADVANCE_CLAIM
      )
    }).to.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date in the future for an advance claims', function () {
    var pastDate = dateFormatter.now().add(-1)
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        pastDate.date(),
        pastDate.month() + 1,
        pastDate.year(),
        VALID_CHILD_VISITOR,
        false,
        IS_ADVANCE_CLAIM
      )
    }).to.throw(ValidationError)
  })

  it('should throw a ValidationError if given a date less than 5 days away for an advance claims', function () {
    var futureDate = dateFormatter.now().add(4, 'days')
    expect(function () {
      new NewClaim(
        VALID_REFERENCE,
        futureDate.date(),
        futureDate.month() + 1,
        futureDate.year(),
        VALID_CHILD_VISITOR,
        false,
        IS_ADVANCE_CLAIM
      )
    }).to.throw(ValidationError)
  })
})
<|endoftext|>


<commit_before>(function(factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        factory(require('jquery'));
    } else {
        factory(jQuery);
    }
}(function($) {

    var defaults = {
            show_top: true,
            show_bottom: true,
            item_top: null,
            item_bottom: null,
            align: 'bottom right',
            navigation: [],
            margin: 100,
            speed: 1000,
            onBeforeMove: function(){},
            onAfterMove: function(){},
            onBeforeGoTop: function(){},
            onAfterGoTop: function(){},
            onBeforeGoBottom: function(){},
            onAfterGoBottom: function(){},
            onBeforeGoSection: function(){},
            onAfterGoSection: function(){}
        },
        settings = {},
        $doc = $(document),
        $win = $(window),
        $div = $('<div>'),
        top_link,
        bottom_link;

    $.elevator = function(options) {

        settings = $.extend({}, defaults, options);

        function scrollTo(target,callback_before,callback_after) {

            settings.onBeforeMove.call(this);

            if (typeof callback_before === 'function') {
                callback_before.call(this);
            }

            $.when($('html,body').animate({
                scrollTop: target
            }, {
                duration: settings.speed
            })).then(function(){
                if (typeof callback_after === 'function') {
                    callback_after.call(this);
                }
                settings.onAfterMove.call(this);
            });

        }

        function getDocHeight() {
            return $doc.height();
        }

        function createTopLink() {

            var classes = 'jq-top jq-mid',
                anchor = '#',
                title = 'Go to Top',
                item_top = settings.item_top;

            if(item_top && typeof(item_top) == 'object'){
                item_top.attr('id') ? item_top.attr('id') : item_top.attr('id','jq-TOP');
                anchor = '#' + item_top.attr('id');
                title = item_top.attr('title') ? item_top.attr('title') : item_top.attr('data-title');
            }

            top_link = $('<a>')
                .addClass(classes)
                .attr('href', anchor)
                .attr('title', title)
                .html('▲');

            top_link.on('click.' + classes, function(e) {

                var pos = 0;

                if(item_top && typeof(item_top) == 'object') {
                    pos = item_top.offset().top;
                }
                else {
                    pos = 0;
                }

                scrollTo(pos,settings.onBeforeGoTop,settings.onAfterGoTop);

                e.preventDefault();

            });

            $div.append(top_link);

        }

        function createNavigationLinks() {

            var classes = 'jq-item jq-sml',
                anchor = '#',
                title = '',
                navigation = settings.navigation;

            $.each(navigation, function(key, val){

                $(val).attr('id') ? $(val).attr('id') : $(val).attr('id','jq-' + parseInt($(val).offset().top));
                anchor = '#' + $(val).attr('id');

                title = $(val).attr('title') ? $(val).attr('title') : $(val).attr('data-title');

                var item_link = $('<a>')
                    .addClass(classes)
                    .attr('href', anchor)
                    .attr('title', title)
                    .html('&nbsp');

                $div.append(item_link);

            });

            $(document).on('click', '.jq-item', function(e) {

                var _item = $($(this).attr('href'));

                scrollTo(_item.offset().top,settings.onBeforeGoSection,settings.onAfterGoSection);

                e.preventDefault();

            });

        }

        function createBottomLink() {

            var classes = 'jq-bottom jq-mid',
                anchor = '#',
                title = 'Go to Bottom',
                item_bottom = settings.item_bottom;

            if(item_bottom && typeof(item_bottom) == 'object'){
                item_bottom.attr('id') ? item_bottom.attr('id') : item_bottom.attr('id','jq-BOTTOM');
                anchor = '#' + item_bottom.attr('id');
                title = item_bottom.attr('title') ? item_bottom.attr('title') : item_bottom.attr('data-title');
            }

            bottom_link = $('<a>')
                .addClass(classes)
                .attr('href', anchor)
                .attr('title', title)
                .html('▼');

            bottom_link.on('click.' + classes, function(e) {

                var pos = 0;

                if(item_bottom && typeof(item_bottom) == 'object') {
                    pos = item_bottom.offset().top + (item_bottom.outerHeight(true) - $win.height());
                }
                else {
                    pos = getDocHeight();
                }

                scrollTo(pos,settings.onBeforeGoBottom,settings.onAfterGoBottom);

                e.preventDefault();

            });

            $div.append(bottom_link);

        }

        function atTop() {

            var item_top = settings.item_top,
                ret = null;

            if(item_top && typeof(item_top) == 'object'){
                ret = $win.scrollTop() <= item_top.offset().top + settings.margin;
            }
            else {
                ret = $win.scrollTop() <= settings.margin;
            }

            return ret;
        }

        function atBottom() {

            var item_bottom = settings.item_bottom,
                ret = null;

            if(item_bottom && typeof(item_bottom) == 'object'){
                ret = $win.scrollTop() >= item_bottom.offset().top - $win.height() - settings.margin;
            }
            else {
                ret = $win.scrollTop() + $win.height() >= getDocHeight() - settings.margin;
            }

            return ret;

        }

        function setAlign() {

            var positions = settings.align.split(' ');

            if (positions.indexOf('top') >= 0) {
                $div.addClass('align-top');
            }

            if (positions.indexOf('bottom') >= 0) {
                $div.addClass('align-bottom');
            }

            if (positions.indexOf('left') >= 0) {
                $div.addClass('align-left');
            }

            if (positions.indexOf('right') >= 0) {
                $div.addClass('align-right');
            }

        }

        function setShape() {

            var shape = settings.shape;

            switch (shape) {
                case 'square':
                    $div.addClass('square');
                    break;
                case 'rounded':
                    $div.addClass('rounded');
                    break;
                case 'circle':
                    $div.addClass('circle');
                    break;
                default:
                    $div.addClass('circle');
            }

        }

        function init() {

            $div.addClass('jq-elevator');

            setAlign();
            setShape();

            if (settings.show_top) {
                createTopLink();
            }

            if (settings.navigation.length > 0) {
                createNavigationLinks();
            }

            if (settings.show_bottom) {
                createBottomLink();
            }

            if (atTop()) {
                settings.show_top ? top_link.removeClass('jq-mid').addClass('jq-sml') : false;
                settings.show_bottom ? bottom_link.removeClass('jq-mid').addClass('jq-big') : false;
            }
            else if (atBottom()) {
                settings.show_top ? top_link.removeClass('jq-mid').addClass('jq-big') : false;
                settings.show_bottom ? bottom_link.removeClass('jq-mid').addClass('jq-sml') : false;
            }

            $doc.scroll(function() {

                if (atTop()) {
                    settings.show_top ? top_link.removeClass('jq-mid').addClass('jq-sml') : false;
                    settings.show_bottom ? bottom_link.removeClass('jq-mid').addClass('jq-big') : false;
                }
                else if (atBottom()) {
                    settings.show_top ? top_link.removeClass('jq-mid').addClass('jq-big') : false;
                    settings.show_bottom ? bottom_link.removeClass('jq-mid').addClass('jq-sml') : false;
                }
                else {
                    settings.show_top ? top_link.removeClass('jq-big jq-sml').addClass('jq-mid') : false;
                    settings.show_bottom ? bottom_link.removeClass('jq-big jq-sml').addClass('jq-mid') : false;
                }
            });

            $('body').append($div);

        }

        init();

    }

}));<commit_msg>Updated jQuery-Elevator - Updated callbacks - Updated Cross Browser Capability<commit_after>(function(factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        factory(require('jquery'));
    } else {
        factory(jQuery);
    }
}(function($) {

    var defaults = {
            show_top: true,
            show_bottom: true,
            item_top: null,
            item_bottom: null,
            align: 'bottom right',
            navigation: [],
            margin: 100,
            speed: 1000,
            onBeforeMove: function(){},
            onAfterMove: function(){},
            onBeforeGoTop: function(){},
            onAfterGoTop: function(){},
            onBeforeGoBottom: function(){},
            onAfterGoBottom: function(){},
            onBeforeGoSection: function(){},
            onAfterGoSection: function(){}
        },
        settings = {},
        $doc = $(document),
        $win = $(window),
        $div = $('<div>'),
        top_link,
        bottom_link;

    $.elevator = function(options) {

        settings = $.extend({}, defaults, options);

        function scrollTo(target,callback_before,callback_after) {

            settings.onBeforeMove.call();

            if (typeof callback_before === 'function') {
                callback_before.call();
            }

            $.when($('html,body').animate({
                scrollTop: target
            }, {
                duration: settings.speed,
            })).then(function(){
                if (typeof callback_after === 'function') {
                    callback_after.call();
                }
                settings.onAfterMove.call();
            });

        }

        function getDocHeight() {
            return $doc.height();
        }

        function createTopLink() {

            var classes = 'jq-top jq-mid',
                anchor = '#',
                title = 'Go to Top',
                item_top = settings.item_top;

            if(item_top && typeof(item_top) == 'object'){
                item_top.attr('id') ? item_top.attr('id') : item_top.attr('id','jq-TOP');
                anchor = '#' + item_top.attr('id');
                title = item_top.attr('title') ? item_top.attr('title') : item_top.attr('data-title');
            }

            top_link = $('<a>')
                .addClass(classes)
                .attr('href', anchor)
                .attr('title', title)
                .html('▲');

            top_link.on('click.' + classes, function(e) {

                var pos = 0;

                if(item_top && typeof(item_top) == 'object') {
                    pos = item_top.offset().top;
                }
                else {
                    pos = 0;
                }

                scrollTo(pos,settings.onBeforeGoTop,settings.onAfterGoTop);

                e.preventDefault();

            });

            $div.append(top_link);

        }

        function createNavigationLinks() {

            var classes = 'jq-item jq-sml',
                anchor = '#',
                title = '',
                navigation = settings.navigation;

            $.each(navigation, function(key, val){

                $(val).attr('id') ? $(val).attr('id') : $(val).attr('id','jq-' + parseInt($(val).offset().top));
                anchor = '#' + $(val).attr('id');

                title = $(val).attr('title') ? $(val).attr('title') : $(val).attr('data-title');

                var item_link = $('<a>')
                    .addClass(classes)
                    .attr('href', anchor)
                    .attr('title', title)
                    .html('&nbsp');

                $div.append(item_link);

            });

            $(document).on('click', '.jq-item', function(e) {

                var _item = $($(this).attr('href'));

                scrollTo(_item.offset().top,settings.onBeforeGoSection,settings.onAfterGoSection);

                e.preventDefault();

            });

        }

        function createBottomLink() {

            var classes = 'jq-bottom jq-mid',
                anchor = '#',
                title = 'Go to Bottom',
                item_bottom = settings.item_bottom;

            if(item_bottom && typeof(item_bottom) == 'object'){
                item_bottom.attr('id') ? item_bottom.attr('id') : item_bottom.attr('id','jq-BOTTOM');
                anchor = '#' + item_bottom.attr('id');
                title = item_bottom.attr('title') ? item_bottom.attr('title') : item_bottom.attr('data-title');
            }

            bottom_link = $('<a>')
                .addClass(classes)
                .attr('href', anchor)
                .attr('title', title)
                .html('▼');

            bottom_link.on('click.' + classes, function(e) {

                var pos = 0;

                if(item_bottom && typeof(item_bottom) == 'object') {
                    pos = item_bottom.offset().top + (item_bottom.outerHeight(true) - $win.height());
                }
                else {
                    pos = getDocHeight();
                }

                scrollTo(pos,settings.onBeforeGoBottom,settings.onAfterGoBottom);

                e.preventDefault();

            });

            $div.append(bottom_link);

        }

        function atTop() {

            var item_top = settings.item_top,
                ret = null;

            if(item_top && typeof(item_top) == 'object'){
                ret = $win.scrollTop() <= item_top.offset().top + settings.margin;
            }
            else {
                ret = $win.scrollTop() <= settings.margin;
            }

            return ret;
        }

        function atBottom() {

            var item_bottom = settings.item_bottom,
                ret = null;

            if(item_bottom && typeof(item_bottom) == 'object'){
                ret = $win.scrollTop() >= item_bottom.offset().top - $win.height() - settings.margin;
            }
            else {
                ret = $win.scrollTop() + $win.height() >= getDocHeight() - settings.margin;
            }

            return ret;

        }

        function setAlign() {

            var positions = settings.align.split(' ');

            if (positions.indexOf('top') >= 0) {
                $div.addClass('align-top');
            }

            if (positions.indexOf('bottom') >= 0) {
                $div.addClass('align-bottom');
            }

            if (positions.indexOf('left') >= 0) {
                $div.addClass('align-left');
            }

            if (positions.indexOf('right') >= 0) {
                $div.addClass('align-right');
            }

        }

        function setShape() {

            var shape = settings.shape;

            switch (shape) {
                case 'square':
                    $div.addClass('square');
                    break;
                case 'rounded':
                    $div.addClass('rounded');
                    break;
                case 'circle':
                    $div.addClass('circle');
                    break;
                default:
                    $div.addClass('circle');
            }

        }

        function init() {

            $div.addClass('jq-elevator');

            setAlign();
            setShape();

            if (settings.show_top) {
                createTopLink();
            }

            if (settings.navigation.length > 0) {
                createNavigationLinks();
            }

            if (settings.show_bottom) {
                createBottomLink();
            }

            if (atTop()) {
                settings.show_top ? top_link.removeClass('jq-mid').addClass('jq-sml') : false;
                settings.show_bottom ? bottom_link.removeClass('jq-mid').addClass('jq-big') : false;
            }
            else if (atBottom()) {
                settings.show_top ? top_link.removeClass('jq-mid').addClass('jq-big') : false;
                settings.show_bottom ? bottom_link.removeClass('jq-mid').addClass('jq-sml') : false;
            }

            $doc.scroll(function() {

                if (atTop()) {
                    settings.show_top ? top_link.removeClass('jq-mid').addClass('jq-sml') : false;
                    settings.show_bottom ? bottom_link.removeClass('jq-mid').addClass('jq-big') : false;
                }
                else if (atBottom()) {
                    settings.show_top ? top_link.removeClass('jq-mid').addClass('jq-big') : false;
                    settings.show_bottom ? bottom_link.removeClass('jq-mid').addClass('jq-sml') : false;
                }
                else {
                    settings.show_top ? top_link.removeClass('jq-big jq-sml').addClass('jq-mid') : false;
                    settings.show_bottom ? bottom_link.removeClass('jq-big jq-sml').addClass('jq-mid') : false;
                }
            });

            $('body').append($div);

        }

        init();

    }

}));<|endoftext|>


<commit_before>var should = require('should');

var getCollidingVertices = require('../../lib/utilities/getCollidingVertices');
var getCollidingVerticesSlowly = require('./getCollidingVerticesSlowly');
var Vertex = require('../../lib/model/vertex');
var VertexStyles = require('../../lib/styles/vertexStyles');

var nextId = 0;
// use this style for all tests for simplicity
var style = new VertexStyles({
  width: 200,
  height: 100
});

var createVertex = function(x, y) {
  return new Vertex({
    id: String(nextId),
    globalId: String(nextId++),
    position: {
      x: x,
      y: y
    },
    styles: style
  });
};

// Compare two Map<Any, Set>s
var compareAnswers = function(actual, expected) {
  actual.size.should.equal(expected.size);
  expected.forEach(function(expectedSet, key) {
    actual.has(key).should.be.true;
    var actualSet = actual.get(key);
    actualSet.size.should.equal(expectedSet.size);
    expectedSet.forEach(function(a) {
      actualSet.has(a).should.be.true;
    });
  });
};

/**
 * Generate a lot of vertices
 * @method generateVertices
 * @param  {Number} canvasSize width and height of square canvas
 * @param  {Number} n how many vertices
 * @return {Array} your vertices
 */
var generateVertices = function(canvasSize, n) {
  var vertices = new Array(n);
  for (var i = 0; i < n; i++) {
    vertices.push(createVertex(Math.floor(Math.random() * canvasSize), Math.floor(Math.random() * canvasSize)));
  }
  return vertices;
};

describe('getCollidingVerticesSlowly', function() {
  // Testing the function to test against.
  it('should work with a simple manual test case', function() {
    var vertices = [
      createVertex(-200, 0), // overlaps with 2
      createVertex(1, 0),
      createVertex(-399, 99), //overlaps with 0
      createVertex(1, 101), // overlaps with 4
      createVertex(1, 100) // overlaps with 3
    ];

    var answerKey = new Map();
    answerKey.set(vertices[0], new Set([vertices[2]]));
    answerKey.set(vertices[1], new Set());
    answerKey.set(vertices[2], new Set([vertices[0]]));
    answerKey.set(vertices[3], new Set([vertices[4]]));
    answerKey.set(vertices[4], new Set([vertices[3]]));

    var funcResult = getCollidingVerticesSlowly(vertices);

    compareAnswers(funcResult, answerKey);

  });
});
describe('getCollidingVertices', function() {
  it('should work with a simple manual test case', function() {
    var vertices = [
      createVertex(-200, 0), // overlaps with 2
      createVertex(1, 0),
      createVertex(-399, 99), //overlaps with 0
      createVertex(1, 101), // overlaps with 4
      createVertex(1, 100) // overlaps with 3
    ];

    var answerKey = new Map();
    answerKey.set(vertices[0], new Set([vertices[2]]));
    answerKey.set(vertices[1], new Set());
    answerKey.set(vertices[2], new Set([vertices[0]]));
    answerKey.set(vertices[3], new Set([vertices[4]]));
    answerKey.set(vertices[4], new Set([vertices[3]]));

    var funcResult = getCollidingVertices(vertices);

    compareAnswers(funcResult, answerKey);
  });

  it('should be idential to the simple algorithm with a large number of random vertices', function(done) {
    this.timeout(5000);
    var vertices = generateVertices(5000, 300);
    // var t = Date.now();
    var fastResult = getCollidingVertices(vertices);
    // tFast = Date.now() - t;
    // t = Date.now();
    var slowResult = getCollidingVerticesSlowly(vertices);
    // var tSlow = Date.now() - t;
    // console.log('' + Math.round((tFast / tSlow) * 100) + '% time of slow algorithm');
    compareAnswers(fastResult, slowResult);
    done();
  });
});<commit_msg>clean up<commit_after>var should = require('should');

var getCollidingVertices = require('../../lib/utilities/getCollidingVertices');
var getCollidingVerticesSlowly = require('./getCollidingVerticesSlowly');
var Vertex = require('../../lib/model/vertex');
var VertexStyles = require('../../lib/styles/vertexStyles');

var nextId = 0;
// use this style for all tests for simplicity
var style = new VertexStyles({
  width: 200,
  height: 100
});

var createVertex = function(x, y) {
  return new Vertex({
    id: String(nextId),
    globalId: String(nextId++),
    position: {
      x: x,
      y: y
    },
    styles: style
  });
};

// Compare two Map<Any, Set>s
var compareAnswers = function(actual, expected) {
  actual.size.should.equal(expected.size);
  expected.forEach(function(expectedSet, key) {
    actual.has(key).should.be.true;
    var actualSet = actual.get(key);
    actualSet.size.should.equal(expectedSet.size);
    expectedSet.forEach(function(a) {
      actualSet.has(a).should.be.true;
    });
  });
};

/**
 * Generate a lot of vertices
 * @method generateVertices
 * @param  {Number} canvasSize width and height of square canvas
 * @param  {Number} n how many vertices
 * @return {Array} your vertices
 */
var generateVertices = function(canvasSize, n) {
  var vertices = new Array(n);
  for (var i = 0; i < n; i++) {
    vertices.push(createVertex(Math.floor(Math.random() * canvasSize), Math.floor(Math.random() * canvasSize)));
  }
  return vertices;
};

describe('getCollidingVerticesSlowly', function() {
  // Testing the function to test against.
  it('should work with a simple manual test case', function() {
    var vertices = [
      createVertex(-200, 0), // overlaps with 2
      createVertex(1, 0),
      createVertex(-399, 99), //overlaps with 0
      createVertex(1, 101), // overlaps with 4
      createVertex(1, 100) // overlaps with 3
    ];

    var answerKey = new Map();
    answerKey.set(vertices[0], new Set([vertices[2]]));
    answerKey.set(vertices[1], new Set());
    answerKey.set(vertices[2], new Set([vertices[0]]));
    answerKey.set(vertices[3], new Set([vertices[4]]));
    answerKey.set(vertices[4], new Set([vertices[3]]));

    var funcResult = getCollidingVerticesSlowly(vertices);

    compareAnswers(funcResult, answerKey);

  });
});
describe('getCollidingVertices', function() {
  it('should work with a simple manual test case', function() {
    var vertices = [
      createVertex(-200, 0), // overlaps with 2
      createVertex(1, 0),
      createVertex(-399, 99), //overlaps with 0
      createVertex(1, 101), // overlaps with 4
      createVertex(1, 100) // overlaps with 3
    ];

    var answerKey = new Map();
    answerKey.set(vertices[0], new Set([vertices[2]]));
    answerKey.set(vertices[1], new Set());
    answerKey.set(vertices[2], new Set([vertices[0]]));
    answerKey.set(vertices[3], new Set([vertices[4]]));
    answerKey.set(vertices[4], new Set([vertices[3]]));

    var funcResult = getCollidingVertices(vertices);

    compareAnswers(funcResult, answerKey);
  });

  it('should be idential to the simple algorithm with a large number of random vertices', function(done) {
    this.timeout(5000);
    var vertices = generateVertices(5000, 300);
    // var t = Date.now();
    var fastResult = getCollidingVertices(vertices);
    // tFast = Date.now() - t;
    // t = Date.now();
    var slowResult = getCollidingVerticesSlowly(vertices);
    // var tSlow = Date.now() - t;
    // console.log('' + Math.round((tFast / tSlow) * 100) + '% time of slow algorithm');
    compareAnswers(fastResult, slowResult);
    done();
  });
});
<|endoftext|>


<commit_before>/*
* File:		jquery.loadJSON.js
* Version:	1.2.5.
* Author:	Jovan Popovic
*
* Copyright 2011 Jovan Popovic, all rights reserved.
*
* This source file is free software, under either the GPL v2 license or a
* BSD style license, as supplied with this software.
*
* This source file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* This file contains implementation of the JQuery templating engine that load JSON
* objects into the HTML code. It is based on Alexandre Caprais notemplate plugin
* with several enchancements that are added to this plugin.
*/

(function ($) {
	$.fn.loadJSON = function (obj, options) {
		function refreshMobileSelect(element) {
			try {
				if ($.isFunction($(element).selectmenu)) {
					$(element).selectmenu('refresh'); //used in the JQuery mobile
				}

			} catch (ex) {
				try {
					//$(element).selectmenu();//This will create duplicate select menu!!!!!
					//$(element).selectmenu('refresh');
				} catch (ex) { }
			}
		}

		function refreshMobileCheckBox(element) {
			try {
				if ($.isFunction($(element).checkboxradio)) {
					$(element).checkboxradio('refresh'); //used in the JQuery mobile
				}
			} catch (ex) { }
		}

		function loadSelect(element, aoValues, name) {
			///
			///Load options into the select list
			///
			///<param name="element" type="JQuery:select">Select list</param>
			///<param name="aoValues" type="Array{value,text,selected}">Array of object containin the options</param>
			///<param name="name" type="String">Name of the select list</param>

			var arr = jQuery.makeArray(element);
			var template = $(arr[arr.length - 1]).clone(true);
			//how many duplicate
			var nbToCreate = obj.length;
			var i = 0;
			//fill started by last
			i = obj.length - 1;
			var iCreate = 0;
			for (iCreate = 0; iCreate < nbToCreate; iCreate++) {
				//duplicate the last
				var last = template.clone(true).insertAfter(arr[arr.length - 1]);
				//setElementValue(last, obj[i], name);
				$(last).attr("value", obj[i].value);
				$(last).text(obj[i].text);
				if (obj[i].selected)
					$(last).attr("selected", true);
				i--;
			}

			///////////////////////////////////////////////////////////////////////////////////////////
			refreshMobileSelect(element);
			//////////////////////////////////////////////////////////////////////////////////////////
		}

		function setElementValue(element, value, name) {
			var type = element.type || element.tagName;
			if (type === null) {
				type = element[0].type || element[0].tagName; //select returns undefined if called directly
				if (type === null) {
					return;
				}
			}
			type = type.toLowerCase();
			switch (type) {
				case 'radio':
					if (value.toString().toLowerCase() == element.value.toLowerCase()) {
						$(element).prop('checked', true);
					} else {
						$(element).removeAttr('checked');
					}
					refreshMobileCheckBox(element);
					break;

				case 'checkbox':
					if (value) {
						$(element).prop('checked', true);
					} else {
						$(element).removeAttr('checked');
					}
					refreshMobileCheckBox(element);
					break;

				case 'option':
					$(element).attr("value", value.value);
					$(element).text(value.text);
					if (value.selected) {
						$(element).attr("selected", true);
					}
					break;

				case 'select-multiple':
					//This is "interesting". In mobile use element.options while in the desktop use element[0].options
					var select = element[0];
					if (element[0].options === null || typeof (element[0].options) == "undefined") {
						select = element;
					}

					if (select.options.length > 1) {
						//If select list is not empty use values array to select optionses
						var values = value.constructor == Array ? value : [value];
						//replaced element with element[0] ???? because now it reports that element.optons does not exists
						for (var i = 0; i < select.options.length; i++) {
							for (var j = 0; j < values.length; j++) {
								select.options[i].selected |= select.options[i].value == values[j];
							}
						}
						refreshMobileSelect(element);

					} else {
						//ELSE: Instead of selecting values use values array to populate select list
						loadSelect(element, value, name);
					}
					break;

				case 'select':
				case 'select-one':
					if (typeof value == "string") {
						$(element).attr("value", value);
						refreshMobileSelect(element);

					} else {
						loadSelect(element, value, name);
					}
					break;

				case 'text':
				case 'hidden':
				case 'email':
				case 'url':
				case 'date':
				case 'datetime':
				case 'time':
				case 'number':
				case 'color':
					$(element).val(value);
					break;

				case 'a':
					var href = $(element).attr("href");
					var iPosition = href.indexOf('#');

					if (iPosition > 1000000) {
						href = href.substr(0, iPosition) + '&' + name + '=' + value + href.substr(iPosition);
					} else {
						iPosition = href.indexOf('?');
						if (iPosition > 0) // if parameters in the URL exists add new pair using &
							href += '&' + name + '=' + value;
						else//otherwise attach pair to URL
							href = href + '?' + name + '=' + value;
					}
					$(element).attr("href", href);
					break;

				case 'img':

					if (obj.constructor == "String") {
						//Assumption is that value is in the HREF$ALT format
						var iPosition = value.indexOf('$');
						var src = "";
						var alt = "";
						if (iPosition > 0) {
							src = value.substring(0, iPosition);
							alt = value.substring(iPosition + 1);

						} else {
							src = value;
							var iPositionStart = value.lastIndexOf('/') + 1;
							var iPositionEnd = value.indexOf('.');
							alt = value.substring(iPositionStart, iPositionEnd);
						}
						$(element).attr("src", src);
						$(element).attr("alt", alt);

					} else {
						$(element).attr("src", obj.src);
						$(element).attr("alt", obj.alt);
						$(element).attr("title", obj.title);
					}
					break;

				case 'textarea':
				case 'submit':
				case 'button':
				default:
					try {
						$(element).html(value.toString());
					} catch (exc) { }
			}

		}

		function browseJSON(obj, element, name) {
			// no object
			if (obj === undefined) {
				// Do nothing

			// branch
			} else if (obj.constructor == Object) {
				if (element.length >= 1 && element[0].tagName == "OPTION") {
					setElementValue(element[0], obj, name);
				}

				for (var prop in obj) {
					if (prop === null || typeof prop == "undefined")
						continue;
					else {
						//Find an element with class, id, name, or rel attribute that matches the propertu name
						var child = jQuery.makeArray(jQuery("." + prop, element)).length > 0 ? jQuery("." + prop, element) :
													jQuery("#" + prop, element).length > 0 ? jQuery("#" + prop, element) :
													jQuery('[name="' + prop + '"]', element).length > 0 ? jQuery('[name="' + prop + '"]', element) :
													jQuery('[rel="' + prop + '"]');
						if (child.length != 0) {
							browseJSON(obj[prop], jQuery(child, element), prop);
						}
					}
				}

			// array
			} else if (obj.constructor == Array) {
				if (element.length == 1 &&
						(element.type == "select" || element.type == "select-one" || element.type == "select-multiple" ||
						element[0].type == "select" || element[0].type == "select-one" || element[0].type == "select-multiple"
					)) {

					///nova dva reda
					setElementValue(element, obj, name);
					return;

				} else {
					var arrayElements = $(element).children("[rel]");
					if (arrayElements.length > 0) {					//if there are rel=[index] elements populate them instead of iteration
						arrayElements.each(function () {
							var rel = $(this).attr("rel");
							browseJSON(obj[rel], $(this), name);
						});

					} else {										//recursive iteration
						var arr = jQuery.makeArray(element);
						var template = $(arr[arr.length - 1]).clone(true);
						var nbToCreate = obj.length;				//how many duplicate
						var i = 0;
						if (element[0] === null || (element[0] !== null && element[0].tagName != "OPTION")) {
							var iExist = 0;
							for (iExist = 0; iExist < arr.length; iExist++) {
								if (i < obj.length) {
									var elem = $(element).eq(iExist);
									browseJSON(obj[i], elem, name);
								}
								i++;
							}
							nbToCreate = obj.length - arr.length;
						}
						//fill started by last
						i = obj.length - 1;
						var iCreate = 0;
						for (iCreate = 0; iCreate < nbToCreate; iCreate++) {
							//duplicate the last
							var last = template.clone(true).insertAfter(arr[arr.length - 1]);
							browseJSON(obj[i], last, name);
							i--;
						}
					}
				}

			// data only
			} else {
				var value = obj;
				var type;
				if (element.length > 0) {
					var i = 0;
					for (i = 0; i < element.length; i++) {
						setElementValue(element[i], obj, name);
					}

				} else {
					setElementValue(element, obj, name);
				}
			}
		} //function browseJSON end

		function init(placeholder) {
			var template;

			if (placeholder.data("loadJSON-template") !== null && placeholder.data("loadJSON-template") != "") {
				template = placeholder.data("loadJSON-template");
				placeholder.html(template);
			} else {
				template = placeholder.html();
				placeholder.data("loadJSON-template", template);
			}
		}

		var defaults = {
			onLoading: function () { },
			onLoaded: function () { },
			mobile: false
		};

		properties = $.extend(defaults, options);

		return this.each(function () {
			if (obj.constructor == String) {
				if (obj.charAt(0) == '{' || obj.charAt(0) == '[') {
					var data = $.parseJSON(obj);
					init($(this));
					properties.onLoading();
					browseJSON(data, this);
					properties.onLoaded();
				}
				else {
					var element = $(this);
					$.ajax({ url: obj,
						success: function (data) {
							element.loadJSON(data, properties);
						},
						cache: false,
						dataType: "json"
					});
				}
			}

			else {
				init($(this));
				properties.onLoading();
				browseJSON(obj, this);
				properties.onLoaded();
			}
		});
	};
})(jQuery);<commit_msg>Only adds options to select if value is an array, otherwise uses $.val()<commit_after>/*
* File:		jquery.loadJSON.js
* Version:	1.2.5.
* Author:	Jovan Popovic
*
* Copyright 2011 Jovan Popovic, all rights reserved.
*
* This source file is free software, under either the GPL v2 license or a
* BSD style license, as supplied with this software.
*
* This source file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* This file contains implementation of the JQuery templating engine that load JSON
* objects into the HTML code. It is based on Alexandre Caprais notemplate plugin
* with several enchancements that are added to this plugin.
*/

(function ($) {
	$.fn.loadJSON = function (obj, options) {
		function refreshMobileSelect(element) {
			try {
				if ($.isFunction($(element).selectmenu)) {
					$(element).selectmenu('refresh'); //used in the JQuery mobile
				}

			} catch (ex) {
				try {
					//$(element).selectmenu();//This will create duplicate select menu!!!!!
					//$(element).selectmenu('refresh');
				} catch (ex) { }
			}
		}

		function refreshMobileCheckBox(element) {
			try {
				if ($.isFunction($(element).checkboxradio)) {
					$(element).checkboxradio('refresh'); //used in the JQuery mobile
				}
			} catch (ex) { }
		}

		function loadSelect(element, aoValues, name) {
			///
			///Load options into the select list
			///
			///<param name="element" type="JQuery:select">Select list</param>
			///<param name="aoValues" type="Array{value,text,selected}">Array of object containin the options</param>
			///<param name="name" type="String">Name of the select list</param>

			var arr = jQuery.makeArray(element);
			var template = $(arr[arr.length - 1]).clone(true);
			//how many duplicate
			var nbToCreate = obj.length;
			var i = 0;
			//fill started by last
			i = obj.length - 1;
			var iCreate = 0;
			for (iCreate = 0; iCreate < nbToCreate; iCreate++) {
				//duplicate the last
				var last = template.clone(true).insertAfter(arr[arr.length - 1]);
				//setElementValue(last, obj[i], name);
				$(last).attr("value", obj[i].value);
				$(last).text(obj[i].text);
				if (obj[i].selected)
					$(last).attr("selected", true);
				i--;
			}

			///////////////////////////////////////////////////////////////////////////////////////////
			refreshMobileSelect(element);
			//////////////////////////////////////////////////////////////////////////////////////////
		}

		function setElementValue(element, value, name) {
			var type = element.type || element.tagName;
			if (type === null) {
				type = element[0].type || element[0].tagName; //select returns undefined if called directly
				if (type === null) {
					return;
				}
			}
			type = type.toLowerCase();
			switch (type) {
				case 'radio':
					if (value.toString().toLowerCase() == element.value.toLowerCase()) {
						$(element).prop('checked', true);
					} else {
						$(element).removeAttr('checked');
					}
					refreshMobileCheckBox(element);
					break;

				case 'checkbox':
					if (value) {
						$(element).prop('checked', true);
					} else {
						$(element).removeAttr('checked');
					}
					refreshMobileCheckBox(element);
					break;

				case 'option':
					$(element).attr("value", value.value);
					$(element).text(value.text);
					if (value.selected) {
						$(element).attr("selected", true);
					}
					break;

				case 'select-multiple':
					//This is "interesting". In mobile use element.options while in the desktop use element[0].options
					var select = element[0];
					if (element[0].options === null || typeof (element[0].options) == "undefined") {
						select = element;
					}

					if (select.options.length > 1) {
						//If select list is not empty use values array to select optionses
						var values = value.constructor == Array ? value : [value];
						//replaced element with element[0] ???? because now it reports that element.optons does not exists
						for (var i = 0; i < select.options.length; i++) {
							for (var j = 0; j < values.length; j++) {
								select.options[i].selected |= select.options[i].value == values[j];
							}
						}
						refreshMobileSelect(element);

					} else {
						//ELSE: Instead of selecting values use values array to populate select list
						loadSelect(element, value, name);
					}
					break;

				case 'select':
				case 'select-one':
					if (typeof value === "array") {
						loadSelect(element, value, name);

					} else {
						$(element).val(value);
						refreshMobileSelect($element);
					}
					break;

				case 'text':
				case 'hidden':
				case 'email':
				case 'url':
				case 'date':
				case 'datetime':
				case 'time':
				case 'number':
				case 'color':
					$(element).val(value);
					break;

				case 'a':
					var href = $(element).attr("href");
					var iPosition = href.indexOf('#');

					if (iPosition > 1000000) {
						href = href.substr(0, iPosition) + '&' + name + '=' + value + href.substr(iPosition);
					} else {
						iPosition = href.indexOf('?');
						if (iPosition > 0) // if parameters in the URL exists add new pair using &
							href += '&' + name + '=' + value;
						else//otherwise attach pair to URL
							href = href + '?' + name + '=' + value;
					}
					$(element).attr("href", href);
					break;

				case 'img':

					if (obj.constructor == "String") {
						//Assumption is that value is in the HREF$ALT format
						var iPosition = value.indexOf('$');
						var src = "";
						var alt = "";
						if (iPosition > 0) {
							src = value.substring(0, iPosition);
							alt = value.substring(iPosition + 1);

						} else {
							src = value;
							var iPositionStart = value.lastIndexOf('/') + 1;
							var iPositionEnd = value.indexOf('.');
							alt = value.substring(iPositionStart, iPositionEnd);
						}
						$(element).attr("src", src);
						$(element).attr("alt", alt);

					} else {
						$(element).attr("src", obj.src);
						$(element).attr("alt", obj.alt);
						$(element).attr("title", obj.title);
					}
					break;

				case 'textarea':
				case 'submit':
				case 'button':
				default:
					try {
						$(element).html(value.toString());
					} catch (exc) { }
			}

		}

		function browseJSON(obj, element, name) {
			// no object
			if (obj === undefined) {
				// Do nothing

			// branch
			} else if (obj.constructor == Object) {
				if (element.length >= 1 && element[0].tagName == "OPTION") {
					setElementValue(element[0], obj, name);
				}

				for (var prop in obj) {
					if (prop === null || typeof prop == "undefined")
						continue;
					else {
						//Find an element with class, id, name, or rel attribute that matches the propertu name
						var child = jQuery.makeArray(jQuery("." + prop, element)).length > 0 ? jQuery("." + prop, element) :
													jQuery("#" + prop, element).length > 0 ? jQuery("#" + prop, element) :
													jQuery('[name="' + prop + '"]', element).length > 0 ? jQuery('[name="' + prop + '"]', element) :
													jQuery('[rel="' + prop + '"]');
						if (child.length != 0) {
							browseJSON(obj[prop], jQuery(child, element), prop);
						}
					}
				}

			// array
			} else if (obj.constructor == Array) {
				if (element.length == 1 &&
						(element.type == "select" || element.type == "select-one" || element.type == "select-multiple" ||
						element[0].type == "select" || element[0].type == "select-one" || element[0].type == "select-multiple"
					)) {

					///nova dva reda
					setElementValue(element, obj, name);
					return;

				} else {
					var arrayElements = $(element).children("[rel]");
					if (arrayElements.length > 0) {					//if there are rel=[index] elements populate them instead of iteration
						arrayElements.each(function () {
							var rel = $(this).attr("rel");
							browseJSON(obj[rel], $(this), name);
						});

					} else {										//recursive iteration
						var arr = jQuery.makeArray(element);
						var template = $(arr[arr.length - 1]).clone(true);
						var nbToCreate = obj.length;				//how many duplicate
						var i = 0;
						if (element[0] === null || (element[0] !== null && element[0].tagName != "OPTION")) {
							var iExist = 0;
							for (iExist = 0; iExist < arr.length; iExist++) {
								if (i < obj.length) {
									var elem = $(element).eq(iExist);
									browseJSON(obj[i], elem, name);
								}
								i++;
							}
							nbToCreate = obj.length - arr.length;
						}
						//fill started by last
						i = obj.length - 1;
						var iCreate = 0;
						for (iCreate = 0; iCreate < nbToCreate; iCreate++) {
							//duplicate the last
							var last = template.clone(true).insertAfter(arr[arr.length - 1]);
							browseJSON(obj[i], last, name);
							i--;
						}
					}
				}

			// data only
			} else {
				var value = obj;
				var type;
				if (element.length > 0) {
					var i = 0;
					for (i = 0; i < element.length; i++) {
						setElementValue(element[i], obj, name);
					}

				} else {
					setElementValue(element, obj, name);
				}
			}
		} //function browseJSON end

		function init(placeholder) {
			var template;

			if (placeholder.data("loadJSON-template") !== null && placeholder.data("loadJSON-template") != "") {
				template = placeholder.data("loadJSON-template");
				placeholder.html(template);
			} else {
				template = placeholder.html();
				placeholder.data("loadJSON-template", template);
			}
		}

		var defaults = {
			onLoading: function () { },
			onLoaded: function () { },
			mobile: false
		};

		properties = $.extend(defaults, options);

		return this.each(function () {
			if (obj.constructor == String) {
				if (obj.charAt(0) == '{' || obj.charAt(0) == '[') {
					var data = $.parseJSON(obj);
					init($(this));
					properties.onLoading();
					browseJSON(data, this);
					properties.onLoaded();
				}
				else {
					var element = $(this);
					$.ajax({ url: obj,
						success: function (data) {
							element.loadJSON(data, properties);
						},
						cache: false,
						dataType: "json"
					});
				}
			}

			else {
				init($(this));
				properties.onLoading();
				browseJSON(obj, this);
				properties.onLoaded();
			}
		});
	};
})(jQuery);
<|endoftext|>