<commit_before>// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * This file contains helpers to load the correct path to various scripts and
 * directories. It is the Node equivalent of devtools_paths.py.
 *
 * Note that not all paths implemented in devtools_paths.py are implemented
 * here. Please add any paths you need that are missing.
 */

const path = require('path');
const os = require('os');

/**
 * You would think we can use __filename here but we cannot because __filename
 * has any symlinks resolved. This means we can't use it to tell if the user is
 * using the external repo with a standalone build setup because the symlink
 * from chromium/src/third_party/devtools-frontend => devtools-frontend repo
 * gets resolved by Node before it gives us __filename.
 *
 * We can use process.argv[1], which is the path to the file currently being
 * executed without any symlinks resolution. If we assume that file is always in
 * the devtools-frontend repository/directory, we can use that file as the
 * starting point for figuring out if we're in Chromium or not. until we find
 * the scripts directory, at which point we've found this file and can use it
 * for all subsequent logic.
 *
 * e.g. the user executes a script: scripts/test/run_lint_check_css.js
 *
 * process.argv[1] =
 * /full/path/devtools-frontend/src/scripts/test/run_lint_check_css.js
 */
const PATH_TO_EXECUTED_FILE = process.argv[1];

const _lookUpCaches = new Map(
    [['chromium', null]],
);
/**
 * This function figures out if we're within a chromium directory, and therefore
 * we are in the integrated workflow mode, rather than working in a standalone
 * devtools-frontend repository.
 */
function isInChromiumDirectory() {
  const cached = _lookUpCaches.get('chromium');
  if (cached) {
    return cached;
  }

  const normalizedPath = PATH_TO_EXECUTED_FILE.split(path.sep).join('/');
  const devtoolsPath = 'src/third_party/devtools-frontend';
  const isInChromium = normalizedPath.includes(devtoolsPath);
  const potentialChromiumDir = PATH_TO_EXECUTED_FILE.substring(0, PATH_TO_EXECUTED_FILE.indexOf(devtoolsPath));
  const result = {isInChromium, chromiumDirectory: potentialChromiumDir};
  _lookUpCaches.set('chromium', result);
  return result;
}
/**
 * Returns the path to the root of the devtools-frontend repository.
 *
 * If we're in Chromium, this will be /path/to/chromium/src/third_party/devtools-frontend/src
 * If it's standalone, it will be /path/to/devtools-frontend
 */
function devtoolsRootPath() {
  return path.dirname(path.dirname(__filename));
}

/**
 * Returns the path to the root of the main repository we're in.
 * if we're in Chromium, this is /path/to/chromium/src
 * if we're in standalone, this is /path/to/devtools-frontend
 *
 * Note this is different to devtoolsRootPath(), which always returns the path
 * to the devtools-frontend source code.
 */
function rootPath() {
  const {isInChromium, chromiumDirectory} = isInChromiumDirectory();
  if (isInChromium) {
    return path.join(chromiumDirectory, 'src');
  }
  return devtoolsRootPath();
}

/**
 * Path to the third_party directory. Used because if we're running in Chromium
 * land we need to use e.g. the Node executable from Chromium's third_party
 * directory, not from the devtools-frontend third_party directory.
 */
function thirdPartyPath() {
  return path.join(rootPath(), 'third_party');
}

function nodePath() {
  const paths = {
    'darwin': path.join('mac', 'node-darwin-x64', 'bin', 'node'),
    'linux': path.join('linux', 'node-linux-x64', 'bin', 'node'),
    'win32': path.join('win', 'node.exe'),
  };
  return path.join(thirdPartyPath(), 'node', paths[os.platform()]);
}

/**
 * The path to the devtools-frontend node_modules folder.
 */
function nodeModulesPath() {
  return path.join(devtoolsRootPath(), 'node_modules');
}

function stylelintExecutablePath() {
  return path.join(nodeModulesPath(), 'stylelint', 'bin', 'stylelint.js');
}

function mochaExecutablePath() {
  return path.join(nodeModulesPath(), 'mocha', 'bin', 'mocha');
}

function downloadedChromeBinaryPath() {
  const paths = {
    'linux': path.join('chrome-linux', 'chrome'),
    'darwin': path.join('chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'),
    'win32': path.join('chrome-win', 'chrome.exe'),
  };
  return path.join(thirdPartyPath(), 'chrome', paths[os.platform()]);
}

module.exports = {
  thirdPartyPath,
  nodePath,
  devtoolsRootPath,
  nodeModulesPath,
  mochaExecutablePath,
  stylelintExecutablePath,
  downloadedChromeBinaryPath
};
<commit_msg>use __dirname<commit_after>// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * This file contains helpers to load the correct path to various scripts and
 * directories. It is the Node equivalent of devtools_paths.py.
 *
 * Note that not all paths implemented in devtools_paths.py are implemented
 * here. Please add any paths you need that are missing.
 */

const path = require('path');
const os = require('os');

/**
 * You would think we can use __filename here but we cannot because __filename
 * has any symlinks resolved. This means we can't use it to tell if the user is
 * using the external repo with a standalone build setup because the symlink
 * from chromium/src/third_party/devtools-frontend => devtools-frontend repo
 * gets resolved by Node before it gives us __filename.
 *
 * We can use process.argv[1], which is the path to the file currently being
 * executed without any symlinks resolution. If we assume that file is always in
 * the devtools-frontend repository/directory, we can use that file as the
 * starting point for figuring out if we're in Chromium or not. until we find
 * the scripts directory, at which point we've found this file and can use it
 * for all subsequent logic.
 *
 * e.g. the user executes a script: scripts/test/run_lint_check_css.js
 *
 * process.argv[1] =
 * /full/path/devtools-frontend/src/scripts/test/run_lint_check_css.js
 */
const PATH_TO_EXECUTED_FILE = process.argv[1];

const _lookUpCaches = new Map(
    [['chromium', null]],
);
/**
 * This function figures out if we're within a chromium directory, and therefore
 * we are in the integrated workflow mode, rather than working in a standalone
 * devtools-frontend repository.
 */
function isInChromiumDirectory() {
  const cached = _lookUpCaches.get('chromium');
  if (cached) {
    return cached;
  }

  const normalizedPath = PATH_TO_EXECUTED_FILE.split(path.sep).join('/');
  const devtoolsPath = 'src/third_party/devtools-frontend';
  const isInChromium = normalizedPath.includes(devtoolsPath);
  const potentialChromiumDir = PATH_TO_EXECUTED_FILE.substring(0, PATH_TO_EXECUTED_FILE.indexOf(devtoolsPath));
  const result = {isInChromium, chromiumDirectory: potentialChromiumDir};
  _lookUpCaches.set('chromium', result);
  return result;
}
/**
 * Returns the path to the root of the devtools-frontend repository.
 *
 * If we're in Chromium, this will be /path/to/chromium/src/third_party/devtools-frontend/src
 * If it's standalone, it will be /path/to/devtools-frontend
 */
function devtoolsRootPath() {
  return path.dirname(__dirname);
}

/**
 * Returns the path to the root of the main repository we're in.
 * if we're in Chromium, this is /path/to/chromium/src
 * if we're in standalone, this is /path/to/devtools-frontend
 *
 * Note this is different to devtoolsRootPath(), which always returns the path
 * to the devtools-frontend source code.
 */
function rootPath() {
  const {isInChromium, chromiumDirectory} = isInChromiumDirectory();
  if (isInChromium) {
    return path.join(chromiumDirectory, 'src');
  }
  return devtoolsRootPath();
}

/**
 * Path to the third_party directory. Used because if we're running in Chromium
 * land we need to use e.g. the Node executable from Chromium's third_party
 * directory, not from the devtools-frontend third_party directory.
 */
function thirdPartyPath() {
  return path.join(rootPath(), 'third_party');
}

function nodePath() {
  const paths = {
    'darwin': path.join('mac', 'node-darwin-x64', 'bin', 'node'),
    'linux': path.join('linux', 'node-linux-x64', 'bin', 'node'),
    'win32': path.join('win', 'node.exe'),
  };
  return path.join(thirdPartyPath(), 'node', paths[os.platform()]);
}

/**
 * The path to the devtools-frontend node_modules folder.
 */
function nodeModulesPath() {
  return path.join(devtoolsRootPath(), 'node_modules');
}

function stylelintExecutablePath() {
  return path.join(nodeModulesPath(), 'stylelint', 'bin', 'stylelint.js');
}

function mochaExecutablePath() {
  return path.join(nodeModulesPath(), 'mocha', 'bin', 'mocha');
}

function downloadedChromeBinaryPath() {
  const paths = {
    'linux': path.join('chrome-linux', 'chrome'),
    'darwin': path.join('chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'),
    'win32': path.join('chrome-win', 'chrome.exe'),
  };
  return path.join(thirdPartyPath(), 'chrome', paths[os.platform()]);
}

module.exports = {
  thirdPartyPath,
  nodePath,
  devtoolsRootPath,
  nodeModulesPath,
  mochaExecutablePath,
  stylelintExecutablePath,
  downloadedChromeBinaryPath
};
<|endoftext|>


<commit_before>// code for making app install buttons and their interactions

// utility logging function for updates
function installLog(inMessage) {
	console.log(inMessage);
	$('#progress').text(inMessage);
}

// global dictionary of app records
var appRecordsByManifest = {};

// install() or installPackage() succeeded
// start tracking download events
function installSuccess(e) {
	installLog('success');
	$('button').off('click');
	console.log('disabled click handlers');

	// add the newly installed app to appRecordsByManifest
	var appRecord = this.result;
	appRecordsByManifest[appRecord.manifestURL] = appRecord;

	$('.installButton').click(launchButtonEventHandler);
	console.log('enabled launch handler');
	$('.installButton').html('Launch');

	console.log(appRecord);
	appRecord.ondownloaderror = function(e) {
		installLog('download error: ' + appRecord.downloadError.name);
		$('.installButton').addClass('btn-danger');
	}
	appRecord.ondownloadsuccess = function(e) {
		installLog('download succeeded');
	}
}

