<commit_before>import React from 'react';
import { Link } from 'react-router';
import { subscribe } from 'horizon-react';
import { Row, Col, Form, FormGroup, Button } from 'react-bootstrap';

import { updateRsvpQuery, updateRsvpResult } from '../../../actions/actionCreators';

import PageHeader from '../../_partials/page-header';

import glob from 'styles/app';

/**
  *
  * RSVP Search Page
  *
  * Includes ..
  *
  * @param ..
  *
  * @return {ReactComponent}
  */

const mapDataToProps = {
  invitations: (hz, props) => {
    hz('invitations').fetch().subscribe(
      invitations => {
        invitations.forEach(
          invitation => {
            invitation.guests.forEach(
              guest => {
                if (guest.email && guest.email === props.rsvpSearch.query) {
                  props.dispatch(updateRsvpResult(invitation));
                }
              }
            );
          }
        );
      }
    );
    return hz('invitations');
  }
};

const mapStateToProps = (state) => ({
  rsvpSearch: state.rsvpSearch
});

class Rsvp extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const query = this.props.rsvpSearch.query;

    const queryMessage = query
    ? 'Invitation not found'
    : '';

    const inviteFound = this.props.rsvpSearch.result
    ? <Button bsSize="large" className={`${glob.button}`} href={`/rsvp/${this.props.rsvpSearch.result.shortName}`}>Go to RSVP</Button>
    :
{queryMessage}
;

    return (

        <Row>
          <Col xs={12}>
            <PageHeader page="Find Invitation" />
          </Col>
        </Row>
        <Row>
          <Col xs={12}>
            <Form>
              <FormGroup>
                <input placeholder="Email" type="email" id="rsvp-query" value={query} onChange={this.handleChange.bind(this)}/>

              </FormGroup>
            </Form>
          </Col>
          <Col xs={12}>
            {inviteFound}
          </Col>
        </Row>

    );
  }

  handleChange(event) {
    this.props.dispatch(updateRsvpQuery(event.target.value));
  }
}

export default subscribe({
  mapDataToProps,
  mapStateToProps
})(Rsvp);
<commit_msg>RSVP Search - prevent reload on enter<commit_after>import React from 'react';
import { Link } from 'react-router';
import { subscribe } from 'horizon-react';
import { Row, Col, Form, FormGroup, Button } from 'react-bootstrap';

import { updateRsvpQuery, updateRsvpResult } from '../../../actions/actionCreators';

import PageHeader from '../../_partials/page-header';

import glob from 'styles/app';

/**
  *
  * RSVP Search Page
  *
  * Includes ..
  *
  * @param ..
  *
  * @return {ReactComponent}
  */

const mapDataToProps = {
  invitations: (hz, props) => {
    hz('invitations').fetch().subscribe(
      invitations => {
        invitations.forEach(
          invitation => {
            invitation.guests.forEach(
              guest => {
                if (guest.email && guest.email === props.rsvpSearch.query) {
                  props.dispatch(updateRsvpResult(invitation));
                }
              }
            );
          }
        );
      }
    );
    return hz('invitations');
  }
};

const mapStateToProps = (state) => ({
  rsvpSearch: state.rsvpSearch
});

class Rsvp extends React.Component {
  constructor(props) {
    super(props);
  }

  handleSubmit(e) {
    e.preventDefault();
  }

  render() {
    const query = this.props.rsvpSearch.query;

    const queryMessage = query
    ? 'Invitation not found'
    : '';

    const inviteFound = this.props.rsvpSearch.result
    ? <Button bsSize="large" className={`${glob.button}`} href={`/rsvp/${this.props.rsvpSearch.result.shortName}`}>Go to RSVP</Button>
    :
{queryMessage}
;

    return (

        <Row>
          <Col xs={12}>
            <PageHeader page="Find Invitation" />
          </Col>
        </Row>
        <Row>
          <Col xs={12}>
            <Form onSubmit={this.handleSubmit}>
              <FormGroup style={{textAlign: 'center'}}>
                <input placeholder="Email" type="email" id="rsvp-query" value={query} onChange={this.handleChange.bind(this)}/>

              </FormGroup>
            </Form>
          </Col>
          <Col xs={12} style={{textAlign: 'center'}}>
            {inviteFound}
          </Col>
        </Row>

    );
  }

  handleChange(event) {
    this.props.dispatch(updateRsvpQuery(event.target.value));
  }
}

export default subscribe({
  mapDataToProps,
  mapStateToProps
})(Rsvp);
<|endoftext|>


<commit_before>// popup
// coded by azrafe7

'use strict';

var self = this;
var bgPage = chrome.extension.getBackgroundPage();	// ref to background page object
var currTab;
var url;
var xhr;

var DEBUG = false;
var VLC_INTERFACE = "http://localhost:8080/requests/";
var EXTENSION_URL = "https://chrome.google.com/webstore/detail/vlc-4-youtube-beta/jldiailifbdkepgpcojllmkbakleicab?hl=en";

var timer;
var info;
var format;
var title;
var lastCommand;

// execute main() when DOM is ready
$(document).ready(main);

function sendRequest(url, errorCallback, successCallback) {
	log("sending", url);
	$("#vlcUrl").val(url);
	xhr = new XMLHttpRequest();
	xhr.open("GET", url);
	xhr.onreadystatechange = function() {
		if (xhr.readyState == 4) {
      var regex = /command=([^&;\s]+)/gi;
      var matches = regex.exec(url);
      lastCommand = matches && matches[1];
			errorCallback = errorCallback || onVlcError;
			successCallback = successCallback || onVlcSuccess;
			if (xhr.status != 200) {
				errorCallback(xhr);
			} else {
				successCallback(xhr);
			}
		}
	}
	xhr.send();
}

function setTitle(format, title) {
	self.format = format || self.format;
	self.title = title || self.title;

	self.video = "Format: " + "" + self.format + "
" +
			"Title: " + "" + self.title + "
";
	$("#stream-info").html(self.video);
}

function setMessage(msg, hideTitle) {
	var $msg = $("#msg");
	$("#stream-info").toggle(!hideTitle);
	$msg.html(msg);
	return $msg;
}

function play(url, options, title) {
  title = title || ellipsizeMiddle(url, 80);
	var urlParam = (options && options.mustEncode) ? encodeURIComponent(url) : url;
	sendRequest(VLC_INTERFACE + "status.json?command=in_play&input=" + urlParam + "&name=" + encodeURIComponent(title));
}

function enqueue(url, options, title) {
  title = title || ellipsizeMiddle(url, 80);
	var urlParam = (options && options.mustEncode) ? encodeURIComponent(url) : url;
	sendRequest(VLC_INTERFACE + "status.json?command=in_enqueue&input=" + urlParam + "&name=" + encodeURIComponent(title));
}

function addFormatFieldTo(item) {
	item.format = item.itag + " - " +
				  item.type.match(/.*?;/) + " " +
				  (item.resolution || "[audio only]") + " " +
				  (item.audioEncoding ? "" : "[video only]") +
				  " (" + (item.quality || item.quality_label || (item.audioBitrate + "br")) + ")";
	return item;
}

function findStreamsFor(url, probeOnly) {
	setMessage("Probing VLC http interface...", true).show();

	sendRequest(VLC_INTERFACE + "status.json", onVlcError, function(xhr) { // probe VLC interface
		interfaceFound();
		setMessage("Retrieving preferred quality stream url...", true);
		ytdl.getInfo(url, function(error, info) { // get video info
			if (error) {
				onInfoError({statusText:error});
				return;
			}

			populateStreams(null, info);

			var quality = "highest";
			var filter = "video";

			var format = ytdl.utils.chooseFormat(info.formats, {quality: quality, filter: filter});
			// if found, make it the first in the array
			if (format && !(format instanceof Error)) {
				info.formats.splice(info.formats.indexOf(format), 1);
				info.formats.unshift(format);
			} else {
				onInfoError({statusText:format.message});
				return;
			}

			onInfoSuccess(null, info, probeOnly);
		});
	});
}

function populateStreams(xhr, data) {
	if (data) info = data;
	else info = JSON.parse(xhr.response).info;

	for (i in info.formats) addFormatFieldTo(info.formats[i]);

	// insert info for current page (plain url)
	info.formats.push({format:"current page url", url:url});

	log("Info (all streams):", info);

	// populate stream links (debug)
	var streams = $("#streams").empty();
	for (var o in info.formats) {
		var i = info.formats[o];
		var a = $("").attr({
			"href":i.url,
			"data-format":i.format,
			"title":ellipsizeMiddle(i.url, 80)
		}).text(i.format);

		var div = $("
").append(a);
		a.bind("click", function() {
			setTitle($(this).attr("data-format"));
			play($(this).attr("href"), { mustEncode: true }, info.title);
		});
		streams.append(div);
	}
}

function onInfoSuccess(xhr, data, probeOnly) {

	var best = info.formats[0];
	log("Preferred stream:", best.format, best.url);

	format = best.format;

	setTitle(format, info.title);
	setMessage("", false);

	// play
	if (!probeOnly) {
		play(best.url, { mustEncode: true }, info.title);
	}

	//$("#vlcUrl").val(VLC_INTERFACE + "status.json?command=in_play&input=" + encodeURIComponent(url));
}

function onInfoError(xhr) {
	log(xhr.status, xhr.statusText, xhr);
	setMessage("No matching stream found (" + xhr.statusText + ").", true);
	/*setTimeout(function() {
		setTitle("unknown (current page url)");
		play(url, { mustEncode: true }, url); // try sending curr url as is
	}, 2000);*/
}

function onVlcSuccess(xhr) {
	log(xhr.status, xhr.statusText, xhr);

	setTitle(format, title);
  var lastCommandStr = "";
  if (lastCommand) lastCommandStr = " (" + lastCommand + ")";
	setMessage("
Command sent to VLC" + lastCommandStr + ".", false).hide().fadeIn(400, "swing");

	$("#no-interface").hide();
	if (!DEBUG) self.timer = setTimeout(function() { window.close(); }, 4000); // close popup
}

function onVlcError(xhr) {
	$("#no-interface").show();
	setMessage("", true);
	log(xhr.status, xhr.statusText, xhr);
}

function interfaceFound(xhr) {
	log("VLC http interface found!");
	$("#no-interface").hide();
}

// main function (executed when the DOM is ready)
function main() {
	$("#no-interface a").bind("click", function() {  // enable interface how-to link
    chrome.tabs.create({url:$(this).attr("href")});
  });

	// hidden
	$("#debug-wrapper").hide();
	$("#no-interface").hide();
	$("#stream-info").hide();

	$("#title").html("" + bgPage.manifest.name + " v" + bgPage.manifest.version + "");
	$("#webstore").bind("click", function() { chrome.tabs.create({url:EXTENSION_URL}) }); // goto extension page on the webstore
	$("#doom .key").bind("click", function() { toggleDoomConsole(); }); // toggle doom console when clicking '\'

	// bind events
	$("#vlcUrl").bind("keyup", function(event) {
		if (event.keyCode == 13) {
			log("send");
			$("#sendBtn").click();
		}
	});

	$("#videoUrl").bind("keyup", function(event) {
		if (event.keyCode == 13) {
			log("find");
			log("find");
			$("#findBtn").click();
		}
	});

	$("body").bind("keyup", function(event) {
    var vlcUrlInput = $("#vlcUrl").get(0);
    var videoUrlInput = $("#videoUrl").get(0);
		if (document.activeElement != vlcUrlInput && document.activeElement != videoUrlInput) {
      if (event.keyCode == 220 || event.keyCode == 86) { // doom console '\' or 'v'
        toggleDoomConsole();
      } else if (event.keyCode == 81) { // 'q' - enqueue
        log("en'q'");
        $("#enqueueBtn").click();
      } else if (event.keyCode == 80) { // 'p' - play
        $("#playBtn").click();
      } else if (event.keyCode == 90) { // 'z' - prev
        $("#prevBtn").click();
      } else if (event.keyCode == 88) { // 'x' - toggle pause
        $("#pauseBtn").click();
      } else if (event.keyCode == 67) { // 'c' - next
        $("#nextBtn").click();
      } else if (event.keyCode == 46) { // 'canc' - clear
        $("#clearBtn").click();
      }
		}
	});

	// buttons
	$("#sendBtn").bind("click", function() { sendRequest($("#vlcUrl").val()); });
	$("#findBtn").bind("click", function() {
		$("#streams").empty();
		url = $("#videoUrl").val();
		findStreamsFor(url, true);
	});
	$("#pauseBtn").bind("click", function() {
		sendRequest(VLC_INTERFACE + "status.json?command=pl_pause");
	});
	$("#prevBtn").bind("click", function() {
		sendRequest(VLC_INTERFACE + "status.json?command=pl_previous");
	});
	$("#nextBtn").bind("click", function() {
		sendRequest(VLC_INTERFACE + "status.json?command=pl_next");
	});
	$("#clearBtn").bind("click", function() {
		sendRequest(VLC_INTERFACE + "status.json?command=pl_empty");
	});
	$("#enqueueBtn").bind("click", function() {
    if (info && info.formats) {
      enqueue(info.formats[0].url, { mustEncode: true }, info.title);
    }
	});
	$("#playBtn").bind("click", function() {
    if (info && info.formats) {
      play(info.formats[0].url, { mustEncode: true }, info.title);
    }
	});

	// query active tab
	chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
		self.currTab = tabs[0];

		self.title = self.currTab.title.substr(0, self.currTab.title.length - 9);
		self.url = self.currTab.url;

		$("#videoUrl").val(self.url);

		// using a little timeout here, so the user can press '\' to choose the stream
		setMessage("Probing VLC http interface...", true).show();
		setTimeout(function() {	findStreamsFor(url, DEBUG); }, 700);
	});
}

