<commit_before>"use strict";

var Discord = require("discord.io");
var fs = require('fs');
var logger = require("winston");
var dlog = require("./lib/dlog.js");

var lib = {};

lib.comic = require("./lib/comic.js");
lib.dave = async function(logger, client, user, userID, channelID, args) {
				client.sendMessage({
					to: channelID,
					message: "OtherDave is not David."
				});
		   };
lib.drunkdraw = require("./lib/drunkdraw.js");
lib.haiku = require("./lib/haiku.js");
lib.mimic = require("./lib/mimic.js");
lib.pedant = require("./lib/pedant.js");
lib.prompt = require("./lib/prompt.js");
lib.respect = require("./lib/respect.js");
lib.update = require("./lib/update.js");

var auth = require("./data/auth.json");
// Configure logger settings
logger.remove(logger.transports.Console);
logger.add(logger.transports.Console, {
    colorize: true
});
logger.level = "debug";
// Initialize Discord Bot
var client = new Discord.Client({
    token: auth.token,
    autorun: true
});
dlog(client, "Hi, I'm OtherDave and I'm BACK FOR BUSINESS.");

client.on("ready", function (evt) {
    logger.info("Connected");
    logger.info("Logged in as: ");
	logger.info(client.username + " - (" + client.id + ")");
});
client.on("message", function (user, userID, channelID, message, evt) {
	// OtherDave shouldn't talk to himself.
	if(userID == client.id) {
		return;
	}

	if (message.substring(0, 1) == "!") {
		var args = message.trim().substring(1).split(" ");
        var cmd = args[0];

        args = args.splice(1);

		if(cmd == "haiku") {
			lib.haiku(logger, client, user, userID,
				channelID, args.join(" "), true)
		} else if(cmd == "quack") {
			client.sendMessage({
				to: channelID,
				message: "quack"
			});
		} else if(cmd in lib) {
			lib[cmd](logger, client, user, userID, channelID, args)
				.catch(function(error) { dlog(client, error) });
		} else {
			client.sendMessage({
				to: channelID,
				message: "I'm sorry Dave, I'm afraid I can't do that."
			});
		}
    } else if(message.indexOf("<@" + client.id + ">") == 0) {
		client.sendMessage({
			to: channelID,
			message: "Hey, you talkin to me?"
		});
	}
	else {
		lib.pedant(logger, client, user, userID, channelID, message)
			.catch(function() {});
		lib.haiku(logger, client, user, userID, channelID, message, false)
			.catch(function() {});

		// OtherDave is always listening...
		fs.appendFile("./data/markov/" + userID + ".txt", message + "\n", function(error) {
			if(error) {
				logger.error(error);
			}
		});
	}
});
<commit_msg>Fix import<commit_after>"use strict";

var Discord = require("discord.io");
var fs = require('fs');
var logger = require("winston");
var dlog = require("./dlog.js");

var lib = {};

lib.comic = require("./lib/comic.js");
lib.dave = async function(logger, client, user, userID, channelID, args) {
				client.sendMessage({
					to: channelID,
					message: "OtherDave is not David."
				});
		   };
lib.drunkdraw = require("./lib/drunkdraw.js");
lib.haiku = require("./lib/haiku.js");
lib.mimic = require("./lib/mimic.js");
lib.pedant = require("./lib/pedant.js");
lib.prompt = require("./lib/prompt.js");
lib.respect = require("./lib/respect.js");
lib.update = require("./lib/update.js");

var auth = require("./data/auth.json");
// Configure logger settings
logger.remove(logger.transports.Console);
logger.add(logger.transports.Console, {
    colorize: true
});
logger.level = "debug";
// Initialize Discord Bot
var client = new Discord.Client({
    token: auth.token,
    autorun: true
});
dlog(client, "Hi, I'm OtherDave and I'm BACK FOR BUSINESS.");

client.on("ready", function (evt) {
    logger.info("Connected");
    logger.info("Logged in as: ");
	logger.info(client.username + " - (" + client.id + ")");
});
client.on("message", function (user, userID, channelID, message, evt) {
	// OtherDave shouldn't talk to himself.
	if(userID == client.id) {
		return;
	}

	if (message.substring(0, 1) == "!") {
		var args = message.trim().substring(1).split(" ");
        var cmd = args[0];

        args = args.splice(1);

		if(cmd == "haiku") {
			lib.haiku(logger, client, user, userID,
				channelID, args.join(" "), true)
		} else if(cmd == "quack") {
			client.sendMessage({
				to: channelID,
				message: "quack"
			});
		} else if(cmd in lib) {
			lib[cmd](logger, client, user, userID, channelID, args)
				.catch(function(error) { dlog(client, error) });
		} else {
			client.sendMessage({
				to: channelID,
				message: "I'm sorry Dave, I'm afraid I can't do that."
			});
		}
    } else if(message.indexOf("<@" + client.id + ">") == 0) {
		client.sendMessage({
			to: channelID,
			message: "Hey, you talkin to me?"
		});
	}
	else {
		lib.pedant(logger, client, user, userID, channelID, message)
			.catch(function() {});
		lib.haiku(logger, client, user, userID, channelID, message, false)
			.catch(function() {});

		// OtherDave is always listening...
		fs.appendFile("./data/markov/" + userID + ".txt", message + "\n", function(error) {
			if(error) {
				logger.error(error);
			}
		});
	}
});
<|endoftext|>


<commit_before>define(['knockout', 'jquery', 'koco-i18next'],
    function(ko, $, kocoI18next) {
        'use strict';

        ko.bindingHandlers.untrustedHtml = {
            update: function(element, valueAccessor, allBindingsAccessor) {
                var value = ko.unwrap(valueAccessor());
                var i18next = kocoI18next.i18next;
                var defaultText = i18next.t('koco-untrusted-html-binding-handler.defaultText');
                var defaultSettings = {
                    defaultText: '[' + defaultText + ']'
                };

                var settings = $.extend({}, defaultSettings, allBindingsAccessor().utHtmlSettings);

                ko.bindingHandlers.html.update(element,
                    function() {
                        return value ? value.replace(/ /gi, ' ').trim() : settings.defaultTitle;
                    });
            }
        };
});
<commit_msg>breadcrumb for future enhancement<commit_after>define(['knockout', 'jquery', 'koco-i18next'],
    function(ko, $, kocoI18next) {
        'use strict';

        ko.bindingHandlers.untrustedHtml = {
            update: function(element, valueAccessor, allBindingsAccessor) {
                var value = ko.unwrap(valueAccessor());
                var i18next = kocoI18next.i18next;
                var defaultText = i18next.t('koco-untrusted-html-binding-handler.defaultText');
                var defaultSettings = {
                    defaultText: '[' + defaultText + ']'
                };

                var settings = $.extend({}, defaultSettings, allBindingsAccessor().utHtmlSettings);

                // @TODO give client more sanitization options
                ko.bindingHandlers.html.update(element,
                    function() {
                        return value ? value.replace(/ /gi, ' ').trim() : settings.defaultTitle;
                    });
            }
        };
});
<|endoftext|>


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

"use strict";

var ViterbiNode = require("./ViterbiNode");

/**
 * ViterbiLattice is a lattice in Viterbi algorithm
 * @constructor
 */
function ViterbiLattice() {
    this.nodes_end_at = [];
    this.nodes_end_at[0] = [ new ViterbiNode("BOS", 0, 0, 0, "BOS", 0, 0) ];
    this.eos_pos = 1;
}

/**
 * Append node to ViterbiLattice
 * @param {ViterbiNode} node
 */
ViterbiLattice.prototype.append = function (node) {
    var last_pos = node.start_pos + node.length - 1;
    if (this.eos_pos < last_pos) {
        this.eos_pos = last_pos;
    }

    var prev_nodes = this.nodes_end_at[last_pos];
    if (prev_nodes == null) {
        prev_nodes = [];
    }
    prev_nodes.push(node);

    this.nodes_end_at[last_pos] = prev_nodes;
};

/**
 * Set ends with EOS (End of Statement)
 */
ViterbiLattice.prototype.appendEos = function () {
    var last_index = this.nodes_end_at.length;
    this.eos_pos++;
    this.nodes_end_at[last_index] = [ new ViterbiNode("EOS", 0, this.eos_pos, 0, "EOS", 0, 0) ];
};

module.exports = ViterbiLattice;
<commit_msg>fix: give explicit empty string "surface_form" for BOS and EOS node<commit_after>/*
 * Copyright 2014 Takuya Asano
 * Copyright 2010-2014 Atilika Inc. and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

"use strict";

var ViterbiNode = require("./ViterbiNode");

/**
 * ViterbiLattice is a lattice in Viterbi algorithm
 * @constructor
 */
function ViterbiLattice() {
    this.nodes_end_at = [];
    this.nodes_end_at[0] = [ new ViterbiNode("BOS", 0, 0, 0, "BOS", 0, 0, "") ];
    this.eos_pos = 1;
}

/**
 * Append node to ViterbiLattice
 * @param {ViterbiNode} node
 */
ViterbiLattice.prototype.append = function (node) {
    var last_pos = node.start_pos + node.length - 1;
    if (this.eos_pos < last_pos) {
        this.eos_pos = last_pos;
    }

    var prev_nodes = this.nodes_end_at[last_pos];
    if (prev_nodes == null) {
        prev_nodes = [];
    }
    prev_nodes.push(node);

    this.nodes_end_at[last_pos] = prev_nodes;
};

/**
 * Set ends with EOS (End of Statement)
 */
ViterbiLattice.prototype.appendEos = function () {
    var last_index = this.nodes_end_at.length;
    this.eos_pos++;
    this.nodes_end_at[last_index] = [ new ViterbiNode("EOS", 0, this.eos_pos, 0, "EOS", 0, 0, "") ];
};

module.exports = ViterbiLattice;
<|endoftext|>