// install() or installPackage() failed
function installFail(e) {
	installLog('install failed: ' + this.error.name);
	$('.installButton').addClass('btn-danger');
}

// when clicking on launch button
// get the App object for that manifest and launch it
function launchButtonEventHandler(e) {
	installLog("clicked launch");
	var url = '';

	if (e.target.getAttribute("data-manifest-url")) {
		url = e.target.getAttribute("data-manifest-url");
	} else if (e.target.getAttribute("data-package-manifest-url")) {
		url = e.target.getAttribute("data-package-manifest-url");
	} else {
		installLog("ERROR: found neither data-packaged-manifest-url nor data-manifest-url");
	}

	if (appRecordsByManifest[url]) {
		installLog('launching');
		appRecordsByManifest[url].launch();
		installLog('launched');
	} else {
		installLog('manifest not found');
	}
}

function installButtonEventHandler(e) {
	installLog("clicked install");

	if (e.target.getAttribute("data-manifest-url")) {
		var url = e.target.getAttribute("data-manifest-url");

		var request = navigator.mozApps.install(url);
		request.onsuccess = installSuccess;
		request.onerror = installFail;

	} else if (e.target.getAttribute("data-package-manifest-url")) {
		var url = e.target.getAttribute("data-package-manifest-url");

		var request = navigator.mozApps.installPackage(url);
		request.onsuccess = installSuccess;
		request.onerror = installFail;

	} else {
		installLog("ERROR: found neither data-packaged-manifest-url nor data-manifest-url");
	}
}

function wireUpInstallButtons(installedManifestURLs) {
	console.log('wiring up install buttons');
	console.log(installedManifestURLs);

	$('.installButton').each(function(index) {
		if ($(this).attr('data-manifest-url') && installedManifestURLs.indexOf($(this).attr('data-manifest-url')) >= 0) {
			console.log("hosted app already installed");
			$(this).click(launchButtonEventHandler);
			$(this).attr('value', 'Launch');
		} else if ($(this).attr('data-package-manifest-url') && installedManifestURLs.indexOf($(this).attr('data-package-manifest-url')) >= 0) {
			console.log("packaged app already installed");
			$(this).click(launchButtonEventHandler);
			$(this).attr('value', 'Launch');
		} else {
			$(this).click(installButtonEventHandler);
		}
	});
}

// Stuff to do when the page loads

$(document).ready(function() {
	// Either retrieve the manifest URL's of all installed apps or disable all install buttons

	// var installedManifestURLs = [];

	// if (window.navigator.mozApps && window.navigator.mozApps.getInstalled) {
	// 	var installListRequest = window.navigator.mozApps.getInstalled();
	// 	installListRequest.onerror = function(e) {
	// 		alert("Error calling getInstalled: " + installListRequest.error.name);

	// 		wireUpInstallButtons([]);
	// 	};

	// 	installListRequest.onsuccess = function(e) {
	// 		for (var installListIndex = 0; installListIndex < installListRequest.result.length; installListIndex++) {
	// 			var manifestURL = installListRequest.result[installListIndex].manifestURL;
	// 			installedManifestURLs.push(manifestURL);
	// 			appRecordsByManifest[manifestURL] = installListRequest.result[installListIndex];
	// 			$('#installed-app-list').append(installListRequest.result[installListIndex].manifest.name + '<br>');
	// 		}

	// 		wireUpInstallButtons(installedManifestURLs);
	// 	};
	// } else {
	// 	$('.installButton').attr("disabled", "disabled");
	// }

	// set up table sorting behavior

	// $('.tablesorter-table').tablesorter({
	//     theme : 'blue',

	//     headers: { 0: { sorter: false }, 1: { sorter: true }, 4: { sorter: false } },

	//     // header layout template; {icon} needed for some themes
	//     headerTemplate : '{content}{icon}',

	//     // initialize column styling of the table
	//     widgets : ["columns"],
	//     widgetOptions : {
	// 		// change the default column class names
	// 		// primary is the first column sorted, secondary is the second, etc
	// 		columns : [ "primary", "secondary", "tertiary" ]
	//     }
	// });

});<commit_msg>remove unused code<commit_after>// code for making app install buttons and their interactions

// utility logging function for updates
function installLog(inMessage) {
	console.log(inMessage);
	$('#progress').text(inMessage);
}

// global dictionary of app records
var appRecordsByManifest = {};

// install() or installPackage() succeeded
// start tracking download events
function installSuccess(e) {
	installLog('success');
	$('button').off('click');
	console.log('disabled click handlers');

	// add the newly installed app to appRecordsByManifest
	var appRecord = this.result;
	appRecordsByManifest[appRecord.manifestURL] = appRecord;

	$('.installButton').click(launchButtonEventHandler);
	console.log('enabled launch handler');
	$('.installButton').html('Launch');

	console.log(appRecord);
	appRecord.ondownloaderror = function(e) {
		installLog('download error: ' + appRecord.downloadError.name);
		$('.installButton').addClass('btn-danger');
	}
	appRecord.ondownloadsuccess = function(e) {
		installLog('download succeeded');
	}
}

// install() or installPackage() failed
function installFail(e) {
	installLog('install failed: ' + this.error.name);
	$('.installButton').addClass('btn-danger');
}

// when clicking on launch button
// get the App object for that manifest and launch it
function launchButtonEventHandler(e) {
	installLog("clicked launch");
	var url = '';

	if (e.target.getAttribute("data-manifest-url")) {
		url = e.target.getAttribute("data-manifest-url");
	} else if (e.target.getAttribute("data-package-manifest-url")) {
		url = e.target.getAttribute("data-package-manifest-url");
	} else {
		installLog("ERROR: found neither data-packaged-manifest-url nor data-manifest-url");
	}

	if (appRecordsByManifest[url]) {
		installLog('launching');
		appRecordsByManifest[url].launch();
		installLog('launched');
	} else {
		installLog('manifest not found');
	}
}

function installButtonEventHandler(e) {
	installLog("clicked install");

	if (e.target.getAttribute("data-manifest-url")) {
		var url = e.target.getAttribute("data-manifest-url");

		var request = navigator.mozApps.install(url);
		request.onsuccess = installSuccess;
		request.onerror = installFail;

	} else if (e.target.getAttribute("data-package-manifest-url")) {
		var url = e.target.getAttribute("data-package-manifest-url");

		var request = navigator.mozApps.installPackage(url);
		request.onsuccess = installSuccess;
		request.onerror = installFail;

	} else {
		installLog("ERROR: found neither data-packaged-manifest-url nor data-manifest-url");
	}
}

function wireUpInstallButtons(installedManifestURLs) {
	console.log('wiring up install buttons');
	console.log(installedManifestURLs);

	$('.installButton').each(function(index) {
		if ($(this).attr('data-manifest-url') && installedManifestURLs.indexOf($(this).attr('data-manifest-url')) >= 0) {
			console.log("hosted app already installed");
			$(this).click(launchButtonEventHandler);
			$(this).attr('value', 'Launch');
		} else if ($(this).attr('data-package-manifest-url') && installedManifestURLs.indexOf($(this).attr('data-package-manifest-url')) >= 0) {
			console.log("packaged app already installed");
			$(this).click(launchButtonEventHandler);
			$(this).attr('value', 'Launch');
		} else {
			$(this).click(installButtonEventHandler);
		}
	});
}

// Stuff to do when the page loads

$(document).ready(function() {
	// Either retrieve the manifest URL's of all installed apps or disable all install buttons

	// set up table sorting behavior

	// $('.tablesorter-table').tablesorter({
	//     theme : 'blue',

	//     headers: { 0: { sorter: false }, 1: { sorter: true }, 4: { sorter: false } },

	//     // header layout template; {icon} needed for some themes
	//     headerTemplate : '{content}{icon}',

	//     // initialize column styling of the table
	//     widgets : ["columns"],
	//     widgetOptions : {
	// 		// change the default column class names
	// 		// primary is the first column sorted, secondary is the second, etc
	// 		columns : [ "primary", "secondary", "tertiary" ]
	//     }
	// });

});<|endoftext|>


<commit_before>/*
 * Say Cheese!
 * Lee Machin, 2012
 * http://leemach.in, http://new-bamboo.co.uk
 *
 * Minimal javascript library for integrating a webcam and snapshots into your app.
 *
 * Handles starting up the webcam and rendering the element, and also capturing shots
 * in a separate canvas element.
 *
 * Depends on video and canvas, and of course, getUserMedia. It's unlikely to work
 * on anything but the newest browsers.
 */
(function() {

  /* Check for the existence of the userMedia feature. */
  function userMediaFeatureExists() {
    return 'getUserMedia' in navigator ||  'webkitGetUserMedia' in navigator;
  };

  var SayCheese = (function() {

    function SayCheese() {
      if (userMediaFeatureExists()) {
        // do something
      } else {
        // should make this more graceful in future
        throw new Error("getUserMedia() is not supported in this browser");
      }

      return this;
    };

    // the getUserMedia function is different on Webkit browsers, so we have to
    // do a bit of faffing about to make sure we call the right one.
    SayCheese.prototype.getUserMedia = function getUserMedia(success, error) {
      userMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia);
      userMedia.call({ video: true }, success, error).apply(this);
    };

    /* The viewfinder is the element we use to preview the webcam stream */
    SayCheese.prototype.createVideo = function() {
      element = document.createElement('video');
      element.autoplay = true;
      return element;
    };

    /* The canvas is used for taking 'photos' */
    SayCheese.prototype.createCanvas = function() {
      element = document.createElement('canvas');
      return element;
    };

    SayCheese.prototype.start = function start() {

      var success = function userMediaSuccess(stream) {
        console.log('woop woop', stream);
      };

      var error = function userMediaError() {
        console.log('nooooooooo');
      };

      this.getUserMedia(success, error);
    };

    SayCheese.prototype.stop = function stop() {

    };

    SayCheese.prototype.takeSnapshot = function takeSnapshot() {

    };

    return SayCheese;

  })();

}).call(this);<commit_msg>fixed illegal invocation error, did some other mucking about<commit_after>/*
 * Say Cheese!
 * Lee Machin, 2012
 * http://leemach.in, http://new-bamboo.co.uk
 *
 * Minimal javascript library for integrating a webcam and snapshots into your app.
 *
 * Handles starting up the webcam and rendering the element, and also capturing shots
 * in a separate canvas element.
 *
 * Depends on video and canvas, and of course, getUserMedia. It's unlikely to work
 * on anything but the newest browsers.
 */
