<commit_before>// JavaScript implementation of ScrollSpy
// finds toc and automatically sorts by main list items as parents and nested list items as children

var toc = document.getElementById("toc");
if (toc !== null) { // checks to see if table of contents exists in page
    toc.classList.add("on");
    var topPadding = 12; // amount of space above header to start noticing a section
    var navBar = document.getElementById("topbar").offsetHeight;
    var tocEl = toc.nextElementSibling.getElementsByTagName("li"); // table of contents list
    var sections = toc.nextElementSibling.getElementsByTagName("a"); // table of contents links
    sections = Array.prototype.slice.call(sections);
    var sectionsLen = sections.length;
    var parentIndex;
    var parentTag = sections[0].getAttribute("href") == "#" ? "H1" : document.getElementById(sections[0].getAttribute("href").substring(1)).nodeName;
    for (var i = 0; i < sectionsLen; i++) {
        // goes through links and creates a 2d array with:
        // [element, offset from top, group]
        var element = sections[i].getAttribute("href") == "#" ? document.getElementById("content").firstElementChild : document.getElementById(sections[i].getAttribute("href").substring(1));
        if (element.nodeName == parentTag) {
            parentIndex = i;
        }
        sections[i] = [element, element.offsetTop - navBar - topPadding, parentIndex];
    }
    var active = 0;
    tocEl[0].classList.toggle("active");
    var sublist;
    var sublistPos = 0;
    var sublistChildren = 0;
    var locked = false;
    var runOnScroll =  function(e) {
        if (locked) return; // if still scrolling, do not run
        locked = true;
        var pos = 0;

        // get current active element
        for (var i = 0; i < sectionsLen; i++) {
            if (window.scrollY > sections[i][1]) {
                pos = i;
            } else {
                break;
            }
        }

        if (active != pos) { // change in active element
            tocEl[active].classList.remove('active');
            active = pos;
            tocEl[active].classList.add('active');
            if (sublist !== null) { // currently in a sublist
                sublistPos = active - sublist;
                if (sublistPos > sublistChildren || sublistPos < 1) {
                    // the position in the sublist is out of range so the sublist has been exited
                    tocEl[sublist].classList.toggle('list');
                    sublist = null;
                    sublistPos = sublistChildren = 0;
                }
            }

            if (tocEl[active].children[1] !== null && tocEl[active].children[1].nodeName == "UL") {
                // this list item has a nested list so a sublist has been entered
                sublist = active;
                sublistChildren = tocEl[active].children[1].childElementCount;
                tocEl[sublist].classList.toggle('list');
            } else if (sections[active][0].nodeName != parentTag) {
                // the current item is not of the header type of the parent items,
                // so it is a sublist item and a sublist has been entered
                sublist = sections[active][2];
                tocEl[sublist].classList.add('list');
                sublistChildren = tocEl[sublist].children[1].childElementCount;
            }
        }
        locked = false;
    }

    window.addEventListener("scroll", runOnScroll);
}
<commit_msg>Fix if statement which treated null and undefined as two different values<commit_after>// JavaScript implementation of ScrollSpy
// finds toc and automatically sorts by main list items as parents and nested list items as children

var toc = document.getElementById("toc");
if (toc !== null) { // checks to see if table of contents exists in page
    toc.classList.add("on");
    var topPadding = 12; // amount of space above header to start noticing a section
    var navBar = document.getElementById("topbar").offsetHeight;
    var tocEl = toc.nextElementSibling.getElementsByTagName("li"); // table of contents list
    var sections = toc.nextElementSibling.getElementsByTagName("a"); // table of contents links
    sections = Array.prototype.slice.call(sections);
    var sectionsLen = sections.length;
    var parentIndex;
    var parentTag = sections[0].getAttribute("href") == "#" ? "H1" : document.getElementById(sections[0].getAttribute("href").substring(1)).nodeName;
    for (var i = 0; i < sectionsLen; i++) {
        // goes through links and creates a 2d array with:
        // [element, offset from top, group]
        var element = sections[i].getAttribute("href") == "#" ? document.getElementById("content").firstElementChild : document.getElementById(sections[i].getAttribute("href").substring(1));
        if (element.nodeName == parentTag) {
            parentIndex = i;
        }
        sections[i] = [element, element.offsetTop - navBar - topPadding, parentIndex];
    }
    var active = 0;
    tocEl[0].classList.toggle("active");
    var sublist;
    var sublistPos = 0;
    var sublistChildren = 0;
    var locked = false;
    var runOnScroll =  function(e) {
        if (locked) return; // if still scrolling, do not run
        locked = true;
        var pos = 0;

        // get current active element
        for (var i = 0; i < sectionsLen; i++) {
            if (window.scrollY > sections[i][1]) {
                pos = i;
            } else {
                break;
            }
        }

        if (active != pos) { // change in active element
            tocEl[active].classList.remove('active');
            active = pos;
            tocEl[active].classList.add('active');
            if (sublist !== null) { // currently in a sublist
                sublistPos = active - sublist;
                if (sublistPos > sublistChildren || sublistPos < 1) {
                    // the position in the sublist is out of range so the sublist has been exited
                    tocEl[sublist].classList.toggle('list');
                    sublist = null;
                    sublistPos = sublistChildren = 0;
                }
            }

            if (tocEl[active].children[1] != null && tocEl[active].children[1].nodeName == "UL") {
                // this list item has a nested list so a sublist has been entered
                sublist = active;
                sublistChildren = tocEl[active].children[1].childElementCount;
                tocEl[sublist].classList.toggle('list');
            } else if (sections[active][0].nodeName != parentTag) {
                // the current item is not of the header type of the parent items,
                // so it is a sublist item and a sublist has been entered
                sublist = sections[active][2];
                tocEl[sublist].classList.add('list');
                sublistChildren = tocEl[sublist].children[1].childElementCount;
            }
        }
        locked = false;
    }

    window.addEventListener("scroll", runOnScroll);
}
<|endoftext|>


<commit_before>function toggleClass() {
    var theme = document.getElementById("theme-area");
    theme.classList.toggle("active");
}
function setTheme(btn) {
    var newTheme = "cld-video-player-skin-" + btn.value;
    var oldTheme = "cld-video-player-skin-";
    if(btn.value == "dark") {
        oldTheme += "light";
    }
    else {
        oldTheme += "dark";
    }
    var vplayers = document.getElementsByClassName("cld-video-player");
    for(var i = 0; i < vplayers.length; i++) {
        vplayers[i].classList.remove(oldTheme);
        vplayers[i].classList.add(newTheme);
    }
    toggleClass();
}

window.addEventListener('scroll',checkPosition,false);

function checkPosition()
{
    var themeArea = document.getElementById("theme-area");
    if(window.scrollY > 50)
    {
        themeArea.classList.add("scrolling");
    } else {
        themeArea.classList.remove("scrolling");
    }
}

function showContentBlocks() {
    var contentBlocks = document.getElementsByClassName("content-block");
    for(var i = 0; i < contentBlocks.length; i++) {
        contentBlocks[i].classList.remove("hidden");
    }
    showProgressBar(true,"transcript");
    showProgressBar(true,"autotag");
}

function initScreen() {
    getTranscriptFile = true;
    transcriptComplete = false;
    progress = 0;
    autoTagProgress = 0;
    transcriptProgress = 0;
    transcriptFileArrivedWithData = false;
    transcriptFileArrivedEmpty = false;

}

function uploadVideo(){
	cloudinary.openUploadWidget({ cloud_name: 'demo', upload_preset: 'video_autotag_transcript_sd_lambda', sources: [ 'local', 'url'], multiple: false, max_file_size: 100000000, resource_type: 'video'},
      function(error, result) { processResponse(error, result); }, false);
}

function useVideo(vid) {
    console.log("useVideo",vid.title);
    initScreen();
    publicId = vid.title + "_autotag";
    transcript = publicId + ".transcript";
    updatePlayers(vid.title + "_sd");
    showContentBlocks();
    progress = 15;
    updateProgress();
    updateAutoPlayers();
}

function updateAutoPlayers() {
    autoTagPlayer.source(publicId);
    transcriptPlayer.source(publicId);
}

function processResponse(error, result) {
    console.log(error, result);
    initScreen();
    if(result && result[0].bytes > 0 && result[0].bytes <= 100000000)
    {
        publicId = result[0].public_id;
        transcript = publicId + ".transcript";
        updatePlayers(publicId);
	showContentBlocks();
        updateProgress();
	updateAutoPlayers();
    }
    else if(result && result[0].bytes > 100000000) {
	    showContentBlocks();
            showError("Uploaded file is too big. This demo file size limit is 100MB");
    }
    else
        showError(error);
}

function updatePlayers(pid) {
    for(var i = 0; i < players.length; i++)
        players[i].source(pid);
    var links = document.getElementsByClassName("manipulation")
    for(var j = 0; j < links.length; j++) {
            var ref = links[j].getAttribute("data-href");
            links[j].setAttribute("href",ref+pid+".mp4");
    }
}

function updateProgress() {
    progress++;
    console.log("updateProgress", progress);
    if (progress == 20)
        checkLambda();
    if(autoTagProgress < 100)
        updateAutoTagProgress()
    if(transcriptProgress < 100)
        updateTranscriptProgress()
    if (autoTagProgress < 100 || transcriptProgress < 100)
        setTimeout(updateProgress,1500);
}

function getData() {
    if(getTranscriptFile && transcriptComplete)
        getTranscript();
    else if (autoTagProgress < 100 || transcriptProgress < 100)
        checkLambda();
    else
        console.log("getData Done");
}

  function getTranscript() {
	console.log("getTranscript", transcript);
	var checkUrl = url + transcript;
    httpTranscript.open('GET', checkUrl);
	httpTranscript.send();
}

function checkLambda() {
    console.log("checkLambda", transcript);
    var checkUrl = "https://4k4smz181f.execute-api.us-east-1.amazonaws.com/Prod/" + publicId;
    httpLambda.open('GET', checkUrl);
	httpLambda.send();
}

var httpLambda = new XMLHttpRequest();
httpLambda.onreadystatechange = function() {
    if (this.readyState == 4) {
        if(this.status == 200) {
          var notify = JSON.parse(httpLambda.responseText);
          checkLambdaNotification(notify);
        }
        setTimeout(getData,4000);
    }
    else
          console.log("onreadystatechange", this.readyState, this.status);
}

var httpTranscript = new XMLHttpRequest();
httpTranscript.onreadystatechange = function() {
    if (this.readyState == 4) {
        if(this.status == 200) {
          var notify = JSON.parse(httpTranscript.responseText);
          checkTranscriptFile(notify);
        }
        setTimeout(getData,3000);
    }
    else
          console.log("onreadystatechange", this.readyState, this.status);
}

function checkLambdaNotification(notify) {
        checkTranscript(notify);
        checkTags(notify);
}

function checkTranscriptFile(notify) {
    if(transcriptComplete && getTranscriptFile && Array.isArray(notify)) {
        transcriptProgress = 99;
	getTranscriptFile = false;
	console.log("transcript arrived");
	if(notify.length > 0) {
        	showJSON("transcript",notify);
		transcriptFileArrivedWithData = true;
		console.log("transcript arrived bigger then 0");
	}
	else {
		showJSON("transcript","There are no detected words for this video");
		transcriptFileArrivedEmpty = true;
		console.log("transcript arrived empty");
	}
    }
}

