<commit_before>const ProductionLine = require('productionline')

class NGNBuilder extends ProductionLine {
  constructor () {
    super()

    // Override standard source
    this.source = path.resolve('./src/common')

    // Create a header with attribution.
    this.header = `v${this.version} generated on: ${(new Date())}\n` +
      `Copyright (c) 2014-${(new Date()).getFullYear()}` +
      `, ${this.author} and contributors. All Rights Reserved. License: ${this.package.license}.`

    // Tokenizers
    this.tokenizer = /\/\/\s{0,30}\[INCLUDE\:\s{0,30}(.*)\]/i
    this.exclusion = /\/\/\s{0,30}\[PARTIAL\](.*)/im

    // Hold partial files
    this.PARTIALS = {}
  }

  testBuild () {
    this.output = path.resolve('./test/lib')

    this.clean()

    this.tasks.add(`Generate test files in ${this.output}`, next => {
      this.walk(this.source).forEach((filepath, i) => {
        let content = this.readFileSync(filepath)

        // If the file is a partial, exclude it
        if (exclusion.test(content)) {
          this.PARTIALS[filepath] = content
          this.highlight(`Excluded ${filepath} (partial)`)
        } else {
          this.writeFileSync(this.output(filepath), this.includePartials(filepath, content))
          this.info(`  ${i + 1} ==> ${this.relativePath(filepath)}`)
        }

        next()
      })
    })
  }

  includePartials (file, content) {
    let tokens = this.tokenizer.exec(content)

    // Replace all tokens
    while (tokens) {
      let filepath = path.join(path.dirname(file), tokens[1])

      if (!this.PARTIALS.hasOwnProperty(filepath)) {
        this.PARTIALS[filepath] = this.readFileSync(filepath)
      }

      content = content.replace(tokens[0], this.PARTIALS[filepath])
      tokens = tokenizer.exec(content)
    }

    return content
  }
}

// Use the custom builder
let pipeline = new NGNBuilder()

// Command Line Interface
switch (process.argv[2]) {
  case '--test':
    pipeline.testBuild()
    break

  default:
    return pipeline.error('No argument specified. Did you mean to run --build?')
}

pipeline.run()
<commit_msg>Added initial build file based on productionline.<commit_after>const path = require('path')
const ProductionLine = require('productionline')

class NGNBuilder extends ProductionLine {
  constructor () {
    super()

    // Override standard source
    this.source = path.resolve('./src/common')

    // Create a header with attribution.
    this.header = `v${this.version} generated on: ${(new Date())}\n` +
      `Copyright (c) 2014-${(new Date()).getFullYear()}` +
      `, ${this.author} and contributors. All Rights Reserved. License: ${this.package.license}.`

    // Tokenizers
    this.tokenizer = /\/\/\s{0,30}\[INCLUDE\:\s{0,30}(.*)\]/i
    this.exclusion = /\/\/\s{0,30}\[PARTIAL\](.*)/im

    // Hold partial files
    this.PARTIALS = {}
  }

  testBuild () {
    this.output = path.resolve('./test/lib')

    this.clean()

    this.tasks.add(`Generate test files in ${this.output}`, next => {
      let excluded = []
      let ui = new this.Table()

      ui.div({
        text: this.COLORS.subtle('Generated Files:'),
        padding: [1, 0, 0, 5]
      })

      console.log(ui.toString())

      this.walk(this.source).forEach(filepath => {
        let content = this.readFileSync(filepath)

        // If the file is a partial, exclude it
        if (this.exclusion.test(content)) {
          this.PARTIALS[filepath] = content
          excluded.push(this.relativePath(filepath))
        } else {
          this.writeFileSync(this.outputDirectory(filepath), this.includePartials(filepath, content))
          this.success(`     ${this.relativePath(filepath)}`)
        }
      })

      ui = new this.Table()

      ui.div({
        text: this.COLORS.subtle('Partials Identified:') + '\n' + this.COLORS.info(excluded.join('\n')),
        padding: [1, 0, 1, 5]
      })

      console.log(ui.toString())

      next()
    })
  }

  includePartials (file, content) {
    let tokens = this.tokenizer.exec(content)

    // Replace all tokens
    while (tokens) {
      let filepath = path.join(path.dirname(file), tokens[1])

      if (!this.PARTIALS.hasOwnProperty(filepath)) {
        this.PARTIALS[filepath] = this.readFileSync(filepath)
      }

      content = content.replace(tokens[0], this.PARTIALS[filepath])
      tokens = this.tokenizer.exec(content)
    }

    return content
  }
}

// Use the custom builder
let pipeline = new NGNBuilder()

// Command Line Interface
switch (process.argv[2]) {
  case '--test':
    pipeline.testBuild()
    break

  default:
    return pipeline.error('No argument specified. Did you mean to run --build?')
}

pipeline.run()
<|endoftext|>


<commit_before>/*
 * jquery.simulate - simulate browser mouse and keyboard events
 *
 * Copyright (c) 2007 Eduardo Lundgren (eduardolundgren@gmail.com)
 * and Richard D. Worth (rdworth@gmail.com)
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 */

;(function($) {

$.fn.extend({
	simulate: function(type, options) {
		return this.each(function() {
			var opt = $.extend({}, $.simulate.defaults, options || {});
			new $.simulate(this, type, opt);
		});
	}
});

$.simulate = function(el, type, options) {
	this.target = el;
	this.options = options;

	if (/^drag$/.test(type)) {
		this[type].apply(this, [this.target, options]);
	} else {
		this.simulateEvent(el, type, options);
	}
}

$.extend($.simulate.prototype, {
	simulateEvent: function(el, type, options) {
		// creates a individual option for each simulation inside this instance
		options = $.extend({}, this.options, options);
		var evt = this.createEvent(type, options);
		return this.dispatchEvent(el, type, evt, options);
	},
	createEvent: function(type, options) {
		if (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {
			return this.mouseEvent(type, options);
		} else if (/^key(up|down|press)$/.test(type)) {
			return this.keyboardEvent(type, options);
		}
	},
	mouseEvent: function(type, options) {
		var evt;
		var e = $.extend({
			bubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,
			screenX: 0, screenY: 0, clientX: options.x || 0, clientY: options.y || 0,
			ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
			button: 0, relatedTarget: undefined
		}, options);

		var relatedTarget = $(e.relatedTarget)[0];

		if ($.isFunction(document.createEvent)) {
			evt = document.createEvent("MouseEvents");
			evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
				e.screenX, e.screenY, e.clientX, e.clientY,
				e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
				e.button, e.relatedTarget || document.body.parentNode);
		} else if (document.createEventObject) {
			evt = document.createEventObject();
			$.extend(evt, e);
			evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
		}
		return evt;
	},
	keyboardEvent: function(type, options) {
		var evt;

		var e = $.extend({ bubbles: true, cancelable: true, view: window,
			ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
			keyCode: 0, charCode: 0
		}, options);

		if ($.isFunction(document.createEvent)) {
			try {
				evt = document.createEvent("KeyEvents");
				evt.initKeyEvent(type, e.bubbles, e.cancelable, e.view,
					e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
					e.keyCode, e.charCode);
			} catch(err) {
				evt = document.createEvent("Events");
				evt.initEvent(type, e.bubbles, e.cancelable);
				$.extend(evt, { view: e.view,
					ctrlKey: e.ctrlKey, altKey: e.altKey, shiftKey: e.shiftKey, metaKey: e.metaKey,
					keyCode: e.keyCode, charCode: e.charCode
				});
			}
		} else if (document.createEventObject) {
			evt = document.createEventObject();
			$.extend(evt, e);
		}
		if ($.browser.msie || $.browser.opera) {
			evt.keyCode = (e.charCode > 0) ? e.charCode : e.keyCode;
			evt.charCode = undefined;
		}
		return evt;
	},

	dispatchEvent: function(el, type, evt, options) {
		if (el.dispatchEvent) {
			el.dispatchEvent(evt);
		} else if (el.fireEvent) {
			el.fireEvent('on' + type, evt);
		}
		// trigget complete for all events - not drag.
		this.triggerComplete(evt, options);
		return evt;
	},

	drag: function(el) {
		var self = this, center = this.findCenter(this.target),
			options = this.options,	x = center.x, y = center.y,
			dx = options.dx || 0, dy = options.dy || 0, target = this.target;

		var coord = { x: x, y: y, complete: null }, evt;
		this.simulateEvent(target, "mouseover", coord);
		this.simulateEvent(target, "mousedown", coord);

		var drag = function(x, y) {
			evt = self.simulateEvent(target, "mousemove", $.extend(coord, { x: x, y: y }));
			// triggering drag callback
			(self.options.drag && self.options.drag($.event.fix(evt)));
		};

		if (/^sync$/.test(options.speed)) {
			// trigger synchronous simulation
			this.triggerSync(center, dx, dy, drag);
		}
		else {
			// trigger asynchronous simulation - animated
			this.triggerAsync(center, dx, dy, drag);
		}

		this.simulateEvent(target, "mouseup", coord);
		this.simulateEvent(target, "mouseout", coord);
		this.triggerComplete(evt, options);
	},

	triggerComplete: function(evt, options) {
		evt = $.event.fix(evt);
		(options.complete && options.complete(evt)); return evt;
	},

	triggerSync: function(center, dx, dy, fn) {
		var x = center.x, y = center.y, mdx = Math.abs(dx) || 0, mdy = Math.abs(dy) || 0;
		var range = Math.max(mdx, mdy), sigx = dx/mdx || 1, sigy = dy/mdy || 1;

		for (var dt = 1; dt <= range; dt++) {
			if (dt <= mdx) x = center.x + sigx*dt;
			if (dt <= mdy) y = center.y + sigy*dt;
			(fn && fn(x, y));
		}
	},

	triggerAsync: function(center, dx, dy, fn) {
		/*TODO*/
		// this method just have to call: (fn && fn(x, y));
		// return the x, y of the mousemove.
		// idea: $.animate({ step: function() { var x,y; (fn && fn(x, y)); } });
	},

	findCenter: function(el) {
		var el = $(this.target), o = el.offset();
		return {
			x: o.left + el.outerWidth() / 2,
			y: o.top + el.outerHeight() / 2
		};
	}
});

$.extend($.simulate, {
	defaults: {
		speed: 'sync'
	}
});

})(jQuery);
<commit_msg>removed x, y as they are not browser event options. Use clientX and clientY<commit_after>/*
 * jquery.simulate - simulate browser mouse and keyboard events
 *
 * Copyright (c) 2007 Eduardo Lundgren (eduardolundgren@gmail.com)
 * and Richard D. Worth (rdworth@gmail.com)
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 */