(function() {

  var SayCheese;

  /* Check for the existence of the userMedia feature. */
  function userMediaFeatureExists() {
    return 'getUserMedia' in navigator ||  'webkitGetUserMedia' in navigator;
  };

  SayCheese = function SayCheese() {
    if (userMediaFeatureExists()) {
      // do something
    } else {
      // should make this more graceful in future
      throw new Error("getUserMedia() is not supported in this browser");
    }

    return this;
  };

  // the getUserMedia function is different on Webkit browsers, so we have to
  // do a bit of faffing about to make sure we call the right one.
  SayCheese.prototype.getUserMedia = function getUserMedia(success, error) {
    return (function() {
      // have to re-bind navigator because the context will be lost, and
      // we'll get illegal invocation errors.
      return (navigator.getUserMedia || navigator.webkitGetUserMedia).bind(navigator)
    })().call(this, { video: true }, success, error);
  };

  /* The viewfinder is the element we use to preview the webcam stream */
  SayCheese.prototype.createVideo = function() {
    element = document.createElement('video');
    element.autoplay = true;
    return element;
  };

  /* The canvas is used for taking 'photos' */
  SayCheese.prototype.createCanvas = function() {
    element = document.createElement('canvas');
    return element;
  };

  SayCheese.prototype.start = function start() {
    console.log('testing');

    var success = function userMediaSuccess(stream) {
      console.log('woop woop', stream);
    };

    var error = function userMediaError() {
      console.log('nooooooooo');
    };

    this.getUserMedia(success, error);
  };

  SayCheese.prototype.stop = function stop() {

  };

  SayCheese.prototype.takeSnapshot = function takeSnapshot() {

  };

}).call(this);<|endoftext|>


<commit_before>/*
 * Say Cheese!
 * Lee Machin, 2012
 * http://leemach.in, http://new-bamboo.co.uk
 *
 * Minimal javascript library for integrating a webcam and snapshots into your app.
 *
 * Handles starting up the webcam and rendering the element, and also capturing shots
 * in a separate canvas element.
 *
 * Depends on video and canvas, and of course, getUserMedia. It's unlikely to work
 * on anything but the newest browsers.
 */

var SayCheese = (function($) {

  var SayCheese;

  /* Check for the existence of the userMedia feature. */
  function userMediaFeatureExists() {
    return 'getUserMedia' in navigator ||  'webkitGetUserMedia' in navigator;
  };

  function eventCoords(evt) {
     return { x: evt.offsetX || evt.layerX, y: evt.offsetY || evt.layerY };
  };

  SayCheese = function SayCheese(element) {
    if (userMediaFeatureExists()) {

      this.viewfinder = {},
      this.snapshots = [],
      this.canvas = null,
      this.context = null,
      this.video = null,
      this.events = {};

      this.element = document.querySelectorAll(element)[0];
      this.element.style.position = 'relative';
    } else {
      // should make this more graceful in future
      throw new Error("getUserMedia() is not supported in this browser");
    }

    return this;
  };

  /**
   * Reimplementing events? No. This is intended to make it easier to
   * replace jQuery with a different solution in future, should that
   * become necessary, and also minimises the impact of the framework
   * on the rest of the code.
   */
  SayCheese.prototype.on = function on(evt, handler) {
    return $(this).on(evt, handler);
  };

  SayCheese.prototype.off = function off(evt, handler) {
    return $(this).off(evt, handler);
  };

  SayCheese.prototype.trigger = function trigger(evt, data) {
    // bubbling up the DOM makes things go a bit crazy. This assumes
    // preventDefault
    return $(this).triggerHandler(evt, data);
  };

  /*
   * the getUserMedia function is different on Webkit browsers, so we have to
   * do a bit of faffing about to make sure we call the right one.
   */
  SayCheese.prototype.getUserMedia = function getUserMedia(success, error) {
    return (function() {
      // have to re-bind navigator because the context will be lost, and
      // we'll get illegal invocation errors.
      return (navigator.getUserMedia || navigator.webkitGetUserMedia).bind(navigator);
    })().call(this, { video: true }, success, error);
  };

  /*
   * Webkit behaves differently as regards getting a proper video URL. So we have
   * to have another check for it.
   */
  SayCheese.prototype.getStreamUrl = function getStreamUrl(stream) {
    url = (function() {
      return (window.URL || window.webkitURL);
    })();

    return (url && url.createObjectURL) ? url.createObjectURL(stream) : stream;
  };

  SayCheese.prototype.createVideo = function createVideo() {
    this.video = document.createElement('video');
    this.video.autoplay = true;
  };

  SayCheese.prototype.setupCanvas = function setupCanvas() {
    this.canvas = document.createElement('canvas');
    this.canvas.width = this.video.offsetWidth;
    this.canvas.height = this.video.offsetHeight;

    this.canvas.style.position = 'absolute';
    this.canvas.style.top = this.video.offsetTop;
    this.canvas.style.left = this.video.offsetLeft;

    this.context = this.canvas.getContext('2d');

    this.element.appendChild(this.canvas);
    this.initDefaultViewfinder();
    this.initDynamicViewfinder();

    // we're now all set up, so dispatch the ready event
    return this.trigger('start');
  };

  SayCheese.prototype.watermark = function watermark() {
    this.context.fillStyle = '#ee5f00';
    this.context.font = 'bold 32px Helvetica';

    x = this.video.offsetWidth - 100;
    y = this.video.offsetHeight - 15;

    this.context.fillText('demo', x, y);
  };

  /*
   * The default viewfinder is just the exact size of the video
   */
  SayCheese.prototype.initDefaultViewfinder = function initDefaultViewfinder() {
    return this.viewfinder = {
      startX: 0,
      startY: 0,
      width: this.video.offsetWidth,
      height: this.video.offsetHeight
    };
  };

  /*
   *  This viewfinder can be resized to capture select portions of the video stream
   */
  SayCheese.prototype.initDynamicViewfinder = function initDynamicViewfinder() {
    // track the dragging status when events are fired
    var isDragging = false,
        box = {};

    var start = function start(evt) {
      evt.preventDefault();
      var coords = eventCoords(evt);
      box.startX = coords.x;
      box.startY = coords.y;
      isDragging = true;
    }.bind(this);

    var stop = function stop(evt) {
      evt.preventDefault();
      isDragging = false;
      this.viewfinder = box;
      this.trigger('change');
    }.bind(this);

    var draw = function draw(evt) {
      evt.preventDefault();
      var coords = eventCoords(evt);
      if (isDragging) {
        box.width = coords.x - box.startX,
        box.height = coords.y - box.startY;

        // draw the shade
        this.context.globalCompositeOperation = 'xor';
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
        this.context.fillStyle = 'rgba(0, 0, 0, .8)';
        this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);

        // draw the window
        this.context.strokeStyle = 'rgba(255, 255, 255, .5)';
        this.context.lineWidth = 2;
        this.context.strokeRect(box.startX, box.startY, box.width, box.height);
        this.context.fillRect(box.startX, box.startY, box.width, box.height);
      }
    }.bind(this);

    this.canvas.addEventListener('mousedown', start, true);
    this.canvas.addEventListener('mouseup', stop, true);
    this.canvas.addEventListener('mousemove', draw, true);

    // add touch events if they're there
    if ('ontouchstart' in window) {
      this.canvas.addEventListener('touchstart', start, true);
      this.canvas.addEventListener('touchend', stop, true);
      this.canvas.addEventListener('touchmove', draw, true);
    }

    // make the cursor a crosshair to make it more clear what can be done
    this.canvas.style.cursor = 'crosshair';
  };

  SayCheese.prototype.resetViewfinder = function() {
    this.context.globalCompositeOperation = 'source-over';
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);

    this.viewfinder = {
      startX: 0,
      startY: 0,
      width: this.videoWidth,
      height: this.videoHeight
    }

    this.trigger('change');
  };

  /* Take a snapshot of the current state of the stream */
  SayCheese.prototype.takeSnapshot = function takeSnapshot(callback) {
    var snapshot = document.createElement('canvas'),
        ctx      = snapshot.getContext('2d');

    snapshot.width  = Math.abs(this.viewfinder.width),
    snapshot.height = Math.abs(this.viewfinder.height);

    ctx.drawImage(this.video,
                       this.viewfinder.startX,
                       this.viewfinder.startY,
                       this.viewfinder.width,
                       this.viewfinder.height,
                       0,
                       0,
                       this.viewfinder.width,
                       this.viewfinder.height);

    this.snapshots.push(snapshot);
    this.trigger('snapshot', snapshot);

    if (callback) {
      callback.call(this, snapshot);
    }

    ctx = null;
  };

  /* Start up the stream, if possible */
  SayCheese.prototype.start = function start(callback) {
    var success = function success(stream) {
      this.createVideo();

      // video width and height don't exist until metadata is loaded
      this.video.addEventListener('loadedmetadata', this.setupCanvas.bind(this), false);

      this.video.src = this.getStreamUrl(stream);
      this.element.appendChild(this.video);
    }.bind(this);

    /* error is also called when someone denies access */
    var error = function error() {
      this.trigger('error', arguments);
    }.bind(this);

    // add the callback to the start event if one is supplied.
    if (callback) {
      this.on('start', callback);
    }

    this.getUserMedia(success, error);
  };

  /* Stop it - TODO: figure out how to actually disable the stream */
  SayCheese.prototype.stop = function stop() {
    this.video = null;
    document.body.removeChild(video);
  };

  return SayCheese;

})($);
<commit_msg>fix indentation<commit_after>/*
 * Say Cheese!
 * Lee Machin, 2012
 * http://leemach.in, http://new-bamboo.co.uk
 *
 * Minimal javascript library for integrating a webcam and snapshots into your app.
 *
 * Handles starting up the webcam and rendering the element, and also capturing shots
 * in a separate canvas element.
 *
 * Depends on video and canvas, and of course, getUserMedia. It's unlikely to work
 * on anything but the newest browsers.
 */