function checkTranscript(notify) {
    if (notify.transcript.status == "pending") {
        console.log("transcript pending");
    }
    else if (notify.transcript.status == "complete") {
	if(transcriptFileArrivedWithData) {
		transcriptComplete = true;
        	transcriptPlayer.source(publicId,{ transformation: {overlay: "subtitles:"+transcript}}).play();
        	console.log("transcript ready");
	}
	else if(transcriptFileArrivedEmpty) {
		transcriptComplete = true;
	}
	else {
		console.log("Wait for transcript to arrive");
	}
    }
    else
    {
        getTranscriptFile = false;
        transcriptComplete = true;
        transcriptPlayer.source(publicId).play();
        transcriptProgress = 99;
        showJSON("transcript","There is no transcript for this video");
        console.log("no transcript");
    }
}

function checkTags(notify) {
    if (notify.tags.status == "pending")
        console.log("autotag pending");
    else if (notify.tags.status == "complete") {
        autoTagProgress = 99;
        showJSON("autotag",notify.tags.data);
    }
    else
        console.log("no autotag");
}

function showProgressBar(show,id) {
    var pre = document.getElementById("pre-"+id);
    var bar = document.getElementById(id+"-bar");
    if(show) {
        bar.setAttribute("style","");
        pre.setAttribute("style","display: none");
    }
    else {
        bar.setAttribute("style","display: none");
        pre.setAttribute("style","");
    }
}

function showError(error) {
    showJSON("autotag",error);
    showJSON("transcript",error);
}

function showJSON(id,notify) {
    var content = document.getElementById(id);
    showProgressBar(false,id);
    var data = JSON.stringify(notify);
    content.innerText = data;
    Prism.highlightElement(content);
}

function updateAutoTagProgress() {
    autoTagProgress++;
    var autoTaggingBar = document.getElementById("autoTaggingBar");
    autoTaggingBar.style.width = autoTagProgress + '%';
}

function updateTranscriptProgress() {
    transcriptProgress++;
    var transcriptBar = document.getElementById("transcriptBar");
    transcriptBar.style.width = transcriptProgress + '%';
}

var url = "https://res.cloudinary.com/demo/raw/upload/";
var publicId = "sample";
var transcript = "sample.transcript"
var getTranscriptFile = true;
var transcriptComplete = false;
var transcriptFileArrivedWithData = false;
var transcriptFileArrivedEmpty = false;
var progress = 0;
var autoTagProgress = 0;
var transcriptProgress = 0;

var cld = cloudinary.Cloudinary.new({ cloud_name: 'demo' });

var players = cld.videoPlayers('.demo-manipulation', {videojs: { bigPlayButton: false, controlBar: false } });

var transcriptPlayer = cld.videoPlayer('demo-transcript-player');

var autoTagPlayer = cld.videoPlayer('demo-autotag-player');

<commit_msg>Update transcode.js<commit_after>function toggleClass() {
    var theme = document.getElementById("theme-area");
    theme.classList.toggle("active");
}
function setTheme(btn) {
    var newTheme = "cld-video-player-skin-" + btn.value;
    var oldTheme = "cld-video-player-skin-";
    if(btn.value == "dark") {
        oldTheme += "light";
    }
    else {
        oldTheme += "dark";
    }
    var vplayers = document.getElementsByClassName("cld-video-player");
    for(var i = 0; i < vplayers.length; i++) {
        vplayers[i].classList.remove(oldTheme);
        vplayers[i].classList.add(newTheme);
    }
    toggleClass();
}

window.addEventListener('scroll',checkPosition,false);

function checkPosition()
{
    var themeArea = document.getElementById("theme-area");
    if(window.scrollY > 50)
    {
        themeArea.classList.add("scrolling");
    } else {
        themeArea.classList.remove("scrolling");
    }
}

function showContentBlocks() {
    var contentBlocks = document.getElementsByClassName("content-block");
    for(var i = 0; i < contentBlocks.length; i++) {
        contentBlocks[i].classList.remove("hidden");
    }
    showProgressBar(true,"transcript");
    showProgressBar(true,"autotag");
}

function initScreen() {
    getTranscriptFile = true;
    transcriptComplete = false;
    progress = 0;
    autoTagProgress = 0;
    transcriptProgress = 0;
    transcriptFileArrivedWithData = false;
    transcriptFileArrivedEmpty = false;

}

function uploadVideo(){
	cloudinary.openUploadWidget({ cloud_name: 'demo', upload_preset: 'video_autotag_transcript_sd_lambda', sources: [ 'local', 'url'], multiple: false, max_file_size: 100000000, resource_type: 'video'},
      function(error, result) { processResponse(error, result); }, false);
}

function useVideo(vid) {
    console.log("useVideo",vid.title);
    initScreen();
    publicId = vid.title + "_autotag";
    transcript = publicId + ".transcript";
    updatePlayers(vid.title + "_sd");
    showContentBlocks();
    progress = 15;
    updateProgress();
    updateAutoPlayers();
}

function updateAutoPlayers() {
    autoTagPlayer.source(publicId);
    transcriptPlayer.source(publicId);
}

function processResponse(error, result) {
    console.log(error, result);
    initScreen();
    if(result && result[0].bytes > 0 && result[0].bytes <= 100000000)
    {
        publicId = result[0].public_id;
        transcript = publicId + ".transcript";
        updatePlayers(publicId);
	showContentBlocks();
        updateProgress();
	updateAutoPlayers();
    }
    else if(result && result[0].bytes > 100000000) {
	    showContentBlocks();
            showError("Uploaded file is too big. This demo file size limit is 100MB");
    }
    else
        showError(error);
}

function updatePlayers(pid) {
    for(var i = 0; i < players.length; i++)
        players[i].source(pid);
    var links = document.getElementsByClassName("manipulation")
    for(var j = 0; j < links.length; j++) {
            var ref = links[j].getAttribute("data-href");
            links[j].setAttribute("href",ref+pid+".mp4");
    }
}

function updateProgress() {
    progress++;
    console.log("updateProgress", progress);
    if (progress == 20)
        checkLambda();
    if(autoTagProgress < 100)
        updateAutoTagProgress()
    if(transcriptProgress < 100)
        updateTranscriptProgress()
    if (autoTagProgress < 100 || transcriptProgress < 100)
        setTimeout(updateProgress,1500);
}

function getData() {
    if(getTranscriptFile && transcriptComplete)
        getTranscript();
    else if (autoTagProgress < 100 || transcriptProgress < 100)
        checkLambda();
    else
        console.log("getData Done");
}

  function getTranscript() {
	console.log("getTranscript", transcript);
	var checkUrl = url + transcript;
    httpTranscript.open('GET', checkUrl);
	httpTranscript.send();
}

function checkLambda() {
    console.log("checkLambda", transcript);
    var checkUrl = "https://4k4smz181f.execute-api.us-east-1.amazonaws.com/Prod/" + publicId;
    httpLambda.open('GET', checkUrl);
	httpLambda.send();
}

var httpLambda = new XMLHttpRequest();
httpLambda.onreadystatechange = function() {
    if (this.readyState == 4) {
        if(this.status == 200) {
          var notify = JSON.parse(httpLambda.responseText);
          checkLambdaNotification(notify);
        }
        setTimeout(getData,4000);
    }
    else
          console.log("onreadystatechange", this.readyState, this.status);
}

var httpTranscript = new XMLHttpRequest();
httpTranscript.onreadystatechange = function() {
    if (this.readyState == 4) {
        if(this.status == 200) {
          var notify = JSON.parse(httpTranscript.responseText);
          checkTranscriptFile(notify);
        }
        setTimeout(getData,3000);
    }
    else
          console.log("onreadystatechange", this.readyState, this.status);
}

function checkLambdaNotification(notify) {
        checkTranscript(notify);
        checkTags(notify);
}

function checkTranscriptFile(notify) {
    if(transcriptComplete && getTranscriptFile && Array.isArray(notify)) {
        transcriptProgress = 99;
	getTranscriptFile = false;
	console.log("transcript arrived");
	if(notify.length > 0) {
        	showJSON("transcript",notify);
		transcriptFileArrivedWithData = true;
		console.log("transcript arrived bigger then 0");
	}
	else {
		showJSON("transcript","There are no detected words for this video");
		transcriptFileArrivedEmpty = true;
		console.log("transcript arrived empty");
	}
    }
}

function checkTranscript(notify) {
    if (notify.transcript.status == "pending") {
        console.log("transcript pending");
    }
    else if (notify.transcript.status == "complete") {
	transcriptComplete = true;
	if(transcriptFileArrivedWithData) {
        	transcriptPlayer.source(publicId,{ transformation: {overlay: "subtitles:"+transcript}}).play();
        	console.log("transcript ready");
	}
	else if(transcriptFileArrivedEmpty) {
		console.log("Transcript arrived empty");
	}
	else {
		console.log("Wait for transcript to arrive");
	}
    }
    else
    {
        getTranscriptFile = false;
        transcriptComplete = true;
        transcriptPlayer.source(publicId).play();
        transcriptProgress = 99;
        showJSON("transcript","There is no transcript for this video");
        console.log("no transcript");
    }
}

function checkTags(notify) {
    if (notify.tags.status == "pending")
        console.log("autotag pending");
    else if (notify.tags.status == "complete") {
        autoTagProgress = 99;
        showJSON("autotag",notify.tags.data);
    }
    else
        console.log("no autotag");
}

function showProgressBar(show,id) {
    var pre = document.getElementById("pre-"+id);
    var bar = document.getElementById(id+"-bar");
    if(show) {
        bar.setAttribute("style","");
        pre.setAttribute("style","display: none");
    }
    else {
        bar.setAttribute("style","display: none");
        pre.setAttribute("style","");
    }
}

function showError(error) {
    showJSON("autotag",error);
    showJSON("transcript",error);
}

function showJSON(id,notify) {
    var content = document.getElementById(id);
    showProgressBar(false,id);
    var data = JSON.stringify(notify);
    content.innerText = data;
    Prism.highlightElement(content);
}

function updateAutoTagProgress() {
    autoTagProgress++;
    var autoTaggingBar = document.getElementById("autoTaggingBar");
    autoTaggingBar.style.width = autoTagProgress + '%';
}

function updateTranscriptProgress() {
    transcriptProgress++;
    var transcriptBar = document.getElementById("transcriptBar");
    transcriptBar.style.width = transcriptProgress + '%';
}

var url = "https://res.cloudinary.com/demo/raw/upload/";
var publicId = "sample";
var transcript = "sample.transcript"
var getTranscriptFile = true;
var transcriptComplete = false;
var transcriptFileArrivedWithData = false;
var transcriptFileArrivedEmpty = false;
var progress = 0;
var autoTagProgress = 0;
var transcriptProgress = 0;

var cld = cloudinary.Cloudinary.new({ cloud_name: 'demo' });

var players = cld.videoPlayers('.demo-manipulation', {videojs: { bigPlayButton: false, controlBar: false } });

var transcriptPlayer = cld.videoPlayer('demo-transcript-player');

var autoTagPlayer = cld.videoPlayer('demo-autotag-player');

<|endoftext|>


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