;(function($) {

$.fn.extend({
	simulate: function(type, options) {
		return this.each(function() {
			var opt = $.extend({}, $.simulate.defaults, options || {});
			new $.simulate(this, type, opt);
		});
	}
});

$.simulate = function(el, type, options) {
	this.target = el;
	this.options = options;

	if (/^drag$/.test(type)) {
		this[type].apply(this, [this.target, options]);
	} else {
		this.simulateEvent(el, type, options);
	}
}

$.extend($.simulate.prototype, {
	simulateEvent: function(el, type, options) {
		// creates a individual option for each simulation inside this instance
		options = $.extend({}, this.options, options);
		var evt = this.createEvent(type, options);
		return this.dispatchEvent(el, type, evt, options);
	},
	createEvent: function(type, options) {
		if (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {
			return this.mouseEvent(type, options);
		} else if (/^key(up|down|press)$/.test(type)) {
			return this.keyboardEvent(type, options);
		}
	},
	mouseEvent: function(type, options) {
		var evt;
		var e = $.extend({
			bubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,
			screenX: 0, screenY: 0, clientX: 0, clientY: 0,
			ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
			button: 0, relatedTarget: undefined
		}, options);

		var relatedTarget = $(e.relatedTarget)[0];

		if ($.isFunction(document.createEvent)) {
			evt = document.createEvent("MouseEvents");
			evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
				e.screenX, e.screenY, e.clientX, e.clientY,
				e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
				e.button, e.relatedTarget || document.body.parentNode);
		} else if (document.createEventObject) {
			evt = document.createEventObject();
			$.extend(evt, e);
			evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
		}
		return evt;
	},
	keyboardEvent: function(type, options) {
		var evt;

		var e = $.extend({ bubbles: true, cancelable: true, view: window,
			ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
			keyCode: 0, charCode: 0
		}, options);

		if ($.isFunction(document.createEvent)) {
			try {
				evt = document.createEvent("KeyEvents");
				evt.initKeyEvent(type, e.bubbles, e.cancelable, e.view,
					e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
					e.keyCode, e.charCode);
			} catch(err) {
				evt = document.createEvent("Events");
				evt.initEvent(type, e.bubbles, e.cancelable);
				$.extend(evt, { view: e.view,
					ctrlKey: e.ctrlKey, altKey: e.altKey, shiftKey: e.shiftKey, metaKey: e.metaKey,
					keyCode: e.keyCode, charCode: e.charCode
				});
			}
		} else if (document.createEventObject) {
			evt = document.createEventObject();
			$.extend(evt, e);
		}
		if ($.browser.msie || $.browser.opera) {
			evt.keyCode = (e.charCode > 0) ? e.charCode : e.keyCode;
			evt.charCode = undefined;
		}
		return evt;
	},

	dispatchEvent: function(el, type, evt, options) {
		if (el.dispatchEvent) {
			el.dispatchEvent(evt);
		} else if (el.fireEvent) {
			el.fireEvent('on' + type, evt);
		}
		// trigget complete for all events - not drag.
		this.triggerComplete(evt, options);
		return evt;
	},

	drag: function(el) {
		var self = this, center = this.findCenter(this.target),
			options = this.options,	x = center.x, y = center.y,
			dx = options.dx || 0, dy = options.dy || 0, target = this.target;

		var coord = { clientX: x, clientX: y, complete: null }, evt;
		this.simulateEvent(target, "mouseover", coord);
		this.simulateEvent(target, "mousedown", coord);

		var drag = function(x, y) {
			evt = self.simulateEvent(target, "mousemove", $.extend(coord, { x: x, y: y }));
			// triggering drag callback
			(self.options.drag && self.options.drag($.event.fix(evt)));
		};

		if (/^sync$/.test(options.speed)) {
			// trigger synchronous simulation
			this.triggerSync(center, dx, dy, drag);
		}
		else {
			// trigger asynchronous simulation - animated
			this.triggerAsync(center, dx, dy, drag);
		}

		this.simulateEvent(target, "mouseup", coord);
		this.simulateEvent(target, "mouseout", coord);
		this.triggerComplete(evt, options);
	},

	triggerComplete: function(evt, options) {
		evt = $.event.fix(evt);
		(options.complete && options.complete(evt)); return evt;
	},

	triggerSync: function(center, dx, dy, fn) {
		var x = center.x, y = center.y, mdx = Math.abs(dx) || 0, mdy = Math.abs(dy) || 0;
		var range = Math.max(mdx, mdy), sigx = dx/mdx || 1, sigy = dy/mdy || 1;

		for (var dt = 1; dt <= range; dt++) {
			if (dt <= mdx) x = center.x + sigx*dt;
			if (dt <= mdy) y = center.y + sigy*dt;
			(fn && fn(x, y));
		}
	},

	triggerAsync: function(center, dx, dy, fn) {
		/*TODO*/
		// this method just have to call: (fn && fn(x, y));
		// return the x, y of the mousemove.
		// idea: $.animate({ step: function() { var x,y; (fn && fn(x, y)); } });
	},

	findCenter: function(el) {
		var el = $(this.target), o = el.offset();
		return {
			x: o.left + el.outerWidth() / 2,
			y: o.top + el.outerHeight() / 2
		};
	}
});

$.extend($.simulate, {
	defaults: {
		speed: 'sync'
	}
});

})(jQuery);
<|endoftext|>


<commit_before>
/**
 * This is the common logic for both the Node.js and web browser
 * implementations of `debug()`.
 *
 * Expose `debug()` as the module.
 */

exports = module.exports = debug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = humanize;

/**
 * The currently active debug mode names, and names to skip.
 */

exports.names = [];
exports.skips = [];

/**
 * Map of special "%n" handling functions, for the debug "format" argument.
 *
 * Valid key names are a single, lowercased letter, i.e. "n".
 */

exports.formatters = {};

/**
 * Create a debugger with the given `namespace`.
 *
 * @param {String} namespace
 * @return {Function}
 * @api public
 */

function debug(namespace) {

  // define the `disabled` version
  function disabled() {
  }
  disabled.enabled = false;

  // define the `enabled` version
  function enabled() {
    var args = Array.prototype.slice.call(arguments);
    if ('string' === typeof args[0]) {
      args[0] = exports.coerce(args[0]);
    } else {
      // anything else let's inspect with %o
      args = ['%o'].concat(args);
    }

    // apply any `formatters` transformations
    var index = 0;
    args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
      // replace "%%" with a placeholder value for now.
      // we restore it after doing the formatters parsing.
      if (match === '%%') return '68ddd49c85cb46fc8c';
      index++;
      var formatter = exports.formatters[format];
      if ('function' === typeof formatter) {
        var val = args[index];
        match = formatter.call(enabled, val);

        // now we need to remove `args[index]` since it's inlined in the `format`
        args.splice(index, 1);
        index--;
      }
      return match;
    }).replace(/68ddd49c85cb46fc8c/g, '%%');

    exports.log.apply(enabled, args);
  }
  enabled.enabled = true;

  var fn = exports.enabled(namespace) ? enabled : disabled;

  fn.namespace = namespace;

  return fn;
}

/**
 * Enables a debug mode by namespaces. This can include modes
 * separated by a colon and wildcards.
 *
 * @param {String} namespaces
 * @api public
 */

function enable(namespaces) {
  exports.save(namespaces);

  var split = (namespaces || '').split(/[\s,]+/);
  var len = split.length;

  for (var i = 0; i < len; i++) {
    namespaces = split[i].replace('*', '.*?');
    if (namespaces[0] === '-') {
      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
    } else {
      exports.names.push(new RegExp('^' + namespaces + '$'));
    }
  }
}

/**
 * Disable debug output.
 *
 * @api public
 */

function disable() {
  exports.enable('');
}

/**
 * Humanize the given `ms`.
 *
 * @param {Number} m
 * @return {String}
 * @api private
 */

function humanize(ms) {
  var sec = 1000;
  var min = 60 * 1000;
  var hour = 60 * min;

  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
  if (ms >= min) return (ms / min).toFixed(1) + 'm';
  if (ms >= sec) return (ms / sec | 0) + 's';
  return ms + 'ms';
}

/**
 * Returns true if the given mode name is enabled, false otherwise.
 *
 * @param {String} name
 * @return {Boolean}
 * @api public
 */

function enabled(name) {
  var i, len;
  for (i = 0, len = exports.skips.length; i < len; i++) {
    if (exports.skips[i].test(name)) {
      return false;
    }
  }
  for (i = 0, len = exports.names.length; i < len; i++) {
    if (exports.names[i].test(name)) {
      return true;
    }
  }
  return false;
}

/**
 * Coerce `val`.
 *
 * @param {Mixed} val
 * @return {Mixed}
 * @api private
 */

function coerce(val) {
  if (val instanceof Error) return val.stack || val.message;
  return val;
}
<commit_msg>debug: remove hacky placeholder logic<commit_after>
/**
 * This is the common logic for both the Node.js and web browser
 * implementations of `debug()`.
 *
 * Expose `debug()` as the module.
 */

exports = module.exports = debug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = humanize;

/**
 * The currently active debug mode names, and names to skip.
 */

exports.names = [];
exports.skips = [];

/**
 * Map of special "%n" handling functions, for the debug "format" argument.
 *
 * Valid key names are a single, lowercased letter, i.e. "n".
 */

exports.formatters = {};

/**
 * Create a debugger with the given `namespace`.
 *
 * @param {String} namespace
 * @return {Function}
 * @api public
 */

function debug(namespace) {

  // define the `disabled` version
  function disabled() {
  }
  disabled.enabled = false;

  // define the `enabled` version
  function enabled() {
    var args = Array.prototype.slice.call(arguments);
    if ('string' === typeof args[0]) {
      args[0] = exports.coerce(args[0]);
    } else {
      // anything else let's inspect with %o
      args = ['%o'].concat(args);
    }

    // apply any `formatters` transformations
    var index = 0;
    args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
      // if we encounter an escaped % then don't increase the array index
      if (match === '%%') return match;
      index++;
      var formatter = exports.formatters[format];
      if ('function' === typeof formatter) {
        var val = args[index];
        match = formatter.call(enabled, val);

        // now we need to remove `args[index]` since it's inlined in the `format`
        args.splice(index, 1);
        index--;
      }
      return match;
    });

    exports.log.apply(enabled, args);
  }
  enabled.enabled = true;

  var fn = exports.enabled(namespace) ? enabled : disabled;

  fn.namespace = namespace;

  return fn;
}

/**
 * Enables a debug mode by namespaces. This can include modes
 * separated by a colon and wildcards.
 *
 * @param {String} namespaces
 * @api public
 */

function enable(namespaces) {
  exports.save(namespaces);

  var split = (namespaces || '').split(/[\s,]+/);
  var len = split.length;

  for (var i = 0; i < len; i++) {
    namespaces = split[i].replace('*', '.*?');
    if (namespaces[0] === '-') {
      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
    } else {
      exports.names.push(new RegExp('^' + namespaces + '$'));
    }
  }
}

