<commit_before>const _ = require('lodash')
const md = require('./template')
const env = require('../lib/env')

module.exports = prBody

const branchFailed = () => md`
💥 Tests on this branch are failing. Here’s how to proceed.

To solve the issue, first find out which of the dependency’s updates is causing the problem. Then fix your code to accomodate the changes in the updated dependency. [next-update](https://www.npmjs.com/package/next-update) is a really handy tool to help you with this.

Then push your changes to this branch and merge it.
`

const enablePrivatePackage = ({installationId, secret}) => `
📦 How to enable private scoped packages

Public scoped packages (\`@scope/name\`) work out of the box, but private scoped packages require an additional setup step:

\`\`\`bash
# Install npm's wombat CLI to create npm hooks
npm install --global wombat

# Adding a single private scoped package
wombat hook add @scope/name https://${env.HOOKS_HOST}/npm/${installationId} ${secret}

# Adding all packages of a scope
wombat hook add @scope https://${env.HOOKS_HOST}/npm/${installationId} ${secret}

# Adding all packages by a specific owner
wombat hook add --type owner substack https://${env.HOOKS_HOST}/npm/${installationId} ${secret}

\`\`\`
`

const badgeAddedText = ({badgeUrl}) => md`
🏷 How to check the status of this repository

Greenkeeper adds a badge to your README which indicates the status of this repository.

This is what your badge looks like right now :point_right:  ![Greenkeeper badge](${badgeUrl})
`

const travisModifiedText = () => md`
🏗 How to configure Travis CI

Greenkeeper has added a rule to your \`.travis.yml\` that whitelists Greenkeeper branches, which are created when your dependencies are updated. Travis CI will run your tests on these branches automatically to see if they still pass.

No additional setup is required 😊

`

const updatePullRequestText = ({ newBranch }) => md`
👩💻 How to update this pull request

\`\`\`bash
  # Change into your repository’s directory
  git fetch
  git checkout ${newBranch}
  npm install-test
  # Adapt your code until everything works again
  git commit -m 'chore: adapt code to updated dependencies'
  git push origin ${newBranch}
\`\`\`
`

const howToIgnoreDependencies = ({ghRepo, newBranch}) => md`
🙈 How to ignore certain dependencies

You may have good reasons for not wanting to update to a certain dependency right now. In this case, you can [change the dependency’s version string in the \`package.json\` file back to whatever you prefer](${ghRepo.html_url}/edit/${newBranch}/package.json).

To make sure Greenkeeper doesn’t nag you again on the next update, add a \`greenkeeper.ignore\` field to your \`package.json\`, containing a list of dependencies you don’t want to update.

\`\`\`js
// package.json
{
  …
  "greenkeeper": {
    "ignore": [
      "package-names",
      "you-want-me-to-ignore"
    ]
  }
}
\`\`\`
`

const howToIgnoreDependenciesInGroup = ({ghRepo, newBranch}) => md`
🙈 How to ignore certain dependencies for this group

You may have good reasons for not wanting to update to a certain dependency right now. In this case, you can [change the dependency’s version string in the \`package.json\` file back to whatever you prefer](${ghRepo.html_url}/edit/${newBranch}/package.json).

To make sure Greenkeeper doesn’t nag you again on the next update of this group, you can add the dependency to this group’s \`ignore\` field in the \`greenkeeper.json\`, for example:
\`\`\`js
// greenkeeper.json
{
  "groups": {
    "frontend": {
      "packages": [
        "frontend/package.json",
        "admin-dashboard/package.json"
      ],
      "ignore": [
        "eslint",
        "standard"
      ]
    }
  }
}
\`\`\`
`

const howTheUpdatesWillLookLike = () => md`
✨ How do dependency updates work with Greenkeeper?

After you merge this pull request, **Greenkeeper will create a new branch whenever a  dependency is updated**, with the new version applied. The branch creation should trigger your testing services and check whether your code still works with the new dependency version. Depending on the the results of these tests Greenkeeper will try to open meaningful and helpful pull requests and issues, so your dependencies remain working and up-to-date.

\`\`\`diff
-  "underscore": "^1.6.0"
+  "underscore": "^1.7.0"
\`\`\`

The above example shows an in-range update. \`1.7.0\` is included in the old \`^1.6.0\` range, because of the [caret \`^\` character ](https://docs.npmjs.com/misc/semver#ranges).
When the test services report success Greenkeeper will silently delete the branch again, because no action needs to be taken – everything is fine.

However, should the tests fail, Greenkeeper will create an issue to inform you about the problem immediately.

This way, you’ll never be surprised by a dependency breaking your code. As long as everything still works, Greenkeeper will stay out of your way, and as soon as something goes wrong, you’ll be the first to know.

\`\`\`diff
-  "lodash": "^3.0.0"
+  "lodash": "^4.0.0"
\`\`\`

In this example, the new version \`4.0.0\` is _not_ included in the old \`^3.0.0\` range.
For version updates like these – let’s call them “out of range” updates – you’ll receive a pull request.

This means that **you no longer need to check for new versions manually** – Greenkeeper will keep you up to date automatically.

These pull requests not only serve as reminders to update: If you have solid tests and good coverage, and the pull requests passes those tests, you can very likely just merge it and release a new version of your software straight away :shipit:

To get a better idea of which ranges apply to which releases, check out the extremely useful [semver calculator](https://semver.npmjs.com/) provided by npm.
`

const faqText = () => md`
FAQ and help

There is a collection of [frequently asked questions](https://greenkeeper.io/faq.html). If those don’t help, you can always [ask the humans behind Greenkeeper](https://github.com/greenkeeperio/greenkeeper/issues/new).
`

// needs to handle files as an array of arrays!
function hasLockFileText (files) {
  if (!files) return
  const lockFiles = ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'].filter((key) => {
    if (_.isArray(files[key]) && files[key].length) {
      return true
    }
    if (files[key] === true) {
      return true
    }
    return false
  })
  if (lockFiles.length === 0) return
  const lockFile = lockFiles[0]
  return md`⚠ Greenkeeper has found a ${md.code(lockFile)} file in this repository. Please use [greenkeeper-lockfile](https://github.com/greenkeeperio/greenkeeper-lockfile) to make sure this gets updated as well.`
}

const mainMessage = ({enabled, depsUpdated, groupName}) => {
  if (groupName && depsUpdated) return md`This pull request **updates all your dependencies in the group \`${groupName}\` to their latest version**. Having them all up to date really is the best starting point for keeping up with new releases. As long as you have the group defined in your \`greenkeeper.json\`, Greenkeeper will look out for further dependency updates relevant to this group and make sure to always handle them together and in real-time.`
  if (enabled) return 'All of your dependencies are already up-to-date, so this repository was enabled right away. Good job :thumbsup:'
  if (depsUpdated) return 'This pull request **updates all your dependencies to their latest version**. Having them all up to date really is the best starting point for keeping up with new releases. Greenkeeper will look out for further dependency updates and make sure to handle them in isolation and in real-time, but only after **you merge this pull request**.'
  return '' // no updates, but private repository
}

const greenkeeperConfigInfoMessage = (info) => {
  if (!info) return ''
  let message = ''
  if (info.isMonorepo) {
    message += '📦 📦  Greenkeeper has detected multiple `package.json` files. '
  }
  if (info.action === 'new') {
    message += 'They have all been added to a new `greenkeeper.json` config file. They’ve been collected in a group called `default`, meaning that all of them will receive updates together. You can rename, add and remove groups and freely assign each `package.json` to whichever group you like. It’s common, for example, to have one `frontend` group and one `backend` group, each with a couple of `package.json` files. In any case, all files in a group will have their updates collected into single PRs and issues. '
  }
  if (info.action === 'updated') {
    message += 'Since this repo already has a `greenkeeper.json` config file with defined groups, Greenkeeper has only checked whether they’re still valid. '
    if (info.deletedPackageFiles.length > 0) {
      message += 'The follwing `package.json` files could no longer be found in the repo and have been removed from your groups config: `' + info.deletedPackageFiles.join(', ') + '`. '
    }
    if (info.deletedGroups.length > 0) {
      message += 'Also, groups which no longer have any entries have been removed: `' + info.deletedGroups.join(', ') + '`. '
    }
  }
  if (info.action === 'added-groups-only') {
    message += 'Since this repo already has a `greenkeeper.json` config file without any defined groups, Greenkeeper has  added all of the `package.json` files to a group called `default`, meaning that all of them will receive updates together. You can rename, add and remove groups and freely assign each `package.json` to whichever group you like. It’s common, for example, to have one `frontend` group and one `backend` group, each with a couple of `package.json` files. In any case, all files in a group will have their updates collected into single PRs and issues. '
  }
  return message
}

const closeMessages = (issueNumbers) => {
  if (issueNumbers && issueNumbers.length === 0) { return }
  return '\nCloses: #' + issueNumbers.join(', #')
}

function prBody ({ghRepo, success, secret, installationId, newBranch, badgeUrl, travisModified, enabled, depsUpdated, accountTokenUrl, files, greenkeeperConfigInfo, groupName, closes}) {
  return md`
${!groupName && `Let’s get started with automated dependency management for ${ghRepo.name} :muscle:`}

${!groupName && hasLockFileText(files)}

${mainMessage({enabled, depsUpdated, groupName})}

${!groupName && !enabled && '**Important: Greenkeeper will only start watching this repository’s dependency updates after you merge this initial pull request**.'}

${!groupName && secret && accountTokenUrl && `💸  **Warning** 💸 Enabling Greenkeeper on this repository by merging this pull request might increase your monthly payment. If you’re unsure, please [check your billing status](${accountTokenUrl}).`}

${!groupName && greenkeeperConfigInfoMessage(greenkeeperConfigInfo)}

---
${
  _.compact([
    depsUpdated && !success && branchFailed(),
    secret && enablePrivatePackage({secret, installationId}),
    badgeUrl && badgeAddedText({badgeUrl}),
    travisModified && travisModifiedText(),
    groupName ? howToIgnoreDependenciesInGroup({ghRepo, newBranch}) : howToIgnoreDependencies({ghRepo, newBranch}),
    updatePullRequestText({ghRepo, newBranch}),
    howTheUpdatesWillLookLike(),
    faqText()
  ]).map(text => `<details>${text}</details>`)
}
${closeMessages(closes)}

---

Good luck with your project and see you soon :sparkles:

Your [Greenkeeper](https://greenkeeper.io) bot :palm_tree:
`
}
<commit_msg>fix: not enough bang, too much and<commit_after>const _ = require('lodash')
const md = require('./template')
const env = require('../lib/env')