var SayCheese = (function($) {

  var SayCheese;

  /* Check for the existence of the userMedia feature. */
  function userMediaFeatureExists() {
    return 'getUserMedia' in navigator ||  'webkitGetUserMedia' in navigator;
  };

  function eventCoords(evt) {
     return { x: evt.offsetX || evt.layerX, y: evt.offsetY || evt.layerY };
  };

  SayCheese = function SayCheese(element) {
    if (userMediaFeatureExists()) {

      this.viewfinder = {},
      this.snapshots = [],
      this.canvas = null,
      this.context = null,
      this.video = null,
      this.events = {};

      this.element = document.querySelectorAll(element)[0];
      this.element.style.position = 'relative';
    } else {
      // should make this more graceful in future
      throw new Error("getUserMedia() is not supported in this browser");
    }

    return this;
  };

  /**
   * Reimplementing events? No. This is intended to make it easier to
   * replace jQuery with a different solution in future, should that
   * become necessary, and also minimises the impact of the framework
   * on the rest of the code.
   */
  SayCheese.prototype.on = function on(evt, handler) {
    return $(this).on(evt, handler);
  };

  SayCheese.prototype.off = function off(evt, handler) {
    return $(this).off(evt, handler);
  };

  SayCheese.prototype.trigger = function trigger(evt, data) {
    // bubbling up the DOM makes things go a bit crazy. This assumes
    // preventDefault
    return $(this).triggerHandler(evt, data);
  };

  /*
   * the getUserMedia function is different on Webkit browsers, so we have to
   * do a bit of faffing about to make sure we call the right one.
   */
  SayCheese.prototype.getUserMedia = function getUserMedia(success, error) {
    return (function() {
      // have to re-bind navigator because the context will be lost, and
      // we'll get illegal invocation errors.
      return (navigator.getUserMedia || navigator.webkitGetUserMedia).bind(navigator);
    })().call(this, { video: true }, success, error);
  };

  /*
   * Webkit behaves differently as regards getting a proper video URL. So we have
   * to have another check for it.
   */
  SayCheese.prototype.getStreamUrl = function getStreamUrl(stream) {
    url = (function() {
      return (window.URL || window.webkitURL);
    })();

    return (url && url.createObjectURL) ? url.createObjectURL(stream) : stream;
  };

  SayCheese.prototype.createVideo = function createVideo() {
    this.video = document.createElement('video');
    this.video.autoplay = true;
  };

  SayCheese.prototype.setupCanvas = function setupCanvas() {
    this.canvas = document.createElement('canvas');
    this.canvas.width = this.video.offsetWidth;
    this.canvas.height = this.video.offsetHeight;

    this.canvas.style.position = 'absolute';
    this.canvas.style.top = this.video.offsetTop;
    this.canvas.style.left = this.video.offsetLeft;

    this.context = this.canvas.getContext('2d');

    this.element.appendChild(this.canvas);
    this.initDefaultViewfinder();
    this.initDynamicViewfinder();

    // we're now all set up, so dispatch the ready event
    return this.trigger('start');
  };

  SayCheese.prototype.watermark = function watermark() {
    this.context.fillStyle = '#ee5f00';
    this.context.font = 'bold 32px Helvetica';

    x = this.video.offsetWidth - 100;
    y = this.video.offsetHeight - 15;

    this.context.fillText('demo', x, y);
  };

  /*
   * The default viewfinder is just the exact size of the video
   */
  SayCheese.prototype.initDefaultViewfinder = function initDefaultViewfinder() {
    return this.viewfinder = {
      startX: 0,
      startY: 0,
      width: this.video.offsetWidth,
      height: this.video.offsetHeight
    };
  };

  /*
   *  This viewfinder can be resized to capture select portions of the video stream
   */
  SayCheese.prototype.initDynamicViewfinder = function initDynamicViewfinder() {
    // track the dragging status when events are fired
    var isDragging = false,
        box = {};

    var start = function start(evt) {
      evt.preventDefault();
      var coords = eventCoords(evt);
      box.startX = coords.x;
      box.startY = coords.y;
      isDragging = true;
    }.bind(this);

    var stop = function stop(evt) {
      evt.preventDefault();
      isDragging = false;
      this.viewfinder = box;
      this.trigger('change');
    }.bind(this);

    var draw = function draw(evt) {
      evt.preventDefault();
      var coords = eventCoords(evt);
      if (isDragging) {
        box.width = coords.x - box.startX,
        box.height = coords.y - box.startY;

        // draw the shade
        this.context.globalCompositeOperation = 'xor';
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
        this.context.fillStyle = 'rgba(0, 0, 0, .8)';
        this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);

        // draw the window
        this.context.strokeStyle = 'rgba(255, 255, 255, .5)';
        this.context.lineWidth = 2;
        this.context.strokeRect(box.startX, box.startY, box.width, box.height);
        this.context.fillRect(box.startX, box.startY, box.width, box.height);
      }
    }.bind(this);

    this.canvas.addEventListener('mousedown', start, true);
    this.canvas.addEventListener('mouseup', stop, true);
    this.canvas.addEventListener('mousemove', draw, true);

    // add touch events if they're there
    if ('ontouchstart' in window) {
      this.canvas.addEventListener('touchstart', start, true);
      this.canvas.addEventListener('touchend', stop, true);
      this.canvas.addEventListener('touchmove', draw, true);
    }

    // make the cursor a crosshair to make it more clear what can be done
    this.canvas.style.cursor = 'crosshair';
  };

  SayCheese.prototype.resetViewfinder = function() {
    this.context.globalCompositeOperation = 'source-over';
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);

    this.viewfinder = {
      startX: 0,
      startY: 0,
      width: this.videoWidth,
      height: this.videoHeight
    }

    this.trigger('change');
  };

  /* Take a snapshot of the current state of the stream */
  SayCheese.prototype.takeSnapshot = function takeSnapshot(callback) {
    var snapshot = document.createElement('canvas'),
        ctx      = snapshot.getContext('2d');

    snapshot.width  = Math.abs(this.viewfinder.width),
    snapshot.height = Math.abs(this.viewfinder.height);

    ctx.drawImage(this.video,
                  this.viewfinder.startX,
                  this.viewfinder.startY,
                  this.viewfinder.width,
                  this.viewfinder.height,
                  0,
                  0,
                  this.viewfinder.width,
                  this.viewfinder.height);

    this.snapshots.push(snapshot);
    this.trigger('snapshot', snapshot);

    if (callback) {
      callback.call(this, snapshot);
    }

    ctx = null;
  };

  /* Start up the stream, if possible */
  SayCheese.prototype.start = function start(callback) {
    var success = function success(stream) {
      this.createVideo();

      // video width and height don't exist until metadata is loaded
      this.video.addEventListener('loadedmetadata', this.setupCanvas.bind(this), false);

      this.video.src = this.getStreamUrl(stream);
      this.element.appendChild(this.video);
    }.bind(this);

    /* error is also called when someone denies access */
    var error = function error() {
      this.trigger('error', arguments);
    }.bind(this);

    // add the callback to the start event if one is supplied.
    if (callback) {
      this.on('start', callback);
    }

    this.getUserMedia(success, error);
  };

  /* Stop it - TODO: figure out how to actually disable the stream */
  SayCheese.prototype.stop = function stop() {
    this.video = null;
    document.body.removeChild(video);
  };

  return SayCheese;

})($);
<|endoftext|>


<commit_before><commit_msg>[cli] Upgrade yarn to 0.24.6<commit_after><|endoftext|>


<commit_before>// Copyright 2011 Joyent, Inc.  All rights reserved.

var util = require('util');
var ldap = require('ldapjs');

var Validator = require('../lib/schema/validator');

var KEY_RE = /^[a-zA-Z0-9\-\_]*$/;

///--- Validation helpers

function validKey(key) {
  return KEY_RE.test(key);
}

///--- API

function Tag() {
  Validator.call(this, {
    name: 'tag',
    required: {
      key: 1,
      value: 1
    },
    strict: true
  });
}
util.inherits(Tag, Validator);

Tag.prototype.validate = function(entry, callback) {
  var errors = [];
  var attrs = entry.attributes;

  if (!validKey(attrs.key[0])) {
    errors.push("Tag key: '" + attrs.key[0] + "' does not have a valid format");
  }

  if (errors.length)
    return callback(new ldap.ConstraintViolationError(errors.join('\n')));

  return callback();
}

///--- Exports

module.exports = {
  createInstance: function() {
    return new Tag();
  }
};
<commit_msg>ZAPI-28: Remove Tag schema<commit_after><|endoftext|>


<commit_before><commit_msg>fix(paths processor spec): provide basePath for testing<commit_after><|endoftext|>


<commit_before>"use strict";