/**
 * Disable debug output.
 *
 * @api public
 */

function disable() {
  exports.enable('');
}

/**
 * Humanize the given `ms`.
 *
 * @param {Number} m
 * @return {String}
 * @api private
 */

function humanize(ms) {
  var sec = 1000;
  var min = 60 * 1000;
  var hour = 60 * min;

  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
  if (ms >= min) return (ms / min).toFixed(1) + 'm';
  if (ms >= sec) return (ms / sec | 0) + 's';
  return ms + 'ms';
}

/**
 * Returns true if the given mode name is enabled, false otherwise.
 *
 * @param {String} name
 * @return {Boolean}
 * @api public
 */

function enabled(name) {
  var i, len;
  for (i = 0, len = exports.skips.length; i < len; i++) {
    if (exports.skips[i].test(name)) {
      return false;
    }
  }
  for (i = 0, len = exports.names.length; i < len; i++) {
    if (exports.names[i].test(name)) {
      return true;
    }
  }
  return false;
}

/**
 * Coerce `val`.
 *
 * @param {Mixed} val
 * @return {Mixed}
 * @api private
 */

function coerce(val) {
  if (val instanceof Error) return val.stack || val.message;
  return val;
}
<|endoftext|>


<commit_before>//https://github.com/searls/jasmine-stealth
(function(jasmine) {
  var isFunction = function(thing) {
    return Object.prototype.toString.call(thing) === '[object Function]';
  };

  beforeEach(function() {
    this.stubFor = this.spyOn;
  });
  jasmine.createStub = jasmine.createSpy;
  jasmine.createStubObj = function(baseName,stubbings) {
    if(stubbings.constructor === Array) {
      return jasmine.createSpyObj(baseName,stubbings);
    } else {
      var obj = {};
      for(var name in stubbings) {
        var stubbing = stubbings[name];
        obj[name] = jasmine.createSpy(baseName + '.' + name);
        if(isFunction(stubbing)) {
          obj[name].andCallFake(stubbing);
        } else {
          obj[name].andReturn(stubbing);
        }
      }
      return obj;
    }
  };

  jasmine.Spy.prototype.when = function() {
    var spy = this,
        ifThis = jasmine.util.argsToArray(arguments);
    spy._stealth_stubbings = spy._stealth_stubbings || [];

    var priorStubbing = spy.plan();

    spy.andCallFake(function() {
      for(var i=0;i<spy._stealth_stubbings.length;i++) {
        var stubbing = spy._stealth_stubbings[i];
        if(jasmine.getEnv().equals_(stubbing.ifThis,jasmine.util.argsToArray(arguments))) {
          return stubbing.thenThat;
        }
      }
      return priorStubbing;
    });

    return {
      thenReturn: function(thenThat) {
        spy._stealth_stubbings.push({
          ifThis: ifThis,
          thenThat: thenThat
        });
        return spy;
      }
    };
  };

  jasmine.Spy.prototype.mostRecentCallThat = function(callThat,context) {
    for (var i=this.calls.length-1; i >= 0; i--) {
      if(callThat.call(context || this,this.calls[i]) === true) {
        return this.calls[i];
      }
    };
  };
})(jasmine);<commit_msg>semicolons matter<commit_after>//https://github.com/searls/jasmine-stealth
(function(jasmine) {
  var isFunction = function(thing) {
    return Object.prototype.toString.call(thing) === '[object Function]';
  };

  beforeEach(function() {
    this.stubFor = this.spyOn;
  });
  jasmine.createStub = jasmine.createSpy;
  jasmine.createStubObj = function(baseName,stubbings) {
    if(stubbings.constructor === Array) {
      return jasmine.createSpyObj(baseName,stubbings);
    } else {
      var obj = {};
      for(var name in stubbings) {
        var stubbing = stubbings[name];
        obj[name] = jasmine.createSpy(baseName + '.' + name);
        if(isFunction(stubbing)) {
          obj[name].andCallFake(stubbing);
        } else {
          obj[name].andReturn(stubbing);
        }
      }
      return obj;
    }
  };

  jasmine.Spy.prototype.when = function() {
    var spy = this,
        ifThis = jasmine.util.argsToArray(arguments);
    spy._stealth_stubbings = spy._stealth_stubbings || [];

    var priorStubbing = spy.plan();

    spy.andCallFake(function() {
      for(var i=0;i<spy._stealth_stubbings.length;i++) {
        var stubbing = spy._stealth_stubbings[i];
        if(jasmine.getEnv().equals_(stubbing.ifThis,jasmine.util.argsToArray(arguments))) {
          return stubbing.thenThat;
        }
      }
      return priorStubbing;
    });

    return {
      thenReturn: function(thenThat) {
        spy._stealth_stubbings.push({
          ifThis: ifThis,
          thenThat: thenThat
        });
        return spy;
      }
    };
  };

  jasmine.Spy.prototype.mostRecentCallThat = function(callThat,context) {
    for (var i=this.calls.length-1; i >= 0; i--) {
      if(callThat.call(context || this,this.calls[i]) === true) {
        return this.calls[i];
      }
    }
  };
})(jasmine);<|endoftext|>


<commit_before><commit_msg>Tweaks<commit_after><|endoftext|>