<commit_before><commit_msg>Fix coding standard violations.<commit_after><|endoftext|>


<commit_before>import { requester } from './requster.js';

export function setUsernameToLocalSorage() {
    let profileUrl = 'https://elsyser.herokuapp.com/api/profile/';

    requester.getJSON(profileUrl)
        .then((data) => {
            localStorage.setItem('elsyser-username', data.username || data.user.username);
        });
}

export function isTeacher(token) {
    if (token.length === 41 && token[40] === '1') {
        return true;
    }

    return false;
}<commit_msg>clean-up<commit_after>import { requester } from './requster.js';

export function isTeacher(token) {
    if (token.length === 41 && token[40] === '1') {
        return true;
    }

    return false;
}<|endoftext|>


<commit_before>import Directive from '@grid/view/directives/directive';
import {
	VIEW_CORE_NAME,
	BODY_CORE_NAME,
	GRID_NAME
} from '@grid/view/definition';
import {
	EventListener,
	EventManager
} from '@grid/core/infrastructure';
import {
	PathService
} from '@grid/core/path';
import {
	noop
} from '@grid/core/utility';

class BodyCore extends Directive(BODY_CORE_NAME, {
	view: `^^${VIEW_CORE_NAME}`,
	root: `^^${GRID_NAME}`
}) {
	constructor($scope, $element) {
		super();

		// this.$scope should be set cause it used by box.js
		this.$scope = $scope;
		this.element = $element[0];

		this.rangeStartCell = null;
		this.scrollContext = {
			top: this.element.scrollTop,
			left: this.element.scrollLeft,
		};

		Object.defineProperty($scope, '$view', {
			get: () => this.view
		});
	}

	onScroll() {
		const element = this.element;
		const scroll = this.view.model.scroll;

		const oldValue = this.scrollContext;
		const newValue = {};
		if (oldValue.top !== element.scrollTop) {
			oldValue.top = newValue.top = element.scrollTop;
		}

		if (oldValue.left !== element.scrollLeft) {
			oldValue.left = newValue.left = element.scrollLeft;
		}

		if (Object.keys(newValue)) {
			scroll(newValue, {
				source: 'body.core'
			});
		}
	}

	onInit() {
		const apply = this.view.model.scroll().mode !== 'virtual'
			? noop
			: f => {
				f();
				this.view.style.invalidate();
			};

		const listener = new EventListener(this.element, new EventManager(this, apply));

		this.using(listener.on('scroll', this.onScroll));
		this.using(listener.on('click', this.onClick));
		this.using(listener.on('mousedown', this.onMouseDown));
		this.using(listener.on('mouseup', this.onMouseUp));

		this.using(listener.on('mousemove', this.onMouseMove));
		this.using(listener.on('mouseleave', this.onMouseLeave));
	}

	onClick(e) {
		const pathFinder = new PathService(this.root.bag.body);
		const cell = pathFinder.cell(e.path);
		if (cell) {
			this.select(cell);
			this.navigate(cell);
			if (cell.column.editorOptions.trigger === 'click' && this.view.edit.cell.enter.canExecute(cell)) {
				this.view.edit.cell.enter.execute(cell);
			}
		}
	}

	onMouseDown(e) {
		const selectionState = this.selection;
		if (selectionState.area !== 'body') {
			return;
		}

		const pathFinder = new PathService(this.root.bag.body);
		const cell = pathFinder.cell(e.path);

		const editMode = this.view.model.edit().mode;
		if (selectionState.mode === 'range') {
			if (!editMode) {
				this.rangeStartCell = cell;
				if (this.rangeStartCell) {
					this.view.selection.selectRange(this.rangeStartCell, null, 'body');
				}
			}
		}
	}

	onMouseMove(e) {
		const pathFinder = new PathService(this.root.bag.body);
		const row = pathFinder.row(e.path);
		if (row) {
			const index = row.index;
			const highlightRow = this.view.highlight.row;
			if (highlightRow.canExecute(index)) {
				this.view
					.model
					.highlight()
					.rows
					.filter(i => i !== index)
					.forEach(i => highlightRow.execute(i, false));

				highlightRow.execute(index, true);
			}
		}

		if (this.selection.mode === 'range') {
			const startCell = this.rangeStartCell;
			const endCell = pathFinder.cell(e.path);

			if (startCell && endCell) {
				this.view.selection.selectRange(startCell, endCell, 'body');
				this.navigate(endCell);
			}
		}
	}

	onMouseLeave() {
		const highlightRow = this.view.highlight.row;
		this.view
			.model
			.highlight()
			.rows
			.forEach(i => highlightRow.execute(i, false));
	}

	onMouseUp() {
		if (this.selection.mode === 'range') {
			this.rangeStartCell = null;
		}
	}

	select(cell) {
		const selectionState = this.selection;
		if (cell.column.type !== 'select' &&
			(selectionState.area !== 'body' || selectionState.mode === 'range')) {
			return;
		}

		const editMode = this.view.model.edit().mode;
		switch (selectionState.unit) {
			case 'row':
				{
					if (cell.column.type === 'select' && cell.column.editorOptions.trigger === 'focus') {
						const focusState = this.view.model.focus();
						if (focusState.rowIndex !== cell.rowIndex || focusState.columnIndex !== cell.columnIndex) {
							this.view.selection.toggleRow.execute(cell.row, 'body');
						}
					} else if (!editMode && cell.column.canEdit) {
						this.view.selection.toggleRow.execute(cell.row, 'body');
					}
					break;
				}

			case 'column':
				{
					if (!editMode) {
						this.view.selection.toggleColumn.execute(cell.column, 'body');
					}
					break;
				}

			case 'mix':
				{
					if (cell.column.type === 'row-indicator') {
						this.view.selection.toggleCell.execute(cell, 'body');
					}
				}
		}
	}

	navigate(cell) {
		const focus = this.view.nav.focus;
		if (focus.canExecute(cell)) {
			focus.execute(cell);
		}
	}

	get selection() {
		return this.view.model.selection();
	}
}

BodyCore.$inject = [
	'$scope',
	'$element'
];

export default {
	restrict: 'A',
	bindToController: true,
	controllerAs: '$body',
	controller: BodyCore,
	require: BodyCore.require,
	link: BodyCore.link,
	scope: true
};<commit_msg>fix formatting<commit_after>import Directive from '@grid/view/directives/directive';
import {
	VIEW_CORE_NAME,
	BODY_CORE_NAME,
	GRID_NAME
} from '@grid/view/definition';
import {
	EventListener,
	EventManager
} from '@grid/core/infrastructure';
import {
	PathService
} from '@grid/core/path';
import {
	noop
} from '@grid/core/utility';

class BodyCore extends Directive(BODY_CORE_NAME, {
	view: `^^${VIEW_CORE_NAME}`,
	root: `^^${GRID_NAME}`
}) {
	constructor($scope, $element) {
		super();

		// this.$scope should be set cause it used by box.js
		this.$scope = $scope;
		this.element = $element[0];

		this.rangeStartCell = null;
		this.scrollContext = {
			top: this.element.scrollTop,
			left: this.element.scrollLeft,
		};

		Object.defineProperty($scope, '$view', {
			get: () => this.view
		});
	}

	onScroll() {
		const element = this.element;
		const scroll = this.view.model.scroll;

		const oldValue = this.scrollContext;
		const newValue = {};
		if (oldValue.top !== element.scrollTop) {
			oldValue.top = newValue.top = element.scrollTop;
		}

		if (oldValue.left !== element.scrollLeft) {
			oldValue.left = newValue.left = element.scrollLeft;
		}

		if (Object.keys(newValue)) {
			scroll(newValue, {
				source: 'body.core'
			});
		}
	}

	onInit() {
		const apply = this.view.model.scroll().mode !== 'virtual'
			? noop
			: f => {
				f();
				this.view.style.invalidate();
			};

		const listener = new EventListener(this.element, new EventManager(this, apply));

		this.using(listener.on('scroll', this.onScroll));
		this.using(listener.on('click', this.onClick));
		this.using(listener.on('mousedown', this.onMouseDown));
		this.using(listener.on('mouseup', this.onMouseUp));

		this.using(listener.on('mousemove', this.onMouseMove));
		this.using(listener.on('mouseleave', this.onMouseLeave));
	}

	onClick(e) {
		const pathFinder = new PathService(this.root.bag.body);
		const cell = pathFinder.cell(e.path);
		if (cell) {
			this.select(cell);
			this.navigate(cell);
			if (cell.column.editorOptions.trigger === 'click' && this.view.edit.cell.enter.canExecute(cell)) {
				this.view.edit.cell.enter.execute(cell);
			}
		}
	}

	onMouseDown(e) {
		const selectionState = this.selection;
		if (selectionState.area !== 'body') {
			return;
		}

		const pathFinder = new PathService(this.root.bag.body);
		const cell = pathFinder.cell(e.path);

		const editMode = this.view.model.edit().mode;
		if (selectionState.mode === 'range') {
			if (!editMode) {
				this.rangeStartCell = cell;
				if (this.rangeStartCell) {
					this.view.selection.selectRange(this.rangeStartCell, null, 'body');
				}
			}
		}
	}

	onMouseMove(e) {
		const pathFinder = new PathService(this.root.bag.body);
		const row = pathFinder.row(e.path);
		if (row) {
			const index = row.index;
			const highlightRow = this.view.highlight.row;
			if (highlightRow.canExecute(index)) {
				this.view
					.model
					.highlight()
					.rows
					.filter(i => i !== index)
					.forEach(i => highlightRow.execute(i, false));

				highlightRow.execute(index, true);
			}
		}

		if (this.selection.mode === 'range') {
			const startCell = this.rangeStartCell;
			const endCell = pathFinder.cell(e.path);

			if (startCell && endCell) {
				this.view.selection.selectRange(startCell, endCell, 'body');
				this.navigate(endCell);
			}
		}
	}

	onMouseLeave() {
		const highlightRow = this.view.highlight.row;
		this.view
			.model
			.highlight()
			.rows
			.forEach(i => highlightRow.execute(i, false));
	}

	onMouseUp() {
		if (this.selection.mode === 'range') {
			this.rangeStartCell = null;
		}
	}

	select(cell) {
		const selectionState = this.selection;
		if (cell.column.type !== 'select' &&
			(selectionState.area !== 'body' || selectionState.mode === 'range')) {
			return;
		}

		const editMode = this.view.model.edit().mode;
		switch (selectionState.unit) {
			case 'row': {
				if (cell.column.type === 'select' && cell.column.editorOptions.trigger === 'focus') {
					const focusState = this.view.model.focus();
					if (focusState.rowIndex !== cell.rowIndex || focusState.columnIndex !== cell.columnIndex) {
						this.view.selection.toggleRow.execute(cell.row, 'body');
					}
				} else if (!editMode && cell.column.canEdit) {
					this.view.selection.toggleRow.execute(cell.row, 'body');
				}
				break;
			}

			case 'column': {
				if (!editMode) {
					this.view.selection.toggleColumn.execute(cell.column, 'body');
				}
				break;
			}

			case 'mix': {
				if (cell.column.type === 'row-indicator') {
					this.view.selection.toggleCell.execute(cell, 'body');
				}
			}
		}
	}

	navigate(cell) {
		const focus = this.view.nav.focus;
		if (focus.canExecute(cell)) {
			focus.execute(cell);
		}
	}

	get selection() {
		return this.view.model.selection();
	}
}

