<commit_before>'use strict';

var d3 = require('d3');
var _ = require('lodash');
var utils = require('lightning-client-utils')
var colorbrewer = require('colorbrewer')

var L = require('leaflet');
var Color = require('color');
var id = 0;

var margin = {
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
};

var Adjacency = function(selector, data, images, opts) {

    if(!opts) {
        opts = {};
    }

    this.opts = opts
    this.width = (opts.width || $(selector).width()) - margin.left - margin.right;
    this.height = (opts.height || (this.width * 0.6)) - margin.top - margin.bottom;

    this.data = this._formatData(data)
    this.selector = selector;
    this._init();

}

Adjacency.prototype._init = function() {

    var width = this.width
    var height = this.height
    var data = this.data
    var selector = this.selector
    var self = this

    this.mid = id++;
    this.markup = '<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>

';

    var matrix = data.matrix;
    var label = data.label;
    var color = utils.getColors(matrix.length);

    // get min and max of matrix value data
    var zmin = d3.min(data.matrix, function(d) {
        return d3.min(d, function(e) {
            return e.z
        });
    });
    var zmax = d3.max(data.matrix, function(d) {
        return d3.max(d, function(e) {
            return e.z
        });
    });

    // set up opacity scale
    var z = d3.scale.linear().domain([0, zmax/5]).range([0.3,1]).clamp(true);

    // set up x and y scales and ranges
    var nrow = matrix.length
    var ncol = matrix[0].length
    var y = d3.scale.ordinal().rangeBands([0, Math.min(width, height)]);
    var x = d3.scale.ordinal().rangeBands([0, Math.min(width, height)]);
    y.domain(d3.range(nrow).sort(function(a, b) { return label[b] - label[a]; }));
    x.domain(d3.range(ncol).sort(function(a, b) { return label[b] - label[a]; }))
    var maxY = nrow * y.rangeBand();
    var maxX = ncol * x.rangeBand();

    // bounds for the graphic
    var bounds = [[0, 0], [maxY, maxX]];

    // create the graphic as a map
    this.$el = $(selector).first();
    this.$el.append(this.markup);
    this.$el.find('#matrix-map-' + this.mid).width(maxX).height(maxY);

    var map = L.map('matrix-map-' + this.mid, {
        center: [maxX/2, maxY/2],
        attributionControl: false,
        zoomControl: false,
        crs: L.CRS.Simple,
    });

    // set the bounds
    map.fitBounds(bounds);
    map.setMaxBounds(bounds);

    // function for handling opacity
    var buildRGBA = function(fill, opacity) {
        var color = Color(fill);
        color.alpha(opacity);
        return color.rgbString();
    };
    buildRGBA = _.memoize(buildRGBA, function(fill, opacity) {
        return fill + ',' + opacity;
    });

    // render the rectangles
    setTimeout(function() {
        _.each(matrix, function(row, i) {
            _.each(row, function(cell, j) {
                var xPos = x(cell.x);
                var yPos = y(i);
                var b = [[yPos, xPos], [yPos + y.rangeBand(), xPos + x.rangeBand()]];
                if (label[i] == label[j]) {
                    var fillColor = color[label[i]]
                } else {
                    var fillColor = "rgb(50,50,50)"
                }
                if (cell.z > 0) {
                    var cellColor = buildRGBA(fillColor, z(cell.z))
                } else {
                    var cellColor = buildRGBA("rgb(240,240,240)", 1.0)
                }
                L.rectangle(b, {color: cellColor, weight: 0.7, className: "cell"}).addTo(map);
            });
        });
    }, 0);

};

Adjacency.prototype._formatData = function(data) {

    var matrix = [];
    var n = data.nodes.length
    data.nodes.forEach(function(node, i) {
        matrix[i] = d3.range(n).map(function(j) { return {x: j, y: i, z: 0}; });
    });

    data.links.forEach(function(link) {
        matrix[link[0]][link[1]].z = link[2];
        matrix[link[1]][link[0]].z = link[2];
        matrix[link[0]][link[0]].z = 1;
        matrix[link[1]][link[1]].z = 1;
    });

    data.matrix = matrix

    data.label = data.label ? data.label : _.times(n, _.constant(0))

    return data

}

module.exports = Adjacency;
<commit_msg>Use length of unique labels<commit_after>'use strict';

var d3 = require('d3');
var _ = require('lodash');
var utils = require('lightning-client-utils')
var colorbrewer = require('colorbrewer')

var L = require('leaflet');
var Color = require('color');
var id = 0;

var margin = {
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
};

var Adjacency = function(selector, data, images, opts) {

    if(!opts) {
        opts = {};
    }

    this.opts = opts
    this.width = (opts.width || $(selector).width()) - margin.left - margin.right;
    this.height = (opts.height || (this.width * 0.6)) - margin.top - margin.bottom;

    this.data = this._formatData(data)
    this.selector = selector;
    this._init();

}

Adjacency.prototype._init = function() {

    var width = this.width
    var height = this.height
    var data = this.data
    var selector = this.selector
    var self = this

    this.mid = id++;
    this.markup = '<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>

';

    var matrix = data.matrix;
    var label = data.label;
    var color = utils.getColors(_.uniq(label).length);

    // get min and max of matrix value data
    var zmin = d3.min(data.matrix, function(d) {
        return d3.min(d, function(e) {
            return e.z
        });
    });
    var zmax = d3.max(data.matrix, function(d) {
        return d3.max(d, function(e) {
            return e.z
        });
    });

    // set up opacity scale
    var z = d3.scale.linear().domain([0, zmax/5]).range([0.3,1]).clamp(true);

    // set up x and y scales and ranges
    var nrow = matrix.length
    var ncol = matrix[0].length
    var y = d3.scale.ordinal().rangeBands([0, Math.min(width, height)]);
    var x = d3.scale.ordinal().rangeBands([0, Math.min(width, height)]);
    y.domain(d3.range(nrow).sort(function(a, b) { return label[b] - label[a]; }));
    x.domain(d3.range(ncol).sort(function(a, b) { return label[b] - label[a]; }))
    var maxY = nrow * y.rangeBand();
    var maxX = ncol * x.rangeBand();

    // bounds for the graphic
    var bounds = [[0, 0], [maxY, maxX]];

    // create the graphic as a map
    this.$el = $(selector).first();
    this.$el.append(this.markup);
    this.$el.find('#matrix-map-' + this.mid).width(maxX).height(maxY);

    var map = L.map('matrix-map-' + this.mid, {
        center: [maxX/2, maxY/2],
        attributionControl: false,
        zoomControl: false,
        crs: L.CRS.Simple,
    });

    // set the bounds
    map.fitBounds(bounds);
    map.setMaxBounds(bounds);

    // function for handling opacity
    var buildRGBA = function(fill, opacity) {
        var color = Color(fill);
        color.alpha(opacity);
        return color.rgbString();
    };
    buildRGBA = _.memoize(buildRGBA, function(fill, opacity) {
        return fill + ',' + opacity;
    });

    // render the rectangles
    setTimeout(function() {
        _.each(matrix, function(row, i) {
            _.each(row, function(cell, j) {
                var xPos = x(cell.x);
                var yPos = y(i);
                var b = [[yPos, xPos], [yPos + y.rangeBand(), xPos + x.rangeBand()]];
                if (label[i] == label[j]) {
                    var fillColor = color[label[i]]
                } else {
                    var fillColor = "rgb(50,50,50)"
                }
                if (cell.z > 0) {
                    var cellColor = buildRGBA(fillColor, z(cell.z))
                } else {
                    var cellColor = buildRGBA("rgb(240,240,240)", 1.0)
                }
                L.rectangle(b, {color: cellColor, weight: 0.7, className: "cell"}).addTo(map);
            });
        });
    }, 0);

};

Adjacency.prototype._formatData = function(data) {

    var matrix = [];
    var n = data.nodes.length
    data.nodes.forEach(function(node, i) {
        matrix[i] = d3.range(n).map(function(j) { return {x: j, y: i, z: 0}; });
    });

    data.links.forEach(function(link) {
        matrix[link[0]][link[1]].z = link[2];
        matrix[link[1]][link[0]].z = link[2];
        matrix[link[0]][link[0]].z = 1;
        matrix[link[1]][link[1]].z = 1;
    });

    data.matrix = matrix

    data.label = data.label ? data.label : _.times(n, _.constant(0))

    return data

}

module.exports = Adjacency;
<|endoftext|>


<commit_before>// VERSION 1.4.12

objName = 'tabGroups';
objPathString = 'tabgroups';
addonUUID = 'd9d0e890-860a-11e5-a837-0800200c9a66';

addonUris = {
	homepage: 'https://addons.mozilla.org/firefox/addon/tab-groups-panorama/',
	support: 'https://github.com/Quicksaver/Tab-Groups/issues',
	fullchangelog: 'https://github.com/Quicksaver/Tab-Groups/commits/master',
	email: 'quicksaver@gmail.com',
	profile: 'https://addons.mozilla.org/firefox/user/quicksaver/',
	api: 'http://fasezero.com/addons/api/tabgroups',
	development: 'http://fasezero.com/addons/'
};

prefList = {
	quickAccessButton: true,
	groupTitleInButton: true,

	displayMode: 'single',
	showGroupThumbs: true,
	gridDynamicSize: true,
	closeIfEmpty: true,
	stackTabs: true,
	showThumbs: true,
	showUrls: true,

	tabViewKeycode: 'E',
	tabViewAccel: true,
	tabViewShift: true,
	tabViewAlt: false,
	tabViewCtrl: false,

	quickAccessKeycode: 'none',
	quickAccessAccel: true,
	quickAccessShift: true,
	quickAccessAlt: false,
	quickAccessCtrl: false,

	nextGroupKeycode: '`',
	nextGroupAccel: true,
	nextGroupShift: false,
	nextGroupAlt: false,
	nextGroupCtrl: false,

	previousGroupKeycode: '`',
	previousGroupAccel: true,
	previousGroupShift: true,
	previousGroupAlt: false,
	previousGroupCtrl: false,

	noWarningsAboutSession: false,

	// for internal use
	pageAutoChanged: false,
	migratedWidget: false,
	migratedPrefs: false,
	migratedKeysets: false
};