var EmberStriker = function (Ember) {

  //---------------------------------------------------------------
  // BEGIN: CustomSelect
  var CustomSelect = Ember.Component.extend({

    __globalEventListener: null,
    classNameBindings:     ['isDisabled','isExpanded'],
    classNames:            'custom-select',
    isDisabled:            false,
    isExpanded:            false,
    options:               [{value: "value", title: "Title", isSelected: false}],
    placeholder:           'Select an option...',
    value:                 null,

    selection: function (key, newVal, oldVal) {
      // setter
      if(arguments.length > 1 && typeof newVal !== 'undefined' && typeof newVal.value !== 'undefined') {this.set('value',newVal.value);}
      // getter
      var options = this.get('options');
      for(var i=0;i<options.length;i++) {if(typeof options[i].value !== 'undefined' && options[i].value === this.get('value')) {return options[i];}}
      return null;
    }.property('options','value'),

    layout: Ember.Handlebars.compile(''
      +'
'
      +'  {{#if isExpanded}}'
      +'
{{placeholder}}
'
      +'    {{#each option in options}}'
      +'
{{option.title}}
'
      +'    {{/each}}'
      +'  {{else}}'
      +'    {{#if selection}}'
      +'
{{selection.title}}
'
      +'    {{else}}'
      +'
{{placeholder}}
'
      +'    {{/if}}'
      +'  {{/if}}'
      +'
'
    ),

    didInsertElement: function () {
      var self = this;
      // initialize options array
      this.get('options').forEach(function(item,index,enumerable){
        Ember.set(item, 'value',      (item.value || null));
        Ember.set(item, 'title',      (item.title || item.value || null));
        Ember.set(item, 'isSelected', (item.value === self.get('value') ? true : false));
      });
      // define global event listener
      this.set('__globalEventListener', function(e){if(self.get('isExpanded')){self.set('isExpanded',false);}return false;});
      // bind global event listener
      window.document.addEventListener('click', this.get('__globalEventListener'), false);
      // run super
      return this._super();
    },

    willDestroyElement: function () {
      // unbind global event listener
      window.document.removeEventListener('click', this.get('__globalEventListener'), false);
      // run super
      return this._super();
    },

    actions: {
      changeSelection: function (option) {
        if(!this.get('isDisabled')) {
          if(this.get('selection')) {this.set('selection.isSelected',false);}
          this.set('selection',option);
          this.set('selection.isSelected',true);
        }
        return false;
      },
      toggleExpanded: function () {
        if(!this.get('isDisabled')) {
          this.toggleProperty('isExpanded');
        }
        return false;
      }
    }

  });
  // END: CustomSelect
  //---------------------------------------------------------------

  //---------------------------------------------------------------
  // BEGIN: CustomTextField
  var CustomTextField = Ember.TextField.extend({

    __globalEventListener: null,
    attributeBindings:     ['maxlength','size'],
    classNameBindings:     ['isActive'],
    classNames:            'edit-in-place-text-field',
    isActive:              false,
    placeholder:           null,
    value:                 null,

    maxlength: function () {
      return (this.get('value')!==null && typeof this.get('value').length!=='undefined' && this.get('value').length>0) ? this.get('value').length+1 : ((this.get('placeholder')!==null && typeof this.get('placeholder').length!=='undefined' && this.get('placeholder').length>0) ? this.get('placeholder').length+1 : 1);
    }.property('placeholder','value'),

    size: function () {
      return (this.get('value')!==null && typeof this.get('value').length!=='undefined' && this.get('value').length>0) ? this.get('value').length+1 : ((this.get('placeholder')!==null && typeof this.get('placeholder').length!=='undefined' && this.get('placeholder').length>0) ? this.get('placeholder').length+1 : 1);
    }.property('placeholder','value'),

    focusIn: function (e) {
      this.set('isActive',true);
    },

    focusOut: function (e) {
      this.set('isActive',false);
      // send default action (defined in hbs template) to controller
      this.sendAction('action');
    }

  });
  // END: CustomTextField
  //---------------------------------------------------------------

  // Public properties & methods
  return {
    'CustomSelect':    CustomSelect,
    'CustomTextField': CustomTextField
  };

}(window.Ember);
<commit_msg>Another bug fix for computed property length.<commit_after>"use strict";

var EmberStriker = function (Ember) {

  //---------------------------------------------------------------
  // BEGIN: CustomSelect
  var CustomSelect = Ember.Component.extend({

    __globalEventListener: null,
    classNameBindings:     ['isDisabled','isExpanded'],
    classNames:            'custom-select',
    isDisabled:            false,
    isExpanded:            false,
    options:               [{value: "value", title: "Title", isSelected: false}],
    placeholder:           'Select an option...',
    value:                 null,

    selection: function (key, newVal, oldVal) {
      // setter
      if(arguments.length > 1 && typeof newVal !== 'undefined' && typeof newVal.value !== 'undefined') {this.set('value',newVal.value);}
      // getter
      var options = this.get('options');
      for(var i=0;i<options.length;i++) {if(typeof options[i].value !== 'undefined' && options[i].value === this.get('value')) {return options[i];}}
      return null;
    }.property('options','value'),

    layout: Ember.Handlebars.compile(''
      +'
'
      +'  {{#if isExpanded}}'
      +'
{{placeholder}}
'
      +'    {{#each option in options}}'
      +'
{{option.title}}
'
      +'    {{/each}}'
      +'  {{else}}'
      +'    {{#if selection}}'
      +'
{{selection.title}}
'
      +'    {{else}}'
      +'
{{placeholder}}
'
      +'    {{/if}}'
      +'  {{/if}}'
      +'
'
    ),

    didInsertElement: function () {
      var self = this;
      // initialize options array
      this.get('options').forEach(function(item,index,enumerable){
        Ember.set(item, 'value',      (item.value || null));
        Ember.set(item, 'title',      (item.title || item.value || null));
        Ember.set(item, 'isSelected', (item.value === self.get('value') ? true : false));
      });
      // define global event listener
      this.set('__globalEventListener', function(e){if(self.get('isExpanded')){self.set('isExpanded',false);}return false;});
      // bind global event listener
      window.document.addEventListener('click', this.get('__globalEventListener'), false);
      // run super
      return this._super();
    },

    willDestroyElement: function () {
      // unbind global event listener
      window.document.removeEventListener('click', this.get('__globalEventListener'), false);
      // run super
      return this._super();
    },

    actions: {
      changeSelection: function (option) {
        if(!this.get('isDisabled')) {
          if(this.get('selection')) {this.set('selection.isSelected',false);}
          this.set('selection',option);
          this.set('selection.isSelected',true);
        }
        return false;
      },
      toggleExpanded: function () {
        if(!this.get('isDisabled')) {
          this.toggleProperty('isExpanded');
        }
        return false;
      }
    }

  });
  // END: CustomSelect
  //---------------------------------------------------------------

  //---------------------------------------------------------------
  // BEGIN: CustomTextField
  var CustomTextField = Ember.TextField.extend({

    __globalEventListener: null,
    attributeBindings:     ['maxlength','size'],
    classNameBindings:     ['isActive'],
    classNames:            'edit-in-place-text-field',
    isActive:              false,
    placeholder:           null,
    value:                 null,

    maxlength: function () {
      return (typeof this.get('value')!=='undefined' && typeof this.get('value').length!=='undefined' && this.get('value').length>0) ? this.get('value').length+1 : ((typeof this.get('placeholder')!=='undefined' && typeof this.get('placeholder').length!=='undefined' && this.get('placeholder').length>0) ? this.get('placeholder').length+1 : 1);
    }.property('placeholder','value'),

    size: function () {
      return (typeof this.get('value')!=='undefined' && typeof this.get('value').length!=='undefined' && this.get('value').length>0) ? this.get('value').length+1 : ((typeof this.get('placeholder')!=='undefined' && typeof this.get('placeholder').length!=='undefined' && this.get('placeholder').length>0) ? this.get('placeholder').length+1 : 1);
    }.property('placeholder','value'),

    focusIn: function (e) {
      this.set('isActive',true);
    },

    focusOut: function (e) {
      this.set('isActive',false);
      // send default action (defined in hbs template) to controller
      this.sendAction('action');
    }

  });
  // END: CustomTextField
  //---------------------------------------------------------------

  // Public properties & methods
  return {
    'CustomSelect':    CustomSelect,
    'CustomTextField': CustomTextField
  };

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


<commit_before>var MISSING_QUOTES = "MissingQuotes";
var URL = window.URL || window.webkitURL;
var diff = {};
diff.platformData = [];
diff.clientData = [];

$("#the-client-file-input").change(function() {

  if (this.files[0]) {
    if (URL){
      var fileUrl = URL.createObjectURL(this.files[0]);
    }
  }

  Papa.parse(this.files[0], {
    header: true,
    dynamicTyping: true,
    skipEmptyLines: true,
    fastMode: true,

    chunk: function(chunk){
      diff.clientData = diff.clientData.concat(chunk.data);
    },

    error: function(err, reason) {
      console.log(err, reason);
    },

    complete: function() {
      setupClient();
      $("#platform-file-chooser-wrapper").removeClass("hidden");
      $("#client-warning-tip").addClass("hidden");
      $("#client-success-tip").removeClass("hidden");
      $("#client-progress-bar").addClass("hidden");
    }
  });

  $("#client-progress").attr('aria-valuenow','100');
  $("#client-progress").css('width','100%');

});

$("#the-platform-file-input").change(function() {
  if(this.files[0]) {
    if(URL){
      var fileUrl = URL.createObjectURL(this.files[0]);
    }
  }

  Papa.parse(this.files[0], {
    header: true,
    dynamicTyping: true,
    skipEmptyLines: true,
    fastMode: true,

    chunk: function(chunk){
      diff.platformData = diff.platformData.concat(chunk.data);
    },

    error: function(err, reason) {
      console.log(err, reason);
    },

    complete: function() {
      setupPlatform();
      $("#report-board").removeClass("hidden");
      $("#platform-warning-tip").addClass("hidden");
      $("#platform-success-tip").removeClass("hidden");
      $("#platform-progress-bar").addClass("hidden");
    }
  });

  $("#platform-progress").attr('aria-valuenow','100');
  $("#platform-progress").css('width','100%');
});

function setupPlatform() {
  diff.platformData.forEach(function(row) {
    row.timestamp = moment.utc(row.timestamp, ["YYYY-MM-DD HH:mm:SS"]);
    // console.log(row.timestamp);
  });
  diff.platformDump = makeDump(diff.platformData);
  console.log(diff.platformDump);
  dateSlider();
}

function setupClient() {
  diff.clientData.forEach(function(row) {
    row.timestamp = moment.utc(row.timestamp, ["YYYY-MM-DD HH:mm:SS"]);
    // console.log(row.timestamp);
  });
  diff.clientDump = makeDump(diff.clientData);
  // console.log(diff.clientDump);
  diff.clientDump.extentDays = d3.extent(diff.clientData, function(row) { return row.timestamp });
}

function showInfo() {
  $("#platform-file-chooser-wrapper").addClass("hidden");
  $("#client-file-chooser-wrapper").addClass("hidden");

  calculate(diff.clientDump);
  calculate(diff.platformDump);

  // ###### FILTERS #######
  // var platformDataByOrder = d3.nest().key(function(d) { return d.oid; }).entries(diff.platformDump.data);
  // var platformDataByDay = d3.nest().key(function(d) { return d.timestamp; }).entries(diff.platformDump.data);

  var platformDateInterval = diff.platformDump.data.filter(function(row) {
    return row.timestamp.isBetween(diff.clientDump.extentDays[0], diff.clientDump.extentDays[1]);
  });
  var clientDateInterval = diff.clientDump.data.filter(function(row) {
    return row.timestamp.isBetween(diff.clientDump.extentDays[0], diff.clientDump.extentDays[1]);
  });

  diffplot(diffTransactionsByDay(transactionsByDay(filterOrderByDateInterval(clientDateInterval)), transactionsByDay(filterOrderByDateInterval(platformDateInterval))));

  var platformDateIntervalByOrder = d3.nest().key(function(d) { return d.oid; }).entries(platformDateInterval);
  var clientDateIntervalByOrder = d3.nest().key(function(d) { return d.oid; }).entries(clientDateInterval);

  // plot(transactionsByDay(diff.clientDump.productsByOrderByDate, transactionsByDay(diff.platformDump.productsByOrderByDate)));

  $("#blackboard").append(
    "
"+
    "
 Client Data
"+
    "
Number of Rows: "+diff.clientDump.numberOfRows+"
"+
    "
Number of Orders: "+clientDateIntervalByOrder.length+"
"+
    "
Max Day: "+diff.clientDump.extentDays[1].toString()+"
"+
    "
Min Day: "+diff.clientDump.extentDays[0].toString()+"
"+

    "
 Platform Data
"+
    "
Number of Rows: "+diff.platformDump.numberOfRows+"
"+
    "
Number of Orders(filtered by client days interval): "+platformDateIntervalByOrder.length+"
"+
    "
"+
    ""
  );

  $("#report-progress").attr('aria-valuenow','100');
  $("#report-progress").css('width','100%');
  $("#report-progress-bar").addClass("hidden");
}

function makeDump(csvData) {
  var object = {
    data: csvData,
    numberOfRows: csvData.length,
  }
  return object;
}

function transactionsByDay(data, array) {
  var object = [];
  if (array) {
    for (entry of array){
      object.push(entry);
    }
  }
  for (month of data) {
    for (i = 0; i < month.values.length; i++) {
      object.push({
        date : month.key+"-"+month.values[i].key,
        data : month.values[i].values.length
      });
    }
  }
  return object;
}

function diffTransactionsByDay(client, platform) {
  var object = [];
  for (i = 0; i < client.length; i++) {
    if (client[i] && platform[i] && client[i].date == platform[i].date) {
      object.push({
        day : client[i].date,
        platform: platform[i].data,
        client: client[i].data,
      });
    } else {
      //showBigWarning(client[i].date, platform[i].date);
      break;
    }
  }
  return object;
}

function plot(data) {
  $("#chart-wrapper").removeClass("hidden");
  var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

  var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);

  var y = d3.scale.linear()
    .range([height, 0]);

  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .ticks(10);

  var svg = d3.select("#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  x.domain(data.map(function(d) { return d.date; }));
  y.domain([0, d3.max(data, function(d) { return d.data; })]);

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
  .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Day");

  svg.selectAll(".bar")
    .data(data)
  .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) { return x(d.date); })
    .attr("width", x.rangeBand())
    .attr("y", function(d) { return y(d.data); })
    .attr("height", function(d) { return height - y(d.data); });

}

