<commit_before>// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Provides utility methods to render soy template.
 * @author chrishenry@google.com (Chris Henry)
 */

goog.provide('goog.soy');

goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.NodeType');
goog.require('goog.dom.TagName');
goog.require('goog.html.legacyconversions');
goog.require('goog.soy.data.SanitizedContent');
goog.require('goog.soy.data.SanitizedContentKind');
goog.require('goog.string');

/**
 * @define {boolean} Whether to require all Soy templates to be "strict html".
 * Soy templates that use strict autoescaping forbid noAutoescape along with
 * many dangerous directives, and return a runtime type SanitizedContent that
 * marks them as safe.
 *
 * If this flag is enabled, Soy templates will fail to render if a template
 * returns plain text -- indicating it is a non-strict template.
 */
goog.define('goog.soy.REQUIRE_STRICT_AUTOESCAPE', false);

/**
 * Type definition for strict Soy templates. Very useful when passing a template
 * as an argument.
 * @typedef {function(?, null=, ?Object<string, *>=):
 *     !goog.soy.data.SanitizedContent}
 */
goog.soy.StrictTemplate;

/**
 * Sets the processed template as the innerHTML of an element. It is recommended
 * to use this helper function instead of directly setting innerHTML in your
 * hand-written code, so that it will be easier to audit the code for cross-site
 * scripting vulnerabilities.
 *
 * @param {?Element} element The element whose content we are rendering into.
 * @param {!goog.soy.data.SanitizedContent} templateResult The processed
 *     template of kind HTML or TEXT (which will be escaped).
 * @template ARG_TYPES
 */
goog.soy.renderHtml = function(element, templateResult) {
  element.innerHTML = goog.soy.ensureTemplateOutputHtml_(templateResult);
};

/**
 * Renders a Soy template and then set the output string as
 * the innerHTML of an element. It is recommended to use this helper function
 * instead of directly setting innerHTML in your hand-written code, so that it
 * will be easier to audit the code for cross-site scripting vulnerabilities.
 *
 * @param {Element} element The element whose content we are rendering into.
 * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
 *     The Soy template defining the element's content.
 * @param {ARG_TYPES=} opt_templateData The data for the template.
 * @param {Object=} opt_injectedData The injected data for the template.
 * @template ARG_TYPES
 */
goog.soy.renderElement = function(
    element, template, opt_templateData, opt_injectedData) {
  // Soy template parameter is only nullable for historical reasons.
  goog.asserts.assert(template, 'Soy template may not be null.');
  element.innerHTML = goog.soy.ensureTemplateOutputHtml_(
      template(
          opt_templateData || goog.soy.defaultTemplateData_, undefined,
          opt_injectedData));
};

/**
 * Renders a Soy template into a single node or a document
 * fragment. If the rendered HTML string represents a single node, then that
 * node is returned (note that this is *not* a fragment, despite them name of
 * the method). Otherwise a document fragment is returned containing the
 * rendered nodes.
 *
 * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
 *     The Soy template defining the element's content.
 * @param {ARG_TYPES=} opt_templateData The data for the template.
 * @param {Object=} opt_injectedData The injected data for the template.
 * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to
 *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
 * @return {!Node} The resulting node or document fragment.
 * @template ARG_TYPES
 */
goog.soy.renderAsFragment = function(
    template, opt_templateData, opt_injectedData, opt_domHelper) {
  // Soy template parameter is only nullable for historical reasons.
  goog.asserts.assert(template, 'Soy template may not be null.');
  var dom = opt_domHelper || goog.dom.getDomHelper();
  var output = template(
      opt_templateData || goog.soy.defaultTemplateData_, undefined,
      opt_injectedData);
  var html = goog.soy.ensureTemplateOutputHtml_(output);
  goog.soy.assertFirstTagValid_(html);
  var safeHtml = output instanceof goog.soy.data.SanitizedContent ?
      output.toSafeHtml() :
      goog.html.legacyconversions.safeHtmlFromString(html);
  return dom.safeHtmlToNode(safeHtml);
};

/**
 * Renders a Soy template into a single node. If the rendered
 * HTML string represents a single node, then that node is returned. Otherwise,
 * a DIV element is returned containing the rendered nodes.
 *
 * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
 *     The Soy template defining the element's content.
 * @param {ARG_TYPES=} opt_templateData The data for the template.
 * @param {Object=} opt_injectedData The injected data for the template.
 * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to
 *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
 * @return {!Element} Rendered template contents, wrapped in a parent DIV
 *     element if necessary.
 * @template ARG_TYPES
 */
goog.soy.renderAsElement = function(
    template, opt_templateData, opt_injectedData, opt_domHelper) {
  // Soy template parameter is only nullable for historical reasons.
  goog.asserts.assert(template, 'Soy template may not be null.');
  return goog.soy.convertToElement_(
      template(
          opt_templateData || goog.soy.defaultTemplateData_, undefined,
          opt_injectedData),
      opt_domHelper);
};

/**
 * Converts a processed Soy template into a single node. If the rendered
 * HTML string represents a single node, then that node is returned. Otherwise,
 * a DIV element is returned containing the rendered nodes.
 *
 * @param {!goog.soy.data.SanitizedContent} templateResult The processed
 *     template of kind HTML or TEXT (which will be escaped).
 * @param {?goog.dom.DomHelper=} opt_domHelper The DOM helper used to
 *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
 * @return {!Element} Rendered template contents, wrapped in a parent DIV
 *     element if necessary.
 */
goog.soy.convertToElement = function(templateResult, opt_domHelper) {
  return goog.soy.convertToElement_(templateResult, opt_domHelper);
};

/**
 * Non-strict version of {@code goog.soy.convertToElement}.
 *
 * @param {*} templateResult The processed template.
 * @param {?goog.dom.DomHelper=} opt_domHelper The DOM helper used to
 *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
 * @return {!Element} Rendered template contents, wrapped in a parent DIV
 *     element if necessary.
 * @private
 */
goog.soy.convertToElement_ = function(templateResult, opt_domHelper) {
  var dom = opt_domHelper || goog.dom.getDomHelper();
  var wrapper = dom.createElement(goog.dom.TagName.DIV);
  var html = goog.soy.ensureTemplateOutputHtml_(templateResult);
  goog.soy.assertFirstTagValid_(html);
  wrapper.innerHTML = html;

  // If the template renders as a single element, return it.
  if (wrapper.childNodes.length == 1) {
    var firstChild = wrapper.firstChild;
    if (firstChild.nodeType == goog.dom.NodeType.ELEMENT) {
      return /** @type {!Element} */ (firstChild);
    }
  }

  // Otherwise, return the wrapper DIV.
  return wrapper;
};

/**
 * Ensures the result is "safe" to insert as HTML.
 *
 * Note if the template has non-strict autoescape, the guarantees here are very
 * weak. It is recommended applications switch to requiring strict
 * autoescaping over time by tweaking goog.soy.REQUIRE_STRICT_AUTOESCAPE.
 *
 * In the case the argument is a SanitizedContent object, it either must
 * already be of kind HTML, or if it is kind="text", the output will be HTML
 * escaped.
 *
 * @param {*} templateResult The template result.
 * @return {string} The assumed-safe HTML output string.
 * @private
 */
goog.soy.ensureTemplateOutputHtml_ = function(templateResult) {
  // Allow strings as long as strict autoescaping is not mandated. Note we
  // allow everything that isn't an object, because some non-escaping templates
  // end up returning non-strings if their only print statement is a
  // non-escaped argument, plus some unit tests spoof templates.
  // TODO(gboyer): Track down and fix these cases.
  if (!goog.soy.REQUIRE_STRICT_AUTOESCAPE && !goog.isObject(templateResult)) {
    return String(templateResult);
  }

  // Allow SanitizedContent of kind HTML.
  if (templateResult instanceof goog.soy.data.SanitizedContent) {
    templateResult =
        /** @type {!goog.soy.data.SanitizedContent} */ (templateResult);
    var ContentKind = goog.soy.data.SanitizedContentKind;
    if (templateResult.contentKind === ContentKind.HTML) {
      return goog.asserts.assertString(templateResult.getContent());
    }
    if (templateResult.contentKind === ContentKind.TEXT) {
      // Allow text to be rendered, as long as we escape it. Other content
      // kinds will fail, since we don't know what to do with them.
      // TODO(gboyer): Perhaps also include URI in this case.
      return goog.string.htmlEscape(templateResult.getContent());
    }
  }

  goog.asserts.fail(
      'Soy template output is unsafe for use as HTML: ' + templateResult);

  // In production, return a safe string, rather than failing hard.
  return 'zSoyz';
};

/**
 * Checks that the rendered HTML does not start with an invalid tag that would
 * likely cause unexpected output from renderAsElement or renderAsFragment.
 * See {@link http://www.w3.org/TR/html5/semantics.html#semantics} for reference
 * as to which HTML elements can be parents of each other.
 * @param {string} html The output of a template.
 * @private
 */
goog.soy.assertFirstTagValid_ = function(html) {
  if (goog.asserts.ENABLE_ASSERTS) {
    var matches = html.match(goog.soy.INVALID_TAG_TO_RENDER_);
    goog.asserts.assert(
        !matches, 'This template starts with a %s, which ' +
            'cannot be a child of a <div>, as required by soy internals. ' +
            'Consider using goog.soy.renderElement instead.\nTemplate output: %s',
        matches && matches[0], html);
  }
};

/**
 * A pattern to find templates that cannot be rendered by renderAsElement or
 * renderAsFragment, as these elements cannot exist as the child of a <div>.
 * @type {!RegExp}
 * @private
 */
goog.soy.INVALID_TAG_TO_RENDER_ =
    /^<(body|caption|col|colgroup|head|html|tr|td|th|tbody|thead|tfoot)>/i;

/**
 * Immutable object that is passed into templates that are rendered
 * without any data.
 * @private @const
 */
goog.soy.defaultTemplateData_ = {};
<commit_msg>Add a dedicated type for strict HTML templates.<commit_after>// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Provides utility methods to render soy template.
 * @author chrishenry@google.com (Chris Henry)
 */

goog.provide('goog.soy');

goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.NodeType');
goog.require('goog.dom.TagName');
goog.require('goog.html.legacyconversions');
goog.require('goog.soy.data.SanitizedContent');
goog.require('goog.soy.data.SanitizedContentKind');
goog.require('goog.string');

/**
 * @define {boolean} Whether to require all Soy templates to be "strict html".
 * Soy templates that use strict autoescaping forbid noAutoescape along with
 * many dangerous directives, and return a runtime type SanitizedContent that
 * marks them as safe.
 *
 * If this flag is enabled, Soy templates will fail to render if a template
 * returns plain text -- indicating it is a non-strict template.
 */
goog.define('goog.soy.REQUIRE_STRICT_AUTOESCAPE', false);

/**
 * Type definition for strict Soy templates. Very useful when passing a template
 * as an argument.
 * @typedef {function(?, null=, ?Object<string, *>=):
 *     !goog.soy.data.SanitizedContent}
 */