// If we're initializing in a content process, we don't care about the rest
if(isContent) { throw 'isContent'; }

paneList = [
	[ "paneTabGroups", true ],
	[ "paneHowTo", true ],
	[ "paneSession", true ]
];

function startAddon(window) {
	prepareObject(window);
	window[objName].Modules.load('TabView', window.gBrowserInit);
}

function stopAddon(window) {
	removeObject(window);
}

// Don't rely on other modules being loaded here, make sure this can do the backup by itself.
function backupCurrentSession() {
	let tmp = {};
	Cu.import("resource:///modules/sessionstore/SessionStore.jsm", tmp);
	let osfile = Cu.import("resource://gre/modules/osfile.jsm");

	let prefix = objName+'-update.js-';

	// We can use the initTime as a seed/identifier to make sure every file has a unique name.
	// This is the same suffix syntax as the automated backups created by Firefox upgrades, except it uses a buildID instead
	// (which we don't have for the add-on, hence initTime instead).
	let filename = prefix+AddonData.initTime;

	// This is the folder where the automated backups created by Firefox upgrades are saved.
	let profileDir = osfile.OS.Constants.Path.profileDir;
	let backupsDir = osfile.OS.Path.join(profileDir, "sessionstore-backups");
	let filepath = osfile.OS.Path.join(backupsDir, filename);

	let state = tmp.SessionStore.getCurrentState();
	let saveState = (new osfile.TextEncoder()).encode(JSON.stringify(state));

	osfile.OS.File.open(filepath, { truncate: true }).then((ref) => {
		ref.write(saveState).then(() => {
			ref.close();

			// Don't keep backups indefinitely, follow the same rules as Firefox does, keep a limited number and rotate them out.
			let existingBackups = [];
			let iterator = new osfile.OS.File.DirectoryIterator(backupsDir);
			iterating = iterator.forEach((file) => {
				// a copy of the current session, for crash-protection
				if(file.name.startsWith(prefix)) {
					let val = parseInt(file.name.substr(prefix.length));
					existingBackups.push(val);
				}
			});
			iterating.then(
				function() {
					iterator.close();
					let max = Services.prefs.getIntPref('browser.sessionstore.upgradeBackup.maxUpgradeBackups');
					if(existingBackups.length > max) {
						// keep the most recently created files
						existingBackups.sort(function(a,b) { return b-a; });
						let toRemove = existingBackups.splice(3);
						for(let seed of toRemove) {
							let name = prefix+seed;
							let path = osfile.OS.Path.join(backupsDir, name);
							osfile.OS.File.remove(path);
						}
					}
				},
				function(reason) { iterator.close(); throw reason; }
			);
		});
	});
}

function onStartup() {
	// If this is the first startup after installing or updating the add-on, make a backup of the session, just in case.
	if(STARTED == ADDON_INSTALL || STARTED == ADDON_UPGRADE || STARTED == ADDON_DOWNGRADE) {
		// Don't block add-on startup if it fails to create the backup for some reason.
		try { backupCurrentSession(); }
		catch(ex) { Cu.reportError(ex); }
	}

	Modules.load('Utils');
	Modules.load('Storage');
	Modules.load('nativePrefs');
	Modules.load('migrate');
	Modules.load('compatibilityFix/sandboxFixes');
	Modules.load('keysets');

	// Scrollbar CSS code needs to be loaded as an AGENT sheet, otherwise it won't apply to scrollbars in non-xul documents.
	Styles.load('scrollbars', 'scrollbars', false, 'agent');

	// Apply the add-on to every window opened and to be opened
	Windows.callOnAll(startAddon, 'navigator:browser');
	Windows.register(startAddon, 'domwindowopened', 'navigator:browser');
}

function onShutdown() {
	// remove the add-on from all windows
	Windows.callOnAll(stopAddon, null, null, true);

	Styles.unload('scrollbars');

	Modules.unload('keysets');
	Modules.unload('compatibilityFix/sandboxFixes');
	Modules.unload('migrate');
	Modules.unload('nativePrefs');
	Modules.unload('Storage');
	Modules.unload('Utils');
}
<commit_msg>Closes #102 use correct default modifiers in OSX shorcuts<commit_after>// VERSION 1.4.13

objName = 'tabGroups';
objPathString = 'tabgroups';
addonUUID = 'd9d0e890-860a-11e5-a837-0800200c9a66';

addonUris = {
	homepage: 'https://addons.mozilla.org/firefox/addon/tab-groups-panorama/',
	support: 'https://github.com/Quicksaver/Tab-Groups/issues',
	fullchangelog: 'https://github.com/Quicksaver/Tab-Groups/commits/master',
	email: 'quicksaver@gmail.com',
	profile: 'https://addons.mozilla.org/firefox/user/quicksaver/',
	api: 'http://fasezero.com/addons/api/tabgroups',
	development: 'http://fasezero.com/addons/'
};

prefList = {
	quickAccessButton: true,
	groupTitleInButton: true,

	displayMode: 'single',
	showGroupThumbs: true,
	gridDynamicSize: true,
	closeIfEmpty: true,
	stackTabs: true,
	showThumbs: true,
	showUrls: true,

	tabViewKeycode: 'E',
	tabViewAccel: true,
	tabViewShift: true,
	tabViewAlt: false,
	tabViewCtrl: false,

	quickAccessKeycode: 'none',
	quickAccessAccel: true,
	quickAccessShift: true,
	quickAccessAlt: false,
	quickAccessCtrl: false,

	nextGroupKeycode: '`',
	nextGroupAccel: !DARWIN,
	nextGroupShift: false,
	nextGroupAlt: false,
	nextGroupCtrl: DARWIN,

	previousGroupKeycode: '`',
	previousGroupAccel: !DARWIN,
	previousGroupShift: true,
	previousGroupAlt: false,
	previousGroupCtrl: DARWIN,

	noWarningsAboutSession: false,

	// for internal use
	pageAutoChanged: false,
	migratedWidget: false,
	migratedPrefs: false,
	migratedKeysets: false
};

// If we're initializing in a content process, we don't care about the rest
if(isContent) { throw 'isContent'; }

paneList = [
	[ "paneTabGroups", true ],
	[ "paneHowTo", true ],
	[ "paneSession", true ]
];

function startAddon(window) {
	prepareObject(window);
	window[objName].Modules.load('TabView', window.gBrowserInit);
}

function stopAddon(window) {
	removeObject(window);
}

// Don't rely on other modules being loaded here, make sure this can do the backup by itself.
function backupCurrentSession() {
	let tmp = {};
	Cu.import("resource:///modules/sessionstore/SessionStore.jsm", tmp);
	let osfile = Cu.import("resource://gre/modules/osfile.jsm");

	let prefix = objName+'-update.js-';

	// We can use the initTime as a seed/identifier to make sure every file has a unique name.
	// This is the same suffix syntax as the automated backups created by Firefox upgrades, except it uses a buildID instead
	// (which we don't have for the add-on, hence initTime instead).
	let filename = prefix+AddonData.initTime;

	// This is the folder where the automated backups created by Firefox upgrades are saved.
	let profileDir = osfile.OS.Constants.Path.profileDir;
	let backupsDir = osfile.OS.Path.join(profileDir, "sessionstore-backups");
	let filepath = osfile.OS.Path.join(backupsDir, filename);

	let state = tmp.SessionStore.getCurrentState();
	let saveState = (new osfile.TextEncoder()).encode(JSON.stringify(state));

	osfile.OS.File.open(filepath, { truncate: true }).then((ref) => {
		ref.write(saveState).then(() => {
			ref.close();

			// Don't keep backups indefinitely, follow the same rules as Firefox does, keep a limited number and rotate them out.
			let existingBackups = [];
			let iterator = new osfile.OS.File.DirectoryIterator(backupsDir);
			iterating = iterator.forEach((file) => {
				// a copy of the current session, for crash-protection
				if(file.name.startsWith(prefix)) {
					let val = parseInt(file.name.substr(prefix.length));
					existingBackups.push(val);
				}
			});
			iterating.then(
				function() {
					iterator.close();
					let max = Services.prefs.getIntPref('browser.sessionstore.upgradeBackup.maxUpgradeBackups');
					if(existingBackups.length > max) {
						// keep the most recently created files
						existingBackups.sort(function(a,b) { return b-a; });
						let toRemove = existingBackups.splice(3);
						for(let seed of toRemove) {
							let name = prefix+seed;
							let path = osfile.OS.Path.join(backupsDir, name);
							osfile.OS.File.remove(path);
						}
					}
				},
				function(reason) { iterator.close(); throw reason; }
			);
		});
	});
}

function onStartup() {
	// If this is the first startup after installing or updating the add-on, make a backup of the session, just in case.
	if(STARTED == ADDON_INSTALL || STARTED == ADDON_UPGRADE || STARTED == ADDON_DOWNGRADE) {
		// Don't block add-on startup if it fails to create the backup for some reason.
		try { backupCurrentSession(); }
		catch(ex) { Cu.reportError(ex); }
	}

	Modules.load('Utils');
	Modules.load('Storage');
	Modules.load('nativePrefs');
	Modules.load('migrate');
	Modules.load('compatibilityFix/sandboxFixes');
	Modules.load('keysets');

	// Scrollbar CSS code needs to be loaded as an AGENT sheet, otherwise it won't apply to scrollbars in non-xul documents.
	Styles.load('scrollbars', 'scrollbars', false, 'agent');

	// Apply the add-on to every window opened and to be opened
	Windows.callOnAll(startAddon, 'navigator:browser');
	Windows.register(startAddon, 'domwindowopened', 'navigator:browser');
}

function onShutdown() {
	// remove the add-on from all windows
	Windows.callOnAll(stopAddon, null, null, true);

	Styles.unload('scrollbars');

	Modules.unload('keysets');
	Modules.unload('compatibilityFix/sandboxFixes');
	Modules.unload('migrate');
	Modules.unload('nativePrefs');
	Modules.unload('Storage');
	Modules.unload('Utils');
}
<|endoftext|>