function diffplot(data) {
  $("#chart-wrapper").removeClass("hidden");

  var margin = {top: 20, right: 20, bottom: 30, left: 40},
      width = 992 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

  var x0 = d3.scale.ordinal()
      .rangeRoundBands([0, width], .1);

  var x1 = d3.scale.ordinal();

  var y = d3.scale.linear()
      .range([height, 0]);

  var color = d3.scale.ordinal()
      .range(["#ffce54", "#3498db", "#ff8336", "#793091", "#d8192c", "#9aca40", "#ffa269"]);

  var xAxis = d3.svg.axis()
      .scale(x0)
      .orient("bottom");

  var yAxis = d3.svg.axis()
      .scale(y)
      .orient("left")
      .tickFormat(d3.format(".2s"));

  var svg = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var ageNames = d3.keys(data[0]).filter(function(key) { return key !== "day"; });

  data.forEach(function(d) {
    d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; });
  });

  x0.domain(data.map(function(d) { return d.day; }));
  x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
  y.domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Population");

  var state = svg.selectAll(".state")
      .data(data)
    .enter().append("g")
      .attr("class", "g")
      .attr("transform", function(d) { return "translate(" + x0(d.day) + ",0)"; });

  state.selectAll("rect")
      .data(function(d) { return d.ages; })
    .enter().append("rect")
      .attr("width", x1.rangeBand())
      .attr("x", function(d) { return x1(d.name); })
      .attr("y", function(d) { return y(d.value); })
      .attr("height", function(d) { return height - y(d.value); })
      .style("fill", function(d) { return color(d.name); });

  var legend = svg.selectAll(".legend")
      .data(ageNames.slice().reverse())
    .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

  legend.append("rect")
      .attr("x", width - 18)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);

  legend.append("text")
      .attr("x", width - 24)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "end")
      .text(function(d) { return d; });
}

function dateSlider() {
  console.log();
  $("#slider").dateRangeSlider({
    arrows: false,
    bounds:{
      min: diff.clientDump.extentDays[0].toDate(),
      max: diff.clientDump.extentDays[1].toDate()
    },defaultValues:{
      min: diff.clientDump.extentDays[0].toDate(),
      max: diff.clientDump.extentDays[1].toDate()
    },formatter:function(val){
      var days = val.getDate(),
      month = val.getMonth() + 1,
      year = val.getFullYear(),
      hour = val.getHours(),
      minute = val.getMinutes(),
      second = val.getSeconds();
      return days + "/" + month + "/" + year ;
    },range:{
      min: {days: 1}
    },step: {days: 1}
  });

  $("#slider").bind("valuesChanged", function(e, data){
    diff.dateRangeSlider = {};
    diff.clientDump.extentDays[0] = data.values.min;
    diff.clientDump.extentDays[1] = data.values.max;
    console.log("Values just changed. min: " + diff.clientDump.extentDays[0] + " max: " + diff.clientDump.extentDays[1]);
  });
}

function calculate(dump) {
  dump.numberOfTransactions = d3.nest().key(function(d) { return d.oid; }).entries(dump.data).length;
}

function filterOrderByDateInterval(data){
  return d3.nest().key(function(d) { return d.timestamp.month(); })
    .key(function(d) { return d.timestamp.date(); })
    .key(function(d) { return d.oid; })
    .rollup(function(v) { return v.length; })
    .entries(data);
}
<commit_msg>cleaned some code and papaparse aprimorations<commit_after>var diff = {};
// diff.platformData = [];
// diff.clientData = [];

$("#the-client-file-input").change(function() {
  Papa.parse(this.files[0], {
    header: true,
    dynamicTyping: true,
    skipEmptyLines: true,
    // fastMode: true,
    // chunk: function(chunk){
    //   diff.clientData = diff.clientData.concat(chunk.data);
    // },
    error: function(err, reason) {
      console.log(err, reason);
    },
    complete: function(result) {
      if(result.errors){
        for (var i = 0; i < result.errors.length; i++) {
          console.log(result.errors[i]);
        }
      }
      setupClient(result.data);
      $("#platform-file-chooser-wrapper").removeClass("hidden");
      $("#client-warning-tip").addClass("hidden");
      $("#client-success-tip").removeClass("hidden");
      $("#client-progress-bar").addClass("hidden");
    }
  });

  $("#client-progress").attr('aria-valuenow','100');
  $("#client-progress").css('width','100%');

});

$("#the-platform-file-input").change(function() {
  Papa.parse(this.files[0], {
    header: true,
    dynamicTyping: true,
    skipEmptyLines: true,
    // fastMode: true,
    // chunk: function(chunk){
    //   diff.platformData = diff.platformData.concat(chunk.data);
    // },
    error: function(err, reason) {
      console.log(err, reason);
    },
    complete: function(result) {
      if(result.errors){
        for (var i = 0; i < result.errors.length; i++) {
          console.log(result.errors[i]);
        }
      }
      setupPlatform(result.data);
      $("#report-board").removeClass("hidden");
      $("#platform-warning-tip").addClass("hidden");
      $("#platform-success-tip").removeClass("hidden");
      $("#platform-progress-bar").addClass("hidden");
      createDateSlider(diff.clientDump.extentDays[0], diff.clientDump.extentDays[1]);
    }
  });

  $("#platform-progress").attr('aria-valuenow','100');
  $("#platform-progress").css('width','100%');
});

function setupPlatform(data) {
  data.forEach(function(row) {
    row.timestamp = moment.utc(row.timestamp, ["YYYY-MM-DD HH:mm:SS"]);
  });

  diff.platformDump = makeDump(data);
}

function setupClient(data) {
  data.forEach(function(row) {
    row.timestamp = moment.utc(row.timestamp, ["YYYY-MM-DD HH:mm:SS"]);
  });

  diff.clientDump = makeDump(data);
  diff.clientDump.extentDays = d3.extent(data, function(row) { return row.timestamp });
}