goog.soy.StrictTemplate;

/**
 * Type definition for strict Soy HTML templates. Very useful when passing
 * a template as an argument.
 * @typedef {function(?, null=, ?Object<string, *>=):
 *     !goog.soy.data.SanitizedHtml}
 */
goog.soy.StrictHtmlTemplate;

/**
 * Sets the processed template as the innerHTML of an element. It is recommended
 * to use this helper function instead of directly setting innerHTML in your
 * hand-written code, so that it will be easier to audit the code for cross-site
 * scripting vulnerabilities.
 *
 * @param {?Element} element The element whose content we are rendering into.
 * @param {!goog.soy.data.SanitizedContent} templateResult The processed
 *     template of kind HTML or TEXT (which will be escaped).
 * @template ARG_TYPES
 */
goog.soy.renderHtml = function(element, templateResult) {
  element.innerHTML = goog.soy.ensureTemplateOutputHtml_(templateResult);
};

/**
 * Renders a Soy template and then set the output string as
 * the innerHTML of an element. It is recommended to use this helper function
 * instead of directly setting innerHTML in your hand-written code, so that it
 * will be easier to audit the code for cross-site scripting vulnerabilities.
 *
 * @param {Element} element The element whose content we are rendering into.
 * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
 *     The Soy template defining the element's content.
 * @param {ARG_TYPES=} opt_templateData The data for the template.
 * @param {Object=} opt_injectedData The injected data for the template.
 * @template ARG_TYPES
 */
goog.soy.renderElement = function(
    element, template, opt_templateData, opt_injectedData) {
  // Soy template parameter is only nullable for historical reasons.
  goog.asserts.assert(template, 'Soy template may not be null.');
  element.innerHTML = goog.soy.ensureTemplateOutputHtml_(
      template(
          opt_templateData || goog.soy.defaultTemplateData_, undefined,
          opt_injectedData));
};

/**
 * Renders a Soy template into a single node or a document
 * fragment. If the rendered HTML string represents a single node, then that
 * node is returned (note that this is *not* a fragment, despite them name of
 * the method). Otherwise a document fragment is returned containing the
 * rendered nodes.
 *
 * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
 *     The Soy template defining the element's content.
 * @param {ARG_TYPES=} opt_templateData The data for the template.
 * @param {Object=} opt_injectedData The injected data for the template.
 * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to
 *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
 * @return {!Node} The resulting node or document fragment.
 * @template ARG_TYPES
 */
goog.soy.renderAsFragment = function(
    template, opt_templateData, opt_injectedData, opt_domHelper) {
  // Soy template parameter is only nullable for historical reasons.
  goog.asserts.assert(template, 'Soy template may not be null.');
  var dom = opt_domHelper || goog.dom.getDomHelper();
  var output = template(
      opt_templateData || goog.soy.defaultTemplateData_, undefined,
      opt_injectedData);
  var html = goog.soy.ensureTemplateOutputHtml_(output);
  goog.soy.assertFirstTagValid_(html);
  var safeHtml = output instanceof goog.soy.data.SanitizedContent ?
      output.toSafeHtml() :
      goog.html.legacyconversions.safeHtmlFromString(html);
  return dom.safeHtmlToNode(safeHtml);
};

/**
 * Renders a Soy template into a single node. If the rendered
 * HTML string represents a single node, then that node is returned. Otherwise,
 * a DIV element is returned containing the rendered nodes.
 *
 * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
 *     The Soy template defining the element's content.
 * @param {ARG_TYPES=} opt_templateData The data for the template.
 * @param {Object=} opt_injectedData The injected data for the template.
 * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to
 *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
 * @return {!Element} Rendered template contents, wrapped in a parent DIV
 *     element if necessary.
 * @template ARG_TYPES
 */
goog.soy.renderAsElement = function(
    template, opt_templateData, opt_injectedData, opt_domHelper) {
  // Soy template parameter is only nullable for historical reasons.
  goog.asserts.assert(template, 'Soy template may not be null.');
  return goog.soy.convertToElement_(
      template(
          opt_templateData || goog.soy.defaultTemplateData_, undefined,
          opt_injectedData),
      opt_domHelper);
};

/**
 * Converts a processed Soy template into a single node. If the rendered
 * HTML string represents a single node, then that node is returned. Otherwise,
 * a DIV element is returned containing the rendered nodes.
 *
 * @param {!goog.soy.data.SanitizedContent} templateResult The processed
 *     template of kind HTML or TEXT (which will be escaped).
 * @param {?goog.dom.DomHelper=} opt_domHelper The DOM helper used to
 *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
 * @return {!Element} Rendered template contents, wrapped in a parent DIV
 *     element if necessary.
 */
goog.soy.convertToElement = function(templateResult, opt_domHelper) {
  return goog.soy.convertToElement_(templateResult, opt_domHelper);
};

/**
 * Non-strict version of {@code goog.soy.convertToElement}.
 *
 * @param {*} templateResult The processed template.
 * @param {?goog.dom.DomHelper=} opt_domHelper The DOM helper used to
 *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
 * @return {!Element} Rendered template contents, wrapped in a parent DIV
 *     element if necessary.
 * @private
 */
goog.soy.convertToElement_ = function(templateResult, opt_domHelper) {
  var dom = opt_domHelper || goog.dom.getDomHelper();
  var wrapper = dom.createElement(goog.dom.TagName.DIV);
  var html = goog.soy.ensureTemplateOutputHtml_(templateResult);
  goog.soy.assertFirstTagValid_(html);
  wrapper.innerHTML = html;

  // If the template renders as a single element, return it.
  if (wrapper.childNodes.length == 1) {
    var firstChild = wrapper.firstChild;
    if (firstChild.nodeType == goog.dom.NodeType.ELEMENT) {
      return /** @type {!Element} */ (firstChild);
    }
  }

  // Otherwise, return the wrapper DIV.
  return wrapper;
};

/**
 * Ensures the result is "safe" to insert as HTML.
 *
 * Note if the template has non-strict autoescape, the guarantees here are very
 * weak. It is recommended applications switch to requiring strict
 * autoescaping over time by tweaking goog.soy.REQUIRE_STRICT_AUTOESCAPE.
 *
 * In the case the argument is a SanitizedContent object, it either must
 * already be of kind HTML, or if it is kind="text", the output will be HTML
 * escaped.
 *
 * @param {*} templateResult The template result.
 * @return {string} The assumed-safe HTML output string.
 * @private
 */
goog.soy.ensureTemplateOutputHtml_ = function(templateResult) {
  // Allow strings as long as strict autoescaping is not mandated. Note we
  // allow everything that isn't an object, because some non-escaping templates
  // end up returning non-strings if their only print statement is a
  // non-escaped argument, plus some unit tests spoof templates.
  // TODO(gboyer): Track down and fix these cases.
  if (!goog.soy.REQUIRE_STRICT_AUTOESCAPE && !goog.isObject(templateResult)) {
    return String(templateResult);
  }

  // Allow SanitizedContent of kind HTML.
  if (templateResult instanceof goog.soy.data.SanitizedContent) {
    templateResult =
        /** @type {!goog.soy.data.SanitizedContent} */ (templateResult);
    var ContentKind = goog.soy.data.SanitizedContentKind;
    if (templateResult.contentKind === ContentKind.HTML) {
      return goog.asserts.assertString(templateResult.getContent());
    }
    if (templateResult.contentKind === ContentKind.TEXT) {
      // Allow text to be rendered, as long as we escape it. Other content
      // kinds will fail, since we don't know what to do with them.
      // TODO(gboyer): Perhaps also include URI in this case.
      return goog.string.htmlEscape(templateResult.getContent());
    }
  }

  goog.asserts.fail(
      'Soy template output is unsafe for use as HTML: ' + templateResult);

  // In production, return a safe string, rather than failing hard.
  return 'zSoyz';
};

/**
 * Checks that the rendered HTML does not start with an invalid tag that would
 * likely cause unexpected output from renderAsElement or renderAsFragment.
 * See {@link http://www.w3.org/TR/html5/semantics.html#semantics} for reference
 * as to which HTML elements can be parents of each other.
 * @param {string} html The output of a template.
 * @private
 */
goog.soy.assertFirstTagValid_ = function(html) {
  if (goog.asserts.ENABLE_ASSERTS) {
    var matches = html.match(goog.soy.INVALID_TAG_TO_RENDER_);
    goog.asserts.assert(
        !matches, 'This template starts with a %s, which ' +
            'cannot be a child of a <div>, as required by soy internals. ' +
            'Consider using goog.soy.renderElement instead.\nTemplate output: %s',
        matches && matches[0], html);
  }
};

/**
 * A pattern to find templates that cannot be rendered by renderAsElement or
 * renderAsFragment, as these elements cannot exist as the child of a <div>.
 * @type {!RegExp}
 * @private
 */
goog.soy.INVALID_TAG_TO_RENDER_ =
    /^<(body|caption|col|colgroup|head|html|tr|td|th|tbody|thead|tfoot)>/i;

/**
 * Immutable object that is passed into templates that are rendered
 * without any data.
 * @private @const
 */
goog.soy.defaultTemplateData_ = {};
<|endoftext|>


<commit_before>/**
 *  Copyright 2015 Zachary Michael - Squishmedia
 *
 *  This file is part of BIDS-Validator.
 *
 *  BIDS-Validator is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  BIDS-Validator is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with BIDS-Validator.  If not, see <http://www.gnu.org/licenses/>
 **/

var JSHINT = require('jshint').JSHINT;

/**
 * JSON
 *
 * Takes a JSON file as a string and a callback
 * as arguments. And callsback with any errors
 * it finds while validating against the BIDS
 * specification.
 */

module.exports = function (contents, callback) {

    if (!JSHINT(contents)) {
        var out = JSHINT.data(),
        errors = out.errors;
        for(var i = 0; errors.length > i; ++i){
        	if(errors[i] !== null){
	        	console.log('break')
	        	errors[i].severity = 'error';
	        	console.log(errors)
	        	console.log('break')
	        }
	    }
        callback(errors);
    } else {
    	// TODO figure out how to filter sidecar only files
    	var jsObj = JSON.parse(contents);
    	jsObj = jsObj.hasOwnProperty('repetition_time');
		if(jsObj === false){
			errors = []
			var newError = {
                evidence: contents,
                line: null,
                character: null,
                reason: 'JSON sidecar files must have key and value for repetition_time',
                severity: 'error'
            }
            errors.push(newError);
            callback(errors);
		}else{
	        callback(null);
	    }

    }
};<commit_msg>fixing conditional cause null is falsey and removing logs<commit_after>/**
 *  Copyright 2015 Zachary Michael - Squishmedia
 *
 *  This file is part of BIDS-Validator.
 *
 *  BIDS-Validator is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  BIDS-Validator is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with BIDS-Validator.  If not, see <http://www.gnu.org/licenses/>
 **/

var JSHINT = require('jshint').JSHINT;