<commit_before>document.getElementById("pre-text").innerHTML = '> Login: ' + getFullDate() + '
 > VISITOR-Device: ~visitorAccount$: ';

function getFullDate() {
	var d = new Date();
	var min = d.getMinutes();
	var secs = d.getSeconds();

	if (min < 10) {
		min = '0' + min;
	}

	if (secs < 10) {
		secs = '0' + secs;
	}

	var days = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'];
	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];

	return days[d.getDay()] + ' ' + months[d.getMonth()] + ' ' + d.getDate() + ' ' + d.getHours() + ':' + min + ':' + secs;
}

//TYPED.JS animation
$(function() {
	$(".type-text").typed({
		strings:["
 ^1250Hello, world! No, wait! Don't panic! You've come to the right place.

I'm Brandon Choi.
 ^800Developer, writer, photographer.

 ^500Press 'ENTER' to learn more about me and what I do.

 ^100START  "],
		typeSpeed: 35,
	});
});

//KEYPRESS LISTENER for ENTER --> about.html
$(document).keypress(function(e) {
	if (e.which == 13) {
		window.location = "../about/about.html";
	}
});

$("#start").click(function(){
	window.location = "../about/about.html";
});

<commit_msg>opener js with new pauses<commit_after>document.getElementById("pre-text").innerHTML = '> Login: ' + getFullDate() + '
 > VISITOR-Device: ~visitorAccount$: ';

function getFullDate() {
	var d = new Date();
	var min = d.getMinutes();
	var secs = d.getSeconds();

	if (min < 10) {
		min = '0' + min;
	}

	if (secs < 10) {
		secs = '0' + secs;
	}

	var days = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'];
	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];

	return days[d.getDay()] + ' ' + months[d.getMonth()] + ' ' + d.getDate() + ' ' + d.getHours() + ':' + min + ':' + secs;
}