/**
 * @fileoverview Text input field.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.provide('Blockly.FieldTextInput');

goog.require('Blockly.Field');
goog.require('Blockly.Msg');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.userAgent');

/**
 * Class for an editable text field.
 * @param {string} text The initial content of the field.
 * @param {Function=} opt_validator An optional function that is called
 *     to validate any constraints on what the user entered.  Takes the new
 *     text as an argument and returns either the accepted text, a replacement
 *     text, or null to abort the change.
 * @extends {Blockly.Field}
 * @constructor
 */
Blockly.FieldTextInput = function(text, opt_validator) {
  Blockly.FieldTextInput.superClass_.constructor.call(this, text,
      opt_validator);
};
goog.inherits(Blockly.FieldTextInput, Blockly.Field);

/**
 * Point size of text.  Should match blocklyText's font-size in CSS.
 */
Blockly.FieldTextInput.FONTSIZE = 11;

/**
 * Mouse cursor style when over the hotspot that initiates the editor.
 */
Blockly.FieldTextInput.prototype.CURSOR = 'text';

/**
 * Allow browser to spellcheck this field.
 * @private
 */
Blockly.FieldTextInput.prototype.spellcheck_ = true;

/**
 * Close the input widget if this input is being deleted.
 */
Blockly.FieldTextInput.prototype.dispose = function() {
  Blockly.WidgetDiv.hideIfOwner(this);
  Blockly.FieldTextInput.superClass_.dispose.call(this);
};

/**
 * Set the text in this field.
 * @param {?string} text New text.
 * @override
 */
Blockly.FieldTextInput.prototype.setValue = function(text) {
  if (text === null) {
    return;  // No change if null.
  }
  if (this.sourceBlock_ && this.validator_) {
    var validated = this.validator_(text);
    // If the new text is invalid, validation returns null.
    // In this case we still want to display the illegal result.
    if (validated !== null && validated !== undefined) {
      text = validated;
    }
  }
  Blockly.Field.prototype.setValue.call(this, text);
};

/**
 * Set whether this field is spellchecked by the browser.
 * @param {boolean} check True if checked.
 */
Blockly.FieldTextInput.prototype.setSpellcheck = function(check) {
  this.spellcheck_ = check;
};

/**
 * Show the inline free-text editor on top of the text.
 * @param {boolean=} opt_quietInput True if editor should be created without
 *     focus.  Defaults to false.
 * @private
 */
Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
  this.workspace_ = this.sourceBlock_.workspace;
  var quietInput = opt_quietInput || false;
  if (!quietInput && (goog.userAgent.MOBILE || goog.userAgent.ANDROID ||
                      goog.userAgent.IPAD)) {
    // Mobile browsers have issues with in-line textareas (focus & keyboards).
    var newValue = window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_);
    if (this.sourceBlock_ && this.validator_) {
      var override = this.validator_(newValue);
      if (override !== undefined) {
        newValue = override;
      }
    }
    this.setValue(newValue);
    return;
  }

  Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_());
  var div = Blockly.WidgetDiv.DIV;
  // Create the input.
  var htmlInput = goog.dom.createDom('input', 'blocklyHtmlInput');
  htmlInput.setAttribute('spellcheck', this.spellcheck_);
  var fontSize =
      (Blockly.FieldTextInput.FONTSIZE * this.workspace_.scale) + 'pt';
  div.style.fontSize = fontSize;
  htmlInput.style.fontSize = fontSize;
  /** @type {!HTMLInputElement} */
  Blockly.FieldTextInput.htmlInput_ = htmlInput;
  div.appendChild(htmlInput);

  htmlInput.value = htmlInput.defaultValue = this.text_;
  htmlInput.oldValue_ = null;
  this.validate_();
  this.resizeEditor_();
  if (!quietInput) {
    htmlInput.focus();
    htmlInput.select();
  }

  // Bind to keydown -- trap Enter without IME and Esc to hide.
  htmlInput.onKeyDownWrapper_ =
      Blockly.bindEvent_(htmlInput, 'keydown', this, this.onHtmlInputKeyDown_);
  // Bind to keyup -- trap Enter; resize after every keystroke.
  htmlInput.onKeyUpWrapper_ =
      Blockly.bindEvent_(htmlInput, 'keyup', this, this.onHtmlInputChange_);
  // Bind to keyPress -- repeatedly resize when holding down a key.
  htmlInput.onKeyPressWrapper_ =
      Blockly.bindEvent_(htmlInput, 'keypress', this, this.onHtmlInputChange_);
  htmlInput.onWorkspaceChangeWrapper_ = this.resizeEditor_.bind(this);
  this.workspace_.addChangeListener(htmlInput.onWorkspaceChangeWrapper_);
};

/**
 * Handle key down to the editor.
 * @param {!Event} e Keyboard event.
 * @private
 */
Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) {
  var htmlInput = Blockly.FieldTextInput.htmlInput_;
  var tabKey = 9, enterKey = 13, escKey = 27;
  if (e.keyCode == enterKey) {
    Blockly.WidgetDiv.hide();
  } else if (e.keyCode == escKey) {
    htmlInput.value = htmlInput.defaultValue;
    Blockly.WidgetDiv.hide();
  } else if (e.keyCode == tabKey) {
    Blockly.WidgetDiv.hide();
    this.sourceBlock_.tab(this, !e.shiftKey);
    e.preventDefault();
  }
};

/**
 * Handle a change to the editor.
 * @param {!Event} e Keyboard event.
 * @private
 */
Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(e) {
  var htmlInput = Blockly.FieldTextInput.htmlInput_;
  // Update source block.
  var text = htmlInput.value;
  if (text !== htmlInput.oldValue_) {
    htmlInput.oldValue_ = text;
    this.setValue(text);
    this.validate_();
  } else if (goog.userAgent.WEBKIT) {
    // Cursor key.  Render the source block to show the caret moving.
    // Chrome only (version 26, OS X).
    this.sourceBlock_.render();
  }
  this.resizeEditor_();
};

/**
 * Check to see if the contents of the editor validates.
 * Style the editor accordingly.
 * @private
 */
Blockly.FieldTextInput.prototype.validate_ = function() {
  var valid = true;
  goog.asserts.assertObject(Blockly.FieldTextInput.htmlInput_);
  var htmlInput = Blockly.FieldTextInput.htmlInput_;
  if (this.sourceBlock_ && this.validator_) {
    valid = this.validator_(htmlInput.value);
  }
  if (valid === null) {
    Blockly.addClass_(htmlInput, 'blocklyInvalidInput');
  } else {
    Blockly.removeClass_(htmlInput, 'blocklyInvalidInput');
  }
};

/**
 * Resize the editor and the underlying block to fit the text.
 * @private
 */
Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
  var div = Blockly.WidgetDiv.DIV;
  var bBox = this.fieldGroup_.getBBox();
  div.style.width = bBox.width * this.workspace_.scale + 'px';
  div.style.height = bBox.height * this.workspace_.scale + 'px';
  var xy = this.getAbsoluteXY_();
  // In RTL mode block fields and LTR input fields the left edge moves,
  // whereas the right edge is fixed.  Reposition the editor.
  if (this.sourceBlock_.RTL) {
    var borderBBox = this.getScaledBBox_();
    xy.x += borderBBox.width;
    xy.x -= div.offsetWidth;
  }
  // Shift by a few pixels to line up exactly.
  xy.y += 1;
  if (goog.userAgent.GECKO && Blockly.WidgetDiv.DIV.style.top) {
    // Firefox mis-reports the location of the border by a pixel
    // once the WidgetDiv is moved into position.
    xy.x -= 1;
    xy.y -= 1;
  }
  if (goog.userAgent.WEBKIT) {
    xy.y -= 3;
  }
  div.style.left = xy.x + 'px';
  div.style.top = xy.y + 'px';
};

/**
 * Close the editor, save the results, and dispose of the editable
 * text field's elements.
 * @return {!Function} Closure to call on destruction of the WidgetDiv.
 * @private
 */
Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
  var thisField = this;
  return function() {
    var htmlInput = Blockly.FieldTextInput.htmlInput_;
    // Save the edit (if it validates).
    var text = htmlInput.value;
    if (thisField.sourceBlock_ && thisField.validator_) {
      var text1 = thisField.validator_(text);
      if (text1 === null) {
        // Invalid edit.
        text = htmlInput.defaultValue;
      } else if (text1 !== undefined) {
        // Validation function has changed the text.
        text = text1;
      }
    }
    thisField.setValue(text);
    thisField.sourceBlock_.rendered && thisField.sourceBlock_.render();
    Blockly.unbindEvent_(htmlInput.onKeyDownWrapper_);
    Blockly.unbindEvent_(htmlInput.onKeyUpWrapper_);
    Blockly.unbindEvent_(htmlInput.onKeyPressWrapper_);
    thisField.workspace_.removeChangeListener(
        htmlInput.onWorkspaceChangeWrapper_);
    Blockly.FieldTextInput.htmlInput_ = null;
    // Delete style properties.
    var style = Blockly.WidgetDiv.DIV.style;
    style.width = 'auto';
    style.height = 'auto';
    style.fontSize = '';
  };
};

/**
 * Ensure that only a number may be entered.
 * @param {string} text The user's text.
 * @return {?string} A string representing a valid number, or null if invalid.
 */
Blockly.FieldTextInput.numberValidator = function(text) {
  if (text === null) {
    return null;
  }
  text = String(text);
  // TODO: Handle cases like 'ten', '1.203,14', etc.
  // 'O' is sometimes mistaken for '0' by inexperienced users.
  text = text.replace(/O/ig, '0');
  // Strip out thousands separators.
  text = text.replace(/,/g, '');
  var n = parseFloat(text || 0);
  return isNaN(n) ? null : String(n);
};

/**
 * Ensure that only a nonnegative integer may be entered.
 * @param {string} text The user's text.
 * @return {?string} A string representing a valid int, or null if invalid.
 */
Blockly.FieldTextInput.nonnegativeIntegerValidator = function(text) {
  var n = Blockly.FieldTextInput.numberValidator(text);
  if (n) {
    n = String(Math.max(0, Math.floor(n)));
  }
  return n;
};
<commit_msg>Fix issue #406 by calling resize from the keypress handler on text inputs. (#408)<commit_after>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2012 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Text input field.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.provide('Blockly.FieldTextInput');

goog.require('Blockly.Field');
goog.require('Blockly.Msg');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.userAgent');

/**
 * Class for an editable text field.
 * @param {string} text The initial content of the field.
 * @param {Function=} opt_validator An optional function that is called
 *     to validate any constraints on what the user entered.  Takes the new
 *     text as an argument and returns either the accepted text, a replacement
 *     text, or null to abort the change.
 * @extends {Blockly.Field}
 * @constructor
 */
Blockly.FieldTextInput = function(text, opt_validator) {
  Blockly.FieldTextInput.superClass_.constructor.call(this, text,
      opt_validator);
};
goog.inherits(Blockly.FieldTextInput, Blockly.Field);

/**
 * Point size of text.  Should match blocklyText's font-size in CSS.
 */
Blockly.FieldTextInput.FONTSIZE = 11;

/**
 * Mouse cursor style when over the hotspot that initiates the editor.
 */
Blockly.FieldTextInput.prototype.CURSOR = 'text';

/**
 * Allow browser to spellcheck this field.
 * @private
 */
Blockly.FieldTextInput.prototype.spellcheck_ = true;