/**
 * JSON
 *
 * Takes a JSON file as a string and a callback
 * as arguments. And callsback with any errors
 * it finds while validating against the BIDS
 * specification.
 */

module.exports = function (contents, callback) {

    if (!JSHINT(contents)) {
        var out = JSHINT.data(),
        errors = out.errors;
        for(var i = 0; errors.length > i; ++i){
        	if(errors[i]){
	        	errors[i].severity = 'error';
	        }
	    }
        callback(errors);
    } else {
    	// TODO figure out how to filter sidecar only files
    	var jsObj = JSON.parse(contents);
    	jsObj = jsObj.hasOwnProperty('repetition_time');
		if(jsObj === false){
			errors = []
			var newError = {
                evidence: contents,
                line: null,
                character: null,
                reason: 'JSON sidecar files must have key and value for repetition_time',
                severity: 'error'
            }
            errors.push(newError);
            callback(errors);
		}else{
	        callback(null);
	    }

    }
};<|endoftext|>


<commit_before>import { amoStageCDN } from './lib/shared';

const staticHost = 'https://addons-amo-cdn.allizom.org';

module.exports = {
  staticHost,

  CSP: {
    directives: {
      fontSrc: [
        staticHost,
      ],
      scriptSrc: [
        staticHost,
        'https://www.google-analytics.com/analytics.js',
      ],
      styleSrc: [staticHost],
      imgSrc: [
        "'self'",
        'data:',
        amoStageCDN,
        staticHost,
        'https://www.google-analytics.com',
      ],
    },
  },
};
<commit_msg>Enable AMInstallButton on AMO -stage (#6206)<commit_after>import { amoStageCDN } from './lib/shared';

const staticHost = 'https://addons-amo-cdn.allizom.org';

module.exports = {
  staticHost,

  CSP: {
    directives: {
      fontSrc: [
        staticHost,
      ],
      scriptSrc: [
        staticHost,
        'https://www.google-analytics.com/analytics.js',
      ],
      styleSrc: [staticHost],
      imgSrc: [
        "'self'",
        'data:',
        amoStageCDN,
        staticHost,
        'https://www.google-analytics.com',
      ],
    },
  },

  enableAMInstallButton: true,
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name		Booru Mass Uploader
// @description	 Add ability to bulk upload images to your booru
// @version	1.0
// @author		Seedmanc
// @include	http://*.booru.org/index.php?page=*&s=mass_upload

function loadAndExecute(url, callback){
	var scriptNode = document.createElement ("script");
	scriptNode.addEventListener("load", callback);
	scriptNode.onerror = function(){
		throw new Error("Can't load "+url);
	};
	scriptNode.src = url;
	document.head.appendChild(scriptNode);
};

(function(){
	if (window.top != window.self)
		return;
	//loadAndExecute("https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js", main);

	var xhr= new XMLHttpRequest();
	xhr.open('GET', 'http://crossorigin.me/http://seedmanc.github.io/Booru-mass-uploader/index.html', true);
	xhr.onreadystatechange= function() {
		if (this.readyState != 4) return;
		if (this.status != 200) return; // or whatever error handling you want
		document.getElementsByTagName('body')[0].innerHTML = this.responseText;
		var s = document.getElementsByTagName('script');
for (var i = 0; i < s.length ; i++) {
  var node=s[i], parent=node.parentElement, d = document.createElement('script');
  d.async=node.async;
  d.src=node.src;
  parent.insertBefore(d,node);
  parent.removeChild(node);
}
	};
	xhr.send();

})();

function main(){

}<commit_msg>integrate link to uploader<commit_after>// ==UserScript==
// @name		Booru Mass Uploader
// @description	 Add ability to bulk upload images to your booru
// @version	1.0
// @author		Seedmanc
// @include	http://*.booru.org/*
// ==/UserScript==

function loadAndExecute(url, callback){
	var scriptNode = document.createElement ("script");
	scriptNode.addEventListener("load", callback);
	scriptNode.onerror = function(){
		throw new Error("Can't load "+url);
	};
	scriptNode.src = url;
	document.head.appendChild(scriptNode);
};

(function(){
	if (window.top != window.self)
		return;

	if (~document.location.href.indexOf('s=mass_upload')) {
		var xhr= new XMLHttpRequest();
		xhr.open('GET', 'http://crossorigin.me/http://seedmanc.github.io/Booru-mass-uploader/index.html', true);
		xhr.onreadystatechange= function() {
			if (this.readyState != 4) return;
			if (this.status != 200) return; // or whatever error handling you want
			document.getElementsByTagName('body')[0].innerHTML = this.responseText;
			var s = document.getElementsByTagName('script');
			for (var i = 0; i < s.length ; i++) {
				var node=s[i], parent=node.parentElement, d = document.createElement('script');
				d.async=node.async;
				d.src=node.src;
				parent.insertBefore(d,node);
				parent.removeChild(node);
			}
		};
		xhr.send();
	} else if (~document.location.href.indexOf('?page='))
		//document.addEventListener('DOMContentLoaded', function()
		{
			var navbar = document.getElementById('navbar');
			var notice = document.getElementById('notice').previous() ;
			notice.parentNode.removeChild(notice);
			var longnotice = document.getElementById('long-notice');
			longnotice.parentNode.removeChild(longnotice);
			var ad = document.querySelectorAll('center div[id*="adbox"]')[0].parentNode;
			ad.parentNode.removeChild(ad);

			var li = document.createElement("li");
			var a  = document.createElement("a");
			a.style= "font-weight:bold;";
			a.appendChild(document.createTextNode('Mass Upload'));
			a.href = document.location.href.split('.')[0]+'.booru.org/index.php?page=post&s=mass_upload';
			li.appendChild(a);
			navbar.appendChild(li);
		}//, false);
})(); <|endoftext|>


<commit_before>;(function(){
var AlloyTouch = typeof require === 'function'
    ? require('../alloy_touch.js')
    : window.AlloyTouch
var Transform = typeof require === 'function'
    ? require('../transformjs/transform.js')
    : window.Transform

let vueAlloyTouch = {};

vueAlloyTouch.install = function(Vue){

    var isVue2 = !!(Vue.version.substr(0,1) == 2);

    if(!AlloyTouch){
        throw new Error('you need include alloy_touch.js')
    }
    if(!Transform){
        throw new Error('you need include transform.js')
    }

    var directiveBinding = null;

    if(isVue2){
        directiveBinding = {
            bind: function(el, binding){
                //注册时的赋值 value, el已经挂载
                var options = getAlloyTouchConfig(el, binding.value);
                Transform(options.target);
                el.__alloytouch__handle = new AlloyTouch(options);
            },
            update: function (el, binding) {
                var value = binding.value;
                if(!el.__alloytouch__handle) {
                    return;
                }
                if(value.min!=undefined){
                    el.__alloytouch__handle.min = value.min;
                }
                if(value.max!= undefined){
                    el.__alloytouch__handle.max = value.max;
                }
            },
            unbind: function(el){
                el.__alloytouch__handle = null;
            }
        };
    }else {
        directiveBinding = {
            bind: function(){
                this.el.__alloytouch__handle = null;

            } ,
            update: function(binding){
                if(!this.el.__alloytouch__handle){
                    var options = getAlloyTouchConfig(this.el, binding);
                    Transform(options.target);
                    this.el.__alloytouch__handle = new AlloyTouch(options);
                }else {
                    if(binding.min!=undefined){
                        this.el.__alloytouch__handle.min = binding.min;
                    }
                    if(binding.max!=undefined){
                        this.el.__alloytouch__handle.max = binding.max;
                    }
                }
            },
           unbind: function(){
                this.el.__alloytouch__handle = null;
           }
        }
    }

    Vue.directive('alloytouch', directiveBinding)
    function noop(){

    }
    function _getOption(value, defaultValue){
        return value==undefined ?defaultValue: value
    }

    function getAlloyTouchConfig(el, value) {

        var options = value.options || {}
        var methods = value.methods || {};
        var result = {
            touch: el,//反馈触摸的dom
            target: el, //运动的对象
            bindSelf: _getOption(options.bindSelf, false),
            property: _getOption(options.property, 'translateY'),  //被运动的属性
            vertical: _getOption(options.vertical,1),//不必需，默认是true代表监听竖直方向touch
            min: _getOption(options.min, 0), //不必需,运动属性的最小值
            max: _getOption(options.max, 0), //不必需,滚动属性的最大值
            sensitivity: _getOption(options.sensitivity, 1),//不必需,触摸区域的灵敏度，默认值为1，可以为负数
            factor: _getOption(options.factor, 1),//不必需,表示触摸位移与被运动属性映射关系，默认值是1
            spring: _getOption(options.spring, 1), //不必需,是否有回弹效果。默认是true
            step: _getOption(options.step, 45),//用于校正到step的整数倍
            change : methods.change || noop,
            touchEnd : methods.touchEnd || noop,
            touchStart : methods.touchStart || noop,
            touchMove : methods.touchMove || noop,
            touchCancel : methods.touchCancel || noop,
            reboundEnd : methods.reboundEnd || noop,
            animationEnd : methods.animationEnd || noop,
            correctionEnd : methods.correctionEnd || noop
        }
        if(value.min !=undefined) {
            result.min = value.min;
        }
        if(value.max !=undefined) {
            result.max = value.max;
        }
        if(!!options.touch){
            var touchEl = el.querySelector(options.touch);
            result.touch = touchEl || el;
        }

        if(!!options.target){
            var target = el.querySelector(options.target);
            result.target = target || el;
        }

        return result;
    }
}

if(typeof module !== 'undefined' && typeof exports === 'object') {
    module.exports = vueAlloyTouch;
} else {
    window.vueAlloyTouch = vueAlloyTouch;
}

})();<commit_msg>fix let bug<commit_after>;(function(){
var AlloyTouch = typeof require === 'function'
    ? require('../alloy_touch.js')
    : window.AlloyTouch
var Transform = typeof require === 'function'
    ? require('../transformjs/transform.js')
    : window.Transform

var vueAlloyTouch = {};

vueAlloyTouch.install = function(Vue){

    var isVue2 = !!(Vue.version.substr(0,1) == 2);

    if(!AlloyTouch){
        throw new Error('you need include alloy_touch.js')
    }
    if(!Transform){
        throw new Error('you need include transform.js')
    }

    var directiveBinding = null;

    if(isVue2){
        directiveBinding = {
            bind: function(el, binding){
                //注册时的赋值 value, el已经挂载
                var options = getAlloyTouchConfig(el, binding.value);
                Transform(options.target);
                el.__alloytouch__handle = new AlloyTouch(options);
            },
            update: function (el, binding) {
                var value = binding.value;
                if(!el.__alloytouch__handle) {
                    return;
                }
                if(value.min!=undefined){
                    el.__alloytouch__handle.min = value.min;
                }
                if(value.max!= undefined){
                    el.__alloytouch__handle.max = value.max;
                }
            },
            unbind: function(el){
                el.__alloytouch__handle = null;
            }
        };
    }else {
        directiveBinding = {
            bind: function(){
                this.el.__alloytouch__handle = null;

            } ,
            update: function(binding){
                if(!this.el.__alloytouch__handle){
                    var options = getAlloyTouchConfig(this.el, binding);
                    Transform(options.target);
                    this.el.__alloytouch__handle = new AlloyTouch(options);
                }else {
                    if(binding.min!=undefined){
                        this.el.__alloytouch__handle.min = binding.min;
                    }
                    if(binding.max!=undefined){
                        this.el.__alloytouch__handle.max = binding.max;
                    }
                }
            },
           unbind: function(){
                this.el.__alloytouch__handle = null;
           }
        }
    }

    Vue.directive('alloytouch', directiveBinding)
    function noop(){

    }
    function _getOption(value, defaultValue){
        return value==undefined ?defaultValue: value
    }

    function getAlloyTouchConfig(el, value) {

        var options = value.options || {}
        var methods = value.methods || {};
        var result = {
            touch: el,//反馈触摸的dom
            target: el, //运动的对象
            bindSelf: _getOption(options.bindSelf, false),
            property: _getOption(options.property, 'translateY'),  //被运动的属性
            vertical: _getOption(options.vertical,1),//不必需，默认是true代表监听竖直方向touch
            min: _getOption(options.min, 0), //不必需,运动属性的最小值
            max: _getOption(options.max, 0), //不必需,滚动属性的最大值
            sensitivity: _getOption(options.sensitivity, 1),//不必需,触摸区域的灵敏度，默认值为1，可以为负数
            factor: _getOption(options.factor, 1),//不必需,表示触摸位移与被运动属性映射关系，默认值是1
            spring: _getOption(options.spring, 1), //不必需,是否有回弹效果。默认是true
            step: _getOption(options.step, 45),//用于校正到step的整数倍
            tap: methods.tap || noop,
            pressMove: methods.pressMove || noop,
            change : methods.change || noop,
            touchEnd : methods.touchEnd || noop,
            touchStart : methods.touchStart || noop,
            touchMove : methods.touchMove || noop,
            touchCancel : methods.touchCancel || noop,
            reboundEnd : methods.reboundEnd || noop,
            animationEnd : methods.animationEnd || noop,
            correctionEnd : methods.correctionEnd || noop
        }
        if(value.min !=undefined) {
            result.min = value.min;
        }
        if(value.max !=undefined) {
            result.max = value.max;
        }
        if(!!options.touch){
            var touchEl = el.querySelector(options.touch);
            result.touch = touchEl || el;
        }

        if(!!options.target){
            var target = el.querySelector(options.target);
            result.target = target || el;
        }

        return result;
    }
}

if(typeof module !== 'undefined' && typeof exports === 'object') {
    module.exports = vueAlloyTouch;
} else {
    window.vueAlloyTouch = vueAlloyTouch;
}

})();<|endoftext|>


<commit_before>'use strict';

/* Services */

angular.module('myApp.services', []).

factory("flash", function($rootScope) {
  var queue = [];
  var currentMessage = "";

  $rootScope.$on("$routeChangeSuccess", function() {
    currentMessage = queue.shift() || "";
  });

  return {
    setMessage: function(message) {
      queue.push(message);
    },
    getMessage: function() {
      return currentMessage;
    }
  };
}).

  value('version', '0.1').

  service('EventBus', function() {
    var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
    return eb;
  }).

  service('AuthService', [function() {
    this.getPerson = function(username) {
      username = username || "(Walle)";
      return {
        firstname: username,
        lastname: "(Web)",
        email: "ww@www.org"
      };
    }
  }]).

  service('AnmalanService', ['AuthService', function(authService) {
    this.addLogMessage = function(_id, _subject, _body, _user, fnDone) {
      var promise = $.Deferred();
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
        eb.onopen = function() {
            eb.send('skapa.loggmeddelande', {id: _id, skapadAv: authService.getPerson(_user), subject: _subject, body: _body},
            function(reply) {
              if (reply.status == "ok") {
                promise.resolve(reply);
            } else {
              promise.reject(reply);
            }
            });
      };
      return promise;
    };

    this.skickaTillPolisen = function(_id, _title, _user, fnDone) {
      var promise = $.Deferred();
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
      eb.onopen = function() {
        eb.send('skicka.till.polisen', {id: _id, username: _user, title: _title},
        function(reply) {
          if (reply.status == "ok") {
            promise.resolve(reply);
          } else {
            promise.reject(reply);
          }
        });
       };
       return promise;
    };

    this.save = function(_anmalan) {
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
      var promise = $.Deferred();
      eb.onopen = function() {
        eb.send('skapa.anmalan', {skapadAv: authService.getPerson(), anmalan: _anmalan},
        function(reply) {
          if (reply.status == "ok") {
            promise.resolve(reply._id);
          } else {
            promise.reject(reply);
          }
          console.log('AnmalanService::save processing reply', reply);
          eb.close();
        });
      };
      return promise;
    };

    this.addFile = function(_id, _file, _user, fnDone) {
      //https://github.com/vert-x/vertx-examples/tree/master/src/raw/java/upload
      //UploadClient
      //console.log('myfile : '+_file);
      console.log('myfile : '+_file.files[0].name);

      var fd = new FormData();
      fd.append("uploadedFile", _file.files[0]);

      //Göra lite snyggare sen
      var uploadComplete = function(evt) {
        console.log(evt.target.responseText);
      };
      var uploadFailed = function(evt) {
        console.log("There was an error attempting to upload the file.");
      };
      var uploadCanceled = function(evt) {
        console.log("The upload has been canceled by the user or the browser dropped the connection.");
      };

      var xhr = new XMLHttpRequest();
      //xhr.upload.addEventListener("progress", _uploadProgress, false);
      xhr.addEventListener("load", uploadComplete, false);
      xhr.addEventListener("error", uploadFailed, false);
      xhr.addEventListener("abort", uploadCanceled, false);
      xhr.open("POST", "http://localhost:8081/form");
      xhr.send(fd);
      console.log('myfile sent!');
    };

    this.findOne = function(id, _user, fnOpen) {
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
      eb.onopen = function() {
        eb.send('test.mongodb', {'action': 'find', 'collection': 'anmalningar', matcher: {'_id': id + ""}},
        function(reply) {
          console.log('AnmalanService::findOne processing reply', reply);
          fnOpen.call(this, "ok", reply);
          eb.close();
        });
      };
    };

    this.findAll = function(fn, fnUpdated) {
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
      eb.onopen = function() {
        console.log("Buss open");
        eb.send('test.mongodb', {action: 'find', collection: 'anmalningar', matcher: {} },
          function(reply) {
            console.log('AnmalanService::processing reply', reply);
            if (reply.status === 'ok') {
              var anmalanArray = [];
              for (var i = 0; i < reply.results.length; i++) {
                anmalanArray[i] = reply.results[i];
              }
              fn.call(this, "ok", anmalanArray);
            } else {
              console.error('Failed to retrieve tickets: ' + reply.message);
              fn.call("error", null);
            }
          }
        );
        eb.registerHandler('anmalan.uppdaterad',
          function(updatedEvent) {
            console.log('AnmalanService::findAll anmalan.uppdaterad', updatedEvent);
            fnUpdated.call(this, "ok", updatedEvent);
          }
        );
      };
      console.log("Events are set up.");
      }
    }]).

    service('global', function($cookieStore, $location, $filter) {
      var globalService = {};
      globalService.user = null;
      globalService.isAuth = function (){
        if (globalService.user == null) {
          globalService.user = $cookieStore.get('user');
        }
        return (globalService.user != null);
      };
      globalService.setUser = function(newUser) {
        globalService.user = newUser;
        if (globalService.user == null)
          $cookieStore.remove('user');
        else
          $cookieStore.put('user', globalService.user);
      };
      globalService.getUser = function() {
        return globalService.user;
      };
      return globalService;
    }).

    service('TimeDisplayService', [function() {
      this.timeSince = function(date) {
        var seconds = Math.floor((new Date() - date) / 1000);
        var interval = Math.floor(seconds / 31536000);

        if (interval > 1) {
          return interval + " år";
        }
        interval = Math.floor(seconds / 2592000);
        if (interval > 1) {
          return interval + " månader";
        }
        interval = Math.floor(seconds / 86400);
        if (interval == 1) {
          return "en dag";
        } else if (interval > 1) {
          return interval + " dagar";
        }
        interval = Math.floor(seconds / 3600);
        if (interval == 1) {
          return "en timme";
        } else if (interval > 1) {
          return interval + " timmar";
        }
        interval = Math.floor(seconds / 60);
        if (interval == 1) {
          return "en minut";
        } else if (interval > 1) {
          return interval + " minuter";
        }
        var seconds = Math.floor(seconds);
        if (seconds == 1) {
          return "en sekund";
        } else if (seconds == 0) {
          return null;
        } else {
          return seconds + " sekunder";
        }
      }
    }]).

    service('LoginService', ['EventBus', function(eb) {
      this.login = function(username, password) {
      var promise = $.Deferred();
      eb.login(username, password,
        function (reply) {
          if (reply.status === 'ok') {
            promise.resolve();
          } else {
            promise.reject();
          }
        });
      return promise;
      }
    }
  ]);
<commit_msg>fixat skicka till polisen<commit_after>'use strict';

/* Services */

angular.module('myApp.services', []).

factory("flash", function($rootScope) {
  var queue = [];
  var currentMessage = "";

  $rootScope.$on("$routeChangeSuccess", function() {
    currentMessage = queue.shift() || "";
  });

  return {
    setMessage: function(message) {
      queue.push(message);
    },
    getMessage: function() {
      return currentMessage;
    }
  };
}).

  value('version', '0.1').

  service('EventBus', function() {
    var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
    return eb;
  }).

  service('AuthService', [function() {
    this.getPerson = function(username) {
      username = username || "(Walle)";
      return {
        firstname: username,
        lastname: "(Web)",
        email: "ww@www.org"
      };
    }
  }]).

  service('AnmalanService', ['AuthService', function(authService) {
    this.addLogMessage = function(_id, _subject, _body, _user, fnDone) {
      var promise = $.Deferred();
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
        eb.onopen = function() {
            eb.send('skapa.loggmeddelande', {id: _id, skapadAv: authService.getPerson(_user), subject: _subject, body: _body},
            function(reply) {
              if (reply.status == "ok") {
                promise.resolve(reply);
            } else {
              promise.reject(reply);
            }
            });
      };
      return promise;
    };

    this.skickaTillPolisen = function(_id, _title, _user, fnDone) {
      var promise = $.Deferred();
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
      eb.onopen = function() {
        eb.send('skicka.till.polisen', {id: _id, skapadAv: authService.getPerson(_user), title: _title},
        function(reply) {
          if (reply.status == "ok") {
            promise.resolve(reply);
          } else {
            promise.reject(reply);
          }
        });
       };
       return promise;
    };

    this.save = function(_anmalan) {
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
      var promise = $.Deferred();
      eb.onopen = function() {
        eb.send('skapa.anmalan', {skapadAv: authService.getPerson(), anmalan: _anmalan},
        function(reply) {
          if (reply.status == "ok") {
            promise.resolve(reply._id);
          } else {
            promise.reject(reply);
          }
          console.log('AnmalanService::save processing reply', reply);
          eb.close();
        });
      };
      return promise;
    };

    this.addFile = function(_id, _file, _user, fnDone) {
      //https://github.com/vert-x/vertx-examples/tree/master/src/raw/java/upload
      //UploadClient
      //console.log('myfile : '+_file);
      console.log('myfile : '+_file.files[0].name);

      var fd = new FormData();
      fd.append("uploadedFile", _file.files[0]);

      //Göra lite snyggare sen
      var uploadComplete = function(evt) {
        console.log(evt.target.responseText);
      };
      var uploadFailed = function(evt) {
        console.log("There was an error attempting to upload the file.");
      };
      var uploadCanceled = function(evt) {
        console.log("The upload has been canceled by the user or the browser dropped the connection.");
      };

      var xhr = new XMLHttpRequest();
      //xhr.upload.addEventListener("progress", _uploadProgress, false);
      xhr.addEventListener("load", uploadComplete, false);
      xhr.addEventListener("error", uploadFailed, false);
      xhr.addEventListener("abort", uploadCanceled, false);
      xhr.open("POST", "http://localhost:8081/form");
      xhr.send(fd);
      console.log('myfile sent!');
    };

    this.findOne = function(id, _user, fnOpen) {
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
      eb.onopen = function() {
        eb.send('test.mongodb', {'action': 'find', 'collection': 'anmalningar', matcher: {'_id': id + ""}},
        function(reply) {
          console.log('AnmalanService::findOne processing reply', reply);
          fnOpen.call(this, "ok", reply);
          eb.close();
        });
      };
    };

    this.findAll = function(fn, fnUpdated) {
      var eb = new vertx.EventBus(window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');
      eb.onopen = function() {
        console.log("Buss open");
        eb.send('test.mongodb', {action: 'find', collection: 'anmalningar', matcher: {} },
          function(reply) {
            console.log('AnmalanService::processing reply', reply);
            if (reply.status === 'ok') {
              var anmalanArray = [];
              for (var i = 0; i < reply.results.length; i++) {
                anmalanArray[i] = reply.results[i];
              }
              fn.call(this, "ok", anmalanArray);
            } else {
              console.error('Failed to retrieve tickets: ' + reply.message);
              fn.call("error", null);
            }
          }
        );
        eb.registerHandler('anmalan.uppdaterad',
          function(updatedEvent) {
            console.log('AnmalanService::findAll anmalan.uppdaterad', updatedEvent);
            fnUpdated.call(this, "ok", updatedEvent);
          }
        );
      };
      console.log("Events are set up.");
      }
    }]).

    service('global', function($cookieStore, $location, $filter) {
      var globalService = {};
      globalService.user = null;
      globalService.isAuth = function (){
        if (globalService.user == null) {
          globalService.user = $cookieStore.get('user');
        }
        return (globalService.user != null);
      };
      globalService.setUser = function(newUser) {
        globalService.user = newUser;
        if (globalService.user == null)
          $cookieStore.remove('user');
        else
          $cookieStore.put('user', globalService.user);
      };
      globalService.getUser = function() {
        return globalService.user;
      };
      return globalService;
    }).

    service('TimeDisplayService', [function() {
      this.timeSince = function(date) {
        var seconds = Math.floor((new Date() - date) / 1000);
        var interval = Math.floor(seconds / 31536000);

        if (interval > 1) {
          return interval + " år";
        }
        interval = Math.floor(seconds / 2592000);
        if (interval > 1) {
          return interval + " månader";
        }
        interval = Math.floor(seconds / 86400);
        if (interval == 1) {
          return "en dag";
        } else if (interval > 1) {
          return interval + " dagar";
        }
        interval = Math.floor(seconds / 3600);
        if (interval == 1) {
          return "en timme";
        } else if (interval > 1) {
          return interval + " timmar";
        }
        interval = Math.floor(seconds / 60);
        if (interval == 1) {
          return "en minut";
        } else if (interval > 1) {
          return interval + " minuter";
        }
        var seconds = Math.floor(seconds);
        if (seconds == 1) {
          return "en sekund";
        } else if (seconds == 0) {
          return null;
        } else {
          return seconds + " sekunder";
        }
      }
    }]).

    service('LoginService', ['EventBus', function(eb) {
      this.login = function(username, password) {
      var promise = $.Deferred();
      eb.login(username, password,
        function (reply) {
          if (reply.status === 'ok') {
            promise.resolve();
          } else {
            promise.reject();
          }
        });
      return promise;
      }
    }
  ]);
<|endoftext|>


<commit_before>$(function() {

    var currentPlayList = null;

    var getAlbumForPlaylist = function(id) {
        var url = $('#urlAlbumForPlayer').val();
        var album = null;
        $.ajaxSetup({async: false});
        $.getJSON(url, {id: id}, function(data){
            if (data.success) {
                album = data.album;
            }
        });
        $.ajaxSetup({async: true});

        return album;
    };

    var getSongsForPlaylist = function(id) {
        var album = getAlbumForPlaylist(id);
        return album.songs;
    };

    var movePlaylist = function() {
        if ($('.sidebar').css('display') === 'none' && $('.sidebar .player').length > 0) {
            var player = $('.sidebar .player');
            $('.mainContent').after(player);
        }
        $('.albumContent.playList').hide(800);
        $("html, body").animate({ scrollTop: $(document).height() }, 1000);
    };

    $('.mainContent').on('click', '.headerDisco .playPause', function(e) {
        e.preventDefault();
        movePlaylist();

        var me = $(this);
        var album = getAlbumForPlaylist(me.attr('id'));
        var songs = album.songs;
        var image = album.image;
        currentPlayList = me.attr('id');
        mozcuPlaylist.setPlaylist(songs);
        $('.jp-playlist').css('background-image', 'url('+ image +')');
    });

    $('.mainContent').on('click', '.playList .songName a', function(e) {
        e.preventDefault();
        movePlaylist();

        var me = $(this);
        var data = me.attr('id').split('-');
        var songs = getSongsForPlaylist(data[0]);
        if (currentPlayList != data[0]) {
            mozcuPlaylist.setPlaylist(songs);
            currentPlayList = data[0];
        }
        mozcuPlaylist.play(data[1] - 1);
    });

    var mozcuPlaylist = new jPlayerPlaylist({
            jPlayer: "#jquery_jplayer_1",
            cssSelectorAncestor: "#jp_container_1"
    }, [],
    {
        playlistOptions: {
            autoPlay: true,
        },
        swfPath: "/js/jplayer",
        supplied: "mp3",
        smoothPlayBar: true,
        wmode: "window",
        keyEnabled: true,
        solution: "flash, html"
    });

});<commit_msg>avances en mobile<commit_after>$(function() {

    var currentPlayList = null;

    var getAlbumForPlaylist = function(id) {
        var url = $('#urlAlbumForPlayer').val();
        var album = null;
        $.ajaxSetup({async: false});
        $.getJSON(url, {id: id}, function(data){
            if (data.success) {
                album = data.album;
            }
        });
        $.ajaxSetup({async: true});

        return album;
    };

    var getSongsForPlaylist = function(id) {
        var album = getAlbumForPlaylist(id);
        return album.songs;
    };

    var movePlaylist = function() {
        if ($('.sidebar').css('display') === 'none' && $('.sidebar .player').length > 0) {
            var player = $('.sidebar .player');
            player.css('position', 'absolute');
            player.css('left', '-500px');
            $('body').append(player);
        }
        //$('.albumContent.playList').hide(800);
        //$("html, body").animate({ scrollTop: $(document).height() }, 1000);
    };

    $('.mainContent').on('click', '.headerDisco .playPause', function(e) {
        e.preventDefault();
        movePlaylist();

        var me = $(this);
        var album = getAlbumForPlaylist(me.attr('id'));
        var songs = album.songs;
        var image = album.image;
        currentPlayList = me.attr('id');
        mozcuPlaylist.setPlaylist(songs);
        $('.jp-playlist').css('background-image', 'url('+ image +')');
    });

    $('.mainContent').on('click', '.playList .songName a', function(e) {
        e.preventDefault();
        movePlaylist();

        var me = $(this);
        var data = me.attr('id').split('-');
        var songs = getSongsForPlaylist(data[0]);
        if (currentPlayList != data[0]) {
            mozcuPlaylist.setPlaylist(songs);
            currentPlayList = data[0];
        }
        mozcuPlaylist.play(data[1] - 1);
    });

    var mozcuPlaylist = new jPlayerPlaylist({
            jPlayer: "#jquery_jplayer_1",
            cssSelectorAncestor: "#jp_container_1"
    }, [],
    {
        playlistOptions: {
            autoPlay: true,
        },
        swfPath: "/js/jplayer",
        supplied: "mp3",
        smoothPlayBar: true,
        wmode: "window",
        keyEnabled: true,
        solution: "flash, html"
    });

});<|endoftext|>


<commit_before>/**
 * Main config parameters for budget web app
 */

// show error messages for at least <delay> milliseconds
export const ERROR_MESSAGE_DELAY = 5000;

// investment rate of return (assumed, per annum)
export const FUTURE_INVESTMENT_RATE = 0.1;

// currency symbol
export const SYMBOL_CURRENCY_HTML = '\u00a3';
export const SYMBOL_CURRENCY_RAW = '£';

// update changes regularly with the server
export const TIMER_UPDATE_SERVER = 1000;

// error messages
export const ERROR_MSG_SERVER_UPDATE = 'Error updating server!';
export const ERROR_MSG_BAD_DATA = 'Please enter valid data';
export const ERROR_MSG_BUG_INVALID_ITEM = 'Bug: no date/cost on edited item';

// font definitions
export const FONT_AXIS_LABEL = '11px Arial, Helvetica, sans-serif';
export const FONT_GRAPH_TITLE = '16px bold Arial, Helvetica, sans-serif';
export const FONT_GRAPH_TITLE_LARGE = '18px bold Arial, Helvetica, sans-serif';
export const FONT_GRAPH_KEY = '13px Arial, Helvetica, sans-serif';
export const FONT_GRAPH_KEY_SMALL = '11px Arial, Helvetica, sans-serif';

export const GRAPH_KEY_SIZE = 12;
export const GRAPH_KEY_OFFSET_X = 5;
export const GRAPH_KEY_OFFSET_Y = 34;
export const GRAPH_BALANCE_NUM_TICKS = 5;
export const GRAPH_SPEND_NUM_ITEMS = 24;

export const GRAPH_FUNDS_TENSION = 0.65;
export const GRAPH_FUNDS_MODES = ['ROI', 'Value', 'Price'];
export const GRAPH_FUNDS_POINT_RADIUS = 3;

export const STOCK_INDICES = (process.env.STOCK_INDICES || '')
    .split(',')
    .reduce((obj, item) => {
        const match = item.match(/^([\w.:]+)\/([\w\s.]+)$/);
        if (match) {
            obj[match[1]] = match[2];
        }

        return obj;
    }, {});

export const DO_STOCKS_LIST = process.env.DO_STOCKS_LIST === 'true';
export const STOCKS_GRAPH_RESOLUTION = 50;

export const LIST_BLOCK_WIDTH = 500;
export const LIST_BLOCK_HEIGHT = 300;

// colours for overview score scale and page categories
export const COLOR_CATEGORY = {
    funds: [84, 110, 122],
    bills: [183, 28, 28],
    food: [67, 160, 71],
    general: [1, 87, 155],
    holiday: [0, 137, 123],
    social: [191, 158, 36],
    income: [36, 191, 55],
    spending: [191, 36, 36],
    balance: [36, 191, 55]
};

// fund colour scale
export const COLOR_FUND_DOWN = [255, 44, 44];
export const COLOR_FUND_UP = [0, 230, 18];

// all other colour definitions
export const COLOR_GRAPH_TITLE = [0, 0, 0];
export const COLOR_DARK = [51, 51, 51];
export const COLOR_LIGHT = [238, 238, 238];
export const COLOR_LIGHT_GREY = [153, 153, 153];
export const COLOR_TRANSLUCENT_LIGHT = [255, 255, 255, 0.5];
export const COLOR_TRANSLUCENT_DARK = [255, 255, 255, 0.8];

export const COLOR_PROFIT = [0, 204, 51];
export const COLOR_LOSS = [204, 51, 0];
export const COLOR_PROFIT_LIGHT = [244, 255, 244];
export const COLOR_LOSS_LIGHT = [255, 244, 244];

export const COLOR_BALANCE_ACTUAL = [0, 51, 153];
export const COLOR_BALANCE_PREDICTED = [255, 0, 0];
export const COLOR_BALANCE_STOCKS = [200, 200, 200, 0.5];

export const COLOR_GRAPH_FUND_ITEM = [66, 134, 244];
export const COLOR_GRAPH_FUND_LINE = COLOR_GRAPH_TITLE;

<commit_msg>Shift key on cashflow graph<commit_after>/**
 * Main config parameters for budget web app
 */

// show error messages for at least <delay> milliseconds
export const ERROR_MESSAGE_DELAY = 5000;

// investment rate of return (assumed, per annum)
export const FUTURE_INVESTMENT_RATE = 0.1;

// currency symbol
export const SYMBOL_CURRENCY_HTML = '\u00a3';
export const SYMBOL_CURRENCY_RAW = '£';

// update changes regularly with the server
export const TIMER_UPDATE_SERVER = 1000;

// error messages
export const ERROR_MSG_SERVER_UPDATE = 'Error updating server!';
export const ERROR_MSG_BAD_DATA = 'Please enter valid data';
export const ERROR_MSG_BUG_INVALID_ITEM = 'Bug: no date/cost on edited item';

// font definitions
export const FONT_AXIS_LABEL = '11px Arial, Helvetica, sans-serif';
export const FONT_GRAPH_TITLE = '16px bold Arial, Helvetica, sans-serif';
export const FONT_GRAPH_TITLE_LARGE = '18px bold Arial, Helvetica, sans-serif';
export const FONT_GRAPH_KEY = '13px Arial, Helvetica, sans-serif';
export const FONT_GRAPH_KEY_SMALL = '11px Arial, Helvetica, sans-serif';

export const GRAPH_KEY_SIZE = 12;
export const GRAPH_KEY_OFFSET_X = 45;
export const GRAPH_KEY_OFFSET_Y = 34;
export const GRAPH_BALANCE_NUM_TICKS = 5;
export const GRAPH_SPEND_NUM_ITEMS = 24;

export const GRAPH_FUNDS_TENSION = 0.65;
export const GRAPH_FUNDS_MODES = ['ROI', 'Value', 'Price'];
export const GRAPH_FUNDS_POINT_RADIUS = 3;

export const STOCK_INDICES = (process.env.STOCK_INDICES || '')
    .split(',')
    .reduce((obj, item) => {
        const match = item.match(/^([\w.:]+)\/([\w\s.]+)$/);
        if (match) {
            obj[match[1]] = match[2];
        }

        return obj;
    }, {});

export const DO_STOCKS_LIST = process.env.DO_STOCKS_LIST === 'true';
export const STOCKS_GRAPH_RESOLUTION = 50;

export const LIST_BLOCK_WIDTH = 500;
export const LIST_BLOCK_HEIGHT = 300;

// colours for overview score scale and page categories
export const COLOR_CATEGORY = {
    funds: [84, 110, 122],
    bills: [183, 28, 28],
    food: [67, 160, 71],
    general: [1, 87, 155],
    holiday: [0, 137, 123],
    social: [191, 158, 36],
    income: [36, 191, 55],
    spending: [191, 36, 36],
    balance: [36, 191, 55]
};

// fund colour scale
export const COLOR_FUND_DOWN = [255, 44, 44];
export const COLOR_FUND_UP = [0, 230, 18];

// all other colour definitions
export const COLOR_GRAPH_TITLE = [0, 0, 0];
export const COLOR_DARK = [51, 51, 51];
export const COLOR_LIGHT = [238, 238, 238];
export const COLOR_LIGHT_GREY = [153, 153, 153];
export const COLOR_TRANSLUCENT_LIGHT = [255, 255, 255, 0.5];
export const COLOR_TRANSLUCENT_DARK = [255, 255, 255, 0.8];

export const COLOR_PROFIT = [0, 204, 51];
export const COLOR_LOSS = [204, 51, 0];
export const COLOR_PROFIT_LIGHT = [244, 255, 244];
export const COLOR_LOSS_LIGHT = [255, 244, 244];

export const COLOR_BALANCE_ACTUAL = [0, 51, 153];
export const COLOR_BALANCE_PREDICTED = [255, 0, 0];
export const COLOR_BALANCE_STOCKS = [200, 200, 200, 0.5];

export const COLOR_GRAPH_FUND_ITEM = [66, 134, 244];
export const COLOR_GRAPH_FUND_LINE = COLOR_GRAPH_TITLE;

<|endoftext|>


<commit_before>// TODO: allow fetching different search partner. Likely
// make the prefetch below generalized and switch based
// on env var.

// This is a second entry point to speed up our query
// to fetch search results.
// We've patched react-scripts to add this as another entry
// point. E.g., the Webpack config by running lives at
// web/node_modules/react-scripts/config/webpack.config.js.
// After modifying files in react-scripts, commit the
// patches with:
// `yarn patch-package react-scripts`
// You can view the patch diff in ./web/patches.
// For this to be meaningful, we have to make sure we inject
// this script first, before all other app code.

import { SEARCH_PROVIDER_BING, SEARCH_PROVIDER_CODEFUEL } from 'js/constants'
import { getSearchProvider } from 'js/utils/search-utils'

// Return an empty script when building the newtab app.
// The newtab app will still build this entry point because
// we share Webpack configs.
if (
  process.env.REACT_APP_WHICH_APP === 'search' &&
  process.env.NODE_ENV === 'production'
) {
  // Override the default search provider on the CodeFuel
  // testing page.
  // TODO: once CodeFuel is the default, revert to:
  // const searchProvider = getSearchProvider()
  let searchProvider
  if (
    ['/search/codefuel/', '/search/codefuel'].indexOf(
      window.location.pathname
    ) > -1
  ) {
    searchProvider = SEARCH_PROVIDER_CODEFUEL
  } else {
    searchProvider = getSearchProvider()
  }

  const getSearchResults = () => {
    // If the path is /query, call fetchBingSearchResults.
    // Let it handle the logic of determining the search query, etc
    if (
      ['/search', '/search/', '/search/codefuel/', '/search/codefuel'].indexOf(
        window.location.pathname
      ) > -1
    ) {
      if (searchProvider === SEARCH_PROVIDER_BING) {
        const {
          prefetchSearchResults: prefetchSearchResultsBing,
        } = require('js/components/Search/fetchBingSearchResults')
        prefetchSearchResultsBing()
      } else if (searchProvider === SEARCH_PROVIDER_CODEFUEL) {
        const {
          prefetchSearchResults: prefetchSearchResultsCodeFuel,
        } = require('js/components/Search/fetchCodefuelSearchResults')
        prefetchSearchResultsCodeFuel()
      }
    }
  }

  try {
    getSearchResults()
  } catch (e) {
    // This script is an optimization, so it's non-critical if
    // it fails.
    console.error(e)
  }
}
<commit_msg>Remove CodeFuel test page workaround for prefetching<commit_after>// TODO: allow fetching different search partner. Likely
// make the prefetch below generalized and switch based
// on env var.

// This is a second entry point to speed up our query
// to fetch search results.
// We've patched react-scripts to add this as another entry
// point. E.g., the Webpack config by running lives at
// web/node_modules/react-scripts/config/webpack.config.js.
// After modifying files in react-scripts, commit the
// patches with:
// `yarn patch-package react-scripts`
// You can view the patch diff in ./web/patches.
// For this to be meaningful, we have to make sure we inject
// this script first, before all other app code.

import { SEARCH_PROVIDER_BING, SEARCH_PROVIDER_CODEFUEL } from 'js/constants'
import { getSearchProvider } from 'js/utils/search-utils'

// Return an empty script when building the newtab app.
// The newtab app will still build this entry point because
// we share Webpack configs.
if (
  process.env.REACT_APP_WHICH_APP === 'search' &&
  process.env.NODE_ENV === 'production'
) {
  const searchProvider = getSearchProvider()
  const getSearchResults = () => {
    // If the path is /query, call fetchBingSearchResults.
    // Let it handle the logic of determining the search query, etc
    if (
      ['/search', '/search/', '/search/codefuel/', '/search/codefuel'].indexOf(
        window.location.pathname
      ) > -1
    ) {
      if (searchProvider === SEARCH_PROVIDER_BING) {
        const {
          prefetchSearchResults: prefetchSearchResultsBing,
        } = require('js/components/Search/fetchBingSearchResults')
        prefetchSearchResultsBing()
      } else if (searchProvider === SEARCH_PROVIDER_CODEFUEL) {
        const {
          prefetchSearchResults: prefetchSearchResultsCodeFuel,
        } = require('js/components/Search/fetchCodefuelSearchResults')
        prefetchSearchResultsCodeFuel()
      }
    }
  }

  try {
    getSearchResults()
  } catch (e) {
    // This script is an optimization, so it's non-critical if
    // it fails.
    console.error(e)
  }
}
<|endoftext|>


<commit_before>/* =========================================================
 * this modalbox implementation is derived from twitter bootstrap,
 * licensed un the Apache License, Version 2.0
 * http://twitter.github.com/bootstrap/javascript.html#modals
 * Copyright 2012 Twitter, Inc.
 * ========================================================= */

(function ($) {

  var Modal = function(options) {
    this.options = options;

    // Adapt style if width is set as an option
    if (this.options.width) {
      $('.modal').width(this.options.width)
        .css('margin-left', Math.round(this.options.width / -2));
    } else {
      $('.modal').removeAttr('style');
    }

    $('.modal-backdrop').toggle(!!this.options.backdrop);

    this.$element = $('#modalbox')
      .on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this));

    this.$element.find('.modal-header h3').text(this.options.title || '');

    if (this.options.remote) {
      this.$element.find('.modal-body')
        .append('
')
        .load(this.options.remote, function() {
          // set focus on input autofocus if it exists
          $(this).find('input[autofocus]').focus();
        });
    } // if no remote option, we display the box as is
  };

  Modal.prototype = {

    constructor: Modal,

    toggle: function() {
      return this[!this.isShown ? 'show' : 'hide']();
    },

    show: function() {
      this.isShown = true;
      this.escape();
      if (!!this.options.backdrop && this.options.backdrop != 'static') {
        $('.modal-backdrop').on('click.dismiss.modal', $.proxy(this.hide, this));
      }
      this.$element.addClass('in');
    },

    hide: function() {
      this.isShown = false;
      this.escape();
      $('.modal-backdrop').off('click.dismiss.modal');
      this.$element.removeClass('in');
    },

    // set escape key
    escape: function () {
      var that = this;
      if (this.isShown && this.options.keyboard) {
        $(document).on('keyup.dismiss.modal', function(e) {
          if (e.which == 27) that.hide();
        });
      } else if (!this.isShown) {
        $(document).off('keyup.dismiss.modal');
      }
    }
  };

  $.modalbox =  {
    show: function(options) {
      var data;
      var defaults = {
        backdrop: 'static',
        keyboard: true
      };

      options = $.extend({}, defaults, typeof options == 'object' && options);

      $('#modalbox').data('modal', (data = new Modal(options)));
      data.show();
    },

    hide: function() {
      var data = $('#modalbox').data('modal');
      if (data) data.hide();
    }
  };

  // build DOM once
  $('body')
    .append($('
')
      .append($('
')
        .append('
<button type="button" class="close" data-dismiss="modal">×</button>

',
                '
',
                '
')))
    .append('
');

})(window.jQuery);
<commit_msg>hide flash when opening modalbox<commit_after>/* =========================================================
 * this modalbox implementation is derived from twitter bootstrap,
 * licensed un the Apache License, Version 2.0
 * http://twitter.github.com/bootstrap/javascript.html#modals
 * Copyright 2012 Twitter, Inc.
 * ========================================================= */

(function ($) {

  var Modal = function(options) {
    this.options = options;

    // Adapt style if width is set as an option
    if (this.options.width) {
      $('.modal').width(this.options.width)
        .css('margin-left', Math.round(this.options.width / -2));
    } else {
      $('.modal').removeAttr('style');
    }

    $('.modal-backdrop').toggle(!!this.options.backdrop);

    this.$element = $('#modalbox')
      .on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this));

    this.$element.find('.modal-header h3').text(this.options.title || '');

    if (this.options.remote) {
      this.$element.find('.modal-body')
        .append('
')
        .load(this.options.remote, function() {
          // set focus on input autofocus if it exists
          $(this).find('input[autofocus]').focus();
        });
    } // if no remote option, we display the box as is
  };

  Modal.prototype = {

    constructor: Modal,

    toggle: function() {
      return this[!this.isShown ? 'show' : 'hide']();
    },

    show: function() {
      // toggle flash advertisment
      $('#pub object').css('visibility', 'hidden');
      this.isShown = true;
      this.escape();
      if (!!this.options.backdrop && this.options.backdrop != 'static') {
        $('.modal-backdrop').on('click.dismiss.modal', $.proxy(this.hide, this));
      }
      this.$element.addClass('in');
    },

    hide: function() {
      // toggle flash advertisment
      $('#pub object').css('visibility', 'visible');
      this.isShown = false;
      this.escape();
      $('.modal-backdrop').off('click.dismiss.modal');
      this.$element.removeClass('in');
    },

    // set escape key
    escape: function () {
      var that = this;
      if (this.isShown && this.options.keyboard) {
        $(document).on('keyup.dismiss.modal', function(e) {
          if (e.which == 27) that.hide();
        });
      } else if (!this.isShown) {
        $(document).off('keyup.dismiss.modal');
      }
    }
  };

  $.modalbox =  {
    show: function(options) {
      var data;
      var defaults = {
        backdrop: 'static',
        keyboard: true
      };

      options = $.extend({}, defaults, typeof options == 'object' && options);

      $('#modalbox').data('modal', (data = new Modal(options)));
      data.show();
    },

    hide: function() {
      var data = $('#modalbox').data('modal');
      if (data) data.hide();
    }
  };

  // build DOM once
  $('body')
    .append($('
')
      .append($('
')
        .append('
<button type="button" class="close" data-dismiss="modal">×</button>

',
                '
',
                '
')))
    .append('
');

})(window.jQuery);
<|endoftext|>


<commit_before>import config from '../config';
import * as util from '../util';

const loadCallbacks = [];
let readingQueue = [];
let speechKit;

let autoPlayEnabled = true;

init();

export function readAllNews() {
    const newsNodes = document.querySelectorAll('[data-news-description="document"]');

    for (let node of newsNodes) {
        const headerNode = node.querySelector('[data-news-description="header"]');
        const textNode = node.querySelector('[data-news-description="text"]');
        const sourceTitleNode = node.querySelector('[data-news-description="source-title"]');

        const headerText = headerNode ? headerNode.innerHTML : '';
        const sourceTitleText = sourceTitleNode ? sourceTitleNode.innerHTML : '';

        const textToRead = util.removeMarkup([
            headerText,
            textNode ? (textNode.innerHTML.includes(headerText) ? '' : textNode.innerHTML) : '',
            headerText.includes(sourceTitleText) ? '' : sourceTitleText,
        ].join('.'))
            .replace(/\s{2,}/, ' ')
            .replace(/\.{2,}/, '.')
            .replace(/\.([\wа-яё])/ig, '. $1');

        readingQueue.push({
            exec: () => readText(textToRead),
            node
        });
    }

    return readAllFromQueue();
}

export function readText(text) {
    const lang = /[а-яё]/i.test(text) ? 'ru-RU' : 'en-US';

    if (!autoPlayEnabled) {
        return readTextByBrowserSynthesis(text, lang);
    }

    return readTextBySpeechKit(text, lang);
}

function readTextByBrowserSynthesis(text, lang) {
    const synthesis = window.speechSynthesis;
    lang = lang.replace(/-/g, '_');

    const utter = new SpeechSynthesisUtterance(text);
    utter.lang = lang;
    utter.rate = lang === 'ru_RU' ? 1 : 0.8;

    return new Promise((resolve, reject) => {
        function onEnd() {
            clear();
            resolve();
        }

        function onError(err) {
            clear();
            reject(err);
        }

        function clear() {
            utter.removeEventListener('end', onEnd);
            utter.removeEventListener('error', onError);
        }

        utter.addEventListener('end', onEnd);
        utter.addEventListener('error', onError);

        synthesis.speak(utter);
    });
}

function readTextBySpeechKit(text, lang) {
    return getSpeechKit().then(speechKit => {
        const tts = speechKit.Tts({
            ...config.speechParams,
            speed: lang === 'ru-RU' ? 1 : 0.8,
            lang,
        });

        return new Promise(resolve => {
            tts.speak(text, { stopCallback: resolve });
        });
    });
}

export function stopReading() {
    readingQueue = [];
}

function init() {
    checkAutoPlay();

    const apiScript = document.createElement('script');

    apiScript.src = 'https://webasr.yandex.net/jsapi/v1/webspeechkit.js';
    apiScript.async = true;
    apiScript.onload = () => {
        apiScript.onload = null;
        onScriptLoad();
    };

    document.body.appendChild(apiScript);
}

function checkAutoPlay() {
    if (typeof Audio === 'undefined') {
        return;
    }

    try {
        const audio = new Audio();
        audio.play()
            .catch(err => {
                if (err.name === 'NotAllowedError') {
                    autoPlayEnabled = false;
                }
            });
    } catch (e) {
        console.warn(e);
    }
}

function onScriptLoad() {
    const _speechKit = window.ya && window.ya.speechkit;

    if (!_speechKit || !_speechKit.settings) {
        return setTimeout(onScriptLoad, 50);
    }

    _speechKit.settings.apikey = config.speechKitKey;
    speechKit = _speechKit;

    while (loadCallbacks.length) {
        const cb = loadCallbacks.shift();
        try {
            cb(_speechKit);
        } catch (e) {
            console.error(e);
        }
    }
}

async function readAllFromQueue() {
    while (readingQueue.length) {
        const item = readingQueue.shift();

        if (!item) {
            break;
        }

        item.node.classList.add('speech-reading');
        await item.exec()
            .then(() => {
                item.node.classList.remove('speech-reading');
            });
    }
}

function getSpeechKit() {
    return new Promise(resolve => {
        if (speechKit) {
            resolve(speechKit);
        } else {
            loadCallbacks.push(resolve);
        }
    });
}
<commit_msg>Fix native audio<commit_after>import config from '../config';
import * as util from '../util';

const synthesis = window.speechSynthesis;

const loadCallbacks = [];
let readingQueue = [];
let speechKit;

let autoPlayEnabled = true;

init();

export function readAllNews() {
    const newsNodes = document.querySelectorAll('[data-news-description="document"]');

    for (let node of newsNodes) {
        const headerNode = node.querySelector('[data-news-description="header"]');
        const textNode = node.querySelector('[data-news-description="text"]');
        const sourceTitleNode = node.querySelector('[data-news-description="source-title"]');

        const headerText = headerNode ? headerNode.innerHTML : '';
        const sourceTitleText = sourceTitleNode ? sourceTitleNode.innerHTML : '';

        const textToRead = util.removeMarkup([
            headerText,
            textNode ? (textNode.innerHTML.includes(headerText) ? '' : textNode.innerHTML) : '',
            headerText.includes(sourceTitleText) ? '' : sourceTitleText,
        ].join('.'))
            .replace(/\s{2,}/, ' ')
            .replace(/\.{2,}/, '.')
            .replace(/\.([\wа-яё])/ig, '. $1');

        readingQueue.push({
            exec: () => readText(textToRead),
            node
        });
    }

    return readAllFromQueue();
}

export function readText(text) {
    const lang = /[а-яё]/i.test(text) ? 'ru-RU' : 'en-US';

    if (!autoPlayEnabled && synthesis) {
        return readTextByBrowserSynthesis(text, lang);
    }

    return readTextBySpeechKit(text, lang);
}

function readTextByBrowserSynthesis(text, lang) {
    const utter = new SpeechSynthesisUtterance(text);
    utter.lang = lang;
    utter.rate = lang.startsWith('ru') ? 1 : 0.8;

    return new Promise(resolve => {
        const endTimeout = setTimeout(onEnd, 30000);

        function onEnd() {
            if (synthesis.speaking) {
                synthesis.cancel();
            }
            clear();
            setTimeout(resolve, 2500);
        }

        function clear() {
            clearTimeout(endTimeout);

            utter.removeEventListener('end', onEnd);
            utter.removeEventListener('error', onEnd);
        }

        utter.addEventListener('end', onEnd);
        utter.addEventListener('error', onEnd);

        synthesis.speak(utter);
    });
}

function readTextBySpeechKit(text, lang) {
    return getSpeechKit().then(speechKit => {
        const tts = speechKit.Tts({
            ...config.speechParams,
            speed: lang.startsWith('ru') ? 1 : 0.8,
            lang,
        });

        return new Promise(resolve => {
            tts.speak(text, { stopCallback: resolve });
        });
    });
}

export function stopReading() {
    readingQueue = [];
}

function init() {
    checkAutoPlay();

    const apiScript = document.createElement('script');

    apiScript.src = 'https://webasr.yandex.net/jsapi/v1/webspeechkit.js';
    apiScript.async = true;
    apiScript.onload = () => {
        apiScript.onload = null;
        onScriptLoad();
    };

    document.body.appendChild(apiScript);
}

function checkAutoPlay() {
    try {
        const audio = new Audio();
        audio.play()
            .catch(err => {
                if (err.name === 'NotAllowedError') {
                    autoPlayEnabled = false;
                }
            });
    } catch (e) {
        console.warn(e);
    }
}

function onScriptLoad() {
    const _speechKit = window.ya && window.ya.speechkit;

    if (!_speechKit || !_speechKit.settings) {
        return setTimeout(onScriptLoad, 50);
    }

    _speechKit.settings.apikey = config.speechKitKey;
    speechKit = _speechKit;

    while (loadCallbacks.length) {
        const cb = loadCallbacks.shift();
        try {
            cb(_speechKit);
        } catch (e) {
            console.error(e);
        }
    }
}

async function readAllFromQueue() {
    while (readingQueue.length) {
        const item = readingQueue.shift();

        if (!item) {
            break;
        }

        item.node.classList.add('speech-reading');
        await item.exec()
            .then(() => {
                item.node.classList.remove('speech-reading');
            });
    }
}

function getSpeechKit() {
    return new Promise(resolve => {
        if (speechKit) {
            resolve(speechKit);
        } else {
            loadCallbacks.push(resolve);
        }
    });
}
<|endoftext|>


<commit_before>const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: [
    'babel-polyfill',
    './views/index.js'
  ],
  output: {
    path: `${__dirname}/public`,
    publicPath: '/',
    filename: 'app.js'
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"production"'
    }),
    new webpack.NoErrorsPlugin(),
    new HtmlWebpackPlugin({
      template: 'templates/index.ejs',
      hash: true
    })
  ],
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['latest', 'react']
        }
      }, {
        test: /\.css$/,
        loaders: ['style', 'css?modules&importLoaders=1', 'postcss']
      }, {
        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        loaders: ['url?limit=10000']
      }, {
        test: /\.(eot|ttf|wav|mp3)(\?v=\d+\.\d+\.\d+)?$/,
        loaders: ['file']
      }
    ]
  },
  resolve: {
    extensions: ['', '.js', '.css']
  },
  postcss: [
    require('postcss-cssnext')
  ]
}
<commit_msg>Fix exclude path<commit_after>const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: [
    'babel-polyfill',
    './views/index.js'
  ],
  output: {
    path: `${__dirname}/public`,
    publicPath: '/',
    filename: 'app.js'
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"production"'
    }),
    new webpack.NoErrorsPlugin(),
    new HtmlWebpackPlugin({
      template: 'templates/index.ejs',
      hash: true
    })
  ],
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules\/(?!react-icons)/,
        loader: 'babel',
        query: {
          presets: ['latest', 'react']
        }
      }, {
        test: /\.css$/,
        loaders: ['style', 'css?modules&importLoaders=1', 'postcss']
      }, {
        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        loaders: ['url?limit=10000']
      }, {
        test: /\.(eot|ttf|wav|mp3)(\?v=\d+\.\d+\.\d+)?$/,
        loaders: ['file']
      }
    ]
  },
  resolve: {
    extensions: ['', '.js', '.css']
  },
  postcss: [
    require('postcss-cssnext')
  ]
}
<|endoftext|>