function showInfo() {
  $("#platform-file-chooser-wrapper").addClass("hidden");
  $("#client-file-chooser-wrapper").addClass("hidden");

  var platformDateInterval = filterByDateInterval(diff.platformDump.data, diff.clientDump.extentDays[0], diff.clientDump.extentDays[1]);
  var clientDateInterval = filterByDateInterval(diff.clientDump.data, diff.clientDump.extentDays[0], diff.clientDump.extentDays[1]);

  numberOfOrderDiffPlot(clientDateInterval, platformDateInterval);

  calculateDumpNumberOfTransactions(diff.clientDump, platformDateInterval);
  calculateDumpNumberOfTransactions(diff.platformDump, clientDateInterval);

  showReport();

  $("#report-progress").attr('aria-valuenow','100');
  $("#report-progress").css('width','100%');
  $("#report-progress-bar").addClass("hidden");
}

function filterByDateInterval(data, beginDate, endDate){
  return data.filter(function(row) {
    return row.timestamp.isBetween(beginDate, endDate);
  });
}

function showReport(){
  $("#blackboard").append(
    "
"+
    "
 Client Data
"+
    "
Number of Rows: "+diff.clientDump.numberOfRows+"
"+
    "
Number of Orders: "+diff.clientDump.numberOfOrders+"
"+
    "
Max Day: "+diff.clientDump.extentDays[1].toString()+"
"+
    "
Min Day: "+diff.clientDump.extentDays[0].toString()+"
"+

    "
 Platform Data
"+
    "
Number of Rows: "+diff.platformDump.numberOfRows+"
"+
    "
Number of Orders(filtered by client days interval): "+diff.platformDump.numberOfOrders+"
"+
    "
"+
    ""
  );
}

function makeDump(csvData) {
  var object = {
    data: csvData,
    numberOfRows: csvData.length,
  }
  return object;
}

function transactionsByDay(data) {
  innerData = filterOrderByDateInterval(data);

  var object = [];
  // if (array) {
  //   for (entry of array){
  //     object.push(entry);
  //   }
  // }
  for (month of innerData) {
    for (i = 0; i < month.values.length; i++) {
      object.push({
        date : month.key+"-"+month.values[i].key,
        data : month.values[i].values.length
      });
    }
  }
  return object;
}

function diffTransactionsByDay(client, platform) {
  innerClient = transactionsByDay(client);
  innerPlatform = transactionsByDay(platform);

  var object = [];
  for (i = 0; i < innerClient.length; i++) {
    if (innerClient[i] && innerPlatform[i] && innerClient[i].date == innerPlatform[i].date) {
      object.push({
        day : innerClient[i].date,
        platform: innerPlatform[i].data,
        client: innerClient[i].data,
      });
    } else {
      //showBigWarning(client[i].date, platform[i].date);
      break;
    }
  }
  return object;
}

function numberOfOrderDiffPlot(clientData, platformData) {
  innerData = diffTransactionsByDay(clientData, platformData);

  $("#chart-wrapper").removeClass("hidden");

  var margin = {top: 20, right: 20, bottom: 30, left: 40},
      width = 992 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

  var x0 = d3.scale.ordinal()
      .rangeRoundBands([0, width], .1);

  var x1 = d3.scale.ordinal();

  var y = d3.scale.linear()
      .range([height, 0]);

  var color = d3.scale.ordinal()
      .range(["#ffce54", "#3498db", "#ff8336", "#793091", "#d8192c", "#9aca40", "#ffa269"]);

  var xAxis = d3.svg.axis()
      .scale(x0)
      .orient("bottom");

  var yAxis = d3.svg.axis()
      .scale(y)
      .orient("left")
      .tickFormat(d3.format(".2s"));

  var svg = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var ageNames = d3.keys(innerData[0]).filter(function(key) { return key !== "day"; });

  innerData.forEach(function(d) {
    d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; });
  });

  x0.domain(innerData.map(function(d) { return d.day; }));
  x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
  y.domain([0, d3.max(innerData, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Population");

  var state = svg.selectAll(".state")
      .data(innerData)
    .enter().append("g")
      .attr("class", "g")
      .attr("transform", function(d) { return "translate(" + x0(d.day) + ",0)"; });

  state.selectAll("rect")
      .data(function(d) { return d.ages; })
    .enter().append("rect")
      .attr("width", x1.rangeBand())
      .attr("x", function(d) { return x1(d.name); })
      .attr("y", function(d) { return y(d.value); })
      .attr("height", function(d) { return height - y(d.value); })
      .style("fill", function(d) { return color(d.name); });

  var legend = svg.selectAll(".legend")
      .data(ageNames.slice().reverse())
    .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

  legend.append("rect")
      .attr("x", width - 18)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);

  legend.append("text")
      .attr("x", width - 24)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "end")
      .text(function(d) { return d; });
}

function createDateSlider(minDate, maxDate) {
  console.log();
  $("#slider").dateRangeSlider({
    arrows: false,
    bounds:{
      min: minDate.toDate(),
      max: maxDate.toDate()
    },defaultValues:{
      min: minDate.toDate(),
      max: maxDate.toDate()
    },formatter:function(val){
      var days = val.getDate(),
      month = val.getMonth() + 1,
      year = val.getFullYear(),
      hour = val.getHours(),
      minute = val.getMinutes(),
      second = val.getSeconds();
      return days + "/" + month + "/" + year ;
    },range:{
      min: {days: 1}
    },step: {days: 1}
  });

  $("#slider").bind("valuesChanged", function(e, data){
    diff.clientDump.extentDays[0] = data.values.min;
    diff.clientDump.extentDays[1] = data.values.max;
    console.log("Values just changed. min: " + diff.clientDump.extentDays[0] + " max: " + diff.clientDump.extentDays[1]);
  });
}

function calculateDumpNumberOfTransactions(dump, data) {
  dump.numberOfOrders = d3.nest().key(function(d) { return d.oid; }).entries(data).length;
}

/* ======================= */

function filterOrderByDateInterval(data){
  return d3.nest().key(function(d) { return d.timestamp.month(); })
    .key(function(d) { return d.timestamp.date(); })
    .key(function(d) { return d.oid; })
    .rollup(function(v) { return v.length; })
    .entries(data);
}

function plot(data) {
  $("#chart-wrapper").removeClass("hidden");
  var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

  var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);

  var y = d3.scale.linear()
    .range([height, 0]);

  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .ticks(10);

  var svg = d3.select("#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  x.domain(data.map(function(d) { return d.date; }));
  y.domain([0, d3.max(data, function(d) { return d.data; })]);

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
  .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Day");

  svg.selectAll(".bar")
    .data(data)
  .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) { return x(d.date); })
    .attr("width", x.rangeBand())
    .attr("y", function(d) { return y(d.data); })
    .attr("height", function(d) { return height - y(d.data); });

}
<|endoftext|>


<commit_before><commit_msg>preload images during page load<commit_after><|endoftext|>


<commit_before>/*
---
description: Creates an Fx.Accordion from any element with Accordion in its data-filters property.  Uses the .toggle elements within the element as the toggles and the .target elements as the targets.
provides: [Behavior.Accordion]
requires: [Widgets/Behavior, More/Fx.Accordion, Widgets/Element.Data]
script: Behavior.Accordion.js
...
*/

Behavior.addGlobalFilters({
        Accordion: function(element, methods) {
                var toggles = element.get('data', 'toggler-elements') || '.toggle';
                var sections = element.get('data', 'section-elements') || '.target';
                var accordion = new Fx.Accordion(toggles, sections);
                this.markForCleanup(element, function() {
                        accordion.detach();
                });
        }
});

<commit_msg>tabs...<commit_after>/*
---
description: Creates an Fx.Accordion from any element with Accordion in its data-filters property.  Uses the .toggle elements within the element as the toggles and the .target elements as the targets.
provides: [Behavior.Accordion]
requires: [Widgets/Behavior, More/Fx.Accordion, Widgets/Element.Data]
script: Behavior.Accordion.js
...
*/

Behavior.addGlobalFilters({
	Accordion: function(element, methods) {
		var toggles = element.get('data', 'toggler-elements') || '.toggle';
		var sections = element.get('data', 'section-elements') || '.target';
		var accordion = new Fx.Accordion(toggles, sections);
		this.markForCleanup(element, function() {
			accordion.detach();
		});
	}
});

<|endoftext|>