/**
 * Close the input widget if this input is being deleted.
 */
Blockly.FieldTextInput.prototype.dispose = function() {
  Blockly.WidgetDiv.hideIfOwner(this);
  Blockly.FieldTextInput.superClass_.dispose.call(this);
};

/**
 * Set the text in this field.
 * @param {?string} text New text.
 * @override
 */
Blockly.FieldTextInput.prototype.setValue = function(text) {
  if (text === null) {
    return;  // No change if null.
  }
  if (this.sourceBlock_ && this.validator_) {
    var validated = this.validator_(text);
    // If the new text is invalid, validation returns null.
    // In this case we still want to display the illegal result.
    if (validated !== null && validated !== undefined) {
      text = validated;
    }
  }
  Blockly.Field.prototype.setValue.call(this, text);
};

/**
 * Set whether this field is spellchecked by the browser.
 * @param {boolean} check True if checked.
 */
Blockly.FieldTextInput.prototype.setSpellcheck = function(check) {
  this.spellcheck_ = check;
};

/**
 * Show the inline free-text editor on top of the text.
 * @param {boolean=} opt_quietInput True if editor should be created without
 *     focus.  Defaults to false.
 * @private
 */
Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
  this.workspace_ = this.sourceBlock_.workspace;
  var quietInput = opt_quietInput || false;
  if (!quietInput && (goog.userAgent.MOBILE || goog.userAgent.ANDROID ||
                      goog.userAgent.IPAD)) {
    // Mobile browsers have issues with in-line textareas (focus & keyboards).
    var newValue = window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_);
    if (this.sourceBlock_ && this.validator_) {
      var override = this.validator_(newValue);
      if (override !== undefined) {
        newValue = override;
      }
    }
    this.setValue(newValue);
    return;
  }

  Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_());
  var div = Blockly.WidgetDiv.DIV;
  // Create the input.
  var htmlInput = goog.dom.createDom('input', 'blocklyHtmlInput');
  htmlInput.setAttribute('spellcheck', this.spellcheck_);
  var fontSize =
      (Blockly.FieldTextInput.FONTSIZE * this.workspace_.scale) + 'pt';
  div.style.fontSize = fontSize;
  htmlInput.style.fontSize = fontSize;
  /** @type {!HTMLInputElement} */
  Blockly.FieldTextInput.htmlInput_ = htmlInput;
  div.appendChild(htmlInput);

  htmlInput.value = htmlInput.defaultValue = this.text_;
  htmlInput.oldValue_ = null;
  this.validate_();
  this.resizeEditor_();
  if (!quietInput) {
    htmlInput.focus();
    htmlInput.select();
  }

  // Bind to keydown -- trap Enter without IME and Esc to hide.
  htmlInput.onKeyDownWrapper_ =
      Blockly.bindEvent_(htmlInput, 'keydown', this, this.onHtmlInputKeyDown_);
  // Bind to keyup -- trap Enter; resize after every keystroke.
  htmlInput.onKeyUpWrapper_ =
      Blockly.bindEvent_(htmlInput, 'keyup', this, this.onHtmlInputChange_);
  // Bind to keyPress -- repeatedly resize when holding down a key.
  htmlInput.onKeyPressWrapper_ =
      Blockly.bindEvent_(htmlInput, 'keypress', this, this.onHtmlInputChange_);
  htmlInput.onWorkspaceChangeWrapper_ = this.resizeEditor_.bind(this);
  this.workspace_.addChangeListener(htmlInput.onWorkspaceChangeWrapper_);
};

/**
 * Handle key down to the editor.
 * @param {!Event} e Keyboard event.
 * @private
 */
Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) {
  var htmlInput = Blockly.FieldTextInput.htmlInput_;
  var tabKey = 9, enterKey = 13, escKey = 27;
  if (e.keyCode == enterKey) {
    Blockly.WidgetDiv.hide();
  } else if (e.keyCode == escKey) {
    htmlInput.value = htmlInput.defaultValue;
    Blockly.WidgetDiv.hide();
  } else if (e.keyCode == tabKey) {
    Blockly.WidgetDiv.hide();
    this.sourceBlock_.tab(this, !e.shiftKey);
    e.preventDefault();
  }
};

/**
 * Handle a change to the editor.
 * @param {!Event} e Keyboard event.
 * @private
 */
Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(e) {
  var htmlInput = Blockly.FieldTextInput.htmlInput_;
  // Update source block.
  var text = htmlInput.value;
  if (text !== htmlInput.oldValue_) {
    htmlInput.oldValue_ = text;
    this.setValue(text);
    this.validate_();
  } else if (goog.userAgent.WEBKIT) {
    // Cursor key.  Render the source block to show the caret moving.
    // Chrome only (version 26, OS X).
    this.sourceBlock_.render();
  }
  this.resizeEditor_();
  Blockly.svgResize(this.sourceBlock_.workspace);
};

/**
 * Check to see if the contents of the editor validates.
 * Style the editor accordingly.
 * @private
 */
Blockly.FieldTextInput.prototype.validate_ = function() {
  var valid = true;
  goog.asserts.assertObject(Blockly.FieldTextInput.htmlInput_);
  var htmlInput = Blockly.FieldTextInput.htmlInput_;
  if (this.sourceBlock_ && this.validator_) {
    valid = this.validator_(htmlInput.value);
  }
  if (valid === null) {
    Blockly.addClass_(htmlInput, 'blocklyInvalidInput');
  } else {
    Blockly.removeClass_(htmlInput, 'blocklyInvalidInput');
  }
};

/**
 * Resize the editor and the underlying block to fit the text.
 * @private
 */
Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
  var div = Blockly.WidgetDiv.DIV;
  var bBox = this.fieldGroup_.getBBox();
  div.style.width = bBox.width * this.workspace_.scale + 'px';
  div.style.height = bBox.height * this.workspace_.scale + 'px';
  var xy = this.getAbsoluteXY_();
  // In RTL mode block fields and LTR input fields the left edge moves,
  // whereas the right edge is fixed.  Reposition the editor.
  if (this.sourceBlock_.RTL) {
    var borderBBox = this.getScaledBBox_();
    xy.x += borderBBox.width;
    xy.x -= div.offsetWidth;
  }
  // Shift by a few pixels to line up exactly.
  xy.y += 1;
  if (goog.userAgent.GECKO && Blockly.WidgetDiv.DIV.style.top) {
    // Firefox mis-reports the location of the border by a pixel
    // once the WidgetDiv is moved into position.
    xy.x -= 1;
    xy.y -= 1;
  }
  if (goog.userAgent.WEBKIT) {
    xy.y -= 3;
  }
  div.style.left = xy.x + 'px';
  div.style.top = xy.y + 'px';
};

/**
 * Close the editor, save the results, and dispose of the editable
 * text field's elements.
 * @return {!Function} Closure to call on destruction of the WidgetDiv.
 * @private
 */
Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
  var thisField = this;
  return function() {
    var htmlInput = Blockly.FieldTextInput.htmlInput_;
    // Save the edit (if it validates).
    var text = htmlInput.value;
    if (thisField.sourceBlock_ && thisField.validator_) {
      var text1 = thisField.validator_(text);
      if (text1 === null) {
        // Invalid edit.
        text = htmlInput.defaultValue;
      } else if (text1 !== undefined) {
        // Validation function has changed the text.
        text = text1;
      }
    }
    thisField.setValue(text);
    thisField.sourceBlock_.rendered && thisField.sourceBlock_.render();
    Blockly.unbindEvent_(htmlInput.onKeyDownWrapper_);
    Blockly.unbindEvent_(htmlInput.onKeyUpWrapper_);
    Blockly.unbindEvent_(htmlInput.onKeyPressWrapper_);
    thisField.workspace_.removeChangeListener(
        htmlInput.onWorkspaceChangeWrapper_);
    Blockly.FieldTextInput.htmlInput_ = null;
    // Delete style properties.
    var style = Blockly.WidgetDiv.DIV.style;
    style.width = 'auto';
    style.height = 'auto';
    style.fontSize = '';
  };
};

/**
 * Ensure that only a number may be entered.
 * @param {string} text The user's text.
 * @return {?string} A string representing a valid number, or null if invalid.
 */
Blockly.FieldTextInput.numberValidator = function(text) {
  if (text === null) {
    return null;
  }
  text = String(text);
  // TODO: Handle cases like 'ten', '1.203,14', etc.
  // 'O' is sometimes mistaken for '0' by inexperienced users.
  text = text.replace(/O/ig, '0');
  // Strip out thousands separators.
  text = text.replace(/,/g, '');
  var n = parseFloat(text || 0);
  return isNaN(n) ? null : String(n);
};

/**
 * Ensure that only a nonnegative integer may be entered.
 * @param {string} text The user's text.
 * @return {?string} A string representing a valid int, or null if invalid.
 */
Blockly.FieldTextInput.nonnegativeIntegerValidator = function(text) {
  var n = Blockly.FieldTextInput.numberValidator(text);
  if (n) {
    n = String(Math.max(0, Math.floor(n)));
  }
  return n;
};
<|endoftext|>


<commit_before>/**
 * 将TypeScript和EXML编译为JavaScript
 */
var path = require("path");
var async = require('../core/async');
var globals = require("../core/globals");
var param = require("../core/params_analyze.js");
var file = require("../core/file.js");
var sdoc = require("./save_docs");
var addExtends = require("./addExtends");

function run(dir, args, opts) {
    if (opts["--output"] == null || opts["--output"].length == 0 || opts["--output"][0] == "") {
        console.log("请设置输出api地址  egret tscdoc --output path");
        return;
    }
    var outputPath = opts["--output"][0] || "";

    var moduleArr = ["core", "res", "html5", "native", "gui", "socket", "dragonbones"];
    var tsList = [];
    for (var i = 0; i < moduleArr.length; i++) {
        tsList = tsList.concat(getModuleList(moduleArr[i]));
    }

    tsList.push("tools/lib/tools/api/StringCode.ts");

    var typeScriptCompiler = require("../tools/egret_tsc_api.js");

    var tempTime = Date.now();
    var cmd = tsList.join(" ") + " -d -t ES5 --out " + globals.addQuotes(path.join(outputPath, "a.d.ts"));
    var apiArr = typeScriptCompiler.compile(function () {
    }, cmd);

    globals.debugLog(3, (Date.now() - tempTime) / 1000);

    var tempClassArr = sdoc.screening(apiArr);
    tempClassArr = addExtends.addChildClasses(tempClassArr);
    var extendsObj = addExtends.addExtends(tempClassArr);

    file.remove(outputPath);
    addExtends.save(extendsObj, outputPath);

    file.remove("tsc_config_temp.txt");
}

function getModuleList(moduleName) {
    var egretPath = path.join(process.argv[1], "../../../");

    var modulePath = path.join(egretPath, "tools/lib/manifest", moduleName + ".json");

    var moduleConfig = JSON.parse(file.read(modulePath));

    //获取源文件地址
    var tsList = moduleConfig.file_list;
    tsList = tsList.map(function (item) {
        return globals.addQuotes(path.join(egretPath, moduleConfig.source, item));
    }).filter(function (item) {
        return item.indexOf(".js") == -1;
    });

    return tsList;
}

exports.run = run;
<commit_msg>add root path for file<commit_after>/**
 * 将TypeScript和EXML编译为JavaScript
 */