function toggleDoomConsole() {
	DEBUG = true;
	clearTimeout(self.timer);
	log("debug");
	$("#debug-wrapper").toggle();
}

function ellipsizeMiddle(str, maxLength) {
	var ellipsis = "...";
	var strLen = str.length;
	if (strLen <= maxLength)
		return str;

	var ellipsisLen = ellipsis.length;
	if (maxLength < ellipsisLen) return ellipsis.substring(0, maxLength);

	var maxStrLen = maxLength - ellipsisLen;
	var leftLen = Math.round(maxStrLen / 2);
	var rightLen = maxStrLen - leftLen;

	return str.substring(0, leftLen) + ellipsis + str.substr(-rightLen);
}

function log(...args) {
	if (DEBUG) console.log.apply(console, args);
}<commit_msg>better error message when unauthorized (login needed)<commit_after>// popup
// coded by azrafe7

'use strict';

var self = this;
var bgPage = chrome.extension.getBackgroundPage();	// ref to background page object
var currTab;
var url;
var xhr;

var DEBUG = false;
var VLC_HOST = "http://localhost";
var VLC_PORT = "8080";
var VLC_INTERFACE = VLC_HOST + ":" + VLC_PORT + "/requests/";
var EXTENSION_URL = "https://chrome.google.com/webstore/detail/vlc-4-youtube-beta/jldiailifbdkepgpcojllmkbakleicab?hl=en";

var timer;
var info;
var format;
var title;
var lastCommand;

// execute main() when DOM is ready
$(document).ready(main);

function sendRequest(url, errorCallback, successCallback) {
	log("sending", url);
	$("#vlcUrl").val(url);
	xhr = new XMLHttpRequest();
	xhr.open("GET", url);
	xhr.onreadystatechange = function() {
		if (xhr.readyState == 4) {
      var regex = /command=([^&;\s]+)/gi;
      var matches = regex.exec(url);
      lastCommand = matches && matches[1];
			errorCallback = errorCallback || onVlcError;
			successCallback = successCallback || onVlcSuccess;
			if (xhr.status != 200) {
				errorCallback(xhr);
			} else {
				successCallback(xhr);
			}
		}
	}
	xhr.send();
}

function setTitle(format, title) {
	self.format = format || self.format;
	self.title = title || self.title;

	self.video = "Format: " + "" + self.format + "
" +
			"Title: " + "" + self.title + "
";
	$("#stream-info").html(self.video);
}

function setMessage(msg, hideTitle) {
	var $msg = $("#msg");
	$("#stream-info").toggle(!hideTitle);
	$msg.html(msg);
	return $msg;
}

function play(url, options, title) {
  title = title || ellipsizeMiddle(url, 80);
	var urlParam = (options && options.mustEncode) ? encodeURIComponent(url) : url;
	sendRequest(VLC_INTERFACE + "status.json?command=in_play&input=" + urlParam + "&name=" + encodeURIComponent(title));
}

function enqueue(url, options, title) {
  title = title || ellipsizeMiddle(url, 80);
	var urlParam = (options && options.mustEncode) ? encodeURIComponent(url) : url;
	sendRequest(VLC_INTERFACE + "status.json?command=in_enqueue&input=" + urlParam + "&name=" + encodeURIComponent(title));
}

function addFormatFieldTo(item) {
	item.format = item.itag + " - " +
				  item.type.match(/.*?;/) + " " +
				  (item.resolution || "[audio only]") + " " +
				  (item.audioEncoding ? "" : "[video only]") +
				  " (" + (item.quality || item.quality_label || (item.audioBitrate + "br")) + ")";
	return item;
}

function findStreamsFor(url, probeOnly) {
	setMessage("Probing VLC http interface...", true).show();

	sendRequest(VLC_INTERFACE + "status.json", onVlcError, function(xhr) { // probe VLC interface
		interfaceFound();
		setMessage("Retrieving preferred quality stream url...", true);
		ytdl.getInfo(url, function(error, info) { // get video info
			if (error) {
				onInfoError({statusText:error});
				return;
			}

			populateStreams(null, info);

			var quality = "highest";
			var filter = "video";

			var format = ytdl.utils.chooseFormat(info.formats, {quality: quality, filter: filter});
			// if found, make it the first in the array
			if (format && !(format instanceof Error)) {
				info.formats.splice(info.formats.indexOf(format), 1);
				info.formats.unshift(format);
			} else {
				onInfoError({statusText:format.message});
				return;
			}

			onInfoSuccess(null, info, probeOnly);
		});
	});
}