module.exports = prBody

const branchFailed = () => md`
💥 Tests on this branch are failing. Here’s how to proceed.

To solve the issue, first find out which of the dependency’s updates is causing the problem. Then fix your code to accomodate the changes in the updated dependency. [next-update](https://www.npmjs.com/package/next-update) is a really handy tool to help you with this.

Then push your changes to this branch and merge it.
`

const enablePrivatePackage = ({installationId, secret}) => `
📦 How to enable private scoped packages

Public scoped packages (\`@scope/name\`) work out of the box, but private scoped packages require an additional setup step:

\`\`\`bash
# Install npm's wombat CLI to create npm hooks
npm install --global wombat

# Adding a single private scoped package
wombat hook add @scope/name https://${env.HOOKS_HOST}/npm/${installationId} ${secret}

# Adding all packages of a scope
wombat hook add @scope https://${env.HOOKS_HOST}/npm/${installationId} ${secret}

# Adding all packages by a specific owner
wombat hook add --type owner substack https://${env.HOOKS_HOST}/npm/${installationId} ${secret}

\`\`\`
`

const badgeAddedText = ({badgeUrl}) => md`
🏷 How to check the status of this repository

Greenkeeper adds a badge to your README which indicates the status of this repository.

This is what your badge looks like right now :point_right:  ![Greenkeeper badge](${badgeUrl})
`

const travisModifiedText = () => md`
🏗 How to configure Travis CI

Greenkeeper has added a rule to your \`.travis.yml\` that whitelists Greenkeeper branches, which are created when your dependencies are updated. Travis CI will run your tests on these branches automatically to see if they still pass.

No additional setup is required 😊

`

const updatePullRequestText = ({ newBranch }) => md`
👩💻 How to update this pull request

\`\`\`bash
  # Change into your repository’s directory
  git fetch
  git checkout ${newBranch}
  npm install-test
  # Adapt your code until everything works again
  git commit -m 'chore: adapt code to updated dependencies'
  git push origin ${newBranch}
\`\`\`
`

const howToIgnoreDependencies = ({ghRepo, newBranch}) => md`
🙈 How to ignore certain dependencies

You may have good reasons for not wanting to update to a certain dependency right now. In this case, you can [change the dependency’s version string in the \`package.json\` file back to whatever you prefer](${ghRepo.html_url}/edit/${newBranch}/package.json).

To make sure Greenkeeper doesn’t nag you again on the next update, add a \`greenkeeper.ignore\` field to your \`package.json\`, containing a list of dependencies you don’t want to update.

\`\`\`js
// package.json
{
  …
  "greenkeeper": {
    "ignore": [
      "package-names",
      "you-want-me-to-ignore"
    ]
  }
}
\`\`\`
`

const howToIgnoreDependenciesInGroup = ({ghRepo, newBranch}) => md`
🙈 How to ignore certain dependencies for this group

You may have good reasons for not wanting to update to a certain dependency right now. In this case, you can [change the dependency’s version string in the \`package.json\` file back to whatever you prefer](${ghRepo.html_url}/edit/${newBranch}/package.json).

To make sure Greenkeeper doesn’t nag you again on the next update of this group, you can add the dependency to this group’s \`ignore\` field in the \`greenkeeper.json\`, for example:
\`\`\`js
// greenkeeper.json
{
  "groups": {
    "frontend": {
      "packages": [
        "frontend/package.json",
        "admin-dashboard/package.json"
      ],
      "ignore": [
        "eslint",
        "standard"
      ]
    }
  }
}
\`\`\`
`

const howTheUpdatesWillLookLike = () => md`
✨ How do dependency updates work with Greenkeeper?

After you merge this pull request, **Greenkeeper will create a new branch whenever a  dependency is updated**, with the new version applied. The branch creation should trigger your testing services and check whether your code still works with the new dependency version. Depending on the the results of these tests Greenkeeper will try to open meaningful and helpful pull requests and issues, so your dependencies remain working and up-to-date.

\`\`\`diff
-  "underscore": "^1.6.0"
+  "underscore": "^1.7.0"
\`\`\`

The above example shows an in-range update. \`1.7.0\` is included in the old \`^1.6.0\` range, because of the [caret \`^\` character ](https://docs.npmjs.com/misc/semver#ranges).
When the test services report success Greenkeeper will silently delete the branch again, because no action needs to be taken – everything is fine.

However, should the tests fail, Greenkeeper will create an issue to inform you about the problem immediately.

This way, you’ll never be surprised by a dependency breaking your code. As long as everything still works, Greenkeeper will stay out of your way, and as soon as something goes wrong, you’ll be the first to know.

\`\`\`diff
-  "lodash": "^3.0.0"
+  "lodash": "^4.0.0"
\`\`\`

In this example, the new version \`4.0.0\` is _not_ included in the old \`^3.0.0\` range.
For version updates like these – let’s call them “out of range” updates – you’ll receive a pull request.

This means that **you no longer need to check for new versions manually** – Greenkeeper will keep you up to date automatically.

These pull requests not only serve as reminders to update: If you have solid tests and good coverage, and the pull requests passes those tests, you can very likely just merge it and release a new version of your software straight away :shipit:

To get a better idea of which ranges apply to which releases, check out the extremely useful [semver calculator](https://semver.npmjs.com/) provided by npm.
`

const faqText = () => md`
FAQ and help

There is a collection of [frequently asked questions](https://greenkeeper.io/faq.html). If those don’t help, you can always [ask the humans behind Greenkeeper](https://github.com/greenkeeperio/greenkeeper/issues/new).
`

// needs to handle files as an array of arrays!
function hasLockFileText (files) {
  if (!files) return
  const lockFiles = ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'].filter((key) => {
    if (_.isArray(files[key]) && files[key].length) {
      return true
    }
    if (files[key] === true) {
      return true
    }
    return false
  })
  if (lockFiles.length === 0) return
  const lockFile = lockFiles[0]
  return md`⚠ Greenkeeper has found a ${md.code(lockFile)} file in this repository. Please use [greenkeeper-lockfile](https://github.com/greenkeeperio/greenkeeper-lockfile) to make sure this gets updated as well.`
}

const mainMessage = ({enabled, depsUpdated, groupName}) => {
  if (groupName && depsUpdated) return md`This pull request **updates all your dependencies in the group \`${groupName}\` to their latest version**. Having them all up to date really is the best starting point for keeping up with new releases. As long as you have the group defined in your \`greenkeeper.json\`, Greenkeeper will look out for further dependency updates relevant to this group and make sure to always handle them together and in real-time.`
  if (enabled) return 'All of your dependencies are already up-to-date, so this repository was enabled right away. Good job :thumbsup:'
  if (depsUpdated) return 'This pull request **updates all your dependencies to their latest version**. Having them all up to date really is the best starting point for keeping up with new releases. Greenkeeper will look out for further dependency updates and make sure to handle them in isolation and in real-time, but only after **you merge this pull request**.'
  return '' // no updates, but private repository
}

const greenkeeperConfigInfoMessage = (info) => {
  if (!info) return ''
  let message = ''
  if (info.isMonorepo) {
    message += '📦 📦  Greenkeeper has detected multiple `package.json` files. '
  }
  if (info.action === 'new') {
    message += 'They have all been added to a new `greenkeeper.json` config file. They’ve been collected in a group called `default`, meaning that all of them will receive updates together. You can rename, add and remove groups and freely assign each `package.json` to whichever group you like. It’s common, for example, to have one `frontend` group and one `backend` group, each with a couple of `package.json` files. In any case, all files in a group will have their updates collected into single PRs and issues. '
  }
  if (info.action === 'updated') {
    message += 'Since this repo already has a `greenkeeper.json` config file with defined groups, Greenkeeper has only checked whether they’re still valid. '
    if (info.deletedPackageFiles.length > 0) {
      message += 'The follwing `package.json` files could no longer be found in the repo and have been removed from your groups config: `' + info.deletedPackageFiles.join(', ') + '`. '
    }
    if (info.deletedGroups.length > 0) {
      message += 'Also, groups which no longer have any entries have been removed: `' + info.deletedGroups.join(', ') + '`. '
    }
  }
  if (info.action === 'added-groups-only') {
    message += 'Since this repo already has a `greenkeeper.json` config file without any defined groups, Greenkeeper has  added all of the `package.json` files to a group called `default`, meaning that all of them will receive updates together. You can rename, add and remove groups and freely assign each `package.json` to whichever group you like. It’s common, for example, to have one `frontend` group and one `backend` group, each with a couple of `package.json` files. In any case, all files in a group will have their updates collected into single PRs and issues. '
  }
  return message
}

const closeMessages = (issueNumbers) => {
  if (!issueNumbers || issueNumbers.length === 0) { return }
  return '\nCloses: #' + issueNumbers.join(', #')
}

function prBody ({ghRepo, success, secret, installationId, newBranch, badgeUrl, travisModified, enabled, depsUpdated, accountTokenUrl, files, greenkeeperConfigInfo, groupName, closes}) {
  return md`
${!groupName && `Let’s get started with automated dependency management for ${ghRepo.name} :muscle:`}

${!groupName && hasLockFileText(files)}

${mainMessage({enabled, depsUpdated, groupName})}

${!groupName && !enabled && '**Important: Greenkeeper will only start watching this repository’s dependency updates after you merge this initial pull request**.'}

${!groupName && secret && accountTokenUrl && `💸  **Warning** 💸 Enabling Greenkeeper on this repository by merging this pull request might increase your monthly payment. If you’re unsure, please [check your billing status](${accountTokenUrl}).`}

${!groupName && greenkeeperConfigInfoMessage(greenkeeperConfigInfo)}

---
${
  _.compact([
    depsUpdated && !success && branchFailed(),
    secret && enablePrivatePackage({secret, installationId}),
    badgeUrl && badgeAddedText({badgeUrl}),
    travisModified && travisModifiedText(),
    groupName ? howToIgnoreDependenciesInGroup({ghRepo, newBranch}) : howToIgnoreDependencies({ghRepo, newBranch}),
    updatePullRequestText({ghRepo, newBranch}),
    howTheUpdatesWillLookLike(),
    faqText()
  ]).map(text => `<details>${text}</details>`)
}
${closeMessages(closes)}

---

Good luck with your project and see you soon :sparkles:

Your [Greenkeeper](https://greenkeeper.io) bot :palm_tree:
`
}
<|endoftext|>


