<commit_before>const sim = "✅";
const nao = "⛔";

module.exports = async (client, message, args) => {
    //let msg = await message.channel.send("Votar");
    let msg = await message.channel.sendMessage(args.join(" "));
    message.delete(5000);
    await msg.react(sim);
    await msg.react(nao);
    const reactions = await msg.awaitReactions(reaction => reaction.emoji.name === sim || reaction.emoji.name === nao, {time: 60000}).then(msg => {
        msg.delete(60000)
      });
    if ((message.member.nickname) !== null){
    message.channel.send(`A votação acabou! \n\n Votação criada por: ${message.member.nickname} \n\n Assunto: ${args.get(msg)} \n\n Resultado: \n\n${sim} Sim = ${reactions.get(sim).count-1}\n\n${nao} Não = ${reactions.get(nao).count-1}`).then(msg => {
        msg.delete(120000)
      }); }
    else if ((message.member.nickname) === null){
    message.channel.send(`A votação acabou! \n\n Votação criada por: ${message.author.username} \n\n Assunto: ${args.get(msg)} \n\n Resultado: \n\n${sim} Sim = ${reactions.get(sim).count-1}\n\n${nao} Não = ${reactions.get(nao).count-1}`).then(msg => {
        msg.delete(120000)
    }); }
};<commit_msg><commit_after>const sim = "✅";
const nao = "⛔";

module.exports = async (client, message, args) => {
    //let msg = await message.channel.send("Votar");
    let msg = await message.channel.sendMessage(args.join(" "));
    message.delete(5000);
    await msg.react(sim);
    await msg.react(nao);
    const reactions = await msg.awaitReactions(reaction => reaction.emoji.name === sim || reaction.emoji.name === nao, {time: 60000}).then(msg => {
        msg.delete(60000)
      });
    if ((message.member.nickname) !== null){
    message.channel.send(`A votação acabou! \n\n Votação criada por: ${message.member.nickname} \n\n Assunto: ${args} \n\n Resultado: \n\n${sim} Sim = ${reactions.get(sim).count-1}\n\n${nao} Não = ${reactions.get(nao).count-1}`).then(msg => {
        msg.delete(120000)
      }); }
    else if ((message.member.nickname) === null){
    message.channel.send(`A votação acabou! \n\n Votação criada por: ${message.author.username} \n\n Assunto: ${args} \n\n Resultado: \n\n${sim} Sim = ${reactions.get(sim).count-1}\n\n${nao} Não = ${reactions.get(nao).count-1}`).then(msg => {
        msg.delete(120000)
    }); }
};<|endoftext|>


<commit_before>// generate and compare a list of files with stat and hash… without using sqlite3
// …while using file streaming with promises
// milestone 1 reached: read dir A and output fname, stat and hashes using promises
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var crypto = require('crypto');

// terminal or console argument handling
/*
if (process.argv.length < 3) {
	console.log("Usage: node nondb.js pathB");
	process.exit(1);
}

var pathB = "";

if (process.argv.length = 4) {
	console.log(process.argv[2]);
	pathB = process.argv.[2];
}
*/
// for now, though, we'll just leave it for testing

var readdirPromise = fs.readdirAsync(".").map(function(fileName) {
	var statPromise = fs.statAsync(fileName);

	return Promise.join(statPromise, fileName, function(statPromise, fileName) {

		if(statPromise.isFile()) {

			function makeStream(file, callback) {
				var result = fs.createReadStream(file);
				return callback(result);
			}

			function process(stream) {
				var hash = crypto.createHash('md5');
				var dig = "";
				return new Promise(function(resolve, reject) {
					stream.on('data', function updateProcess(chunk) {
						hash.update(chunk, 'utf8');
					});
					stream.on('end', resolve);
				}).then(function publish() {
					var digest = hash.digest('hex');
					dig = digest;
					console.log(digest + ": "+ fileName+ " - "+statPromise.size+ " bytes");
					// return digest;
				});
			}

			makeStream(fileName, process);

		} // endif

	});

});
<commit_msg>Update nondb_app.js<commit_after>// generate and compare a list of files with stat and hash… without using sqlite3
// …while using file streaming with promises
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var crypto = require('crypto');
var path = require('path');
// terminal or console argument handling
/*
if (process.argv.length < 3) {
	console.log("Usage: node nondb.js pathB");
	process.exit(1);
}

var pathB = "";

if (process.argv.length = 4) {
	console.log(process.argv[2]);
	pathB = process.argv.[2];
}
*/
// for now, though, we'll just leave it for testing

// find duplicate files with Node.js, cuz, you know, it's useful

var pathA = "."; // folder you're in, wherever that might be
var pathB = "/path/to/the/directory/you/want/to/compare/it/to"; // yes, yes, argv, etc, but I haven't bothered yet, ok!

var hashes = []; // where the magical hashes will be stored - but wait, that's not all, now also with file info!

// I dub this: promise hell! (or possibly this could just be done eons better, but well, it works...)
function hashDirIn(folder) {
	var pathPromiseA = fs.readdirAsync(folder).map(function(fileName) {
		var workPath = path.join(folder, fileName);
		var statPromise = fs.statAsync(workPath);

		return Promise.join(statPromise, fileName, function(statPromise, fileName) {

			if(statPromise.isFile()) {

				function makeStream(file, callback) {
					var result = fs.createReadStream(workPath);
					return callback(result);
				}

				function process(stream) {
					var hash = crypto.createHash('md5');
					return new Promise(function(resolve, reject) {
						stream.on('data', function updateProcess(chunk) {
							hash.update(chunk, 'utf8');
						});
						stream.on('end', resolve);
					}).then(function publish() {
						var digest = hash.digest('hex');
						hashes.push({digest:digest, path:workPath});
					});
				}

				return makeStream(fileName, process);

			} // endif :p

		});

	}).then(function(){
		// sort and display dupes
		if(i==1) {
			hashes.sort(function(a, b) {
				if (a.digest < b.digest) {
					return -1;
				}
				if (a.digest > b.digest) {
					return 1;
				}
				return 0;
			});
			var dupe = 1;
			hashes.map(function(obj, index) {
				// note: currently this won't deal gracefully with more than two equal files at a time, though it will find them all (gotta find them all!)
				if (index-1 >= 0) {
					if(obj.digest == hashes[index-1].digest) {
						console.log("Dupe "+dupe+" found:");
						console.log(obj.path);
						console.log("Equal to:")
						console.log(hashes[index-1].path+"\n");
						dupe++;
					}
				}
			});
		}
		i++; // why do I feel this is cheating?
	});
}
var i = 0;
hashDirIn(pathA);
hashDirIn(pathB);
// but how to check both concurrently instead of one after the other? Ah well, it's late and my bottle of Ileach is soon empty...
<|endoftext|>


<commit_before>const { expect } = require('chai');
const {
	preparePagination,
	lookupSchool,
	deleteNewsHistory,
} = require('./../../../../src/services/news/hooks/news.hooks');

describe('#preparePagination', () => {
	it('should convert the $paginate query parameter from a string to boolean', () => {
		const context = {
			params: {
				query: {
					$paginate: 'true',
				},
			},
		};
		expect(() => preparePagination(context)).not.to.throw(Error);
		expect(preparePagination(context).params.query).to.deep.equal({ $paginate: true });

		context.params.query.$paginate = 'false';
		expect(() => preparePagination(context)).not.to.throw(Error);
		expect(preparePagination(context).params.query).to.deep.equal({ $paginate: false });
	});

	it('should work if no query is given', () => {
		const context = {
			params: {},
		};
		expect(() => preparePagination(context)).not.to.throw(Error);
		expect(preparePagination(context)).to.deep.equal(context);
	});
});
<commit_msg>Test lookupSchool and deleteNewsHistory hooks<commit_after>const { expect } = require('chai');
const { BadRequest } = require('@feathersjs/errors');
const { ObjectId } = require('mongoose').Types;
const app = require('../../../../src/app');
const { createTestUser, cleanup } = require('../../helpers/testObjects')(app);
const { newsHistoryModel } = require('../../../../src/services/news/model');
const {
	preparePagination,
	lookupSchool,
	deleteNewsHistory,
} = require('./../../../../src/services/news/hooks/news.hooks');

describe('news hooks', () => {
	describe('#preparePagination', () => {
		it('should convert the $paginate query parameter from a string to boolean', () => {
			const context = {
				params: {
					query: {
						$paginate: 'true',
					},
				},
			};
			expect(() => preparePagination(context)).not.to.throw(Error);
			expect(preparePagination(context).params.query).to.deep.equal({ $paginate: true });

			context.params.query.$paginate = 'false';
			expect(() => preparePagination(context)).not.to.throw(Error);
			expect(preparePagination(context).params.query).to.deep.equal({ $paginate: false });
		});

		it('should work if no query is given', () => {
			const context = {
				params: {},
			};
			expect(() => preparePagination(context)).not.to.throw(Error);
			expect(preparePagination(context)).to.deep.equal(context);
		});
	});

	describe('#lookupSchool', () => {
		it('should require authentication to provide a user', async () => {
			try {
				await lookupSchool({});
				expect.fail('This call should have failed');
			} catch (err) {
				expect(err).to.be.instanceOf(BadRequest);
			}
			try {
				await lookupSchool({
					params: {
						query: { _id: 42 },
					},
				});
				expect.fail('This call should have failed');
			} catch (err) {
				expect(err).to.be.instanceOf(BadRequest);
			}
		});

		it('should add the logged-in user\' school to the request params', async () => {
			const user = await createTestUser();
			const context = await lookupSchool({
				app,
				params: {
					account: {
						userId: user._id,
					},
				},
			});
			expect(context.params.account.schoolId.toString()).to.equal(user.schoolId.toString());
		});

		after(cleanup);
	});

	describe('#deleteNewsHistory', () => {
		it('should only work if given an id', async () => {
			const context = {
				app,
				params: {
					query: { _id: { $in: [1, 2, 3] } },
				},
			};
			expect(await deleteNewsHistory(context)).to.deep.equal(context);
		});

		it('should remove all newsHistory items referencing the deleted news id', async () => {
			const newsId = new ObjectId();
			await newsHistoryModel.deleteMany({}).exec();
			await newsHistoryModel.create([
				{ title: 'foo', content: 'bar', parentId: newsId },
				{ title: 'baz', content: '420', parentId: newsId },
				{ title: 'test', content: 'bla' },
				{ title: 'title', content: 'content', parentId: new ObjectId() },
			]);

			expect(await newsHistoryModel.count()).to.equal(4);
			await deleteNewsHistory({ id: newsId.toString() });
			expect(await newsHistoryModel.count()).to.equal(2);

			// cleanup
			await newsHistoryModel.deleteMany({}).exec();
		});

		after(cleanup);
	});
});
<|endoftext|>


<commit_before>const assert = require('assert');
const CryptoJS = require('crypto-js');
const { Configuration } = require('@schul-cloud/commons');
const app = require('../../../src/app');
const testObjects = require('../helpers/testObjects')(app);

const storageProviderService = app.service('storageProvider');