function populateStreams(xhr, data) {
	if (data) info = data;
	else info = JSON.parse(xhr.response).info;

	for (i in info.formats) addFormatFieldTo(info.formats[i]);

	// insert info for current page (plain url)
	info.formats.push({format:"current page url", url:url});

	log("Info (all streams):", info);

	// populate stream links (debug)
	var streams = $("#streams").empty();
	for (var o in info.formats) {
		var i = info.formats[o];
		var a = $("").attr({
			"href":i.url,
			"data-format":i.format,
			"title":ellipsizeMiddle(i.url, 80)
		}).text(i.format);

		var div = $("
").append(a);
		a.bind("click", function() {
			setTitle($(this).attr("data-format"));
			play($(this).attr("href"), { mustEncode: true }, info.title);
		});
		streams.append(div);
	}
}

function onInfoSuccess(xhr, data, probeOnly) {

	var best = info.formats[0];
	log("Preferred stream:", best.format, best.url);

	format = best.format;

	setTitle(format, info.title);
	setMessage("", false);

	// play
	if (!probeOnly) {
		play(best.url, { mustEncode: true }, info.title);
	}

	//$("#vlcUrl").val(VLC_INTERFACE + "status.json?command=in_play&input=" + encodeURIComponent(url));
}

function onInfoError(xhr) {
	log(xhr.status, xhr.statusText, xhr);
	setMessage("No matching stream found (" + xhr.statusText + ").", true);
	/*setTimeout(function() {
		setTitle("unknown (current page url)");
		play(url, { mustEncode: true }, url); // try sending curr url as is
	}, 2000);*/
}

function onVlcSuccess(xhr) {
	log(xhr.status, xhr.statusText, xhr);

	setTitle(format, title);
  var lastCommandStr = "";
  if (lastCommand) lastCommandStr = " (" + lastCommand + ")";
	setMessage("
Command sent to VLC" + lastCommandStr + ".", false).hide().fadeIn(400, "swing");

	$("#no-interface").hide();
	if (!DEBUG) self.timer = setTimeout(function() { window.close(); }, 4000); // close popup
}

function onVlcError(xhr) {
	$("#no-interface").show();
  var errorText = xhr.statusText;
  var intf = VLC_HOST + ":" + VLC_PORT;
  if (xhr.status == 401) errorText = 'Unauthorized, please login here first';
	setMessage("
Received: " + errorText + " (" + xhr.status + ").", true);
	log(xhr.status, errorText, xhr);
}

function interfaceFound(xhr) {
	log("VLC http interface found!");
	$("#no-interface").hide();
}

// main function (executed when the DOM is ready)
function main() {
	$("#no-interface a").bind("click", function() {  // enable interface how-to link
    chrome.tabs.create({url:$(this).attr("href")});
  });

	// hidden
	$("#debug-wrapper").hide();
	$("#no-interface").hide();
	$("#stream-info").hide();

	$("#title").html("" + bgPage.manifest.name + " v" + bgPage.manifest.version + "");
	$("#webstore").bind("click", function() { chrome.tabs.create({url:EXTENSION_URL}) }); // goto extension page on the webstore
	$("#doom .key").bind("click", function() { toggleDoomConsole(); }); // toggle doom console when clicking '\'

	// bind events
	$("#vlcUrl").bind("keyup", function(event) {
		if (event.keyCode == 13) {
			log("send");
			$("#sendBtn").click();
		}
	});

	$("#videoUrl").bind("keyup", function(event) {
		if (event.keyCode == 13) {
			log("find");
			log("find");
			$("#findBtn").click();
		}
	});

	$("body").bind("keyup", function(event) {
    var vlcUrlInput = $("#vlcUrl").get(0);
    var videoUrlInput = $("#videoUrl").get(0);
		if (document.activeElement != vlcUrlInput && document.activeElement != videoUrlInput) {
      if (event.keyCode == 220 || event.keyCode == 86) { // doom console '\' or 'v'
        toggleDoomConsole();
      } else if (event.keyCode == 81) { // 'q' - enqueue
        log("en'q'");
        $("#enqueueBtn").click();
      } else if (event.keyCode == 80) { // 'p' - play
        $("#playBtn").click();
      } else if (event.keyCode == 90) { // 'z' - prev
        $("#prevBtn").click();
      } else if (event.keyCode == 88) { // 'x' - toggle pause
        $("#pauseBtn").click();
      } else if (event.keyCode == 67) { // 'c' - next
        $("#nextBtn").click();
      } else if (event.keyCode == 46) { // 'canc' - clear
        $("#clearBtn").click();
      }
		}
	});

	// buttons
	$("#sendBtn").bind("click", function() { sendRequest($("#vlcUrl").val()); });
	$("#findBtn").bind("click", function() {
		$("#streams").empty();
		url = $("#videoUrl").val();
		findStreamsFor(url, true);
	});
	$("#pauseBtn").bind("click", function() {
		sendRequest(VLC_INTERFACE + "status.json?command=pl_pause");
	});
	$("#prevBtn").bind("click", function() {
		sendRequest(VLC_INTERFACE + "status.json?command=pl_previous");
	});
	$("#nextBtn").bind("click", function() {
		sendRequest(VLC_INTERFACE + "status.json?command=pl_next");
	});
	$("#clearBtn").bind("click", function() {
		sendRequest(VLC_INTERFACE + "status.json?command=pl_empty");
	});
	$("#enqueueBtn").bind("click", function() {
    if (info && info.formats) {
      enqueue(info.formats[0].url, { mustEncode: true }, info.title);
    }
	});
	$("#playBtn").bind("click", function() {
    if (info && info.formats) {
      play(info.formats[0].url, { mustEncode: true }, info.title);
    }
	});

	// query active tab
	chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
		self.currTab = tabs[0];

		self.title = self.currTab.title.substr(0, self.currTab.title.length - 9);
		self.url = self.currTab.url;

		$("#videoUrl").val(self.url);

		// using a little timeout here, so the user can press '\' to choose the stream
		setMessage("Probing VLC http interface...", true).show();
		setTimeout(function() {	findStreamsFor(url, DEBUG); }, 700);
	});
}

function toggleDoomConsole() {
	DEBUG = true;
	clearTimeout(self.timer);
	log("debug");
	$("#debug-wrapper").toggle();
}

function ellipsizeMiddle(str, maxLength) {
	var ellipsis = "...";
	var strLen = str.length;
	if (strLen <= maxLength)
		return str;

	var ellipsisLen = ellipsis.length;
	if (maxLength < ellipsisLen) return ellipsis.substring(0, maxLength);

	var maxStrLen = maxLength - ellipsisLen;
	var leftLen = Math.round(maxStrLen / 2);
	var rightLen = maxStrLen - leftLen;

	return str.substring(0, leftLen) + ellipsis + str.substr(-rightLen);
}

function log(...args) {
	if (DEBUG) console.log.apply(console, args);
}
<|endoftext|>


<commit_before>define(
	[
		"../meta",
		"./invocation",
		"./implementation-not-found"
	],
	function (meta, Invocation, ImplementationNotFound) {
		"use strict";

		meta({
			"entity": "method",
			"for": "Function",
			"name": "Abstract",
			"static": true,
			"description": "A higher-order function that returns a function to serve as an abstract implementation.",
			"arguments": [{
				"name": "functionName",
				"type": "string",
				"description": "The "
			}],
			"returns": {
				"type": "function",
				"description": "throws an ImplementationNotFound error."
			}
		});

		Function.Abstract = function (functionName) {
			return function () {
				var invocation = Invocation.instance,
					errorDetails = {
						functionName: functionName
					};
				if (invocation) {
					errorDetails.signature = invocation.signature;
					errorDetails.nonMatchingSignatures = invocation.nonMatchingImplementationSignatures;
					invocation.reset();
				}
				if (!errorDetails.signature) {
					errorDetails.signature = Function.getInvocationSignature(arguments);
				}
				throw new ImplementationNotFound(errorDetails);
			};
		};
	}
);
<commit_msg>adding to meta<commit_after>define(
	[
		"../meta",
		"./invocation",
		"./implementation-not-found"
	],
	function (meta, Invocation, ImplementationNotFound) {
		"use strict";

		meta({
			"entity": "method",
			"for": "Function",
			"name": "Abstract",
			"static": true,
			"description": "A higher-order function that returns a function to serve as an abstract implementation.",
			"arguments": [{
				"name": "functionName",
				"type": "string",
				"description": "The name of the function which should overload or override the return abstract function."
			}],
			"returns": {
				"type": "function",
				"description": "Throws an ImplementationNotFound errors."
			}
		});

		Function.Abstract = function (functionName) {
			return function () {
				var invocation = Invocation.instance,
					errorDetails = {
						functionName: functionName
					};
				if (invocation) {
					errorDetails.signature = invocation.signature;
					errorDetails.nonMatchingSignatures = invocation.nonMatchingImplementationSignatures;
					invocation.reset();
				}
				if (!errorDetails.signature) {
					errorDetails.signature = Function.getInvocationSignature(arguments);
				}
				throw new ImplementationNotFound(errorDetails);
			};
		};
	}
);
<|endoftext|>


<commit_before>var ROOT_TABS;
var EDIT_MODE = false;

$().ready(function() {
    'use strict';

    $(window).blur(function() {
        window.close;
    });

    printBookmarks();
    //deleteEmptyFolder();

    $("#sort, #group, #crop").click(function(e) {
        e.preventDefault();
        toggleAllButtons();
    });

    $("#sort").click(function(e) {
        previewFunction(sort);
    });

    $("#group").click(function(e) {
        previewFunction(group);
    });

    $("#crop").click(function(e) {
        previewFunction(crop);
    });
    $("#learn").click(function(e) {
        window.open("https://github.com/koolzz/bookmark-beautifier", "_blank");
    });

    $("#search").click(function(e) {
        $("#search").select();
    });

    $("#edit").click(function(e) {
        EDIT_MODE = !EDIT_MODE;
        if (EDIT_MODE) {
            $('body').animate({
                scrollTop: 300
            }, 700);
            showEditButtons();
            $("#bookmarks, .selectedLink").removeClass('selectedLink');
            $(".panel-heading").css("background-color", "#CF995F");
        } else {
            $('body').animate({
                scrollTop: 1
            }, 700);
            hideEditButtons();
            showFolderChildren(false);
            $(".panel-heading").css("background-color", "#009688");
        }
    });

    $('#add-folder').click(function(e) {
        if ($(".search").is(":visible")) {
            $(".search").slideUp(400);
        } else {
            showSearchLine();
        }
    });

    $("#search").keyup(function() {
        if (EDIT_MODE) {
            $(this).keypress(function(e) {
                if (e.which == 13) {
                    if ($(this).val().trim().length != 0) {
                        addNewButton($(this).val().trim());
                        $("#search").val('');
                    }
                }
            });

            $('#resetSearch').click(function(event) {
                if ($(event.target).closest("#search, #tools, #desision").length) return;
                $('#resetSearch').unbind("click");
                $("#search").val('');
                event.stopPropagation();
            });
        } else {
            if ($("#sort").hasClass("disabled"))
                return;
            $('#resetSearch').click(function(event) {
                if ($(event.target).closest("#search, #tools, #desision").length) return;
                printBookmarks();
                $('#resetSearch').unbind("click");
                $("#search").val('');
                event.stopPropagation();
            });
            if ($(this).val().trim().length === 0) {
                $("#search").val('');
                printBookmarks();
            } else {
                searchBookmark($(this).val().trim());
            }
        }

    });

    $("#bookmarks").on('click', '#bLink', function selectFunction(e) {
        if (EDIT_MODE)
            return;
        var li = $(e.currentTarget);
        if (li.hasClass("selectedLink")) {
            window.open(li[0].children[0].href, "_blank");
        } else {
            $("#bookmarks, .selectedLink").removeClass('selectedLink');
            li.addClass("selectedLink")
        }
    });

    $("#bookmarks").on('dblclick', 'li', function(e) {
        if (!EDIT_MODE)
            return;
        if ($('#bookmarks').find('.editSelectedVal').length != 0)
            return;
        var oldVal;
        var url;

        var target=$(e.target).is('a')?e.target:$(e.target)[0].children[0];

        if ($(target).is('a')){
            oldVal = $(target).html();
            url = target.href;
        } else {
            oldVal = $(this).clone().children().remove().end().text();
            return; //TODO enable renaming folders
        }
        updateVal($(target), oldVal,url);
    });
});

function sortableList() {

    $("#bookmarks ul").each(function(key, e) {
        var group = key > 0 ? "subfolders" : "mainfolder";
        Sortable.create(e, {
            group: {
                name: group,
                pull: true,
                put: true
            },
            animation: 150,
            onUpdate: function(evt) {
                var item = evt.item;
                var parent = $(item).parent();
                var href = item.children[0].href;
                var title;
                if (typeof href === 'undefined') {
                    title = $(item).contents().filter(function() {
                        return this.nodeType == 3;
                    })[0].nodeValue;
                } else {
                    var title = $(item).context.innerText;
                }
                var index = evt.newIndex < evt.oldIndex ? evt.newIndex : evt.newIndex + 1;
                chrome.bookmarks.search({
                    'url': href,
                    'title': title
                }, function(result) {
                    var folder = result[0];
                    chrome.bookmarks.move(folder.id, {
                        'parentId': folder.parentId,
                        'index': index
                    }, function() {
                        printBookmarks(true, false, true);
                    });
                });
            },
            onAdd: function(evt) {
                var item = evt.item;
                var old = evt.from;
                var parentTitle = $(item).parent().parent().contents().filter(function() {
                    return this.nodeType == 3;
                })[0].nodeValue;
                var href = item.children[0].href;
                var title;
                if (typeof href === 'undefined') {
                    title = $(item).contents().filter(function() {
                        return this.nodeType == 3;
                    })[0].nodeValue;
                } else {
                    var title = $(item).context.innerText;
                }
                var index = evt.newIndex;
                chrome.bookmarks.search({
                    'title': parentTitle
                }, function(PARENT) {
                    var id = parentTitle === "Bookmarks bar" ? '1' : parentTitle === "Other bookmarks" ? '2' : parentTitle === "Mobile bookmarks" ? '3' : PARENT[0].id;
                    chrome.bookmarks.search({
                        'url': href,
                        'title': title
                    }, function(result) {
                        var folder = result[0];
                        chrome.bookmarks.move(folder.id, {
                            'parentId': id,
                            'index': index
                        }, function() {
                            printBookmarks(true, false, true);
                        });
                    });
                });

            }
        });
    });
}

function deleteEmptyFolder(folder) {
    if (folder) {
        folder.children.forEach(function(bookmark) {
            if (typeof bookmark.url === 'undefined') {
                if (bookmark.children.length != 0) {
                    deleteEmptyFolder(bookmark);
                } else if (bookmark.id > ROOT_TABS) {
                    deleteFolder(bookmark);
                }
            }
        });
    } else {
        chrome.bookmarks.getTree(function(root) {
            root.forEach(function(folder) {
                folder.children.forEach(function(bookmark) {
                    if (typeof bookmark.url === 'undefined') {
                        if (bookmark.children.length != 0) {
                            deleteEmptyFolder(bookmark);
                        } else if (bookmark.id > ROOT_TABS) {
                            deleteFolder(bookmark);
                        }
                    }
                });
            });
        });
    }
}

function deleteFolder(bookmarkFolder) {
    chrome.bookmarks.remove(bookmarkFolder.id, function() {
        console.log(bookmarkFolder.title + " removed");
    });
}

function getHostname(url) {
    var m = url.match(/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i);
    return m ? m[0] : null;
}

function getFolderName(hostname) {
    var m = hostname.match(/:\/\/(www\.)?(.*)\./);
    return m ? m[2] : null;
}

function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

function stripPunctuation(string) {
    var punctuationless = string.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
    var finalString = punctuationless.replace(/\s{2,}/g, " ");
    return finalString;
}

function addLinksToFolder(newFolder, list, printAfter) {
    var parentId = newFolder.id;
    var name = newFolder.title;

    var length = list.length;
    $.each(list, function(key, value) {
        var subli = $("<li>")
            .text = value.title;

        chrome.bookmarks.move(String(value.id), {
            'parentId': parentId,
            'index': key
        }, function(done) {
            if (key == length - 1 && printAfter)
                printBookmarks();
        });
    });

}

function sortByName(a, b) {
    var aName = a.title.toLowerCase();
    var bName = b.title.toLowerCase();
    return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0));
}

function addBookmark(parentId, title, url) {
    chrome.bookmarks.create({
        'parentId': parentId,
        'title': title,
        'url': url
    });
}

function rename(oldTitle, url, newTitle) {
    chrome.bookmarks.search({
        'title': oldTitle?oldTitle:undefined,
        'url': url
    }, function callback(results) {
        chrome.bookmarks.update(String(results[0].id), {
            'title': newTitle
        });
    })
}

function updateVal(currentLi, oldVal, url) {
    $(currentLi).html('<input class="editSelectedVal" type="text" value="' + oldVal + '" />');
    $(".editSelectedVal").focus();
    $(".editSelectedVal").keyup(function(event) {
        if (event.keyCode == 13) {
            rename(oldVal,url, $(".editSelectedVal").val().trim());
            $(currentLi).html($(".editSelectedVal").val().trim());
        }
    });
    $(document).on("click", function(e) {
        if ($(e.target).is(".editSelectedVal")) {
            return;
        } else {
            $(".editSelectedVal").parent("a").html(oldVal);
            $(document).unbind("click");
        }
    });
}