//TYPED.JS animation
$(function() {
	$(".type-text").typed({
		strings:["
 ^1250Hello, world! ^600No, wait! Don't panic! You've come to the right place.

^650I'm Brandon Choi.
 ^800Developer, writer, photographer.

 ^500Press 'ENTER' to learn more about me and what I do.

 ^100START  "],
		typeSpeed: 35,
	});
});

//KEYPRESS LISTENER for ENTER --> about.html
$(document).keypress(function(e) {
	if (e.which == 13) {
		window.location = "../about/about.html";
	}
});

$("#start").click(function(){
	window.location = "../about/about.html";
});

<|endoftext|>


<commit_before>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

(function(document) {
  'use strict';

  // Grab a reference to our auto-binding template
  // and give it some initial binding values
  // Learn more about auto-binding templates at http://goo.gl/Dx1u2g
  var app = document.querySelector('#app');

  // Sets app default base URL
  app.baseUrl = '/';
  if (window.location.port === '') {  // if production
    // Uncomment app.baseURL below and
    // set app.baseURL to '/your-pathname/' if running from folder in production
    app.baseUrl = '/flamechamp.github.io/';
  }

  // Listen for template bound event to know when bindings
  // have resolved and content has been stamped to the page
  app.addEventListener('dom-change', function() {
    console.log('Our app is ready to rock!');
  });

  // See https://github.com/Polymer/polymer/issues/1381
  window.addEventListener('WebComponentsReady', function() {
    // imports are loaded and elements have been registered
  });

  // Main area's paper-scroll-header-panel custom condensing transformation of
  // the appName in the middle-container and the bottom title in the bottom-container.
  // The appName is moved to top and shrunk on condensing. The bottom sub title
  // is shrunk to nothing on condensing.
  window.addEventListener('paper-header-transform', function(e) {
    var appName = Polymer.dom(document).querySelector('#mainToolbar .app-name');
    var middleContainer = Polymer.dom(document).querySelector('#mainToolbar .middle-container');
    var bottomContainer = Polymer.dom(document).querySelector('#mainToolbar .bottom-container');
    var detail = e.detail;
    var heightDiff = detail.height - detail.condensedHeight;
    var yRatio = Math.min(1, detail.y / heightDiff);
    // appName max size when condensed. The smaller the number the smaller the condensed size.
    var maxMiddleScale = 0.50;
    var auxHeight = heightDiff - detail.y;
    var auxScale = heightDiff / (1 - maxMiddleScale);
    var scaleMiddle = Math.max(maxMiddleScale, auxHeight / auxScale + maxMiddleScale);
    var scaleBottom = 1 - yRatio;

    // Move/translate middleContainer
    Polymer.Base.transform('translate3d(0,' + yRatio * 100 + '%,0)', middleContainer);

    // Scale bottomContainer and bottom sub title to nothing and back
    Polymer.Base.transform('scale(' + scaleBottom + ') translateZ(0)', bottomContainer);

    // Scale middleContainer appName
    Polymer.Base.transform('scale(' + scaleMiddle + ') translateZ(0)', appName);
  });

  // Scroll page to top and expand header
  app.scrollPageToTop = function() {
    app.$.headerPanelMain.scrollToTop(true);
  };

  app.closeDrawer = function() {
    app.$.paperDrawerPanel.closeDrawer();
  };

})(document);
<commit_msg>Update app.js<commit_after>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

(function(document) {
  'use strict';

  // Grab a reference to our auto-binding template
  // and give it some initial binding values
  // Learn more about auto-binding templates at http://goo.gl/Dx1u2g
  var app = document.querySelector('#app');

  // Sets app default base URL
  app.baseUrl = '/';
  if (window.location.port === '') {  // if production
    // Uncomment app.baseURL below and
    // set app.baseURL to '/your-pathname/' if running from folder in production
    // app.baseUrl = '/flamechamp.github.io/';
  }

  // Listen for template bound event to know when bindings
  // have resolved and content has been stamped to the page
  app.addEventListener('dom-change', function() {
    console.log('Our app is ready to rock!');
  });

  // See https://github.com/Polymer/polymer/issues/1381
  window.addEventListener('WebComponentsReady', function() {
    // imports are loaded and elements have been registered
  });

  // Main area's paper-scroll-header-panel custom condensing transformation of
  // the appName in the middle-container and the bottom title in the bottom-container.
  // The appName is moved to top and shrunk on condensing. The bottom sub title
  // is shrunk to nothing on condensing.
  window.addEventListener('paper-header-transform', function(e) {
    var appName = Polymer.dom(document).querySelector('#mainToolbar .app-name');
    var middleContainer = Polymer.dom(document).querySelector('#mainToolbar .middle-container');
    var bottomContainer = Polymer.dom(document).querySelector('#mainToolbar .bottom-container');
    var detail = e.detail;
    var heightDiff = detail.height - detail.condensedHeight;
    var yRatio = Math.min(1, detail.y / heightDiff);
    // appName max size when condensed. The smaller the number the smaller the condensed size.
    var maxMiddleScale = 0.50;
    var auxHeight = heightDiff - detail.y;
    var auxScale = heightDiff / (1 - maxMiddleScale);
    var scaleMiddle = Math.max(maxMiddleScale, auxHeight / auxScale + maxMiddleScale);
    var scaleBottom = 1 - yRatio;

    // Move/translate middleContainer
    Polymer.Base.transform('translate3d(0,' + yRatio * 100 + '%,0)', middleContainer);

    // Scale bottomContainer and bottom sub title to nothing and back
    Polymer.Base.transform('scale(' + scaleBottom + ') translateZ(0)', bottomContainer);

    // Scale middleContainer appName
    Polymer.Base.transform('scale(' + scaleMiddle + ') translateZ(0)', appName);
  });

  // Scroll page to top and expand header
  app.scrollPageToTop = function() {
    app.$.headerPanelMain.scrollToTop(true);
  };

  app.closeDrawer = function() {
    app.$.paperDrawerPanel.closeDrawer();
  };

})(document);
<|endoftext|>


<commit_before>// tabs.js

// collect all the tabs
var tabs = $('.tab').attr('tabindex', '0');

// get an array of tab-panel ids
var tab_targets = tabs.map(function() {
    return this.hash;
}).get();

// use those ids to get the actual tab-panels
var tab_panels = $(tab_targets.join(','));

function showTab(id) {
    // if no id provided, use the id of the first panel
    id = !id ? tab_targets[0] : id;
    // remove the active class from the tabs,
    // and add it back to the one the user selected
    tabs.removeClass('active').attr('aria-selected', 'false').filter(function() {
        return (this.hash === id);
    }).addClass('active').attr('aria-selected', 'true');
    // hide all the panels, then filter to the one
    // we're interested in and show it
    tab_panels.find('.tab-panel-heading').hide();
    tab_panels.hide().attr('aria-hidden', 'true').filter(id).show().attr('aria-hidden', 'false');
    console.log('Switched to tab:', id);
}

$(window).on('hashchange', function() {
    // check if the hash is a target
    var hash = location.hash;
    if (tab_targets.indexOf(hash) !== -1) {
        showTab(hash);
    }
});

// initialize
showTab(tab_targets.indexOf(location.hash) !== -1 ? location.hash : '');
<commit_msg>escapes showTab if no tab being shown<commit_after>// tabs.js

// collect all the tabs
var tabs = $('.tab').attr('tabindex', '0');

// get an array of tab-panel ids
var tab_targets = tabs.map(function() {
    return this.hash;
}).get();

// use those ids to get the actual tab-panels
var tab_panels = $(tab_targets.join(','));

function showTab(id) {
    // if no id provided, use the id of the first panel
    id = !id ? tab_targets[0] : id;
    if (!id) {
        return
    }
    // remove the active class from the tabs,
    // and add it back to the one the user selected
    tabs.removeClass('active').attr('aria-selected', 'false').filter(function() {
        return (this.hash === id);
    }).addClass('active').attr('aria-selected', 'true');
    // hide all the panels, then filter to the one
    // we're interested in and show it
    tab_panels.find('.tab-panel-heading').hide();
    tab_panels.hide().attr('aria-hidden', 'true').filter(id).show().attr('aria-hidden', 'false');
    console.log('Switched to tab:', id);
}

$(window).on('hashchange', function() {
    // check if the hash is a target
    var hash = location.hash;
    if (tab_targets.indexOf(hash) !== -1) {
        showTab(hash);
    }
});

// initialize
showTab(tab_targets.indexOf(location.hash) !== -1 ? location.hash : '');
<|endoftext|>


<commit_before>//= require ./lib
//= require ./extension
//= require ./models
//= require ./Config
//= require ./react
//= require ./components
//= require ./screens
//= require ./extension/LateLoaded
//= require ./Boot

import Config from './config';
import Boot from './boot';
<commit_msg>remove asset_pipeline gunk<commit_after>import Boot from './boot';
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// @ts-nocheck
// TODO(crbug.com/1011811): Enable TypeScript compiler checks

import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as Host from '../host/host.js';
import * as PerfUI from '../perf_ui/perf_ui.js';
import * as SDK from '../sdk/sdk.js';
import * as UI from '../ui/ui.js';

import {ProfileFlameChartDataProvider} from './CPUProfileFlameChart.js';
import {Formatter, ProfileDataGridNode} from './ProfileDataGrid.js';           // eslint-disable-line no-unused-vars
import {ProfileEvents, ProfileHeader, ProfileType} from './ProfileHeader.js';  // eslint-disable-line no-unused-vars
import {ProfileView, WritableProfileHeader} from './ProfileView.js';

/**
 * @implements {UI.SearchableView.Searchable}
 * @unrestricted
 */
export class CPUProfileView extends ProfileView {
  /**
   * @param {!CPUProfileHeader} profileHeader
   */
  constructor(profileHeader) {
    super();
    this._profileHeader = profileHeader;
    this.initialize(new NodeFormatter(this));
    const profile = profileHeader.profileModel();
    this.adjustedTotal = profile.profileHead.total;
    this.adjustedTotal -= profile.idleNode ? profile.idleNode.total : 0;
    this.setProfile(profile);
  }

  /**
   * @override
   */
  wasShown() {
    super.wasShown();
    PerfUI.LineLevelProfile.Performance.instance().reset();
    PerfUI.LineLevelProfile.Performance.instance().appendCPUProfile(this._profileHeader.profileModel());
  }

  /**
   * @override
   * @param {string} columnId
   * @return {string}
   */
  columnHeader(columnId) {
    switch (columnId) {
      case 'self':
        return Common.UIString.UIString('Self Time');
      case 'total':
        return Common.UIString.UIString('Total Time');
    }
    return '';
  }

  /**
   * @override
   * @return {!ProfileFlameChartDataProvider}
   */
  createFlameChartDataProvider() {
    return new CPUFlameChartDataProvider(this._profileHeader.profileModel(), this._profileHeader._cpuProfilerModel);
  }
}

/**
 * @unrestricted
 */
export class CPUProfileType extends ProfileType {
  constructor() {
    super(CPUProfileType.TypeId, Common.UIString.UIString('Record JavaScript CPU Profile'));
    this._recording = false;

    CPUProfileType.instance = this;
    SDK.SDKModel.TargetManager.instance().addModelListener(
        SDK.CPUProfilerModel.CPUProfilerModel, SDK.CPUProfilerModel.Events.ConsoleProfileFinished,
        this._consoleProfileFinished, this);
  }

  /**
   * @override
   * @return {?CPUProfileHeader}
   */
  profileBeingRecorded() {
    return /** @type {?CPUProfileHeader} */ (super.profileBeingRecorded());
  }

  /**
   * @override
   * @return {string}
   */
  typeName() {
    return 'CPU';
  }

  /**
   * @override
   * @return {string}
   */
  fileExtension() {
    return '.cpuprofile';
  }

  /**
   * @override
   */
  get buttonTooltip() {
    return this._recording ? Common.UIString.UIString('Stop CPU profiling') :
                             Common.UIString.UIString('Start CPU profiling');
  }

  /**
   * @override
   * @return {boolean}
   */
  buttonClicked() {
    if (this._recording) {
      this._stopRecordingProfile();
      return false;
    }
    this._startRecordingProfile();
    return true;
  }

  /**
   * @override
   */
  get treeItemTitle() {
    return Common.UIString.UIString('CPU PROFILES');
  }

  /**
   * @override
   */
  get description() {
    return Common.UIString.UIString(
        'CPU profiles show where the execution time is spent in your page\'s JavaScript functions.');
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _consoleProfileFinished(event) {
    const data = /** @type {!SDK.CPUProfilerModel.EventData} */ (event.data);
    const cpuProfile = /** @type {!Protocol.Profiler.Profile} */ (data.cpuProfile);
    const profile = new CPUProfileHeader(data.cpuProfilerModel, this, data.title);
    profile.setProtocolProfile(cpuProfile);
    this.addProfile(profile);
  }

  _startRecordingProfile() {
    const cpuProfilerModel = UI.Context.Context.instance().flavor(SDK.CPUProfilerModel.CPUProfilerModel);
    if (this.profileBeingRecorded() || !cpuProfilerModel) {
      return;
    }
    const profile = new CPUProfileHeader(cpuProfilerModel, this);
    this.setProfileBeingRecorded(profile);
    SDK.SDKModel.TargetManager.instance().suspendAllTargets();
    this.addProfile(profile);
    profile.updateStatus(Common.UIString.UIString('Recording…'));
    this._recording = true;
    cpuProfilerModel.startRecording();
    Host.userMetrics.actionTaken(Host.UserMetrics.Action.ProfilesCPUProfileTaken);
  }

  async _stopRecordingProfile() {
    this._recording = false;
    if (!this.profileBeingRecorded() || !this.profileBeingRecorded()._cpuProfilerModel) {
      return;
    }

    const profile = await this.profileBeingRecorded()._cpuProfilerModel.stopRecording();
    const recordedProfile = this.profileBeingRecorded();
    if (recordedProfile) {
      console.assert(profile);
      recordedProfile.setProtocolProfile(profile);
      recordedProfile.updateStatus('');
      this.setProfileBeingRecorded(null);
    }

    await SDK.SDKModel.TargetManager.instance().resumeAllTargets();
    this.dispatchEventToListeners(ProfileEvents.ProfileComplete, recordedProfile);
  }

  /**
   * @override
   * @param {string} title
   * @return {!ProfileHeader}
   */
  createProfileLoadedFromFile(title) {
    return new CPUProfileHeader(null, this, title);
  }

  /**
   * @override
   */
  profileBeingRecordedRemoved() {
    this._stopRecordingProfile();
  }
}

CPUProfileType.TypeId = 'CPU';

/**
 * @unrestricted
 */
export class CPUProfileHeader extends WritableProfileHeader {
  /**
   * @param {?SDK.CPUProfilerModel.CPUProfilerModel} cpuProfilerModel
   * @param {!CPUProfileType} type
   * @param {string=} title
   */
  constructor(cpuProfilerModel, type, title) {
    super(cpuProfilerModel && cpuProfilerModel.debuggerModel(), type, title);
    this._cpuProfilerModel = cpuProfilerModel;
  }

  /**
   * @override
   * @return {!ProfileView}
   */
  createView() {
    return new CPUProfileView(this);
  }

  /**
   * @return {!Protocol.Profiler.Profile}
   */
  protocolProfile() {
    return this._protocolProfile;
  }

  /**
   * @return {!SDK.CPUProfileDataModel.CPUProfileDataModel}
   */
  profileModel() {
    return this._profileModel;
  }

  /**
   * @override
   * @param {!Protocol.Profiler.Profile} profile
   */
  setProfile(profile) {
    const target = this._cpuProfilerModel && this._cpuProfilerModel.target() || null;
    this._profileModel = new SDK.CPUProfileDataModel.CPUProfileDataModel(profile, target);
  }
}

/**
 * @implements {Formatter}
 * @unrestricted
 */
export class NodeFormatter {
  /**
   * @param {!CPUProfileView} profileView
   */
  constructor(profileView) {
    this._profileView = profileView;
  }

  /**
   * @override
   * @param {number} value
   * @return {string}
   */
  formatValue(value) {
    return Common.UIString.UIString('%.1f\xa0ms', value);
  }

  /**
   * @override
   * @param {number} value
   * @return {string}
   */
  formatValueAccessibleText(value) {
    return this.formatValue(value);
  }

  /**
   * @override
   * @param {number} value
   * @param {!ProfileDataGridNode} node
   * @return {string}
   */
  formatPercent(value, node) {
    return node.profileNode === this._profileView.profile().idleNode ? '' :
                                                                       Common.UIString.UIString('%.2f\xa0%%', value);
  }

  /**
   * @override
   * @param  {!ProfileDataGridNode} node
   * @return {?Element}
   */
  linkifyNode(node) {
    const cpuProfilerModel = this._profileView._profileHeader._cpuProfilerModel;
    const target = cpuProfilerModel ? cpuProfilerModel.target() : null;
    const options = {className: 'profile-node-file'};
    return this._profileView.linkifier().maybeLinkifyConsoleCallFrame(target, node.profileNode.callFrame, options);
  }
}

/**
 * @unrestricted
 */
export class CPUFlameChartDataProvider extends ProfileFlameChartDataProvider {
  /**
   * @param {!SDK.CPUProfileDataModel.CPUProfileDataModel} cpuProfile
   * @param {?SDK.CPUProfilerModel.CPUProfilerModel} cpuProfilerModel
   */
  constructor(cpuProfile, cpuProfilerModel) {
    super();
    this._cpuProfile = cpuProfile;
    this._cpuProfilerModel = cpuProfilerModel;
  }

  /**
   * @override
   * @return {!PerfUI.FlameChart.TimelineData}
   */
  _calculateTimelineData() {
    /** @type {!Array.<?CPUFlameChartDataProvider.ChartEntry>} */
    const entries = [];
    /** @type {!Array.<number>} */
    const stack = [];
    let maxDepth = 5;

    function onOpenFrame() {
      stack.push(entries.length);
      // Reserve space for the entry, as they have to be ordered by startTime.
      // The entry itself will be put there in onCloseFrame.
      entries.push(null);
    }
    /**
     * @param {number} depth
     * @param {!SDK.CPUProfileDataModel.CPUProfileNode} node
     * @param {number} startTime
     * @param {number} totalTime
     * @param {number} selfTime
     */
    function onCloseFrame(depth, node, startTime, totalTime, selfTime) {
      const index = stack.pop();
      entries[index] = new CPUFlameChartDataProvider.ChartEntry(depth, totalTime, startTime, selfTime, node);
      maxDepth = Math.max(maxDepth, depth);
    }
    this._cpuProfile.forEachFrame(onOpenFrame, onCloseFrame);

    /** @type {!Array<!SDK.CPUProfileDataModel.CPUProfileNode>} */
    const entryNodes = new Array(entries.length);
    const entryLevels = new Uint16Array(entries.length);
    const entryTotalTimes = new Float32Array(entries.length);
    const entrySelfTimes = new Float32Array(entries.length);
    const entryStartTimes = new Float64Array(entries.length);

    for (let i = 0; i < entries.length; ++i) {
      const entry = entries[i];
      entryNodes[i] = entry.node;
      entryLevels[i] = entry.depth;
      entryTotalTimes[i] = entry.duration;
      entryStartTimes[i] = entry.startTime;
      entrySelfTimes[i] = entry.selfTime;
    }

    this._maxStackDepth = maxDepth + 1;

    this._timelineData = new PerfUI.FlameChart.TimelineData(entryLevels, entryTotalTimes, entryStartTimes, null);

    /** @type {!Array<!SDK.CPUProfileDataModel.CPUProfileNode>} */
    this._entryNodes = entryNodes;
    this._entrySelfTimes = entrySelfTimes;

    return this._timelineData;
  }

  /**
   * @override
   * @param {number} entryIndex
   * @return {?Element}
   */
  prepareHighlightedEntryInfo(entryIndex) {
    const timelineData = this._timelineData;
    const node = this._entryNodes[entryIndex];
    if (!node) {
      return null;
    }

    const entryInfo = [];
    /**
     * @param {string} title
     * @param {string} value
     */
    function pushEntryInfoRow(title, value) {
      entryInfo.push({title: title, value: value});
    }
    /**
     * @param {number} ms
     * @return {string}
     */
    function millisecondsToString(ms) {
      if (ms === 0) {
        return '0';
      }
      if (ms < 1000) {
        return Common.UIString.UIString('%.1f\xa0ms', ms);
      }
      return Number.secondsToString(ms / 1000, true);
    }
    const name = UI.UIUtils.beautifyFunctionName(node.functionName);
    pushEntryInfoRow(ls`Name`, name);
    const selfTime = millisecondsToString(this._entrySelfTimes[entryIndex]);
    const totalTime = millisecondsToString(timelineData.entryTotalTimes[entryIndex]);
    pushEntryInfoRow(ls`Self time`, selfTime);
    pushEntryInfoRow(ls`Total time`, totalTime);
    const linkifier = new Components.Linkifier.Linkifier();
    const link = linkifier.maybeLinkifyConsoleCallFrame(
        this._cpuProfilerModel && this._cpuProfilerModel.target(), node.callFrame);
    if (link) {
      pushEntryInfoRow(ls`URL`, link.textContent);
    }
    linkifier.dispose();
    pushEntryInfoRow(ls`Aggregated self time`, Number.secondsToString(node.self / 1000, true));
    pushEntryInfoRow(ls`Aggregated total time`, Number.secondsToString(node.total / 1000, true));
    if (node.deoptReason) {
      pushEntryInfoRow(ls`Not optimized`, node.deoptReason);
    }

    return ProfileView.buildPopoverTable(entryInfo);
  }
}

/**
 * @unrestricted
 */
CPUFlameChartDataProvider.ChartEntry = class {
  /**
   * @param {number} depth
   * @param {number} duration
   * @param {number} startTime
   * @param {number} selfTime
   * @param {!SDK.CPUProfileDataModel.CPUProfileNode} node
   */
  constructor(depth, duration, startTime, selfTime, node) {
    this.depth = depth;
    this.duration = duration;
    this.startTime = startTime;
    this.selfTime = selfTime;
    this.node = node;
  }
};
<commit_msg>TypeScrip-ify profiler/CPUProfileView.js<commit_after>/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as Host from '../host/host.js';
import * as PerfUI from '../perf_ui/perf_ui.js';
import * as SDK from '../sdk/sdk.js';
import * as UI from '../ui/ui.js';

import {ProfileFlameChartDataProvider} from './CPUProfileFlameChart.js';
import {Formatter, ProfileDataGridNode} from './ProfileDataGrid.js';           // eslint-disable-line no-unused-vars
import {ProfileEvents, ProfileHeader, ProfileType} from './ProfileHeader.js';  // eslint-disable-line no-unused-vars
import {ProfileView, WritableProfileHeader} from './ProfileView.js';

/**
 * @implements {UI.SearchableView.Searchable}
 * @unrestricted
 */
export class CPUProfileView extends ProfileView {
  /**
   * @param {!CPUProfileHeader} profileHeader
   */
  constructor(profileHeader) {
    super();
    this._profileHeader = profileHeader;
    this.initialize(new NodeFormatter(this));
    const profile = profileHeader.profileModel();
    this.adjustedTotal = profile.profileHead.total;
    this.adjustedTotal -= profile.idleNode ? profile.idleNode.total : 0;
    this.setProfile(profile);
  }

  /**
   * @override
   */
  wasShown() {
    super.wasShown();
    PerfUI.LineLevelProfile.Performance.instance().reset();
    PerfUI.LineLevelProfile.Performance.instance().appendCPUProfile(this._profileHeader.profileModel());
  }

  /**
   * @override
   * @param {string} columnId
   * @return {string}
   */
  columnHeader(columnId) {
    switch (columnId) {
      case 'self':
        return Common.UIString.UIString('Self Time');
      case 'total':
        return Common.UIString.UIString('Total Time');
    }
    return '';
  }

  /**
   * @override
   * @return {!ProfileFlameChartDataProvider}
   */
  createFlameChartDataProvider() {
    return new CPUFlameChartDataProvider(this._profileHeader.profileModel(), this._profileHeader._cpuProfilerModel);
  }
}

/**
 * @unrestricted
 */
export class CPUProfileType extends ProfileType {
  constructor() {
    super(CPUProfileType.TypeId, Common.UIString.UIString('Record JavaScript CPU Profile'));
    this._recording = false;

    SDK.SDKModel.TargetManager.instance().addModelListener(
        SDK.CPUProfilerModel.CPUProfilerModel, SDK.CPUProfilerModel.Events.ConsoleProfileFinished,
        this._consoleProfileFinished, this);
  }

  /**
   * @override
   * @return {?CPUProfileHeader}
   */
  profileBeingRecorded() {
    return /** @type {?CPUProfileHeader} */ (super.profileBeingRecorded());
  }

  /**
   * @override
   * @return {string}
   */
  typeName() {
    return 'CPU';
  }

  /**
   * @override
   * @return {string}
   */
  fileExtension() {
    return '.cpuprofile';
  }

  /**
   * @override
   */
  get buttonTooltip() {
    return this._recording ? Common.UIString.UIString('Stop CPU profiling') :
                             Common.UIString.UIString('Start CPU profiling');
  }

  /**
   * @override
   * @return {boolean}
   */
  buttonClicked() {
    if (this._recording) {
      this._stopRecordingProfile();
      return false;
    }
    this._startRecordingProfile();
    return true;
  }

  /**
   * @override
   */
  get treeItemTitle() {
    return Common.UIString.UIString('CPU PROFILES');
  }

  /**
   * @override
   */
  get description() {
    return Common.UIString.UIString(
        'CPU profiles show where the execution time is spent in your page\'s JavaScript functions.');
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _consoleProfileFinished(event) {
    const data = /** @type {!SDK.CPUProfilerModel.EventData} */ (event.data);
    const cpuProfile = /** @type {!Protocol.Profiler.Profile} */ (data.cpuProfile);
    const profile = new CPUProfileHeader(data.cpuProfilerModel, this, data.title);
    profile.setProtocolProfile(cpuProfile);
    this.addProfile(profile);
  }

  _startRecordingProfile() {
    const cpuProfilerModel = UI.Context.Context.instance().flavor(SDK.CPUProfilerModel.CPUProfilerModel);
    if (this.profileBeingRecorded() || !cpuProfilerModel) {
      return;
    }
    const profile = new CPUProfileHeader(cpuProfilerModel, this);
    this.setProfileBeingRecorded(profile);
    SDK.SDKModel.TargetManager.instance().suspendAllTargets();
    this.addProfile(profile);
    profile.updateStatus(Common.UIString.UIString('Recording…'));
    this._recording = true;
    cpuProfilerModel.startRecording();
    Host.userMetrics.actionTaken(Host.UserMetrics.Action.ProfilesCPUProfileTaken);
  }

  async _stopRecordingProfile() {
    this._recording = false;
    const profileBeingRecorded = this.profileBeingRecorded();
    if (!profileBeingRecorded || !profileBeingRecorded._cpuProfilerModel) {
      return;
    }

    const profile = await profileBeingRecorded._cpuProfilerModel.stopRecording();
    const recordedProfile = this.profileBeingRecorded();
    if (recordedProfile) {
      if (!profile) {
        throw new Error('Expected profile to be non-null');
      }
      recordedProfile.setProtocolProfile(profile);
      recordedProfile.updateStatus('');
      this.setProfileBeingRecorded(null);
    }

    await SDK.SDKModel.TargetManager.instance().resumeAllTargets();
    this.dispatchEventToListeners(ProfileEvents.ProfileComplete, recordedProfile);
  }

  /**
   * @override
   * @param {string} title
   * @return {!ProfileHeader}
   */
  createProfileLoadedFromFile(title) {
    return new CPUProfileHeader(null, this, title);
  }

  /**
   * @override
   */
  profileBeingRecordedRemoved() {
    this._stopRecordingProfile();
  }
}

CPUProfileType.TypeId = 'CPU';

/**
 * @unrestricted
 */
export class CPUProfileHeader extends WritableProfileHeader {
  /**
   * @param {?SDK.CPUProfilerModel.CPUProfilerModel} cpuProfilerModel
   * @param {!CPUProfileType} type
   * @param {string=} title
   */
  constructor(cpuProfilerModel, type, title) {
    super(cpuProfilerModel && cpuProfilerModel.debuggerModel(), type, title);
    this._cpuProfilerModel = cpuProfilerModel;
  }

  /**
   * @override
   * @return {!ProfileView}
   */
  createView() {
    return new CPUProfileView(this);
  }

  /**
   * @return {!Protocol.Profiler.Profile}
   */
  protocolProfile() {
    if (!this._protocolProfile) {
      throw new Error('Expected _protocolProfile to be available');
    }
    return this._protocolProfile;
  }

  /**
   * @return {!SDK.CPUProfileDataModel.CPUProfileDataModel}
   */
  profileModel() {
    if (!this._profileModel) {
      throw new Error('Expected _profileModel to be available');
    }
    return this._profileModel;
  }

  /**
   * @override
   * @param {!Protocol.Profiler.Profile} profile
   */
  setProfile(profile) {
    const target = this._cpuProfilerModel && this._cpuProfilerModel.target() || null;
    this._profileModel = new SDK.CPUProfileDataModel.CPUProfileDataModel(profile, target);
  }
}

/**
 * @implements {Formatter}
 * @unrestricted
 */
export class NodeFormatter {
  /**
   * @param {!CPUProfileView} profileView
   */
  constructor(profileView) {
    this._profileView = profileView;
  }

  /**
   * @override
   * @param {number} value
   * @return {string}
   */
  formatValue(value) {
    return Common.UIString.UIString('%.1f\xa0ms', value);
  }

  /**
   * @override
   * @param {number} value
   * @return {string}
   */
  formatValueAccessibleText(value) {
    return this.formatValue(value);
  }

  /**
   * @override
   * @param {number} value
   * @param {!ProfileDataGridNode} node
   * @return {string}
   */
  formatPercent(value, node) {
    if (this._profileView) {
      const profile = this._profileView.profile();
      if (profile &&
          node.profileNode !== /** @type {!SDK.CPUProfileDataModel.CPUProfileDataModel} */ (profile).idleNode) {
        return Common.UIString.UIString('%.2f\xa0%%', value);
      }
    }
    return '';
  }

  /**
   * @override
   * @param  {!ProfileDataGridNode} node
   * @return {?Element}
   */
  linkifyNode(node) {
    const cpuProfilerModel = this._profileView._profileHeader._cpuProfilerModel;
    const target = cpuProfilerModel ? cpuProfilerModel.target() : null;
    const options = {className: 'profile-node-file', columnNumber: undefined, tabStop: undefined};
    return this._profileView.linkifier().maybeLinkifyConsoleCallFrame(target, node.profileNode.callFrame, options);
  }
}

/**
 * @unrestricted
 */
export class CPUFlameChartDataProvider extends ProfileFlameChartDataProvider {
  /**
   * @param {!SDK.CPUProfileDataModel.CPUProfileDataModel} cpuProfile
   * @param {?SDK.CPUProfilerModel.CPUProfilerModel} cpuProfilerModel
   */
  constructor(cpuProfile, cpuProfilerModel) {
    super();
    this._cpuProfile = cpuProfile;
    this._cpuProfilerModel = cpuProfilerModel;
  }

  /**
   * @override
   * @return {!PerfUI.FlameChart.TimelineData}
   */
  _calculateTimelineData() {
    /** @type {!Array.<?CPUFlameChartDataProvider.ChartEntry>} */
    const entries = [];
    /** @type {!Array.<number>} */
    const stack = [];
    let maxDepth = 5;

    function onOpenFrame() {
      stack.push(entries.length);
      // Reserve space for the entry, as they have to be ordered by startTime.
      // The entry itself will be put there in onCloseFrame.
      entries.push(null);
    }
    /**
     * @param {number} depth
     * @param {!SDK.CPUProfileDataModel.CPUProfileNode} node
     * @param {number} startTime
     * @param {number} totalTime
     * @param {number} selfTime
     */
    function onCloseFrame(depth, node, startTime, totalTime, selfTime) {
      const index = /** @type {number} */ (stack.pop());
      entries[index] = new CPUFlameChartDataProvider.ChartEntry(depth, totalTime, startTime, selfTime, node);
      maxDepth = Math.max(maxDepth, depth);
    }
    this._cpuProfile.forEachFrame(onOpenFrame, onCloseFrame);

    /** @type {!Array<!SDK.CPUProfileDataModel.CPUProfileNode>} */
    const entryNodes = new Array(entries.length);
    const entryLevels = new Uint16Array(entries.length);
    const entryTotalTimes = new Float32Array(entries.length);
    const entrySelfTimes = new Float32Array(entries.length);
    const entryStartTimes = new Float64Array(entries.length);

    for (let i = 0; i < entries.length; ++i) {
      const entry = entries[i];
      if (!entry) {
        continue;
      }
      entryNodes[i] = entry.node;
      entryLevels[i] = entry.depth;
      entryTotalTimes[i] = entry.duration;
      entryStartTimes[i] = entry.startTime;
      entrySelfTimes[i] = entry.selfTime;
    }

    this._maxStackDepth = maxDepth + 1;

    this._timelineData = new PerfUI.FlameChart.TimelineData(entryLevels, entryTotalTimes, entryStartTimes, null);

    /** @type {!Array<!SDK.CPUProfileDataModel.CPUProfileNode>} */
    this._entryNodes = entryNodes;
    this._entrySelfTimes = entrySelfTimes;

    return this._timelineData;
  }

  /**
   * @override
   * @param {number} entryIndex
   * @return {?Element}
   */
  prepareHighlightedEntryInfo(entryIndex) {
    if (!this._entryNodes) {
      return null;
    }
    const timelineData = this._timelineData;
    const node = this._entryNodes[entryIndex];
    if (!node) {
      return null;
    }

    /** @type {!Array<!{title: string, value: string}>} */
    const entryInfo = [];
    /**
     * @param {string} title
     * @param {string} value
     */
    function pushEntryInfoRow(title, value) {
      entryInfo.push({title: title, value: value});
    }
    /**
     * @param {number} ms
     * @return {string}
     */
    function millisecondsToString(ms) {
      if (ms === 0) {
        return '0';
      }
      if (ms < 1000) {
        return Common.UIString.UIString('%.1f\xa0ms', ms);
      }
      return Number.secondsToString(ms / 1000, true);
    }
    const name = UI.UIUtils.beautifyFunctionName(node.functionName);
    pushEntryInfoRow(ls`Name`, name);
    const selfTime = millisecondsToString(/** @type {!Float32Array} */ (this._entrySelfTimes)[entryIndex]);
    const totalTime =
        millisecondsToString(/** @type {!PerfUI.FlameChart.TimelineData} */ (timelineData).entryTotalTimes[entryIndex]);
    pushEntryInfoRow(ls`Self time`, selfTime);
    pushEntryInfoRow(ls`Total time`, totalTime);
    const linkifier = new Components.Linkifier.Linkifier();
    const link = linkifier.maybeLinkifyConsoleCallFrame(
        this._cpuProfilerModel && this._cpuProfilerModel.target(), node.callFrame);
    if (link) {
      pushEntryInfoRow(ls`URL`, link.textContent || '');
    }
    linkifier.dispose();
    pushEntryInfoRow(ls`Aggregated self time`, Number.secondsToString(node.self / 1000, true));
    pushEntryInfoRow(ls`Aggregated total time`, Number.secondsToString(node.total / 1000, true));
    if (node.deoptReason) {
      pushEntryInfoRow(ls`Not optimized`, node.deoptReason);
    }

    return ProfileView.buildPopoverTable(entryInfo);
  }
}

/**
 * @unrestricted
 */
CPUFlameChartDataProvider.ChartEntry = class {
  /**
   * @param {number} depth
   * @param {number} duration
   * @param {number} startTime
   * @param {number} selfTime
   * @param {!SDK.CPUProfileDataModel.CPUProfileNode} node
   */
  constructor(depth, duration, startTime, selfTime, node) {
    this.depth = depth;
    this.duration = duration;
    this.startTime = startTime;
    this.selfTime = selfTime;
    this.node = node;
  }
};
<|endoftext|>


<commit_before>document.write("woot");
<commit_msg>got some canvas shit workign<commit_after>$(function(){
	var theCanvas = $("canvas").get(0).getContext('2d');
	theCanvas.fillRect(10, 10, 40, 40);
});

<|endoftext|>


<commit_before>import Selection from "./Selection.js";

let modelist = ace.require("ace/ext/modelist");

export default class BasicTextEditor
{
  constructor(element, session)
  {
    this.element = element;
    this.element.className = "ace-editor-container"

    this.session = session;

    this.aceEditor = this.createEditor();

    this.selections = new Map();

    this.infoBar = this.createInfoBar();
    this.selectionInfo = this.createSelectionInfo();
    this.updateSelectionInfo();

    this.selection = this.aceEditor.getSelection();
    this.selection.on("changeCursor", () => this.updateSelectionInfo());
    this.selection.on("changeCursor", () => this.updateSelections());
    this.selection.on("changeSelection", () => this.updateSelections());
  }

  createEditor()
  {
    let editorElement = document.createElement("div");

    // create text editor
    let aceEditor = ace.edit(editorElement);
    aceEditor.$blockScrolling = Infinity;
    aceEditor.session.selection.clearSelection();

    let settings = this.session.settingsMenu.sections["Text Editor"];
    settings.subscribeEditor(aceEditor);

    this.element.appendChild(editorElement);

    return aceEditor;
  }

  createInfoBar()
  {
    let bar = document.createElement("div");
    bar.className = "bottom-bar";

    this.element.appendChild(bar);

    return bar;
  }

  createSelectionInfo()
  {
    let selectionInfoElement = document.createElement("span");
    selectionInfoElement.className = "selection-info";

    this.infoBar.appendChild(selectionInfoElement);

    return selectionInfoElement;
  }

  setSelections(userId, ranges)
  {
    this.removeSelections(userId);

    let selections = [];

    for(let range of ranges) {
      let selection = new Selection(userId, range, this.aceEditor, this.session);

      if(userId == this.session.id && range.isEmpty())
        selection.enableBlink();

      selections.push(selection);
    }

    this.selections.set(userId, selections);
  }

  removeSelections(userId) {
    let selections = this.selections.get(userId);

    if(!selections)
      return;

    for(let selection of selections) {
      selection.destroy();
    }

    this.selections.delete(userId);
  }

  updateSelections()
  {
    let ranges = this.selection.getAllRanges();

    this.setSelections(this.session.id, ranges);
  }

  updateHighlighter(path)
  {
    let mode = modelist.getModeForPath(path).mode;
    this.aceEditor.session.setMode(mode);
  }

  updateSelectionInfo()
  {
    let pos = this.aceEditor.getCursorPosition();
    this.selectionInfo.innerText = `Ln ${pos.row + 1}, Col ${pos.column + 1}`;
  }

  clearHistory()
  {
    this.aceEditor.session.setUndoManager(new ace.UndoManager());
  }

  destroy()
  {
    for(let [userId] in this.selections) {
      this.removeSelections(userId);
    }

    let settings = this.session.settingsMenu.sections["Text Editor"];
    settings.unsubscribeEditor(this.aceEditor);

    this.aceEditor.destroy();
  }
}
<commit_msg>Fix leak caused by using 'in' instead of 'of' for 'for' loops<commit_after>import Selection from "./Selection.js";

let modelist = ace.require("ace/ext/modelist");

export default class BasicTextEditor
{
  constructor(element, session)
  {
    this.element = element;
    this.element.className = "ace-editor-container"

    this.session = session;

    this.aceEditor = this.createEditor();

    this.selections = new Map();

    this.infoBar = this.createInfoBar();
    this.selectionInfo = this.createSelectionInfo();
    this.updateSelectionInfo();

    this.selection = this.aceEditor.getSelection();
    this.selection.on("changeCursor", () => this.updateSelectionInfo());
    this.selection.on("changeCursor", () => this.updateSelections());
    this.selection.on("changeSelection", () => this.updateSelections());
  }

  createEditor()
  {
    let editorElement = document.createElement("div");

    // create text editor
    let aceEditor = ace.edit(editorElement);
    aceEditor.$blockScrolling = Infinity;
    aceEditor.session.selection.clearSelection();

    let settings = this.session.settingsMenu.sections["Text Editor"];
    settings.subscribeEditor(aceEditor);

    this.element.appendChild(editorElement);

    return aceEditor;
  }

  createInfoBar()
  {
    let bar = document.createElement("div");
    bar.className = "bottom-bar";

    this.element.appendChild(bar);

    return bar;
  }

  createSelectionInfo()
  {
    let selectionInfoElement = document.createElement("span");
    selectionInfoElement.className = "selection-info";

    this.infoBar.appendChild(selectionInfoElement);

    return selectionInfoElement;
  }

  setSelections(userId, ranges)
  {
    this.removeSelections(userId);

    let selections = [];

    for(let range of ranges) {
      let selection = new Selection(userId, range, this.aceEditor, this.session);

      if(userId == this.session.id && range.isEmpty())
        selection.enableBlink();

      selections.push(selection);
    }

    this.selections.set(userId, selections);
  }

  removeSelections(userId) {
    let selections = this.selections.get(userId);

    if(!selections)
      return;

    for(let selection of selections) {
      selection.destroy();
    }

    this.selections.delete(userId);
  }

  updateSelections()
  {
    let ranges = this.selection.getAllRanges();

    this.setSelections(this.session.id, ranges);
  }

  updateHighlighter(path)
  {
    let mode = modelist.getModeForPath(path).mode;
    this.aceEditor.session.setMode(mode);
  }

  updateSelectionInfo()
  {
    let pos = this.aceEditor.getCursorPosition();
    this.selectionInfo.innerText = `Ln ${pos.row + 1}, Col ${pos.column + 1}`;
  }

  clearHistory()
  {
    this.aceEditor.session.setUndoManager(new ace.UndoManager());
  }

  destroy()
  {
    for(let [userId] of this.selections) {
      this.removeSelections(userId);
    }

    let settings = this.session.settingsMenu.sections["Text Editor"];
    settings.unsubscribeEditor(this.aceEditor);

    this.aceEditor.destroy();
  }
}
<|endoftext|>


<commit_before>var r = g = b = 255; // White by default.

document.querySelector('#connect').addEventListener('click', function() {
  document.querySelector('#state').classList.add('connecting');
  playbulbCandle.connect()
  .then(() => {
    document.querySelector('#state').classList.remove('connecting');
    document.querySelector('#state').classList.add('connected');
    return playbulbCandle.getDeviceName().then(handleDeviceName)
    .then(() => playbulbCandle.getBatteryLevel().then(handleBatteryLevel));
  })
  .catch(error => {
    // TODO: Replace with toast when snackbar lands.
    console.error('Argh!', error);
  });
});

function handleDeviceName(deviceName) {
  document.querySelector('#deviceName').value = deviceName;
}

function handleBatteryLevel(batteryLevel) {
  document.querySelector('#batteryLevel').textContent = batteryLevel + '%';
}

/* Device name */

document.querySelector('#deviceName').addEventListener('input', function() {
  playbulbCandle.setDeviceName(this.value)
  .catch(error => {
    console.error('Argh!', error);
  });
});

/* Color picker */

var img = new Image();
img.src = 'color-wheel.png'
img.onload = function() {
  var canvas = document.querySelector('canvas');
  var context = canvas.getContext('2d');

  canvas.width = 300 * devicePixelRatio;
  canvas.height = 300 * devicePixelRatio;
  canvas.style.width = "300px";
  canvas.style.height = "300px";
  canvas.addEventListener('click', function(evt) {
    // Refresh canvas in case user zooms and devicePixelRatio changes.
    canvas.width = 300 * devicePixelRatio;
    canvas.height = 300 * devicePixelRatio;
    context.drawImage(img, 0, 0, canvas.width, canvas.height);

    var rect = canvas.getBoundingClientRect();
    var x = Math.round((evt.clientX - rect.left) * devicePixelRatio);
    var y = Math.round((evt.clientY - rect.top) * devicePixelRatio);
    var data = context.getImageData(0, 0, canvas.width, canvas.height).data;

    r = data[((canvas.width * y) + x) * 4];
    g = data[((canvas.width * y) + x) * 4 + 1];
    b = data[((canvas.width * y) + x) * 4 + 2];

    changeColor();

    context.beginPath();
    context.arc(x, y + 2, 10 * devicePixelRatio, 0, 2 * Math.PI, false);
    context.shadowColor = '#333';
    context.shadowBlur = 4 * devicePixelRatio;
    context.fillStyle = 'white';
    context.fill();
  });

  context.drawImage(img, 0, 0, canvas.width, canvas.height);
}

/* Color effects */

document.querySelector('#noEffect').addEventListener('click', changeColor);
document.querySelector('#candleEffect').addEventListener('click', changeColor);
document.querySelector('#flashing').addEventListener('click', changeColor);
document.querySelector('#pulse').addEventListener('click', changeColor);
document.querySelector('#rainbow').addEventListener('click', changeColor);
document.querySelector('#rainbowFade').addEventListener('click', changeColor);

function changeColor() {
  var effect = document.querySelector('[name="effectSwitch"]:checked').id;
  switch(effect) {
    case 'noEffect':
      playbulbCandle.setColor(r, g, b).then(onColorChanged);
      break;
    case 'candleEffect':
      playbulbCandle.setCandleEffectColor(r, g, b).then(onColorChanged);
      break;
    case 'flashing':
      playbulbCandle.setFlashingColor(r, g, b).then(onColorChanged);
      break;
    case 'pulse':
      playbulbCandle.setPulseColor(r, g, b).then(onColorChanged);
      break;
    case 'rainbow':
      playbulbCandle.setRainbow().then(onColorChanged);
      break;
    case 'rainbowFade':
      playbulbCandle.setRainbowFade().then(onColorChanged);
      break;
  }
}

function onColorChanged(rgb) {
  if (rgb) {
    console.log('Color changed to ' + rgb);
    r = rgb[0];
    g = rgb[1];
    b = rgb[2];
  } else {
    console.log('Color changed');
  }
}

window.onload = function() {
  var connect = document.getElementById("connect");
  var no_bt = document.getElementById("no-bluetooth");
  if (navigator.bluetooth == undefined) {
    console.log("No navigator.bluetooth found.");
    connect.style.display = "none";
    no_bt.style.display = "block";
  } else {
    connect.style.display = "block";
    no_bt.style.display = "none";
  }
  screen.orientation.lock('portrait').catch(e => e);
};
<commit_msg>playbulb: Handle touchmove events<commit_after>var r = g = b = 255; // White by default.

document.querySelector('#connect').addEventListener('click', function() {
  document.querySelector('#state').classList.add('connecting');
  playbulbCandle.connect()
  .then(() => {
    document.querySelector('#state').classList.remove('connecting');
    document.querySelector('#state').classList.add('connected');
    return playbulbCandle.getDeviceName().then(handleDeviceName)
    .then(() => playbulbCandle.getBatteryLevel().then(handleBatteryLevel));
  })
  .catch(error => {
    // TODO: Replace with toast when snackbar lands.
    console.error('Argh!', error);
  });
});

function handleDeviceName(deviceName) {
  document.querySelector('#deviceName').value = deviceName;
}

function handleBatteryLevel(batteryLevel) {
  document.querySelector('#batteryLevel').textContent = batteryLevel + '%';
}

/* Device name */

document.querySelector('#deviceName').addEventListener('input', function() {
  playbulbCandle.setDeviceName(this.value)
  .catch(error => {
    console.error('Argh!', error);
  });
});

/* Color picker */

var img = new Image();
img.src = 'color-wheel.png'
img.onload = function() {
  var canvas = document.querySelector('canvas');
  var context = canvas.getContext('2d');

  canvas.width = 300 * devicePixelRatio;
  canvas.height = 300 * devicePixelRatio;
  canvas.style.width = "300px";
  canvas.style.height = "300px";

  canvas.addEventListener('click', draw);
  canvas.addEventListener('touchmove', function(evt) {
    evt.preventDefault();
    draw(evt.targetTouches[0]);
  });

  function draw(evt) {
    // Refresh canvas in case user zooms and devicePixelRatio changes.
    canvas.width = 300 * devicePixelRatio;
    canvas.height = 300 * devicePixelRatio;
    context.drawImage(img, 0, 0, canvas.width, canvas.height);

    var rect = canvas.getBoundingClientRect();
    var x = Math.round((evt.clientX - rect.left) * devicePixelRatio);
    var y = Math.round((evt.clientY - rect.top) * devicePixelRatio);
    var data = context.getImageData(0, 0, canvas.width, canvas.height).data;

    r = data[((canvas.width * y) + x) * 4];
    g = data[((canvas.width * y) + x) * 4 + 1];
    b = data[((canvas.width * y) + x) * 4 + 2];

    changeColor();

    context.beginPath();
    context.arc(x, y + 2, 10 * devicePixelRatio, 0, 2 * Math.PI, false);
    context.shadowColor = '#333';
    context.shadowBlur = 4 * devicePixelRatio;
    context.fillStyle = 'white';
    context.fill();
  };

  context.drawImage(img, 0, 0, canvas.width, canvas.height);
}

/* Color effects */

document.querySelector('#noEffect').addEventListener('click', changeColor);
document.querySelector('#candleEffect').addEventListener('click', changeColor);
document.querySelector('#flashing').addEventListener('click', changeColor);
document.querySelector('#pulse').addEventListener('click', changeColor);
document.querySelector('#rainbow').addEventListener('click', changeColor);
document.querySelector('#rainbowFade').addEventListener('click', changeColor);

var colorChanging = false;

function changeColor() {
  if (colorChanging) {
    return;
  }
  colorChanging = true;
  var effect = document.querySelector('[name="effectSwitch"]:checked').id;
  switch(effect) {
    case 'noEffect':
      playbulbCandle.setColor(r, g, b).then(onColorChanged);
      break;
    case 'candleEffect':
      playbulbCandle.setCandleEffectColor(r, g, b).then(onColorChanged);
      break;
    case 'flashing':
      playbulbCandle.setFlashingColor(r, g, b).then(onColorChanged);
      break;
    case 'pulse':
      playbulbCandle.setPulseColor(r, g, b).then(onColorChanged);
      break;
    case 'rainbow':
      playbulbCandle.setRainbow().then(onColorChanged);
      break;
    case 'rainbowFade':
      playbulbCandle.setRainbowFade().then(onColorChanged);
      break;
  }
}

function onColorChanged(rgb) {
  if (rgb) {
    console.log('Color changed to ' + rgb);
    r = rgb[0];
    g = rgb[1];
    b = rgb[2];
  } else {
    console.log('Color changed');
  }
  colorChanging = false;
}

window.addEventListener('unhandledrejection', function() {
  colorChanging = false;
});

window.onload = function() {
  var connect = document.getElementById("connect");
  var no_bt = document.getElementById("no-bluetooth");
  if (navigator.bluetooth == undefined) {
    console.log("No navigator.bluetooth found.");
    connect.style.display = "none";
    no_bt.style.display = "block";
  } else {
    connect.style.display = "block";
    no_bt.style.display = "none";
  }
  screen.orientation.lock('portrait').catch(e => e);
};
<|endoftext|>


<commit_before>{% comment %}

This is the template which generates src/js/hutmap/models.js
Context:
{
  'models': [
    {'name': 'model1', 'fields': ['field1', 'field2', ...]},
    ...
  ]
}

{% endcomment %}

// This file generated from the template at scripts/make/generate/templates/models.js
// Please do not edit by hand.
{% for model in models %}
goog.provide('hutmap.{{ model.name }}');
{% endfor %}
goog.requier('goog.asserts');
goog.require('goog.array');
goog.require('goog.object');

{% for model in models %}
hutmap.{{ model.name }} = function(values) {
  if (!values)
    values = {};

  if (goog.DEBUG) {
    this._check_ctor_args(values);
  }

  {% for field in model.fields %}
  this.{{ field }} = (values.{{ field }} == undefined) ? null : values.{{ field }};
  {% for model2 in models %}
  {% ifequal model2.name|lower field|lower %}
  {% ifnotequal model.name|lower field|lower %}
  this.{{ field }} = new hutmap.{{ model2.name }}(this.{{ field }});
  {% endifnotequal %}
  {% endifequal %}
  {% endfor %}
  {% endfor %}

  {% for field in model.fields %}
  if (this.{{ field }} !== undefined &&
      this.{{ field }} !== null &&
      this.{{ field }} !== '') {
    this.{{ field }}_display =  this.{{ field }};
  } else {
    this.{{ field }}_display = 'unknown';
    {% for model2 in models %}
    {% ifequal model2.name|lower field|lower %}
    {% ifnotequal model.name|lower field|lower %}
    this.{{ field }}_display = new hutmap.{{ model2.name }}();
    {% endifnotequal %}
    {% endifequal %}
    {% endfor %}
  }
  {% endfor %}

  if (goog.DEBUG) {
    this._check_rep();
  }
};

hutmap.{{ model.name }}.prototype._check_ctor_args = function(values) {
  keys = goog.object.getKeys(values);
  fields = [
    {# put all methods added to the models here #}
    'equals',
    {% for field in model.fields %}
    '{{ field }}',
    {% if not forloop.last %}
    '{{ field }}_display',
    {% else %}
    '{{ field }}_display'
    {% endif %}
    {% endfor %}
  ];
  goog.array.forEach(keys, function(key, index, array) {
    if (!goog.array.contains(fields, key)) {
      throw "hutmap.{{ model.name }}(): Invalid field '" + key + "' given in values parameter.";
    }
  });
};

hutmap.{{ model.name }}.prototype._check_rep = function() {
  {% if 'id' in model.fields %}
  goog.asserts.assertNumber(this.id);
  goog.asserts.assert(this.id >= 0);
  {% endif %}
};

hutmap.{{ model.name }}.prototype.equals = function(other) {
  {% for field in model.fields %}
  {% if forloop.first %}
  return this.{{ field }} === other.{{ field }} &&
  {% endif %}
  {% if not forloop.first and not forloop.last %}
    this.{{ field }} === other.{{ field }} &&
  {% endif %}
  {% if forloop.last %}
    this.{{ field }} === other.{{ field }};
  {% endif %}
  {% endfor %}
};
{% endfor %}
<commit_msg>Fixed typo.<commit_after>{% comment %}

This is the template which generates src/js/hutmap/models.js
Context:
{
  'models': [
    {'name': 'model1', 'fields': ['field1', 'field2', ...]},
    ...
  ]
}

{% endcomment %}

// This file generated from the template at scripts/make/generate/templates/models.js
// Please do not edit by hand.
{% for model in models %}
goog.provide('hutmap.{{ model.name }}');
{% endfor %}
goog.require('goog.asserts');
goog.require('goog.array');
goog.require('goog.object');

{% for model in models %}
hutmap.{{ model.name }} = function(values) {
  if (!values)
    values = {};

  if (goog.DEBUG) {
    this._check_ctor_args(values);
  }

  {% for field in model.fields %}
  this.{{ field }} = (values.{{ field }} == undefined) ? null : values.{{ field }};
  {% for model2 in models %}
  {% ifequal model2.name|lower field|lower %}
  {% ifnotequal model.name|lower field|lower %}
  this.{{ field }} = new hutmap.{{ model2.name }}(this.{{ field }});
  {% endifnotequal %}
  {% endifequal %}
  {% endfor %}
  {% endfor %}

  {% for field in model.fields %}
  if (this.{{ field }} !== undefined &&
      this.{{ field }} !== null &&
      this.{{ field }} !== '') {
    this.{{ field }}_display =  this.{{ field }};
  } else {
    this.{{ field }}_display = 'unknown';
    {% for model2 in models %}
    {% ifequal model2.name|lower field|lower %}
    {% ifnotequal model.name|lower field|lower %}
    this.{{ field }}_display = new hutmap.{{ model2.name }}();
    {% endifnotequal %}
    {% endifequal %}
    {% endfor %}
  }
  {% endfor %}

  if (goog.DEBUG) {
    this._check_rep();
  }
};

hutmap.{{ model.name }}.prototype._check_ctor_args = function(values) {
  keys = goog.object.getKeys(values);
  fields = [
    {# put all methods added to the models here #}
    'equals',
    {% for field in model.fields %}
    '{{ field }}',
    {% if not forloop.last %}
    '{{ field }}_display',
    {% else %}
    '{{ field }}_display'
    {% endif %}
    {% endfor %}
  ];
  goog.array.forEach(keys, function(key, index, array) {
    if (!goog.array.contains(fields, key)) {
      throw "hutmap.{{ model.name }}(): Invalid field '" + key + "' given in values parameter.";
    }
  });
};

hutmap.{{ model.name }}.prototype._check_rep = function() {
  {% if 'id' in model.fields %}
  goog.asserts.assertNumber(this.id);
  goog.asserts.assert(this.id >= 0);
  {% endif %}
};

hutmap.{{ model.name }}.prototype.equals = function(other) {
  {% for field in model.fields %}
  {% if forloop.first %}
  return this.{{ field }} === other.{{ field }} &&
  {% endif %}
  {% if not forloop.first and not forloop.last %}
    this.{{ field }} === other.{{ field }} &&
  {% endif %}
  {% if forloop.last %}
    this.{{ field }} === other.{{ field }};
  {% endif %}
  {% endfor %}
};
{% endfor %}
<|endoftext|>