describe('storageProvider service', () => {
	let configBefore = {};

	before(() => {
		configBefore = Configuration.toObject(); // deep copy current config
		Configuration.set('S3_KEY', '1234567891234567');
	});

	it('registered the storage provider service', () => {
		assert.ok(storageProviderService);
	});

	it('encrypts the secret correctly', async () => {
		const secret = '123456789';
		const provider = await testObjects.createTestStorageProvider({ secretAccessKey: secret });
		const decrypted = CryptoJS.AES
			.decrypt(provider.secretAccessKey, Configuration.get('S3_KEY'))
			.toString(CryptoJS.enc.Utf8);
		assert.strictEqual(decrypted, secret);
	});

	after(async () => {
		await testObjects.cleanup();
		Configuration.reset(configBefore);
	});
});
<commit_msg>Use expect<commit_after>const { expect } = require('chai');
const CryptoJS = require('crypto-js');
const { Configuration } = require('@schul-cloud/commons');
const app = require('../../../src/app');
const testObjects = require('../helpers/testObjects')(app);

const storageProviderService = app.service('storageProvider');

describe('storageProvider service', () => {
	let configBefore = {};

	before(() => {
		configBefore = Configuration.toObject(); // deep copy current config
		Configuration.set('S3_KEY', '1234567891234567');
	});

	it('registered the storage provider service', () => {
		expect(storageProviderService).to.be.ok;
	});

	it('encrypts the secret correctly', async () => {
		const secret = '123456789';
		const provider = await testObjects.createTestStorageProvider({ secretAccessKey: secret });
		const decrypted = CryptoJS.AES
			.decrypt(provider.secretAccessKey, Configuration.get('S3_KEY'))
			.toString(CryptoJS.enc.Utf8);
		expect(decrypted).to.equal(secret);
	});

	after(async () => {
		await testObjects.cleanup();
		Configuration.reset(configBefore);
	});
});
<|endoftext|>


<commit_before>const zmq = require("../..")
const semver = require("semver")
const weak = require("weak")
const {assert} = require("chai")
const {uniqAddress} = require("./helpers")

for (const proto of ["inproc", "ipc", "tcp"]) {
  describe(`socket with ${proto} curve send/receive`, function() {
    beforeEach(function() {
      const serverKeypair = zmq.curveKeypair()
      const clientKeypair = zmq.curveKeypair()

      this.sockA = new zmq.Pair({
        linger: 0,
        curveServer: true,
        curvePublicKey: serverKeypair.publicKey,
        curveSecretKey: serverKeypair.secretKey,
      })

      this.sockB = new zmq.Pair({
        linger: 0,
        curveServerKey: serverKeypair.publicKey,
        curvePublicKey: clientKeypair.publicKey,
        curveSecretKey: clientKeypair.secretKey,
      })
    })

    afterEach(function() {
      this.sockA.close()
      this.sockB.close()
      gc()
    })

    describe("when connected", function() {
      beforeEach(async function() {
        const address = uniqAddress(proto)
        await this.sockB.bind(address)
        await this.sockA.connect(address)
      })

      it("should deliver single string message", async function() {
        const sent = "foo"
        await this.sockA.send(sent)

        const recv = await this.sockB.receive()
        assert.deepEqual([sent], recv.map(buf => buf.toString()))
      })
    })
  })
}
<commit_msg>Skip curve tests if not available.<commit_after>const zmq = require("../..")
const semver = require("semver")
const weak = require("weak")
const {assert} = require("chai")
const {uniqAddress} = require("./helpers")

for (const proto of ["inproc", "ipc", "tcp"]) {
  describe(`socket with ${proto} curve send/receive`, function() {
    beforeEach(function() {
      if (!zmq.capability.curve) this.skip()

      const serverKeypair = zmq.curveKeypair()
      const clientKeypair = zmq.curveKeypair()

      this.sockA = new zmq.Pair({
        linger: 0,
        curveServer: true,
        curvePublicKey: serverKeypair.publicKey,
        curveSecretKey: serverKeypair.secretKey,
      })

      this.sockB = new zmq.Pair({
        linger: 0,
        curveServerKey: serverKeypair.publicKey,
        curvePublicKey: clientKeypair.publicKey,
        curveSecretKey: clientKeypair.secretKey,
      })
    })

    afterEach(function() {
      this.sockA.close()
      this.sockB.close()
      gc()
    })

    describe("when connected", function() {
      beforeEach(async function() {
        const address = uniqAddress(proto)
        await this.sockB.bind(address)
        await this.sockA.connect(address)
      })

      it("should deliver single string message", async function() {
        const sent = "foo"
        await this.sockA.send(sent)

        const recv = await this.sockB.receive()
        assert.deepEqual([sent], recv.map(buf => buf.toString()))
      })
    })
  })
}
<|endoftext|>


<commit_before>if (typeof(module) !== 'undefined') {
    var _ = require("underscore");
    var Promise = require("bluebird");
    var weapon = require("../server/weaponServer.js");
    var inSystem = require("./inSystem.js");
}

outfit = class extends inSystem {
    constructor(buildInfo) {
	// source is a ship / object the outfit is equipped to
	super(...arguments);
	this.buildInfo = buildInfo;
	this.ready = false;
	this.url = 'objects/outfits/';
	if (typeof(buildInfo) !== 'undefined') {
	    this.name = buildInfo.name;
	    this.count = buildInfo.count || 1;
	}
	this.weapons = [];
    }

    async build(source) {
	this.source = source;
	await this.loadResources();
	if (this.meta.functions.weapon) {
	    await this.buildWeapons();
	}
	this.applyEffects();
	this.ready = true;
    }

    loadResources() {

	return new Promise( function(fulfill, reject) {
	    // fix me to not use jquery
	    var loader = new PIXI.loaders.Loader();
	    var meta;
	    var url = this.url + this.name + ".json";
	    loader
		.add('meta', url)
		.load(function(loader, resource) {
		    this.meta = resource.meta.data;
		}.bind(this));
	    loader.onComplete.add(function() {
		fulfill();
	    });
	    loader.onError.add(reject.bind(this, "Could not get url " + url));
	    /*

	    $.getJSON(this.url + this.name + ".json", _.bind(function(data) {
		this.meta = data;

		if ((typeof(this.meta) !== 'undefined') && (this.meta !== null)) {
		    fulfill();
		}
		else {
		    reject();
		}

	    }, this));
	    */
	}.bind(this));

    }

    buildWeapons() {

	this.weapons = _.map( this.meta.functions.weapon, function(weaponName) {
	    var buildInfo = {
		"name": weaponName,
		"source": this.source.UUID,
		"count": this.count
	    };
	    if (typeof this.buildInfo.UUIDS !== 'undefined') {
		buildInfo.UUID = this.buildInfo.UUIDS[buildInfo.name];
	    }
	    if (typeof this.buildInfo.socket !== 'undefined') {
		buildInfo.socket = this.buildInfo.socket;
	    }
	    var w = new weapon(buildInfo, this.source);
	    this.addChild(w);
	    return w;
	}.bind(this));

	return Promise.all(_.map( this.weapons, function(weapon) {return weapon.build();}));

    }

    applyEffects() {

	if (this.meta.functions["speed increase"]) {
	    this.source.properties.maxSpeed += this.meta.functions["speed increase"] * this.count;
	}

    }

    destroy() {
	_.each(this.weapons, function(w) {w.destroy();});

    }
}

if (typeof(module) !== 'undefined') {
    module.exports = outfit;
}
<commit_msg>remove unneccessary comment<commit_after>if (typeof(module) !== 'undefined') {
    var _ = require("underscore");
    var Promise = require("bluebird");
    var weapon = require("../server/weaponServer.js");
    var inSystem = require("./inSystem.js");
}

outfit = class extends inSystem {
    constructor(buildInfo) {
	// source is a ship / object the outfit is equipped to
	super(...arguments);
	this.buildInfo = buildInfo;
	this.ready = false;
	this.url = 'objects/outfits/';
	if (typeof(buildInfo) !== 'undefined') {
	    this.name = buildInfo.name;
	    this.count = buildInfo.count || 1;
	}
	this.weapons = [];
    }

    async build(source) {
	this.source = source;
	await this.loadResources();
	if (this.meta.functions.weapon) {
	    await this.buildWeapons();
	}
	this.applyEffects();
	this.ready = true;
    }

    loadResources() {

	return new Promise( function(fulfill, reject) {
	    // fix me to not use jquery
	    var loader = new PIXI.loaders.Loader();
	    var meta;
	    var url = this.url + this.name + ".json";
	    loader
		.add('meta', url)
		.load(function(loader, resource) {
		    this.meta = resource.meta.data;
		}.bind(this));
	    loader.onComplete.add(function() {
		fulfill();
	    });
	    loader.onError.add(reject.bind(this, "Could not get url " + url));

	}.bind(this));

    }

    buildWeapons() {

	this.weapons = _.map( this.meta.functions.weapon, function(weaponName) {
	    var buildInfo = {
		"name": weaponName,
		"source": this.source.UUID,
		"count": this.count
	    };
	    if (typeof this.buildInfo.UUIDS !== 'undefined') {
		buildInfo.UUID = this.buildInfo.UUIDS[buildInfo.name];
	    }
	    if (typeof this.buildInfo.socket !== 'undefined') {
		buildInfo.socket = this.buildInfo.socket;
	    }
	    var w = new weapon(buildInfo, this.source);
	    this.addChild(w);
	    return w;
	}.bind(this));

	return Promise.all(_.map( this.weapons, function(weapon) {return weapon.build();}));

    }

    applyEffects() {

	if (this.meta.functions["speed increase"]) {
	    this.source.properties.maxSpeed += this.meta.functions["speed increase"] * this.count;
	}

    }

    destroy() {
	_.each(this.weapons, function(w) {w.destroy();});

    }
}

if (typeof(module) !== 'undefined') {
    module.exports = outfit;
}
<|endoftext|>