function toggleAllButtons() {
    if ($("#sort").hasClass("disabled")) {
        $('#bookmarks').animate({
            height: 505
        }, 600);
        $(".search").slideDown(600);
        $("#decision").slideUp(500, function() {
            $("#decision").css('display', 'none');
        });
        $('body').animate({
            scrollTop: 1
        }, 700);
    } else {
        $(".search").slideUp(600);
        $('#bookmarks').animate({
            height: 475
        }, 600);
        $("#decision").slideDown(500);
        $('body').animate({
            scrollTop: 300
        }, 700);
    }
    toggleButtons(["#reject", "#apply"]);
    toggleButtons(["#sort", "#group", "#crop"]);
}

function toggleButtons(idList) {
    idList.forEach(function(id) {
        var button = $(id);
        if (button.hasClass("disabled")) {
            button.removeClass("disabled");
            button.addClass("active");
        } else {
            button.removeClass("active");
            button.addClass("disabled");
        }
    });
}

function searchBookmark(text) {
    var keys = {
        children: []
    };
    chrome.bookmarks.search(text, function(results) {
        $('#bookmarks').empty();
        results.forEach(function(result) {
            if (typeof result.url != 'undefined') {
                keys.children.push(result);
            }
        });
        $('#bookmarks').append(printBookmarkFolder(keys));
    });
}

function showEditButtons() {
    $(".search").slideUp(400, function print() {
        printBookmarks(true, true);
    });
    $("#add-folder").fadeIn(400);
    $("#trash").fadeIn(400);
    $("#search").val('');
}

function hideEditButtons() {
    $(".search").slideDown(400, function print() {
        printBookmarks(false);
    });
    $("#add-folder").fadeOut(400);
    $("#trash").fadeOut(400);
    $("#search").val('');
    $('#search').attr("placeholder", "Type bookmark name");
}

function showSearchLine() {
    $(".search").slideDown(400);
    $('#search').attr("placeholder", "New folder name");
}

function addNewButton(name) {
    chrome.bookmarks.create({
        'parentId': '1',
        'title': name
    }, function callback() {
        printBookmarks();
    });
}
<commit_msg>Fix add bookmark folder issue with drag and drop list<commit_after>var ROOT_TABS;
var EDIT_MODE = false;

$().ready(function() {
    'use strict';

    $(window).blur(function() {
        window.close;
    });

    printBookmarks();
    //deleteEmptyFolder();

    $("#sort, #group, #crop").click(function(e) {
        e.preventDefault();
        toggleAllButtons();
    });

    $("#sort").click(function(e) {
        previewFunction(sort);
    });

    $("#group").click(function(e) {
        previewFunction(group);
    });

    $("#crop").click(function(e) {
        previewFunction(crop);
    });
    $("#learn").click(function(e) {
        window.open("https://github.com/koolzz/bookmark-beautifier", "_blank");
    });

    $("#search").click(function(e) {
        $("#search").select();
    });

    $("#edit").click(function(e) {
        EDIT_MODE = !EDIT_MODE;
        if (EDIT_MODE) {
            $('body').animate({
                scrollTop: 300
            }, 700);
            showEditButtons();
            $("#bookmarks, .selectedLink").removeClass('selectedLink');
            $(".panel-heading").css("background-color", "#CF995F");
        } else {
            $('body').animate({
                scrollTop: 1
            }, 700);
            hideEditButtons();
            showFolderChildren(false);
            $(".panel-heading").css("background-color", "#009688");
        }
    });

    $('#add-folder').click(function(e) {
        if ($(".search").is(":visible")) {
            $(".search").slideUp(400);
        } else {
            showSearchLine();
        }
    });

    $("#search").keyup(function() {
        if (EDIT_MODE) {
            $(this).keypress(function(e) {
                if (e.which == 13) {
                    if ($(this).val().trim().length != 0) {
                        addNewFolder($(this).val().trim());
                        $("#search").val('');
                    }
                }
            });

            $('#resetSearch').click(function(event) {
                if ($(event.target).closest("#search, #tools, #desision").length) return;
                $('#resetSearch').unbind("click");
                $("#search").val('');
                event.stopPropagation();
            });
        } else {
            if ($("#sort").hasClass("disabled"))
                return;
            $('#resetSearch').click(function(event) {
                if ($(event.target).closest("#search, #tools, #desision").length) return;
                printBookmarks();
                $('#resetSearch').unbind("click");
                $("#search").val('');
                event.stopPropagation();
            });
            if ($(this).val().trim().length === 0) {
                $("#search").val('');
                printBookmarks();
            } else {
                searchBookmark($(this).val().trim());
            }
        }

    });

    $("#bookmarks").on('click', '#bLink', function selectFunction(e) {
        if (EDIT_MODE)
            return;
        var li = $(e.currentTarget);
        if (li.hasClass("selectedLink")) {
            window.open(li[0].children[0].href, "_blank");
        } else {
            $("#bookmarks, .selectedLink").removeClass('selectedLink');
            li.addClass("selectedLink")
        }
    });

    $("#bookmarks").on('dblclick', 'li', function(e) {
        if (!EDIT_MODE)
            return;
        if ($('#bookmarks').find('.editSelectedVal').length != 0)
            return;
        var oldVal;
        var url;

        var target=$(e.target).is('a')?e.target:$(e.target)[0].children[0];

        if ($(target).is('a')){
            oldVal = $(target).html();
            url = target.href;
        } else {
            oldVal = $(this).clone().children().remove().end().text();
            return; //TODO enable renaming folders
        }
        updateVal($(target), oldVal,url);
    });
});

function sortableList() {

    $("#bookmarks ul").each(function(key, e) {
        var group = key > 0 ? "subfolders" : "mainfolder";
        Sortable.create(e, {
            group: {
                name: group,
                pull: true,
                put: true
            },
            animation: 150,
            onUpdate: function(evt) {
                var item = evt.item;
                var parent = $(item).parent();
                var href = item.children[0].href;
                var title;
                if (typeof href === 'undefined') {
                    title = $(item).contents().filter(function() {
                        return this.nodeType == 3;
                    })[0].nodeValue;
                } else {
                    var title = $(item).context.innerText;
                }
                var index = evt.newIndex < evt.oldIndex ? evt.newIndex : evt.newIndex + 1;
                chrome.bookmarks.search({
                    'url': href,
                    'title': title
                }, function(result) {
                    var folder = result[0];
                    chrome.bookmarks.move(folder.id, {
                        'parentId': folder.parentId,
                        'index': index
                    }, function() {
                        printBookmarks(true, false, true);
                    });
                });
            },
            onAdd: function(evt) {
                var item = evt.item;
                var old = evt.from;
                var parentTitle = $(item).parent().parent().contents().filter(function() {
                    return this.nodeType == 3;
                })[0].nodeValue;
                var href = item.children[0].href;
                var title;
                if (typeof href === 'undefined') {
                    title = $(item).contents().filter(function() {
                        return this.nodeType == 3;
                    })[0].nodeValue;
                } else {
                    var title = $(item).context.innerText;
                }
                var index = evt.newIndex;
                chrome.bookmarks.search({
                    'title': parentTitle
                }, function(PARENT) {
                    var id = parentTitle === "Bookmarks bar" ? '1' : parentTitle === "Other bookmarks" ? '2' : parentTitle === "Mobile bookmarks" ? '3' : PARENT[0].id;
                    chrome.bookmarks.search({
                        'url': href,
                        'title': title
                    }, function(result) {
                        var folder = result[0];
                        chrome.bookmarks.move(folder.id, {
                            'parentId': id,
                            'index': index
                        }, function() {
                            printBookmarks(true, false, true);
                        });
                    });
                });

            }
        });
    });
}

function deleteEmptyFolder(folder) {
    if (folder) {
        folder.children.forEach(function(bookmark) {
            if (typeof bookmark.url === 'undefined') {
                if (bookmark.children.length != 0) {
                    deleteEmptyFolder(bookmark);
                } else if (bookmark.id > ROOT_TABS) {
                    deleteFolder(bookmark);
                }
            }
        });
    } else {
        chrome.bookmarks.getTree(function(root) {
            root.forEach(function(folder) {
                folder.children.forEach(function(bookmark) {
                    if (typeof bookmark.url === 'undefined') {
                        if (bookmark.children.length != 0) {
                            deleteEmptyFolder(bookmark);
                        } else if (bookmark.id > ROOT_TABS) {
                            deleteFolder(bookmark);
                        }
                    }
                });
            });
        });
    }
}

function deleteFolder(bookmarkFolder) {
    chrome.bookmarks.remove(bookmarkFolder.id, function() {
        console.log(bookmarkFolder.title + " removed");
    });
}

function getHostname(url) {
    var m = url.match(/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i);
    return m ? m[0] : null;
}

function getFolderName(hostname) {
    var m = hostname.match(/:\/\/(www\.)?(.*)\./);
    return m ? m[2] : null;
}

function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

function stripPunctuation(string) {
    var punctuationless = string.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
    var finalString = punctuationless.replace(/\s{2,}/g, " ");
    return finalString;
}

function addLinksToFolder(newFolder, list, printAfter) {
    var parentId = newFolder.id;
    var name = newFolder.title;

    var length = list.length;
    $.each(list, function(key, value) {
        var subli = $("<li>")
            .text = value.title;

        chrome.bookmarks.move(String(value.id), {
            'parentId': parentId,
            'index': key
        }, function(done) {
            if (key == length - 1 && printAfter)
                printBookmarks();
        });
    });

}

function sortByName(a, b) {
    var aName = a.title.toLowerCase();
    var bName = b.title.toLowerCase();
    return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0));
}

function addBookmark(parentId, title, url) {
    chrome.bookmarks.create({
        'parentId': parentId,
        'title': title,
        'url': url
    });
}

function rename(oldTitle, url, newTitle) {
    chrome.bookmarks.search({
        'title': oldTitle?oldTitle:undefined,
        'url': url
    }, function callback(results) {
        chrome.bookmarks.update(String(results[0].id), {
            'title': newTitle
        });
    })
}

function updateVal(currentLi, oldVal, url) {
    $(currentLi).html('<input class="editSelectedVal" type="text" value="' + oldVal + '" />');
    $(".editSelectedVal").focus();
    $(".editSelectedVal").keyup(function(event) {
        if (event.keyCode == 13) {
            rename(oldVal,url, $(".editSelectedVal").val().trim());
            $(currentLi).html($(".editSelectedVal").val().trim());
        }
    });
    $(document).on("click", function(e) {
        if ($(e.target).is(".editSelectedVal")) {
            return;
        } else {
            $(".editSelectedVal").parent("a").html(oldVal);
            $(document).unbind("click");
        }
    });
}

function toggleAllButtons() {
    if ($("#sort").hasClass("disabled")) {
        $('#bookmarks').animate({
            height: 505
        }, 600);
        $(".search").slideDown(600);
        $("#decision").slideUp(500, function() {
            $("#decision").css('display', 'none');
        });
        $('body').animate({
            scrollTop: 1
        }, 700);
    } else {
        $(".search").slideUp(600);
        $('#bookmarks').animate({
            height: 475
        }, 600);
        $("#decision").slideDown(500);
        $('body').animate({
            scrollTop: 300
        }, 700);
    }
    toggleButtons(["#reject", "#apply"]);
    toggleButtons(["#sort", "#group", "#crop"]);
}

function toggleButtons(idList) {
    idList.forEach(function(id) {
        var button = $(id);
        if (button.hasClass("disabled")) {
            button.removeClass("disabled");
            button.addClass("active");
        } else {
            button.removeClass("active");
            button.addClass("disabled");
        }
    });
}