BodyCore.$inject = [
	'$scope',
	'$element'
];

export default {
	restrict: 'A',
	bindToController: true,
	controllerAs: '$body',
	controller: BodyCore,
	require: BodyCore.require,
	link: BodyCore.link,
	scope: true
};<|endoftext|>


<commit_before>var SYUILOUI = {};

SYUILOUI.Tab = function($tabList) {
	var $tabContents = [];

	$tabList.find('li').each(function(i, elem) {
		var $tabListItem = $(elem);
		var id = $tabListItem.find('a').attr('href');
		$tabContents.push($(id));
		$tabListItem.addClass('unactive');

		$tabListItem.click(function() {
			var num = $tabList.find('li').index(this);
			$tabList.find('li').removeClass('active');
			$(this).addClass('active');

			$.each($tabContents, function() {
				$(this).css("display", "none");
			});

			$tabContents[num].css("display", "block");

			return false;
		});
	});

	$tabContents.each(function(i, elem) {
		var $tabContent = $(elem);
		$tabContent.css("display", "none");
	});

	$tabList[0].attr('class', 'active');
	$tabContent[0].css("display", "block");
}
<commit_msg>Add class<commit_after>var SYUILOUI = {};

SYUILOUI.Tab = function($tabList) {
	var $tabContents = [];

	$tabList.find('li').each(function(i, elem) {
		var $tabListItem = $(elem);
		var id = $tabListItem.find('a').attr('href');
		$tabContents.push($(id));
		$tabListItem.addClass('unactive');

		$tabListItem.click(function() {
			var num = $tabList.find('li').index(this);
			$tabList.find('li').removeClass('active');
			$(this).removeClass('unactive').addClass('active');

			$.each($tabContents, function() {
				$(this).css("display", "none");
			});

			$tabContents[num].css("display", "block");

			return false;
		});
	});

	$tabContents.each(function(i, elem) {
		var $tabContent = $(elem);
		$tabContent.css("display", "none");
	});

	$tabList.find('li')[0].removeClass('unactive').addClass('active');
	$tabContent[0].css("display", "block");
}
<|endoftext|>


<commit_before>import cheerio from 'cheerio';
import request from 'request';
var Horseman = require('node-horseman');
var MongoClient = require('mongodb').MongoClient;

import events from 'events';
const eventEmitter = new events.EventEmitter();

// Internal dependencies
import { Author, Comment } from './models';

const DB_URL = 'mongodb://172.17.0.2:27017/opiniorizer';

const TRIP_ADVISOR_URL = "https://www.tripadvisor.com";
const TRIP_ADVISOR_MEMBER_URL = ( username ) => ( `${TRIP_ADVISOR_URL}/members/${username}` )
const TRIP_ADVISOR_SEARCH_URL = ( criteria ) => ( `${TRIP_ADVISOR_URL}/Search?q=${criteria}` );
const TRIP_ADVISOR_REVIEW_URL = ( review ) => ( `${TRIP_ADVISOR_URL}${review}` );
const MAX_N_WORKERS = 5;

let BASE_REVIEW_URL = "";

export default class PoiCollector {

	constructor( poi ) {
		this.poi = poi;
	}

	collect() {

		this.discoverUrl().then( ( url ) => {

			this.discoverHowManyPages( TRIP_ADVISOR_REVIEW_URL( url ) ).then( ( number ) => {

				// let workers = this.startWorkers( number );

				// Promise.all(workers).then( ( result ) => {

				// 	console.log("Finish workers");
				//

				this.createWorker( number );

				// }, this.dispatchError );

			}, this.dispatchError);

		}, this.dispatchError );
	}

	// Discover which url must be appended to base url to fetch reviews
	discoverUrl() {

		return this.executeAsync( (resolve, reject) => {

			const searchUrl = TRIP_ADVISOR_SEARCH_URL( this.poi );

			request.get( searchUrl, (error, response, body) => {

				if(error)
					reject(error);

				const $ = cheerio.load(body);

				const results = $('.review-count');
				const reviews_url = results[0].attribs.href;
				console.log( reviews_url );
				const url_split = reviews_url.split('?');
				BASE_REVIEW_URL = url_split[0];

				console.log( "Base url: " +  BASE_REVIEW_URL );

				resolve(reviews_url);
			} );

		} );

	}

	// Discover how many pages a review owns
	discoverHowManyPages( review ) {

		return this.executeAsync( ( resolve, reject ) => {

			request.get( review, ( error, response, body ) => {

				if(error)
					reject(error);

				const $ = cheerio.load(body);
				const pageBar = $('.pageNumbers');

				const lastPageElement = pageBar.children().get(pageBar.children().length - 1);

				resolve(lastPageElement.children[0].data);
			} );

		} );

	}

	// Start works defining which pages every worker will collect
	startWorkers( numberPages ) {

		console.log("Starting workers");
		console.log("Pages: " + numberPages);

		let workers = [];
		const nPagesPerWorker = parseInt(( numberPages /  MAX_N_WORKERS ));

		for(let p = 1; p <= numberPages; p += nPagesPerWorker){

			if(p + nPagesPerWorker > numberPages)
				workers.push( this.createWorker( p,  numberPages - p) );
			else
				workers.push( this.createWorker( p, nPagesPerWorker ) );

		}

		return workers;
	}

	// Create a worker responsible for collecting reviews in such pages
	createWorker( maxPages ) {

		const action = function(err, db) {

			if(err){
				console.log("MongoDB connection error");
				return;
			}

			const collection = db.collection('opinions');

			eventEmitter.on('nextCollect', ( page ) => {

				console.log("Collecting page " + page + "...");

				// ##### TODO
				// Erro abaixo: maxPages está vindo menor que o esperado..olhar..
				// if( page > maxPages ){
				// 	console.log(`Max pages error...page = ${page} / maxPage=${maxPages}`);
				// 	eventEmitter.removeListener('nextCollect');
				// 	return;
				// }

				let partsUrl = BASE_REVIEW_URL.split('-');

				let task;

				if(page == 1)
					task = this.collectReviews( collection, TRIP_ADVISOR_REVIEW_URL( BASE_REVIEW_URL ) );
				else {

					const offset = (page-1) * 10;
					let urlTemp = partsUrl.slice(0, partsUrl.length);

					urlTemp.splice(4, 0, `or${offset}`);

					const baseUrl = urlTemp.join('-');

					console.log(TRIP_ADVISOR_REVIEW_URL( baseUrl ));

					task = this.collectReviews( collection, TRIP_ADVISOR_REVIEW_URL( baseUrl ) );

				}

				task.then( () => {
					eventEmitter.emit('nextCollect', page + 1);
				} );

			});

			eventEmitter.emit( 'nextCollect', 1);

		}.bind(this);

		MongoClient.connect(DB_URL, action);

	}

	// Collect reviews according to full url ( tripAdvisor_url + review_url_base )
	collectReviews( collection, url ) {

		console.log("Collecting reviews");

		return new Promise( (resolve, reject) => {

			console.log( url );

			const horseman = new Horseman();

			const clickAllShowmore = ( selector ) => {

				$( selector ).each( ( index, item ) => {
					$( item ).click();
				});
			};

			horseman
				.open( url )
				.waitForSelector( '.review-container', { timeout: 5000 } )
				.evaluate( clickAllShowmore, '.review-container .taLnk' )
				.wait(10000)
				.evaluate( () => {

					return $('body').html();

				} )
				.then( ( body ) => {

						const $ = cheerio.load( body );
						const reviews = $('.reviewSelector');

						Object.keys( reviews ).forEach( ( pos ) => {

							if( !isNaN(pos) ) {

								const reviewsInfosComp = reviews[pos];
								// console.log( reviewsInfosComp.children[0] );
								// console.log(reviewsInfosComp);
								const authorInfos = this.collectAuthorInfos( reviewsInfosComp.children[0].children[0] );
								const comment = this.collectCommentInfos( reviewsInfosComp.children[0].children[1] );

								authorInfos.then( ( author ) => {

									comment.author = author;
									comment.collectedAt = new Date();

									console.log( "Saving comment into database..." );
									collection.insert( comment );

								}, () => {
									console.log( "Error collecting author's infos" );
								} )

							}

						} );

					return;

				} ).finally( () => {
					console.log("Finished collecting");
					horseman.close();
					resolve();

				} );

		} );

	}