<commit_before>define(['backbone', 'underscore', 'channels', 'mixin', 'rivetView'], function (Backbone, _, channels, mixin, rivetView) {

    var BaseView = Backbone.View.extend({
        options : {
            name : 'BaseView',
            bindings: [
                // Example: [stringObjectToListenTo, stringEventName, stringCallbackFunction]
                //          ['model', 'change:something', 'callbackFunction']
                // Bindings have to be all strings, since config does not have access to the view's context
                // if strings are provided it is assumed that the context is the view
            ]
        },
        defaultBindings: [],
        initialize : initialize,
        start : start,
        render : render,
        dataToJSON : dataToJSON,
        bindEventListeners: bindEventListeners
        // Dynamically created, so the cache is not shared on the prototype:
        // elementCache: elementCache
    });

    function initialize () {
        var ModelType = this.options.ModelType || Backbone.Model;
        this.elementCache = _.memoize(elementCache);
        if (this.options.templateHtml) {
            this.template = _.template(this.options.templateHtml);
        }
        this.model = new ModelType(this.options.modelData);
        if (this.options.bindings) {
            this.bindEventListeners(this.options.bindings);
        }
        if(this.options.rivetConfig) {
            this.rivetView = rivetView({
                rivetScope : this.options.rivetConfig.scope,
                rivetPrefix : this.options.rivetConfig.prefix,
                instaUpdateRivets : (this.options.rivetConfig.instaUpdateRivets ? true : false)
            })
        }

    }

    function start () {
        var $deferred = new $.Deferred();

        $
            .when(_runLifeCycleMethod.call(this, this.beforeRender, 'BeforeRender'))
            .then(
                _lifeCycleMethodReference.call(this, this.render, 'Render'),
                _rejectStart.call(this, $deferred))
            .then(
                _lifeCycleMethodReference.call(this, this.afterRender, 'AfterRender'),
                _rejectStart.call(this, $deferred))
            .then(
                _resolveStart.call(this, $deferred),
                _rejectStart.call(this, $deferred));

        return $deferred.promise();
    }

    function render () {
        if (this.$el && this.template) {
            if (this.options.appendView) {
                this.$el.append(this.template(this.dataToJSON()));
            } else {
                this.$el.html(this.template(this.dataToJSON()));
            }
        }
    }

    function elementCache(selector) {
        return this.$el.find(selector);
    }

    function dataToJSON () {
        return this.model ? this.model.toJSON() : {};
    }

    /**
     * bindEventListeners
     * Bind all event listerns specified in 'defaultListeners' and 'options.listeners' using 'listenTo'
     *
     * @param (Array[Array]) listenerArray - A collection of arrays of arguments that will be used with 'Backbone.Events.listenTo'
     *
     * @example:
     *      bindEventListeners([['myModel', 'change:something', 'myCallbackFunction']]);
     *
     * @remarks
     * Passing in an array with a string as the first parameter will attempt to bind to this[firstArgument] so that
     * it is possible to listen to view properties that have not yet been instantiated (i.e. viewModels)
     */
    function bindEventListeners (listenerArray) {
        var self = this,
            listenerArgs;

        this.stopListening();

        listenerArgs = _.map(listenerArray.concat(this.defaultBindings), function (argsArray) {

            // Since the view config object doesn't have access to the view's context, we must provide it
            _.each([argsArray[0], argsArray[1] ,argsArray[2]], function(arg, index) {
                if (_.isString(arg) && index != 1) {
                    argsArray[index] = _getProperty(self, arg);
                } else if (index == 1) {
                    argsArray[index] = arg;
                }
            });

            return argsArray;
        });

        // TODO: test that duplicate itmems will pick the bindings from options, throwing out defaults
        listenerArray = _.uniq(listenerArgs, function (a, b) {
            return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
        });

        _.each(listenerArray, function (listenerArgs) {
            self.listenTo.apply(self, listenerArgs);
        });
    }

    // Share channels among all Views
    BaseView.prototype.channels = BaseView.prototype.channels || channels;

    // --------------------------
    // Private Methods

    /**
     * Life cycle methods have an event triggered before the run.
     * If a life cycle method has one or more arguments, then the first argument passed in is its deferred.
     * The life cycle method will automatically return this deferred, otherwise it will pass through whatever
     * the method itself returns.
     *
     * @param lifeCycleMethod
     * @param lifeCycleMethodName
     * @returns {*}
     * @private
     */
    function _runLifeCycleMethod (lifeCycleMethod, lifeCycleMethodName) {
        if (!lifeCycleMethod) {
            return undefined;
        }

        return mixin({}, lifeCycleMethod)({
            async : lifeCycleMethod.length,
            preEvent : {
                name : this.options.name + ':on' + lifeCycleMethodName,
                channel : this.channels.views
            }
        }).call(this);
    }

    /**
     * A convenience wrapper for creating life cycle method references.
     * @param lifeCycleMethod
     * @param lifeCycleMethodName
     * @returns {*}
     * @private
     */
    function _lifeCycleMethodReference (lifeCycleMethod, lifeCycleMethodName) {
        return function () {
            return _runLifeCycleMethod.call(this, lifeCycleMethod, lifeCycleMethodName);
        }.bind(this);
    }

    function _resolveStart ($deferred) {
        return function () {
            $deferred.resolve();
        }.bind(this);
    }

    function _rejectStart ($deferred) {
        return function () {
            $deferred.reject();
        }.bind(this);
    }

    function _getProperty(obj, parts, create) {
        if (typeof parts === 'string') {
            parts = parts.split('.');
        }

        var part;
        while (typeof obj === 'object' && obj && parts.length) {
            part = parts.shift();
            if (!(part in obj) && create) {
                obj[part] = {};
            }
            obj = obj[part];
        }

        return obj;
    };

    return BaseView;
});
<commit_msg>changes to baseView for appended views<commit_after>define(['backbone', 'underscore', 'channels', 'mixin', 'rivetView'], function (Backbone, _, channels, mixin, rivetView) {

    var BaseView = Backbone.View.extend({
        options : {
            name : 'BaseView',
            bindings: [
                // Example: [stringObjectToListenTo, stringEventName, stringCallbackFunction]
                //          ['model', 'change:something', 'callbackFunction']
                // Bindings have to be all strings, since config does not have access to the view's context
                // if strings are provided it is assumed that the context is the view
            ]
        },
        defaultBindings: [],
        initialize : initialize,
        start : start,
        render : render,
        dataToJSON : dataToJSON,
        bindEventListeners: bindEventListeners
        // Dynamically created, so the cache is not shared on the prototype:
        // elementCache: elementCache
    });

    function initialize () {
        var ModelType = this.options.ModelType || Backbone.Model;
        this.elementCache = _.memoize(elementCache);
        if (this.options.templateHtml) {
            this.template = _.template(this.options.templateHtml);
        }
        this.model = new ModelType(this.options.modelData);
        if (this.options.bindings) {
            this.bindEventListeners(this.options.bindings);
        }
        if (this.options.appendView) {
            this.model.set('viewId', this.cid.toLowerCase());
            this.rivetView = rivetView({
                rivetScope : this.cid,
                rivetPrefix : this.cid
            })
        }
        if(this.options.rivetConfig) {
            this.rivetView = rivetView({
                rivetScope : this.options.rivetConfig.scope,
                rivetPrefix : this.options.rivetConfig.prefix,
                instaUpdateRivets : (this.options.rivetConfig.instaUpdateRivets ? true : false)
            })
        }

    }

    function start () {
        var $deferred = new $.Deferred();

        $
            .when(_runLifeCycleMethod.call(this, this.beforeRender, 'BeforeRender'))
            .then(
                _lifeCycleMethodReference.call(this, this.render, 'Render'),
                _rejectStart.call(this, $deferred))
            .then(
                _lifeCycleMethodReference.call(this, this.afterRender, 'AfterRender'),
                _rejectStart.call(this, $deferred))
            .then(
                _resolveStart.call(this, $deferred),
                _rejectStart.call(this, $deferred));

        return $deferred.promise();
    }

    function render () {
        if (this.$el && this.template) {
            if (this.options.appendView) {
                this.$el.append(this.template(this.dataToJSON()));
            } else {
                this.$el.html(this.template(this.dataToJSON()));
            }
        }
    }

    function elementCache(selector) {
        return this.$el.find(selector);
    }

    function dataToJSON () {
        return this.model ? this.model.toJSON() : {};
    }

    /**
     * bindEventListeners
     * Bind all event listerns specified in 'defaultListeners' and 'options.listeners' using 'listenTo'
     *
     * @param (Array[Array]) listenerArray - A collection of arrays of arguments that will be used with 'Backbone.Events.listenTo'
     *
     * @example:
     *      bindEventListeners([['myModel', 'change:something', 'myCallbackFunction']]);
     *
     * @remarks
     * Passing in an array with a string as the first parameter will attempt to bind to this[firstArgument] so that
     * it is possible to listen to view properties that have not yet been instantiated (i.e. viewModels)
     */
    function bindEventListeners (listenerArray) {
        var self = this,
            listenerArgs;

        this.stopListening();

        listenerArgs = _.map(listenerArray.concat(this.defaultBindings), function (argsArray) {

            // Since the view config object doesn't have access to the view's context, we must provide it
            _.each([argsArray[0], argsArray[1] ,argsArray[2]], function(arg, index) {
                if (_.isString(arg) && index != 1) {
                    argsArray[index] = _getProperty(self, arg);
                } else if (index == 1) {
                    argsArray[index] = arg;
                }
            });

            return argsArray;
        });

        // TODO: test that duplicate itmems will pick the bindings from options, throwing out defaults
        listenerArray = _.uniq(listenerArgs, function (a, b) {
            return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
        });

        _.each(listenerArray, function (listenerArgs) {
            self.listenTo.apply(self, listenerArgs);
        });
    }

    // Share channels among all Views
    BaseView.prototype.channels = BaseView.prototype.channels || channels;

    // --------------------------
    // Private Methods

    /**
     * Life cycle methods have an event triggered before the run.
     * If a life cycle method has one or more arguments, then the first argument passed in is its deferred.
     * The life cycle method will automatically return this deferred, otherwise it will pass through whatever
     * the method itself returns.
     *
     * @param lifeCycleMethod
     * @param lifeCycleMethodName
     * @returns {*}
     * @private
     */
    function _runLifeCycleMethod (lifeCycleMethod, lifeCycleMethodName) {
        if (!lifeCycleMethod) {
            return undefined;
        }

        return mixin({}, lifeCycleMethod)({
            async : lifeCycleMethod.length,
            preEvent : {
                name : this.options.name + ':on' + lifeCycleMethodName,
                channel : this.channels.views
            }
        }).call(this);
    }

    /**
     * A convenience wrapper for creating life cycle method references.
     * @param lifeCycleMethod
     * @param lifeCycleMethodName
     * @returns {*}
     * @private
     */
    function _lifeCycleMethodReference (lifeCycleMethod, lifeCycleMethodName) {
        return function () {
            return _runLifeCycleMethod.call(this, lifeCycleMethod, lifeCycleMethodName);
        }.bind(this);
    }

    function _resolveStart ($deferred) {
        return function () {
            $deferred.resolve();
        }.bind(this);
    }

    function _rejectStart ($deferred) {
        return function () {
            $deferred.reject();
        }.bind(this);
    }

    function _getProperty(obj, parts, create) {
        if (typeof parts === 'string') {
            parts = parts.split('.');
        }

        var part;
        while (typeof obj === 'object' && obj && parts.length) {
            part = parts.shift();
            if (!(part in obj) && create) {
                obj[part] = {};
            }
            obj = obj[part];
        }

        return obj;
    };

    return BaseView;
});
<|endoftext|>