<commit_before>"use strict";

var path = require("path");
var webpack = require("webpack");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require("html-webpack-plugin");
var poststylus = require("poststylus");
var autoprefixer = require("autoprefixer");
var srcPath = path.join(__dirname, "src");

module.exports = {
  resolve: {
    alias: {
      "react": "react-lite",
      "react-dom": "react-lite"
    },
    root: srcPath,
    extensions: ["", ".js", ".jsx", ".styl"],
    modulesDirectories: ["node_modules", "src"]
  },
  entry: {
    "commons": [
      "jquery",
      "moment",
      "react-lite",
      "react-redux",
      "react-router",
      "react-router-redux",
      "redux",
      "redux-thunk"
    ],
    "index": path.join(srcPath, "index.js")
  },
  output: {
    path: path.join(__dirname, "dist"),
    publicPath: "",
    filename: "[name]-[hash].js",
  },
  module: {
    loaders: [{
      test: /\.jsx?$/,
      include: srcPath,
      loader: "babel"
    }, {
      test: /\.css$/,
      include: path.join(srcPath, "assets/css"),
      loader: ExtractTextPlugin.extract(
        "style",
        "css!postcss"
      )
    }, {
      test: /\.styl$/,
      include: path.join(srcPath, "assets/styles"),
      loader: ExtractTextPlugin.extract(
        "style",
        "css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!stylus"
      )
    }, {
      test: /\.json$/,
      include: path.join(srcPath, "assets"),
      loader: "json"
    }, {
      test: /.*\.(gif|png|jpe?g|svg)$/i,
      include: path.join(srcPath, "assets/images"),
      loaders: [
        "file?hash=sha512&digest=hex&name=[hash].[ext]",
        "image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: \"65-90\", speed: 2, verbose: true}}"
      ]
    }]
  },
  // misc plugins
  stylus: {
    use: [
      poststylus([
        "autoprefixer"
      ])
    ]
  },
  postcss: [autoprefixer],
  // webpack plugins
  plugins: [
    new ExtractTextPlugin(
      "[name]-[hash].css",
      { allChunks: true }
    ),
    new HtmlWebpackPlugin({
      favicon: path.join(srcPath, "assets/images/favicon.png"),
      hash: true,
      template: path.join(srcPath, "assets/index.html")
    }),
    new webpack.DefinePlugin({
      "process.env.NODE_ENV": JSON.stringify("production"),
      "__DEV__": false
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), // saves ~100k from build
    new webpack.NoErrorsPlugin(),
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: "commons",
      filename: "commons.js"
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: { warnings: false }
    })
  ]
}
<commit_msg>Put js files in js/ dir, but keep html at root.<commit_after>"use strict";