function searchBookmark(text) {
    var keys = {
        children: []
    };
    chrome.bookmarks.search(text, function(results) {
        $('#bookmarks').empty();
        results.forEach(function(result) {
            if (typeof result.url != 'undefined') {
                keys.children.push(result);
            }
        });
        $('#bookmarks').append(printBookmarkFolder(keys));
    });
}

function showEditButtons() {
    $(".search").slideUp(400, function print() {
        printBookmarks(true, true);
    });
    $("#add-folder").fadeIn(400);
    $("#trash").fadeIn(400);
    $("#search").val('');
}

function hideEditButtons() {
    $(".search").slideDown(400, function print() {
        printBookmarks(false);
    });
    $("#add-folder").fadeOut(400);
    $("#trash").fadeOut(400);
    $("#search").val('');
    $('#search').attr("placeholder", "Type bookmark name");
}

function showSearchLine() {
    $(".search").slideDown(400);
    $('#search').attr("placeholder", "New folder name");
}

function addNewFolder(name) {
    chrome.bookmarks.create({
        'parentId': '1',
        'title': name
    }, function callback() {
        printBookmarks(true, false, true);
    });
}
<|endoftext|>


<commit_before>var dialogs = [], $dcon;

$(function() {
    $dcon = $('#modalDialogContainer');
    init();
});

/**
 * メニュー初期化
 */
function init() {
    const $service = $('#service').click(() => openKTR());
    $('#options').click(() => window.open('/html/options.html', '_blank'));

    // 認証情報があれば出社、退社を表示
    if (KTR.credential.valid()) {
        $('.inout-block').css('display', 'table');
    }

    // メニューを追加
    addMenus($service);

    // 状態による内容の更新
    KTR.status.update((status) => {
        // 出社、退社
        updateMenu(status);

        // メニュー
        addMenus($service);

        // お知らせ
        if (status.information.recent) {
            $service.text('新しいお知らせ').addClass('attention');
        }
    });

    /**
     * ログインしていたら勤務テーブルを表示する
     */
    if (KTR.credential.valid()) {
        document.querySelector('#time-table').style.display = 'block';
        // TODO: @tosite0345 リファクタリング
        KTR.service._request(
            {method: 'GET'},
            '?module=timesheet&action=browse',
            (html) => {
                console.log(workInfoTableColumns(html));
            }
        );
    }
}

/**
 * 出社時刻、退社時刻の更新
 */
function updateMenu(status) {
    if (status.code === KTR.STATUS.UNKNOWN) {
        return;
    }

    if (status.start) {
        $('#action1').text('出社 ' + status.start).removeClass('enabled').unbind('click', startWork);
    } else {
        $('#action1').addClass('enabled').click(startWork);
    }

    if (status.leave) {
        $('#action2').text('退社 ' + status.leave).removeClass('enabled').unbind('click', leaveWork);
    } else {
        $('#action2').addClass('enabled').click(leaveWork);
    }
}

/**
 * メニューを追加
 */
function addMenus($service) {
    if ($service.parent().find('.menu').length === 0) {
        KTR.menuList.get((menus) => {
            menus.forEach((menu) => {
                $(`<li class="menu enabled" data-module="${menu.module}" data-action="${menu.action}"/>`)
                    .append(`<img src="${KTR.service.url()}${menu.icon}"/>`)
                    .append(menu.title)
                    .insertBefore($service);
            });
        });

        // イベント設定
        $('.menu').click(function() {
            var $this = $(this);
            openKTR({
                module: $this.data('module'),
                action: $this.data('action')
            });
        });
    }
}

/**
 * 出社処理
 */
function startWork() {
    confirmDialog(KTR.message.get('start'), stamp.bind(null, KTR.STAMP.ON));
}

/**
 * 退社処理
 */
function leaveWork() {
    confirmDialog(KTR.message.get('leave'), stamp.bind(null, KTR.STAMP.OFF));
}

/**
 * 打刻
 */
function stamp(type) {
    KTR.service.stamp(type, updateMenu);
}

/**
 * 確認ダイアログを開く
 */