var path = require("path");
var async = require('../core/async');
var globals = require("../core/globals");
var param = require("../core/params_analyze.js");
var file = require("../core/file.js");
var sdoc = require("./save_docs");
var addExtends = require("./addExtends");

function run(dir, args, opts) {
    if (opts["--output"] == null || opts["--output"].length == 0 || opts["--output"][0] == "") {
        console.log("请设置输出api地址  egret tscdoc --output path");
        return;
    }
    var outputPath = opts["--output"][0] || "";

    var moduleArr = ["core", "res", "html5", "native", "gui", "socket", "dragonbones"];
    var tsList = [];
    for (var i = 0; i < moduleArr.length; i++) {
        tsList = tsList.concat(getModuleList(moduleArr[i]));
    }

    var egretPath = path.join(process.argv[1], "../../../");
    tsList.push(path.join(egretPath, "tools/lib/tools/api/StringCode.ts"));

    var typeScriptCompiler = require("../tools/egret_tsc_api.js");

    var tempTime = Date.now();
    var cmd = tsList.join(" ") + " -d -t ES5 --out " + globals.addQuotes(path.join(outputPath, "a.d.ts"));
    var apiArr = typeScriptCompiler.compile(function () {
    }, cmd);

    globals.debugLog(3, (Date.now() - tempTime) / 1000);

    var tempClassArr = sdoc.screening(apiArr);
    tempClassArr = addExtends.addChildClasses(tempClassArr);
    var extendsObj = addExtends.addExtends(tempClassArr);

    file.remove(outputPath);
    addExtends.save(extendsObj, outputPath);

    file.remove("tsc_config_temp.txt");
}

function getModuleList(moduleName) {
    var egretPath = path.join(process.argv[1], "../../../");

    var modulePath = path.join(egretPath, "tools/lib/manifest", moduleName + ".json");

    var moduleConfig = JSON.parse(file.read(modulePath));

    //获取源文件地址
    var tsList = moduleConfig.file_list;
    tsList = tsList.map(function (item) {
        return globals.addQuotes(path.join(egretPath, moduleConfig.source, item));
    }).filter(function (item) {
        return item.indexOf(".js") == -1;
    });

    return tsList;
}

exports.run = run;
<|endoftext|>


<commit_before>'use strict';
var chai = require( 'chai' );
// Variable to use as our "success token" in promise assertions
var SUCCESS = 'success';
// Chai-as-promised and the `expect( prom ).to.eventually.equal( SUCCESS ) is
// used to ensure that the assertions running within the promise chains are
// actually run.
chai.use( require( 'chai-as-promised' ) );
var expect = chai.expect;

var WP = require( '../../' );
var WPRequest = require( '../../lib/shared/wp-request.js' );

// Define some arrays to use ensuring the returned data is what we expect
// it to be (e.g. an array of the names from categories on the first page)
var expectedResults = {
	names: {
		page1: [
			'aciform',
			'antiquarianism',
			'arrangement',
			'asmodeus',
			'Blogroll',
			'broder',
			'buying',
			'Cat A',
			'Cat B',
			'Cat C'
		],
		page2: [
			'championship',
			'chastening',
			'Child 1',
			'Child 2',
			'Child Category 01',
			'Child Category 02',
			'Child Category 03',
			'Child Category 04',
			'Child Category 05',
			'clerkship'
		],
		pageLast: [
			'ween',
			'wellhead',
			'wellintentioned',
			'whetstone',
			'years'
		]
	}
};

// Inspecting the titles of the returned categories arrays is an easy way to
// validate that the right page of results was returned
function getNames( categories ) {
	return categories.map(function( category ) {
		return category.name;
	});
}