<commit_before>'use strict';

function $(selector){
    return document.querySelector(selector);
}

function $All(selector){
    return document.querySelectorAll(selector);
}

function assignGlobalObjects(list){
    for(let item of Object.keys(list))
	window[item] = $(list[item]);
}

function assignMethods(constructor, methods){
    for(let I of Object.keys(methods))
	constructor.prototype[I] = methods[I];
}

function elementAssign(element, properties){
    /* no property is set, exit without processing */
    if(!properties)
	return;

    /* shorthand for textContent */
    if(typeof properties == 'string'){
	element.textContent = properties;
	return;
    }

    /* shorthand for children */
    if(Array.isArray(properties)){
	let children = properties;
	properties = {};
	properties.children = children;
    }

    /* assign array-like data structures */
    if(properties.children){
	for(let child of properties.children){
	    if(!child)
		continue;
	    element.appendChild(child);
	}
	delete properties.children;
    }
    if(properties.classList){
	for(let className of properties.classList){
	    if(!className)
		continue;
	    element.classList.add(className);
	}
	delete properties.classList;
    }
    /* assign objects */
    ['style', 'dataset'].forEach(function(item){
	if(properties[item]){
	    for(let I of Object.keys(properties[item])){
		if(!properties[item][I])
		    continue;
		element[item][I] = properties[item][I];
	    }
	    delete properties[item];
	}
    });

    /* assign other properties */
    for(let I of Object.keys(properties)){
	if(!properties[I])
	    continue;
	element[I] = properties[I];
    }
}

function create(type, properties){
    var element = document.createElement(type);
    elementAssign(element, properties);
    return element;
}

function inst(template, data){
    var instance = document.importNode(template, true).content;
    for(let selector of Object.keys(data))
	elementAssign(instance.querySelector(selector), data[selector]);
    return instance;
}

function hide(element){
    if(element.style.display == 'none')
	return false;
    if(element.style.display)
	element.dataset.style_display = element.style.display;
    element.style.display = 'none';
    return true;
}

function show(element){
    if(element.style.display != 'none')
	return false;
    if(element.dataset.style_display){
	element.style.display = element.dataset.style_display;
	delete element.dataset.style_display;
    }else{
	element.style.display = '';
    }
    return true;
}

function* previousElementIterator(element){
    while(element){
	element = element.previousElementSibling;
	/* yield if previous sibling element exists */
	if(element)
	    yield element;
    }
}

function* nextElementIterator(element){
    while(element){
	element = element.nextElementSibling;
	/* yield if next sibling element exists */
	if(element)
	    yield element;
    }
}

function printf(args){
    var string = arguments[0];
    /* note that %n in the string must be in ascending order */
    /* like 'Foo %1 Bar %2 %3' */
    var i;
    for(i=arguments.length-1; i>0; i--)
	string = string.replace('%'+i, arguments[i]);
    return string;
}

/* Polyfill */
if(!NodeList.prototype[Symbol.iterator]){
    NodeList.prototype[Symbol.iterator] = function* (){
	for(let i=0; i<this.length; i++)
	    yield this[i];
    };
}
<commit_msg>Add insertAfter()<commit_after>'use strict';

function $(selector){
    return document.querySelector(selector);
}

function $All(selector){
    return document.querySelectorAll(selector);
}

function assignGlobalObjects(list){
    for(let item of Object.keys(list))
	window[item] = $(list[item]);
}

function assignMethods(constructor, methods){
    for(let I of Object.keys(methods))
	constructor.prototype[I] = methods[I];
}

function elementAssign(element, properties){
    /* no property is set, exit without processing */
    if(!properties)
	return;

    /* shorthand for textContent */
    if(typeof properties == 'string'){
	element.textContent = properties;
	return;
    }

    /* shorthand for children */
    if(Array.isArray(properties)){
	let children = properties;
	properties = {};
	properties.children = children;
    }

    /* assign array-like data structures */
    if(properties.children){
	for(let child of properties.children){
	    if(!child)
		continue;
	    element.appendChild(child);
	}
	delete properties.children;
    }
    if(properties.classList){
	for(let className of properties.classList){
	    if(!className)
		continue;
	    element.classList.add(className);
	}
	delete properties.classList;
    }
    /* assign objects */
    ['style', 'dataset'].forEach(function(item){
	if(properties[item]){
	    for(let I of Object.keys(properties[item])){
		if(!properties[item][I])
		    continue;
		element[item][I] = properties[item][I];
	    }
	    delete properties[item];
	}
    });

    /* assign other properties */
    for(let I of Object.keys(properties)){
	if(!properties[I])
	    continue;
	element[I] = properties[I];
    }
}

function create(type, properties){
    var element = document.createElement(type);
    elementAssign(element, properties);
    return element;
}

function inst(template, data){
    var instance = document.importNode(template, true).content;
    for(let selector of Object.keys(data))
	elementAssign(instance.querySelector(selector), data[selector]);
    return instance;
}

function hide(element){
    if(element.style.display == 'none')
	return false;
    if(element.style.display)
	element.dataset.style_display = element.style.display;
    element.style.display = 'none';
    return true;
}

function show(element){
    if(element.style.display != 'none')
	return false;
    if(element.dataset.style_display){
	element.style.display = element.dataset.style_display;
	delete element.dataset.style_display;
    }else{
	element.style.display = '';
    }
    return true;
}

function insertAfter(newNode, referenceNode){
	referenceNode.insertBefore(newNode, referenceNode.nextSibling);
}

function* previousElementIterator(element){
    while(element){
	element = element.previousElementSibling;
	/* yield if previous sibling element exists */
	if(element)
	    yield element;
    }
}

function* nextElementIterator(element){
    while(element){
	element = element.nextElementSibling;
	/* yield if next sibling element exists */
	if(element)
	    yield element;
    }
}

function printf(args){
    var string = arguments[0];
    /* note that %n in the string must be in ascending order */
    /* like 'Foo %1 Bar %2 %3' */
    var i;
    for(i=arguments.length-1; i>0; i--)
	string = string.replace('%'+i, arguments[i]);
    return string;
}