function confirmDialog(msg, callback) {
    openDialog(
        $('
').text(msg),
        $('<button/>').addClass('confirm').text('はい')  .click(closeDialog).click(callback),
        $('<button/>').addClass('confirm').text('いいえ').click(closeDialog)
    );
}

/**
 * ダイアログを開く
 */
function openDialog() {
    var dialogId = 'modalDialog' + (dialogs.length + 1);
    var $diag = $('
').hide();
    var $m = $('
').addClass('modal');
    var $d = $('
').addClass('dialog');
    for (var i = 0, max = arguments.length; i < max; i++) {
        $d.append(arguments[i]);
    }
    $diag.append($m).append($d).appendTo($dcon);
    $diag.show(100, () => {
        $d.css('top', ($m.innerHeight() - $d.innerHeight()) / 2);
    });
    dialogs.push($diag);
}

/**
 * ダイアログを閉じる
 */
function closeDialog(recursive) {
    var $diag = dialogs.pop();
    if ($diag) {
        $diag.hide(100, () => {
            $diag.empty().remove();
            if (recursive) {
                closeDialog(true);
            }
        });
    }
}

/**
 * 勤之助を開く
 */
function openKTR(param) {
    var url = KTR.service.url();
    if (typeof param === 'object') {
        url += `?module=${param.module}&action=${param.action}`;
    }

    // 認証情報がなかったらそのまま開く
    if (!KTR.credential.valid()) {
        window.open(url, '_blank');
        return;
    }

    // ログインエラーなどが発生しても勤之助を開く
    var error_bak = KTR.error;
    var _open = (arg) => {
        KTR.error = error_bak;
        if (typeof arg === 'object') {
            KTR.information.changeStatusToRead(arg);
        }
        window.open(url, '_blank');
    };
    KTR.error = _open;
    KTR.status.update(_open, true);
}

/**
 * 勤怠状況テーブルのカラム名を取得する
 */
function workInfoTableColumns (html) {
    let colPos, part, columnTags;
    const columns = [];
    if ((colPos = html.search(/所定労働
日数<\/b><\/td>/)) !== -1) {
        part = html.substring(colPos);
        columnTags = part.substr(0, part.search(/<\/tr>/)).split(/<\/td>/);
    }
    if (columnTags) {
        status.menus = [];
        columnTags.forEach((columnTag) => {
            let column = columnTag.replace(//g, '')
                .replace(/\s+/g, '')
                .replace(/
/g, '')
                .replace(//g, '')
                .replace(/<\/b>/g, '');
            if (column !== '') { columns.push(column); }
        });
    } else {
        KTR.error('項目特定エラー：Issueに連絡ください。');
    }
    return columns;
}
<commit_msg>引数を指定して集計テーブル・詳細テーブルのどちらにも対応できるようにしました<commit_after>var dialogs = [], $dcon;

$(function() {
    $dcon = $('#modalDialogContainer');
    init();
});

/**
 * メニュー初期化
 */
function init() {
    const $service = $('#service').click(() => openKTR());
    $('#options').click(() => window.open('/html/options.html', '_blank'));

    // 認証情報があれば出社、退社を表示
    if (KTR.credential.valid()) {
        $('.inout-block').css('display', 'table');
    }

    // メニューを追加
    addMenus($service);

    // 状態による内容の更新
    KTR.status.update((status) => {
        // 出社、退社
        updateMenu(status);

        // メニュー
        addMenus($service);

        // お知らせ
        if (status.information.recent) {
            $service.text('新しいお知らせ').addClass('attention');
        }
    });

    /**
     * ログインしていたら勤務テーブルを表示する
     */
    if (KTR.credential.valid()) {
        document.querySelector('#time-table').style.display = 'block';
        // TODO: @tosite0345 リファクタリング
        KTR.service._request(
            {method: 'GET'},
            '?module=timesheet&action=browse',
            (html) => {
                console.log(workTableColumns(html, '', '所定労働
日数'));
                console.log(workTableColumns(html, '', '日'));
            }
        );
    }
}

/**
 * 出社時刻、退社時刻の更新
 */
function updateMenu(status) {
    if (status.code === KTR.STATUS.UNKNOWN) {
        return;
    }

    if (status.start) {
        $('#action1').text('出社 ' + status.start).removeClass('enabled').unbind('click', startWork);
    } else {
        $('#action1').addClass('enabled').click(startWork);
    }

    if (status.leave) {
        $('#action2').text('退社 ' + status.leave).removeClass('enabled').unbind('click', leaveWork);
    } else {
        $('#action2').addClass('enabled').click(leaveWork);
    }
}

/**
 * メニューを追加
 */
function addMenus($service) {
    if ($service.parent().find('.menu').length === 0) {
        KTR.menuList.get((menus) => {
            menus.forEach((menu) => {
                $(`<li class="menu enabled" data-module="${menu.module}" data-action="${menu.action}"/>`)
                    .append(`<img src="${KTR.service.url()}${menu.icon}"/>`)
                    .append(menu.title)
                    .insertBefore($service);
            });
        });

        // イベント設定
        $('.menu').click(function() {
            var $this = $(this);
            openKTR({
                module: $this.data('module'),
                action: $this.data('action')
            });
        });
    }
}

/**
 * 出社処理
 */
function startWork() {
    confirmDialog(KTR.message.get('start'), stamp.bind(null, KTR.STAMP.ON));
}

/**
 * 退社処理
 */
function leaveWork() {
    confirmDialog(KTR.message.get('leave'), stamp.bind(null, KTR.STAMP.OFF));
}

/**
 * 打刻
 */
function stamp(type) {
    KTR.service.stamp(type, updateMenu);
}

/**
 * 確認ダイアログを開く
 */
function confirmDialog(msg, callback) {
    openDialog(
        $('
').text(msg),
        $('<button/>').addClass('confirm').text('はい')  .click(closeDialog).click(callback),
        $('<button/>').addClass('confirm').text('いいえ').click(closeDialog)
    );
}

/**
 * ダイアログを開く
 */
function openDialog() {
    var dialogId = 'modalDialog' + (dialogs.length + 1);
    var $diag = $('
').hide();
    var $m = $('
').addClass('modal');
    var $d = $('
').addClass('dialog');
    for (var i = 0, max = arguments.length; i < max; i++) {
        $d.append(arguments[i]);
    }
    $diag.append($m).append($d).appendTo($dcon);
    $diag.show(100, () => {
        $d.css('top', ($m.innerHeight() - $d.innerHeight()) / 2);
    });
    dialogs.push($diag);
}

/**
 * ダイアログを閉じる
 */
function closeDialog(recursive) {
    var $diag = dialogs.pop();
    if ($diag) {
        $diag.hide(100, () => {
            $diag.empty().remove();
            if (recursive) {
                closeDialog(true);
            }
        });
    }
}

/**
 * 勤之助を開く
 */
function openKTR(param) {
    var url = KTR.service.url();
    if (typeof param === 'object') {
        url += `?module=${param.module}&action=${param.action}`;
    }

    // 認証情報がなかったらそのまま開く
    if (!KTR.credential.valid()) {
        window.open(url, '_blank');
        return;
    }

    // ログインエラーなどが発生しても勤之助を開く
    var error_bak = KTR.error;
    var _open = (arg) => {
        KTR.error = error_bak;
        if (typeof arg === 'object') {
            KTR.information.changeStatusToRead(arg);
        }
        window.open(url, '_blank');
    };
    KTR.error = _open;
    KTR.status.update(_open, true);
}

/**
 * 勤怠状況集計テーブルのカラム名を取得する
 */
function workTableColumns (html, tag, selector) {
    let colPos, part, columnTags;
    const columns = [];
    if ((colPos = html.search(tag + selector)) !== -1) {
        part = html.substring(colPos);
        columnTags = part.substr(0, part.search(/<\/tr>/)).split(/<\/td>/);
    }
    if (columnTags) {
        status.menus = [];
        columnTags.forEach((columnTag) => {
            let column = columnTag.replace(tag, '')
                .replace(/\s+/g, '')
                .replace(/
/g, '')
                .replace(//g, '')
                .replace(/<\/b>/g, '');
            if (column !== '') { columns.push(column); }
        });
    } else {
        KTR.error('項目特定エラー：Issueに連絡ください。');
    }
    return columns;
}
<|endoftext|>


<commit_before>// Your Google Drive Spreadsheet URL
var GOOGLE_SHEET_ID = "1vmYQjQ9f6CR8Hs5JH3GGJ6F9fqWfLSW0S4dz-t2KTF4";

var FEATURE = {
  'orphans' : false,// @todo screwing things for notifications??!
  'patterns' : true,
  'notify' : true
};

/* color project cards */

var colors = {
  'names' : ['nightlyblue','developerblue','mobileblue','summitteal','geckgreen','flameyellow','marketorange','firefoxorange','dinored','bikeshedmagenta','aurorapurple'],
  'hexes' : ['#2D457E','#1EC198','#F19B2D','#DF5B74','#135E9F','#7CC260','#E66C32','#793876','#20A5D9','#F9D12F','#C95142'],
  'id' : 0,
  'getColor' : function (type){
    var color = type === 'hex' ? colors.hexes[colors.id] : colors.names[colors.id];
    colors.id += 1;
    if ( colors.id === colors.names.length ) { colors.id = 0; }
    return color;
  },
};

/* better typography */

var typography = {
  preventTextOrphans : function () {
    var textElements = document.querySelectorAll('h1,h3,li,p');
    Array.prototype.forEach.call(textElements, function(el, i){
      el.innerHTML = el.innerHTML.replace(/\s([^\s<]{0,10})\s*$/,' $1');
    });
  },
};

/* UI effects */

var fadeUpdate = {
  'projects' : document.getElementById('projectContainer'),
  'fadeOut' : function () {
    fadeUpdate.projects.classList.add('fadeUpdate');
  },
  'fadeIn' : function () {
    fadeUpdate.projects.classList.remove('fadeUpdate');
  },
  'fadeOutIn' : function () {
    fadeUpdate.fadeOut();
    setTimeout( function () {
      fadeUpdate.fadeIn();
    }, 100);
  },
};

/* search */

var search = {
  'input' : document.getElementById('searchBox'),
  'dismissButton' : document.querySelector('#search .dismiss'),
  'projectContainer' : document.getElementById('projectContainer'),
  'checkContents' : function (selector, text) {
    text = text.toLowerCase();
    var elements = document.querySelectorAll(selector);
    var results = Array.prototype.filter.call(elements, function(element){
      return RegExp(text).test(element.textContent.toLowerCase());
    });
    return results;
  },
  'getInput' : function (evt) {
    if (evt.keyCode === 27) { // escape
      search.dismiss();
      search.input.blur();
    } else if (evt.keyCode === 13) { // enter
      search.input.blur();
    } else {
      search.filter();
    }
  },
  'filter' : function () {
    search.activate();
    var query = search.input.value;
    if (query.length > 2) {
      search.projectContainer.classList.add('searching');
      search.clearPrevious();
      var results = search.checkContents('.project', query);
      if (results.length > 0) {
        results.forEach(function(item, i){
          item.classList.add('found');
        });
      } else {
        // nothing found
      }
    } else {
      search.deactivate();
    }
  },
  'activate' : function(){
    search.input.parentElement.classList.add('focus');
  },
  'deactivate' : function(){
    search.projectContainer.classList.remove('searching');
    search.input.parentElement.classList.remove('focus');
  },
  'dismiss' : function(){
    search.input.value = '';
    search.input.focus();
    search.filter();
  },
  'clearPrevious' : function () {
    var previouslyFound = document.querySelectorAll('.found');
    Array.prototype.forEach.call(previouslyFound, function(elem, i){
      elem.classList.remove('found');
    });
  },
  'init' : function () {
    search.input.onkeyup = search.getInput;
    search.dismissButton.onclick = search.dismiss;
    // @todo - add clear search icon
  },
};

/* add new project form */

var newProjectForm = {
  'formContainer' : document.getElementById('addProjectForm'),
  'projectContainer' : document.getElementById('projectContainer'),
  'toggleFormButton' : document.getElementById('toggleFormButton'),
  'getDisplayState' : function () {
    var state = newProjectForm.formContainer.style.display;
    return state;
  },
  'showForm' : function (){
    newProjectForm.formContainer.style.display = 'block';
    newProjectForm.projectContainer.style.display = 'none'; // @todo get elem within module
    newProjectForm.toggleFormButton.style.transform = 'rotate(45deg)';
  },
  'hideForm' : function (){
    newProjectForm.formContainer.style.display = 'none';
    newProjectForm.projectContainer.style.display = 'block';
    newProjectForm.toggleFormButton.style.transform = 'rotate(0deg)';
    setTimeout(function(){ PulseMaker.getData(); }, 250);
  },
  'toggleForm' : function () {
    var displayState = newProjectForm.getDisplayState();
    if (displayState === 'block') {
      newProjectForm.hideForm();
    } else {
      newProjectForm.showForm();
    }
  },
  'init' : function () {
    newProjectForm.toggleFormButton.onclick = newProjectForm.toggleForm;
  },
};

/* favorite stars */

var starred = {
  'list' : [],
  'header' : document.getElementById('starredHeader'),
  'getStarred' : function () {
    var allStarred = document.querySelectorAll('.starred');
    return allStarred;
  },
  'saveStar' : function (id) {
    starred.list.push(id);
    var starIDs = starred.list.toString();
    localStorage.setItem("pulse",starIDs);
  },
  'deleteStar' : function (id) {
    var index = starred.list.indexOf(id);
    if (index != -1) {
        starred.list.splice(index, 1);
    }
    var starIDs = starred.list.toString();
    localStorage.setItem("pulse",starIDs);
  },
  'toggle' : function (event) {
    var star = event.target;
    var project = star.parentElement;
    var status = project.classList.contains('starred');
    if (status) {
      project.classList.remove('starred');
    } else {
      project.classList.add('starred');
    }
    if (!status) {
      starred.saveStar(project.id);
    } else {
      starred.deleteStar(project.id);
    }
  },
  'loadStars' : function () {
    var starIDs = localStorage.getItem("pulse");
    if (!starIDs) { return false; }
    starred.list = starIDs.split(',');
    starred.header.classList.remove('hidden');
  },
  'showStars' : function () {
    Array.prototype.forEach.call(starred.list, function(el, i){
      var project = document.getElementById(el);
      if (project) { project.classList.add('starred'); }
    });
  },
  'addHandlers' : function () {
    var starButtons = document.querySelectorAll('.star');
    Array.prototype.forEach.call(starButtons, function(el, i){
      el.onclick = starred.toggle;
    });
  },
  'init' : function () {
    starred.addHandlers();
    starred.showStars();
  },
};

/* notifications */

var notify = {};

notify.interval = 1 * 60 * 1000;

notify.checkPermission = function() {
  var permission = false;
  if (Notification.permission === "granted") {
    console.log('permission granted');
    permission = true;
    return permission;
  } else if (Notification.permission !== 'denied') {
    console.log('permission unknown');
    // permission unknown
    permission = notify.requestPermission();
    return permission;
  } else {
    console.log('permission denied');
    return permission;
  }
};

notify.requestPermission = function() {
  var permission = false;
  Notification.requestPermission(function(result) {
      if (result === 'denied') {
        return false;
      } else if (result === 'default') {
        return false;
      } else { // accepted
        return true;
      }
  });
};

notify.create = function(notice) {
  if ("Notification" in window) {
    var permission = notify.checkPermission();
    if (permission) {
      try {
        new window.Notification('');
      } catch (e) {
        if (e.name === 'TypeError') { // dang you ambivalent android
          return false;
        }
      }
      var notification = new Notification('Mozilla Pulse', { body: notice });
    }
  }
};

notify.checkForUpdates = function(newestTimestamp,newestTitle){
  var updated = false;
  var lastProject = Number(localStorage.getItem("lastProject"));
  if (lastProject && lastProject < newestTimestamp) {
    var notification = 'Check out ' + newestTitle;
    notify.create(notification);
    updated = true;
  }
  localStorage.setItem("lastProject",newestTimestamp);
  return updated;
};

notify.init = function () {
  var getProjects = setInterval(PulseMaker.refresh, notify.interval);
};

/* utility */

var utility = {
  'findContainer' : function(elem, containerClass){
      while ((elem = elem.parentElement) && !elem.classList.contains(containerClass));
      return elem;
  },
};

/* Detailer View Handler */

function enableDetailView() {
  var showDetailsModal = function(id) {
    var $detailViewTitle = $("#detail-view-wrapper h3");
    var $detailViewContent = $("#detail-view-wrapper .content");
    var $projectSummary = $("#"+id).children(".projectSummary");
    var html =
      "[ Project ID ] " + id + "

" +
      "[ Project Name ] " + $projectSummary.find("h2").html() + "

" +
      "[ Project Creator ] " + $projectSummary.find("h3").html() + "

" +
      "[ Project Description ] " + $projectSummary.find(".description").html() + "

" +
      "[ Project Interest ] " + $projectSummary.find(".interest").html() + "

" +
      "[ Project Links ] " + $projectSummary.find(".projectLinks").html().split("").join("  ");
    toggleOverlay('on');
    $detailViewTitle.html($projectSummary.find("h2").html());
    $detailViewContent.html(html);

    // FIXME: just a quick solution to add id query param to URL
    window.history.pushState(id, "", window.location.href.split("?")[0] + "?id=" + id);
  };

  var toggleOverlay = function(onOrOff) {
    var $overlay = $("#lightbox-overlay");
    var $detailViewWrapper = $("#detail-view-wrapper");
    if ( onOrOff === 'on' ) {
      $overlay.show();
      $detailViewWrapper.show();
    }
    if ( onOrOff === 'off' ) {
      $overlay.hide();
      $detailViewWrapper.hide();
      window.history.pushState("Mozilla Network Pulse", "", window.location.href.split("?")[0]);
    }
  };

  $(".project").on('click', function() {
    showDetailsModal($(this).attr('id'));
  });
  $("#close-control").on('click', function() {
    toggleOverlay('off');
  });

  if ( window.location.href.indexOf("id=") > -1 ) {
    var queryParams = window.location.href.split("?")[1].split("&");
    var currentProjectId;
    queryParams.forEach(function(param) {
      if ( param.substr(0,3) === 'id=' ) {
        currentProjectId = param.substr(3);
      }
    });
    showDetailsModal(currentProjectId);
  }
};

/* pulse maker */

var PulseMaker = {
  'url' : "https://spreadsheets.google.com/feeds/cells/"+GOOGLE_SHEET_ID+"/1/public/values?alt=json",
  'projects' : [],
  'init': function() {
    newProjectForm.init();
    starred.loadStars();
    PulseMaker.getData(true);
    search.init();
    if (FEATURE.notify) { notify.init(); }
  },
  'getData' : function (firstRun) {
    console.log('Getting data from Google Spreadsheet.');
    $.getJSON( PulseMaker.url, function( data ) {
      // succeeded!
      PulseMaker.projects = PulseMaker.parseGoogleSheetData(data);
      console.log(PulseMaker.projects);
      PulseMaker.renderApp(firstRun);
    }).error(function() {
      console.log("Failed to fetch data from Google Spreadsheet.");
    }).complete( function() {
      // AJAX call is done (whether it was successful or failed)
      console.log("Ajax call to Google Spreadsheet has finished.");
    });
  },
  'renderApp': function(firstRun) {
    var sortedProjects = PulseMaker.sortByTimestamp(PulseMaker.projects);
    var newestTimestamp = Date.parse(sortedProjects[0].Timestamp);
    var newestTitle = sortedProjects[0].Title;
    if (FEATURE.notify) {
      var updated = notify.checkForUpdates(newestTimestamp,newestTitle);
      console.log('updated: ',updated);
    }
    if (updated || firstRun) {
      PulseMaker.clearProjectLists();
      PulseMaker.renderProjectsIntoView(sortedProjects);
    }
    document.getElementById('loading').style.display = 'none';
    PulseMaker.toggleAdditionalFeatures();
    setTimeout(function(){
      PulseMaker.dismissSplash();
    }, 250);

    // detail view handler
    enableDetailView();
  },
  'dismissSplash' : function() {
    var siteHeader = document.getElementById('siteHeader');
    siteHeader.classList.add('dismissed');
    var remove = setTimeout(function(){
      siteHeader.style.display = 'none';
    }, 500);

  },
  'sortByTimestamp' : function (data) {
    var sorted = _.orderBy( data, function(o) {
      var timestamp = Date.parse(o.Timestamp);
      return timestamp;
    }, 'desc');
    return sorted;
  },
  'renderProjectsIntoView' : function(sortedData) {
    $.each( sortedData, function( projectID, projectData ) { // @todo replace jquery
      ProjectCard.render(projectData);
    });
  },
  'refresh' : function () {
    console.log('refresh');
    PulseMaker.getData(false);
  },
  'clearProjectLists' : function () {
    fadeUpdate.fadeOut();
    document.getElementById('loading').style.display = 'block';
    var lists = document.querySelectorAll('.projectList');
    Array.prototype.forEach.call(lists, function(list, i){
      list.innerHTML = '';
    });
  },
  'toggleAdditionalFeatures' : function () {
    if (FEATURE.orphans) { typography.preventTextOrphans(); }
    fadeUpdate.fadeIn();
    starred.init();
  },
  'parseGoogleSheetData': function(driveData) {
    // Formats JSON data returned from Google Spreadsheet and formats it into
    // an array with a series of objects with key value pairs like "column-name":"value"
    var headings = {};
    var newData = {};
    var finalData = [];
    var entries = driveData.feed.entry;

    for(var i = 0; i < entries.length; i++){
      var entry = entries[i];
      var row = parseInt(entry.gs$cell.row);
      var col = parseInt(entry.gs$cell.col);
      var value = entry.content.$t;

      if(row == 1) {
        headings[col] = value;
      }

      if(row > 1) {
        if(!newData[row]) {
          newData[row] = {};
        }
        newData[row][headings[col]] = value;
      }
    }

    for(var k in newData){
      finalData.push(newData[k]);
    }

    return finalData;
  }
};

// initialize network pulse
PulseMaker.init();

<commit_msg>temp - test if event tracking works<commit_after>// Your Google Drive Spreadsheet URL
var GOOGLE_SHEET_ID = "1vmYQjQ9f6CR8Hs5JH3GGJ6F9fqWfLSW0S4dz-t2KTF4";

var FEATURE = {
  'orphans' : false,// @todo screwing things for notifications??!
  'patterns' : true,
  'notify' : true
};

/* color project cards */

var colors = {
  'names' : ['nightlyblue','developerblue','mobileblue','summitteal','geckgreen','flameyellow','marketorange','firefoxorange','dinored','bikeshedmagenta','aurorapurple'],
  'hexes' : ['#2D457E','#1EC198','#F19B2D','#DF5B74','#135E9F','#7CC260','#E66C32','#793876','#20A5D9','#F9D12F','#C95142'],
  'id' : 0,
  'getColor' : function (type){
    var color = type === 'hex' ? colors.hexes[colors.id] : colors.names[colors.id];
    colors.id += 1;
    if ( colors.id === colors.names.length ) { colors.id = 0; }
    return color;
  },
};

/* better typography */

var typography = {
  preventTextOrphans : function () {
    var textElements = document.querySelectorAll('h1,h3,li,p');
    Array.prototype.forEach.call(textElements, function(el, i){
      el.innerHTML = el.innerHTML.replace(/\s([^\s<]{0,10})\s*$/,' $1');
    });
  },
};

/* UI effects */

var fadeUpdate = {
  'projects' : document.getElementById('projectContainer'),
  'fadeOut' : function () {
    fadeUpdate.projects.classList.add('fadeUpdate');
  },
  'fadeIn' : function () {
    fadeUpdate.projects.classList.remove('fadeUpdate');
  },
  'fadeOutIn' : function () {
    fadeUpdate.fadeOut();
    setTimeout( function () {
      fadeUpdate.fadeIn();
    }, 100);
  },
};

/* search */

var search = {
  'input' : document.getElementById('searchBox'),
  'dismissButton' : document.querySelector('#search .dismiss'),
  'projectContainer' : document.getElementById('projectContainer'),
  'checkContents' : function (selector, text) {
    text = text.toLowerCase();
    var elements = document.querySelectorAll(selector);
    var results = Array.prototype.filter.call(elements, function(element){
      return RegExp(text).test(element.textContent.toLowerCase());
    });
    return results;
  },
  'getInput' : function (evt) {
    if (evt.keyCode === 27) { // escape
      search.dismiss();
      search.input.blur();
    } else if (evt.keyCode === 13) { // enter
      search.input.blur();
    } else {
      search.filter();
    }
  },
  'filter' : function () {
    search.activate();
    var query = search.input.value;
    if (query.length > 2) {
      search.projectContainer.classList.add('searching');
      search.clearPrevious();
      var results = search.checkContents('.project', query);
      if (results.length > 0) {
        results.forEach(function(item, i){
          item.classList.add('found');
        });
      } else {
        // nothing found
      }
    } else {
      search.deactivate();
    }
  },
  'activate' : function(){
    search.input.parentElement.classList.add('focus');
  },
  'deactivate' : function(){
    search.projectContainer.classList.remove('searching');
    search.input.parentElement.classList.remove('focus');
  },
  'dismiss' : function(){
    search.input.value = '';
    search.input.focus();
    search.filter();
  },
  'clearPrevious' : function () {
    var previouslyFound = document.querySelectorAll('.found');
    Array.prototype.forEach.call(previouslyFound, function(elem, i){
      elem.classList.remove('found');
    });
  },
  'init' : function () {
    search.input.onkeyup = search.getInput;
    search.dismissButton.onclick = search.dismiss;
    // @todo - add clear search icon
  },
};

/* add new project form */

var newProjectForm = {
  'formContainer' : document.getElementById('addProjectForm'),
  'projectContainer' : document.getElementById('projectContainer'),
  'toggleFormButton' : document.getElementById('toggleFormButton'),
  'getDisplayState' : function () {
    var state = newProjectForm.formContainer.style.display;
    return state;
  },
  'showForm' : function (){
    newProjectForm.formContainer.style.display = 'block';
    newProjectForm.projectContainer.style.display = 'none'; // @todo get elem within module
    newProjectForm.toggleFormButton.style.transform = 'rotate(45deg)';
  },
  'hideForm' : function (){
    newProjectForm.formContainer.style.display = 'none';
    newProjectForm.projectContainer.style.display = 'block';
    newProjectForm.toggleFormButton.style.transform = 'rotate(0deg)';
    setTimeout(function(){ PulseMaker.getData(); }, 250);
  },
  'toggleForm' : function () {
    var displayState = newProjectForm.getDisplayState();
    if (displayState === 'block') {
      newProjectForm.hideForm();
    } else {
      newProjectForm.showForm();
    }
  },
  'init' : function () {
    newProjectForm.toggleFormButton.onclick = newProjectForm.toggleForm;
  },
};

/* favorite stars */

var starred = {
  'list' : [],
  'header' : document.getElementById('starredHeader'),
  'getStarred' : function () {
    var allStarred = document.querySelectorAll('.starred');
    return allStarred;
  },
  'saveStar' : function (id) {
    starred.list.push(id);
    var starIDs = starred.list.toString();
    localStorage.setItem("pulse",starIDs);
  },
  'deleteStar' : function (id) {
    var index = starred.list.indexOf(id);
    if (index != -1) {
        starred.list.splice(index, 1);
    }
    var starIDs = starred.list.toString();
    localStorage.setItem("pulse",starIDs);
  },
  'toggle' : function (event) {
    var star = event.target;
    var project = star.parentElement;
    var status = project.classList.contains('starred');
    if (status) {
      project.classList.remove('starred');
    } else {
      project.classList.add('starred');
    }
    if (!status) {
      starred.saveStar(project.id);
    } else {
      starred.deleteStar(project.id);
    }
  },
  'loadStars' : function () {
    var starIDs = localStorage.getItem("pulse");
    if (!starIDs) { return false; }
    starred.list = starIDs.split(',');
    starred.header.classList.remove('hidden');
  },
  'showStars' : function () {
    Array.prototype.forEach.call(starred.list, function(el, i){
      var project = document.getElementById(el);
      if (project) { project.classList.add('starred'); }
    });
  },
  'addHandlers' : function () {
    var starButtons = document.querySelectorAll('.star');
    Array.prototype.forEach.call(starButtons, function(el, i){
      el.onclick = starred.toggle;
    });
  },
  'init' : function () {
    starred.addHandlers();
    starred.showStars();
  },
};

/* notifications */

var notify = {};

notify.interval = 1 * 60 * 1000;

notify.checkPermission = function() {
  var permission = false;
  if (Notification.permission === "granted") {
    console.log('permission granted');
    permission = true;
    return permission;
  } else if (Notification.permission !== 'denied') {
    console.log('permission unknown');
    // permission unknown
    permission = notify.requestPermission();
    return permission;
  } else {
    console.log('permission denied');
    return permission;
  }
};

notify.requestPermission = function() {
  var permission = false;
  Notification.requestPermission(function(result) {
      if (result === 'denied') {
        return false;
      } else if (result === 'default') {
        return false;
      } else { // accepted
        return true;
      }
  });
};

notify.create = function(notice) {
  if ("Notification" in window) {
    var permission = notify.checkPermission();
    if (permission) {
      try {
        new window.Notification('');
      } catch (e) {
        if (e.name === 'TypeError') { // dang you ambivalent android
          return false;
        }
      }
      var notification = new Notification('Mozilla Pulse', { body: notice });
    }
  }
};

notify.checkForUpdates = function(newestTimestamp,newestTitle){
  var updated = false;
  var lastProject = Number(localStorage.getItem("lastProject"));
  if (lastProject && lastProject < newestTimestamp) {
    var notification = 'Check out ' + newestTitle;
    notify.create(notification);
    updated = true;
  }
  localStorage.setItem("lastProject",newestTimestamp);
  return updated;
};

notify.init = function () {
  var getProjects = setInterval(PulseMaker.refresh, notify.interval);
};

/* utility */

var utility = {
  'findContainer' : function(elem, containerClass){
      while ((elem = elem.parentElement) && !elem.classList.contains(containerClass));
      return elem;
  },
};

/* Detailer View Handler */

function enableDetailView() {
  var showDetailsModal = function(id,trigger) {
    var $detailViewTitle = $("#detail-view-wrapper h3");
    var $detailViewContent = $("#detail-view-wrapper .content");
    var $projectSummary = $("#"+id).children(".projectSummary");
    var html =
      "[ Project ID ] " + id + "

" +
      "[ Project Name ] " + $projectSummary.find("h2").html() + "

" +
      "[ Project Creator ] " + $projectSummary.find("h3").html() + "

" +
      "[ Project Description ] " + $projectSummary.find(".description").html() + "

" +
      "[ Project Interest ] " + $projectSummary.find(".interest").html() + "

" +
      "[ Project Links ] " + $projectSummary.find(".projectLinks").html().split("").join("  ");
    toggleOverlay('on');
    $detailViewTitle.html($projectSummary.find("h2").html());
    $detailViewContent.html(html);

    // FIXME: just a quick solution to add id query param to URL
    window.history.pushState(id, "", window.location.href.split("?")[0] + "?id=" + id);

    if (trigger === 'click') {
      ga('send', {
        hitType: 'event',
        eventCategory: 'Detail View',
        eventAction: 'Clicked on Card',
        eventLabel: id
      });
    }
  };

  var toggleOverlay = function(onOrOff) {
    var $overlay = $("#lightbox-overlay");
    var $detailViewWrapper = $("#detail-view-wrapper");
    if ( onOrOff === 'on' ) {
      $overlay.show();
      $detailViewWrapper.show();
    }
    if ( onOrOff === 'off' ) {
      $overlay.hide();
      $detailViewWrapper.hide();
      window.history.pushState("Mozilla Network Pulse", "", window.location.href.split("?")[0]);
    }
  };

  $(".project").on('click', function() {
    showDetailsModal($(this).attr('id'),'click');
  });
  $("#close-control").on('click', function() {
    toggleOverlay('off');
  });

  if ( window.location.href.indexOf("id=") > -1 ) {
    var queryParams = window.location.href.split("?")[1].split("&");
    var currentProjectId;
    queryParams.forEach(function(param) {
      if ( param.substr(0,3) === 'id=' ) {
        currentProjectId = param.substr(3);
      }
    });
    showDetailsModal(currentProjectId);
  }
};

/* pulse maker */

var PulseMaker = {
  'url' : "https://spreadsheets.google.com/feeds/cells/"+GOOGLE_SHEET_ID+"/1/public/values?alt=json",
  'projects' : [],
  'init': function() {
    newProjectForm.init();
    starred.loadStars();
    PulseMaker.getData(true);
    search.init();
    if (FEATURE.notify) { notify.init(); }
  },
  'getData' : function (firstRun) {
    console.log('Getting data from Google Spreadsheet.');
    $.getJSON( PulseMaker.url, function( data ) {
      // succeeded!
      PulseMaker.projects = PulseMaker.parseGoogleSheetData(data);
      console.log(PulseMaker.projects);
      PulseMaker.renderApp(firstRun);
    }).error(function() {
      console.log("Failed to fetch data from Google Spreadsheet.");
    }).complete( function() {
      // AJAX call is done (whether it was successful or failed)
      console.log("Ajax call to Google Spreadsheet has finished.");
    });
  },
  'renderApp': function(firstRun) {
    var sortedProjects = PulseMaker.sortByTimestamp(PulseMaker.projects);
    var newestTimestamp = Date.parse(sortedProjects[0].Timestamp);
    var newestTitle = sortedProjects[0].Title;
    if (FEATURE.notify) {
      var updated = notify.checkForUpdates(newestTimestamp,newestTitle);
      console.log('updated: ',updated);
    }
    if (updated || firstRun) {
      PulseMaker.clearProjectLists();
      PulseMaker.renderProjectsIntoView(sortedProjects);
    }
    document.getElementById('loading').style.display = 'none';
    PulseMaker.toggleAdditionalFeatures();
    setTimeout(function(){
      PulseMaker.dismissSplash();
    }, 250);

    // detail view handler
    enableDetailView();
  },
  'dismissSplash' : function() {
    var siteHeader = document.getElementById('siteHeader');
    siteHeader.classList.add('dismissed');
    var remove = setTimeout(function(){
      siteHeader.style.display = 'none';
    }, 500);

  },
  'sortByTimestamp' : function (data) {
    var sorted = _.orderBy( data, function(o) {
      var timestamp = Date.parse(o.Timestamp);
      return timestamp;
    }, 'desc');
    return sorted;
  },
  'renderProjectsIntoView' : function(sortedData) {
    $.each( sortedData, function( projectID, projectData ) { // @todo replace jquery
      ProjectCard.render(projectData);
    });
  },
  'refresh' : function () {
    console.log('refresh');
    PulseMaker.getData(false);
  },
  'clearProjectLists' : function () {
    fadeUpdate.fadeOut();
    document.getElementById('loading').style.display = 'block';
    var lists = document.querySelectorAll('.projectList');
    Array.prototype.forEach.call(lists, function(list, i){
      list.innerHTML = '';
    });
  },
  'toggleAdditionalFeatures' : function () {
    if (FEATURE.orphans) { typography.preventTextOrphans(); }
    fadeUpdate.fadeIn();
    starred.init();
  },
  'parseGoogleSheetData': function(driveData) {
    // Formats JSON data returned from Google Spreadsheet and formats it into
    // an array with a series of objects with key value pairs like "column-name":"value"
    var headings = {};
    var newData = {};
    var finalData = [];
    var entries = driveData.feed.entry;

    for(var i = 0; i < entries.length; i++){
      var entry = entries[i];
      var row = parseInt(entry.gs$cell.row);
      var col = parseInt(entry.gs$cell.col);
      var value = entry.content.$t;

      if(row == 1) {
        headings[col] = value;
      }

      if(row > 1) {
        if(!newData[row]) {
          newData[row] = {};
        }
        newData[row][headings[col]] = value;
      }
    }

    for(var k in newData){
      finalData.push(newData[k]);
    }

    return finalData;
  }
};

// initialize network pulse
PulseMaker.init();

<|endoftext|>


<commit_before>// @flow
import moment from 'moment-timezone'
export {moment}

export const dayMoment = (time: string, format: ?string = 'ddd h:mma') =>
  moment.tz(time, format, false, 'America/Winnipeg')
export const hourMoment = (time: string) =>
  moment.tz(time, 'h:mma', false, 'America/Winnipeg')
<commit_msg>add plainMoment helper for taking a format string<commit_after>// @flow
import moment from 'moment-timezone'
export {moment}

export const dayMoment = (time: string, format: ?string = 'ddd h:mma') =>
  moment.tz(time, format, false, 'America/Winnipeg')
export const hourMoment = (time: string) =>
  moment.tz(time, 'h:mma', false, 'America/Winnipeg')
export const plainMoment = (time: string, format: string) =>
  moment.tz(time, format, false, 'America/Winnipeg')
<|endoftext|>


<commit_before>(function($, Fleeting){
    $(function(){
	var search = window.location.search.slice(1).split("=");
	var evaporate = 5000;
	var index = search.indexOf('evaporate')
	if (index !== -1 && search[index + 1]) {
	    evaporate = parseInt(search[index + 1]) || evaporate;
	}

	console.log(evaporate);

        var view = new Fleeting.CharactersView({
            el : $("body"),
            strategy : function(){
                this.hidden(true);
            },
            evaporateTime : evaporate
        });

        (function loop(){
            window.setTimeout(loop, 1000);
            view.tick();
        })();
    });
})(jQuery, Fleeting);
<commit_msg>Please jslint<commit_after>(function($, Fleeting){
    $(function(){
        var search = window.location.search.slice(1).split("=");
        var evaporate = 5000;
        var index = search.indexOf('evaporate');
        if (index !== -1 && search[index + 1]) {
            evaporate = parseInt(search[index + 1], 10) || evaporate;
        }

        console.log(evaporate);

        var view = new Fleeting.CharactersView({
            el : $("body"),
            strategy : function(){
                this.hidden(true);
            },
            evaporateTime : evaporate
        });

        (function loop(){
            window.setTimeout(loop, 1000);
            view.tick();
        })();
    });
})(jQuery, Fleeting);
<|endoftext|>


<commit_before>function play_round(){
    document.getElementById('number-first').innerHTML = Math.floor(Math.random() * 10);
    document.getElementById('number-second').innerHTML = Math.floor(Math.random() * 10);
    document.getElementById('number-third').innerHTML = Math.floor(Math.random() * 10);

    // If all numbers match...
    if(document.getElementById('number-first').innerHTML == document.getElementById('number-second').innerHTML
      && document.getElementById('number-second').innerHTML == document.getElementById('number-third').innerHTML){
        document.getElementById('result').innerHTML =
          'Three Match! +'
          + (parseInt(document.getElementById('number-first').innerHTML) * 2)
          + ' coins!';

        // ...give player twice as many coins as the numbers that matched.
        coins += parseInt(document.getElementById('number-first').innerHTML) * 2;

    // If first number matches either of the other two numbers...
    }else if(document.getElementById('number-first').innerHTML == document.getElementById('number-second').innerHTML
      || document.getElementById('number-first').innerHTML == document.getElementById('number-third').innerHTML){
        document.getElementById('result').innerHTML =
          'Two Match. +'
          + document.getElementById('number-first').innerHTML
          + ' coins.';

        // ...give player as many coins as the first number.
        coins += parseInt(document.getElementById('number-first').innerHTML);

    // If the second and third numbers match...
    }else if(document.getElementById('number-second').innerHTML == document.getElementById('number-third').innerHTML){
        document.getElementById('result').innerHTML =
          'Two Match. +'
          + document.getElementById('number-second').innerHTML
          + ' coins.';

        // ...give player as many coins as second number.
        coins += parseInt(document.getElementById('number-second').innerHTML);

    // If no numbers match...
    }else{
        document.getElementById('result').innerHTML = 'No Match... -2 coins...';

        // ...take away two coins from player.
        coins -= 2;
    }

    // Update remaining coins.
    document.getElementById('coins').innerHTML = coins;
}

function reset(){
    if(!window.confirm('Reset coins?')){
        return;
    }

    coins = 100;
    document.getElementById('coins').innerHTML = coins;
    document.getElementById('number-first').innerHTML = '';
    document.getElementById('number-second').innerHTML = '';
    document.getElementById('number-third').innerHTML = '';
    document.getElementById('result').innerHTML = '';
}

var coins = 100;

document.getElementById('coins').innerHTML = coins;

window.onkeydown = function(e){
    var key = e.keyCode || e.which;

    // S: play a round.
    if(key == 83){
        play_round();
    }
};
<commit_msg>moved initial setup to window.onload<commit_after>function play_round(){
    document.getElementById('number-first').innerHTML = Math.floor(Math.random() * 10);
    document.getElementById('number-second').innerHTML = Math.floor(Math.random() * 10);
    document.getElementById('number-third').innerHTML = Math.floor(Math.random() * 10);

    // If all numbers match...
    if(document.getElementById('number-first').innerHTML == document.getElementById('number-second').innerHTML
      && document.getElementById('number-second').innerHTML == document.getElementById('number-third').innerHTML){
        document.getElementById('result').innerHTML =
          'Three Match! +'
          + (parseInt(document.getElementById('number-first').innerHTML) * 2)
          + ' coins!';

        // ...give player twice as many coins as the numbers that matched.
        coins += parseInt(document.getElementById('number-first').innerHTML) * 2;

    // If first number matches either of the other two numbers...
    }else if(document.getElementById('number-first').innerHTML == document.getElementById('number-second').innerHTML
      || document.getElementById('number-first').innerHTML == document.getElementById('number-third').innerHTML){
        document.getElementById('result').innerHTML =
          'Two Match. +'
          + document.getElementById('number-first').innerHTML
          + ' coins.';

        // ...give player as many coins as the first number.
        coins += parseInt(document.getElementById('number-first').innerHTML);

    // If the second and third numbers match...
    }else if(document.getElementById('number-second').innerHTML == document.getElementById('number-third').innerHTML){
        document.getElementById('result').innerHTML =
          'Two Match. +'
          + document.getElementById('number-second').innerHTML
          + ' coins.';

        // ...give player as many coins as second number.
        coins += parseInt(document.getElementById('number-second').innerHTML);

    // If no numbers match...
    }else{
        document.getElementById('result').innerHTML = 'No Match... -2 coins...';

        // ...take away two coins from player.
        coins -= 2;
    }

    // Update remaining coins.
    document.getElementById('coins').innerHTML = coins;
}

function reset(){
    if(!window.confirm('Reset coins?')){
        return;
    }

    coins = 100;
    document.getElementById('coins').innerHTML = coins;
    document.getElementById('number-first').innerHTML = '';
    document.getElementById('number-second').innerHTML = '';
    document.getElementById('number-third').innerHTML = '';
    document.getElementById('result').innerHTML = '';
}

var coins = 100;

window.onkeydown = function(e){
    var key = e.keyCode || e.which;

    // S: play a round.
    if(key == 83){
        play_round();
    }
};

window.onload = function(e){
    document.getElementById('coins').innerHTML = coins;
};
<|endoftext|>