<commit_before>/*global describe, beforeEach, module, inject, it, spyOn, expect, $ */
describe('uiRemove', function () {
    'use strict';

    var scope, $compile, $window;
    beforeEach(module('ui.directives'));
    beforeEach(inject(function (_$rootScope_, _$compile_, _$window_) {
        scope = _$rootScope_.$new();
        $compile = _$compile_;
        $window = _$window_;
    }));

    describe('compiling this directive', function () {
        it('should bind to window "scroll" event with a ui-scrollfix namespace', function () {
            spyOn($.fn, 'bind');
            $compile('

')(scope);
            expect($.fn.bind).toHaveBeenCalled();
            expect($.fn.bind.mostRecentCall.args[0]).toBe('scroll.ui-scrollfix');
        });
    });
    describe('scrolling the window', function () {
        it('should add the ui-scrollfix class if the offset is greater than specified', function () {
            var element = $compile('

')(scope);
            $($window).trigger('scroll.ui-scrollfix');
            expect(element.hasClass('ui-scrollfix')).toBe(true);
        });
        it('should remove the ui-scrollfix class if the offset is less than specified (using absolute coord)', function () {
            var element = $compile('

')(scope);
            $($window).trigger('scroll.ui-scrollfix');
            expect(element.hasClass('ui-scrollfix')).toBe(false);

        });
        it('should remove the ui-scrollfix class if the offset is less than specified (using relative coord)', function () {
            var element = $compile('

')(scope);
            $($window).trigger('scroll.ui-scrollfix');
            expect(element.hasClass('ui-scrollfix')).toBe(false);
        });
    });
});<commit_msg>fixing broken scrollfix test<commit_after>/*global describe, beforeEach, module, inject, it, spyOn, expect, $ */
describe('uiScrollfix', function () {
    'use strict';

    var scope, $compile, $window;
    beforeEach(module('ui.directives'));
    beforeEach(inject(function (_$rootScope_, _$compile_, _$window_) {
        scope = _$rootScope_.$new();
        $compile = _$compile_;
        $window = _$window_;
    }));

    describe('compiling this directive', function () {
        it('should bind to window "scroll" event with a ui-scrollfix namespace', function () {
            spyOn($.fn, 'on');
            $compile('

')(scope);
            expect($.fn.on).toHaveBeenCalled();
            expect($.fn.on.mostRecentCall.args[0]).toBe('scroll.ui-scrollfix');
        });
    });
    describe('scrolling the window', function () {
        it('should add the ui-scrollfix class if the offset is greater than specified', function () {
            var element = $compile('

')(scope);
            $($window).trigger('scroll.ui-scrollfix');
            expect(element.hasClass('ui-scrollfix')).toBe(true);
        });
        it('should remove the ui-scrollfix class if the offset is less than specified (using absolute coord)', function () {
            var element = $compile('

')(scope);
            $($window).trigger('scroll.ui-scrollfix');
            expect(element.hasClass('ui-scrollfix')).toBe(false);

        });
        it('should remove the ui-scrollfix class if the offset is less than specified (using relative coord)', function () {
            var element = $compile('

')(scope);
            $($window).trigger('scroll.ui-scrollfix');
            expect(element.hasClass('ui-scrollfix')).toBe(false);
        });
    });
});<|endoftext|>


<commit_before>/*
 * DiscoJuice
 *  Work is based upon mock up made by the Kantara ULX group.
 *
 * Author: Andreas Åkre Solberg, UNINETT, andreas.solberg@uninett.no
 * Licence undecided. Awaiting alignment with the licence of the origin Kantara mockup.
 */
if (typeof DiscoJuice == "undefined") var DiscoJuice = {};

DiscoJuice.UI = {
	// Reference to the top level DiscoJuice object
	"parent" : DiscoJuice,

	// The current data model
	"control": null,

	// Reference to the
	"popup": null,

	// Entities / items
	"resulthtml": 'Loading data…',

	"show": function() {
		this.control.load();

		this.popup.fadeIn("slow");
		$("div#discojuice_overlay").show(); // fadeIn("fast");
		this.focusSearch();
	},

	"focusSearch": function() {
		$("input.discojuice_search").focus();
	},

	"hide": function() {
		$("div#discojuice_overlay").fadeOut("slow"); //fadeOut("fast");
		this.popup.fadeOut("slow");
	},

	"clearItems": function() {
		this.resulthtml = '';
	},

	// addItem(item, description, {country, flag}, keywordmatch, distance)
	// addItem(current, current.descr || null, countrydef, search, current.distance);
	"addItem": function(item, countrydef, search, distance) {
		var textLink = '';
		var classes = '';
		if (item.weight < -50) classes += 'hothit';

		var iconpath = this.parent.Utils.options.get('discoPath', '') + 'logos/';
		var flagpath = this.parent.Utils.options.get('discoPath', '') + 'flags/';
		var clear = false;

		var debugweight = this.parent.Utils.options.get('debug.weight', false);

		// Add icon element first
		if (item.icon) {
			textLink += '';
			clear = true;
		}

		// Add title
		textLink += '' + item.title + '';

		// Add matched search term
		if (search && search !== true) {
			textLink += '– ' + search + '';
		} else if (item.descr) {
			textLink += '– ' +  item.descr + '';
		}

		if (countrydef || (distance != undefined)) {

			textLink += '';
			if (countrydef) {
				textLink += '';
				if (countrydef.flag) textLink += ' ';
				textLink += countrydef.country + '';
			}

			if (distance != undefined) {
				if (distance < 1) {
					textLink += 'Nearby';
				} else {
					textLink += '' +  Math.round(distance) + ' km' + '';
				}

			}
			textLink += '';
		}

		if (debugweight) {
			textLink += '
';

			if (item.subID) {
				textLink += '<input value="' + item.subID + '" />';
			}

			var w = 0;
			if (item.weight) {
				w += item.weight;
			}
			if (item.distanceweight) {
				w += item.distanceweight;
			}
			textLink += 'Weight ' + Math.round(100*w)/100 + ' ';

			if (item.weight) {
				textLink += ' (base ' + item.weight + ')   ';
			}
			if (item.distanceweight) {
				textLink += '(dist ' + Math.round(100*item.distanceweight)/100 + ')';
			}

			textLink += '
';
		}

		// Add a clear bar.
		if (clear) {
			textLink += '
';
		}

		var relID = item.entityID;
		if (item.subID) {
			relID += '#' + item.subID;
		}

		// Wrap in A element
		textLink = '' +
			textLink + '';

		this.resulthtml += textLink;
	},

	"refreshData": function(showmore, show, listcount) {
		var that = this;

		this.parent.Utils.log('DiscoJuice.UI refreshData()');

		this.popup.find("div.scroller").empty().append(this.resulthtml);
		this.popup.find("div.scroller a").each(function() {
			var overthere = that;	// Overthere is a reference to the UI object
			$(this).click(function(event) {
				event.preventDefault();
				overthere.hide();

				// The "rel" attribute is containing: 'entityid#subid'
				// THe following code, decodes that.
				var relID = unescape($(this).attr('rel'));
				var entityID = relID;
				var subID = undefined;
				if (relID.match(/^.*#.+?$/)) {
					var matched = /^(.*)#(.+?)$/.exec(relID);
					entityID = matched[1];
					subID = matched[2];
				}
				overthere.control.selectProvider(entityID, subID);
			});
		});

		if (showmore) {
			var moreLink = 'Results limited to ' + show + ' entries – show more…';
			this.popup.find("p.discojuice_moreLinkContainer").empty().append(moreLink);
			this.popup.find("p.discojuice_moreLinkContainer a.discojuice_showmore").click(function(e) {
				event.preventDefault();
				that.control.increase();
			});
		} else {
			this.popup.find("p.discojuice_moreLinkContainer").empty();
			if (listcount > 10) {
				var moreLink = '' + listcount + ' entries listed';
				this.popup.find("p.discojuice_moreLinkContainer").append(moreLink);
			}
		}
	},

	"enable": function(control) {
		var imgpath = this.parent.Utils.options.get('discoPath', '') + 'images/';

		var textSearch = this.parent.Utils.options.get('textSearch', 'or search for a provider, in example Univerity of Oslo');
		var textHelp = this.parent.Utils.options.get('textHelp', 'Help me, I cannot find my provider');
		var textHelpMore = this.parent.Utils.options.get('textHelpMore', 'If your institusion is not connected to Foodle, you may create a new account using any of the Guest providers, such as OpenIdP (Guest users).');

		var html = 	'
' +
			'
' +
				' ' +
				'
' + this.parent.Utils.options.get('title', 'Title')  +  '
' +
				'
' + this.parent.Utils.options.get('subtitle', 'Subtitle') + '
' +
			'
' +

			'
' +
				'
' +
					'
 Loading list of providers...
' +
				'
' +
				'

' +
			'
' +

			'
' +
				'
<input type="search" class="discojuice_search" results=5 autosave="discojuice" name="searchfield" placeholder="' + textSearch + '" value="" />
' +
				'
' +
					'' + textHelp + '' +
					'
' + textHelpMore + '
' +
				'
' +
			'
' +

			'
' +
				'
' +
					'
' +
						'' +
						'Locate me more accurately using HTML5 Geo-Location' +
					'
' +
					'

' +
				'
' +
				'

' +
			'
' +

			'
' +
				'<button id="discojuiceextesion_listener" />' +
			'
' +

			'
' +
				'
DiscoJuice © UNINETT
' +
			'
' +

		'
';
		var that = this;

		if (this.parent.Utils.options.get('overlay', true) === true) {
			var overlay = '

';
			$(overlay).appendTo($("body"));
		}

		this.popup = $(html).appendTo($("body"));

		if (this.parent.Utils.options.get('always', false) === true) {
			this.popup.find(".discojuice_close").hide();
			this.show();
		} else {
			// Add a listener to the sign in button.
			$(control).click(function(event) {
				event.preventDefault();
				that.show();
				return false;
			});
		}

		this.popup.find("#discojuiceextesion_listener").click(function() {
			that.control.discojuiceextension();
		});

		// Add listeners to the close button.
		this.popup.find(".discojuice_close").click(function() {
			that.hide();
		});

 		// Add toogle for what is this text.
		this.popup.find(".discojuice_what").click(function() {
			that.popup.find(".discojuice_whatisthis").toggleClass("show");
		});

		if (this.parent.Utils.options.get('location', false) && navigator.geolocation) {
			var that = this;
			$("#locateme").click(function(event) {
				var imgpath = that.parent.Utils.options.get('discoPath', '') + 'images/';
				event.preventDefault();
				$("div.locatemebefore").hide();
				$("div.locatemeafter").html('
 Getting your location...
');
				that.control.locateMe();
			});
		} else {
			$("dd#locatemediv").hide();
		}

	},

	"setLocationText": function(html) {
		return $("div.locatemeafter").html(html);
	},

	"addContent": function(html) {
		return $(html).appendTo($("body"));
	},
	"addFilter": function(html) {
		return $(html).prependTo(this.popup.find('.filters'));
//		this.popup.find('.filters').append(html).css('border', '1px solid red');
	}
};

<commit_msg>Fix a bug in DiscoJuice that caused problem in Firefox. Wrong parameter name for event object.<commit_after>/*
 * DiscoJuice
 *  Work is based upon mock up made by the Kantara ULX group.
 *
 * Author: Andreas Åkre Solberg, UNINETT, andreas.solberg@uninett.no
 * Licence undecided. Awaiting alignment with the licence of the origin Kantara mockup.
 */
if (typeof DiscoJuice == "undefined") var DiscoJuice = {};

DiscoJuice.UI = {
	// Reference to the top level DiscoJuice object
	"parent" : DiscoJuice,

	// The current data model
	"control": null,

	// Reference to the
	"popup": null,

	// Entities / items
	"resulthtml": 'Loading data…',

	"show": function() {
		this.control.load();

		this.popup.fadeIn("slow");
		$("div#discojuice_overlay").show(); // fadeIn("fast");
		this.focusSearch();
	},

	"focusSearch": function() {
		$("input.discojuice_search").focus();
	},

	"hide": function() {
		$("div#discojuice_overlay").fadeOut("slow"); //fadeOut("fast");
		this.popup.fadeOut("slow");
	},

	"clearItems": function() {
		this.resulthtml = '';
	},

	// addItem(item, description, {country, flag}, keywordmatch, distance)
	// addItem(current, current.descr || null, countrydef, search, current.distance);
	"addItem": function(item, countrydef, search, distance) {
		var textLink = '';
		var classes = '';
		if (item.weight < -50) classes += 'hothit';

		var iconpath = this.parent.Utils.options.get('discoPath', '') + 'logos/';
		var flagpath = this.parent.Utils.options.get('discoPath', '') + 'flags/';
		var clear = false;

		var debugweight = this.parent.Utils.options.get('debug.weight', false);

		// Add icon element first
		if (item.icon) {
			textLink += '';
			clear = true;
		}

		// Add title
		textLink += '' + item.title + '';

		// Add matched search term
		if (search && search !== true) {
			textLink += '– ' + search + '';
		} else if (item.descr) {
			textLink += '– ' +  item.descr + '';
		}

		if (countrydef || (distance != undefined)) {

			textLink += '';
			if (countrydef) {
				textLink += '';
				if (countrydef.flag) textLink += ' ';
				textLink += countrydef.country + '';
			}

			if (distance != undefined) {
				if (distance < 1) {
					textLink += 'Nearby';
				} else {
					textLink += '' +  Math.round(distance) + ' km' + '';
				}

			}
			textLink += '';
		}

		if (debugweight) {
			textLink += '
';

			if (item.subID) {
				textLink += '<input value="' + item.subID + '" />';
			}

			var w = 0;
			if (item.weight) {
				w += item.weight;
			}
			if (item.distanceweight) {
				w += item.distanceweight;
			}
			textLink += 'Weight ' + Math.round(100*w)/100 + ' ';

			if (item.weight) {
				textLink += ' (base ' + item.weight + ')   ';
			}
			if (item.distanceweight) {
				textLink += '(dist ' + Math.round(100*item.distanceweight)/100 + ')';
			}

			textLink += '
';
		}

		// Add a clear bar.
		if (clear) {
			textLink += '
';
		}

		var relID = item.entityID;
		if (item.subID) {
			relID += '#' + item.subID;
		}

		// Wrap in A element
		textLink = '' +
			textLink + '';

		this.resulthtml += textLink;
	},

	"refreshData": function(showmore, show, listcount) {
		var that = this;

		this.parent.Utils.log('DiscoJuice.UI refreshData()');

		this.popup.find("div.scroller").empty().append(this.resulthtml);
		this.popup.find("div.scroller a").each(function() {
			var overthere = that;	// Overthere is a reference to the UI object
			$(this).click(function(event) {
				event.preventDefault();
				overthere.hide();

				// The "rel" attribute is containing: 'entityid#subid'
				// THe following code, decodes that.
				var relID = unescape($(this).attr('rel'));
				var entityID = relID;
				var subID = undefined;
				if (relID.match(/^.*#.+?$/)) {
					var matched = /^(.*)#(.+?)$/.exec(relID);
					entityID = matched[1];
					subID = matched[2];
				}
				overthere.control.selectProvider(entityID, subID);
			});
		});

		if (showmore) {
			var moreLink = 'Results limited to ' + show + ' entries – show more…';
			this.popup.find("p.discojuice_moreLinkContainer").empty().append(moreLink);
			this.popup.find("p.discojuice_moreLinkContainer a.discojuice_showmore").click(function(event) {
				event.preventDefault();
				that.control.increase();
			});
		} else {
			this.popup.find("p.discojuice_moreLinkContainer").empty();
			if (listcount > 10) {
				var moreLink = '' + listcount + ' entries listed';
				this.popup.find("p.discojuice_moreLinkContainer").append(moreLink);
			}
		}
	},

	"enable": function(control) {
		var imgpath = this.parent.Utils.options.get('discoPath', '') + 'images/';

		var textSearch = this.parent.Utils.options.get('textSearch', 'or search for a provider, in example Univerity of Oslo');
		var textHelp = this.parent.Utils.options.get('textHelp', 'Help me, I cannot find my provider');
		var textHelpMore = this.parent.Utils.options.get('textHelpMore', 'If your institusion is not connected to Foodle, you may create a new account using any of the Guest providers, such as OpenIdP (Guest users).');

		var html = 	'
' +
			'
' +
				' ' +
				'
' + this.parent.Utils.options.get('title', 'Title')  +  '
' +
				'
' + this.parent.Utils.options.get('subtitle', 'Subtitle') + '
' +
			'
' +

			'
' +
				'
' +
					'
 Loading list of providers...
' +
				'
' +
				'

' +
			'
' +

			'
' +
				'
<input type="search" class="discojuice_search" results=5 autosave="discojuice" name="searchfield" placeholder="' + textSearch + '" value="" />
' +
				'
' +
					'' + textHelp + '' +
					'
' + textHelpMore + '
' +
				'
' +
			'
' +

			'
' +
				'
' +
					'
' +
						'' +
						'Locate me more accurately using HTML5 Geo-Location' +
					'
' +
					'

' +
				'
' +
				'

' +
			'
' +

			'
' +
				'<button id="discojuiceextesion_listener" />' +
			'
' +

			'
' +
				'
DiscoJuice © UNINETT
' +
			'
' +

		'
';
		var that = this;

		if (this.parent.Utils.options.get('overlay', true) === true) {
			var overlay = '

';
			$(overlay).appendTo($("body"));
		}

		this.popup = $(html).appendTo($("body"));

		if (this.parent.Utils.options.get('always', false) === true) {
			this.popup.find(".discojuice_close").hide();
			this.show();
		} else {
			// Add a listener to the sign in button.
			$(control).click(function(event) {
				event.preventDefault();
				that.show();
				return false;
			});
		}

		this.popup.find("#discojuiceextesion_listener").click(function() {
			that.control.discojuiceextension();
		});

		// Add listeners to the close button.
		this.popup.find(".discojuice_close").click(function() {
			that.hide();
		});

 		// Add toogle for what is this text.
		this.popup.find(".discojuice_what").click(function() {
			that.popup.find(".discojuice_whatisthis").toggleClass("show");
		});

		if (this.parent.Utils.options.get('location', false) && navigator.geolocation) {
			var that = this;
			$("#locateme").click(function(event) {
				var imgpath = that.parent.Utils.options.get('discoPath', '') + 'images/';
				event.preventDefault();
				$("div.locatemebefore").hide();
				$("div.locatemeafter").html('
 Getting your location...
');
				that.control.locateMe();
			});
		} else {
			$("dd#locatemediv").hide();
		}

	},

	"setLocationText": function(html) {
		return $("div.locatemeafter").html(html);
	},

	"addContent": function(html) {
		return $(html).appendTo($("body"));
	},
	"addFilter": function(html) {
		return $(html).prependTo(this.popup.find('.filters'));
//		this.popup.find('.filters').append(html).css('border', '1px solid red');
	}
};

<|endoftext|>


<commit_before>// # Quick start guide to the open platform
//
// _**Guide in progress, not fully working/done yet.**_
//
// This introduction to getting started with the open platform is online on:
// [https://openplatform.dbc.dk/v0/guide.html#client\_id:client\_secret](https://openplatform.dbc.dk/v0/guide.html#client_id:client_secret). Supply your `client_id` and `client_secret` in the url hash, to make the examples work.
//
// The api-documentation is [https://openplatform.dbc.dk/v0/](https://openplatform.dbc.dk/v0/).
//
// The guide is written as a literate JavaScript
// [source file](https://openplatform.dbc.dk/v0/guide.js),
// that can be executed directly in the browser.
// Open the browser console to see the result of the examples.
//
// # JavaScript API
//
// To use the open platform from a browser, load
// `https://openplatform.dbc.dk/v0/dbc_openplatform.min.js`,
// with a `<script>`-tag, or in a similar way.
// Then the `dbcOpenPlatform` object will be available.
// Do not cache this JavaScript library indefinitely,
// as the underlying implementation may change
// if we change the transport protocol.
//
// This guide assumes familiarity with [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) which are used asynchronous JavaScript code.
//
// ## Connecting
//
// First you need to connect to the platform:

dbcOpenPlatform.connect(
    client_id(), client_secret(),
    user_id(), user_password()) // optional
.then(function(token) {

// Notice that the `user_id` consist of "user-id@agency-id".
// You can always check whether you are connected,

console.log('connected:',
    dbcOpenPlatform.connected());

// It also possible to disconnect
// (useful to save power on mobile devices)

dbcOpenPlatform.disconnect()
.then(function() {

// and to reconnect with an existing token

dbcOpenPlatform.connect(token)
.then(function() {

// ## Calling the api
//
// The api exposes the different endpoints as methods
// on the `dbcOpenPlatform` object. For example,
// a search is executed with:

dbcOpenPlatform.search({
    q: 'ost',
    fields: ['title', 'creator', 'pid']})
.then(function(results) {
    console.log('search example', results);
});

// Errors are caught as usual with promises:

dbcOpenPlatform.work({ invalid_parameter: 'foo'})
.catch(function(err) {
    console.log('work error example', err);
});

// By default, successful requests exclude the
// result envelope, - if you want the envelope,
// add `envelope: true` to the request.

dbcOpenPlatform.suggest({
    q: 'jens', type: 'creator',
    timings: true, envelope: true})
.then(function(results) {
    console.log('suggest example', results);
});

// # OAuth2 Authentication
//
// In order to use the HTTP-API, we need to acquire an `access_token`.
//
// For this we need various credentials:
//
// - `client_id` - identifies app and library
// - `client_secret` - password connected with the `client_id`
// - `user_id` - library user id (often consisting of 10 digits) followed by an "@" followed by the library agency id, or `@` for anonymous user. The library agency ids can be found via the `libraries` endpoint, through an anonymous user login.
// - `user_password` - typically the pin for the library user, or just `@` for anonymous users
//

// The `access_token` is retrieved with a HTTP-POST request,
// with `client_id` and `client_secret` supplied through basic authentication,
// and `user_id`, `user_password` supplied in the request body.
// In browser JavaScript this can be done with XHR:

var xhr = new XMLHttpRequest();

xhr.open('POST', 'https://auth.dbc.dk/oauth/token');

xhr.setRequestHeader('Authorization', 'Basic ' +
    btoa(client_id() + ':' + client_secret()));

xhr.setRequestHeader('Content-Type',
    'application/x-www-form-urlencoded');

xhr.send('grant_type=password' +
    '&username=' + user_id() +
    '&password=' + user_password());

// This request returns a JSON object,
// which has an `access_token` property on success.
// The rest of this guide assume that we have a valid `access_token`

xhr_promise(xhr).then(function(result) {
    var access_token = result.access_token;

// # GET API
//
// You can also express the entire query in an url,
// which is useful for interactive testing.
// An example search url is:
// https://openplatform.dbc.dk/v0/search?q=hej&pretty=true&access_token=...
//
// The serviceprovider tries to parse each individual url parameter
// as a string, and if that fails just use it as a string. This
// makes it possible to add more complex parameters, such as `.../work?pids=["870970-basis:05760755","870970-basis:27648452"]&...`
//
// # POST API
//
// Requests to the API can be sent by POSTing a JSON object
// to the API endpoint:

HTTP_POST('https://openplatform.dbc.dk/v0/suggest',
    { q: 'Steppe', type: 'title',
      access_token: access_token});

HTTP_POST('https://openplatform.dbc.dk/v0/search',
    {q: 'hello', access_token: access_token});

// All of the other APIs also have the same structure
// of sending a JSON object of parameters to the endpoint
// and then getting the result back.
//
// In browser JavaScript, HTTP-POSTing a JSON object
// can be done like this:

function HTTP_POST(url, parameters) {
    xhr = new XMLHttpRequest();
    xhr.open('POST', url);
    xhr.setRequestHeader('Content-Type',
        'application/json');
    xhr.send(JSON.stringify(parameters));
    return xhr_promise(xhr);
}

//

// # Support code
//
// The following sections are the utility functions used above.
// It is implemented here for completeness.
// Feel free to skip the rest of this file.

// Make sample get-request-url include proper `access_token`:

var link = document.getElementById('sample_url');
link.href = link.innerHTML =
  'https://openplatform.dbc.dk/v0/search?' +
  'q=hej&pretty=true&access_token=' + access_token;

// Close open code blocks. They contain scope for logins / tokens.

}); }); }); });

// The example code assumes that the credentials are supplied in
// the url-hash. Here is a quick hack to extract them from the url:

function client_id() {
  return location.hash.split(':')[0].slice(1); }
function client_secret() {
  return location.hash.split(':')[1]; }
function user_id() {
  return location.hash.split(':')[2] || '@'; }
function user_password() {
  return location.hash.split(':')[3] || '@'; }
if(client_id() === 'id' || !client_secret()) {
  throw 'Please use your client_id' +
    ' and client_secret in the url';
}

// A XMLHttpRequest requires setting event handlers
// to get the result of the request.
// Here is a utility function that does the boilerplate
// code, and transforms the XHR-request into a promise.
// It also logs, and parse the result as JSON
// on the way through.

function xhr_promise(xhr) {
  return new Promise(function(resolve, reject) {
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4) {
        console.log(xhr.responseURL, xhr);
        if(xhr.status === 200) {
          var result = xhr.response;
          try {
            result = JSON.parse(result);
          } catch(e) {
          }
          resolve(result);
        } else {
          reject(xhr);
        }
      }
    }
  });
}

// Final note: the code above is written as a tutorial code,
// designed to be simple to read, and get started with,
// rather than proper and correct. It does not follow
// best practices for production code.
<commit_msg>update guide, fixes 424 (#427)<commit_after>// # Quick start guide to the open platform
//
// _**Guide in progress, not fully working/done yet.**_
//
// This introduction to getting started with the open platform is online on:
// [https://openplatform.dbc.dk/v0/guide.html#client\_id:client\_secret](https://openplatform.dbc.dk/v0/guide.html#client_id:client_secret). Supply your `client_id` and `client_secret` in the url hash, to make the examples work.
//
// The api-documentation is [https://openplatform.dbc.dk/v0/](https://openplatform.dbc.dk/v0/).
//
// The guide is written as a literate JavaScript
// [source file](https://openplatform.dbc.dk/v0/guide.js),
// that can be executed directly in the browser.
// Open the browser console to see the result of the examples.
//
// # JavaScript API
//
// To use the open platform from a browser, load
// `https://openplatform.dbc.dk/v0/dbc_openplatform.min.js`,
// with a `<script>`-tag, or in a similar way.
// Then the `dbcOpenPlatform` object will be available.
// Do not cache this JavaScript library indefinitely,
// as the underlying implementation may change
// if we change the transport protocol.
//
// This guide assumes familiarity with [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) which are used asynchronous JavaScript code.
//
// ## Connecting
//
// First you need to connect to the platform:

dbcOpenPlatform.connect(
    client_id(), client_secret(),
    user_id(), user_password()) // optional
.then(function(token) {

// Notice that the `user_id` consist of "user-id@agency-id".
// You can always check whether you are connected,

console.log('connected:',
    dbcOpenPlatform.connected());

// It also possible to disconnect
// (useful to save power on mobile devices)

dbcOpenPlatform.disconnect()
.then(function() {

// and to reconnect with an existing token

dbcOpenPlatform.connect(token)
.then(function() {

// ## Calling the api
//
// The api exposes the different endpoints as methods
// on the `dbcOpenPlatform` object. For example,
// a search is executed with:

dbcOpenPlatform.search({
    q: 'ost',
    fields: ['title', 'creator', 'pid']})
.then(function(results) {
    console.log('search example', results);
});

// Errors are caught as usual with promises:

dbcOpenPlatform.work({ invalid_parameter: 'foo'})
.catch(function(err) {
    console.log('work error example', err);
});

// By default, successful requests exclude the
// result envelope, - if you want the envelope,
// add `envelope: true` to the request.

dbcOpenPlatform.suggest({
    q: 'jens', type: 'creator',
    timings: true, envelope: true})
.then(function(results) {
    console.log('suggest example', results);
});

// Notice that while suggest just takes a string,
// queries for search and facets
// are expressed as [CQL](http://www.danbib.dk/broend3_soeg).
// This means that searches like `den lille prins` will fail,
// and has to be `den AND lille AND prins` or `"den lille prins"` or ...,
// depending on the desired result.

dbcOpenPlatform.facets({q: '"den lille prins"'})
.then(function(results) {
    console.log('facets example', results);
});

// # OAuth2 Authentication
//
// In order to use the HTTP-API, we need to acquire an `access_token`.
//
// For this we need various credentials:
//
// - `client_id` - identifies app and library
// - `client_secret` - password connected with the `client_id`
// - `user_id` - library user id (often consisting of 10 digits) followed by an "@" followed by the library agency id, or `@` for anonymous user. The library agency ids can be found via the `libraries` endpoint, through an anonymous user login.
// - `user_password` - typically the pin for the library user, or just `@` for anonymous users
//

// The `access_token` is retrieved with a HTTP-POST request,
// with `client_id` and `client_secret` supplied through basic authentication,
// and `user_id`, `user_password` supplied in the request body.
// In browser JavaScript this can be done with XHR:

var xhr = new XMLHttpRequest();

xhr.open('POST', 'https://auth.dbc.dk/oauth/token');

xhr.setRequestHeader('Authorization', 'Basic ' +
    btoa(client_id() + ':' + client_secret()));

xhr.setRequestHeader('Content-Type',
    'application/x-www-form-urlencoded');

xhr.send('grant_type=password' +
    '&username=' + user_id() +
    '&password=' + user_password());

// This request returns a JSON object,
// which has an `access_token` property on success.
// The rest of this guide assume that we have a valid `access_token`

xhr_promise(xhr).then(function(result) {
    var access_token = result.access_token;

// # GET API
//
// You can also express the entire query in an url,
// which is useful for interactive testing.
// An example search url is:
// https://openplatform.dbc.dk/v0/search?q=hej&pretty=true&access_token=...
//
// The serviceprovider tries to parse each individual url parameter
// as a string, and if that fails just use it as a string. This
// makes it possible to add more complex parameters, such as `.../work?pids=["870970-basis:05760755","870970-basis:27648452"]&...`
//
// # POST API
//
// Requests to the API can be sent by POSTing a JSON object
// to the API endpoint:

HTTP_POST('https://openplatform.dbc.dk/v0/suggest',
    { q: 'Steppe', type: 'title',
      access_token: access_token});

HTTP_POST('https://openplatform.dbc.dk/v0/search',
    {q: 'hello', access_token: access_token});

// All of the other APIs also have the same structure
// of sending a JSON object of parameters to the endpoint
// and then getting the result back.
//
// In browser JavaScript, HTTP-POSTing a JSON object
// can be done like this:

function HTTP_POST(url, parameters) {
    xhr = new XMLHttpRequest();
    xhr.open('POST', url);
    xhr.setRequestHeader('Content-Type',
        'application/json');
    xhr.send(JSON.stringify(parameters));
    return xhr_promise(xhr);
}

//

// # Support code
//
// The following sections are the utility functions used above.
// It is implemented here for completeness.
// Feel free to skip the rest of this file.

// Make sample get-request-url include proper `access_token`:

var link = document.getElementById('sample_url');
link.href = link.innerHTML =
  'https://openplatform.dbc.dk/v0/search?' +
  'q=hej&pretty=true&access_token=' + access_token;

// Close open code blocks. They contain scope for logins / tokens.

}); }); }); });

// The example code assumes that the credentials are supplied in
// the url-hash. Here is a quick hack to extract them from the url:

function client_id() {
  return location.hash.split(':')[0].slice(1); }
function client_secret() {
  return location.hash.split(':')[1]; }
function user_id() {
  return location.hash.split(':')[2] || '@'; }
function user_password() {
  return location.hash.split(':')[3] || '@'; }
if(client_id() === 'id' || !client_secret()) {
  throw 'Please use your client_id' +
    ' and client_secret in the url';
}

// A XMLHttpRequest requires setting event handlers
// to get the result of the request.
// Here is a utility function that does the boilerplate
// code, and transforms the XHR-request into a promise.
// It also logs, and parse the result as JSON
// on the way through.

function xhr_promise(xhr) {
  return new Promise(function(resolve, reject) {
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4) {
        console.log(xhr.responseURL, xhr);
        if(xhr.status === 200) {
          var result = xhr.response;
          try {
            result = JSON.parse(result);
          } catch(e) {
          }
          resolve(result);
        } else {
          reject(xhr);
        }
      }
    }
  });
}

// Final note: the code above is written as a tutorial code,
// designed to be simple to read, and get started with,
// rather than proper and correct. It does not follow
// best practices for production code.
<|endoftext|>


<commit_before>angular.module('formly.render')
.directive('formlyField', function formlyField($http, $compile, $templateCache, formlyConfig) {
	'use strict';
	return {
		restrict: 'AE',
		transclude: true,
		scope: {
			optionsData: '&options',
			formId: '=formId',
			index: '=index',
			result: '=formResult'
		},
		link: function fieldLink($scope, $element) {
      var templateOptions = 0;
      templateOptions += $scope.options.template ? 1 : 0;
      templateOptions += $scope.options.type ? 1 : 0;
      templateOptions += $scope.options.templateUrl ? 1 : 0;
      if (templateOptions === 0) {
        console.warn('Formly Error: template type \'' + $scope.options.type + '\' not supported. On element:', $element);
        return;
      } else if (templateOptions > 1) {
        console.warn('Formly Error: You must only provide a type, template, or templateUrl for a field. On element:', $element);
      }
      var template = $scope.options.template || formlyConfig.getTemplate($scope.options.type);
			if (template) {
				setElementTemplate(template);
			} else {
				var templateUrl = $scope.options.templateUrl || formlyConfig.getTemplateUrl($scope.options.type);
				if (templateUrl) {
					$http.get(templateUrl, {
						cache: $templateCache
					}).then(function(response) {
						setElementTemplate(response.data);
					}, function(error) {
						console.warn('Formly Error: Problem loading template for ' + templateUrl, error);
					});
				}
			}
			function setElementTemplate(templateData) {
				$element.html(templateData);
				$compile($element.contents())($scope);
			}
		},
		controller: function fieldController($scope) {
			$scope.options = $scope.optionsData();
			var type = $scope.options.type;
			if (!type && $scope.options.template) {
				type = 'template';
			} else if (!type && $scope.options.templateUrl) {
				type = 'templateUrl';
			}

			// set field id to link labels and fields
			$scope.id = $scope.formId + type + $scope.index;
		}
	};
});
<commit_msg>Adding key to the form id<commit_after>angular.module('formly.render')
.directive('formlyField', function formlyField($http, $compile, $templateCache, formlyConfig) {
	'use strict';
	return {
		restrict: 'AE',
		transclude: true,
		scope: {
			optionsData: '&options',
			formId: '=formId',
			index: '=index',
			result: '=formResult'
		},
		link: function fieldLink($scope, $element) {
      var templateOptions = 0;
      templateOptions += $scope.options.template ? 1 : 0;
      templateOptions += $scope.options.type ? 1 : 0;
      templateOptions += $scope.options.templateUrl ? 1 : 0;
      if (templateOptions === 0) {
        console.warn('Formly Error: template type \'' + $scope.options.type + '\' not supported. On element:', $element);
        return;
      } else if (templateOptions > 1) {
        console.warn('Formly Error: You must only provide a type, template, or templateUrl for a field. On element:', $element);
      }
      var template = $scope.options.template || formlyConfig.getTemplate($scope.options.type);
			if (template) {
				setElementTemplate(template);
			} else {
				var templateUrl = $scope.options.templateUrl || formlyConfig.getTemplateUrl($scope.options.type);
				if (templateUrl) {
					$http.get(templateUrl, {
						cache: $templateCache
					}).then(function(response) {
						setElementTemplate(response.data);
					}, function(error) {
						console.warn('Formly Error: Problem loading template for ' + templateUrl, error);
					});
				}
			}
			function setElementTemplate(templateData) {
				$element.html(templateData);
				$compile($element.contents())($scope);
			}
		},
		controller: function fieldController($scope) {
			$scope.options = $scope.optionsData();
			var type = $scope.options.type;
			if (!type && $scope.options.template) {
				type = 'template';
			} else if (!type && $scope.options.templateUrl) {
				type = 'templateUrl';
			}

			// set field id to link labels and fields
			$scope.id = $scope.formId + type + $scope.options.key + $scope.index;
		}
	};
});
<|endoftext|>


<commit_before>ko.bindingProvider.instance = new StringInterpolatingBindingProvider();

var availableRoles = [
  {value: 'ingest', text: 'ingest'},
  {value: 'mixer', text: 'mixer'},
  {value: 'record', text: 'record'},
  {value: 'stream', text: 'stream'}
]

var roleDisplay = function(value, sourceData) {
   var selectedRoles = "",
       checked = $.fn.editableutils.itemsByValue(value, sourceData);

   if(checked.length) {
     $.each(checked, function(i, v) {
       selectedRoles += "
" + $.fn.editableutils.escape(v.text) + "
";
     });
     $(this).html('
' + selectedRoles + '
');
   } else {
     $(this).empty();
   }
}

function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

var viewModel = {
  stations: ko.mapping.fromJS([]),
}

var availableDevices = function(options) {
  var innerModel = ko.mapping.fromJS(options.data);
  availableDevices = [];
  console.log(options.data.devices,options.data.settings.devices);
  connected = options.data.devices;
  configured = options.data.settings.devices || [];
  if (configured == 'all') {
    configured = [];
  }
  console.log(connected,configured);

  $.map(connected,function(v){
    var availableDevice = {};
    availableDevice.name = v.name || 'unknown';
    availableDevice.id = v.id;
    availableDevice.type = v.type;
    for(var i in configured) {
      var id = configured[i].id;
      var test = availableDevice.id;
      var match = false;
      if (id == test) {
        match = true;
        break;
      }
    }
    if (!match) {
      console.log(availableDevice,match);
      availableDevices.push(availableDevice);
    }
  });
  return availableDevices;
}

var mapping = {
  create: function(options) {
    var innerModel = ko.mapping.fromJS(options.data)
    if (options.data.devices) {
      innerModel.availableDevices = availableDevices(options)
    }
    return innerModel;
  }
};

viewModel.roomDuplicates = ko.computed(function() {
  return viewModel.stations().map(function(item) {
    return (item.settings.room ? item.settings.room() : '')
  })
})

viewModel.rooms = ko.computed(function() {
  return viewModel.roomDuplicates().filter(onlyUnique)
})

ko.applyBindings(viewModel);

var socket = io.connect('//:5001')

$.get( "/api/stations", function( data ) {
})
  .done(function(data) {
    ko.mapping.fromJS(data, mapping, viewModel.stations)
    socket.on('change', function (data) {
      console.log(data);
      if (data.type == 'remove') {
        viewModel.stations.remove(function(item) {
          return item._id() == data.content
        })
      }
      if (data.type == 'insert') {
        viewModel.stations.push(ko.mapping.fromJS(data.content, mapping))
      }
      if (data.type == 'update') {
        var match = ko.utils.arrayFirst(viewModel.stations(), function(item) {
          return data.content._id === item._id();
        });
        if (match) {
          viewModel.stations.splice(viewModel.stations.indexOf(match),1,ko.mapping.fromJS(data.content));
        }
      }
      if (data.type == 'notify') {
      }

    });
  })

var availableDeviceClick = function (item, configured, macaddress) {
  var value = ko.toJS(item);
  var devices = ko.toJS(configured) || [];
  if (devices == 'all') {
    devices = [];
  }
  devices.push(value);

  var post = {};
  post.key = "settings.devices";
  post.value = devices;

  $.ajax({
    url: '/api/stations/' + macaddress() + '/partial',
    type: 'POST',
    data: post
  })
};

var actionStationManagers = function(roomId, action) {
  ko.utils.arrayForEach(viewModel.stations(), function(station) {
    if (station.settings.room() === roomId) {
      var post = new Object();
      post.station_macaddress = station.settings.macaddress();
      post.id = "Station";
      post.command_url = "manager";
      post.action = action;
      actionStationPost(post);
    }
  })
}

var actionStations = function(roomId, action) {
  ko.utils.arrayForEach(viewModel.stations(), function(station) {
    if (station.settings.room() === roomId) {
      var post = new Object();
      post.station_macaddress = station.settings.macaddress();
      post.id = "all";
      post.command_url = "command";
      post.action = action;
      actionStationPost(post);
    }
  })
}

var actionStationManager = function(macaddress, action) {
  var post = new Object();
  post.station_macaddress = macaddress;
  post.id = "Station";
  post.command_url = "manager";
  post.action = action;
  actionStationPost(post);
}

$("body").on("click", ".actionOnclick", function (e) {
  var post = new Object();
  post.station_macaddress = $(e.currentTarget).closest("[data-macaddress]").data('macaddress');
  post.id = $(e.currentTarget).data('id');
  post.command_url = "command";
  post.action = $(e.currentTarget).data('action');
  actionStationPost(post);
});

var actionDevice = function(macaddress, device, action) {
  var post = new Object();
  post.station_macaddress = macaddress;
  post.id = device;
  post.command_url = "command";
  post.action = action;
  actionStationPost(post);
}

var actionStationPost = function(post) {
  console.log(post)
  $.ajax({
    url: '/api/station/' + post.station_macaddress + '/action',
    type: 'POST',
    data: post
  })
}

var removeStation = function(data, event) {
  $.ajax({
    url: "/api/station/"+ data.settings.macaddress(),
    type: 'DELETE'
  })
    .done(function(data) {
      console.log( "removed station", JSON.stringify(data) );
    })
}

var removeStationRoom = function(data, event) {
  $.ajax({
    url: "/api/stations/"+ data.settings.macaddress()  + '/partial',
    type: 'POST',
    data: {
      key: 'settings.room',
      value: ''
    }
  })
    .done(function(data) {
      console.log( "removed station", JSON.stringify(data) );
    })
}

function submitStation(data, event) {
  var $form = $(event.currentTarget).parents('#add-station');

  $.ajax({
    type: "POST",
    url: "/api/station",
    data: data,
  })
    .done(function() {
      $form.collapse('hide')
    })
}

var macRewrite = function(macaddress) {
  if (!macaddress) { return false }
  return macaddress.replace(/-\s*/g, ":")
}

<commit_msg>added try catch to handle previous broken logic<commit_after>ko.bindingProvider.instance = new StringInterpolatingBindingProvider();

var availableRoles = [
  {value: 'ingest', text: 'ingest'},
  {value: 'mixer', text: 'mixer'},
  {value: 'record', text: 'record'},
  {value: 'stream', text: 'stream'}
]

var roleDisplay = function(value, sourceData) {
   var selectedRoles = "",
       checked = $.fn.editableutils.itemsByValue(value, sourceData);

   if(checked.length) {
     $.each(checked, function(i, v) {
       selectedRoles += "
" + $.fn.editableutils.escape(v.text) + "
";
     });
     $(this).html('
' + selectedRoles + '
');
   } else {
     $(this).empty();
   }
}

function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

var viewModel = {
  stations: ko.mapping.fromJS([]),
}

var availableDevices = function(options) {
  var innerModel = ko.mapping.fromJS(options.data);
  availableDevices = [];
  console.log(options.data.devices,options.data.settings.devices);
  connected = options.data.devices;
  configured = options.data.settings.devices || [];
  if (configured == 'all') {
    configured = [];
  }
  console.log(connected,configured);

  $.map(connected,function(v){
    var availableDevice = {};
    availableDevice.name = v.name || 'unknown';
    availableDevice.id = v.id;
    availableDevice.type = v.type;
    for(var i in configured) {
      var id = configured[i].id;
      var test = availableDevice.id;
      var match = false;
      if (id == test) {
        match = true;
        break;
      }
    }
    if (!match) {
      console.log(availableDevice,match);
      availableDevices.push(availableDevice);
    }
  });
  return availableDevices;
}

var mapping = {
  create: function(options) {
    var innerModel = ko.mapping.fromJS(options.data)
    if (options.data.devices) {
      try {
        innerModel.availableDevices = availableDevices(options)
      }
      catch(err) {
        console.log(err)
        console.log("station devices broken, update the station!")
      }
    }
    return innerModel;
  }
};

viewModel.roomDuplicates = ko.computed(function() {
  return viewModel.stations().map(function(item) {
    return (item.settings.room ? item.settings.room() : '')
  })
})

viewModel.rooms = ko.computed(function() {
  return viewModel.roomDuplicates().filter(onlyUnique)
})

ko.applyBindings(viewModel);

var socket = io.connect('//:5001')

$.get( "/api/stations", function( data ) {
})
  .done(function(data) {
    ko.mapping.fromJS(data, mapping, viewModel.stations)
    socket.on('change', function (data) {
      console.log(data);
      if (data.type == 'remove') {
        viewModel.stations.remove(function(item) {
          return item._id() == data.content
        })
      }
      if (data.type == 'insert') {
        viewModel.stations.push(ko.mapping.fromJS(data.content, mapping))
      }
      if (data.type == 'update') {
        var match = ko.utils.arrayFirst(viewModel.stations(), function(item) {
          return data.content._id === item._id();
        });
        if (match) {
          viewModel.stations.splice(viewModel.stations.indexOf(match),1,ko.mapping.fromJS(data.content));
        }
      }
      if (data.type == 'notify') {
      }

    });
  })

var availableDeviceClick = function (item, configured, macaddress) {
  var value = ko.toJS(item);
  var devices = ko.toJS(configured) || [];
  if (devices == 'all') {
    devices = [];
  }
  devices.push(value);

  var post = {};
  post.key = "settings.devices";
  post.value = devices;

  $.ajax({
    url: '/api/stations/' + macaddress() + '/partial',
    type: 'POST',
    data: post
  })
};

var actionStationManagers = function(roomId, action) {
  ko.utils.arrayForEach(viewModel.stations(), function(station) {
    if (station.settings.room() === roomId) {
      var post = new Object();
      post.station_macaddress = station.settings.macaddress();
      post.id = "Station";
      post.command_url = "manager";
      post.action = action;
      actionStationPost(post);
    }
  })
}

var actionStations = function(roomId, action) {
  ko.utils.arrayForEach(viewModel.stations(), function(station) {
    if (station.settings.room() === roomId) {
      var post = new Object();
      post.station_macaddress = station.settings.macaddress();
      post.id = "all";
      post.command_url = "command";
      post.action = action;
      actionStationPost(post);
    }
  })
}

var actionStationManager = function(macaddress, action) {
  var post = new Object();
  post.station_macaddress = macaddress;
  post.id = "Station";
  post.command_url = "manager";
  post.action = action;
  actionStationPost(post);
}

$("body").on("click", ".actionOnclick", function (e) {
  var post = new Object();
  post.station_macaddress = $(e.currentTarget).closest("[data-macaddress]").data('macaddress');
  post.id = $(e.currentTarget).data('id');
  post.command_url = "command";
  post.action = $(e.currentTarget).data('action');
  actionStationPost(post);
});

var actionDevice = function(macaddress, device, action) {
  var post = new Object();
  post.station_macaddress = macaddress;
  post.id = device;
  post.command_url = "command";
  post.action = action;
  actionStationPost(post);
}

var actionStationPost = function(post) {
  console.log(post)
  $.ajax({
    url: '/api/station/' + post.station_macaddress + '/action',
    type: 'POST',
    data: post
  })
}

var removeStation = function(data, event) {
  $.ajax({
    url: "/api/station/"+ data.settings.macaddress(),
    type: 'DELETE'
  })
    .done(function(data) {
      console.log( "removed station", JSON.stringify(data) );
    })
}

var removeStationRoom = function(data, event) {
  $.ajax({
    url: "/api/stations/"+ data.settings.macaddress()  + '/partial',
    type: 'POST',
    data: {
      key: 'settings.room',
      value: ''
    }
  })
    .done(function(data) {
      console.log( "removed station", JSON.stringify(data) );
    })
}

function submitStation(data, event) {
  var $form = $(event.currentTarget).parents('#add-station');

  $.ajax({
    type: "POST",
    url: "/api/station",
    data: data,
  })
    .done(function() {
      $form.collapse('hide')
    })
}

var macRewrite = function(macaddress) {
  if (!macaddress) { return false }
  return macaddress.replace(/-\s*/g, ":")
}

<|endoftext|>


<commit_before>var MongoClient = require('mongodb').MongoClient,
  config = require('./config.json'),
  logging = require('./logging'),
  validator = require('validator'),
  format = require('util').format;

var database;

exports.init = function(callback) {
  MongoClient.connect(config.mongodb.host, function (err, db) {
    if (err) {
      callback(err);
      return;
    }

    database = db;
    callback();
  });
};

exports.save = function(req, res, next) {
  if (!req.params.email || !validator.isEmail(validator.toString(req.params.email))) {
    res.send(400, {
      message: 'Email is a required field'
    });
    return;
  }

  var collection = database.collection('developerPlusComingSoon');

  collection.insert({
    email: validator.toString(req.params.email)
  }, function (err) {
    res.send(err ? 503 : 200);
  });
};
<commit_msg>tripping whichspace from email input<commit_after>var MongoClient = require('mongodb').MongoClient,
  config = require('./config.json'),
  logging = require('./logging'),
  validator = require('validator'),
  format = require('util').format;

var database;

exports.init = function(callback) {
  MongoClient.connect(config.mongodb.host, function (err, db) {
    if (err) {
      callback(err);
      return;
    }

    database = db;
    callback();
  });
};

exports.save = function(req, res, next) {
  if (!req.params.email || !validator.isEmail(validator.toString(req.params.email))) {
    res.send(400, {
      message: 'Email is a required field'
    });
    return;
  }

  var collection = database.collection('developerPlusComingSoon');

  collection.insert({
    email: validator.trim(validator.toString(req.params.email))
  }, function (err) {
    res.send(err ? 503 : 200);
  });
};
<|endoftext|>


<commit_before>/**
 * The viewLocator module collaborates with the viewEngine module to provide views (literally dom sub-trees) to other parts of the framework as needed. The primary consumer of the viewLocator is the composition module.
 * @module viewLocator
 * @requires system
 * @requires viewEngine
 */
define(['durandal/system', 'durandal/viewEngine'], function (system, viewEngine) {
    function findInElements(nodes, url) {
        for (var i = 0; i < nodes.length; i++) {
            var current = nodes[i];
            var existingUrl = current.getAttribute('data-view');
            if (existingUrl == url) {
                return current;
            }
        }
    }

    function escape(str) {
        return (str + '').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
    }

    /**
     * @class ViewLocatorModule
     * @static
     */
    return {
        /**
         * Allows you to set up a convention for mapping module folders to view folders. It is a convenience method that customizes `convertModuleIdToViewId` and `translateViewIdToArea` under the covers.
         * @method useConvention
         * @param {string} [modulesPath] A string to match in the path and replace with the viewsPath. If not specified, the match is 'viewmodels'.
         * @param {string} [viewsPath] The replacement for the modulesPath. If not specified, the replacement is 'views'.
         * @param {string} [areasPath] Partial views are mapped to the "views" folder if not specified. Use this parameter to change their location.
         */
        useConvention: function(modulesPath, viewsPath, areasPath) {
            modulesPath = modulesPath || 'viewmodels';
            viewsPath = viewsPath || 'views';
            areasPath = areasPath || viewsPath;

            var reg = new RegExp(escape(modulesPath), 'gi');

            this.convertModuleIdToViewId = function (moduleId) {
                return moduleId.replace(reg, viewsPath);
            };

            this.translateViewIdToArea = function (viewId, area) {
                if (!area || area == 'partial') {
                    return areasPath + '/' + viewId;
                }

                return areasPath + '/' + area + '/' + viewId;
            };
        },
        /**
         * Maps an object instance to a view instance.
         * @method locateViewForObject
         * @param {object} obj The object to locate the view for.
         * @param {string} [area] The area to translate the view to.
         * @param {DOMElement[]} [elementsToSearch] An existing set of elements to search first.
         * @return {Promise} A promise of the view.
         */
        locateViewForObject: function(obj, area, elementsToSearch) {
            var view;

            if (obj.getView) {
                view = obj.getView();
                if (view) {
                    return this.locateView(view, area, elementsToSearch);
                }
            }

            if (obj.viewUrl) {
                return this.locateView(obj.viewUrl, area, elementsToSearch);
            }

            var id = system.getModuleId(obj);
            if (id) {
                return this.locateView(this.convertModuleIdToViewId(id), area, elementsToSearch);
            }

            return this.locateView(this.determineFallbackViewId(obj), area, elementsToSearch);
        },
        /**
         * Converts a module id into a view id. By default the ids are the same.
         * @method convertModuleIdToViewId
         * @param {string} moduleId The module id.
         * @return {string} The view id.
         */
        convertModuleIdToViewId: function(moduleId) {
            return moduleId;
        },
        /**
         * If no view id can be determined, this function is called to genreate one. By default it attempts to determine the object's type and use that.
         * @method determineFallbackViewId
         * @param {object} obj The object to determine the fallback id for.
         * @return {string} The view id.
         */
        determineFallbackViewId: function (obj) {
            var funcNameRegex = /function (.{1,})\(/;
            var results = (funcNameRegex).exec((obj).constructor.toString());
            var typeName = (results && results.length > 1) ? results[1] : "";

            return 'views/' + typeName;
        },
        /**
         * Takes a view id and translates it into a particular area. By default, no translation occurs.
         * @method translateViewIdToArea
         * @param {string} viewId The view id.
         * @param {string} area The area to translate the view to.
         * @return {string} The translated view id.
         */
        translateViewIdToArea: function (viewId, area) {
            return viewId;
        },
        /**
         * Locates the specified view.
         * @method locateView
         * @param {string|DOMElement} viewOrUrlOrId A view, view url or view id to locate.
         * @param {string} [area] The area to translate the view to.
         * @param {DOMElement[]} [elementsToSearch] An existing set of elements to search first.
         * @return {Promise} A promise of the view.
         */
        locateView: function(viewOrUrlOrId, area, elementsToSearch) {
            if (typeof viewOrUrlOrId === 'string') {
                var viewId;

                if (viewEngine.isViewUrl(viewOrUrlOrId)) {
                    viewId = viewEngine.convertViewUrlToViewId(viewOrUrlOrId);
                } else {
                    viewId = viewOrUrlOrId;
                }

                if (area) {
                    viewId = this.translateViewIdToArea(viewId, area);
                }

                if (elementsToSearch) {
                    var existing = findInElements(elementsToSearch, viewId);
                    if (existing) {
                        return system.defer(function(dfd) {
                            dfd.resolve(existing);
                        }).promise();
                    }
                }

                return viewEngine.createView(viewId);
            }

            return system.defer(function(dfd) {
                dfd.resolve(viewOrUrlOrId);
            }).promise();
        }
    };
});<commit_msg>Fix bug where IE will fail to load view due to wrong typeName In the 'determineFallbackViewId' function in viewLocator, the code will attempt to read out constructor function name using a regex. The regex assume that there are no trailing spaces between the function name and the paranthesis. IE seem to inject a space there. This causes the function to return something like 'views/MyConstructor .html' (notice the space)<commit_after>/**
 * The viewLocator module collaborates with the viewEngine module to provide views (literally dom sub-trees) to other parts of the framework as needed. The primary consumer of the viewLocator is the composition module.
 * @module viewLocator
 * @requires system
 * @requires viewEngine
 */
define(['durandal/system', 'durandal/viewEngine'], function (system, viewEngine) {
    function findInElements(nodes, url) {
        for (var i = 0; i < nodes.length; i++) {
            var current = nodes[i];
            var existingUrl = current.getAttribute('data-view');
            if (existingUrl == url) {
                return current;
            }
        }
    }

    function escape(str) {
        return (str + '').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
    }

    /**
     * @class ViewLocatorModule
     * @static
     */
    return {
        /**
         * Allows you to set up a convention for mapping module folders to view folders. It is a convenience method that customizes `convertModuleIdToViewId` and `translateViewIdToArea` under the covers.
         * @method useConvention
         * @param {string} [modulesPath] A string to match in the path and replace with the viewsPath. If not specified, the match is 'viewmodels'.
         * @param {string} [viewsPath] The replacement for the modulesPath. If not specified, the replacement is 'views'.
         * @param {string} [areasPath] Partial views are mapped to the "views" folder if not specified. Use this parameter to change their location.
         */
        useConvention: function(modulesPath, viewsPath, areasPath) {
            modulesPath = modulesPath || 'viewmodels';
            viewsPath = viewsPath || 'views';
            areasPath = areasPath || viewsPath;

            var reg = new RegExp(escape(modulesPath), 'gi');

            this.convertModuleIdToViewId = function (moduleId) {
                return moduleId.replace(reg, viewsPath);
            };

            this.translateViewIdToArea = function (viewId, area) {
                if (!area || area == 'partial') {
                    return areasPath + '/' + viewId;
                }

                return areasPath + '/' + area + '/' + viewId;
            };
        },
        /**
         * Maps an object instance to a view instance.
         * @method locateViewForObject
         * @param {object} obj The object to locate the view for.
         * @param {string} [area] The area to translate the view to.
         * @param {DOMElement[]} [elementsToSearch] An existing set of elements to search first.
         * @return {Promise} A promise of the view.
         */
        locateViewForObject: function(obj, area, elementsToSearch) {
            var view;

            if (obj.getView) {
                view = obj.getView();
                if (view) {
                    return this.locateView(view, area, elementsToSearch);
                }
            }

            if (obj.viewUrl) {
                return this.locateView(obj.viewUrl, area, elementsToSearch);
            }

            var id = system.getModuleId(obj);
            if (id) {
                return this.locateView(this.convertModuleIdToViewId(id), area, elementsToSearch);
            }

            return this.locateView(this.determineFallbackViewId(obj), area, elementsToSearch);
        },
        /**
         * Converts a module id into a view id. By default the ids are the same.
         * @method convertModuleIdToViewId
         * @param {string} moduleId The module id.
         * @return {string} The view id.
         */
        convertModuleIdToViewId: function(moduleId) {
            return moduleId;
        },
        /**
         * If no view id can be determined, this function is called to genreate one. By default it attempts to determine the object's type and use that.
         * @method determineFallbackViewId
         * @param {object} obj The object to determine the fallback id for.
         * @return {string} The view id.
         */
        determineFallbackViewId: function (obj) {
            var funcNameRegex = /function (.{1,})\(/;
            var results = (funcNameRegex).exec((obj).constructor.toString());
            var typeName = (results && results.length > 1) ? results[1] : "";
            typeName = typeName.trim();
            return 'views/' + typeName;
        },
        /**
         * Takes a view id and translates it into a particular area. By default, no translation occurs.
         * @method translateViewIdToArea
         * @param {string} viewId The view id.
         * @param {string} area The area to translate the view to.
         * @return {string} The translated view id.
         */
        translateViewIdToArea: function (viewId, area) {
            return viewId;
        },
        /**
         * Locates the specified view.
         * @method locateView
         * @param {string|DOMElement} viewOrUrlOrId A view, view url or view id to locate.
         * @param {string} [area] The area to translate the view to.
         * @param {DOMElement[]} [elementsToSearch] An existing set of elements to search first.
         * @return {Promise} A promise of the view.
         */
        locateView: function(viewOrUrlOrId, area, elementsToSearch) {
            if (typeof viewOrUrlOrId === 'string') {
                var viewId;

                if (viewEngine.isViewUrl(viewOrUrlOrId)) {
                    viewId = viewEngine.convertViewUrlToViewId(viewOrUrlOrId);
                } else {
                    viewId = viewOrUrlOrId;
                }

                if (area) {
                    viewId = this.translateViewIdToArea(viewId, area);
                }

                if (elementsToSearch) {
                    var existing = findInElements(elementsToSearch, viewId);
                    if (existing) {
                        return system.defer(function(dfd) {
                            dfd.resolve(existing);
                        }).promise();
                    }
                }

                return viewEngine.createView(viewId);
            }

            return system.defer(function(dfd) {
                dfd.resolve(viewOrUrlOrId);
            }).promise();
        }
    };
});<|endoftext|>


<commit_before>//= require jquery.hoverIntent

window.ChannelViewLayout = Backbone.Marionette.Layout.extend({
  tagName: "div",

  template: 'channels/channel',

  regions: {
    factList: '#facts_for_channel',
    activityList: '#activity_for_channel'
  },

  templateHelpers: function(){
    return {
      activities_link: function(){ return this.link + "/activities";}
    };
  },

  initialize: function(opts) {
    this.initSubChannels();
    this.on('render', _.bind(function(){
      this.renderSubChannels();
      this.initSubChannelMenu();
      this.initAddToChannel();
      this.$('header .authority').tooltip({title: 'Authority of ' + this.model.attributes.created_by.username + ' on "' + this.model.attributes.title + '"'});
    },this));
  },

  initSubChannels: function() {
    if (this.model.get('inspectable?')){
      this.subchannelView = new SubchannelsView({
        collection: this.model.subchannels(),
        model: this.model
      });
    }
  },

  renderSubChannels: function(){
    if (this.subchannelView) {
      this.subchannelView.render();
      this.$('header .button-wrap').after(this.subchannelView.el);
    }
  },

  initSubChannelMenu: function() {
    if( this.model.get("followable?") ) {
      var addToChannelButton = this.$("#add-to-channel");
      var followChannelMenu =this.$("#follow-channel");

      followChannelMenu.css({"left": addToChannelButton.position().left});

      addToChannelButton.hoverIntent(
        function() { followChannelMenu.fadeIn("fast"); },
        function() { followChannelMenu.delay(600).fadeOut("fast"); }
      );

      followChannelMenu.on("mouseover", function() {
        followChannelMenu.stop(true, true).show();
      });

      followChannelMenu.on("mouseout", function() {
       if (!followChannelMenu.find("input#channel_title").is(":focus")) {
          followChannelMenu.delay(500).fadeOut("fast");
        }
      });
    }
  },

  initAddToChannel: function() {
    if ( this.$('#add-to-channel') && typeof currentUser !== "undefined" && typeof currentChannel !== "undefined" ) {
      this.addToChannelView = new AddToChannelView({
        collection: currentUser.channels,
        el: this.$('#follow-channel'),
        model: currentChannel,
        containingChannels: currentChannel.getOwnContainingChannels()
      }).render();
    }
  },
  onClose: function() {
    if ( this.addToChannelView ) {
      this.addToChannelView.close();
    }

    if ( this.subchannelView ) {
      this.subchannelView.close();
    }
  },
  activateTab: function(selector) {
    var tabs = this.$('.tabs ul');
    tabs.find('li').removeClass('active');
    tabs.find(selector).addClass('active');
  }

});

window.ChannelView = ChannelViewLayout.extend({

  getFactsView: function() {
    return facts_view = new FactsView({
      collection: new ChannelFacts([],{
        channel: this.model
      }),
      model: this.model
    });
  },

  onRender: function() {
    this.factList.show(this.getFactsView());
    this.activateTab(".factlinks");
  }
});

window.ChannelActivitiesView = ChannelViewLayout.extend({

  getActivitiesView: function(){
    return new ActivitiesView({collection: this.collection});
  },

  onRender: function() {
    this.activityList.show(this.getActivitiesView());
    this.activateTab('.activity');
  }

});
<commit_msg>Removed old assingment<commit_after>//= require jquery.hoverIntent

window.ChannelViewLayout = Backbone.Marionette.Layout.extend({
  tagName: "div",

  template: 'channels/channel',

  regions: {
    factList: '#facts_for_channel',
    activityList: '#activity_for_channel'
  },

  templateHelpers: function(){
    return {
      activities_link: function(){ return this.link + "/activities";}
    };
  },

  initialize: function(opts) {
    this.initSubChannels();
    this.on('render', _.bind(function(){
      this.renderSubChannels();
      this.initSubChannelMenu();
      this.initAddToChannel();
      this.$('header .authority').tooltip({title: 'Authority of ' + this.model.attributes.created_by.username + ' on "' + this.model.attributes.title + '"'});
    },this));
  },

  initSubChannels: function() {
    if (this.model.get('inspectable?')){
      this.subchannelView = new SubchannelsView({
        collection: this.model.subchannels(),
        model: this.model
      });
    }
  },

  renderSubChannels: function(){
    if (this.subchannelView) {
      this.subchannelView.render();
      this.$('header .button-wrap').after(this.subchannelView.el);
    }
  },

  initSubChannelMenu: function() {
    if( this.model.get("followable?") ) {
      var addToChannelButton = this.$("#add-to-channel");
      var followChannelMenu =this.$("#follow-channel");

      followChannelMenu.css({"left": addToChannelButton.position().left});

      addToChannelButton.hoverIntent(
        function() { followChannelMenu.fadeIn("fast"); },
        function() { followChannelMenu.delay(600).fadeOut("fast"); }
      );

      followChannelMenu.on("mouseover", function() {
        followChannelMenu.stop(true, true).show();
      });

      followChannelMenu.on("mouseout", function() {
       if (!followChannelMenu.find("input#channel_title").is(":focus")) {
          followChannelMenu.delay(500).fadeOut("fast");
        }
      });
    }
  },

  initAddToChannel: function() {
    if ( this.$('#add-to-channel') && typeof currentUser !== "undefined" && typeof currentChannel !== "undefined" ) {
      this.addToChannelView = new AddToChannelView({
        collection: currentUser.channels,
        el: this.$('#follow-channel'),
        model: currentChannel,
        containingChannels: currentChannel.getOwnContainingChannels()
      }).render();
    }
  },
  onClose: function() {
    if ( this.addToChannelView ) {
      this.addToChannelView.close();
    }

    if ( this.subchannelView ) {
      this.subchannelView.close();
    }
  },
  activateTab: function(selector) {
    var tabs = this.$('.tabs ul');
    tabs.find('li').removeClass('active');
    tabs.find(selector).addClass('active');
  }

});

window.ChannelView = ChannelViewLayout.extend({

  getFactsView: function() {
    return new FactsView({
      collection: new ChannelFacts([],{
        channel: this.model
      }),
      model: this.model
    });
  },

  onRender: function() {
    this.factList.show(this.getFactsView());
    this.activateTab(".factlinks");
  }
});

window.ChannelActivitiesView = ChannelViewLayout.extend({

  getActivitiesView: function(){
    return new ActivitiesView({collection: this.collection});
  },

  onRender: function() {
    this.activityList.show(this.getActivitiesView());
    this.activateTab('.activity');
  }

});
<|endoftext|>