<commit_before>(function($) {
  module('Detail view', {
    setup: function() {
      cloudStack.dialog.__confirm = cloudStack.dialog.confirm;
      cloudStack.ui.notifications.__add = cloudStack.ui.notifications.add;
    },

    teardown: function() {
      cloudStack.dialog.confirm = cloudStack.dialog.__confirm;
      cloudStack.ui.notifications.add = cloudStack.ui.notifications.__add;
    }
  });

  test('Basic', function() {
    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: [{}],
          dataProvider: function() {}
        },
        tabB: {
          title: 'tabB',
          fields: [{}],
          dataProvider: function() {}
        }
      }
    };

    var $detailView = $('<div>');

    ok($detailView.detailView(detailView), 'Create detail view');
    equal($detailView.find('.ui-tabs-nav li').size(), 2, 'Detail view has correct tab count');
    equal($detailView.find('.ui-tabs-nav li:first a').html(), 'tabA', 'First tab has correct title');
    equal($detailView.find('.ui-tabs-nav li:last a').html(), 'tabB', 'Last tab has correct title');
  });

  test('Data provider', function() {
    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: [{
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' }
          }],
          dataProvider: function(args) {
            start();
            ok(args.response.success({
              data: {
                fieldA: 'dataProviderFieldA',
                fieldB: 'dataProviderFieldB'
              }
            }), 'Call success');
            equal($detailView.find('tr').size(), 2, 'Correct fields rendered');
            equal($detailView.find('tr:first td:first').html(), 'fieldA', 'First field has correct label');
            equal($detailView.find('tr:first td:last').html(), 'dataProviderFieldA', 'First field has correct content');
            equal($detailView.find('tr:last td:first').html(), 'fieldB', 'Last field has correct label');
            equal($detailView.find('tr:last td:last').html(), 'dataProviderFieldB', 'Last field has correct content');
          }
        }
      }
    };
    var $detailView = $('<div>');

    stop();

    // Test first tab
    $detailView = $detailView.detailView(detailView);

    // Test last tab
    $detailView.find('.ui-tabs-nav li:last').click();
  });

  test('Data provider, multiple tabs', function() {
    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: [{
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' }
          }],
          dataProvider: function(args) {
            start();
            ok(args.response.success({
              data: {
                fieldA: 'dataProviderFieldA',
                fieldB: 'dataProviderFieldB'
              }
            }), 'Call success');
            equal($detailView.find('tr').size(), 2, 'Correct fields rendered');
            equal($detailView.find('tr:first td:first').html(), 'fieldA', 'First field has correct label');
            equal($detailView.find('tr:first td:last').html(), 'dataProviderFieldA', 'First field has correct content');
            equal($detailView.find('tr:last td:first').html(), 'fieldB', 'Last field has correct label');
            equal($detailView.find('tr:last td:last').html(), 'dataProviderFieldB', 'Last field has correct content');
          }
        },

        tabB: {
          title: 'tabB',
          fields: [{
            fieldC: { label: 'fieldC' },
            fieldD: { label: 'fieldD' },
            fieldC: { label: 'fieldE' },
            fieldD: { label: 'fieldF' }
          }],
          dataProvider: function(args) {
            start();
            ok(args.response.success({
              data: {
                fieldC: 'dataProviderFieldC',
                fieldD: 'dataProviderFieldD',
                fieldE: 'dataProviderFieldE',
                fieldF: 'dataProviderFieldF'
              }
            }), 'Call success');
            equal($detailView.find('tr').size(), 4, 'Correct fields rendered');
            equal($detailView.find('tr:first td:first').html(), 'fieldC', 'First field has correct label');
            equal($detailView.find('tr:first td:last').html(), 'dataProviderFieldC', 'First field has correct content');
            equal($detailView.find('tr:last td:first').html(), 'fieldF', 'Last field has correct label');
            equal($detailView.find('tr:last td:last').html(), 'dataProviderFieldF', 'Last field has correct content');
          }
        }
      }
    };
    var $detailView = $('<div>');

    stop();

    // Test first tab
    $detailView = $detailView.detailView(detailView);

    // Test last tab
    $detailView.find('.ui-tabs-nav li:last').click();
  });

  test('Field pre-filter', function() {
    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: {
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' },
            fieldC: { label: 'fieldC' },
            fieldD: { label: 'fieldD' }
          },
          preFilter: function(args) {
            return ['fieldB', 'fieldC'];
          },
          dataProvider: function (args) {
            args.response.success({
              data: {
                fieldA: 'fieldAContent',
                fieldB: 'fieldBContent',
                fieldC: 'fieldCContent',
                fieldD: 'fieldDContent'
              }
            });

            start();
            equal($detailView.find('tr').size(), 2, 'Correct fields rendered');
            equal($detailView.find('tr:first td:first').html(), 'fieldA', 'First field has correct label');
            equal($detailView.find('tr:first td:last').html(), 'fieldAContent', 'First field has correct content');
            equal($detailView.find('tr:last td:first').html(), 'fieldD', 'Last field has correct label');
            equal($detailView.find('tr:last td:last').html(), 'fieldDContent', 'Last field has correct content');
          }
        }
      }
    };
    var $detailView = $('<div>');

    stop();

    $detailView.detailView(detailView);
  });

  test('Action', function() {
    var detailView = {
      actions: {
        actionA: {
          label: 'testActionA',
          action: function(args) {
            start();
            ok(args.response.success(), 'Call success from action A');
          },
          messages: {
            confirm: function() { return 'testActionAConfirm'; },
            notification: function() { return 'testActionANotification'; }
          }
        },
        actionB: {
          label: 'testActionB',
          action: function(args) {
            start();
            ok(args.response.success(), 'Call success from action B');
          },
          messages: {
            confirm: function() { return 'testActionBConfirm'; },
            notification: function() { return 'testActionBNotification'; }
          },
          notification: {
            poll: function(args) {
              start();
              ok(args.complete(), 'Call complete from async action B');
            }
          }
        }
      },
      tabs: {
        tabA: {
          title: 'tabA',
          fields: {
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' }
          },
          dataProvider: function(args) {
            args.response.success({
              data: {
                fieldA: 'fieldAContent',
                fieldB: 'fieldBContent'
              }
            });
          }
        }
      }
    };
    var $detailView = $('<div>');

    $detailView.detailView(detailView).appendTo('#qunit-fixture');

    equal($detailView.find('.detail-actions').size(), 1, 'Action container present');
    equal($detailView.find('.detail-actions .action').size(), 2, 'Correct action count');
    equal($detailView.find('.detail-actions .action.actionA').size(), 1, 'actionA present');
    equal($detailView.find('.detail-actions .action.actionB').size(), 1, 'actionB present');

    cloudStack.dialog.confirm = function(args) {
      start();
      equal(args.message, 'testActionAConfirm', 'Correct confirmation message for action A');
      stop();

      args.action(); // Perform action
    };

    cloudStack.ui.notifications.add = function(notification, success, successArgs) {
      stop();
      equal(notification.desc, 'testActionANotification', 'Correct notification message for action A');
      start();
    };

    $detailView.find('.detail-actions .action.actionA a').click(); // <a> triggers action, not action's container

    cloudStack.dialog.confirm = function(args) {
      start();
      equal(args.message, 'testActionBConfirm', 'Correct confirmation message for action B');
      stop();

      args.action(); // Perform action
    };

    cloudStack.ui.notifications.add = function(notification, success, successArgs) {
      start();
      equal(notification.desc, 'testActionBNotification', 'Correct notification message for action B');
      stop();
      notification.poll({ complete: function() { return true; } });
    };

    $detailView.find('.detail-actions .action.actionB a').click(); // <a> triggers action, not action's container
  });

  test('Refresh', function() {
    var dataA = ['dataLoad1A', 'dataLoad2A'];
    var dataB = ['dataLoad1B', 'dataLoad2B'];
    var index = 0;

    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: {
            fieldA: { label: 'fieldA' }
          },
          dataProvider: function(args) {
            args.response.success({ data: { fieldA: dataA[index]  }});
            start();
            equal($detailView.find('tr td:last').html(), dataA[index], 'Tab A data correct for load ' + (index + 1));
            index++;
          }
        },
        tabB: {
          title: 'tabB',
          fields: {
            fieldB: { label: 'fieldB' }
          },
          dataProvider: function(args) {
            args.response.success({ data: { fieldB: dataB[index]  }});
            start();
            equal($detailView.find('tr td:last').html(), dataB[index], 'Tab B data correct for load ' + (index + 1));
            index++;
          }
        }
      }
    };
    var $detailView = $('<div>');

    stop();
    $detailView.detailView(detailView).appendTo('#qunit-fixture');

    stop();
    $detailView.find('.button.refresh').click();

    stop();
    index = 0;
    $detailView.find('.ui-tabs-nav li.last a').click();

    stop();
    $detailView.find('.button.refresh').click();
  });
}(jQuery));
<commit_msg>Add detail view action filter tests<commit_after>(function($) {
  module('Detail view', {
    setup: function() {
      cloudStack.dialog.__confirm = cloudStack.dialog.confirm;
      cloudStack.ui.notifications.__add = cloudStack.ui.notifications.add;
    },

    teardown: function() {
      cloudStack.dialog.confirm = cloudStack.dialog.__confirm;
      cloudStack.ui.notifications.add = cloudStack.ui.notifications.__add;
    }
  });

  test('Basic', function() {
    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: [{}],
          dataProvider: function() {}
        },
        tabB: {
          title: 'tabB',
          fields: [{}],
          dataProvider: function() {}
        }
      }
    };

    var $detailView = $('<div>');

    ok($detailView.detailView(detailView), 'Create detail view');
    equal($detailView.find('.ui-tabs-nav li').size(), 2, 'Detail view has correct tab count');
    equal($detailView.find('.ui-tabs-nav li:first a').html(), 'tabA', 'First tab has correct title');
    equal($detailView.find('.ui-tabs-nav li:last a').html(), 'tabB', 'Last tab has correct title');
  });

  test('Data provider', function() {
    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: [{
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' }
          }],
          dataProvider: function(args) {
            start();
            ok(args.response.success({
              data: {
                fieldA: 'dataProviderFieldA',
                fieldB: 'dataProviderFieldB'
              }
            }), 'Call success');
            equal($detailView.find('tr').size(), 2, 'Correct fields rendered');
            equal($detailView.find('tr:first td:first').html(), 'fieldA', 'First field has correct label');
            equal($detailView.find('tr:first td:last').html(), 'dataProviderFieldA', 'First field has correct content');
            equal($detailView.find('tr:last td:first').html(), 'fieldB', 'Last field has correct label');
            equal($detailView.find('tr:last td:last').html(), 'dataProviderFieldB', 'Last field has correct content');
          }
        }
      }
    };
    var $detailView = $('<div>');

    stop();

    // Test first tab
    $detailView = $detailView.detailView(detailView);

    // Test last tab
    $detailView.find('.ui-tabs-nav li:last').click();
  });

  test('Data provider, multiple tabs', function() {
    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: [{
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' }
          }],
          dataProvider: function(args) {
            start();
            ok(args.response.success({
              data: {
                fieldA: 'dataProviderFieldA',
                fieldB: 'dataProviderFieldB'
              }
            }), 'Call success');
            equal($detailView.find('tr').size(), 2, 'Correct fields rendered');
            equal($detailView.find('tr:first td:first').html(), 'fieldA', 'First field has correct label');
            equal($detailView.find('tr:first td:last').html(), 'dataProviderFieldA', 'First field has correct content');
            equal($detailView.find('tr:last td:first').html(), 'fieldB', 'Last field has correct label');
            equal($detailView.find('tr:last td:last').html(), 'dataProviderFieldB', 'Last field has correct content');
          }
        },

        tabB: {
          title: 'tabB',
          fields: [{
            fieldC: { label: 'fieldC' },
            fieldD: { label: 'fieldD' },
            fieldC: { label: 'fieldE' },
            fieldD: { label: 'fieldF' }
          }],
          dataProvider: function(args) {
            start();
            ok(args.response.success({
              data: {
                fieldC: 'dataProviderFieldC',
                fieldD: 'dataProviderFieldD',
                fieldE: 'dataProviderFieldE',
                fieldF: 'dataProviderFieldF'
              }
            }), 'Call success');
            equal($detailView.find('tr').size(), 4, 'Correct fields rendered');
            equal($detailView.find('tr:first td:first').html(), 'fieldC', 'First field has correct label');
            equal($detailView.find('tr:first td:last').html(), 'dataProviderFieldC', 'First field has correct content');
            equal($detailView.find('tr:last td:first').html(), 'fieldF', 'Last field has correct label');
            equal($detailView.find('tr:last td:last').html(), 'dataProviderFieldF', 'Last field has correct content');
          }
        }
      }
    };
    var $detailView = $('<div>');

    stop();

    // Test first tab
    $detailView = $detailView.detailView(detailView);

    // Test last tab
    $detailView.find('.ui-tabs-nav li:last').click();
  });

  test('Field pre-filter', function() {
    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: {
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' },
            fieldC: { label: 'fieldC' },
            fieldD: { label: 'fieldD' }
          },
          preFilter: function(args) {
            return ['fieldB', 'fieldC'];
          },
          dataProvider: function (args) {
            args.response.success({
              data: {
                fieldA: 'fieldAContent',
                fieldB: 'fieldBContent',
                fieldC: 'fieldCContent',
                fieldD: 'fieldDContent'
              }
            });

            start();
            equal($detailView.find('tr').size(), 2, 'Correct fields rendered');
            equal($detailView.find('tr:first td:first').html(), 'fieldA', 'First field has correct label');
            equal($detailView.find('tr:first td:last').html(), 'fieldAContent', 'First field has correct content');
            equal($detailView.find('tr:last td:first').html(), 'fieldD', 'Last field has correct label');
            equal($detailView.find('tr:last td:last').html(), 'fieldDContent', 'Last field has correct content');
          }
        }
      }
    };
    var $detailView = $('<div>');

    stop();

    $detailView.detailView(detailView);
  });

  test('Action', function() {
    var detailView = {
      actions: {
        actionA: {
          label: 'testActionA',
          action: function(args) {
            start();
            ok(args.response.success(), 'Call success from action A');
          },
          messages: {
            confirm: function() { return 'testActionAConfirm'; },
            notification: function() { return 'testActionANotification'; }
          }
        },
        actionB: {
          label: 'testActionB',
          action: function(args) {
            start();
            ok(args.response.success(), 'Call success from action B');
          },
          messages: {
            confirm: function() { return 'testActionBConfirm'; },
            notification: function() { return 'testActionBNotification'; }
          },
          notification: {
            poll: function(args) {
              start();
              ok(args.complete(), 'Call complete from async action B');
            }
          }
        }
      },
      tabs: {
        tabA: {
          title: 'tabA',
          fields: {
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' }
          },
          dataProvider: function(args) {
            args.response.success({
              data: {
                fieldA: 'fieldAContent',
                fieldB: 'fieldBContent'
              }
            });
          }
        }
      }
    };
    var $detailView = $('<div>');

    $detailView.detailView(detailView).appendTo('#qunit-fixture');

    equal($detailView.find('.detail-actions').size(), 1, 'Action container present');
    equal($detailView.find('.detail-actions .action').size(), 2, 'Correct action count');
    equal($detailView.find('.detail-actions .action.actionA').size(), 1, 'actionA present');
    equal($detailView.find('.detail-actions .action.actionB').size(), 1, 'actionB present');

    cloudStack.dialog.confirm = function(args) {
      start();
      equal(args.message, 'testActionAConfirm', 'Correct confirmation message for action A');
      stop();

      args.action(); // Perform action
    };

    cloudStack.ui.notifications.add = function(notification, success, successArgs) {
      stop();
      equal(notification.desc, 'testActionANotification', 'Correct notification message for action A');
      start();
    };

    $detailView.find('.detail-actions .action.actionA a').click(); // <a> triggers action, not action's container

    cloudStack.dialog.confirm = function(args) {
      start();
      equal(args.message, 'testActionBConfirm', 'Correct confirmation message for action B');
      stop();

      args.action(); // Perform action
    };

    cloudStack.ui.notifications.add = function(notification, success, successArgs) {
      start();
      equal(notification.desc, 'testActionBNotification', 'Correct notification message for action B');
      stop();
      notification.poll({ complete: function() { return true; } });
    };

    $detailView.find('.detail-actions .action.actionB a').click(); // <a> triggers action, not action's container
  });

  test('Action filter', function() {
    var detailView = {
      actions: {
        actionA: {
          label: 'testActionA',
          action: function(args) {}
        },
        actionB: {
          label: 'testActionB',
          action: function(args) {}
        }
      },
      tabs: {
        tabA: {
          title: 'tabA',
          fields: {
            fieldA: { label: 'fieldA' },
            fieldB: { label: 'fieldB' }
          },
          dataProvider: function(args) {
            args.response.success({
              actionFilter: function() {
                return ['actionA'];
              },
              data: {
                fieldA: 'fieldAContent',
                fieldB: 'fieldBContent'
              }
            });
          }
        }
      }
    };
    var $detailView = $('<div>');

    $detailView.detailView(detailView).appendTo('#qunit-fixture');

    equal($detailView.find('.detail-actions .action').size(), 1, 'Correct action count');
    equal($detailView.find('.detail-actions .action.actionA').size(), 1, 'actionA present');
    notEqual($detailView.find('.detail-actions .action.actionB').size(), 1, 'actionB not present');
  });

  test('Refresh', function() {
    var dataA = ['dataLoad1A', 'dataLoad2A'];
    var dataB = ['dataLoad1B', 'dataLoad2B'];
    var index = 0;

    var detailView = {
      tabs: {
        tabA: {
          title: 'tabA',
          fields: {
            fieldA: { label: 'fieldA' }
          },
          dataProvider: function(args) {
            args.response.success({ data: { fieldA: dataA[index]  }});
            start();
            equal($detailView.find('tr td:last').html(), dataA[index], 'Tab A data correct for load ' + (index + 1));
            index++;
          }
        },
        tabB: {
          title: 'tabB',
          fields: {
            fieldB: { label: 'fieldB' }
          },
          dataProvider: function(args) {
            args.response.success({ data: { fieldB: dataB[index]  }});
            start();
            equal($detailView.find('tr td:last').html(), dataB[index], 'Tab B data correct for load ' + (index + 1));
            index++;
          }
        }
      }
    };
    var $detailView = $('<div>');

    stop();
    $detailView.detailView(detailView).appendTo('#qunit-fixture');

    stop();
    $detailView.find('.button.refresh').click();

    stop();
    index = 0;
    $detailView.find('.ui-tabs-nav li.last a').click();

    stop();
    $detailView.find('.button.refresh').click();
  });
}(jQuery));
<|endoftext|>