describe( 'integration: categories()', function() {
	var wp;

	beforeEach(function() {
		wp = new WP({
			endpoint: 'http://wpapi.loc/wp-json'
		});
	});

	it( 'can be used to retrieve a collection of category terms', function() {
		var prom = wp.categories().get().then(function( categories ) {
			expect( categories ).to.be.an( 'array' );
			expect( categories.length ).to.equal( 10 );
			return SUCCESS;
		});
		return expect( prom ).to.eventually.equal( SUCCESS );
	});

	it( 'retrieves the first 10 categories by default', function() {
		var prom = wp.categories().get().then(function( categories ) {
			expect( categories ).to.be.an( 'array' );
			expect( categories.length ).to.equal( 10 );
			return SUCCESS;
		});
		return expect( prom ).to.eventually.equal( SUCCESS );
	});

	describe( 'paging properties', function() {

		it( 'are exposed as _paging on the response array', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories ).to.have.property( '_paging' );
				expect( categories._paging ).to.be.an( 'object' );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'include the total number of categories', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories._paging ).to.have.property( 'total' );
				expect( categories._paging.total ).to.equal( '65' );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'include the total number of pages available', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories._paging ).to.have.property( 'totalPages' );
				expect( categories._paging.totalPages ).to.equal( '7' );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'provides a bound WPRequest for the next page as .next', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories._paging ).to.have.property( 'next' );
				expect( categories._paging.next ).to.be.an( 'object' );
				expect( categories._paging.next ).to.be.an.instanceOf( WPRequest );
				expect( categories._paging.next._options.endpoint ).to
					.equal( 'http://wpapi.loc/wp-json/wp/v2/categories?page=2' );
				// Get last page & ensure "next" no longer appears
				return wp.categories().page( categories._paging.totalPages ).get().then(function( categories ) {
					expect( categories._paging ).not.to.have.property( 'next' );
					expect( getNames( categories ) ).to.deep.equal( expectedResults.names.pageLast );
					return SUCCESS;
				});
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'allows access to the next page of results via .next', function() {
			var prom = wp.categories().get().then(function( categories ) {
				return categories._paging.next.get().then(function( categories ) {
					expect( categories ).to.be.an( 'array' );
					expect( categories.length ).to.equal( 10 );
					expect( getNames( categories ) ).to.deep.equal( expectedResults.names.page2 );
					return SUCCESS;
				});
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'provides a bound WPRequest for the previous page as .prev', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories._paging ).not.to.have.property( 'prev' );
				return categories._paging.next.get().then(function( categories ) {
					expect( categories._paging ).to.have.property( 'prev' );
					expect( categories._paging.prev ).to.be.an( 'object' );
					expect( categories._paging.prev ).to.be.an.instanceOf( WPRequest );
					expect( categories._paging.prev._options.endpoint ).to
						.equal( 'http://wpapi.loc/wp-json/wp/v2/categories?page=1' );
					return SUCCESS;
				});
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'allows access to the previous page of results via .prev', function() {
			var prom = wp.categories().page( 2 ).get().then(function( categories ) {
				expect( getNames( categories ) ).to.deep.equal( expectedResults.names.page2 );
				return categories._paging.prev.get().then(function( categories ) {
					expect( categories ).to.be.an( 'array' );
					expect( categories.length ).to.equal( 10 );
					expect( getNames( categories ) ).to.deep.equal( expectedResults.names.page1 );
					return SUCCESS;
				});
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

	describe( 'term()', function() {

		it( 'can be used to access an individual category term', function() {
			var selectedCategory;
			var prom = wp.categories().get().then(function( categories ) {
				// Pick one of the categories
				selectedCategory = categories[ 3 ];
				// Query for that category directly
				return wp.categories().term( selectedCategory.id );
			}).then(function( category ) {
				expect( category ).to.be.an( 'object' );
				expect( category ).to.have.property( 'id' );
				expect( category.id ).to.equal( selectedCategory.id );
				expect( category ).to.have.property( 'slug' );
				expect( category.slug ).to.equal( selectedCategory.slug );
				expect( category ).to.have.property( 'taxonomy' );
				expect( category.taxonomy ).to.equal( 'category' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( 0 );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

	describe( 'search()', function() {

		it( 'can be used to retrieve a category by slug', function() {
			var selectedCategory;
			var prom = wp.categories().get().then(function( categories ) {
				// Pick one of the categories
				selectedCategory = categories[ 3 ];
				// Search for that category by slug
				return wp.categories().search( selectedCategory.slug );
			}).then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 1 );
				return categories[ 0 ];
			}).then(function( category ) {
				expect( category ).to.be.an( 'object' );
				expect( category ).to.have.property( 'id' );
				expect( category.id ).to.equal( selectedCategory.id );
				expect( category ).to.have.property( 'slug' );
				expect( category.slug ).to.equal( selectedCategory.slug );
				expect( category ).to.have.property( 'taxonomy' );
				expect( category.taxonomy ).to.equal( 'category' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( 0 );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'returns all categories matching the provided search string', function() {
			var prom = wp.categories().search( 'parent' ).get().then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 4 );
				var slugs = categories.map(function( cat ) {
					return cat.slug;
				}).sort().join( ' ' );
				expect( slugs ).to.equal( 'foo-a-foo-parent foo-parent parent parent-category' );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'can be used to retrieve a category by slug from a set of search results', function() {
			var prom = wp.categories().search( 'parent' ).get().then(function( categories ) {
				// Iterating over response of search is the best we can do until
				// filtering for taxonomy term collections is reinstated
				for ( var i = 0; i < 4; i++ ) {
					if ( categories[ i ].slug === 'parent' ) {
						return categories[ i ];
					}
				}
			}).then(function( category ) {
				expect( category ).to.have.property( 'slug' );
				expect( category.slug ).to.equal( 'parent' );
				expect( category ).to.have.property( 'name' );
				expect( category.name ).to.equal( 'Parent' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( 0 );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

	describe( 'parent()', function() {

		it( 'can be used to retrieve direct children of a specific category', function() {
			var parentCat;
			var childCat1;
			var childCat2;
			// First, find the "parent" category
			var prom = wp.categories().search( 'parent' ).get().then(function( categories ) {
				for ( var i = 0; i < 4; i++ ) {
					if ( categories[ i ].slug === 'parent' ) {
						// Return a query for the matching category's child
						parentCat = categories[ i ];
						return wp.categories().parent( parentCat.id );
					}
				}
			}).then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 1 );
				var category = categories[ 0 ];
				expect( category ).to.have.property( 'name' );
				expect( category.name ).to.equal( 'Child 1' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( parentCat.id );
				childCat1 = category;
				// Go one level deeper
				return wp.categories().parent( childCat1.id );
			}).then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 1 );
				var category = categories[ 0 ];
				expect( category ).to.have.property( 'name' );
				expect( category.name ).to.equal( 'Child 2' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( childCat1.id );
				childCat2 = category;
				// Go one level deeper
				return wp.categories().parent( childCat2.id );
			}).then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 0 );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

});
<commit_msg>Add integration test around term collection .forPost() method<commit_after>'use strict';
var chai = require( 'chai' );
// Variable to use as our "success token" in promise assertions
var SUCCESS = 'success';
// Chai-as-promised and the `expect( prom ).to.eventually.equal( SUCCESS ) is
// used to ensure that the assertions running within the promise chains are
// actually run.
chai.use( require( 'chai-as-promised' ) );
var expect = chai.expect;
var _ = require( 'lodash' );

var WP = require( '../../' );
var WPRequest = require( '../../lib/shared/wp-request.js' );

// Define some arrays to use ensuring the returned data is what we expect
// it to be (e.g. an array of the names from categories on the first page)
var expectedResults = {
	names: {
		page1: [
			'aciform',
			'antiquarianism',
			'arrangement',
			'asmodeus',
			'Blogroll',
			'broder',
			'buying',
			'Cat A',
			'Cat B',
			'Cat C'
		],
		page2: [
			'championship',
			'chastening',
			'Child 1',
			'Child 2',
			'Child Category 01',
			'Child Category 02',
			'Child Category 03',
			'Child Category 04',
			'Child Category 05',
			'clerkship'
		],
		pageLast: [
			'ween',
			'wellhead',
			'wellintentioned',
			'whetstone',
			'years'
		]
	}
};

// Inspecting the titles of the returned categories arrays is an easy way to
// validate that the right page of results was returned
function getNames( categories ) {
	return categories.map(function( category ) {
		return category.name;
	});
}

describe( 'integration: categories()', function() {
	var wp;

	beforeEach(function() {
		wp = new WP({
			endpoint: 'http://wpapi.loc/wp-json'
		});
	});

	it( 'can be used to retrieve a collection of category terms', function() {
		var prom = wp.categories().get().then(function( categories ) {
			expect( categories ).to.be.an( 'array' );
			expect( categories.length ).to.equal( 10 );
			return SUCCESS;
		});
		return expect( prom ).to.eventually.equal( SUCCESS );
	});

	it( 'retrieves the first 10 categories by default', function() {
		var prom = wp.categories().get().then(function( categories ) {
			expect( categories ).to.be.an( 'array' );
			expect( categories.length ).to.equal( 10 );
			return SUCCESS;
		});
		return expect( prom ).to.eventually.equal( SUCCESS );
	});

	describe( 'paging properties', function() {

		it( 'are exposed as _paging on the response array', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories ).to.have.property( '_paging' );
				expect( categories._paging ).to.be.an( 'object' );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'include the total number of categories', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories._paging ).to.have.property( 'total' );
				expect( categories._paging.total ).to.equal( '65' );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'include the total number of pages available', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories._paging ).to.have.property( 'totalPages' );
				expect( categories._paging.totalPages ).to.equal( '7' );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'provides a bound WPRequest for the next page as .next', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories._paging ).to.have.property( 'next' );
				expect( categories._paging.next ).to.be.an( 'object' );
				expect( categories._paging.next ).to.be.an.instanceOf( WPRequest );
				expect( categories._paging.next._options.endpoint ).to
					.equal( 'http://wpapi.loc/wp-json/wp/v2/categories?page=2' );
				// Get last page & ensure "next" no longer appears
				return wp.categories().page( categories._paging.totalPages ).get().then(function( categories ) {
					expect( categories._paging ).not.to.have.property( 'next' );
					expect( getNames( categories ) ).to.deep.equal( expectedResults.names.pageLast );
					return SUCCESS;
				});
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'allows access to the next page of results via .next', function() {
			var prom = wp.categories().get().then(function( categories ) {
				return categories._paging.next.get().then(function( categories ) {
					expect( categories ).to.be.an( 'array' );
					expect( categories.length ).to.equal( 10 );
					expect( getNames( categories ) ).to.deep.equal( expectedResults.names.page2 );
					return SUCCESS;
				});
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'provides a bound WPRequest for the previous page as .prev', function() {
			var prom = wp.categories().get().then(function( categories ) {
				expect( categories._paging ).not.to.have.property( 'prev' );
				return categories._paging.next.get().then(function( categories ) {
					expect( categories._paging ).to.have.property( 'prev' );
					expect( categories._paging.prev ).to.be.an( 'object' );
					expect( categories._paging.prev ).to.be.an.instanceOf( WPRequest );
					expect( categories._paging.prev._options.endpoint ).to
						.equal( 'http://wpapi.loc/wp-json/wp/v2/categories?page=1' );
					return SUCCESS;
				});
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'allows access to the previous page of results via .prev', function() {
			var prom = wp.categories().page( 2 ).get().then(function( categories ) {
				expect( getNames( categories ) ).to.deep.equal( expectedResults.names.page2 );
				return categories._paging.prev.get().then(function( categories ) {
					expect( categories ).to.be.an( 'array' );
					expect( categories.length ).to.equal( 10 );
					expect( getNames( categories ) ).to.deep.equal( expectedResults.names.page1 );
					return SUCCESS;
				});
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

	describe( 'term()', function() {

		it( 'can be used to access an individual category term', function() {
			var selectedCategory;
			var prom = wp.categories().get().then(function( categories ) {
				// Pick one of the categories
				selectedCategory = categories[ 3 ];
				// Query for that category directly
				return wp.categories().term( selectedCategory.id );
			}).then(function( category ) {
				expect( category ).to.be.an( 'object' );
				expect( category ).to.have.property( 'id' );
				expect( category.id ).to.equal( selectedCategory.id );
				expect( category ).to.have.property( 'slug' );
				expect( category.slug ).to.equal( selectedCategory.slug );
				expect( category ).to.have.property( 'taxonomy' );
				expect( category.taxonomy ).to.equal( 'category' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( 0 );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

	describe( 'search()', function() {

		it( 'can be used to retrieve a category by slug', function() {
			var selectedCategory;
			var prom = wp.categories().get().then(function( categories ) {
				// Pick one of the categories
				selectedCategory = categories[ 3 ];
				// Search for that category by slug
				return wp.categories().search( selectedCategory.slug );
			}).then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 1 );
				return categories[ 0 ];
			}).then(function( category ) {
				expect( category ).to.be.an( 'object' );
				expect( category ).to.have.property( 'id' );
				expect( category.id ).to.equal( selectedCategory.id );
				expect( category ).to.have.property( 'slug' );
				expect( category.slug ).to.equal( selectedCategory.slug );
				expect( category ).to.have.property( 'taxonomy' );
				expect( category.taxonomy ).to.equal( 'category' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( 0 );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'returns all categories matching the provided search string', function() {
			var prom = wp.categories().search( 'parent' ).get().then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 4 );
				var slugs = categories.map(function( cat ) {
					return cat.slug;
				}).sort().join( ' ' );
				expect( slugs ).to.equal( 'foo-a-foo-parent foo-parent parent parent-category' );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

		it( 'can be used to retrieve a category by slug from a set of search results', function() {
			var prom = wp.categories().search( 'parent' ).get().then(function( categories ) {
				// Iterating over response of search is the best we can do until
				// filtering for taxonomy term collections is reinstated
				for ( var i = 0; i < 4; i++ ) {
					if ( categories[ i ].slug === 'parent' ) {
						return categories[ i ];
					}
				}
			}).then(function( category ) {
				expect( category ).to.have.property( 'slug' );
				expect( category.slug ).to.equal( 'parent' );
				expect( category ).to.have.property( 'name' );
				expect( category.name ).to.equal( 'Parent' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( 0 );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

	describe( 'parent()', function() {

		it( 'can be used to retrieve direct children of a specific category', function() {
			var parentCat;
			var childCat1;
			var childCat2;
			// First, find the "parent" category
			var prom = wp.categories().search( 'parent' ).get().then(function( categories ) {
				for ( var i = 0; i < 4; i++ ) {
					if ( categories[ i ].slug === 'parent' ) {
						// Return a query for the matching category's child
						parentCat = categories[ i ];
						return wp.categories().parent( parentCat.id );
					}
				}
			}).then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 1 );
				var category = categories[ 0 ];
				expect( category ).to.have.property( 'name' );
				expect( category.name ).to.equal( 'Child 1' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( parentCat.id );
				childCat1 = category;
				// Go one level deeper
				return wp.categories().parent( childCat1.id );
			}).then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 1 );
				var category = categories[ 0 ];
				expect( category ).to.have.property( 'name' );
				expect( category.name ).to.equal( 'Child 2' );
				expect( category ).to.have.property( 'parent' );
				expect( category.parent ).to.equal( childCat1.id );
				childCat2 = category;
				// Go one level deeper
				return wp.categories().parent( childCat2.id );
			}).then(function( categories ) {
				expect( categories ).to.be.an( 'array' );
				expect( categories.length ).to.equal( 0 );
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

	describe( 'forPost()', function() {

		it( 'can be used to retrieve terms for a specific post', function() {
			var postCategories;
			var prom = wp.posts().perPage( 1 ).embed().get().then(function( posts ) {
				var post = posts[ 0 ];
				// Find the categories for this post
				postCategories = _.findWhere( post._embedded['https://api.w.org/term'], function( terms ) {
					if ( terms.length && terms[ 0 ].taxonomy === 'category' ) {
						return true;
					}
				});
				var postId = post.id;
				return wp.categories().forPost( postId );
			}).then(function( categories ) {
				expect( categories.length ).to.equal( postCategories.length );
				categories.forEach(function( cat, idx ) {
					[
						'id',
						'name',
						'slug',
						'taxonomy'
					].forEach(function( prop ) {
						expect( cat[ prop ] ).to.equal( postCategories[ idx ][ prop ] );
					});
				});
				return SUCCESS;
			});
			return expect( prom ).to.eventually.equal( SUCCESS );
		});

	});

});
<|endoftext|>


<commit_before>import _ from 'lodash';
import { bindActionCreators } from 'redux';

export const createAction = (type, payload) => _.merge({ type }, { payload });

export const bindAllActionCreators = (actionCreators, dispatch) => {
  return Object.keys(actionCreators).reduce((result, key) => {
      return Object.assign({}, result, {
        [key] : bindActionCreators(actionCreators[key], dispatch)
        });
  }, {});
}
<commit_msg>Tidy up<commit_after>import { bindActionCreators } from 'redux';

export const createAction = (type, payload) => {
  return { type, payload };
};

export const bindAllActionCreators = (actionCreators, dispatch) => {
  return Object.keys(actionCreators).reduce((result, key) => {
    return Object.assign({}, result, {
      [key]: bindActionCreators(actionCreators[key], dispatch),
    });
  }, {});
};
<|endoftext|>


<commit_before>var EE = require('events').EventEmitter;
var inherits = require('inherits');

function PhrasePrompt(options) {
    if (!this instanceof PhrasePrompt) {
        return new PhrasePrompt(options);
    }
    // TODO: ick
    options = options || {};
    if (!options.scoreResult) throw new Error('missing scoreResult option');
    if (!options.generatePhrase) throw new Error('missing generatePhrase option');
    if (!options.complexity) throw new Error('missing complexity option');
    if (!options.input) throw new Error('missing input');
    if (!options.display) throw new Error('missing display');

    this.running = false;
    this.repromptDelay = options.repromptDelay || 100;
    this.scoreResult = options.scoreResult;
    this.displayTime = options.displayTime || 1000;
    this.inputTime = options.inputTime || 10000;
    this.input = options.input;
    this.displayElement = options.display;
    this.expected = '';
    this.inputing = null;
    this.generatePhrase = options.generatePhrase;
    this.complexity = options.complexity;

    this.input.on('data', this.onInput.bind(this));
    this.on('showdisplay', this.onDisplay.bind(this));
    this.on('settimeout', this.onSetTimeout.bind(this));
    this.on('showinput', this.onShowInput.bind(this));
}

inherits(PhrasePrompt, EE);

PhrasePrompt.prototype.prompt = function() {
    this.record = {
        elapsed: {},
        timeout: {}
    };
    var text = this.generatePhrase.apply(this, this.complexity.value);
    this.expected = text;
    this.display(text);
    this.setTimer();
    this.record.expected = this.expected;
    this.onInput('');
};

PhrasePrompt.prototype.display = function(text) {
    this.displayElement.innerHTML = text;
    this.input.element.value = '';
    this.input.element.size = text.length + 2;
    this.showDisplay(text);
    this.emit('display');
};

PhrasePrompt.prototype.showDisplay = function() {
    if (this.inputing !== false) {
        this.inputing = false;
        this.emit('showdisplay');
    }
};

PhrasePrompt.prototype.showInput = function() {
    this.clearTimer();
    if (this.inputing !== true) {
        this.inputing = true;
        this.emit('showinput');
        this.input.element.disabled = false;
        this.input.element.focus();
    }
    this.setTimer();
};

PhrasePrompt.prototype.setTimer = function() {
    this.clearTimer();
    if (this.inputing) {
        this.timer = setTimeout(function() {
            if (this.inputing) this.emitRecord(true);
        }.bind(this), this.inputTime);
        this.emit('settimeout', 'input', this.inputTime);
    } else {
        this.timer = setTimeout(function() {
            if (!this.inputing) this.showInput();
        }.bind(this), this.displayTime);
        this.emit('settimeout', 'display', this.displayTime);
    }
};

PhrasePrompt.prototype.clearTimer = function() {
    if (this.timer) {
        clearTimeout(this.timer);
        delete this.timer;
    }
};

PhrasePrompt.prototype.start = function() {
    if (!this.running) {
        this.running = true;
        this.prompt();
    }
};

PhrasePrompt.prototype.stop = function() {
    if (this.running) {
        this.running = false;
        this.emitRecord(true);
    }
};

PhrasePrompt.prototype.emitRecord = function(force) {
    if (this.record) {
        if (this.record.inputShownAt) {
            this.record.elapsed.input = Date.now() - this.record.inputShownAt;
        }
        this.record.forced = force;
        this.scoreResult(this.record, force);
    }
    if (force || this.record && this.record.finished) {
        if (this.record) {
            this.emit('result', this.record);
            this.record = null;
        }
        this.reprompt();
    }
};

PhrasePrompt.prototype.reprompt = function() {
    this.clearTimer();
    if (this.inputing) {
        this.input.element.disabled = true;
    }
    if (this.running) {
        setTimeout(this.prompt.bind(this), this.repromptDelay);
    }
};

PhrasePrompt.prototype.onSetTimeout = function(kind, time) {
    if (this.record) {
        this.record.timeout[kind] = time;
    }
};

PhrasePrompt.prototype.onDisplay = function() {
    if (this.record && !this.record.displayedAt) {
        this.record.displayedAt = Date.now();
    }
};

PhrasePrompt.prototype.onShowInput = function() {
    this.record.inputShownAt = Date.now();
    if (this.record.displayedAt) {
        if (!this.record.elapsed.display) {
            this.record.elapsed.display = this.record.inputShownAt - this.record.displayedAt;
        }
    }
};

PhrasePrompt.prototype.onInput = function(got, force) {
    if (this.record) this.record.got = got;
    this.emitRecord(force);
};

module.exports = PhrasePrompt;
<commit_msg>phrase_prompt: inline setTimer<commit_after>var EE = require('events').EventEmitter;
var inherits = require('inherits');

function PhrasePrompt(options) {
    if (!this instanceof PhrasePrompt) {
        return new PhrasePrompt(options);
    }
    // TODO: ick
    options = options || {};
    if (!options.scoreResult) throw new Error('missing scoreResult option');
    if (!options.generatePhrase) throw new Error('missing generatePhrase option');
    if (!options.complexity) throw new Error('missing complexity option');
    if (!options.input) throw new Error('missing input');
    if (!options.display) throw new Error('missing display');

    this.running = false;
    this.repromptDelay = options.repromptDelay || 100;
    this.scoreResult = options.scoreResult;
    this.displayTime = options.displayTime || 1000;
    this.inputTime = options.inputTime || 10000;
    this.input = options.input;
    this.displayElement = options.display;
    this.expected = '';
    this.inputing = null;
    this.generatePhrase = options.generatePhrase;
    this.complexity = options.complexity;

    this.input.on('data', this.onInput.bind(this));
    this.on('showdisplay', this.onDisplay.bind(this));
    this.on('settimeout', this.onSetTimeout.bind(this));
    this.on('showinput', this.onShowInput.bind(this));
}

inherits(PhrasePrompt, EE);

PhrasePrompt.prototype.prompt = function() {
    this.record = {
        elapsed: {},
        timeout: {}
    };
    var text = this.generatePhrase.apply(this, this.complexity.value);
    this.expected = text;
    this.display(text);
    this.clearTimer();
    this.timer = setTimeout(function() {
        if (!this.inputing) this.showInput();
    }.bind(this), this.displayTime);
    this.emit('settimeout', 'display', this.displayTime);
    this.record.expected = this.expected;
    this.onInput('');
};

PhrasePrompt.prototype.display = function(text) {
    this.displayElement.innerHTML = text;
    this.input.element.value = '';
    this.input.element.size = text.length + 2;
    this.showDisplay(text);
    this.emit('display');
};

PhrasePrompt.prototype.showDisplay = function() {
    if (this.inputing !== false) {
        this.inputing = false;
        this.emit('showdisplay');
    }
};

PhrasePrompt.prototype.showInput = function() {
    if (this.inputing !== true) {
        this.inputing = true;
        this.emit('showinput');
        this.input.element.disabled = false;
        this.input.element.focus();
    }
    this.clearTimer();
    this.timer = setTimeout(function() {
        if (this.inputing) this.emitRecord(true);
    }.bind(this), this.inputTime);
    this.emit('settimeout', 'input', this.inputTime);
};

PhrasePrompt.prototype.clearTimer = function() {
    if (this.timer) {
        clearTimeout(this.timer);
        delete this.timer;
    }
};

PhrasePrompt.prototype.start = function() {
    if (!this.running) {
        this.running = true;
        this.prompt();
    }
};

PhrasePrompt.prototype.stop = function() {
    if (this.running) {
        this.running = false;
        this.emitRecord(true);
    }
};

PhrasePrompt.prototype.emitRecord = function(force) {
    if (this.record) {
        if (this.record.inputShownAt) {
            this.record.elapsed.input = Date.now() - this.record.inputShownAt;
        }
        this.record.forced = force;
        this.scoreResult(this.record, force);
    }
    if (force || this.record && this.record.finished) {
        if (this.record) {
            this.emit('result', this.record);
            this.record = null;
        }
        this.reprompt();
    }
};

PhrasePrompt.prototype.reprompt = function() {
    this.clearTimer();
    if (this.inputing) {
        this.input.element.disabled = true;
    }
    if (this.running) {
        setTimeout(this.prompt.bind(this), this.repromptDelay);
    }
};

PhrasePrompt.prototype.onSetTimeout = function(kind, time) {
    if (this.record) {
        this.record.timeout[kind] = time;
    }
};

PhrasePrompt.prototype.onDisplay = function() {
    if (this.record && !this.record.displayedAt) {
        this.record.displayedAt = Date.now();
    }
};

PhrasePrompt.prototype.onShowInput = function() {
    this.record.inputShownAt = Date.now();
    if (this.record.displayedAt) {
        if (!this.record.elapsed.display) {
            this.record.elapsed.display = this.record.inputShownAt - this.record.displayedAt;
        }
    }
};

PhrasePrompt.prototype.onInput = function(got, force) {
    if (this.record) this.record.got = got;
    this.emitRecord(force);
};

module.exports = PhrasePrompt;
<|endoftext|>


<commit_before>const path = require('path');
const prettier = require('prettier');
const fs = require('fs');
const chokidar = require('chokidar');
const paths = require('../paths');

const PRETTIER_CONFIG_FILES = [
  '.prettierrc',
  '.prettierrc.json',
  '.prettierrc.yaml',
  '.prettierrc.yml',
  '.prettierrc.js',
  'package.json',
  'prettier.config.js',
  '.editorconfig',
].map(f => paths.map(f));

const DEFAULT_PRETTIER_OPTIONS = {
  singleQuote: true,
  trailingComma: 'all',
  printWidth: 120,
  cursorOffset: 0,
  insertFinalNewline: true,
  editorconfig: true,
};

if (!global.__REKIT_NO_WATCH) {
  const watcher = chokidar.watch(PRETTIER_CONFIG_FILES, {
    persistent: true,
    awaitWriteFinish: true,
  });

  const clearConfigCache = () => prettier.clearConfigCache();
  watcher
    .on('add', clearConfigCache)
    .on('change', clearConfigCache)
    .on('ready', clearConfigCache)
    .on('unlink', clearConfigCache)
    .on('error', clearConfigCache);
}

function format(code, file, opts = {}) {
  const filePath = path.isAbsolute(file) ? file : paths.map(file);
  if (!code) code = fs.readFileSync(filePath).toString();

  let formatted = code;
  try {
    const options = prettier.resolveConfig.sync(filePath) || {};
    const finalOptions = Object.assign(
      { filepath: filePath },
      DEFAULT_PRETTIER_OPTIONS,
      options,
      opts,
    );
    if (!finalOptions.insertFinalNewline) {
      finalOptions.rangeStart = 0;
      finalOptions.rangeEnd = code.length - 1;
    }
    formatted = prettier.formatWithCursor(code, finalOptions);
  } catch (err) {
    console.log('Failed to format code: ', err);
  }
  return formatted;
}

module.exports = format;
<commit_msg>Start watch when first format.<commit_after>const path = require('path');
const prettier = require('prettier');
const fs = require('fs');
const chokidar = require('chokidar');
const paths = require('../paths');

const PRETTIER_CONFIG_FILES = [
  '.prettierrc',
  '.prettierrc.json',
  '.prettierrc.yaml',
  '.prettierrc.yml',
  '.prettierrc.js',
  'package.json',
  'prettier.config.js',
  '.editorconfig',
].map(f => paths.map(f));

const DEFAULT_PRETTIER_OPTIONS = {
  singleQuote: true,
  trailingComma: 'all',
  printWidth: 120,
  cursorOffset: 0,
  insertFinalNewline: true,
  editorconfig: true,
};

let watcher;
function startWatch() {
  if (!global.__REKIT_NO_WATCH) {
    watcher = chokidar.watch(PRETTIER_CONFIG_FILES, {
      persistent: true,
      awaitWriteFinish: true,
    });

    const clearConfigCache = () => prettier.clearConfigCache();
    watcher.on('all', clearConfigCache);
  }
}

function format(code, file, opts = {}) {
  if (!watcher) startWatch();
  const filePath = path.isAbsolute(file) ? file : paths.map(file);
  if (!code) code = fs.readFileSync(filePath).toString();

  let formatted = code;
  try {
    const options = prettier.resolveConfig.sync(filePath) || {};
    const finalOptions = Object.assign(
      { filepath: filePath },
      DEFAULT_PRETTIER_OPTIONS,
      options,
      opts,
    );
    if (!finalOptions.insertFinalNewline) {
      finalOptions.rangeStart = 0;
      finalOptions.rangeEnd = code.length - 1;
    }
    formatted = prettier.formatWithCursor(code, finalOptions);
  } catch (err) {
    console.log('Failed to format code: ', err);
  }
  return formatted;
}

module.exports = format;
<|endoftext|>


<commit_before>/* eslint-disable no-param-reassign */

let regex; // make global as it's used by both single and multiHandler

function getOptions() {
  return new Promise((resolve) => {
    chrome.storage.sync.get(null, options => resolve(options));
  });
}

// Regex test cases here: https://regexr.com/3gv3c
function genBracketsRegex(options) {
  const genRegexStr = `(?:\\()([A-Z .,!?:"'\`\\\\/\\&+-]\\d?){${options.lowLimit},${options.upLimit}}(?:\\))`;
  regex = new RegExp(genRegexStr, 'gi');
  return regex;
}

function genTag(text) {
  const dataSafeText = text.replace(/&/g, '&').replace(/"/g, '"'); // so it doesn't break html layout
  return `<bracket-less data-bracketless="${dataSafeText}">${text}</bracket-less>`;
}

function injectTag(text, tag, target) {
  const replaceRegex = new RegExp(text.replace(/[.,!?:"'`\\/&-(+)]/g, '\\$&')); // to match exactly that text
  target.innerHTML = target.innerHTML.replace(replaceRegex, tag);
}

function singleHandler(textNode, multiClone) {
  const textArr = textNode.textContent.match(regex);
  const parent = multiClone || textNode.parentNode;

  if (textArr.length > 1) { // multiple brackets
    const replica = multiClone ? parent : parent.cloneNode(true);
    textArr.forEach((text) => {
      text = text.slice(1, -1);
      injectTag(text, genTag(text, replica), replica);
    });
    parent.innerHTML = replica.innerHTML;
  } else { // single bracket
    textArr[0] = textArr[0].slice(1, -1); // slice brackets
    injectTag(textArr[0], genTag(textArr[0]), parent);
  }
}

function multiHandler(textNodes) {
  const parentClone = textNodes[0].parentNode.cloneNode(true);
  textNodes.forEach((siblingText) => {
    singleHandler(siblingText, parentClone);
  });
  textNodes[0].parentNode.innerHTML = parentClone.innerHTML;
}

function iterateNodes(nodesArr) {
  nodesArr.forEach((textNode) => {
    if (Array.isArray(textNode)) {
      multiHandler(textNode);
    } else {
      singleHandler(textNode);
    }
  });
}

function nativeTreeWalker(bracketsRegex) {
  const ignoredTags = ['A', 'PRE', 'CODE', 'SCRIPT', 'STYLE'];
  // only accept nodes that have allowed text and are not in ignored tag
  const filter = {
    acceptNode(node) {
      if (bracketsRegex.test(node.data) && !ignoredTags.includes(node.parentNode.tagName)) {
        return NodeFilter.FILTER_ACCEPT;
      }
      return NodeFilter.FILTER_SKIP;
    },
  };
  const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, filter);
  walker.nextNode(); // first element is the root element!
  const nodes = [walker.currentNode]; // store one value immediately so length is not 0
  const sameParent = [];

  while (walker.nextNode()) {
    const prev = nodes[nodes.length - 1];
    const cur = walker.currentNode;
    if (cur.parentNode.isSameNode(prev.parentNode)) {
      // empty? add prev element
      if (!sameParent.length) sameParent.push(prev);
      sameParent.push(cur);
    } else {
      // if not empty replace last single elem and empty
      if (sameParent.length) nodes[nodes.length - 1] = sameParent.splice(0);
      nodes.push(cur);
    }
  }
  // If no brackets found on the page. Current node will be root (body). Verify its type to be text
  if (walker.currentNode.nodeType !== 3) return [];
  return nodes;
}

const regexPr = getOptions()
  .then(genBracketsRegex);

regexPr
  .then(nativeTreeWalker)
  .then(iterateNodes);
<commit_msg>Send disable request if no brackets found<commit_after>/* eslint-disable no-param-reassign */

let regex; // make global as it's used by both single and multiHandler

function getOptions() {
  return new Promise((resolve) => {
    chrome.storage.sync.get(null, options => resolve(options));
  });
}

// Regex test cases here: https://regexr.com/3gv3c
function genBracketsRegex(options) {
  const genRegexStr = `(?:\\()([A-Z .,!?:"'\`\\\\/\\&+-]\\d?){${options.lowLimit},${options.upLimit}}(?:\\))`;
  regex = new RegExp(genRegexStr, 'gi');
  return regex;
}

function genTag(text) {
  const dataSafeText = text.replace(/&/g, '&').replace(/"/g, '"'); // so it doesn't break html layout
  return `<bracket-less data-bracketless="${dataSafeText}">${text}</bracket-less>`;
}

function injectTag(text, tag, target) {
  const replaceRegex = new RegExp(text.replace(/[.,!?:"'`\\/&-(+)]/g, '\\$&')); // to match exactly that text
  target.innerHTML = target.innerHTML.replace(replaceRegex, tag);
}

function singleHandler(textNode, multiClone) {
  const textArr = textNode.textContent.match(regex);
  const parent = multiClone || textNode.parentNode;

  if (textArr.length > 1) { // multiple brackets
    const replica = multiClone ? parent : parent.cloneNode(true);
    textArr.forEach((text) => {
      text = text.slice(1, -1);
      injectTag(text, genTag(text, replica), replica);
    });
    parent.innerHTML = replica.innerHTML;
  } else { // single bracket
    textArr[0] = textArr[0].slice(1, -1); // slice brackets
    injectTag(textArr[0], genTag(textArr[0]), parent);
  }
}

function multiHandler(textNodes) {
  const parentClone = textNodes[0].parentNode.cloneNode(true);
  textNodes.forEach((siblingText) => {
    singleHandler(siblingText, parentClone);
  });
  textNodes[0].parentNode.innerHTML = parentClone.innerHTML;
}

function iterateNodes(nodesArr) {
  nodesArr.forEach((textNode) => {
    if (Array.isArray(textNode)) {
      multiHandler(textNode);
    } else {
      singleHandler(textNode);
    }
  });
  return nodesArr.length;
}

function nativeTreeWalker(bracketsRegex) {
  const ignoredTags = ['A', 'PRE', 'CODE', 'SCRIPT', 'STYLE'];
  // only accept nodes that have allowed text and are not in ignored tag
  const filter = {
    acceptNode(node) {
      if (bracketsRegex.test(node.data) && !ignoredTags.includes(node.parentNode.tagName)) {
        return NodeFilter.FILTER_ACCEPT;
      }
      return NodeFilter.FILTER_SKIP;
    },
  };
  const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, filter);
  walker.nextNode(); // first element is the root element!
  const nodes = [walker.currentNode]; // store one value immediately so length is not 0
  const sameParent = [];

  while (walker.nextNode()) {
    const prev = nodes[nodes.length - 1];
    const cur = walker.currentNode;
    if (cur.parentNode.isSameNode(prev.parentNode)) {
      // empty? add prev element
      if (!sameParent.length) sameParent.push(prev);
      sameParent.push(cur);
    } else {
      // if not empty replace last single elem and empty
      if (sameParent.length) nodes[nodes.length - 1] = sameParent.splice(0);
      nodes.push(cur);
    }
  }
  // If no brackets found on the page. Current node will be root (body). Verify its type to be text
  if (walker.currentNode.nodeType !== 3) return [];
  return nodes;
}

const regexPr = getOptions()
  .then(genBracketsRegex);

regexPr
  .then(nativeTreeWalker)
  .then(iterateNodes)
  .then((count) => {
    if (count === 0) chrome.runtime.sendMessage({ disable: true });
  });
<|endoftext|>


<commit_before>var util = require('util'),

    async = require('async'),
    _ = require('lodash'),

    config = require('../config'),
    MongoDB = require('../mongodb');

function ModelFormatter(){
    var self = this;

    /**
     *
     * @param options
     * @param options.complete
     */
    this.formatDB = function(options){
        var _options = _.extend({}, options),
            queryData = {species : 'dog'},
            updatedAnimal;

        MongoDB.findAnimals(queryData, {
            debug: config.debugLevel,
            complete: function (err, animals) {
                async.each(animals, function each (animal, done){
                    console.log('formatting %s', animal);
                    updatedAnimal = self.formatAnimal(animal);
                    self.saveAnimal(updatedAnimal, {
                        complete : function(){
                            done();
                        }
                    });
                }, function complete(){
                    if (_options.complete) _options.complete.apply(_options.context);
                });
            }
        });
    };

    this.formatAnimal = function(model){
        var self = this;
        _.forEach(model, function(propData, propName){
            switch(propName){
                case 'images':
                    propData.val = self.formatImagesArray(propData.val);
                default:
                    model[propName] = propData;
            }
        });
        return model;
    };

    this.formatImagesArray = function(imagesArr){

        function formatImgURL(imageURL){
            console.log('formatting %s', imageURL);
            return (/^http:/.test(imageURL)) ? imageURL : util.format("%s%s", config.domain, imageURL);
        }
        return imagesArr.map(formatImgURL);
    };

    this.saveAnimal = function(model, options){
        var _options = _.extend({}, options),
            reducedModel = {};

        _.forEach(model, function(propData, propName){
            reducedModel[propName] = propData.val;
        });

        MongoDB.saveAnimal(reducedModel, {
            debug: config.debugLevel,
            complete: function (err, newAnimal) {
                console.log('saved %j', newAnimal);
                if (_options.complete) _options.complete.apply(_options.context, [null, newAnimal])
            }
        });
    }
};

module.exports= new ModelFormatter();
<commit_msg>removes some unncessary debug output<commit_after>var util = require('util'),

    async = require('async'),
    _ = require('lodash'),

    config = require('../config'),
    MongoDB = require('../mongodb');

function ModelFormatter(){
    var self = this;

    /**
     *
     * @param options
     * @param options.complete
     */
    this.formatDB = function(options){
        var _options = _.extend({}, options),
            queryData = {species : 'dog'},
            updatedAnimal;

        MongoDB.findAnimals(queryData, {
            debug: config.debugLevel,
            complete: function (err, animals) {
                async.each(animals, function each (animal, done){
                    updatedAnimal = self.formatAnimal(animal);
                    self.saveAnimal(updatedAnimal, {
                        complete : function(){
                            done();
                        }
                    });
                }, function complete(){
                    if (_options.complete) _options.complete.apply(_options.context);
                });
            }
        });
    };

    this.formatAnimal = function(model){
        var self = this;
        _.forEach(model, function(propData, propName){
            switch(propName){
                case 'images':
                    propData.val = self.formatImagesArray(propData.val);
                default:
                    model[propName] = propData;
            }
        });
        return model;
    };

    this.formatImagesArray = function(imagesArr){

        function formatImgURL(imageURL){
            return (/^http:/.test(imageURL)) ? imageURL : util.format("%s%s", config.domain, imageURL);
        }
        return imagesArr.map(formatImgURL);
    };

    this.saveAnimal = function(model, options){
        var _options = _.extend({}, options),
            reducedModel = {};

        _.forEach(model, function(propData, propName){
            reducedModel[propName] = propData.val;
        });

        MongoDB.saveAnimal(reducedModel, {
            debug: config.debugLevel,
            complete: function (err, newAnimal) {
                if (_options.complete) _options.complete.apply(_options.context, [null, newAnimal])
            }
        });
    }
};

module.exports= new ModelFormatter();
<|endoftext|>