/* Polyfill */
if(!NodeList.prototype[Symbol.iterator]){
    NodeList.prototype[Symbol.iterator] = function* (){
	for(let i=0; i<this.length; i++)
	    yield this[i];
    };
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * app-lightcontrol, 26.09.2016 Spaceify Oy
 *
 * @class AppLightcontrol
 */

var spaceify = require("/api/spaceifyapplication.js");

function AppLightcontrol()
{
var self = this;

var lightsService = null;

// EXPOSED JSON-RPC METHODS -- -- -- -- -- -- -- -- -- -- //

var lights =  {0:  {state: {on: true, hue: 123456} }, 1: {state: {on: false, hue: 654} } };

var getLightStates = function()
	{
	return lights;
	//lightsService.callRpc("loadContent", [url, lightsServiceId, contentType]);
	}

var setLightState =  function(lightId, state)
	{
	lights.lightId.state = state;
	}

	// IMPLEMENT start AND fail METHODS IN YOUR APPLICATION!!! -- -- -- -- -- -- -- -- -- -- //
self.start = function()
	{
	// PROVIDED - CONNECTIONS FROM CLIENTS TO US
	var service = spaceify.getProvidedService("spaceify.org/services/lightcontrol");

	service.exposeRpcMethod("getLightStates", self, getLightStates);
	service.exposeRpcMethod("setLightState", self, setLightState);

	// REQUIRED - OUR CONNECTION TO THE LIGHTS SERVICE
	lightsService = spaceify.getRequiredService("spaceify.org/services/lights");
	}

self.fail = function()
	{
	}

}

var appLightcontrol = new AppLightcontrol();
spaceify.start(appLightcontrol, {webservers: {http: true, https: true}});
<commit_msg>Testable version<commit_after>#!/usr/bin/env node
/**
 * app-lightcontrol, 26.09.2016 Spaceify Oy
 *
 * @class AppLightcontrol
 */

var spaceify = require("/api/spaceifyapplication.js");

function AppLightcontrol()
{
var self = this;

var lightsService = null;

// EXPOSED JSON-RPC METHODS -- -- -- -- -- -- -- -- -- -- //

var lights =  {0:  {state: {on: true, hue: 123456} }, 1: {state: {on: false, hue: 654} } };

self.getLightStates = function()
	{
	var foundLights = lightsService.sync.callRpc("getLights", [], self);
	return foundLights;
	//lightsService.callRpc("loadContent", [url, lightsServiceId, contentType]);
	};

self.setLightState =  function(gatewayId, lightId, state)
	{
	lightsService.sync.callRpc("setLightState", [gatewayId, lightId, state]);
	//lights.lightId.state = state;
	};

	// IMPLEMENT start AND fail METHODS IN YOUR APPLICATION!!! -- -- -- -- -- -- -- -- -- -- //
self.start = function()
	{
	// PROVIDED - CONNECTIONS FROM CLIENTS TO US
	var service = spaceify.getProvidedService("spaceify.org/services/lightcontrol");

	service.exposeRpcMethod("getLightStates", self, self.getLightStates);
	service.exposeRpcMethod("setLightState", self, self.setLightState);

	// REQUIRED - OUR CONNECTION TO THE LIGHTS SERVICE
	lightsService = spaceify.getRequiredService("spaceify.org/services/lights");
	};

self.fail = function()
	{
	};

}

var appLightcontrol = new AppLightcontrol();
spaceify.start(appLightcontrol, {webservers: {http: true, https: true}});
<|endoftext|>


<commit_before>/*
 * Patches for the tabbrowser-tabs object.
 *
 * These are necessary where the original implementation assumes a
 * horizontal layout.
 */
var VTTabbrowserTabs = {

    patch: function() {
        var tabs = document.getElementById("tabbrowser-tabs");
        tabs._getDropIndex = this._getDropIndex;
        tabs._setEffectAllowedForDataTransfer
            = this._setEffectAllowedForDataTransfer;
        tabs.addEventListener('dragover', this.onDragOver, false);
    },

    _getDropIndex: function(event) {
        var tabs = this.childNodes;
        var tab = this._getDragTargetTab(event);
        // CHANGE for Vertical Tabs: no ltr handling, X -> Y, width -> height
        // and group support.
        for (let i = tab ? tab._tPos : 0; i < tabs.length; i++) {
            // If we're dropping anywhere on a group, drop to within the group
            if (event.screenY < tabs[i].boxObject.screenY + tabs[i].boxObject.height
                && this.VTGroups.isGroup(tabs[i])) {
                //TODO We should be appending to the group's children
                return i + 1;
            }
            if (event.screenY < tabs[i].boxObject.screenY + tabs[i].boxObject.height / 2)
                return i;
        }
        return tabs.length;
    },

    _setEffectAllowedForDataTransfer: function(event) {
        var dt = event.dataTransfer;
        // Disallow dropping multiple items
        if (dt.mozItemCount > 1)
            return dt.effectAllowed = "none";

        var types = dt.mozTypesAt(0);
        var sourceNode = null;
        // tabs are always added as the first type
        if (types[0] == TAB_DROP_TYPE) {
            var sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
            if (sourceNode instanceof XULElement &&
                sourceNode.localName == "tab" &&
                (sourceNode.parentNode == this ||
                 (sourceNode.ownerDocument.defaultView instanceof ChromeWindow &&
                  sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser"))) {
                if (sourceNode.parentNode == this &&
                    // CHANGE for Vertical Tabs: X -> Y, width -> height
                    (event.screenY >= sourceNode.boxObject.screenY &&
                     event.screenY <= (sourceNode.boxObject.screenY +
                                       sourceNode.boxObject.height))) {
                    return dt.effectAllowed = "none";
                }

                return dt.effectAllowed = "copyMove";
            }
        }

        for (let i = 0; i < this._supportedLinkDropTypes.length; i++) {
            if (types.contains(this._supportedLinkDropTypes[i])) {
                // Here we need to to do this manually
                return dt.effectAllowed = dt.dropEffect = "link";
            }
        }
        return dt.effectAllowed = "none";
    },

    // Calculate the drop indicator's position for vertical tabs.
    // Overwrites what the original 'dragover' event handler does
    // towards the end.
    onDragOver: function(aEvent) {
        var tabs = document.getElementById("tabbrowser-tabs");
        var ind = tabs._tabDropIndicator;
        var newIndex = tabs._getDropIndex(aEvent);
        var rect = tabs.getBoundingClientRect();
        var newMargin;

        if (newIndex == tabs.childNodes.length) {
            let tabRect = tabs.childNodes[newIndex-1].getBoundingClientRect();
            newMargin = tabRect.bottom - rect.top;
        } else {
            let tabRect = tabs.childNodes[newIndex].getBoundingClientRect();
            newMargin = tabRect.top - rect.top;
        }

        newMargin += ind.clientHeight / 2;
        ind.style.MozTransform = "translate(0, " + Math.round(newMargin) + "px)";
        ind.style.MozMarginStart = null;
        ind.style.marginTop = null;
        ind.style.maxWidth = rect.width + "px";
    }

};
<commit_msg>Factor out logic for data transfer eligibility<commit_after>/*
 * Patches for the tabbrowser-tabs object.
 *
 * These are necessary where the original implementation assumes a
 * horizontal layout.
 */
var VTTabbrowserTabs = {

    patch: function() {
        var tabs = document.getElementById("tabbrowser-tabs");
        tabs._getDropIndex = this._getDropIndex;
        tabs._isAllowedForDataTransfer = this._isAllowedForDataTransfer;
        tabs._setEffectAllowedForDataTransfer
            = this._setEffectAllowedForDataTransfer;
        tabs.addEventListener('dragover', this.onDragOver, false);
    },

    _getDropIndex: function(event) {
        var tabs = this.childNodes;
        var tab = this._getDragTargetTab(event);
        // CHANGE for Vertical Tabs: no ltr handling, X -> Y, width -> height
        // and group support.
        for (let i = tab ? tab._tPos : 0; i < tabs.length; i++) {
            // If we're dropping anywhere on a group, drop to within the group
            if (event.screenY < tabs[i].boxObject.screenY + tabs[i].boxObject.height
                && this.VTGroups.isGroup(tabs[i])) {
                //TODO We should be appending to the group's children
                return i + 1;
            }
            if (event.screenY < tabs[i].boxObject.screenY + tabs[i].boxObject.height / 2)
                return i;
        }
        return tabs.length;
    },

    _isAllowedForDataTransfer: function(node) {
        return (node instanceof XULElement
                && node.localName == "tab"
                && (node.parentNode == this
                    || (node.ownerDocument.defaultView instanceof ChromeWindow
                        && node.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser")));

    },

    _setEffectAllowedForDataTransfer: function(event) {
        var dt = event.dataTransfer;
        // Disallow dropping multiple items
        if (dt.mozItemCount > 1)
            return dt.effectAllowed = "none";

        var types = dt.mozTypesAt(0);
        // tabs are always added as the first type
        if (types[0] == TAB_DROP_TYPE) {
            let sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
            if (this._isAllowedForDataTransfer(sourceNode)) {
                if (sourceNode.parentNode == this &&
                    // CHANGE for Vertical Tabs: X -> Y, width -> height
                    (event.screenY >= sourceNode.boxObject.screenY &&
                     event.screenY <= (sourceNode.boxObject.screenY +
                                       sourceNode.boxObject.height))) {
                    return dt.effectAllowed = "none";
                }

                return dt.effectAllowed = "copyMove";
            }
        }

        for (let i = 0; i < this._supportedLinkDropTypes.length; i++) {
            if (types.contains(this._supportedLinkDropTypes[i])) {
                // Here we need to to do this manually
                return dt.effectAllowed = dt.dropEffect = "link";
            }
        }
        return dt.effectAllowed = "none";
    },

    // Calculate the drop indicator's position for vertical tabs.
    // Overwrites what the original 'dragover' event handler does
    // towards the end.
    onDragOver: function(aEvent) {
        var tabs = document.getElementById("tabbrowser-tabs");
        var ind = tabs._tabDropIndicator;
        var newIndex = tabs._getDropIndex(aEvent);
        var rect = tabs.getBoundingClientRect();
        var newMargin;

        if (newIndex == tabs.childNodes.length) {
            let tabRect = tabs.childNodes[newIndex-1].getBoundingClientRect();
            newMargin = tabRect.bottom - rect.top;
        } else {
            let tabRect = tabs.childNodes[newIndex].getBoundingClientRect();
            newMargin = tabRect.top - rect.top;
        }

        newMargin += ind.clientHeight / 2;
        ind.style.MozTransform = "translate(0, " + Math.round(newMargin) + "px)";
        ind.style.MozMarginStart = null;
        ind.style.marginTop = null;
        ind.style.maxWidth = rect.width + "px";
    }

};
<|endoftext|>


<commit_before>/* ESGF Dataset search */

(function($) {
  $.extend({
    EsgDatasetSearch: function(options) {
      var defaults = {
        oid: null,
        url: null,
        constraints: null,
        categories: null,
        keywords: null,
        pinnedFacets: null,
        selectedFacet: 'project',
        bbox: null,
      };
      var searchOptions = $.extend(defaults, options);
      var selectedFacet = searchOptions.selectedFacet;

      var init = function() {
        initDatasetCollapse();
        initToggleCollapse();
        init_search_options();
        initQuery();
        init_constraints();
        init_facets();
        init_facet_values();
        init_pinned_facets();
        initTimeConstraints();
        initBBoxExtent();
        //updateHiddenFields();
      };

      /*
      var updateHiddenFields = function() {
        // TODO: this is not the way it should be done
        $('#deformField1').val($("#" + searchOptions.oid + '-constraints').val());
        $('#deformField2').val($("#" + searchOptions.oid + '-query').val());
        $('#deformField3').val($("#" + searchOptions.oid + '-distrib').val());
        $('#deformField4').val($("#" + searchOptions.oid + '-replica').val());
        $('#deformField5').val($("#" + searchOptions.oid + '-latest').val());
        $('#deformField6').val($("#" + searchOptions.oid + '-temporal').val());
        // $('#deformField7').val($("#" + searchOptions.oid + '-spatial').val());
        $('#deformField8').val($("#" + searchOptions.oid + '-start').val()+'-01-01');
        $('#deformField9').val($("#" + searchOptions.oid + '-end').val()+'-12-31');
        // $('#deformField10').val($("#" + searchOptions.oid + '-bbox').val());
      };
      */

      var _buildListGroupItem = function(item) {
        var color = 'info';
        if (item.type == 'Aggregation') {
          color = 'success';
        }
        var text = '
';
        text += '';
        if (item.cart_available) {
          text += '<btn';
          text += ' class="btn btn-default btn-xs pull-right';
          if (item.is_in_cart) {
            text += ' btn-cart-remove"';
            text += ' title="Remove from Cart"';
          } else {
            text += ' btn-cart-add"';
            text += ' title="Add to Cart"';
          }
          text += ' data-toggle="tooltip"';
          text += ' data-value="' + item.opendap_url + '"';
          text += ' data-type="application/x-ogc-dods"';
          text += ' role="button">';
          text += '<icon class="fa fa-lg';
          if (item.is_in_cart) {
            text += ' fa-times">';
          } else {
            text += ' fa-cart-plus">';
          }
          text += '</icon>';
          text += '</btn>';
        }
        text += item.title;
        text += '
';
        text += item.abstract;
        text += '';
        text += '
';
        if (item.download_url) {
          text += '';
          text += ' Download ';
        }
        if (item.opendap_url) {
          text += '';
          text += ' OpenDAP ';
        }
        /*
        text += '';
        text += ' Info ';
        */
        text += '
';
        text += '
';
        return text;
      };

      var initDatasetCollapse = function() {
        $('.dataset').on('show.bs.collapse', function () {
          var _el = $(this);
          var dataset_id = $(this).find('.items').attr('dataset_id');
          var waitDialog = $('#please-wait-dialog');
          waitDialog.modal('show');
          // fill dataset items
          $.getJSON(buildItemsSearchQuery(dataset_id), function(result) {
            var html = '';
            $.each(result.items, function(i, item) {
              html += _buildListGroupItem(item);
            });
            _el.find('.items').html(html);
            waitDialog.modal('hide');
          });
        })
      };

      var initToggleCollapse = function() {
        $('a[data-toggle="collapse"]').click(function () {
          $(this).find('i').toggleClass('fa-chevron-right fa-chevron-down');
        })
      };

      // using ctrl for multiple selection of facets
      var ctrlPressed = false;
      $(window).keydown(function(e) {
        if (e.which == 17) { // ctrl
          ctrlPressed = true;
        }
      }).keyup(function(e) {
        if (e.which == 17) { // ctrl
          ctrlPressed = false;
          search();
        }
      });

      // using delete to remove selections of current category
      $(window).keydown(function(e) {
        if (e.which == 46) { // delete
          $(".tm-selection").tagsManager('empty');
          search();
        }
      });

      var killEvent = function (e) {
        e.cancelBubble = true;
        e.returnValue = false;
        e.stopPropagation();
        e.preventDefault();
      };

      var deleted_constraint_handler = function(constraint) {
        $(".tm-selection").tagsManager('limitPopTags');
        search();
      };

      var selected_facet_handler = function (facet) {
        selectedFacet = facet;
        $('#search-label-category').text("KEYWORDS: " + selectedFacet)
        search();
      };

      var selected_facet_value_handler = function (facet_value) {
        value = selectedFacet  + ':' + facet_value;
        $(".tm-selection").tagsManager('limitPushTags');
        $(".tm-selection").tagsManager('pushTag', value);
        if (!ctrlPressed) {
          search();
        }
      };

      var numTags = function(tags) {
        var result = 1;
        if (tags != '') {
          result = tags.split(',').length;
        }
        return result;
      };

      var init_search_options = function() {
        $('#' + searchOptions.oid + '-distrib').click(function () {
          search();
        });

        $('#' + searchOptions.oid + '-replica').click(function () {
          search();
        });

        $('#' + searchOptions.oid + '-latest').click(function () {
          search();
        });

        $('#' + searchOptions.oid + '-temporal').click(function () {
          search();
        });
      };

      var initQuery = function() {
        $('#' + searchOptions.oid + '-query').keypress(function(e) {
          // disable ENTER
          if (e.which == 13) {
            killEvent(e);
            search();
          };
          $('#' + searchOptions.oid + '-query').on('change', function(){
            search();
          });
        });
      };

      var initTimeConstraints = function() {
        // start year
        $('#' + searchOptions.oid + '-start').keypress(function(e) {
          // disable ENTER and run search
          if (e.which == 13) {
            killEvent(e);
            search();
          };
        });
        $('#' + searchOptions.oid + '-start').on('change', function(){
          search();
        });

        // end year
        $('#' + searchOptions.oid + '-end').keypress(function(e) {
          // disable ENTER and run search
          if (e.which == 13) {
            killEvent(e);
            search();
          };
        });
        $('#' + searchOptions.oid + '-end').on('change', function(){
          search();
        });
      };

      var init_constraints = function() {
        $(".tm-selection").tagsManager({
          preventSubmitOnEnter: true,
          delimiters: [9, 13, 44],
          //maxTags: 2,
          tagClass: 'tm-tag tm-tag-success',
          hiddenTagListId: searchOptions.oid + '-constraints',
          deleteHandler: deleted_constraint_handler,
          prefilled: searchOptions.constraints,
          maxTags: numTags(searchOptions.constraints),
        });
      };

      var initBBoxExtent = function() {
        var map = L.map('map', {
          center: [0, 0],
          zoom: 0,
          zoomControl: false,
        });  // map
        // base layer
        L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
        map.on('moveend', function() {
          searchOptions.bbox = map.getBounds().toBBoxString();
          //search();
        });

      };   // bbox extent

      var init_facets = function() {
        $(".tm-facets").tagsManager({
          //prefilled: ["hello"],
          preventSubmitOnEnter: true,
          delimiters: [9, 13, 44],
          //maxTags: 1,
          tagClass: 'tm-tag tm-tag-info',
          isSelectable: true,
          selectHandler: selected_facet_handler,
          prefilled: searchOptions.categories,
          maxTags: numTags(searchOptions.categories),
        });
      };

      var init_facet_values = function() {
        $(".tm-facet").tagsManager({
          //prefilled: ["MPI-M", "NCC", "MIROC", "BCC"],
          preventSubmitOnEnter: true,
          delimiters: [9, 13, 44],
          //maxTags: 4,
          tagClass: 'tm-tag tm-tag-warning tm-tag-mini',
          isSelectable: true,
          selectHandler: selected_facet_value_handler,
          prefilled: searchOptions.keywords,
          maxTags: numTags(searchOptions.keywords),
        });
      };

      var init_pinned_facets = function() {
        $(".tm-pinned-facets").tagsManager({
          //prefilled: ["hello"],
          preventSubmitOnEnter: true,
          delimiters: [9, 13, 44],
          tagClass: 'tm-tag tm-tag-disabled',
          isSelectable: false,
          prefilled: searchOptions.pinnedFacets,
          maxTags: numTags(searchOptions.pinnedFacets),
        });
      };

      var _buildQuery = function(baseURL) {
        var query = baseURL;
        // constraints
        query += '&constraints=' + $("#" + searchOptions.oid + '-constraints').val();
        // distrib option
        if ($('#' + searchOptions.oid + '-distrib').is(":checked") == true) {
          query += '&distrib=true';
        } else {
          query += '&distrib=false';
        }
        // latest option
        if ($('#' + searchOptions.oid + '-latest').is(":checked") == true) {
          query += '&latest=true';
        } else {
          query += '&latest=false';
        }
        // replica option
        if ($('#' + searchOptions.oid + '-replica').is(":checked") == true) {
          query += '&replica=true';
        } else {
          query += '&replica=false';
        }
        // freetext search
        query += '&query=' + $('#' + searchOptions.oid + '-query').val();
        // date options
        if ($('#' + searchOptions.oid + '-temporal').is(":checked") == true) {
          query += '&temporal=true';
        } else {
          query += '&temporal=false';
        }
        query += '&start=' + $('#' + searchOptions.oid + '-start').val();
        query += '&end=' + $('#' + searchOptions.oid + '-end').val();
        return query;
      }

      var buildDatasetSearchQuery = function() {
        var searchURL = searchOptions.url + '?';
        searchURL += 'selected=' + selectedFacet;
        return _buildQuery(searchURL);
      };

      var buildItemsSearchQuery = function(dataset_id) {
        var searchURL = "/esgfsearch/items?";
        searchURL += "dataset_id=" + dataset_id;
        return _buildQuery(searchURL);
      };

      var search = function() {
        query = buildDatasetSearchQuery();
        window.location = query;
      };

      init();
    },
  });
})(jQuery);
<commit_msg>cleaned up init methods<commit_after>/* ESGF Dataset search */

(function($) {
  $.extend({
    EsgDatasetSearch: function(options) {
      var defaults = {
        oid: null,
        url: null,
        constraints: null,
        categories: null,
        keywords: null,
        pinnedFacets: null,
        selectedFacet: 'project',
        bbox: null,
      };
      var searchOptions = $.extend(defaults, options);
      var selectedFacet = searchOptions.selectedFacet;

      var init = function() {
        initDatasetCollapse();
        initToggleCollapse();
        initSearchOptions();
        initQuery();
        initConstraints();
        initCategories();
        initKeywords();
        initPinnedKeywords();
        initTimeExtent();
        initBBoxExtent();
      };

      var _buildListGroupItem = function(item) {
        var color = 'info';
        if (item.type == 'Aggregation') {
          color = 'success';
        }
        var text = '
';
        text += '';
        if (item.cart_available) {
          text += '<btn';
          text += ' class="btn btn-default btn-xs pull-right';
          if (item.is_in_cart) {
            text += ' btn-cart-remove"';
            text += ' title="Remove from Cart"';
          } else {
            text += ' btn-cart-add"';
            text += ' title="Add to Cart"';
          }
          text += ' data-toggle="tooltip"';
          text += ' data-value="' + item.opendap_url + '"';
          text += ' data-type="application/x-ogc-dods"';
          text += ' role="button">';
          text += '<icon class="fa fa-lg';
          if (item.is_in_cart) {
            text += ' fa-times">';
          } else {
            text += ' fa-cart-plus">';
          }
          text += '</icon>';
          text += '</btn>';
        }
        text += item.title;
        text += '
';
        text += item.abstract;
        text += '';
        text += '
';
        if (item.download_url) {
          text += '';
          text += ' Download ';
        }
        if (item.opendap_url) {
          text += '';
          text += ' OpenDAP ';
        }
        /*
        text += '';
        text += ' Info ';
        */
        text += '
';
        text += '
';
        return text;
      };

      var initDatasetCollapse = function() {
        $('.dataset').on('show.bs.collapse', function () {
          var _el = $(this);
          var dataset_id = $(this).find('.items').attr('dataset_id');
          var waitDialog = $('#please-wait-dialog');
          waitDialog.modal('show');
          // fill dataset items
          $.getJSON(buildItemsSearchQuery(dataset_id), function(result) {
            var html = '';
            $.each(result.items, function(i, item) {
              html += _buildListGroupItem(item);
            });
            _el.find('.items').html(html);
            waitDialog.modal('hide');
          });
        })
      };

      var initToggleCollapse = function() {
        $('a[data-toggle="collapse"]').click(function () {
          $(this).find('i').toggleClass('fa-chevron-right fa-chevron-down');
        })
      };

      // using ctrl for multiple selection of facets
      var ctrlPressed = false;
      $(window).keydown(function(e) {
        if (e.which == 17) { // ctrl
          ctrlPressed = true;
        }
      }).keyup(function(e) {
        if (e.which == 17) { // ctrl
          ctrlPressed = false;
          search();
        }
      });

      // using delete to remove selections of current category
      $(window).keydown(function(e) {
        if (e.which == 46) { // delete
          $(".tm-selection").tagsManager('empty');
          search();
        }
      });

      var killEvent = function (e) {
        e.cancelBubble = true;
        e.returnValue = false;
        e.stopPropagation();
        e.preventDefault();
      };

      var deleted_constraint_handler = function(constraint) {
        $(".tm-selection").tagsManager('limitPopTags');
        search();
      };

      var selected_facet_handler = function (facet) {
        selectedFacet = facet;
        $('#search-label-category').text("KEYWORDS: " + selectedFacet)
        search();
      };

      var selected_facet_value_handler = function (facet_value) {
        value = selectedFacet  + ':' + facet_value;
        $(".tm-selection").tagsManager('limitPushTags');
        $(".tm-selection").tagsManager('pushTag', value);
        if (!ctrlPressed) {
          search();
        }
      };

      var numTags = function(tags) {
        var result = 1;
        if (tags != '') {
          result = tags.split(',').length;
        }
        return result;
      };

      var initSearchOptions = function() {
        $('#' + searchOptions.oid + '-distrib').click(function () {
          search();
        });

        $('#' + searchOptions.oid + '-replica').click(function () {
          search();
        });

        $('#' + searchOptions.oid + '-latest').click(function () {
          search();
        });

        $('#' + searchOptions.oid + '-temporal').click(function () {
          search();
        });
      };

      var initQuery = function() {
        $('#' + searchOptions.oid + '-query').keypress(function(e) {
          // disable ENTER
          if (e.which == 13) {
            killEvent(e);
            search();
          };
          $('#' + searchOptions.oid + '-query').on('change', function(){
            search();
          });
        });
      };

      var initTimeExtent = function() {
        // start year
        $('#' + searchOptions.oid + '-start').keypress(function(e) {
          // disable ENTER and run search
          if (e.which == 13) {
            killEvent(e);
            search();
          };
        });
        $('#' + searchOptions.oid + '-start').on('change', function(){
          search();
        });

        // end year
        $('#' + searchOptions.oid + '-end').keypress(function(e) {
          // disable ENTER and run search
          if (e.which == 13) {
            killEvent(e);
            search();
          };
        });
        $('#' + searchOptions.oid + '-end').on('change', function(){
          search();
        });
      };

      var initConstraints = function() {
        $(".tm-selection").tagsManager({
          preventSubmitOnEnter: true,
          delimiters: [9, 13, 44],
          //maxTags: 2,
          tagClass: 'tm-tag tm-tag-success',
          hiddenTagListId: searchOptions.oid + '-constraints',
          deleteHandler: deleted_constraint_handler,
          prefilled: searchOptions.constraints,
          maxTags: numTags(searchOptions.constraints),
        });
      };

      var initBBoxExtent = function() {
        var map = L.map('map', {
          center: [0, 0],
          zoom: 0,
          zoomControl: false,
        });  // map
        // base layer
        L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
        map.on('moveend', function() {
          searchOptions.bbox = map.getBounds().toBBoxString();
          //search();
        });

      };   // bbox extent

      var initCategories = function() {
        $(".tm-facets").tagsManager({
          //prefilled: ["hello"],
          preventSubmitOnEnter: true,
          delimiters: [9, 13, 44],
          //maxTags: 1,
          tagClass: 'tm-tag tm-tag-info',
          isSelectable: true,
          selectHandler: selected_facet_handler,
          prefilled: searchOptions.categories,
          maxTags: numTags(searchOptions.categories),
        });
      };

      var initKeywords = function() {
        $(".tm-facet").tagsManager({
          //prefilled: ["MPI-M", "NCC", "MIROC", "BCC"],
          preventSubmitOnEnter: true,
          delimiters: [9, 13, 44],
          //maxTags: 4,
          tagClass: 'tm-tag tm-tag-warning tm-tag-mini',
          isSelectable: true,
          selectHandler: selected_facet_value_handler,
          prefilled: searchOptions.keywords,
          maxTags: numTags(searchOptions.keywords),
        });
      };

      var initPinnedKeywords = function() {
        $(".tm-pinned-facets").tagsManager({
          //prefilled: ["hello"],
          preventSubmitOnEnter: true,
          delimiters: [9, 13, 44],
          tagClass: 'tm-tag tm-tag-disabled',
          isSelectable: false,
          prefilled: searchOptions.pinnedFacets,
          maxTags: numTags(searchOptions.pinnedFacets),
        });
      };

      var _buildQuery = function(baseURL) {
        var query = baseURL;
        // constraints
        query += '&constraints=' + $("#" + searchOptions.oid + '-constraints').val();
        // distrib option
        if ($('#' + searchOptions.oid + '-distrib').is(":checked") == true) {
          query += '&distrib=true';
        } else {
          query += '&distrib=false';
        }
        // latest option
        if ($('#' + searchOptions.oid + '-latest').is(":checked") == true) {
          query += '&latest=true';
        } else {
          query += '&latest=false';
        }
        // replica option
        if ($('#' + searchOptions.oid + '-replica').is(":checked") == true) {
          query += '&replica=true';
        } else {
          query += '&replica=false';
        }
        // freetext search
        query += '&query=' + $('#' + searchOptions.oid + '-query').val();
        // date options
        if ($('#' + searchOptions.oid + '-temporal').is(":checked") == true) {
          query += '&temporal=true';
        } else {
          query += '&temporal=false';
        }
        query += '&start=' + $('#' + searchOptions.oid + '-start').val();
        query += '&end=' + $('#' + searchOptions.oid + '-end').val();
        return query;
      }

      var buildDatasetSearchQuery = function() {
        var searchURL = searchOptions.url + '?';
        searchURL += 'selected=' + selectedFacet;
        return _buildQuery(searchURL);
      };

      var buildItemsSearchQuery = function(dataset_id) {
        var searchURL = "/esgfsearch/items?";
        searchURL += "dataset_id=" + dataset_id;
        return _buildQuery(searchURL);
      };

      var search = function() {
        query = buildDatasetSearchQuery();
        window.location = query;
      };

      init();
    },
  });
})(jQuery);
<|endoftext|>


<commit_before>/*global define*/
'use strict';

// Dependecies

define([
    'jquery',
    'jquery-ui',
    'pubsub',
    'underscore',
    'bootstrap'
], function(
    jQuery,
    jQuery_ui,
    PubSub,
    _,
    bootstrap
)
{
    // Variables
    var target = undefined;
    var notes = {};
    var idCounter = 0;

    // Module References
    var $setUIValue = undefined;
    var $tooltipGenerator = undefined;
    var $disableUIElement = undefined;
    var $menuRibbon = undefined;
    var $stringEditor = undefined;

    // Selectors //
    var $newNote = jQuery('#newNote');
    var $saveNote = jQuery('#saveNote');
    var $deleteNote = jQuery('#deleteNote');
    var $noteTitle = jQuery('#noteTitle');
    var $noteColor = jQuery('#noteColor');
    var $noteOpacity = jQuery('#noteOpacity');
    var $noteBody = jQuery('#noteBody');
    var $notesTable = jQuery('#notesTable');
    var $screen = jQuery('#screenWrapper');

    // Contructor //
    function notesTab(argument) {
        // Acquire Module References //
        if (!(_.isUndefined(argument.setUIValue))) $setUIValue = argument.setUIValue;
        else return false;
        if (!(_.isUndefined(argument.tooltipGenerator))) $tooltipGenerator = argument.tooltipGenerator;
        else return false;
        if (!(_.isUndefined(argument.disableUIElement))) $disableUIElement = argument.disableUIElement;
        else return false;
        if (!(_.isUndefined(argument.menuRibbon))) $menuRibbon = argument.menuRibbon;
        else return false;
        if (!(_.isUndefined(argument.stringEditor))) $stringEditor = argument.stringEditor;
        else return false;

        // Inputs //
        $noteOpacity.html('<option>0</option><option>2</option><option>4</option><option>6</option><option>8</option><option>10</option>');
        $noteOpacity.selectpicker();
        $noteOpacity.selectpicker('val','10');
        $noteOpacity.on('change',function(){
            $screen.find('#'+notes.activeEntry).css('-ms-filter','progid:DXImageTransform.Microsoft.Alpha(Opacity='+$stringEditor.multiply10($noteOpacity.val())+')');
            $screen.find('#'+notes.activeEntry).css('filter','alpha(opacity='+$stringEditor.multiply10($noteOpacity.val())+')');
            $screen.find('#'+notes.activeEntry).css('opacity',$stringEditor.divide10($noteOpacity.val()));
        });
        $noteColor.spectrum({
            color: "#ffffff",
            allowEmpty:true,
            chooseText: "Choose",
            cancelText: "Close",
            move: function(){
                $setUIValue.setValue({
                    noteColor:{
                        other: $noteColor,
                        value: '#'+$noteColor.spectrum('get').toHex()
                    }
                });
                $screen.find('#'+notes.activeEntry).css('background-color','#'+$noteColor.spectrum('get').toHex());
                $screen.find('#'+notes.activeEntry).find('.notes').css('background-color','#'+$noteColor.spectrum('get').toHex());
            },
            change: function(){
                $setUIValue.setValue({
                    noteColor:{
                        other: $noteColor,
                        value: '#'+$noteColor.spectrum('get').toHex()
                    }
                });
                $screen.find('#'+notes.activeEntry).css('background-color','#'+$noteColor.spectrum('get').toHex());
                $screen.find('#'+notes.activeEntry).find('.notes').css('background-color','#'+$noteColor.spectrum('get').toHex());
            }
        });
        $disableUIElement.disableElement({
            noteTitle:{
                value: true
            },
            noteBody:{
                value: true
            },
            noteOpacity:{
                value: true
            },
            noteColor:{
                value: true
            }
        });
        $notesTable.hide('slow');

        // Buttons //
        $newNote.on('click',function(){
            if (!($newNote.hasClass('disabled'))){
                highlightNote(notes.activeEntry,false);
                highlightNote(addNote(),true);
                $disableUIElement.disableElement({
                noteTitle:{
                    value: false
                },
                noteBody:{
                    value: false
                },
                noteOpacity:{
                    value: false
                },
                noteColor:{
                    value: false
                },
                newNote:{
                    value: true
                },
                saveNote:{
                    value: false
                },
                deleteNote:{
                    value: false
                }
            });
            }
        });
        $saveNote.on('click',function(){
            if (!($saveNote.hasClass('disabled'))){
                editNote({
                    title: $noteTitle.val(),
                    body: $noteBody.val(),
                    color: '#'+$noteColor.spectrum('get').toHex(),
                    opacity: $noteOpacity.val(),
                    atomNote: notes[notes.activeEntry].atomNote
                });
                $disableUIElement.disableElement({
                noteTitle:{
                    value: true
                },
                noteBody:{
                    value: true
                },
                noteOpacity:{
                    value: true
                },
                noteColor:{
                    value: true
                },
                newNote:{
                    value: false
                },
                saveNote:{
                    value: true
                },
                deleteNote:{
                    value: true
                }
            });
            }
        });
        $deleteNote.on('click',function(){
            if (!($deleteNote.hasClass('disabled'))){
                deleteNote();
                $disableUIElement.disableElement({
                noteTitle:{
                    value: true
                },
                noteBody:{
                    value: true
                },
                noteOpacity:{
                    value: true
                },
                noteColor:{
                    value: true
                },
                newNote:{
                    value: false
                },
                saveNote:{
                    value: true
                },
                deleteNote:{
                    value: true
                }
            });
            }
        });

        // Reset //
        $notesTable.on('reset', function(){
             $notesTable.find('tbody').html('');
        });
    };

    function addNote(newID){
        var id = undefined;
        var atomNote = false;

        // Clear Forms
        $noteTitle.val('');
        $noteBody.val('');
        $noteOpacity.selectpicker('val','10');
        $noteColor.children().css('background','transparent');

        // Add Note //
        if (_.isUndefined(newID)) {
            id = 'note'+idCounter;
            idCounter++;
        }
        else {
            atomNote = true;
            id = newID;
        }
        $notesTable.find('tbody').append('
	Untitled Note
');
        $notesTable.show('slow');

        // Create Database Entry //
        notes[id] = {
            title: '',
            body: '',
            color: '',
            opacity: '',
            atomNote: atomNote
        };
        createCanvasNote(id);

        // Handlers //
        $notesTable.find('#'+id).find('.selectable').on('click',function(){
            selectNote(id);
        });
        $notesTable.find('#'+id).find('.noteButton').on('click', function(){
            var value = undefined;
            ($notesTable.find('#'+id).find('.noteButton').hasClass('visible')) ? value = false : value = true;
            $setUIValue.setValue({
                noteVisibility:{
                    value: value,
                    other: $notesTable.find('#'+id)
                }
            });
            if (notes[id].atomNote === true) {
                $setUIValue.setValue({
                    noteVisibility:{
                        publish: {id:id, visible: value, x: parseInt($screen.find('#'+id).css('left'),10), y: parseInt($screen.find('#'+id).css('top'),10)}
                    }
                });
            }
            showCanvasNote(id,value);
        });
        $setUIValue.setValue({
            noteVisibility:{
                value: false,
                other: $notesTable.find('#'+id)
            }
        });

        if (atomNote === true) $setUIValue.setValue({
            atomNoteTable: { publish: getAtomNoteTable() }
        });

        return id;
    };
    function editNote(note){
        // Update Database //
        if (notes.activeEntry !== false) notes[notes.activeEntry] = note;
        else return false;

        // Update Entry //
        if (note.title !== '') {
            $notesTable.find('#'+notes.activeEntry).find('.note-name').html(note.title);
            $screen.find('#'+notes.activeEntry).find('.noteTitle').html(note.title);
        }
        if (note.body !== '') $screen.find('#'+notes.activeEntry).find('.notes').html(note.body);
        highlightNote(notes.activeEntry,false);

        // Clear Forms
        $noteTitle.val('');
        $noteBody.val('');
        $noteOpacity.selectpicker('val','10');
        $noteColor.children().css('background','transparent');
    };
    function deleteNote(){

        // Update Database //
        if (notes.activeEntry !== false) {
            if (notes[notes.activeEntry].atomNote === true) {
                delete notes[notes.activeEntry];
                $setUIValue.setValue({
                    atomNoteTable: { publish: getAtomNoteTable() }
                });
            }
            else delete notes[notes.activeEntry];
        }
        else return false;

        // Remove Entry //
        $notesTable.find('#'+notes.activeEntry).remove();
        deleteCanvasNote(notes.activeEntry);
        highlightNote('q',false);

        // Clear Forms
        $noteTitle.val('');
        $noteBody.val('');
        $noteOpacity.selectpicker('val','10');
        $noteColor.children().css('background','transparent');
    };
    function selectNote(id){
        highlightNote(notes.activeEntry,false);
        $noteTitle.val(notes[id].title);
        $noteBody.val(notes[id].body);
        if (notes[id].color !== '') $noteColor.spectrum('set',notes[id].color);
        if (notes[id].opacity !== '') $noteOpacity.selectpicker('val',notes[id].opacity);
        highlightNote(id,true);
        $disableUIElement.disableElement({
            noteTitle:{
                value: false
            },
            noteBody:{
                value: false
            },
            noteOpacity:{
                value: false
            },
            noteColor:{
                value: false
            },
            newNote:{
                value: true
            },
            saveNote:{
                value: false
            },
            deleteNote:{
                value: false
            }
        });
    };
    function highlightNote(id,state){
        var color = (state) ? 'bg-light-purple' : 'bg-dark-gray';
        $notesTable.find('#'+id).removeAttr('class');
        $notesTable.find('#'+id).attr('class',color);
        if (state === true) notes.activeEntry = id;
        else notes.activeEntry = false;
    };
    function showCanvasNote(id,value){
        if (value === true) $screen.find('#'+id).show('slow');
        else $screen.find('#'+id).hide('slow');
    };
    function createCanvasNote(id){
        $screen.prepend('

Notes

'+notes[id].body+'

');
        var notepad = $screen.find('#'+id);
        notepad.hide();
        notepad.draggable({
            scroll: false,
            drag: function(event, ui){
                if (notes[id].atomNote === true){
                    var x = parseInt(ui.position.left) + parseInt($screen.find('#'+id).css('width'),10) / 2;
                    var y = parseInt(ui.position.top) + parseInt($screen.find('#'+id).css('height'),10) / 2;
                    $setUIValue.setValue({
                        noteMovement:{
                            publish: { id: id, x: x, y: y }
                        }
                    });
                }
            },
            containment: jQuery('#app-container')
        });
        notepad.find('img').on('click',function(){
            showCanvasNote(id,false);
            $setUIValue.setValue({
                noteVisibility:{
                    value: false,
                    other: $notesTable.find('#'+id)
                }
            });
            if (notes[id].atomNote === true) {
                $setUIValue.setValue({
                    noteVisibility:{
                        publish: {id:id, visible: false, x: parseInt($screen.find('#'+id).css('left'),10), y: parseInt($screen.find('#'+id).css('top'),10)}
                    }
                });
            }
        });
    };
    function deleteCanvasNote(id){
        $screen.find('#'+id).remove();
    };
    function getAtomNoteTable(){
        var table = [];
        _.each(notes, function($parameter,k){
            if ($parameter.atomNote === true) table.push(k);
        });
        return table;
    };

    notesTab.prototype.moveToNote = function(id){
        $menuRibbon.switchTab('notesTab');
        if (_.isUndefined(notes[id])) {
            highlightNote(notes.activeEntry,false);
            highlightNote(addNote(id),true);
            $disableUIElement.disableElement({
                noteTitle:{
                    value: false
                },
                noteBody:{
                    value: false
                },
                noteOpacity:{
                    value: false
                },
                noteColor:{
                    value: false
                },
                newNote:{
                    value: true
                },
                saveNote:{
                    value: false
                },
                deleteNote:{
                    value: false
                }
            });
        }
        else selectNote(id);
    };
    notesTab.getAtomNoteTable = function(){
        return getAtomNoteTable();
    };

    return notesTab;
});<commit_msg>Hotfix<commit_after>/*global define*/
'use strict';

// Dependecies

define([
    'jquery',
    'jquery-ui',
    'pubsub',
    'underscore',
    'bootstrap'
], function(
    jQuery,
    jQuery_ui,
    PubSub,
    _,
    bootstrap
)
{
    // Variables
    var target = undefined;
    var notes = {};
    var idCounter = 0;

    // Module References
    var $setUIValue = undefined;
    var $tooltipGenerator = undefined;
    var $disableUIElement = undefined;
    var $menuRibbon = undefined;
    var $stringEditor = undefined;

    // Selectors //
    var $newNote = jQuery('#newNote');
    var $saveNote = jQuery('#saveNote');
    var $deleteNote = jQuery('#deleteNote');
    var $noteTitle = jQuery('#noteTitle');
    var $noteColor = jQuery('#noteColor');
    var $noteOpacity = jQuery('#noteOpacity');
    var $noteBody = jQuery('#noteBody');
    var $notesTable = jQuery('#notesTable');
    var $screen = jQuery('#screenWrapper');

    // Contructor //
    function notesTab(argument) {
        // Acquire Module References //
        if (!(_.isUndefined(argument.setUIValue))) $setUIValue = argument.setUIValue;
        else return false;
        if (!(_.isUndefined(argument.tooltipGenerator))) $tooltipGenerator = argument.tooltipGenerator;
        else return false;
        if (!(_.isUndefined(argument.disableUIElement))) $disableUIElement = argument.disableUIElement;
        else return false;
        if (!(_.isUndefined(argument.menuRibbon))) $menuRibbon = argument.menuRibbon;
        else return false;
        if (!(_.isUndefined(argument.stringEditor))) $stringEditor = argument.stringEditor;
        else return false;

        // Inputs //
        $noteOpacity.html('<option>0</option><option>2</option><option>4</option><option>6</option><option>8</option><option>10</option>');
        $noteOpacity.selectpicker();
        $noteOpacity.selectpicker('val','10');
        $noteOpacity.on('change',function(){
            $screen.find('#'+notes.activeEntry).css('-ms-filter','progid:DXImageTransform.Microsoft.Alpha(Opacity='+$stringEditor.multiply10($noteOpacity.val())+')');
            $screen.find('#'+notes.activeEntry).css('filter','alpha(opacity='+$stringEditor.multiply10($noteOpacity.val())+')');
            $screen.find('#'+notes.activeEntry).css('opacity',$stringEditor.divide10($noteOpacity.val()));
        });
        $noteColor.spectrum({
            color: "#ffffff",
            allowEmpty:true,
            chooseText: "Choose",
            cancelText: "Close",
            move: function(){
                $setUIValue.setValue({
                    noteColor:{
                        other: $noteColor,
                        value: '#'+$noteColor.spectrum('get').toHex()
                    }
                });
                $screen.find('#'+notes.activeEntry).css('background-color','#'+$noteColor.spectrum('get').toHex());
                $screen.find('#'+notes.activeEntry).find('.notes').css('background-color','#'+$noteColor.spectrum('get').toHex());
            },
            change: function(){
                $setUIValue.setValue({
                    noteColor:{
                        other: $noteColor,
                        value: '#'+$noteColor.spectrum('get').toHex()
                    }
                });
                $screen.find('#'+notes.activeEntry).css('background-color','#'+$noteColor.spectrum('get').toHex());
                $screen.find('#'+notes.activeEntry).find('.notes').css('background-color','#'+$noteColor.spectrum('get').toHex());
            }
        });
        $disableUIElement.disableElement({
            noteTitle:{
                value: true
            },
            noteBody:{
                value: true
            },
            noteOpacity:{
                value: true
            },
            noteColor:{
                value: true
            }
        });
        $notesTable.hide('slow');

        // Buttons //
        $newNote.on('click',function(){
            if (!($newNote.hasClass('disabled'))){
                highlightNote(notes.activeEntry,false);
                highlightNote(addNote(),true);
                $disableUIElement.disableElement({
                noteTitle:{
                    value: false
                },
                noteBody:{
                    value: false
                },
                noteOpacity:{
                    value: false
                },
                noteColor:{
                    value: false
                },
                newNote:{
                    value: true
                },
                saveNote:{
                    value: false
                },
                deleteNote:{
                    value: false
                }
            });
            }
        });
        $saveNote.on('click',function(){
            if (!($saveNote.hasClass('disabled'))){
                editNote({
                    title: $noteTitle.val(),
                    body: $noteBody.val(),
                    color: '#'+$noteColor.spectrum('get').toHex(),
                    opacity: $noteOpacity.val(),
                    atomNote: notes[notes.activeEntry].atomNote
                });
                $disableUIElement.disableElement({
                noteTitle:{
                    value: true
                },
                noteBody:{
                    value: true
                },
                noteOpacity:{
                    value: true
                },
                noteColor:{
                    value: true
                },
                newNote:{
                    value: false
                },
                saveNote:{
                    value: true
                },
                deleteNote:{
                    value: true
                }
            });
            }
        });
        $deleteNote.on('click',function(){
            if (!($deleteNote.hasClass('disabled'))){
                deleteNote();
                $disableUIElement.disableElement({
                noteTitle:{
                    value: true
                },
                noteBody:{
                    value: true
                },
                noteOpacity:{
                    value: true
                },
                noteColor:{
                    value: true
                },
                newNote:{
                    value: false
                },
                saveNote:{
                    value: true
                },
                deleteNote:{
                    value: true
                }
            });
            }
        });

        // Reset //
        $notesTable.on('reset', function(){
             $notesTable.find('tbody').html('');
        });
    };

    function addNote(newID){
        var id = undefined;
        var atomNote = false;

        // Clear Forms
        $noteTitle.val('');
        $noteBody.val('');
        $noteOpacity.selectpicker('val','10');
        $noteColor.children().css('background','transparent');

        // Add Note //
        if (_.isUndefined(newID)) {
            id = 'note'+idCounter;
            idCounter++;
        }
        else {
            atomNote = true;
            id = newID;
        }
        $notesTable.find('tbody').append('
	Untitled Note
');
        $notesTable.show('slow');

        // Create Database Entry //
        notes[id] = {
            title: '',
            body: '',
            color: '',
            opacity: '',
            atomNote: atomNote
        };
        createCanvasNote(id);

        // Handlers //
        $notesTable.find('#'+id).find('.selectable').on('click',function(){
            selectNote(id);
        });
        $notesTable.find('#'+id).find('.noteButton').on('click', function(){
            var value = undefined;
            ($notesTable.find('#'+id).find('.noteButton').hasClass('visible')) ? value = false : value = true;
            $setUIValue.setValue({
                noteVisibility:{
                    value: value,
                    other: $notesTable.find('#'+id)
                }
            });
            if (notes[id].atomNote === true) {
                $setUIValue.setValue({
                    noteVisibility:{
                        publish: {id:id, visible: value, x: parseInt($screen.find('#'+id).css('left'),10), y: parseInt($screen.find('#'+id).css('top'),10)}
                    }
                });
            }
            showCanvasNote(id,value);
        });
        $setUIValue.setValue({
            noteVisibility:{
                value: false,
                other: $notesTable.find('#'+id)
            }
        });

        if (atomNote === true) $setUIValue.setValue({
            atomNoteTable: { publish: getAtomNoteTable() }
        });

        return id;
    };
    function editNote(note){
        // Update Database //
        if (notes.activeEntry !== false) notes[notes.activeEntry] = note;
        else return false;

        // Update Entry //
        if (note.title !== '') {
            $notesTable.find('#'+notes.activeEntry).find('.note-name').html(note.title);
            $screen.find('#'+notes.activeEntry).find('.noteTitle').html(note.title);
        }
        if (note.body !== '') $screen.find('#'+notes.activeEntry).find('.notes').html(note.body);
        highlightNote(notes.activeEntry,false);

        // Clear Forms
        $noteTitle.val('');
        $noteBody.val('');
        $noteOpacity.selectpicker('val','10');
        $noteColor.children().css('background','transparent');
    };
    function deleteNote(){

        // Update Database //
        if (notes.activeEntry !== false) {
            if (notes[notes.activeEntry].atomNote === true) {
                delete notes[notes.activeEntry];
                $setUIValue.setValue({
                    atomNoteTable: { publish: getAtomNoteTable() }
                });
            }
            else delete notes[notes.activeEntry];
        }
        else return false;

        // Remove Entry //
        $notesTable.find('#'+notes.activeEntry).remove();
        deleteCanvasNote(notes.activeEntry);
        highlightNote('q',false);

        // Clear Forms
        $noteTitle.val('');
        $noteBody.val('');
        $noteOpacity.selectpicker('val','10');
        $noteColor.children().css('background','transparent');
    };
    function selectNote(id){
        highlightNote(notes.activeEntry,false);
        $noteTitle.val(notes[id].title);
        $noteBody.val(notes[id].body);
        if (notes[id].color !== '') $noteColor.spectrum('set',notes[id].color);
        if (notes[id].opacity !== '') $noteOpacity.selectpicker('val',notes[id].opacity);
        highlightNote(id,true);
        $disableUIElement.disableElement({
            noteTitle:{
                value: false
            },
            noteBody:{
                value: false
            },
            noteOpacity:{
                value: false
            },
            noteColor:{
                value: false
            },
            newNote:{
                value: true
            },
            saveNote:{
                value: false
            },
            deleteNote:{
                value: false
            }
        });
    };
    function highlightNote(id,state){
        var color = (state) ? 'bg-light-purple' : 'bg-dark-gray';
        $notesTable.find('#'+id).removeAttr('class');
        $notesTable.find('#'+id).attr('class',color);
        if (state === true) notes.activeEntry = id;
        else notes.activeEntry = false;
    };
    function showCanvasNote(id,value){
        if (value === true) $screen.find('#'+id).show('slow');
        else $screen.find('#'+id).hide('slow');
    };
    function createCanvasNote(id){
        $screen.prepend('

Notes

'+notes[id].body+'

');
        var notepad = $screen.find('#'+id);
        notepad.hide();
        notepad.draggable({
            scroll: false,
            drag: function(event, ui){
                if (notes[id].atomNote === true){
                    var x = parseInt(ui.position.left) + parseInt($screen.find('#'+id).css('width'),10) / 2;
                    var y = parseInt(ui.position.top) + parseInt($screen.find('#'+id).css('height'),10) / 2;
                    $setUIValue.setValue({
                        noteMovement:{
                            publish: { id: id, x: x, y: y }
                        }
                    });
                }
            },
            containment: jQuery('#app-container')
        });
        notepad.find('img').on('click',function(){
            showCanvasNote(id,false);
            $setUIValue.setValue({
                noteVisibility:{
                    value: false,
                    other: $notesTable.find('#'+id)
                }
            });
            if (notes[id].atomNote === true) {
                $setUIValue.setValue({
                    noteVisibility:{
                        publish: {id:id, visible: false, x: parseInt($screen.find('#'+id).css('left'),10), y: parseInt($screen.find('#'+id).css('top'),10)}
                    }
                });
            }
        });
    };
    function deleteCanvasNote(id){
        $screen.find('#'+id).remove();
    };
    function getAtomNoteTable(){
        var table = [];
        _.each(notes, function($parameter,k){
            if ($parameter.atomNote === true) table.push(k);
        });
        return table;
    };

    notesTab.prototype.moveToNote = function(id){
        $menuRibbon.switchTab('notesTab');
        if (_.isUndefined(notes[id])) {
            highlightNote(notes.activeEntry,false);
            highlightNote(addNote(id),true);
            $disableUIElement.disableElement({
                noteTitle:{
                    value: false
                },
                noteBody:{
                    value: false
                },
                noteOpacity:{
                    value: false
                },
                noteColor:{
                    value: false
                },
                newNote:{
                    value: true
                },
                saveNote:{
                    value: false
                },
                deleteNote:{
                    value: false
                }
            });
        }
        else selectNote(id);
    };
    notesTab.prototype.getAtomNoteTable = function(){
        return getAtomNoteTable();
    };

    return notesTab;
});<|endoftext|>