<commit_before>import React, {Component, cloneElement} from 'react';
import PropTypes from 'prop-types';
import IconButton from '../IconButton';
import NavigationMenu from '../svg-icons/navigation/menu';
import Paper from '../Paper';
import propTypes from '../utils/propTypes';
import warning from 'warning';

export function getStyles(props, context) {
  const {
    appBar,
    button: {
      iconButtonSize,
    },
    zIndex,
  } = context.muiTheme;

  const flatButtonSize = 36;

  const styles = {
    root: {
      position: 'relative',
      zIndex: zIndex.appBar,
      width: '100%',
      display: 'flex',
      backgroundColor: appBar.color,
      paddingLeft: appBar.padding,
      paddingRight: appBar.padding,
    },
    title: {
      whiteSpace: 'nowrap',
      overflow: 'hidden',
      textOverflow: 'ellipsis',
      margin: 0,
      paddingTop: 0,
      letterSpacing: 0,
      fontSize: 24,
      fontWeight: appBar.titleFontWeight,
      color: appBar.textColor,
      height: appBar.height,
      lineHeight: `${appBar.height}px`,
    },
    mainElement: {
      boxFlex: 1,
      flex: '1',
    },
    iconButtonStyle: {
      marginTop: (appBar.height - iconButtonSize) / 2,
      marginRight: 8,
      marginLeft: -16,
    },
    iconButtonIconStyle: {
      fill: appBar.textColor,
      color: appBar.textColor,
    },
    flatButton: {
      color: appBar.textColor,
      marginTop: (iconButtonSize - flatButtonSize) / 2 + 1,
    },
  };

  return styles;
}

class AppBar extends Component {
  static muiName = 'AppBar';

  static propTypes = {
    /**
     * The id value used for the component.
     * This will be used as a base for all child components also.
     * If not provided the class name along with appropriate properties and a random number will be used.
     */
    id: PropTypes.string,
    /**
     * Can be used to render a tab inside an app bar for instance.
     */
    children: PropTypes.node,
    /**
     * Applied to the app bar's root element.
     */
    className: PropTypes.string,
    /**
     * The classname of the icon on the left of the app bar.
     * If you are using a stylesheet for your icons, enter the class name for the icon to be used here.
     */
    iconClassNameLeft: PropTypes.string,
    /**
     * Similiar to the iconClassNameLeft prop except that
     * it applies to the icon displayed on the right of the app bar.
     */
    iconClassNameRight: PropTypes.string,
    /**
     * The custom element to be displayed on the left side of the
     * app bar such as an SvgIcon.
     */
    iconElementLeft: PropTypes.element,
    /**
     * Similiar to the iconElementLeft prop except that this element is displayed on the right of the app bar.
     */
    iconElementRight: PropTypes.element,
    /**
     * Override the inline-styles of the element displayed on the left side of the app bar.
     */
    iconStyleLeft: PropTypes.object,
    /**
     * Override the inline-styles of the element displayed on the right side of the app bar.
     */
    iconStyleRight: PropTypes.object,
    /**
     * Callback function for when the left icon is selected via a touch tap.
     *
     * @param {object} event TouchTap event targeting the left `IconButton`.
     */
    onLeftIconButtonTouchTap: PropTypes.func,
    /**
     * Callback function for when the right icon is selected via a touch tap.
     *
     * @param {object} event TouchTap event targeting the right `IconButton`.
     */
    onRightIconButtonTouchTap: PropTypes.func,
    /**
     * Callback function for when the title text is selected via a touch tap.
     *
     * @param {object} event TouchTap event targeting the `title` node.
     */
    onTitleTouchTap: PropTypes.func,
    /**
     * Determines whether or not to display the Menu icon next to the title.
     * Setting this prop to false will hide the icon.
     */
    showMenuIconButton: PropTypes.bool,
    /**
     * Override the inline-styles of the root element.
     */
    style: PropTypes.object,
    /**
     * The title to display on the app bar.
     */
    title: PropTypes.node,
    /**
     * Override the inline-styles of the app bar's title element.
     */
    titleStyle: PropTypes.object,
    /**
     * The zDepth of the component.
     * The shadow of the app bar is also dependent on this property.
     */
    zDepth: propTypes.zDepth,
  };

  static defaultProps = {
    showMenuIconButton: true,
    title: '',
    zDepth: 1,
  };

  static contextTypes = {
    muiTheme: PropTypes.object.isRequired,
  };

  componentWillMount() {
    const uniqueId = `${this.constructor.name}-${Math.floor(Math.random() * 0xFFFF)}`;
    this.uniqueId = uniqueId.replace(/[^A-Za-z0-9-]/gi, '');
  }

  componentDidMount() {
    warning(!this.props.iconElementLeft || !this.props.iconClassNameLeft, `Material-UI: Properties iconElementLeft
      and iconClassNameLeft cannot be simultaneously defined. Please use one or the other.`);

    warning(!this.props.iconElementRight || !this.props.iconClassNameRight, `Material-UI: Properties iconElementRight
      and iconClassNameRight cannot be simultaneously defined. Please use one or the other.`);
  }

  handleTouchTapLeftIconButton = (event) => {
    if (this.props.onLeftIconButtonTouchTap) {
      this.props.onLeftIconButtonTouchTap(event);
    }
  };

  handleTouchTapRightIconButton = (event) => {
    if (this.props.onRightIconButtonTouchTap) {
      this.props.onRightIconButtonTouchTap(event);
    }
  };

  handleTitleTouchTap = (event) => {
    if (this.props.onTitleTouchTap) {
      this.props.onTitleTouchTap(event);
    }
  };

  render() {
    const {
      id,
      title,
      titleStyle,
      iconStyleLeft,
      iconStyleRight,
      onTitleTouchTap, // eslint-disable-line no-unused-vars
      showMenuIconButton,
      iconElementLeft,
      iconElementRight,
      iconClassNameLeft,
      iconClassNameRight,
      onLeftIconButtonTouchTap, // eslint-disable-line no-unused-vars
      onRightIconButtonTouchTap, // eslint-disable-line no-unused-vars
      className,
      style,
      zDepth,
      children,
      ...other
    } = this.props;

    const {prepareStyles} = this.context.muiTheme;
    const styles = getStyles(this.props, this.context);

    let menuElementLeft;
    let menuElementRight;

    const baseId = id || this.uniqueId;

    // If the title is a string, wrap in an h1 tag.
    // If not, wrap in a div tag.
    const titleComponent = typeof title === 'string' || title instanceof String ? 'h1' : 'div';
    const titleId = baseId + '-' + (typeof title === 'string' ? title + '-id' : 'id-title-id');

    const titleElement = React.createElement(titleComponent, {
      onTouchTap: this.handleTitleTouchTap,
      id: titleId,
      style: prepareStyles(Object.assign(styles.title, styles.mainElement, titleStyle)),
    }, title);

    const iconLeftStyle = Object.assign({}, styles.iconButtonStyle, iconStyleLeft);
    const iconButtonParent = this.props.title.length === 0 ? "App Bar" : this.props.title + " App Bar";
    const appBarTitle = typeof title === 'string' ? title : '';
    const appBarId= baseId + '-' + appBarTitle;

    if (showMenuIconButton) {
      if (iconElementLeft) {
        const iconElementLeftProps = {};

        if (iconElementLeft.type.muiName === 'IconButton') {
          const iconElemLeftChildren = iconElementLeft.props.children;
          const iconButtonIconStyle = !(
            iconElemLeftChildren &&
            iconElemLeftChildren.props &&
            iconElemLeftChildren.props.color
          ) ? styles.iconButtonIconStyle : null;

          iconElementLeftProps.iconStyle = Object.assign({}, iconButtonIconStyle, iconElementLeft.props.iconStyle);
        }

        if (!iconElementLeft.props.onTouchTap && this.props.onLeftIconButtonTouchTap) {
          iconElementLeftProps.onTouchTap = this.handleTouchTapLeftIconButton;
        }

        menuElementLeft = (

            {Object.keys(iconElementLeftProps).length > 0 ?
              cloneElement(iconElementLeft, iconElementLeftProps) :
              iconElementLeft}

        );
      } else {
        menuElementLeft = (
          <IconButton
            style={iconLeftStyle}
            iconStyle={styles.iconButtonIconStyle}
            iconClassName={iconClassNameLeft}
            onTouchTap={this.handleTouchTapLeftIconButton}
            buttonAriaLabel={iconButtonParent + ' left side'}
            labelledBy={titleId}
          >
            {iconClassNameLeft ?
              '' :
              <NavigationMenu style={Object.assign({}, styles.iconButtonIconStyle)} />
            }
          </IconButton>
        );
      }
    }

    const iconRightStyle = Object.assign({}, styles.iconButtonStyle, {
      marginRight: -16,
      marginLeft: 'auto',
    }, iconStyleRight);

    if (iconElementRight) {
      const iconElementRightProps = {};

      switch (iconElementRight.type.muiName) {
        case 'IconMenu':
        case 'IconButton':
          const iconElemRightChildren = iconElementRight.props.children;
          const iconButtonIconStyle = !(
            iconElemRightChildren &&
            iconElemRightChildren.props &&
            iconElemRightChildren.props.color
          ) ? styles.iconButtonIconStyle : null;

          iconElementRightProps.iconStyle = Object.assign({}, iconButtonIconStyle, iconElementRight.props.iconStyle);
          break;

        case 'FlatButton':
          iconElementRightProps.style = Object.assign({}, styles.flatButton, iconElementRight.props.style);
          break;

        default:
      }

      if (!iconElementRight.props.onTouchTap && this.props.onRightIconButtonTouchTap) {
        iconElementRightProps.onTouchTap = this.handleTouchTapRightIconButton;
      }

      menuElementRight = (

          {Object.keys(iconElementRightProps).length > 0 ?
            cloneElement(iconElementRight, iconElementRightProps) :
            iconElementRight}

      );
    } else if (iconClassNameRight) {
      menuElementRight = (
        <IconButton
          style={iconRightStyle}
          iconStyle={styles.iconButtonIconStyle}
          iconClassName={iconClassNameRight}
          onTouchTap={this.handleTouchTapRightIconButton}
          buttonAriaLabel={iconButtonParent + ' right side'}
          labelledBy={titleId}
        />
      );
    }

    return (
      <Paper
        id={appBarId}
        {...other}
        rounded={false}
        className={className}
        style={Object.assign({}, styles.root, style)}
        zDepth={zDepth}
      >
        {menuElementLeft}
        {titleElement}
        {menuElementRight}
        {children}
      </Paper>
    );
  }
}