var path = require("path");
var webpack = require("webpack");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require("html-webpack-plugin");
var poststylus = require("poststylus");
var autoprefixer = require("autoprefixer");
var srcPath = path.join(__dirname, "src");

module.exports = {
  resolve: {
    alias: {
      "react": "react-lite",
      "react-dom": "react-lite"
    },
    root: srcPath,
    extensions: ["", ".js", ".jsx", ".styl"],
    modulesDirectories: ["node_modules", "src"]
  },
  entry: {
    "commons": [
      "jquery",
      "moment",
      "react-lite",
      "react-redux",
      "react-router",
      "react-router-redux",
      "redux",
      "redux-thunk"
    ],
    "index": path.join(srcPath, "index.js")
  },
  output: {
    path: path.join(__dirname, "dist"),
    publicPath: "",
    filename: "js/[name]-[hash].js",
  },
  module: {
    loaders: [{
      test: /\.jsx?$/,
      include: srcPath,
      loader: "babel"
    }, {
      test: /\.css$/,
      include: path.join(srcPath, "assets/css"),
      loader: ExtractTextPlugin.extract(
        "style",
        "css!postcss"
      )
    }, {
      test: /\.styl$/,
      include: path.join(srcPath, "assets/styles"),
      loader: ExtractTextPlugin.extract(
        "style",
        "css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!stylus"
      )
    }, {
      test: /\.json$/,
      include: path.join(srcPath, "assets"),
      loader: "json"
    }, {
      test: /.*\.(gif|png|jpe?g|svg)$/i,
      include: path.join(srcPath, "assets/images"),
      loaders: [
        "file?hash=sha512&digest=hex&name=[hash].[ext]",
        "image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: \"65-90\", speed: 2, verbose: true}}"
      ]
    }]
  },
  // misc plugins
  stylus: {
    use: [
      poststylus([
        "autoprefixer"
      ])
    ]
  },
  postcss: [autoprefixer],
  // webpack plugins
  plugins: [
    new ExtractTextPlugin(
      "[name]-[hash].css",
      { allChunks: true }
    ),
    new HtmlWebpackPlugin({
      favicon: path.join(srcPath, "assets/images/favicon.png"),
      hash: true,
      template: path.join(srcPath, "assets/index.html")
    }),
    new webpack.DefinePlugin({
      "process.env.NODE_ENV": JSON.stringify("production"),
      "__DEV__": false
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), // saves ~100k from build
    new webpack.NoErrorsPlugin(),
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: "commons",
      filename: "commons.js"
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: { warnings: false }
    })
  ]
}
<|endoftext|>