	collectAuthorInfos( component ) {

		const getInfoCount = ( $, infoName ) => {

			let value = $(`a[name=${infoName}]`);
			if( value && value[0] ) {
				value = parseInt( value[0].children[0].data.split(' ')[0] );
			} else {
				value = 0;
			}

			return value;
		}

		return this.executeAsync( ( resolve, reject ) => {

			const userNameComp = component.children[0].children[0].children[0].children[1].children[0];
			const username = userNameComp.children[0].data;

			const searchUrl = TRIP_ADVISOR_MEMBER_URL( username );

			request.get( searchUrl, (error, response, body) => {

				if(error){
					console.log(" Error requesting username... ");
					reject();
				} else {

					const $ = cheerio.load(body);

					let memberSince = $('.ageSince').children().get(0);
					if( memberSince ) {

						memberSince = memberSince.children[0].data;

						let countReviews = getInfoCount($, 'reviews' );
						let countRatings = getInfoCount($, 'ratings' );
						let countPostForum = getInfoCount($, 'forums' );
						let countHelpfulVotes = getInfoCount($, 'lists' );

						const levelComp = $('.level.tripcollectiveinfo');
						let level = levelComp[0]
						if( level )
							level = level.children[1].children[0].data;
						else
							level = 0;

						const points = $('.points')[0].children[0].data;

						const author = new Author();
						author.memberSince = memberSince;
						author.reviews = countReviews;
						author.ratings = countRatings;
						author.postForum = countPostForum;
						author.helpfulVotes = countHelpfulVotes;
						author.level = level;

						resolve( author );

					} else {
						reject();
					}

				}

			} );

		} );

	}

	collectCommentInfos( component ) {

		const comment = new Comment;

		const infosComp = component.children[0].children[0];

		// Title
		const titleComp = infosComp.children[1];
		comment.title = titleComp.children[0].children[0].children[0].data;

		// Bubble count
		const bubbleComp = infosComp.children[0];
		const bubbleInfoComp = bubbleComp.children[0];
		comment.bubbleCount = parseInt(bubbleInfoComp.attribs.class.split(' ')[1].split('_')[1]/10);

		// Creation date
		const createdAtComp = infosComp.children[0];
		const createdAtInfoComp = createdAtComp.children[1];
		comment.createdAt = createdAtInfoComp.attribs.title;

		// Comment
		const commentComp = infosComp.children[2];
		// comment.text = commentComp.children[0].children[0].data.replace(/\\n/,'');
		comment.text = commentComp.children[0].children[0].children[0].data;

		// Thanks count
		const thanksComp = infosComp.children[3];

		if( thanksComp.children[1] && thanksComp.children[1].children[0] && thanksComp.children[1].children[0].children[0] &&
			thanksComp.children[1].children[0].children[0].children[1] && thanksComp.children[1].children[0].children[0].children[1].children[0] ) {

			const thanksCount = thanksComp.children[1].children[0].children[0].children[1].children[0].data;

			comment.thanksCount = parseInt( thanksCount );
		} else
			comment.thanksCount = 0;

		// Query
		comment.query = this.poi;

		// console.log( comment );
		return comment;
	}

	executeAsync( fn ) {

		return new Promise( ( resolve, reject ) => {
			fn( resolve, reject );
		} );

	}

	dispatchError( error ) {
		console.log( error );
	}

}<commit_msg>Fixing on getting poi url properly<commit_after>import cheerio from 'cheerio';
import request from 'request';
var Horseman = require('node-horseman');
var MongoClient = require('mongodb').MongoClient;

import events from 'events';
const eventEmitter = new events.EventEmitter();

// Internal dependencies
import { Author, Comment } from './models';

const DB_URL = 'mongodb://localhost:27017/opiniorizer';

const TRIP_ADVISOR_URL = "https://www.tripadvisor.com";
const TRIP_ADVISOR_MEMBER_URL = ( username ) => ( `${TRIP_ADVISOR_URL}/members/${username}` )
const TRIP_ADVISOR_SEARCH_URL = ( criteria ) => ( `${TRIP_ADVISOR_URL}/Search?q=${criteria}` );
const TRIP_ADVISOR_REVIEW_URL = ( review ) => ( `${TRIP_ADVISOR_URL}${review}` );
const MAX_N_WORKERS = 5;

let BASE_REVIEW_URL = "";

export default class PoiCollector {

	constructor( poi ) {
		this.poi = poi;
	}

	collect() {

		this.discoverUrl().then( ( url ) => {

			this.discoverHowManyPages( TRIP_ADVISOR_REVIEW_URL( url ) ).then( ( number ) => {

				// let workers = this.startWorkers( number );

				// Promise.all(workers).then( ( result ) => {

				// 	console.log("Finish workers");
				//

				this.createWorker( number );

				// }, this.dispatchError );

			}, this.dispatchError);

		}, this.dispatchError );
	}