export default AppBar;
<commit_msg>AppBar - es6 lint cleanup #38 moved the id value to the correct place in the props fixed concatenation issues when strings are being joined with +<commit_after>import React, {Component, cloneElement} from 'react';
import PropTypes from 'prop-types';
import IconButton from '../IconButton';
import NavigationMenu from '../svg-icons/navigation/menu';
import Paper from '../Paper';
import propTypes from '../utils/propTypes';
import warning from 'warning';

export function getStyles(props, context) {
  const {
    appBar,
    button: {
      iconButtonSize,
    },
    zIndex,
  } = context.muiTheme;

  const flatButtonSize = 36;

  const styles = {
    root: {
      position: 'relative',
      zIndex: zIndex.appBar,
      width: '100%',
      display: 'flex',
      backgroundColor: appBar.color,
      paddingLeft: appBar.padding,
      paddingRight: appBar.padding,
    },
    title: {
      whiteSpace: 'nowrap',
      overflow: 'hidden',
      textOverflow: 'ellipsis',
      margin: 0,
      paddingTop: 0,
      letterSpacing: 0,
      fontSize: 24,
      fontWeight: appBar.titleFontWeight,
      color: appBar.textColor,
      height: appBar.height,
      lineHeight: `${appBar.height}px`,
    },
    mainElement: {
      boxFlex: 1,
      flex: '1',
    },
    iconButtonStyle: {
      marginTop: (appBar.height - iconButtonSize) / 2,
      marginRight: 8,
      marginLeft: -16,
    },
    iconButtonIconStyle: {
      fill: appBar.textColor,
      color: appBar.textColor,
    },
    flatButton: {
      color: appBar.textColor,
      marginTop: (iconButtonSize - flatButtonSize) / 2 + 1,
    },
  };

  return styles;
}

class AppBar extends Component {
  static muiName = 'AppBar';

  static propTypes = {
    /**
     * Can be used to render a tab inside an app bar for instance.
     */
    children: PropTypes.node,
    /**
     * Applied to the app bar's root element.
     */
    className: PropTypes.string,
    /**
     * The classname of the icon on the left of the app bar.
     * If you are using a stylesheet for your icons, enter the class name for the icon to be used here.
     */
    iconClassNameLeft: PropTypes.string,
    /**
     * Similiar to the iconClassNameLeft prop except that
     * it applies to the icon displayed on the right of the app bar.
     */
    iconClassNameRight: PropTypes.string,
    /**
     * The custom element to be displayed on the left side of the
     * app bar such as an SvgIcon.
     */
    iconElementLeft: PropTypes.element,
    /**
     * Similiar to the iconElementLeft prop except that this element is displayed on the right of the app bar.
     */
    iconElementRight: PropTypes.element,
    /**
     * Override the inline-styles of the element displayed on the left side of the app bar.
     */
    iconStyleLeft: PropTypes.object,
    /**
     * Override the inline-styles of the element displayed on the right side of the app bar.
     */
    iconStyleRight: PropTypes.object,
    /**
     * The id value used for the component.
     * This will be used as a base for all child components also.
     * If not provided the class name along with appropriate properties and a random number will be used.
     */
    id: PropTypes.string,
    /**
     * Callback function for when the left icon is selected via a touch tap.
     *
     * @param {object} event TouchTap event targeting the left `IconButton`.
     */
    onLeftIconButtonTouchTap: PropTypes.func,
    /**
     * Callback function for when the right icon is selected via a touch tap.
     *
     * @param {object} event TouchTap event targeting the right `IconButton`.
     */
    onRightIconButtonTouchTap: PropTypes.func,
    /**
     * Callback function for when the title text is selected via a touch tap.
     *
     * @param {object} event TouchTap event targeting the `title` node.
     */
    onTitleTouchTap: PropTypes.func,
    /**
     * Determines whether or not to display the Menu icon next to the title.
     * Setting this prop to false will hide the icon.
     */
    showMenuIconButton: PropTypes.bool,
    /**
     * Override the inline-styles of the root element.
     */
    style: PropTypes.object,
    /**
     * The title to display on the app bar.
     */
    title: PropTypes.node,
    /**
     * Override the inline-styles of the app bar's title element.
     */
    titleStyle: PropTypes.object,
    /**
     * The zDepth of the component.
     * The shadow of the app bar is also dependent on this property.
     */
    zDepth: propTypes.zDepth,
  };

  static defaultProps = {
    showMenuIconButton: true,
    title: '',
    zDepth: 1,
  };

  static contextTypes = {
    muiTheme: PropTypes.object.isRequired,
  };

  componentWillMount() {
    const uniqueId = `${this.constructor.name}-${Math.floor(Math.random() * 0xFFFF)}`;
    this.uniqueId = uniqueId.replace(/[^A-Za-z0-9-]/gi, '');
  }

  componentDidMount() {
    warning(!this.props.iconElementLeft || !this.props.iconClassNameLeft, `Material-UI: Properties iconElementLeft
      and iconClassNameLeft cannot be simultaneously defined. Please use one or the other.`);

    warning(!this.props.iconElementRight || !this.props.iconClassNameRight, `Material-UI: Properties iconElementRight
      and iconClassNameRight cannot be simultaneously defined. Please use one or the other.`);
  }

  handleTouchTapLeftIconButton = (event) => {
    if (this.props.onLeftIconButtonTouchTap) {
      this.props.onLeftIconButtonTouchTap(event);
    }
  };

  handleTouchTapRightIconButton = (event) => {
    if (this.props.onRightIconButtonTouchTap) {
      this.props.onRightIconButtonTouchTap(event);
    }
  };

  handleTitleTouchTap = (event) => {
    if (this.props.onTitleTouchTap) {
      this.props.onTitleTouchTap(event);
    }
  };

  render() {
    const {
      id,
      title,
      titleStyle,
      iconStyleLeft,
      iconStyleRight,
      onTitleTouchTap, // eslint-disable-line no-unused-vars
      showMenuIconButton,
      iconElementLeft,
      iconElementRight,
      iconClassNameLeft,
      iconClassNameRight,
      onLeftIconButtonTouchTap, // eslint-disable-line no-unused-vars
      onRightIconButtonTouchTap, // eslint-disable-line no-unused-vars
      className,
      style,
      zDepth,
      children,
      ...other
    } = this.props;

    const {prepareStyles} = this.context.muiTheme;
    const styles = getStyles(this.props, this.context);

    let menuElementLeft;
    let menuElementRight;

    const baseId = id || this.uniqueId;

    // If the title is a string, wrap in an h1 tag.
    // If not, wrap in a div tag.
    const titleComponent = typeof title === 'string' || title instanceof String ? 'h1' : 'div';
    const titlePart = typeof title === 'string' ? `${title}-id` : 'id-title-id';
    const titleId = `${baseId}-${titlePart}`;

    const titleElement = React.createElement(titleComponent, {
      onTouchTap: this.handleTitleTouchTap,
      id: titleId,
      style: prepareStyles(Object.assign(styles.title, styles.mainElement, titleStyle)),
    }, title);

    const iconLeftStyle = Object.assign({}, styles.iconButtonStyle, iconStyleLeft);
    const iconButtonParent = this.props.title.length === 0 ? 'App Bar' : `${this.props.title} App Bar`;
    const appBarTitle = typeof title === 'string' ? title : '';
    const appBarId = `${baseId}-${appBarTitle}`;

    if (showMenuIconButton) {
      if (iconElementLeft) {
        const iconElementLeftProps = {};

        if (iconElementLeft.type.muiName === 'IconButton') {
          const iconElemLeftChildren = iconElementLeft.props.children;
          const iconButtonIconStyle = !(
            iconElemLeftChildren &&
            iconElemLeftChildren.props &&
            iconElemLeftChildren.props.color
          ) ? styles.iconButtonIconStyle : null;

          iconElementLeftProps.iconStyle = Object.assign({}, iconButtonIconStyle, iconElementLeft.props.iconStyle);
        }

        if (!iconElementLeft.props.onTouchTap && this.props.onLeftIconButtonTouchTap) {
          iconElementLeftProps.onTouchTap = this.handleTouchTapLeftIconButton;
        }

        menuElementLeft = (

            {Object.keys(iconElementLeftProps).length > 0 ?
              cloneElement(iconElementLeft, iconElementLeftProps) :
              iconElementLeft}

        );
      } else {
        menuElementLeft = (
          <IconButton
            style={iconLeftStyle}
            iconStyle={styles.iconButtonIconStyle}
            iconClassName={iconClassNameLeft}
            onTouchTap={this.handleTouchTapLeftIconButton}
            buttonAriaLabel={`${iconButtonParent} left side`}
            labelledBy={titleId}
          >
            {iconClassNameLeft ?
              '' :
              <NavigationMenu style={Object.assign({}, styles.iconButtonIconStyle)} />
            }
          </IconButton>
        );
      }
    }

    const iconRightStyle = Object.assign({}, styles.iconButtonStyle, {
      marginRight: -16,
      marginLeft: 'auto',
    }, iconStyleRight);

    if (iconElementRight) {
      const iconElementRightProps = {};

      switch (iconElementRight.type.muiName) {
        case 'IconMenu':
        case 'IconButton':
          const iconElemRightChildren = iconElementRight.props.children;
          const iconButtonIconStyle = !(
            iconElemRightChildren &&
            iconElemRightChildren.props &&
            iconElemRightChildren.props.color
          ) ? styles.iconButtonIconStyle : null;

          iconElementRightProps.iconStyle = Object.assign({}, iconButtonIconStyle, iconElementRight.props.iconStyle);
          break;

        case 'FlatButton':
          iconElementRightProps.style = Object.assign({}, styles.flatButton, iconElementRight.props.style);
          break;

        default:
      }

      if (!iconElementRight.props.onTouchTap && this.props.onRightIconButtonTouchTap) {
        iconElementRightProps.onTouchTap = this.handleTouchTapRightIconButton;
      }

      menuElementRight = (

          {Object.keys(iconElementRightProps).length > 0 ?
            cloneElement(iconElementRight, iconElementRightProps) :
            iconElementRight}

      );
    } else if (iconClassNameRight) {
      menuElementRight = (
        <IconButton
          style={iconRightStyle}
          iconStyle={styles.iconButtonIconStyle}
          iconClassName={iconClassNameRight}
          onTouchTap={this.handleTouchTapRightIconButton}
          buttonAriaLabel={`${iconButtonParent} right side`}
          labelledBy={titleId}
        />
      );
    }

    return (
      <Paper
        id={appBarId}
        {...other}
        rounded={false}
        className={className}
        style={Object.assign({}, styles.root, style)}
        zDepth={zDepth}
      >
        {menuElementLeft}
        {titleElement}
        {menuElementRight}
        {children}
      </Paper>
    );
  }
}