<commit_before>var baseConfig = require('./webpack.config.common.js');
var webpack = require('webpack');
const merge = require('webpack-merge');
var path = require('path');

var CopyWebpackPlugin = require('copy-webpack-plugin');
var OfflinePlugin = require('offline-plugin');

module.exports = merge(baseConfig, {
  output: {
    path: path.resolve(__dirname, './dist/static/'),
    filename: 'js/[name]-bundle.[chunkhash].js'
  },
  plugins: [
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        screw_ie8: true,
        warnings: false,
      },
      // mangle brakes angular.
      mangle: false,
      output: {
        screw_ie8: true
      },
      exclude: [/\.min\.js$/gi]
    }),
    // it's always better if OfflinePlugin is the last plugin added
    new OfflinePlugin(),
  ],
});
<commit_msg>Copy service worker to root path.<commit_after>var baseConfig = require('./webpack.config.common.js');
var webpack = require('webpack');
const merge = require('webpack-merge');
var path = require('path');

var OfflinePlugin = require('offline-plugin');

module.exports = merge(baseConfig, {
  output: {
    path: path.resolve(__dirname, './dist/static/'),
    filename: 'js/[name]-bundle.[chunkhash].js'
  },
  plugins: [
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        screw_ie8: true,
        warnings: false,
      },
      // mangle brakes angular.
      mangle: false,
      output: {
        screw_ie8: true
      },
      exclude: [/\.min\.js$/gi]
    }),
    // it's always better if OfflinePlugin is the last plugin added
    new OfflinePlugin({
      ServiceWorker: {
        output: '../sw.js',
      },
    }),
  ],
});
<|endoftext|>