	// Discover which url must be appended to base url to fetch reviews
	discoverUrl() {

		return this.executeAsync( (resolve, reject) => {

			const searchUrl = TRIP_ADVISOR_SEARCH_URL( this.poi );

			request.get( searchUrl, (error, response, body) => {

				if(error)
					reject(error);

				const $ = cheerio.load(body);

				const results = $('.review-count');

				const reviews_url = results[0].attribs.onclick.match(/\/[\w\-\.\?\=\#]+/g)[0];
				console.log( reviews_url );
				const url_split = reviews_url.split('?');
				BASE_REVIEW_URL = url_split[0];

				console.log( "Base url: " +  BASE_REVIEW_URL );

				resolve(reviews_url);
			} );

		} );

	}

	// Discover how many pages a review owns
	discoverHowManyPages( review ) {

		return this.executeAsync( ( resolve, reject ) => {

			request.get( review, ( error, response, body ) => {

				if(error)
					reject(error);

				const $ = cheerio.load(body);
				const pageBar = $('.pageNumbers');

				const lastPageElement = pageBar.children().get(pageBar.children().length - 1);

				resolve(lastPageElement.children[0].data);
			} );

		} );

	}

	// Start works defining which pages every worker will collect
	startWorkers( numberPages ) {

		console.log("Starting workers");
		console.log("Pages: " + numberPages);

		let workers = [];
		const nPagesPerWorker = parseInt(( numberPages /  MAX_N_WORKERS ));

		for(let p = 1; p <= numberPages; p += nPagesPerWorker){

			if(p + nPagesPerWorker > numberPages)
				workers.push( this.createWorker( p,  numberPages - p) );
			else
				workers.push( this.createWorker( p, nPagesPerWorker ) );

		}

		return workers;
	}

	// Create a worker responsible for collecting reviews in such pages
	createWorker( maxPages ) {

		const action = function(err, db) {

			if(err){
				console.log("MongoDB connection error");
				return;
			}

			const collection = db.collection('opinions');

			eventEmitter.on('nextCollect', ( page ) => {

				console.log("Collecting page " + page + "...");

				// ##### TODO
				// Erro abaixo: maxPages está vindo menor que o esperado..olhar..
				// if( page > maxPages ){
				// 	console.log(`Max pages error...page = ${page} / maxPage=${maxPages}`);
				// 	eventEmitter.removeListener('nextCollect');
				// 	return;
				// }

				let partsUrl = BASE_REVIEW_URL.split('-');

				let task;

				if(page == 1)
					task = this.collectReviews( collection, TRIP_ADVISOR_REVIEW_URL( BASE_REVIEW_URL ) );
				else {

					const offset = (page-1) * 10;
					let urlTemp = partsUrl.slice(0, partsUrl.length);

					urlTemp.splice(4, 0, `or${offset}`);

					const baseUrl = urlTemp.join('-');

					console.log(TRIP_ADVISOR_REVIEW_URL( baseUrl ));

					task = this.collectReviews( collection, TRIP_ADVISOR_REVIEW_URL( baseUrl ) );

				}

				task.then( () => {
					eventEmitter.emit('nextCollect', page + 1);
				} );

			});

			eventEmitter.emit( 'nextCollect', 1);

		}.bind(this);

		MongoClient.connect(DB_URL, action);

	}

	// Collect reviews according to full url ( tripAdvisor_url + review_url_base )
	collectReviews( collection, url ) {

		console.log("Collecting reviews");

		return new Promise( (resolve, reject) => {

			console.log( url );

			const horseman = new Horseman();

			const clickAllShowmore = ( selector ) => {

				$( selector ).each( ( index, item ) => {
					$( item ).click();
				});
			};

			horseman
				.open( url )
				.waitForSelector( '.review-container', { timeout: 5000 } )
				.evaluate( clickAllShowmore, '.review-container .taLnk' )
				.wait(10000)
				.evaluate( () => {

					return $('body').html();

				} )
				.then( ( body ) => {

						const $ = cheerio.load( body );
						const reviews = $('.reviewSelector');

						Object.keys( reviews ).forEach( ( pos ) => {

							if( !isNaN(pos) ) {

								const reviewsInfosComp = reviews[pos];
								// console.log( reviewsInfosComp.children[0] );
								// console.log(reviewsInfosComp);
								const authorInfos = this.collectAuthorInfos( reviewsInfosComp.children[0].children[0] );
								const comment = this.collectCommentInfos( reviewsInfosComp.children[0].children[1] );

								authorInfos.then( ( author ) => {

									comment.author = author;
									comment.collectedAt = new Date();

									console.log( "Saving comment into database..." );
									collection.insert( comment );

								}, () => {
									console.log( "Error collecting author's infos" );
								} )

							}

						} );

					return;

				} ).finally( () => {
					console.log("Finished collecting");
					horseman.close();
					resolve();

				} );

		} );

	}

	collectAuthorInfos( component ) {

		const getInfoCount = ( $, infoName ) => {

			let value = $(`a[name=${infoName}]`);
			if( value && value[0] ) {
				value = parseInt( value[0].children[0].data.split(' ')[0] );
			} else {
				value = 0;
			}

			return value;
		}

		return this.executeAsync( ( resolve, reject ) => {

			const userNameComp = component.children[0].children[0].children[0].children[1].children[0];
			const username = userNameComp.children[0].data;

			const searchUrl = TRIP_ADVISOR_MEMBER_URL( username );

			request.get( searchUrl, (error, response, body) => {

				if(error){
					console.log(" Error requesting username... ");
					reject();
				} else {

					const $ = cheerio.load(body);

					let memberSince = $('.ageSince').children().get(0);
					if( memberSince ) {

						memberSince = memberSince.children[0].data;

						let countReviews = getInfoCount($, 'reviews' );
						let countRatings = getInfoCount($, 'ratings' );
						let countPostForum = getInfoCount($, 'forums' );
						let countHelpfulVotes = getInfoCount($, 'lists' );

						const levelComp = $('.level.tripcollectiveinfo');
						let level = levelComp[0]
						if( level )
							level = level.children[1].children[0].data;
						else
							level = 0;

						const points = $('.points')[0].children[0].data;

						const author = new Author();
						author.memberSince = memberSince;
						author.reviews = countReviews;
						author.ratings = countRatings;
						author.postForum = countPostForum;
						author.helpfulVotes = countHelpfulVotes;
						author.level = level;

						resolve( author );

					} else {
						reject();
					}

				}

			} );

		} );

	}

	collectCommentInfos( component ) {

		const comment = new Comment;

		const infosComp = component.children[0].children[0];

		// Title
		const titleComp = infosComp.children[1];
		comment.title = titleComp.children[0].children[0].children[0].data;

		// Bubble count
		const bubbleComp = infosComp.children[0];
		const bubbleInfoComp = bubbleComp.children[0];
		comment.bubbleCount = parseInt(bubbleInfoComp.attribs.class.split(' ')[1].split('_')[1]/10);

		// Creation date
		const createdAtComp = infosComp.children[0];
		const createdAtInfoComp = createdAtComp.children[1];
		comment.createdAt = createdAtInfoComp.attribs.title;

		// Comment
		const commentComp = infosComp.children[2];
		// comment.text = commentComp.children[0].children[0].data.replace(/\\n/,'');
		comment.text = commentComp.children[0].children[0].children[0].data;

		// Thanks count
		const thanksComp = infosComp.children[3];

		if( thanksComp.children[1] && thanksComp.children[1].children[0] && thanksComp.children[1].children[0].children[0] &&
			thanksComp.children[1].children[0].children[0].children[1] && thanksComp.children[1].children[0].children[0].children[1].children[0] ) {

			const thanksCount = thanksComp.children[1].children[0].children[0].children[1].children[0].data;

			comment.thanksCount = parseInt( thanksCount );
		} else
			comment.thanksCount = 0;

		// Query
		comment.query = this.poi;

		// console.log( comment );
		return comment;
	}

	executeAsync( fn ) {

		return new Promise( ( resolve, reject ) => {
			fn( resolve, reject );
		} );

	}

	dispatchError( error ) {
		console.log( error );
	}

}<|endoftext|>


<commit_before>// Copyright (c) 2011 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.

var localStrings = new LocalStrings();
var hasPDFPlugin = true;
var expectedPageCount = 0;
var pageRangesInfo = [];
var printJobTitle = '';

/**
 * Window onload handler, sets up the page.
 */
function load() {
  initializeAnimation();

  updateSummary();

  $('printer-list').disabled = true;
  $('print-button').disabled = true;
  $('print-button').addEventListener('click', printFile);
  $('cancel-button').addEventListener('click', function(e) {
    window.close();
  });

  $('copies').addEventListener('input', validateNumberOfCopies);
  $('copies').addEventListener('blur', handleCopiesFieldBlur);
  $('individual-pages').addEventListener('blur', handlePageRangesFieldBlur);
  $('landscape').onclick = onLayoutModeToggle;
  $('portrait').onclick = onLayoutModeToggle;
  $('color').onclick = getPreview;
  $('bw').onclick = getPreview;

  chrome.send('getPrinters');
};

/**
 * Parses the copies field text for validation and updates the state of print
 * button and collate checkbox. If the specified value is invalid, displays an
 * invalid warning icon on the text box and sets the error message as the title
 * message of text box.
 */
function validateNumberOfCopies() {
  var copiesField = $('copies');
  var message = '';
  if (!isNumberOfCopiesValid())
    message = localStrings.getString('invalidNumberOfCopiesTitleToolTip');
  copiesField.setCustomValidity(message);
  copiesField.title = message;
  updatePrintButtonState();
}

/**
 * Handles copies field blur event.
 */
function handleCopiesFieldBlur() {
  checkAndSetCopiesField();
  printSettingChanged();
}

/**
 * Handles page ranges field blur event.
 */
function handlePageRangesFieldBlur() {
  checkAndSetPageRangesField();
}

/**
 * Depending on 'copies' value, shows/hides the collate checkbox.
 */
function updateCollateCheckboxState() {
  $('collate-option').hidden = getCopies() <= 1;
}

/**
 * Validates the copies text field value.
 * NOTE: An empty copies field text is considered valid because the blur event
 * listener of this field will set it back to a default value.
 * @return {boolean} true if the number of copies is valid else returns false.
 */
function isNumberOfCopiesValid() {
  var copiesFieldText = $('copies').value.replace(/\s/g, '');
  if (copiesFieldText == '')
    return true;

  var numericExp = /^[0-9]+$/;
  return (numericExp.test(copiesFieldText) && Number(copiesFieldText) > 0);
}

/**
 * Checks the value of the copies field. If it is a valid number it does
 * nothing. If it can only parse the first part of the string it replaces the
 * string with the first part. Example: '123abcd' becomes '123'.
 * If the string can't be parsed at all it replaces with 1.
 */
function checkAndSetCopiesField() {
  var copiesField = $('copies');
  var copies = parseInt(copiesField.value, 10);
  if (isNaN(copies))
    copies = 1;
  copiesField.value = copies;
  updateSummary();
}

/**
 * Checks the value of the page ranges text field. It parses the page ranges and
 * normalizes them. For example: '1,2,3,5,9-10' becomes '1-3, 5, 9-10'.
 * If it can't parse the whole string it will replace with the part it parsed.
 * For example: '1-6,9-10,sd343jf' becomes '1-6, 9-10'. If the specified page
 * range includes all pages it replaces it with the empty string (so that the
 * example text is automatically shown.
 *
 */
function checkAndSetPageRangesField() {
  var pageRanges = getPageRanges();
  var parsedPageRanges = '';
  var individualPagesField = $('individual-pages');

  if (pageRanges.length == 1 && pageRanges[0].from == 1 &&
          pageRanges[0].to == expectedPageCount) {
    individualPagesField.value = parsedPageRanges;
    return;
  }

  for (var i = 0; i < pageRanges.length; i++) {
    if (pageRanges[i].from == pageRanges[i].to)
      parsedPageRanges += pageRanges[i].from;
    else
      parsedPageRanges += pageRanges[i].from + '-' + pageRanges[i].to;
    if (i < pageRanges.length - 1)
      parsedPageRanges += ', ';
  }
  individualPagesField.value = parsedPageRanges;
  updateSummary();
}

/**
 * Checks whether the preview layout setting is set to 'landscape' or not.
 *
 * @return {boolean} true if layout is 'landscape'.
 */
function isLandscape() {
  return $('landscape').checked;
}

/**
 * Checks whether the preview color setting is set to 'color' or not.
 *
 * @return {boolean} true if color is 'color'.
 */
function isColor() {
  return $('color').checked;
}

/**
 * Checks whether the preview collate setting value is set or not.
 *
 * @return {boolean} true if collate setting is enabled and checked.
 */
function isCollated() {
  var collateField = $('collate');
  return !collateField.disabled && collateField.checked;
}

/**
 * Returns the number of copies currently indicated in the copies textfield. If
 * the contents of the textfield can not be converted to a number or if <1 it
 * returns 1.
 *
 * @return {number} number of copies.
 */
function getCopies() {
  var copies = parseInt($('copies').value, 10);
  if (!copies || copies <= 1)
    copies = 1;
  return copies;
}

/**
 * Checks whether the preview two-sided checkbox is checked.
 *
 * @return {boolean} true if two-sided is checked.
 */
function isTwoSided() {
  return $('two-sided').checked;
}

/**
 * Creates a JSON string based on the values in the printer settings.
 *
 * @return {string} JSON string with print job settings.
 */
function getSettingsJSON() {
  var selectedPrinter = $('printer-list').selectedIndex;
  var printerName = '';
  if (selectedPrinter >= 0)
    printerName = $('printer-list').options[selectedPrinter].textContent;
  var printAll = $('all-pages').checked;
  var printToPDF = (printerName == localStrings.getString('printToPDF'));

  return JSON.stringify({'printerName': printerName,
                         'pageRange': getPageRanges(),
                         'printAll': printAll,
                         'twoSided': isTwoSided(),
                         'copies': getCopies(),
                         'collate': isCollated(),
                         'landscape': isLandscape(),
                         'color': isColor(),
                         'printToPDF': printToPDF});
}

/**
 * Asks the browser to print the preview PDF based on current print settings.
 */
function printFile() {
  chrome.send('print', [getSettingsJSON()]);
}

/**
 * Asks the browser to generate a preview PDF based on current print settings.
 */
function getPreview() {
  chrome.send('getPreview', [getSettingsJSON()]);
}

/**
 * Fill the printer list drop down.
 * @param {Array} printers Array of printer names.
 * @param {number} defaultPrinterIndex The index of the default printer.
 */
function setPrinters(printers, defaultPrinterIndex) {
  if (printers.length > 0) {
    for (var i = 0; i < printers.length; ++i) {
      var option = document.createElement('option');
      option.textContent = printers[i];
      $('printer-list').add(option);
      if (i == defaultPrinterIndex)
        option.selected = true;
    }
  } else {
    var option = document.createElement('option');
    option.textContent = localStrings.getString('noPrinter');
    $('printer-list').add(option);
  }

  // Adding option for saving PDF to disk.
  var option = document.createElement('option');
  option.textContent = localStrings.getString('printToPDF');
  $('printer-list').add(option);
  $('printer-list').disabled = false;

  // Once the printer list is populated, generate the initial preview.
  getPreview();
}

/**
 * Sets the color mode for the PDF plugin.
 * @param {boolean} color is true if the PDF plugin should display in color.
 */
function setColor(color) {
  if (!hasPDFPlugin) {
    return;
  }
  $('pdf-viewer').grayscale(!color);
}

function onPDFLoad() {
  if (isLandscape())
    $('pdf-viewer').fitToWidth();
  else
    $('pdf-viewer').fitToHeight();
}

/**
 * Update the print preview when new preview data is available.
 * Create the PDF plugin as needed.
 * @param {number} pageCount The expected total pages count.
 * @param {string} jobTitle The print job title.
 *
 */
function updatePrintPreview(pageCount, jobTitle) {
  // Set the expected page count.
  expectedPageCount = pageCount;

  // Set the print job title.
  printJobTitle = jobTitle;

  // Update the current tab title.
  document.title = localStrings.getStringF('printPreviewTitleFormat', jobTitle);

  createPDFPlugin();

  updateSummary();
}

/**
 * Create the PDF plugin or reload the existing one.
 */
function createPDFPlugin() {
  if (!hasPDFPlugin) {
    return;
  }

  // Enable the print button.
  if (!$('printer-list').disabled) {
    $('print-button').disabled = false;
  }

  if ($('pdf-viewer')) {
    $('pdf-viewer').reload();
    $('pdf-viewer').grayscale(!isColor());
    return;
  }

  var loadingElement = $('loading');
  loadingElement.classList.add('hidden');
  var mainView = loadingElement.parentNode;

  var pdfPlugin = document.createElement('embed');
  pdfPlugin.setAttribute('id', 'pdf-viewer');
  pdfPlugin.setAttribute('type', 'application/pdf');
  pdfPlugin.setAttribute('src', 'chrome://print/print.pdf');
  mainView.appendChild(pdfPlugin);
  if (!pdfPlugin.onload) {
    hasPDFPlugin = false;
    mainView.removeChild(pdfPlugin);
    $('no-plugin').classList.remove('hidden');
    return;
  }
  pdfPlugin.grayscale(true);
  pdfPlugin.onload('onPDFLoad()');
}

/**
 * Updates the state of print button depending on the user selection.
 *
 * If the user has selected 'All' pages option, enables the print button.
 * If the user has selected a page range, depending on the validity of page
 * range text enables/disables the print button.
 * Depending on the validity of 'copies' value, enables/disables the print
 * button.
 */
function updatePrintButtonState() {
  $('print-button').disabled = (!($('all-pages').checked ||
                                  $('individual-pages').checkValidity()) ||
                                !$('copies').checkValidity());
}

window.addEventListener('DOMContentLoaded', load);

/**
 * Listener function that executes whenever any of the available settings
 * is changed.
 */
function printSettingChanged() {
  updateCollateCheckboxState();
  updateSummary();
}

/**
 * Updates the print summary based on the currently selected user options.
 *
 */
function updateSummary() {
  var html = '';
  var pageList = getPageList();
  var copies = getCopies();
  var printButton = $('print-button');
  var printSummary = $('print-summary');

  if (isNaN($('copies').value)) {
    html = localStrings.getString('invalidNumberOfCopiesTitleToolTip');
    printSummary.innerHTML = html;
    return;
  }

  if (pageList.length <= 0) {
    html = localStrings.getString('pageRangeInvalidTitleToolTip');
    printSummary.innerHTML = html;
    printButton.disabled = true;
    return;
  }

  var pagesLabel = localStrings.getString('printPreviewPageLabelSingular');
  var twoSidedLabel = '';
  var timesSign = '';
  var numOfCopies = '';
  var copiesLabel = '';
  var equalSign = '';
  var numOfSheets = '';
  var sheetsLabel = '';

  printButton.disabled = false;

  if (pageList.length > 1)
    pagesLabel = localStrings.getString('printPreviewPageLabelPlural');

  if (isTwoSided())
    twoSidedLabel = '('+localStrings.getString('optionTwoSided')+')';

  if (copies > 1) {
    timesSign = '×';
    numOfCopies = copies;
    copiesLabel = localStrings.getString('copiesLabel').toLowerCase();
  }

  if ((copies > 1) || (isTwoSided())) {
    numOfSheets = pageList.length;

    if (isTwoSided())
      numOfSheets = Math.ceil(numOfSheets / 2);

    equalSign = '=';
    numOfSheets *= copies;
    sheetsLabel = localStrings.getString('printPreviewSheetsLabel');
  }

  html = localStrings.getStringF('printPreviewSummaryFormat', pageList.length,
                                  pagesLabel, twoSidedLabel, timesSign,
                                  numOfCopies, copiesLabel, equalSign,
                                  ''+numOfSheets+'',
                                  ''+sheetsLabel+'');

  // Removing extra spaces from within the string.
  html.replace(/\s{2,}/g, ' ');
  printSummary.innerHTML = html;
}

/**
 * Handles a click event on the two-sided option.
 */
function handleTwoSidedClick(event) {
  var el = $('binding');
  handleZippyClickEl(el);
  printSettingChanged(event);
}

/**
 * When the user switches printing orientation mode the page field selection is
 * reset to "all pages selected". After the change the number of pages will be
 * different and currently selected page numbers might no longer be valid.
 * Even if they are still valid the content of these pages will be different.
 */
function onLayoutModeToggle() {
  $('individual-pages').value = '';
  $('all-pages').checked = true;
  getPreview();
}

/**
 * Returns a list of all pages in the specified ranges. If the page ranges can't
 * be parsed an empty list is returned.
 *
 * @return {Array}
 */
function getPageList() {
  var pageText = $('individual-pages').value;

  if ($('all-pages').checked || pageText == '')
    pageText = '1-' + expectedPageCount;

  var pageList = [];
  var parts = pageText.split(/,/);

  for (var i = 0; i < parts.length; i++) {
    var part = parts[i];
    var match = part.match(/([0-9]+)-([0-9]+)/);

    if (match && match[1] && match[2]) {
      var from = parseInt(match[1], 10);
      var to = parseInt(match[2], 10);

      if (from && to) {
        for (var j = from; j <= to; j++)
          if (j <= expectedPageCount)
            pageList.push(j);
      }
    } else if (parseInt(part, 10)) {
      if (parseInt(part, 10) <= expectedPageCount)
        pageList.push(parseInt(part, 10));
    }
  }
  return pageList;
}

/**
 * Parses the selected page ranges, processes them and returns the results.
 * It squashes whenever possible. Example '1-2,3,5-7' becomes 1-3,5-7
 *
 * @return {Array} an array of page range objects. A page range object has
 *     fields 'from' and 'to'.
 */
function getPageRanges() {
  var pageList = getPageList();
  var pageRanges = [];
  for (var i = 0; i < pageList.length; i++) {
    tempFrom = pageList[i];
    while (i + 1 < pageList.length && pageList[i + 1] == pageList[i] + 1)
      i++;
    tempTo = pageList[i];
    pageRanges.push({'from': tempFrom, 'to': tempTo});
  }
  return pageRanges;
}
<commit_msg>Cleanup: Remove an unneed variable in the print preview Javascript code.<commit_after>// Copyright (c) 2011 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.

var localStrings = new LocalStrings();
var hasPDFPlugin = true;
var expectedPageCount = 0;
var pageRangesInfo = [];

/**
 * Window onload handler, sets up the page.
 */
function load() {
  initializeAnimation();

  updateSummary();

  $('printer-list').disabled = true;
  $('print-button').disabled = true;
  $('print-button').addEventListener('click', printFile);
  $('cancel-button').addEventListener('click', function(e) {
    window.close();
  });

  $('copies').addEventListener('input', validateNumberOfCopies);
  $('copies').addEventListener('blur', handleCopiesFieldBlur);
  $('individual-pages').addEventListener('blur', handlePageRangesFieldBlur);
  $('landscape').onclick = onLayoutModeToggle;
  $('portrait').onclick = onLayoutModeToggle;
  $('color').onclick = getPreview;
  $('bw').onclick = getPreview;

  chrome.send('getPrinters');
};

/**
 * Parses the copies field text for validation and updates the state of print
 * button and collate checkbox. If the specified value is invalid, displays an
 * invalid warning icon on the text box and sets the error message as the title
 * message of text box.
 */
function validateNumberOfCopies() {
  var copiesField = $('copies');
  var message = '';
  if (!isNumberOfCopiesValid())
    message = localStrings.getString('invalidNumberOfCopiesTitleToolTip');
  copiesField.setCustomValidity(message);
  copiesField.title = message;
  updatePrintButtonState();
}

/**
 * Handles copies field blur event.
 */
function handleCopiesFieldBlur() {
  checkAndSetCopiesField();
  printSettingChanged();
}

/**
 * Handles page ranges field blur event.
 */
function handlePageRangesFieldBlur() {
  checkAndSetPageRangesField();
}

/**
 * Depending on 'copies' value, shows/hides the collate checkbox.
 */
function updateCollateCheckboxState() {
  $('collate-option').hidden = getCopies() <= 1;
}

/**
 * Validates the copies text field value.
 * NOTE: An empty copies field text is considered valid because the blur event
 * listener of this field will set it back to a default value.
 * @return {boolean} true if the number of copies is valid else returns false.
 */
function isNumberOfCopiesValid() {
  var copiesFieldText = $('copies').value.replace(/\s/g, '');
  if (copiesFieldText == '')
    return true;

  var numericExp = /^[0-9]+$/;
  return (numericExp.test(copiesFieldText) && Number(copiesFieldText) > 0);
}

/**
 * Checks the value of the copies field. If it is a valid number it does
 * nothing. If it can only parse the first part of the string it replaces the
 * string with the first part. Example: '123abcd' becomes '123'.
 * If the string can't be parsed at all it replaces with 1.
 */
function checkAndSetCopiesField() {
  var copiesField = $('copies');
  var copies = parseInt(copiesField.value, 10);
  if (isNaN(copies))
    copies = 1;
  copiesField.value = copies;
  updateSummary();
}

/**
 * Checks the value of the page ranges text field. It parses the page ranges and
 * normalizes them. For example: '1,2,3,5,9-10' becomes '1-3, 5, 9-10'.
 * If it can't parse the whole string it will replace with the part it parsed.
 * For example: '1-6,9-10,sd343jf' becomes '1-6, 9-10'. If the specified page
 * range includes all pages it replaces it with the empty string (so that the
 * example text is automatically shown.
 *
 */
function checkAndSetPageRangesField() {
  var pageRanges = getPageRanges();
  var parsedPageRanges = '';
  var individualPagesField = $('individual-pages');

  if (pageRanges.length == 1 && pageRanges[0].from == 1 &&
          pageRanges[0].to == expectedPageCount) {
    individualPagesField.value = parsedPageRanges;
    return;
  }

  for (var i = 0; i < pageRanges.length; i++) {
    if (pageRanges[i].from == pageRanges[i].to)
      parsedPageRanges += pageRanges[i].from;
    else
      parsedPageRanges += pageRanges[i].from + '-' + pageRanges[i].to;
    if (i < pageRanges.length - 1)
      parsedPageRanges += ', ';
  }
  individualPagesField.value = parsedPageRanges;
  updateSummary();
}

/**
 * Checks whether the preview layout setting is set to 'landscape' or not.
 *
 * @return {boolean} true if layout is 'landscape'.
 */
function isLandscape() {
  return $('landscape').checked;
}

/**
 * Checks whether the preview color setting is set to 'color' or not.
 *
 * @return {boolean} true if color is 'color'.
 */
function isColor() {
  return $('color').checked;
}

/**
 * Checks whether the preview collate setting value is set or not.
 *
 * @return {boolean} true if collate setting is enabled and checked.
 */
function isCollated() {
  var collateField = $('collate');
  return !collateField.disabled && collateField.checked;
}

/**
 * Returns the number of copies currently indicated in the copies textfield. If
 * the contents of the textfield can not be converted to a number or if <1 it
 * returns 1.
 *
 * @return {number} number of copies.
 */
function getCopies() {
  var copies = parseInt($('copies').value, 10);
  if (!copies || copies <= 1)
    copies = 1;
  return copies;
}

/**
 * Checks whether the preview two-sided checkbox is checked.
 *
 * @return {boolean} true if two-sided is checked.
 */
function isTwoSided() {
  return $('two-sided').checked;
}

/**
 * Creates a JSON string based on the values in the printer settings.
 *
 * @return {string} JSON string with print job settings.
 */
function getSettingsJSON() {
  var selectedPrinter = $('printer-list').selectedIndex;
  var printerName = '';
  if (selectedPrinter >= 0)
    printerName = $('printer-list').options[selectedPrinter].textContent;
  var printAll = $('all-pages').checked;
  var printToPDF = (printerName == localStrings.getString('printToPDF'));

  return JSON.stringify({'printerName': printerName,
                         'pageRange': getPageRanges(),
                         'printAll': printAll,
                         'twoSided': isTwoSided(),
                         'copies': getCopies(),
                         'collate': isCollated(),
                         'landscape': isLandscape(),
                         'color': isColor(),
                         'printToPDF': printToPDF});
}

/**
 * Asks the browser to print the preview PDF based on current print settings.
 */
function printFile() {
  chrome.send('print', [getSettingsJSON()]);
}

/**
 * Asks the browser to generate a preview PDF based on current print settings.
 */
function getPreview() {
  chrome.send('getPreview', [getSettingsJSON()]);
}

/**
 * Fill the printer list drop down.
 * @param {Array} printers Array of printer names.
 * @param {number} defaultPrinterIndex The index of the default printer.
 */
function setPrinters(printers, defaultPrinterIndex) {
  if (printers.length > 0) {
    for (var i = 0; i < printers.length; ++i) {
      var option = document.createElement('option');
      option.textContent = printers[i];
      $('printer-list').add(option);
      if (i == defaultPrinterIndex)
        option.selected = true;
    }
  } else {
    var option = document.createElement('option');
    option.textContent = localStrings.getString('noPrinter');
    $('printer-list').add(option);
  }

  // Adding option for saving PDF to disk.
  var option = document.createElement('option');
  option.textContent = localStrings.getString('printToPDF');
  $('printer-list').add(option);
  $('printer-list').disabled = false;

  // Once the printer list is populated, generate the initial preview.
  getPreview();
}

/**
 * Sets the color mode for the PDF plugin.
 * @param {boolean} color is true if the PDF plugin should display in color.
 */
function setColor(color) {
  if (!hasPDFPlugin) {
    return;
  }
  $('pdf-viewer').grayscale(!color);
}

function onPDFLoad() {
  if (isLandscape())
    $('pdf-viewer').fitToWidth();
  else
    $('pdf-viewer').fitToHeight();
}

/**
 * Update the print preview when new preview data is available.
 * Create the PDF plugin as needed.
 * @param {number} pageCount The expected total pages count.
 * @param {string} jobTitle The print job title.
 *
 */
function updatePrintPreview(pageCount, jobTitle) {
  // Set the expected page count.
  expectedPageCount = pageCount;

  // Update the current tab title.
  document.title = localStrings.getStringF('printPreviewTitleFormat', jobTitle);

  createPDFPlugin();

  updateSummary();
}

/**
 * Create the PDF plugin or reload the existing one.
 */
function createPDFPlugin() {
  if (!hasPDFPlugin) {
    return;
  }

  // Enable the print button.
  if (!$('printer-list').disabled) {
    $('print-button').disabled = false;
  }

  if ($('pdf-viewer')) {
    $('pdf-viewer').reload();
    $('pdf-viewer').grayscale(!isColor());
    return;
  }

  var loadingElement = $('loading');
  loadingElement.classList.add('hidden');
  var mainView = loadingElement.parentNode;

  var pdfPlugin = document.createElement('embed');
  pdfPlugin.setAttribute('id', 'pdf-viewer');
  pdfPlugin.setAttribute('type', 'application/pdf');
  pdfPlugin.setAttribute('src', 'chrome://print/print.pdf');
  mainView.appendChild(pdfPlugin);
  if (!pdfPlugin.onload) {
    hasPDFPlugin = false;
    mainView.removeChild(pdfPlugin);
    $('no-plugin').classList.remove('hidden');
    return;
  }
  pdfPlugin.grayscale(true);
  pdfPlugin.onload('onPDFLoad()');
}

/**
 * Updates the state of print button depending on the user selection.
 *
 * If the user has selected 'All' pages option, enables the print button.
 * If the user has selected a page range, depending on the validity of page
 * range text enables/disables the print button.
 * Depending on the validity of 'copies' value, enables/disables the print
 * button.
 */
function updatePrintButtonState() {
  $('print-button').disabled = (!($('all-pages').checked ||
                                  $('individual-pages').checkValidity()) ||
                                !$('copies').checkValidity());
}

window.addEventListener('DOMContentLoaded', load);

/**
 * Listener function that executes whenever any of the available settings
 * is changed.
 */
function printSettingChanged() {
  updateCollateCheckboxState();
  updateSummary();
}

/**
 * Updates the print summary based on the currently selected user options.
 *
 */
function updateSummary() {
  var html = '';
  var pageList = getPageList();
  var copies = getCopies();
  var printButton = $('print-button');
  var printSummary = $('print-summary');

  if (isNaN($('copies').value)) {
    html = localStrings.getString('invalidNumberOfCopiesTitleToolTip');
    printSummary.innerHTML = html;
    return;
  }

  if (pageList.length <= 0) {
    html = localStrings.getString('pageRangeInvalidTitleToolTip');
    printSummary.innerHTML = html;
    printButton.disabled = true;
    return;
  }

  var pagesLabel = localStrings.getString('printPreviewPageLabelSingular');
  var twoSidedLabel = '';
  var timesSign = '';
  var numOfCopies = '';
  var copiesLabel = '';
  var equalSign = '';
  var numOfSheets = '';
  var sheetsLabel = '';

  printButton.disabled = false;

  if (pageList.length > 1)
    pagesLabel = localStrings.getString('printPreviewPageLabelPlural');

  if (isTwoSided())
    twoSidedLabel = '('+localStrings.getString('optionTwoSided')+')';

  if (copies > 1) {
    timesSign = '×';
    numOfCopies = copies;
    copiesLabel = localStrings.getString('copiesLabel').toLowerCase();
  }

  if ((copies > 1) || (isTwoSided())) {
    numOfSheets = pageList.length;

    if (isTwoSided())
      numOfSheets = Math.ceil(numOfSheets / 2);

    equalSign = '=';
    numOfSheets *= copies;
    sheetsLabel = localStrings.getString('printPreviewSheetsLabel');
  }

  html = localStrings.getStringF('printPreviewSummaryFormat', pageList.length,
                                  pagesLabel, twoSidedLabel, timesSign,
                                  numOfCopies, copiesLabel, equalSign,
                                  ''+numOfSheets+'',
                                  ''+sheetsLabel+'');

  // Removing extra spaces from within the string.
  html.replace(/\s{2,}/g, ' ');
  printSummary.innerHTML = html;
}

/**
 * Handles a click event on the two-sided option.
 */
function handleTwoSidedClick(event) {
  var el = $('binding');
  handleZippyClickEl(el);
  printSettingChanged(event);
}

/**
 * When the user switches printing orientation mode the page field selection is
 * reset to "all pages selected". After the change the number of pages will be
 * different and currently selected page numbers might no longer be valid.
 * Even if they are still valid the content of these pages will be different.
 */
function onLayoutModeToggle() {
  $('individual-pages').value = '';
  $('all-pages').checked = true;
  getPreview();
}

/**
 * Returns a list of all pages in the specified ranges. If the page ranges can't
 * be parsed an empty list is returned.
 *
 * @return {Array}
 */
function getPageList() {
  var pageText = $('individual-pages').value;

  if ($('all-pages').checked || pageText == '')
    pageText = '1-' + expectedPageCount;

  var pageList = [];
  var parts = pageText.split(/,/);

  for (var i = 0; i < parts.length; i++) {
    var part = parts[i];
    var match = part.match(/([0-9]+)-([0-9]+)/);

    if (match && match[1] && match[2]) {
      var from = parseInt(match[1], 10);
      var to = parseInt(match[2], 10);

      if (from && to) {
        for (var j = from; j <= to; j++)
          if (j <= expectedPageCount)
            pageList.push(j);
      }
    } else if (parseInt(part, 10)) {
      if (parseInt(part, 10) <= expectedPageCount)
        pageList.push(parseInt(part, 10));
    }
  }
  return pageList;
}

/**
 * Parses the selected page ranges, processes them and returns the results.
 * It squashes whenever possible. Example '1-2,3,5-7' becomes 1-3,5-7
 *
 * @return {Array} an array of page range objects. A page range object has
 *     fields 'from' and 'to'.
 */
function getPageRanges() {
  var pageList = getPageList();
  var pageRanges = [];
  for (var i = 0; i < pageList.length; i++) {
    tempFrom = pageList[i];
    while (i + 1 < pageList.length && pageList[i + 1] == pageList[i] + 1)
      i++;
    tempTo = pageList[i];
    pageRanges.push({'from': tempFrom, 'to': tempTo});
  }
  return pageRanges;
}
<|endoftext|>


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

(function(scope) {
  'use strict';

  var isWrapperFor = scope.isWrapperFor;

  // This is a list of the elements we currently override the global constructor
  // for.
  var elements = {
    'a': 'HTMLAnchorElement',
    'applet': 'HTMLAppletElement',
    'area': 'HTMLAreaElement',
    'br': 'HTMLBRElement',
    'base': 'HTMLBaseElement',
    'body': 'HTMLBodyElement',
    'button': 'HTMLButtonElement',
    // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.
    'dl': 'HTMLDListElement',
    'datalist': 'HTMLDataListElement',
    'data': 'HTMLDataElement',
    'dir': 'HTMLDirectoryElement',
    'div': 'HTMLDivElement',
    'embed': 'HTMLEmbedElement',
    'fieldset': 'HTMLFieldSetElement',
    'font': 'HTMLFontElement',
    'form': 'HTMLFormElement',
    'frame': 'HTMLFrameElement',
    'frameset': 'HTMLFrameSetElement',
    'hr': 'HTMLHRElement',
    'head': 'HTMLHeadElement',
    'h1': 'HTMLHeadingElement',
    'html': 'HTMLHtmlElement',
    'iframe': 'HTMLIFrameElement',
    'input': 'HTMLInputElement',
    'li': 'HTMLLIElement',
    'label': 'HTMLLabelElement',
    'legend': 'HTMLLegendElement',
    'link': 'HTMLLinkElement',
    'map': 'HTMLMapElement',
    'marquee': 'HTMLMarqueeElement',
    'menu': 'HTMLMenuElement',
    'menuitem': 'HTMLMenuItemElement',
    'meta': 'HTMLMetaElement',
    'meter': 'HTMLMeterElement',
    'del': 'HTMLModElement',
    'ol': 'HTMLOListElement',
    'object': 'HTMLObjectElement',
    'optgroup': 'HTMLOptGroupElement',
    'option': 'HTMLOptionElement',
    'output': 'HTMLOutputElement',
    'p': 'HTMLParagraphElement',
    'param': 'HTMLParamElement',
    'pre': 'HTMLPreElement',
    'progress': 'HTMLProgressElement',
    'q': 'HTMLQuoteElement',
    'script': 'HTMLScriptElement',
    'select': 'HTMLSelectElement',
    'source': 'HTMLSourceElement',
    'span': 'HTMLSpanElement',
    'style': 'HTMLStyleElement',
    'time': 'HTMLTimeElement',
    'caption': 'HTMLTableCaptionElement',
    // WebKit and Moz are wrong:
    // https://bugs.webkit.org/show_bug.cgi?id=111469
    // https://bugzilla.mozilla.org/show_bug.cgi?id=848096
    // 'td': 'HTMLTableCellElement',
    'col': 'HTMLTableColElement',
    'table': 'HTMLTableElement',
    'tr': 'HTMLTableRowElement',
    'thead': 'HTMLTableSectionElement',
    'tbody': 'HTMLTableSectionElement',
    'textarea': 'HTMLTextAreaElement',
    'track': 'HTMLTrackElement',
    'title': 'HTMLTitleElement',
    'ul': 'HTMLUListElement',
    'video': 'HTMLVideoElement',
  };

  function overrideConstructor(tagName) {
    var nativeConstructorName = elements[tagName];
    var nativeConstructor = window[nativeConstructorName];
    if (!nativeConstructor)
      return;
    var element = document.createElement(tagName);
    var wrapperConstructor = element.constructor;
    window[nativeConstructorName] = wrapperConstructor;
  }

  Object.keys(elements).forEach(overrideConstructor);

  Object.getOwnPropertyNames(scope.wrappers).forEach(function(name) {
    window[name] = scope.wrappers[name]
  });

  // Export for testing.
  scope.knownElements = elements;

})(window.ShadowDOMPolyfill);
<commit_msg>Do not create an applet element during startup<commit_after>// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.

(function(scope) {
  'use strict';

  var isWrapperFor = scope.isWrapperFor;

  // This is a list of the elements we currently override the global constructor
  // for.
  var elements = {
    'a': 'HTMLAnchorElement',

    // Do not create an applet element by default since it shows a warning in
    // IE.
    // https://github.com/Polymer/polymer/issues/217
    // 'applet': 'HTMLAppletElement',

    'area': 'HTMLAreaElement',
    'br': 'HTMLBRElement',
    'base': 'HTMLBaseElement',
    'body': 'HTMLBodyElement',
    'button': 'HTMLButtonElement',
    // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.
    'dl': 'HTMLDListElement',
    'datalist': 'HTMLDataListElement',
    'data': 'HTMLDataElement',
    'dir': 'HTMLDirectoryElement',
    'div': 'HTMLDivElement',
    'embed': 'HTMLEmbedElement',
    'fieldset': 'HTMLFieldSetElement',
    'font': 'HTMLFontElement',
    'form': 'HTMLFormElement',
    'frame': 'HTMLFrameElement',
    'frameset': 'HTMLFrameSetElement',
    'hr': 'HTMLHRElement',
    'head': 'HTMLHeadElement',
    'h1': 'HTMLHeadingElement',
    'html': 'HTMLHtmlElement',
    'iframe': 'HTMLIFrameElement',
    'input': 'HTMLInputElement',
    'li': 'HTMLLIElement',
    'label': 'HTMLLabelElement',
    'legend': 'HTMLLegendElement',
    'link': 'HTMLLinkElement',
    'map': 'HTMLMapElement',
    'marquee': 'HTMLMarqueeElement',
    'menu': 'HTMLMenuElement',
    'menuitem': 'HTMLMenuItemElement',
    'meta': 'HTMLMetaElement',
    'meter': 'HTMLMeterElement',
    'del': 'HTMLModElement',
    'ol': 'HTMLOListElement',
    'object': 'HTMLObjectElement',
    'optgroup': 'HTMLOptGroupElement',
    'option': 'HTMLOptionElement',
    'output': 'HTMLOutputElement',
    'p': 'HTMLParagraphElement',
    'param': 'HTMLParamElement',
    'pre': 'HTMLPreElement',
    'progress': 'HTMLProgressElement',
    'q': 'HTMLQuoteElement',
    'script': 'HTMLScriptElement',
    'select': 'HTMLSelectElement',
    'source': 'HTMLSourceElement',
    'span': 'HTMLSpanElement',
    'style': 'HTMLStyleElement',
    'time': 'HTMLTimeElement',
    'caption': 'HTMLTableCaptionElement',
    // WebKit and Moz are wrong:
    // https://bugs.webkit.org/show_bug.cgi?id=111469
    // https://bugzilla.mozilla.org/show_bug.cgi?id=848096
    // 'td': 'HTMLTableCellElement',
    'col': 'HTMLTableColElement',
    'table': 'HTMLTableElement',
    'tr': 'HTMLTableRowElement',
    'thead': 'HTMLTableSectionElement',
    'tbody': 'HTMLTableSectionElement',
    'textarea': 'HTMLTextAreaElement',
    'track': 'HTMLTrackElement',
    'title': 'HTMLTitleElement',
    'ul': 'HTMLUListElement',
    'video': 'HTMLVideoElement',
  };

  function overrideConstructor(tagName) {
    var nativeConstructorName = elements[tagName];
    var nativeConstructor = window[nativeConstructorName];
    if (!nativeConstructor)
      return;
    var element = document.createElement(tagName);
    var wrapperConstructor = element.constructor;
    window[nativeConstructorName] = wrapperConstructor;
  }

  Object.keys(elements).forEach(overrideConstructor);

  Object.getOwnPropertyNames(scope.wrappers).forEach(function(name) {
    window[name] = scope.wrappers[name]
  });

  // Export for testing.
  scope.knownElements = elements;

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