export default AppBar;
<|endoftext|>


<commit_before>"use strict";
/*
 * Cross-domain task proxy implementation for Bebras task API - v1.0 - 08/2014
 *
 * This file implements a "TaskProxyManager" object in the global scope so that
 * platforms using this file can just call
 * "myTask = TaskProxyManager.getTaskProxy(task_id)" to get the task object
 * associated to a task loaded in an iframe. Then they can just call
 * "myTask.myFunction()", with function of the API, the task object will take
 * care of message sending and receiving with the actual task.
 * 'task_id' here refers to the "id" attribute of the iframe in which a task is
 * loaded.
 *
 * It depends on jQuery (though this could be removed) and jschannel.
 *
 */

/**
 * Global objects
 */

var TaskProxyManager = {
   tasks: {},
   platforms: {},
   getRandomID: function() {
      var low = Math.floor(Math.random() * 922337203).toString();
      var high = Math.floor(Math.random() * 2000000000).toString();
      return high + low;
   },
   getTaskProxy: function(idFrame, callback, force) {
      if (TaskProxyManager.tasks[idFrame] && !force) {
         return TaskProxyManager.tasks[idFrame];
      } else {
         if (force) {
            TaskProxyManager.deleteTaskProxy(idFrame);
         }
         $('#'+idFrame).each(function() {
            TaskProxyManager.tasks[idFrame] = new Task($(this), function() {
               if (idFrame in TaskProxyManager.platforms) {
                  TaskProxyManager.tasks[idFrame].setPlatform(TaskProxyManager.platforms[idFrame]);
               }
               callback(TaskProxyManager.tasks[idFrame]);
            });
         });
      }
   },
   setPlatform: function(task, platform) {
      TaskProxyManager.platforms[task.Id] = platform;
      TaskProxyManager.tasks[task.Id].setPlatform(platform);
   },
   deleteTaskProxy: function(idFrame) {
      var task = TaskProxyManager.tasks[idFrame];
      if (task && task.chan) {
         task.chan.destroy();
      }
      delete(TaskProxyManager.tasks[idFrame]);
      delete(TaskProxyManager.platforms[idFrame]);
   },
   getUrl: function(taskUrl, sToken, sPlatform, prefix) {
      var channelId = (prefix ? prefix : '')+this.getRandomID();
      return taskUrl+'?sToken='+encodeURIComponent(sToken)+'&sPlatform='+encodeURIComponent(sPlatform)+'&channelId='+encodeURIComponent(channelId);
   }
};

TaskProxyManager.getGraderProxy = TaskProxyManager.getTaskProxy;

/**
 * Enable / Disable messages debug
 */
var platformDebug = false;

/*
 * Task object, created from an iframe DOM element
 */
function Task(iframe, callback) {
   this.iframe = iframe;
   this.Id = iframe.attr('id');
   function getUrlParameterByName(name, url) {
       var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
           results = regex.exec(url);
       return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
   }
   this.chan = Channel.build({
      window: iframe[0].contentWindow,
      origin: "*",
      scope: getUrlParameterByName('channelId', iframe[0].src),
      onReady: function() {
         console.error("channel is ready!");
         callback();
      }
   });
   this.setPlatform = function(platform) {
      this.platform = platform;
      this.chan.bind('platform.validate', function (trans, mode) {
         platform.validate(mode, trans.complete, trans.error);
         trans.delayReturn(true);
         console.error('platform.validate with mode '+mode);
      });
      this.chan.bind('platform.getTaskParams', function (trans, keyDefault) {
         var key = keyDefault ? keyDefault[0] : undefined;
         var defaultValue = keyDefault ? keyDefault[1] : undefined;
         platform.getTaskParams(key, defaultValue, trans.complete, trans.error);
         trans.delayReturn(true);
      });
      this.chan.bind('platform.showView', function (trans, view) {
         platform.showView(view, trans.complete, trans.error);
         trans.delayReturn(true);
      });
      this.chan.bind('platform.askHint', function (trans) {
         platform.askHint(trans.complete, trans.error);
         trans.delayReturn(true);
      });
      this.chan.bind('platform.updateHeight', function (trans, height) {
         platform.updateHeight(height, trans.complete, trans.error);
         trans.delayReturn(true);
      });
      this.chan.bind('platform.openUrl', function (trans, url) {
         platform.openUrl(url, trans.complete, trans.error);
         trans.delayReturn(true);
      });
   };
}

Task.prototype.getSourceId = function() {
   return this.Id;
};

Task.prototype.getTargetUrl = function() {
   return this.iframe.attr('src');
};

Task.prototype.getTarget = function() {
   return this.iframe[0].contentWindow;
};

Task.prototype.getDomain = function() {
   var url = this.getTargetUrl();
   return url.substr(0, url.indexOf('/', 7));
};

/**
 * Task API functions
 */
Task.prototype.load = function(views, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.load",
      params: views,
      timeout: 5000,
      success: success,
      error: error
   });
};

Task.prototype.unload = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.unload",
      timeout: 1000,
      error: error,
      success: success
   });
};

Task.prototype.getHeight = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getHeight",
      timeout: 50,
      error: error,
      success: success
   });
};

Task.prototype.updateToken = function(token, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.updateToken",
      params: token,
      timeout: 10000,
      error: error,
      success: success
   });
};

Task.prototype.getMetaData = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getMetaData",
      timeout: 500,
      error: error,
      success: success
   });
};

Task.prototype.getAnswer = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getAnswer",
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.reloadAnswer = function(answer, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.reloadAnswer",
      params: answer,
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.getState = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getState",
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.reloadState = function(state, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.reloadState",
      params: state,
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.getViews = function(success, error) {
   if (!error) error = function() {console.error(arguments)};
   this.chan.call({method: "task.getViews",
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.showViews = function(views, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.showViews",
      params: views,
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.gradeAnswer = function(answer, answerToken, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.gradeAnswer",
      params: [answer, answerToken],
      error: error,
      success: success,
      timeout: 30000
   });
};

Task.prototype.getResources = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getResources",
      params: [],
      error: error,
      success: success,
      timeout: 30000
   });
};

// for grader.gradeTask
Task.prototype.gradeTask = Task.prototype.gradeAnswer;

/*
 * Platform object definition, created from a Task object (see below)
 */

function Platform(task) {
   this.task = task;
}

Platform.prototype.getTask = function() {
   return this.task;
};

/*
 * Simple prototypes for platform API functions, to be overriden by your
 * platform's specific functions (for each platform object)
 */

Platform.prototype.validate = function(mode, success, error) {error('platform.validate is not defined');};
Platform.prototype.showView = function(views, success, error) {error('platform.validate is not defined');};
Platform.prototype.askHint = function(platformToken, success, error) {error('platform.validate is not defined');};
Platform.prototype.updateHeight = function(height, success, error) {this.task.iframe.height(parseInt(height)+40);success();};
Platform.prototype.openUrl = function(url) {error('platform.openUrl is not defined!');};
Platform.prototype.getTaskParams = function(key, defaultValue, success, error) {
   var res = {minScore: -3, maxScore: 10, randomSeed: 0, noScore: 0, readOnly: false};
   if (typeof key !== 'undefined') {
      if (key !== 'options' && key in res) {
         return this.taskParams[key];
      } else {
         return (typeof defaultValue !== 'undefined') ? defaultValue : null;
      }
   }
   success(res);
};
<commit_msg>fix debug message<commit_after>"use strict";
/*
 * Cross-domain task proxy implementation for Bebras task API - v1.0 - 08/2014
 *
 * This file implements a "TaskProxyManager" object in the global scope so that
 * platforms using this file can just call
 * "myTask = TaskProxyManager.getTaskProxy(task_id)" to get the task object
 * associated to a task loaded in an iframe. Then they can just call
 * "myTask.myFunction()", with function of the API, the task object will take
 * care of message sending and receiving with the actual task.
 * 'task_id' here refers to the "id" attribute of the iframe in which a task is
 * loaded.
 *
 * It depends on jQuery (though this could be removed) and jschannel.
 *
 */

/**
 * Global objects
 */

var TaskProxyManager = {
   tasks: {},
   platforms: {},
   getRandomID: function() {
      var low = Math.floor(Math.random() * 922337203).toString();
      var high = Math.floor(Math.random() * 2000000000).toString();
      return high + low;
   },
   getTaskProxy: function(idFrame, callback, force) {
      if (TaskProxyManager.tasks[idFrame] && !force) {
         return TaskProxyManager.tasks[idFrame];
      } else {
         if (force) {
            TaskProxyManager.deleteTaskProxy(idFrame);
         }
         $('#'+idFrame).each(function() {
            TaskProxyManager.tasks[idFrame] = new Task($(this), function() {
               if (idFrame in TaskProxyManager.platforms) {
                  TaskProxyManager.tasks[idFrame].setPlatform(TaskProxyManager.platforms[idFrame]);
               }
               callback(TaskProxyManager.tasks[idFrame]);
            });
         });
      }
   },
   setPlatform: function(task, platform) {
      TaskProxyManager.platforms[task.Id] = platform;
      TaskProxyManager.tasks[task.Id].setPlatform(platform);
   },
   deleteTaskProxy: function(idFrame) {
      var task = TaskProxyManager.tasks[idFrame];
      if (task && task.chan) {
         task.chan.destroy();
      }
      delete(TaskProxyManager.tasks[idFrame]);
      delete(TaskProxyManager.platforms[idFrame]);
   },
   getUrl: function(taskUrl, sToken, sPlatform, prefix) {
      var channelId = (prefix ? prefix : '')+this.getRandomID();
      return taskUrl+'?sToken='+encodeURIComponent(sToken)+'&sPlatform='+encodeURIComponent(sPlatform)+'&channelId='+encodeURIComponent(channelId);
   }
};

TaskProxyManager.getGraderProxy = TaskProxyManager.getTaskProxy;

/**
 * Enable / Disable messages debug
 */
var platformDebug = false;

/*
 * Task object, created from an iframe DOM element
 */
function Task(iframe, callback) {
   this.iframe = iframe;
   this.Id = iframe.attr('id');
   function getUrlParameterByName(name, url) {
       var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
           results = regex.exec(url);
       return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
   }
   this.chan = Channel.build({
      window: iframe[0].contentWindow,
      origin: "*",
      scope: getUrlParameterByName('channelId', iframe[0].src),
      onReady: function() {
         callback();
      }
   });
   this.setPlatform = function(platform) {
      this.platform = platform;
      this.chan.bind('platform.validate', function (trans, mode) {
         platform.validate(mode, trans.complete, trans.error);
         trans.delayReturn(true);
         console.error('platform.validate with mode '+mode);
      });
      this.chan.bind('platform.getTaskParams', function (trans, keyDefault) {
         var key = keyDefault ? keyDefault[0] : undefined;
         var defaultValue = keyDefault ? keyDefault[1] : undefined;
         platform.getTaskParams(key, defaultValue, trans.complete, trans.error);
         trans.delayReturn(true);
      });
      this.chan.bind('platform.showView', function (trans, view) {
         platform.showView(view, trans.complete, trans.error);
         trans.delayReturn(true);
      });
      this.chan.bind('platform.askHint', function (trans) {
         platform.askHint(trans.complete, trans.error);
         trans.delayReturn(true);
      });
      this.chan.bind('platform.updateHeight', function (trans, height) {
         platform.updateHeight(height, trans.complete, trans.error);
         trans.delayReturn(true);
      });
      this.chan.bind('platform.openUrl', function (trans, url) {
         platform.openUrl(url, trans.complete, trans.error);
         trans.delayReturn(true);
      });
   };
}

Task.prototype.getSourceId = function() {
   return this.Id;
};

Task.prototype.getTargetUrl = function() {
   return this.iframe.attr('src');
};

Task.prototype.getTarget = function() {
   return this.iframe[0].contentWindow;
};

Task.prototype.getDomain = function() {
   var url = this.getTargetUrl();
   return url.substr(0, url.indexOf('/', 7));
};

/**
 * Task API functions
 */
Task.prototype.load = function(views, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.load",
      params: views,
      timeout: 5000,
      success: success,
      error: error
   });
};

Task.prototype.unload = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.unload",
      timeout: 1000,
      error: error,
      success: success
   });
};

Task.prototype.getHeight = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getHeight",
      timeout: 50,
      error: error,
      success: success
   });
};

Task.prototype.updateToken = function(token, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.updateToken",
      params: token,
      timeout: 10000,
      error: error,
      success: success
   });
};

Task.prototype.getMetaData = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getMetaData",
      timeout: 500,
      error: error,
      success: success
   });
};

Task.prototype.getAnswer = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getAnswer",
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.reloadAnswer = function(answer, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.reloadAnswer",
      params: answer,
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.getState = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getState",
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.reloadState = function(state, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.reloadState",
      params: state,
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.getViews = function(success, error) {
   if (!error) error = function() {console.error(arguments)};
   this.chan.call({method: "task.getViews",
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.showViews = function(views, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.showViews",
      params: views,
      error: error,
      success: success,
      timeout: 1000
   });
};

Task.prototype.gradeAnswer = function(answer, answerToken, success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.gradeAnswer",
      params: [answer, answerToken],
      error: error,
      success: success,
      timeout: 30000
   });
};

Task.prototype.getResources = function(success, error) {
   if (!error) error = function(errMsg) {console.error(errMsg)};
   this.chan.call({method: "task.getResources",
      params: [],
      error: error,
      success: success,
      timeout: 30000
   });
};

// for grader.gradeTask
Task.prototype.gradeTask = Task.prototype.gradeAnswer;

/*
 * Platform object definition, created from a Task object (see below)
 */

function Platform(task) {
   this.task = task;
}

Platform.prototype.getTask = function() {
   return this.task;
};

/*
 * Simple prototypes for platform API functions, to be overriden by your
 * platform's specific functions (for each platform object)
 */

Platform.prototype.validate = function(mode, success, error) {error('platform.validate is not defined');};
Platform.prototype.showView = function(views, success, error) {error('platform.validate is not defined');};
Platform.prototype.askHint = function(platformToken, success, error) {error('platform.validate is not defined');};
Platform.prototype.updateHeight = function(height, success, error) {this.task.iframe.height(parseInt(height)+40);success();};
Platform.prototype.openUrl = function(url) {error('platform.openUrl is not defined!');};
Platform.prototype.getTaskParams = function(key, defaultValue, success, error) {
   var res = {minScore: -3, maxScore: 10, randomSeed: 0, noScore: 0, readOnly: false};
   if (typeof key !== 'undefined') {
      if (key !== 'options' && key in res) {
         return this.taskParams[key];
      } else {
         return (typeof defaultValue !== 'undefined') ? defaultValue : null;
      }
   }
   success(res);
};
<|endoftext|>


<commit_before>/**
 * Analytics Settings form.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import {
	AccountSelect,
	AdsConversionIDTextField,
	AnonymizeIPSwitch,
	ExistingTagNotice,
	ProfileSelect,
	PropertySelect,
	TrackingExclusionSwitches,
	UseSnippetSwitch,
	ProfileNameTextField,
	ExistingGTMPropertyNotice,
} from '../common';
import StoreErrorNotices from '../../../../components/StoreErrorNotices';
import GA4Notice from '../common/GA4Notice';
import { STORE_NAME } from '../../datastore/constants';
const { useSelect } = Data;

export default function SettingsForm() {
	const hasExistingTag = useSelect( ( select ) => select( STORE_NAME ).hasExistingTag() );

	return (

			<GA4Notice />
			<StoreErrorNotices moduleSlug="analytics" storeName={ STORE_NAME } />
			<ExistingTagNotice />
			{ ! hasExistingTag && <ExistingGTMPropertyNotice /> }

				<AccountSelect />

				<PropertySelect />

				<ProfileSelect />

				<ProfileNameTextField />

				<UseSnippetSwitch />

				<AnonymizeIPSwitch />

				<TrackingExclusionSwitches />

				<AdsConversionIDTextField />

	);
}
<commit_msg>Add settings form updates.<commit_after>/**
 * Analytics Settings form.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import {
	AccountSelect,
	AdsConversionIDTextField,
	AnonymizeIPSwitch,
	ExistingTagNotice,
	ProfileSelect,
	PropertySelect,
	TrackingExclusionSwitches,
	UseSnippetSwitch,
	ProfileNameTextField,
	ExistingGTMPropertyNotice,
} from '../common';
import {
	PropertySelect as PropertySelect4,
} from '../../../analytics-4/components/common';
import { isFeatureEnabled } from '../../../../features';
import StoreErrorNotices from '../../../../components/StoreErrorNotices';
import GA4Notice from '../common/GA4Notice';
import { SETUP_FLOW_MODE_GA4_TRANSITIONAL, SETUP_FLOW_MODE_UA, STORE_NAME } from '../../datastore/constants';
import { MODULES_ANALYTICS_4, PROPERTY_CREATE } from '../../../analytics-4/datastore/constants';
import SettingsNotice, { TYPE_INFO } from '../../../../components/SettingsNotice';
import Link from '../../../../components/Link';
const { useSelect, useDispatch } = Data;

export default function SettingsForm() {
	const ga4Enabled = isFeatureEnabled( 'ga4setup' );
	const hasExistingTag = useSelect( ( select ) => select( STORE_NAME ).hasExistingTag() );
	const { selectProperty } = useDispatch( MODULES_ANALYTICS_4 );
	// const setupFlowMode = useSelect( ( select ) => select( STORE_NAME ).getSetupFlowMode() );
	// @TODO remove these, only for dev.
	const setupFlowMode = SETUP_FLOW_MODE_UA;
	// const setupFlowMode = SETUP_FLOW_MODE_GA4_TRANSITIONAL
	if ( ga4Enabled && SETUP_FLOW_MODE_UA === setupFlowMode ) {
		selectProperty( PROPERTY_CREATE );
	}

	return (

			<GA4Notice />
			<StoreErrorNotices moduleSlug="analytics" storeName={ STORE_NAME } />
			<ExistingTagNotice />
			{ ! hasExistingTag && <ExistingGTMPropertyNotice /> }

				<AccountSelect />

				<PropertySelect />

				<ProfileSelect />

			{
				ga4Enabled && SETUP_FLOW_MODE_GA4_TRANSITIONAL === setupFlowMode && (
					<SettingsNotice type={ TYPE_INFO }>

							{ __( 'You\'ll need to connect the Google Analytics 4 property that\'s associated with this Universal Analytics property', 'google-site-kit' ) }

							<PropertySelect4 />

						<Link
							href="https://sitekit.withgoogle.com/documentation/ga4-analytics-property/"
							external
							inherit
						>
							{ __( 'Learn more here.', 'google-site-kit' ) }
						</Link>
					</SettingsNotice>
				)
			}
			{
				ga4Enabled && SETUP_FLOW_MODE_UA === setupFlowMode && (
					<SettingsNotice type={ TYPE_INFO }>
						{ __( 'A Google Analytics 4 property will also be created.', 'google-site-kit' ) }
						<Link
							href="https://sitekit.withgoogle.com/documentation/ga4-analytics-property/"
							external
							inherit
						>
							{ __( 'Learn more here.', 'google-site-kit' ) }
						</Link>
					</SettingsNotice>
				)
			}

				<ProfileNameTextField />

				<UseSnippetSwitch />

				<AnonymizeIPSwitch />

				<TrackingExclusionSwitches />

				<AdsConversionIDTextField />

	);
}
<|endoftext|>