<commit_before>/*global declare, it, describe, beforeEach, afterEach, before, after*/
import { expect } from "mocha-es6";
import { createDOMEnvironment } from "../rendering/dom-helper.js";
import { morph, Renderer } from "../index.js";
import { pt, Color, Rectangle } from "lively.graphics";
import { num } from "lively.lang";
import { EventDispatcher } from "../events.js";

var world, submorph1, submorph2, eventDispatcher;

function createDummyWorld() {
  world = morph({
    type: "world", name: "world", extent: pt(300,300),
    submorphs: [{
        name: "submorph1", extent: pt(100,100), position: pt(10,10), fill: Color.red,
        submorphs: [{name: "submorph2", extent: pt(20,20), position: pt(5,10), fill: Color.green}]
      }]
  });
  submorph1 = world.submorphs[0];
  submorph2 = submorph1.submorphs[0];
}

var renderer, domEnv;

async function createAndRenderDummyWorld() {
  createDummyWorld();
  domEnv = await createDOMEnvironment();
  renderer = new Renderer(world, domEnv.document.body, domEnv);
  renderer.startRenderWorldLoop()
  eventDispatcher = new EventDispatcher(domEnv.window, world).install();
}

function cleanup() {
  renderer && renderer.clear();
  domEnv && domEnv.destroy();
}

describe("halos", () => {

  beforeEach(async () => createAndRenderDummyWorld());
  afterEach(() => cleanup());

// createAndRenderDummyWorld()
// cleanup()

  it("halo items are placed correctly", () => {
    submorph1.origin = pt(20,30);
    var halo = world.showHaloFor(submorph1),
        innerButton = halo.buttonControls.find(item =>
        submorph1.bounds().containsPoint(item.globalBounds().center()));
    expect(innerButton).equals(undefined, `halo item ${innerButton} is inside the bounds of its target`);
    expect(halo.originHalo().bounds().center()).equals(submorph1.origin);
  });

  it("drag drags", () => {
    var halo = world.showHaloFor(submorph1);
    halo.dragHalo().update(pt(10,5));
    expect(submorph1.position).equals(pt(20, 15));
  });

  it("resize resizes", () => {
    var halo = world.showHaloFor(submorph1);
    halo.resizeHalo().update(pt(10,5));
    expect(submorph1.extent).equals(pt(110, 105));
  });

  it("align to the morph extent while resizing", () => {
    submorph1.origin = pt(20,30);
    var halo = world.showHaloFor(submorph1, "test-pointer-1"),
        resizeButton = halo.resizeHalo(),
        resizeButtonCenter = resizeButton.globalBounds().center();
    resizeButton.update(pt(42,42));
    expect(halo.extent).equals(submorph1.extent);
  });

  it("rotate rotates", () => {
    var halo = world.showHaloFor(submorph1);
    halo.rotateHalo().init(num.toRadians(10));
    halo.rotateHalo().update(num.toRadians(25));
    expect(submorph1.rotation).closeTo(num.toRadians(15), 0.1);
  });

  it("close removes", () => {
    var halo = world.showHaloFor(submorph1);
    halo.closeHalo().update();
    expect(submorph1.owner).equals(null);
  });

  it("origin shifts origin", () => {
    submorph1.origin = pt(20,30);
    var halo = world.showHaloFor(submorph1);
    halo.originHalo().update(pt(10,5));
    expect(submorph1.origin).equals(pt(30, 35));
    expect(halo.originHalo().bounds().center()).equals(pt(30, 35));
  });

  it("grab grabs", () => {
    var halo = world.showHaloFor(submorph2),
        hand = world.handForPointerId("test-pointer");
    halo.grabHalo().init(hand)
    hand.position = submorph1.globalBounds().center();
    expect(submorph2.owner).equals(hand);
    halo.grabHalo().update(hand)
    expect(halo.position).equals(submorph2.globalBounds().topLeft());
    expect(submorph2.owner).equals(submorph1);
  });

  it("copy copies", () => {
    var halo = world.showHaloFor(submorph2),
        hand = world.handForPointerId("test-pointer");
    halo.copyHalo().init(hand)
    var copy = halo.target;
    expect(copy).not.equals(submorph2);
    hand.position = submorph1.globalBounds().center();
    halo.copyHalo().update(hand)
    expect(halo.position).equals(copy.globalBounds().topLeft());
    expect(copy.owner).equals(submorph1);
  });

});
<commit_msg>testing for origin halo action with transforms<commit_after>/*global declare, it, describe, beforeEach, afterEach, before, after*/
import { expect } from "mocha-es6";
import { createDOMEnvironment } from "../rendering/dom-helper.js";
import { morph, Renderer } from "../index.js";
import { pt, Color, Rectangle } from "lively.graphics";
import { num } from "lively.lang";
import { EventDispatcher } from "../events.js";

var world, submorph1, submorph2, eventDispatcher;

function createDummyWorld() {
  world = morph({
    type: "world", name: "world", extent: pt(300,300),
    submorphs: [{
        name: "submorph1", extent: pt(100,100), position: pt(10,10), fill: Color.red,
        submorphs: [{name: "submorph2", extent: pt(20,20), position: pt(5,10), fill: Color.green}]
      }]
  });
  submorph1 = world.submorphs[0];
  submorph2 = submorph1.submorphs[0];
}

var renderer, domEnv;

async function createAndRenderDummyWorld() {
  createDummyWorld();
  domEnv = await createDOMEnvironment();
  renderer = new Renderer(world, domEnv.document.body, domEnv);
  renderer.startRenderWorldLoop()
  eventDispatcher = new EventDispatcher(domEnv.window, world).install();
}

function cleanup() {
  renderer && renderer.clear();
  domEnv && domEnv.destroy();
}

describe("halos", () => {

  beforeEach(async () => createAndRenderDummyWorld());
  afterEach(() => cleanup());

// createAndRenderDummyWorld()
// cleanup()

  it("halo items are placed correctly", () => {
    submorph1.origin = pt(20,30);
    var halo = world.showHaloFor(submorph1),
        innerButton = halo.buttonControls.find(item =>
        submorph1.bounds().containsPoint(item.globalBounds().center()));
    expect(innerButton).equals(undefined, `halo item ${innerButton} is inside the bounds of its target`);
    expect(halo.originHalo().bounds().center()).equals(submorph1.origin);
  });

  it("drag drags", () => {
    var halo = world.showHaloFor(submorph1);
    halo.dragHalo().update(pt(10,5));
    expect(submorph1.position).equals(pt(20, 15));
  });

  it("resize resizes", () => {
    var halo = world.showHaloFor(submorph1);
    halo.resizeHalo().update(pt(10,5));
    expect(submorph1.extent).equals(pt(110, 105));
  });

  it("align to the morph extent while resizing", () => {
    submorph1.origin = pt(20,30);
    var halo = world.showHaloFor(submorph1, "test-pointer-1"),
        resizeButton = halo.resizeHalo(),
        resizeButtonCenter = resizeButton.globalBounds().center();
    resizeButton.update(pt(42,42));
    expect(halo.extent).equals(submorph1.extent);
  });

  it("rotate rotates", () => {
    var halo = world.showHaloFor(submorph1);
    halo.rotateHalo().init(num.toRadians(10));
    halo.rotateHalo().update(num.toRadians(25));
    expect(submorph1.rotation).closeTo(num.toRadians(15), 0.1);
  });

  it("close removes", () => {
    var halo = world.showHaloFor(submorph1);
    halo.closeHalo().update();
    expect(submorph1.owner).equals(null);
  });

  it("origin shifts origin", () => {
    submorph1.origin = pt(20,30);
    var halo = world.showHaloFor(submorph1);
    halo.originHalo().update(pt(10,5));
    expect(submorph1.origin).equals(pt(30, 35));
    expect(halo.originHalo().bounds().center()).equals(pt(30, 35));
  });

  it("origin shifts origin accorfing to global delta", () => {
    submorph1.position = pt(200,100);
    submorph1.rotateBy(num.toRadians(90));
    var halo = world.showHaloFor(submorph1);
    halo.originHalo().update(pt(20,5));
    expect(submorph1.origin).equals(pt(5, -20));
  });

  it("grab grabs", () => {
    var halo = world.showHaloFor(submorph2),
        hand = world.handForPointerId("test-pointer");
    halo.grabHalo().init(hand)
    hand.position = submorph1.globalBounds().center();
    expect(submorph2.owner).equals(hand);
    halo.grabHalo().update(hand)
    expect(halo.position).equals(submorph2.globalBounds().topLeft());
    expect(submorph2.owner).equals(submorph1);
  });

  it("copy copies", () => {
    var halo = world.showHaloFor(submorph2),
        hand = world.handForPointerId("test-pointer");
    halo.copyHalo().init(hand)
    var copy = halo.target;
    expect(copy).not.equals(submorph2);
    hand.position = submorph1.globalBounds().center();
    halo.copyHalo().update(hand)
    expect(halo.position).equals(copy.globalBounds().topLeft());
    expect(copy.owner).equals(submorph1);
  });

});
<|endoftext|>


<commit_before>(function() {
    var Agora = this.Agora,
        app = this.app;

    Agora.HomeActivtyList = Agora.ActivityListView.extend({

        collectionReset: function(collection) {
            this.$el.empty();
            collection.each(this.addItem);

            this.slideShowElement = '#activity_items'; // this is where the infinite news scroll will be shown
            this.DELAY_SPEED = 4000; // specifies how much time between new items appear

            // Our projection.
            this.xy = d3.geo.mercator();
            this.geopath = d3.geo.path().projection(this.xy);

            this.states = d3.select("#home_worldmap_canvas").append("svg").append("g").attr("id", "states");

            this.currentSlide = 0; // keeps track of current slide
            this.slides = $('#activity-list > div'); // this is the original list of slides
            this.interval = setInterval(this.nextSlide, this.DELAY_SPEED); // used for setInerval

            // init
            var self = this;
            this.slides.each(function() {
                $(this).appendTo($(self.slideShowElement));
            });

            d3.json("/static/js/world-countries.json",
                function(collection) {

                    self.xy.scale(320);
                    var translate = self.xy.translate();
                    translate[0] = 160;
                    translate[1] = 110;
                    self.xy.translate(translate);

                    self.states
                        .selectAll("path")
                        .data(collection.features)
                        .enter().append("path")
                        .attr("d", self.geopath);

                    self.slides.each(function() {
                        self.geolocateElement($(this));
                    });
                }
            );

        },

        // Goes to the next slide
        nextSlide:function  () {
            //if the current slide is at the end, loop to the first slide.
            if (this.currentSlide >= this.slides.length -1) {
                this.currentSlide = 0;
            } else {
                this.currentSlide++;
            }

            // Add a new slide

            $(this.slideShowElement + ' > div').first().removeClass('activity-action-first');

            var newElement = $(this.slides[this.currentSlide]).clone().addClass('activity-action-first').hide();

            newElement.prependTo($(this.slideShowElement));
            newElement.animate({"height": "toggle", "opacity": "toggle"}, "slow");
            $(this.slideShowElement + ' > div').last().remove();

            this.geolocateElement(newElement);

            //if the auto slide advance is set, stop it, then start again.
            if (this.interval != null) {
                clearInterval(this.interval);
            }
            //Goes to next slide every couple of seconds.
            this.interval = setInterval(this.nextSlide, this.DELAY_SPEED);
        },

        geolocateElement:function (element)
        {
            var geodata = element.attr("geodata");

            if (geodata.length > 0) {
                geodata = geodata.substr(1, geodata.length - 2);
                geodata = geodata.split(",");
                // Make appear a point in the map
                var pos = [parseFloat(geodata[1]), parseFloat(geodata[0])];
                this.geolocate(pos);
            }
        },

        geolocate: function (pos)
        {
            pos = this.xy(pos);

            function animateSecondStep()
            {
                d3.select(this)
                .transition()
                    .duration(35000)
                    .style("fill-opacity", "0")
                    .each("end", function() {
                        d3.select(this).remove();
                    });
            }

            d3.select("#home_worldmap_canvas svg")
                .append("svg:circle")
                .style("fill-opacity", "0.1")
                .style("fill", "red")
                .attr("r", 10)
                .attr("cx", pos[0])
                .attr("cy", pos[1])
                .transition()
                .delay(0)
                .duration(1000)
                .attr("r", 1.5)
                .style("fill-opacity", "1")
                .each("end", animateSecondStep);
        },
    });

    Agora.HomeAnonymousView = Backbone.View.extend({
        el: "body",

        initialize: function() {
            _.bindAll(this);
            // Only initialize on correct section of page exists.
            if ($("#activity-list").length > 0) {
                this.activityListView = new Agora.HomeActivtyList();
            }
        },
    });
}).call(this)
<commit_msg>Fixing firefox 100% cpu usage<commit_after>(function() {
    var Agora = this.Agora,
        app = this.app;

    Agora.HomeActivtyList = Agora.ActivityListView.extend({

        points: [],

        collectionReset: function(collection) {
            this.$el.empty();
            collection.each(this.addItem);

            this.slideShowElement = '#activity_items'; // this is where the infinite news scroll will be shown
            this.DELAY_SPEED = 4000; // specifies how much time between new items appear

            // Our projection.
            this.xy = d3.geo.mercator();
            this.geopath = d3.geo.path().projection(this.xy);

            this.states = d3.select("#home_worldmap_canvas").append("svg").append("g").attr("id", "states");

            this.currentSlide = 0; // keeps track of current slide
            this.slides = $('#activity-list > div'); // this is the original list of slides
            this.interval = setInterval(this.nextSlide, this.DELAY_SPEED); // used for setInerval

            // init
            var self = this;
            this.slides.each(function() {
                $(this).appendTo($(self.slideShowElement));
            });

            d3.json("/static/js/world-countries.json",
                function(collection) {

                    self.xy.scale(320);
                    var translate = self.xy.translate();
                    translate[0] = 160;
                    translate[1] = 110;
                    self.xy.translate(translate);

                    self.states
                        .selectAll("path")
                        .data(collection.features)
                        .enter().append("path")
                        .attr("d", self.geopath);

                    self.slides.each(function() {
                        self.geolocateElement($(this));
                    });
                }
            );

        },

        // Goes to the next slide
        nextSlide:function  () {
            //if the current slide is at the end, loop to the first slide.
            if (this.currentSlide >= this.slides.length -1) {
                this.currentSlide = 0;
            } else {
                this.currentSlide++;
            }

            // Add a new slide

            $(this.slideShowElement + ' > div').first().removeClass('activity-action-first');

            var newElement = $(this.slides[this.currentSlide]).clone().addClass('activity-action-first').hide();

            newElement.prependTo($(this.slideShowElement));
            newElement.animate({"height": "toggle", "opacity": "toggle"}, "slow");
            $(this.slideShowElement + ' > div').last().remove();

            this.geolocateElement(newElement);

            //if the auto slide advance is set, stop it, then start again.
            if (this.interval != null) {
                clearInterval(this.interval);
            }
            //Goes to next slide every couple of seconds.
            this.interval = setInterval(this.nextSlide, this.DELAY_SPEED);
        },

        geolocateElement:function (element)
        {
            var geodata = element.attr("geodata");

            if (geodata.length > 0) {
                geodata = geodata.substr(1, geodata.length - 2);
                geodata = geodata.split(",");
                // Make appear a point in the map
                var pos = [parseFloat(geodata[1]), parseFloat(geodata[0])];
                this.geolocate(pos);
            }
        },

        geolocate: function (pos)
        {
            pos = this.xy(pos);

            var point = this.points.pop()
            if (point) {
                d3.select(point)
                .transition()
                    .duration(100)
                    .style("fill-opacity", "0")
                    .each("end", function() {
                        d3.select(this).remove();
                    });
            }

            var self = this;
            function animateSecondStep()
            {
                self.points.push(this);
            }

            d3.select("#home_worldmap_canvas svg")
                .append("svg:circle")
                .style("fill-opacity", "0.1")
                .style("fill", "red")
                .attr("r", 10)
                .attr("cx", pos[0])
                .attr("cy", pos[1])
                .transition()
                .delay(0)
                .duration(1000)
                .attr("r", 1.5)
                .style("fill-opacity", "1")
                .each("end", animateSecondStep);
        },
    });

    Agora.HomeAnonymousView = Backbone.View.extend({
        el: "body",

        initialize: function() {
            _.bindAll(this);
            // Only initialize on correct section of page exists.
            if ($("#activity-list").length > 0) {
                this.activityListView = new Agora.HomeActivtyList();
            }
        },
    });
}).call(this)
<|endoftext|>


<commit_before><commit_msg>Draft something that might remind a jwt validatior<commit_after><|endoftext|>


<commit_before>// public IP for backend in EC2
var EBURL = "http://ec2-52-23-243-230.compute-1.amazonaws.com:5000"

var storage_keys = ['user_id', 'jrec', 'sequence_id', 'session_id', 'doc_id', 'text', 'info']

var POPUPONSCREEN = false;

var LIMIT = 39;

// TODO: shuhan I believe you said you will delete this part?
chrome.runtime.onMessage.addListener(function(request, sender, callback) {
  chrome.storage.local.set({ "activated_language_learning": request.activated},
    function(){
      chrome.storage.local.get(['sequence_id', 'doc_id'],
       function(obj) {
        var needsInit = !('sequence_id' in obj) || obj['sequence_id'] == 0 || obj['sequence_id'] >= LIMIT;
        if (request.activated && needsInit) {
          show_intro();
        } else if (request.activated) {
          navigate(buildURL(obj['doc_id']), buildURL(obj["doc_id"]) != window.location.href)
        } else {
          window.location.href = window.location.href;
        }
      });
  });
});
//

chrome.storage.local.get(["activated_language_learning", "doc_id"], function(r) {
  if (! "activated_language_learning" in r ||
    !r["activated_language_learning"]) {

  } else {
    $(document).ready(function() {
      if (hasStarted()) {
        if (justStarted()) {
          initialize();
        } else if (buildURL(r["doc_id"]) != window.location.href) {
          // allow users to navigate other NHK easy articles
          // navigate(buildURL(r["doc_id"]), false);
        } else {
          highlightText();
        }
      }
  });

  }
})

function convertDocIdToId(doc_id) {
  return doc_id.substr(0,15);
}

function scrollToMyPopUp() {
    $('html,body').animate({
            scrollTop: $("#myPopup").offset().top - 100
          },
          'slow', function() {
            setTimeout(function(){}, 2000);
            POPUPONSCREEN = $("#myPopup").isOnScreen();
            if (!POPUPONSCREEN) {
              scrollToMyPopUp();
            }
          });
}

function initialize() {
  chrome.storage.local.get(storage_keys, function(obj) {
            $.ajax({
              type: 'GET',
              url: EBURL + '/initialize',
              success: function (e) {
                var valuesToSet = {
                  'sequence_id': 0,
                  'session_id': e['session_id']
                };
                if (obj['user_id'] == null) {
                  valuesToSet['user_id'] = e['user_id'];
                  valuesToSet['jrec'] = e['jrec'];
                  valuesToSet['doc_id'] = e['doc_id'];
                  valuesToSet['text'] = e['text'];
                  valuesToSet['info'] = e['info'];
                }
                chrome.storage.local.set(valuesToSet, function() {
                  chrome.storage.local.get(['doc_id'], function(d) {
                    navigate(buildURL(d['doc_id']), false)
                  })
                });
              },
              error: function(error) {
                console.log(error);
              }
            });
          });
}

function highlightText() {
  chrome.storage.local.get(storage_keys, function(e) {
            text = e['text'];
            addTagToText(text);

            document.body.style.background = "black";
            $(".contentWrap").css('background', 'unset');
            $("#side").append("

");
            $("#enq_answer_disp").css('background', 'unset');
            $("#enq_ansbak").css('background', 'unset');
            $("#main_enqdiv").hide();
            $("#targetText").append("  Do you understand this passage?
 <button type='button' class='yesButton' id='yesButtonId'> Yes </button> <button type='button' class='noButton' id='noButtonId'> No </button> ");

            $('.overlay').fadeIn(300);
            scrollToMyPopUp();
            var seen = new Date().getTime()

              document.getElementById("yesButtonId").addEventListener("click", function() {
                submitAnswerAndGetNext(true, seen)
              }, false);

              document.getElementById("noButtonId").addEventListener("click", function() {
                submitAnswerAndGetNext(false, seen)
              }, false);
          });

}
// checks whether URL contains http://www3.nhk.or.jp/
function needsInit() {
  chrome.storage.local.get('sequence_id', function(obj) {
    return !'sequence_id' in obj || obj['sequence_id'] == 0 || obj['sequence_id'] >= LIMIT;
  });
}

// checks whether URL contains http://www3.nhk.or.jp/
function hasStarted() {
  return window.location.href.indexOf("http://www3.nhk.or.jp/") > -1;
}

// gets the id of the current document of interest
// if you are not on a document but on NHK
// then this method will return 'easy'
function justStarted() {
  var currentUrl = window.location.href.split('/')
  return currentUrl[currentUrl.length - 2] == 'easy'
}

function buildURL(docId) {
  id = convertDocIdToId(docId);
  return 'http://www3.nhk.or.jp/news/easy/' + id + '/' + id + '.html'
}
// given a docId, navigates page to article corresponding to it
function navigate(docId, inNewTab) {
  chrome.runtime.sendMessage({"url": docId, "newTab": inNewTab});
}

// isplay final page
function show_intro() {
	navigate(chrome.extension.getURL('welcome_page.htm'), true);
}

// isplay final page
function show_final_page() {
	navigate(chrome.extension.getURL('final_page.htm'), false);
}

// given a text, adds the text in a div with
// id set as targetText
//
// after trying differet ways to extract the text
// from the html setup of NHK, I did the following:
//
// I have a pointer to a chacater in the html, i, and
// a pointer to a character in the text, indexOfText
//
// Every time I see the character '<', I start accumulating
// the characters up to '>' into tagName; if tagName is
// 'rt' then those are furiganas, so we skip to the next
// instance of '>' which would be the tag that closes the
// rt tag; otherwise, I adjust i and indexOfText properly
// to find the overlap with the first and last index of
// the overlap within the html; when the overlap is found,
// we open the div targetText in the first index and
// close the div in the last index
function addTagToText(text) {
  text = text.trim();
  text = text.replace("＜", "【");
  text = text.replace("＞", "】");
  console.log(text);
  var i = 0;
  var indexOfText = 0;
  var firstIndex = 0;
  var lastIndex = 0;
  html = $("#newsarticle").html();
  while ( i < html.length && indexOfText < text.length) {
    if (html.charAt(i) == '<') {
        j = i +1;
        tagName = "";
        while (html.charAt(j) != '>') {
            tagName += html.charAt(j);
            j += 1
        }
        if (tagName == "rt") {
            j += 1
            while (html.charAt(j) != '>') {
                j += 1
            }
        }
        i = j + 1;
    } else if (html.charAt(i) == ' ' || html.charAt(i) == '\n') {
        i += 1
    } else if (text.charAt(indexOfText) == ' ') {
        indexOfText += 1
    } else {
        if (text.charAt(indexOfText) == html.charAt(i)) {
          if (indexOfText == 0) {
            firstIndex = i;
          }
          indexOfText += 1
        } else {
          indexOfText = 0;
        }
        i += 1
    }
  }

  lastIndex = i;
  var newHtml = html.substring(0, firstIndex);
  var addSpan = false
  var spanClass = '<ruby>'
  if (newHtml.substring(newHtml.length - spanClass.length) == spanClass) {
    addSpan = true
  }
  var tag = '
';
  if (newHtml.substring(newHtml.length-6) == '<ruby>') {
    newHtml = newHtml.substring(0, newHtml.length-6);
    tag += '<ruby>'
  }
  if (addSpan) {
    newHtml = newHtml.substring(0, newHtml.length - spanClass.length);
    newHtml += tag;
    newHtml += spanClass;
  }
  else {
    newHtml += tag;
  }

  newHtml += html.substring(firstIndex, lastIndex);
  newHtml +=  '
'
  newHtml += html.substring(lastIndex);
  $("#newsarticle").html(newHtml);
}

// submit user response (true or false) to the backend
// and get the next document id
function submitAnswerAndGetNext(userResponse, seen) {
  chrome.storage.local.get(storage_keys, function(e) {
          e['answered'] = new Date().getTime()
          e['seen'] = seen
          $.ajax({
                 type: 'POST',
                 contentType: 'application/json',
                 processData: false,
                 traditional: true,
                 data: JSON.stringify(e),
                 url: EBURL + '/record_response/' + userResponse,
                 success: function (d) {
                  if (d['end']) {
                    chrome.storage.local.set({
                      'user_summary': d['user_summary'],
                      'jrec': d['new_jrec'],
                      'sequence_id': e['sequence_id'] + 1
                    }, function() {
                      show_final_page();
                      window.close();
                    });
                  } else {
                    chrome.storage.local.set(
                      {
                        'jrec': d['jrec'],
                        'doc_id': d['next_doc_id'],
                        'text': d['next_text'],
                        'info': d['next_info'],
                        'sequence_id': e['sequence_id'] + 1
                      }, function() {
                        navigate(buildURL(d['next_doc_id']), false);
                      });
                  }
                },
                  error: function(error) {
                    console.log(error);
                  }
                });

        });
}

// credits to https://stackoverflow.com/questions/8897289/how-to-check-if-an-element-is-off-screen
$.fn.isOnScreen = function(partial){

    //let's be sure we're checking only one element (in case function is called on set)
    var t = $(this).first();

    //we're using getBoundingClientRect to get position of element relative to viewport
    //so we dont need to care about scroll position
    var box = t[0].getBoundingClientRect();

    //let's save window size
    var win = {
        h : $(window).height(),
        w : $(window).width()
    };

    //now we check against edges of element

    //firstly we check one axis
    //for example we check if left edge of element is between left and right edge of scree (still might be above/below)
    var topEdgeInRange = box.top >= 0 && box.top <= win.h;
    var bottomEdgeInRange = box.bottom >= 0 && box.bottom <= win.h;

    var leftEdgeInRange = box.left >= 0 && box.left <= win.w;
    var rightEdgeInRange = box.right >= 0 && box.right <= win.w;

    //here we check if element is bigger then window and 'covers' the screen in given axis
    var coverScreenHorizontally = box.left <= 0 && box.right >= win.w;
    var coverScreenVertically = box.top <= 0 && box.bottom >= win.h;

    //now we check 2nd axis
    var topEdgeInScreen = topEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
    var bottomEdgeInScreen = bottomEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );

    var leftEdgeInScreen = leftEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
    var rightEdgeInScreen = rightEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );

    //now knowing presence of each edge on screen, we check if element is partially or entirely present on screen
    var isPartiallyOnScreen = topEdgeInScreen || bottomEdgeInScreen || leftEdgeInScreen || rightEdgeInScreen;
    var isEntirelyOnScreen = topEdgeInScreen && bottomEdgeInScreen && leftEdgeInScreen && rightEdgeInScreen;

    return partial ? isPartiallyOnScreen : isEntirelyOnScreen;

};
<commit_msg>Code Clean.<commit_after>// public IP for backend in EC2
var EBURL = "http://ec2-52-23-243-230.compute-1.amazonaws.com:5000"

var storage_keys = ['user_id', 'jrec', 'sequence_id', 'session_id', 'doc_id', 'text', 'info']

var POPUPONSCREEN = false;

var LIMIT = 39;

// TODO: shuhan I believe you said you will delete this part?
/* chrome.runtime.onMessage.addListener(function(request, sender, callback) {
  chrome.storage.local.set({ "activated_language_learning": request.activated},
    function(){
      chrome.storage.local.get(['sequence_id', 'doc_id'],
       function(obj) {
        var needsInit = !('sequence_id' in obj) || obj['sequence_id'] == 0 || obj['sequence_id'] >= LIMIT;
        if (request.activated && needsInit) {
          show_intro();
        } else if (request.activated) {
          navigate(buildURL(obj['doc_id']), buildURL(obj["doc_id"]) != window.location.href)
        } else {
          window.location.href = window.location.href;
        }
      });
  });
}); */
//

chrome.storage.local.get(["activated_language_learning", "doc_id"], function(r) {
  //if (! "activated_language_learning" in r ||
  //  !r["activated_language_learning"]) {
  //} else {
  if ("activated_language_learning" in r && r["activated_language_learning"]) {
    $(document).ready(function() {
      if (hasStarted()) {
        if (justStarted()) {
          initialize();
        } else if (buildURL(r["doc_id"]) != window.location.href) {
          // allow users to navigate other NHK easy articles
          // navigate(buildURL(r["doc_id"]), false);
        } else {
          highlightText();
        }
      }
  });

  }
})

function convertDocIdToId(doc_id) {
  return doc_id.substr(0,15);
}

function scrollToMyPopUp() {
    $('html,body').animate({
            scrollTop: $("#myPopup").offset().top - 100
          },
          'slow', function() {
            setTimeout(function(){}, 2000);
            POPUPONSCREEN = $("#myPopup").isOnScreen();
            if (!POPUPONSCREEN) {
              scrollToMyPopUp();
            }
          });
}

function initialize() {
  chrome.storage.local.get(storage_keys, function(obj) {
            $.ajax({
              type: 'GET',
              url: EBURL + '/initialize',
              success: function (e) {
                var valuesToSet = {
                  'sequence_id': 0,
                  'session_id': e['session_id']
                };
                if (obj['user_id'] == null) {
                  valuesToSet['user_id'] = e['user_id'];
                  valuesToSet['jrec'] = e['jrec'];
                  valuesToSet['doc_id'] = e['doc_id'];
                  valuesToSet['text'] = e['text'];
                  valuesToSet['info'] = e['info'];
                }
                chrome.storage.local.set(valuesToSet, function() {
                  chrome.storage.local.get(['doc_id'], function(d) {
                    navigate(buildURL(d['doc_id']), false)
                  })
                });
              },
              error: function(error) {
                console.log(error);
              }
            });
          });
}

function highlightText() {
  chrome.storage.local.get(storage_keys, function(e) {
            text = e['text'];
            addTagToText(text);

            document.body.style.background = "black";
            $(".contentWrap").css('background', 'unset');
            $("#side").append("

");
            $("#enq_answer_disp").css('background', 'unset');
            $("#enq_ansbak").css('background', 'unset');
            $("#main_enqdiv").hide();
            $("#targetText").append("  Do you understand this passage?
 <button type='button' class='yesButton' id='yesButtonId'> Yes </button> <button type='button' class='noButton' id='noButtonId'> No </button> ");

            $('.overlay').fadeIn(300);
            scrollToMyPopUp();
            var seen = new Date().getTime()

              document.getElementById("yesButtonId").addEventListener("click", function() {
                submitAnswerAndGetNext(true, seen)
              }, false);

              document.getElementById("noButtonId").addEventListener("click", function() {
                submitAnswerAndGetNext(false, seen)
              }, false);
          });

}
// checks whether URL contains http://www3.nhk.or.jp/
function needsInit() {
  chrome.storage.local.get('sequence_id', function(obj) {
    return !'sequence_id' in obj || obj['sequence_id'] == 0 || obj['sequence_id'] > LIMIT;
  });
}

// checks whether URL contains http://www3.nhk.or.jp/
function hasStarted() {
  return window.location.href.indexOf("http://www3.nhk.or.jp/") > -1;
}

// gets the id of the current document of interest
// if you are not on a document but on NHK
// then this method will return 'easy'
function justStarted() {
  var currentUrl = window.location.href.split('/')
  return currentUrl[currentUrl.length - 2] == 'easy'
}

function buildURL(docId) {
  id = convertDocIdToId(docId);
  return 'http://www3.nhk.or.jp/news/easy/' + id + '/' + id + '.html'
}
// given a docId, navigates page to article corresponding to it
function navigate(docId, inNewTab) {
  chrome.runtime.sendMessage({"url": docId, "newTab": inNewTab});
}

// isplay final page
function show_intro() {
	navigate(chrome.extension.getURL('welcome_page.htm'), true);
}

// isplay final page
function show_final_page() {
	navigate(chrome.extension.getURL('final_page.htm'), false);
}

// given a text, adds the text in a div with
// id set as targetText
//
// after trying differet ways to extract the text
// from the html setup of NHK, I did the following:
//
// I have a pointer to a chacater in the html, i, and
// a pointer to a character in the text, indexOfText
//
// Every time I see the character '<', I start accumulating
// the characters up to '>' into tagName; if tagName is
// 'rt' then those are furiganas, so we skip to the next
// instance of '>' which would be the tag that closes the
// rt tag; otherwise, I adjust i and indexOfText properly
// to find the overlap with the first and last index of
// the overlap within the html; when the overlap is found,
// we open the div targetText in the first index and
// close the div in the last index
function addTagToText(text) {
  text = text.trim();
  text = text.replace("＜", "【");
  text = text.replace("＞", "】");
  console.log(text);
  var i = 0;
  var indexOfText = 0;
  var firstIndex = 0;
  var lastIndex = 0;
  html = $("#newsarticle").html();
  while ( i < html.length && indexOfText < text.length) {
    if (html.charAt(i) == '<') {
        j = i +1;
        tagName = "";
        while (html.charAt(j) != '>') {
            tagName += html.charAt(j);
            j += 1
        }
        if (tagName == "rt") {
            j += 1
            while (html.charAt(j) != '>') {
                j += 1
            }
        }
        i = j + 1;
    } else if (html.charAt(i) == ' ' || html.charAt(i) == '\n') {
        i += 1
    } else if (text.charAt(indexOfText) == ' ') {
        indexOfText += 1
    } else {
        if (text.charAt(indexOfText) == html.charAt(i)) {
          if (indexOfText == 0) {
            firstIndex = i;
          }
          indexOfText += 1
        } else {
          indexOfText = 0;
        }
        i += 1
    }
  }

  lastIndex = i;
  var newHtml = html.substring(0, firstIndex);
  var addSpan = false
  var spanClass = '<ruby>'
  if (newHtml.substring(newHtml.length - spanClass.length) == spanClass) {
    addSpan = true
  }
  var tag = '
';
  if (newHtml.substring(newHtml.length-6) == '<ruby>') {
    newHtml = newHtml.substring(0, newHtml.length-6);
    tag += '<ruby>'
  }
  if (addSpan) {
    newHtml = newHtml.substring(0, newHtml.length - spanClass.length);
    newHtml += tag;
    newHtml += spanClass;
  }
  else {
    newHtml += tag;
  }

  newHtml += html.substring(firstIndex, lastIndex);
  newHtml +=  '
'
  newHtml += html.substring(lastIndex);
  $("#newsarticle").html(newHtml);
}

// submit user response (true or false) to the backend
// and get the next document id
function submitAnswerAndGetNext(userResponse, seen) {
  chrome.storage.local.get(storage_keys, function(e) {
          e['answered'] = new Date().getTime()
          e['seen'] = seen
          $.ajax({
                 type: 'POST',
                 contentType: 'application/json',
                 processData: false,
                 traditional: true,
                 data: JSON.stringify(e),
                 url: EBURL + '/record_response/' + userResponse,
                 success: function (d) {
                  if (d['end']) {
                    chrome.storage.local.set({
                      'user_summary': d['user_summary'],
                      'jrec': d['new_jrec'],
                      'sequence_id': e['sequence_id'] + 1
                    }, function() {
                      show_final_page();
                      window.close();
                    });
                  } else {
                    chrome.storage.local.set(
                      {
                        'jrec': d['jrec'],
                        'doc_id': d['next_doc_id'],
                        'text': d['next_text'],
                        'info': d['next_info'],
                        'sequence_id': e['sequence_id'] + 1
                      }, function() {
                        navigate(buildURL(d['next_doc_id']), false);
                      });
                  }
                },
                  error: function(error) {
                    console.log(error);
                  }
                });

        });
}

// credits to https://stackoverflow.com/questions/8897289/how-to-check-if-an-element-is-off-screen
$.fn.isOnScreen = function(partial){

    //let's be sure we're checking only one element (in case function is called on set)
    var t = $(this).first();

    //we're using getBoundingClientRect to get position of element relative to viewport
    //so we dont need to care about scroll position
    var box = t[0].getBoundingClientRect();

    //let's save window size
    var win = {
        h : $(window).height(),
        w : $(window).width()
    };

    //now we check against edges of element

    //firstly we check one axis
    //for example we check if left edge of element is between left and right edge of scree (still might be above/below)
    var topEdgeInRange = box.top >= 0 && box.top <= win.h;
    var bottomEdgeInRange = box.bottom >= 0 && box.bottom <= win.h;

    var leftEdgeInRange = box.left >= 0 && box.left <= win.w;
    var rightEdgeInRange = box.right >= 0 && box.right <= win.w;

    //here we check if element is bigger then window and 'covers' the screen in given axis
    var coverScreenHorizontally = box.left <= 0 && box.right >= win.w;
    var coverScreenVertically = box.top <= 0 && box.bottom >= win.h;

    //now we check 2nd axis
    var topEdgeInScreen = topEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
    var bottomEdgeInScreen = bottomEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );

    var leftEdgeInScreen = leftEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
    var rightEdgeInScreen = rightEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );

    //now knowing presence of each edge on screen, we check if element is partially or entirely present on screen
    var isPartiallyOnScreen = topEdgeInScreen || bottomEdgeInScreen || leftEdgeInScreen || rightEdgeInScreen;
    var isEntirelyOnScreen = topEdgeInScreen && bottomEdgeInScreen && leftEdgeInScreen && rightEdgeInScreen;

    return partial ? isPartiallyOnScreen : isEntirelyOnScreen;

};
<|endoftext|>


<commit_before>'use strict';

var Auth = require('./Auth');
var Util = require('./Util');
var gcloud = require('gcloud');
var Q = require('q');
var path = require('path');
var fs = require('fs');

function Filestore(repoName) {
  this.name = repoName;
  this.bucketName = Util.makeBucketName(repoName);
  this.storage = gcloud.storage(Auth);
  this.bucket = this.storage.bucket(this.bucketName);
}

Filestore.prototype.save = function() {
  var args = Array.prototype.slice.call(arguments);
  var cb = args.pop();
  var fileOnDisk = args[args.length -1];
  args[0] = this.makeBranchName(args[0]);
  args[args.length - 1] = path.basename(args[args.length - 1]);
  var fullPath = args.join('/');
  this.persistFile(fileOnDisk, fullPath, cb);
};

Filestore.prototype.get = function(path, cb) {
  var file = this.bucket.file(path);
  file.download(cb);
};

Filestore.prototype.saveBuildNumberFile = function(branch, buildId, buildNumber, fileOnDisk, cb) {
  this.save.apply(this, arguments);
};

Filestore.prototype.saveBuildFile = function(branch, buildId, fileOnDisk, cb) {
  this.save.apply(this, arguments);
};

Filestore.prototype.saveBranchFile = function(branch, fileOnDisk, cb) {
  this.save.apply(this, arguments);
};

Filestore.prototype.saveRepoFile = function(fileOnDisk, cb) {
  this.persistFile(fileOnDisk, path.basename(fileOnDisk),  cb);
};

// Takes contents and saves it into a file named 'filename' for the build
Filestore.prototype.saveRunFile = function(buildId, buildNumber, filename, fileOnDisk, cb) {
  var me = this;
  this.getBranch(buildId, function(err, branch, safeBranch) {
    if (err) {
      cb(err);
    } else {
      var fullPath = path.join(safeBranch, String(buildId), String(buildNumber), filename);
      me.persistFile(fileOnDisk, fullPath, cb);
    }
  });
};

/*
 * All files in fileList are stored in the 'prefix' directory in the bucket
 */
Filestore.prototype.persistFiles = function(prefix, fileList, cb) {
  var me = this;
  // Array of function calls that return promises to save each file
  var promises = fileList.map(function(file) {
    return Q.ninvoke(me, 'persistFile', file, path.join(prefix, path.basename(file)));
  });
  Util.dealWithAllPromises(promises, cb);
};

Filestore.prototype.persistFile = function(from, to, cb) {
  var me = this;
  var options = {
    destination: to
  };
  this.storage.createBucket(this.bucketName, function(err, bucket) {
    if (err) {
      // Asume bucket already exists
      // TODO(trostler): verify that's true!
      bucket = me.storage.bucket(me.bucketName);
    }

    // Make bucket world-readable
    bucket.acl.default.add({
      entity: 'allUsers',
      role: me.storage.acl.READER_ROLE
    }, function(aerr /*, apiResponse*/) {
      if (aerr) {
        cb(aerr);
      } else {
        bucket.upload(from, options, cb);
      }
    });
  });
};

Filestore.prototype.makeBranchName = function(branch) {
  return ['branch', branch].join('-');
};

Filestore.prototype.getBasePublicURL = function(branch, buildId, buildNumber) {
  branch = this.makeBranchName(branch);
  return path.join(this.bucketName, branch, String(buildId), String(buildNumber));
};

Filestore.prototype.getFile = function(buildId, filePath, cb) {
  var me = this;
  this.getBranch(buildId, function(err, branch, safeBranch) {
    if (err) {
      cb(err);
    } else {
      var fullFilename = path.join(safeBranch, String(buildId), filePath);
      var file = me.bucket.file(fullFilename);
      file.download(cb);
    }
  });
};

Filestore.prototype.getLogFile = function(buildId, buildNumber, filename, cb) {
  var logFile = path.join(String(buildId), String(buildNumber), filename);
  this.getFile(buildId, logFile, cb);
};

Filestore.prototype.getMainLogFile = function(buildId, buildNumber, cb) {
  this.getLogFile(buildId, buildNumber, 'user-script.clean.log', cb);
};

Filestore.prototype.dealfest = function(err, cb, allItems, apiResponse, nextQuery, func) {
  if (err) {
    cb(err);
  } else {
    if (apiResponse.items) {
      allItems = allItems.concat(apiResponse.items.map(function(item) {
        return item.name;
      }));
    }
    if (!nextQuery) {
      cb(null, allItems);
    } else {
      func.call(this, null, cb, allItems, nextQuery);
    }
  }
};

Filestore.prototype.getFileList = function(filePath, cb, filesSoFar, nextQuery) {
  var query;
  if (!filesSoFar) {
    filesSoFar = [];
    query = {
      prefix: filePath,
      delimeter: '/'
    };
  }

  var me = this;
  this.bucket.getFiles(nextQuery || query, function(err, files, nextQ, apiResponse) {
    me.dealfest(err, cb, filesSoFar, apiResponse, nextQ, me.getFileList);
  });
};

Filestore.prototype.getBranches = function(cb) {
  var branches = {};
  this.getFileList('', function(err, fileList) {
    if (err) {
      cb(err);
    } else {
      fileList.forEach(function(fileName) {
        var regex = new RegExp('^branch-([^/]+)');
        var matches = regex.exec(fileName);
        if (matches) {
          branches[matches[1]] = 1;
        }
      });
      cb(null, Object.keys(branches));
    }
  });
};

Filestore.prototype.getBranchFileList = function(branch, cb) {
  var safeBranch = this.makeBranchName(branch);
  this.getFileList(safeBranch, cb);
};

Filestore.prototype.getBuildFileList = function(buildId, cb) {
  var me = this;
  this.getBranch(buildId, function(err, branch, safeBranch) {
    if (err) {
      cb(err);
    } else {
      var dirPath = path.join(safeBranch, String(buildId));
      me.getFileList(dirPath, cb);
    }
  });
};

Filestore.prototype.getRunFileList = function(buildId, buildNumber, cb) {
  var me = this;
  this.getBranch(buildId, function(err, branch, safeBranch) {
    if (err) {
      cb(err);
    } else {
      var dirPath = path.join(safeBranch, String(buildId), String(buildNumber));
      me.getFileList(dirPath, cb);
    }
  });
};

Filestore.prototype.deleteFile = function(filename, cb) {
  var file = this.bucket.file(filename);
  file.delete(cb);
};

Filestore.prototype.deleteFiles = function(fileList, cb) {
  var me = this;
  var promises = fileList.map(function(file) {
    return Q.ninvoke(me, 'deleteFile', file);
  });
  Util.dealWithAllPromises(promises, cb);
};

Filestore.prototype.deleteRunFiles = function(buildId, buildNumber, cb) {
  var me = this;
  this.getRunFileList(buildId, buildNumber, function(err, fileList) {
    if (err) {
      cb(err);
    } else {
      me.deleteFiles(fileList, cb);
    }
  });
};

// Not dangerous at all :)
Filestore.prototype.deleteAllBranches = function(cb) {
  var me = this;
  this.getBranches(function(err, branches) {
    if (err) {
      cb(err);
    } else {
      var promises = branches.map(function(branch) {
        return Q.ninvoke(me, 'deleteBranchFiles', branch);
      });
      Util.dealWithAllPromises(promises, cb);
    }
  });
};

Filestore.prototype.deleteBranchFiles = function(branch, cb) {
  var me = this;
  this.getBranchFileList(branch, function(err, fileList) {
    if (err) {
      cb(err);
    } else {
      me.deleteFiles(fileList, cb);
    }
  });
};

Filestore.prototype.deleteBuildFiles = function(buildId, cb) {
  var me = this;
  this.getBuildFileList(buildId, function(err, fileList) {
    if (err) {
      cb(err);
    } else {
      me.deleteFiles(fileList, cb);
    }
  });
};

Filestore.prototype.getBranch = function(buildId, cb) {
  var me = this;
  this.getFileList('', function(err, list) {
    if (err) {
      cb(err);
    } else {
      var branch = list.reduce(function(previous, fileName) {
        // try to match branch-(branch}/buildId
        if (previous) {
          return previous;
        }
        var regex = new RegExp('^branch-([^/]+)/' + buildId + '/');
        var matches = regex.exec(fileName);
        if (matches) {
          return matches[1];
        }
      }, '');
      if (!branch) {
        cb('Cannot find branch for buildId ' + buildId);
      } else {
        cb(null, branch, me.makeBranchName(branch));
      }
    }
  });
};

// Returns PROMISE
Filestore.prototype.savePrivateKey = function(branch, buildId, buildNumber, keyData, cb) {
  var tmpFile = path.join('/tmp', branch + buildId + buildNumber, 'private.key');
  if (!fs.existsSync(path.dirname(tmpFile))) {
    fs.mkdirSync(path.dirname(tmpFile));
  }
  fs.writeFileSync(tmpFile, keyData, 'utf8');
  return Q.ninvoke(this, 'saveBuildNumberFile', branch, buildId, buildNumber, tmpFile);
};

Filestore.prototype.getPrivateKey = function(buildId, buildNumber, cb) {
  this.getFile(buildId, path.join(String(buildNumber), 'private.key'), cb);
};

// Returns PROMISE
Filestore.prototype.saveStartupScript = function(branch, buildId, buildNumber, script, cb) {
  var tmpFile = path.join('/tmp', branch + buildId + buildNumber, 'startupScript.sh');
  if (!fs.existsSync(path.dirname(tmpFile))) {
    fs.mkdirSync(path.dirname(tmpFile));
  }
  fs.writeFileSync(tmpFile, script, 'utf8');
  return Q.ninvoke(this, 'saveBuildNumberFile', branch, buildId, buildNumber, tmpFile);
};

Filestore.prototype.getStartupScript = function(buildId, buildNumber, cb) {
  this.getFile(buildId, path.join(String(buildNumber), 'startupScript.sh'), cb);
};

Filestore.prototype.saveScriptAndPK = function(branch, buildId, buildNumber, script, pk) {
  var me = this;
  return this.saveStartupScript(branch, buildId, buildNumber, script)
  .then(function() {
    return me.savePrivateKey(branch, buildId, buildNumber, pk);
  });
};

module.exports = Filestore;
<commit_msg>fixup getlogfile<commit_after>'use strict';

var Auth = require('./Auth');
var Util = require('./Util');
var gcloud = require('gcloud');
var Q = require('q');
var path = require('path');
var fs = require('fs');

function Filestore(repoName) {
  this.name = repoName;
  this.bucketName = Util.makeBucketName(repoName);
  this.storage = gcloud.storage(Auth);
  this.bucket = this.storage.bucket(this.bucketName);
}

Filestore.prototype.save = function() {
  var args = Array.prototype.slice.call(arguments);
  var cb = args.pop();
  var fileOnDisk = args[args.length -1];
  args[0] = this.makeBranchName(args[0]);
  args[args.length - 1] = path.basename(args[args.length - 1]);
  var fullPath = args.join('/');
  this.persistFile(fileOnDisk, fullPath, cb);
};

Filestore.prototype.get = function(path, cb) {
  var file = this.bucket.file(path);
  file.download(cb);
};

Filestore.prototype.saveBuildNumberFile = function(branch, buildId, buildNumber, fileOnDisk, cb) {
  this.save.apply(this, arguments);
};

Filestore.prototype.saveBuildFile = function(branch, buildId, fileOnDisk, cb) {
  this.save.apply(this, arguments);
};

Filestore.prototype.saveBranchFile = function(branch, fileOnDisk, cb) {
  this.save.apply(this, arguments);
};

Filestore.prototype.saveRepoFile = function(fileOnDisk, cb) {
  this.persistFile(fileOnDisk, path.basename(fileOnDisk),  cb);
};

// Takes contents and saves it into a file named 'filename' for the build
Filestore.prototype.saveRunFile = function(buildId, buildNumber, filename, fileOnDisk, cb) {
  var me = this;
  this.getBranch(buildId, function(err, branch, safeBranch) {
    if (err) {
      cb(err);
    } else {
      var fullPath = path.join(safeBranch, String(buildId), String(buildNumber), filename);
      me.persistFile(fileOnDisk, fullPath, cb);
    }
  });
};

/*
 * All files in fileList are stored in the 'prefix' directory in the bucket
 */
Filestore.prototype.persistFiles = function(prefix, fileList, cb) {
  var me = this;
  // Array of function calls that return promises to save each file
  var promises = fileList.map(function(file) {
    return Q.ninvoke(me, 'persistFile', file, path.join(prefix, path.basename(file)));
  });
  Util.dealWithAllPromises(promises, cb);
};

Filestore.prototype.persistFile = function(from, to, cb) {
  var me = this;
  var options = {
    destination: to
  };
  this.storage.createBucket(this.bucketName, function(err, bucket) {
    if (err) {
      // Asume bucket already exists
      // TODO(trostler): verify that's true!
      bucket = me.storage.bucket(me.bucketName);
    }

    // Make bucket world-readable
    bucket.acl.default.add({
      entity: 'allUsers',
      role: me.storage.acl.READER_ROLE
    }, function(aerr /*, apiResponse*/) {
      if (aerr) {
        cb(aerr);
      } else {
        bucket.upload(from, options, cb);
      }
    });
  });
};

Filestore.prototype.makeBranchName = function(branch) {
  return ['branch', branch].join('-');
};

Filestore.prototype.getBasePublicURL = function(branch, buildId, buildNumber) {
  branch = this.makeBranchName(branch);
  return path.join(this.bucketName, branch, String(buildId), String(buildNumber));
};

Filestore.prototype.getFile = function(buildId, filePath, cb) {
  var me = this;
  this.getBranch(buildId, function(err, branch, safeBranch) {
    if (err) {
      cb(err);
    } else {
      var fullFilename = path.join(safeBranch, String(buildId), filePath);
      var file = me.bucket.file(fullFilename);
      file.download(cb);
    }
  });
};

Filestore.prototype.getLogFile = function(buildId, buildNumber, filename, cb) {
  var logFile = path.join(String(buildNumber), filename);
  this.getFile(buildId, logFile, cb);
};

Filestore.prototype.getMainLogFile = function(buildId, buildNumber, cb) {
  this.getLogFile(buildId, buildNumber, 'user-script.clean.log', cb);
};

Filestore.prototype.dealfest = function(err, cb, allItems, apiResponse, nextQuery, func) {
  if (err) {
    cb(err);
  } else {
    if (apiResponse.items) {
      allItems = allItems.concat(apiResponse.items.map(function(item) {
        return item.name;
      }));
    }
    if (!nextQuery) {
      cb(null, allItems);
    } else {
      func.call(this, null, cb, allItems, nextQuery);
    }
  }
};

Filestore.prototype.getFileList = function(filePath, cb, filesSoFar, nextQuery) {
  var query;
  if (!filesSoFar) {
    filesSoFar = [];
    query = {
      prefix: filePath,
      delimeter: '/'
    };
  }

  var me = this;
  this.bucket.getFiles(nextQuery || query, function(err, files, nextQ, apiResponse) {
    me.dealfest(err, cb, filesSoFar, apiResponse, nextQ, me.getFileList);
  });
};

Filestore.prototype.getBranches = function(cb) {
  var branches = {};
  this.getFileList('', function(err, fileList) {
    if (err) {
      cb(err);
    } else {
      fileList.forEach(function(fileName) {
        var regex = new RegExp('^branch-([^/]+)');
        var matches = regex.exec(fileName);
        if (matches) {
          branches[matches[1]] = 1;
        }
      });
      cb(null, Object.keys(branches));
    }
  });
};

Filestore.prototype.getBranchFileList = function(branch, cb) {
  var safeBranch = this.makeBranchName(branch);
  this.getFileList(safeBranch, cb);
};

Filestore.prototype.getBuildFileList = function(buildId, cb) {
  var me = this;
  this.getBranch(buildId, function(err, branch, safeBranch) {
    if (err) {
      cb(err);
    } else {
      var dirPath = path.join(safeBranch, String(buildId));
      me.getFileList(dirPath, cb);
    }
  });
};

Filestore.prototype.getRunFileList = function(buildId, buildNumber, cb) {
  var me = this;
  this.getBranch(buildId, function(err, branch, safeBranch) {
    if (err) {
      cb(err);
    } else {
      var dirPath = path.join(safeBranch, String(buildId), String(buildNumber));
      me.getFileList(dirPath, cb);
    }
  });
};

Filestore.prototype.deleteFile = function(filename, cb) {
  var file = this.bucket.file(filename);
  file.delete(cb);
};

Filestore.prototype.deleteFiles = function(fileList, cb) {
  var me = this;
  var promises = fileList.map(function(file) {
    return Q.ninvoke(me, 'deleteFile', file);
  });
  Util.dealWithAllPromises(promises, cb);
};

Filestore.prototype.deleteRunFiles = function(buildId, buildNumber, cb) {
  var me = this;
  this.getRunFileList(buildId, buildNumber, function(err, fileList) {
    if (err) {
      cb(err);
    } else {
      me.deleteFiles(fileList, cb);
    }
  });
};

// Not dangerous at all :)
Filestore.prototype.deleteAllBranches = function(cb) {
  var me = this;
  this.getBranches(function(err, branches) {
    if (err) {
      cb(err);
    } else {
      var promises = branches.map(function(branch) {
        return Q.ninvoke(me, 'deleteBranchFiles', branch);
      });
      Util.dealWithAllPromises(promises, cb);
    }
  });
};

Filestore.prototype.deleteBranchFiles = function(branch, cb) {
  var me = this;
  this.getBranchFileList(branch, function(err, fileList) {
    if (err) {
      cb(err);
    } else {
      me.deleteFiles(fileList, cb);
    }
  });
};

Filestore.prototype.deleteBuildFiles = function(buildId, cb) {
  var me = this;
  this.getBuildFileList(buildId, function(err, fileList) {
    if (err) {
      cb(err);
    } else {
      me.deleteFiles(fileList, cb);
    }
  });
};

Filestore.prototype.getBranch = function(buildId, cb) {
  var me = this;
  this.getFileList('', function(err, list) {
    if (err) {
      cb(err);
    } else {
      var branch = list.reduce(function(previous, fileName) {
        // try to match branch-(branch}/buildId
        if (previous) {
          return previous;
        }
        var regex = new RegExp('^branch-([^/]+)/' + buildId + '/');
        var matches = regex.exec(fileName);
        if (matches) {
          return matches[1];
        }
      }, '');
      if (!branch) {
        cb('Cannot find branch for buildId ' + buildId);
      } else {
        cb(null, branch, me.makeBranchName(branch));
      }
    }
  });
};

// Returns PROMISE
Filestore.prototype.savePrivateKey = function(branch, buildId, buildNumber, keyData, cb) {
  var tmpFile = path.join('/tmp', branch + buildId + buildNumber, 'private.key');
  if (!fs.existsSync(path.dirname(tmpFile))) {
    fs.mkdirSync(path.dirname(tmpFile));
  }
  fs.writeFileSync(tmpFile, keyData, 'utf8');
  return Q.ninvoke(this, 'saveBuildNumberFile', branch, buildId, buildNumber, tmpFile);
};

Filestore.prototype.getPrivateKey = function(buildId, buildNumber, cb) {
  this.getFile(buildId, path.join(String(buildNumber), 'private.key'), cb);
};

// Returns PROMISE
Filestore.prototype.saveStartupScript = function(branch, buildId, buildNumber, script, cb) {
  var tmpFile = path.join('/tmp', branch + buildId + buildNumber, 'startupScript.sh');
  if (!fs.existsSync(path.dirname(tmpFile))) {
    fs.mkdirSync(path.dirname(tmpFile));
  }
  fs.writeFileSync(tmpFile, script, 'utf8');
  return Q.ninvoke(this, 'saveBuildNumberFile', branch, buildId, buildNumber, tmpFile);
};

Filestore.prototype.getStartupScript = function(buildId, buildNumber, cb) {
  this.getFile(buildId, path.join(String(buildNumber), 'startupScript.sh'), cb);
};

Filestore.prototype.saveScriptAndPK = function(branch, buildId, buildNumber, script, pk) {
  var me = this;
  return this.saveStartupScript(branch, buildId, buildNumber, script)
  .then(function() {
    return me.savePrivateKey(branch, buildId, buildNumber, pk);
  });
};

module.exports = Filestore;
<|endoftext|>


<commit_before>/* global CKEDITOR */

/**
 * Define changes to default configuration here.
 * For the complete reference: http://docs.ckeditor.com/#!/api/CKEDITOR.config
 */

/**
 * @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

/**
 * Load any external plugins (i.e, plugins not bundled with CKEditor)
 */
CKEDITOR.plugins.addExternal('codemirror', window.NAILS.URL + 'js/ckeditor.plugins/codemirror/');
CKEDITOR.plugins.addExternal('mediaembed', window.NAILS.URL + 'js/ckeditor.plugins/mediaembed/');

/**
 * Set the contents of the "Styles" dropdown
 */
CKEDITOR.stylesSet.add(
    'nailsStyles',
    [
        {
            name: 'Preformatted',
            element: 'pre'
        },
        {
            name: 'Code Block',
            element: 'pre',
            attributes: {'class': 'code-block'}
        },
        {
            name: 'Big',
            element: 'big'
        },
        {
            name: 'Small',
            element: 'small'
        },
        {
            name: 'Computer Code',
            element: 'code'
        },
        {
            name: 'Variable',
            element: 'var'
        },
        {
            name: 'Deleted Text',
            element: 'del'
        },
        {
            name: 'Marker',
            element: 'mark'
        }
    ]
);

/**
 * Define the CSS to use in the content area
 * @type {String}
 */
CKEDITOR.config.contentsCss = window.NAILS.URL + 'css/nails.admin.ckeditor.css';

/**
 * Define the CKEditor config object
 */
CKEDITOR.editorConfig = function(config) {
    /**
     * The name of the styles object to show in the "Styles" dropdown
     * @type {String}
     */
    config.stylesSet = 'nailsStyles';

    /**
     * Additional plugins to enable
     * @type {String}
     */
    config.extraPlugins = 'justify,autogrow,mediaembed,codemirror,colorbutton,colordialog,font,image,pastefromword,iframe';

    /**
     * Plugins to remove
     * @type {String}
     */
    config.removePlugins = 'resize,elementspath';

    /**
     * The toolbar groups arrangement, optimized for a single toolbar row.
     * @type {Array}
     */
    config.toolbarGroups = [
        {
            name: 'document',
            groups: ['mode']
        },
        {
            name: 'styles',
            groups: ['']
        },
        {
            name: 'basicstyles',
            groups: ['basicstyles']
        },
        {
            name: 'colors'
        },
        {
            name: 'clipboard',
            groups: ['clipboard', 'undo']
        },
        {
            name: 'paragraph',
            groups: ['align', 'list', 'indent', 'blocks']
        },
        {
            name: 'links'
        },
        {
            name: 'insert',
            groups: ['mediaembed']
        },
        {
            name: 'tools'
        },
        {
            name: 'others'
        }
    ];

    /**
     * Any specific, individual, buttons to remove
     * @type {String}
     */
    config.removeButtons = 'Font';

    /**
     * Only allow certain formatting
     * @type {Object}
     */
    config.format_small = {
        element: 'small',
        name: 'Small'
    };

    /**
     * Only allow formatting on specific tags
     * @type {String}
     */
    config.format_tags = 'p;small;h1;h2;h3;h4;h5';

    /**
     * Allow the editor to define whatever classes the user wants on elements.
     * Same deal for data-* attributes
     * @type {Object}
     */
    config.extraAllowedContent = {
        '*': {
            classes: '*',
            attributes: 'data-*,id,clas'
        },
        'img': {
            attributes: '!width,!height'
        }
    };

    /**
     * Limit height of autoGrow plugin
     * @type {Number}
     */
    config.autoGrow_maxHeight = 500;

    /**
     * Considering that the basic setup doesn't provide pasting cleanup features,
     * it's recommended to force everything to be plain text.
     * @type {Boolean}
     */
    config.forcePasteAsPlainText = true;

    /**
     * Configure the CDN endpoints
     * @type {string}
     */
    config.filebrowserImageBrowseUrl = window.SITE_URL + 'admin/cdn/manager?isModal=1';
    config.filebrowserFlashBrowseUrl = window.SITE_URL + 'admin/cdn/manager?isModal=1';
    config.filebrowserBrowseUrl = window.SITE_URL + 'admin/cdn/manager?isModal=1';

    /**
     * Dialog colour; tie it in with the rest of admin
     * @type {String}
     */
    config.dialog_backgroundCoverColor = 'rgb(0,0,0)';
    config.dialog_backgroundCoverOpacity = 0.75;

    /**
     * Don't show codemirror buttons
     * @type {Object}
     */
    config.codemirror = {
        showSearchButton: false,
        showCommentButton: false,
        showFormatButton: false,
        showUncommentButton: false,
        showAutoCompleteButton: false
    };

    /**
     * Enable pasteformword prompt
     * @type {boolean}
     */
    config.pasteFromWordPromptCleanup = true;
};
<commit_msg>Using enhanced image plugin for ckeditor<commit_after>/* global CKEDITOR */

/**
 * Define changes to default configuration here.
 * For the complete reference: http://docs.ckeditor.com/#!/api/CKEDITOR.config
 */

/**
 * @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

/**
 * Load any external plugins (i.e, plugins not bundled with CKEditor)
 */
CKEDITOR.plugins.addExternal('codemirror', window.NAILS.URL + 'js/ckeditor.plugins/codemirror/');
CKEDITOR.plugins.addExternal('mediaembed', window.NAILS.URL + 'js/ckeditor.plugins/mediaembed/');

/**
 * Set the contents of the "Styles" dropdown
 */
CKEDITOR.stylesSet.add(
    'nailsStyles',
    [
        {
            name: 'Preformatted',
            element: 'pre'
        },
        {
            name: 'Code Block',
            element: 'pre',
            attributes: {'class': 'code-block'}
        },
        {
            name: 'Big',
            element: 'big'
        },
        {
            name: 'Small',
            element: 'small'
        },
        {
            name: 'Computer Code',
            element: 'code'
        },
        {
            name: 'Variable',
            element: 'var'
        },
        {
            name: 'Deleted Text',
            element: 'del'
        },
        {
            name: 'Marker',
            element: 'mark'
        }
    ]
);

/**
 * Define the CSS to use in the content area
 * @type {String}
 */
CKEDITOR.config.contentsCss = window.NAILS.URL + 'css/nails.admin.ckeditor.css';

/**
 * Define the CKEditor config object
 */
CKEDITOR.editorConfig = function(config) {
    /**
     * The name of the styles object to show in the "Styles" dropdown
     * @type {String}
     */
    config.stylesSet = 'nailsStyles';

    /**
     * Additional plugins to enable
     * @type {String}
     */
    config.extraPlugins = 'justify,autogrow,mediaembed,codemirror,colorbutton,colordialog,font,image2,pastefromword,iframe';

    /**
     * Plugins to remove
     * @type {String}
     */
    config.removePlugins = 'resize,elementspath,image';

    /**
     * The toolbar groups arrangement, optimized for a single toolbar row.
     * @type {Array}
     */
    config.toolbarGroups = [
        {
            name: 'document',
            groups: ['mode']
        },
        {
            name: 'styles',
            groups: ['']
        },
        {
            name: 'basicstyles',
            groups: ['basicstyles']
        },
        {
            name: 'colors'
        },
        {
            name: 'clipboard',
            groups: ['clipboard', 'undo']
        },
        {
            name: 'paragraph',
            groups: ['align', 'list', 'indent', 'blocks']
        },
        {
            name: 'links'
        },
        {
            name: 'insert',
            groups: ['mediaembed']
        },
        {
            name: 'tools'
        },
        {
            name: 'others'
        }
    ];

    /**
     * Any specific, individual, buttons to remove
     * @type {String}
     */
    config.removeButtons = 'Font';

    /**
     * Only allow certain formatting
     * @type {Object}
     */
    config.format_small = {
        element: 'small',
        name: 'Small'
    };

    /**
     * Only allow formatting on specific tags
     * @type {String}
     */
    config.format_tags = 'p;small;h1;h2;h3;h4;h5';

    /**
     * Allow the editor to define whatever classes the user wants on elements.
     * Same deal for data-* attributes
     * @type {Object}
     */
    config.extraAllowedContent = {
        '*': {
            classes: '*',
            attributes: 'data-*,id,clas'
        },
        'img': {
            attributes: '!width,!height'
        }
    };

    /**
     * Limit height of autoGrow plugin
     * @type {Number}
     */
    config.autoGrow_maxHeight = 500;

    /**
     * Considering that the basic setup doesn't provide pasting cleanup features,
     * it's recommended to force everything to be plain text.
     * @type {Boolean}
     */
    config.forcePasteAsPlainText = true;

    /**
     * Configure the CDN endpoints
     * @type {string}
     */
    config.filebrowserImageBrowseUrl = window.SITE_URL + 'admin/cdn/manager?isModal=1';
    config.filebrowserFlashBrowseUrl = window.SITE_URL + 'admin/cdn/manager?isModal=1';
    config.filebrowserBrowseUrl = window.SITE_URL + 'admin/cdn/manager?isModal=1';

    /**
     * Dialog colour; tie it in with the rest of admin
     * @type {String}
     */
    config.dialog_backgroundCoverColor = 'rgb(0,0,0)';
    config.dialog_backgroundCoverOpacity = 0.75;

    /**
     * Don't show codemirror buttons
     * @type {Object}
     */
    config.codemirror = {
        showSearchButton: false,
        showCommentButton: false,
        showFormatButton: false,
        showUncommentButton: false,
        showAutoCompleteButton: false
    };

    /**
     * Enable pasteformword prompt
     * @type {boolean}
     */
    config.pasteFromWordPromptCleanup = true;
};
<|endoftext|>


<commit_before>(function (undefined) {
    "use strict";

    var async = require("async"),
        assert = require("assert"),
        request = require('request'),
        fixture = require("./fixture.js");

    describe('HTTP access', function () {

        beforeEach(function (done) {
            fixture.install('tests-couchdb-logger-service', function (err) {
                try {
                    assert(!err);
                    fixture.populate(done);
                } catch (e) {
                    console.log(err);
                    done(e);
                }
            });
        });

        it('does rewriting to index page', function (done) {
            request(fixture.location() + '/_design/main/_rewrite/', function (err, response, body) {
                try {
                    assert(!err);
                    assert.strictEqual(0, body.indexOf('<!DOCTYPE html>'), body);
                    done();
                } catch (e) {
                    done(e);
                }
            });
        });

        it('provides limited list of events sorted by timestamp', function (done) {
            request(fixture.location() + '/_design/main/_rewrite/all/0/2', function (err, response, body) {
                try {
                    assert(!err);
                    assert.equal(2, JSON.parse(body).rows.length);
                    done();
                } catch (e) {
                    done(e);
                }
            });

        });

        it('provides list of first events sorted by timestamp', function (done) {
            request(fixture.location() + '/_design/main/_rewrite/all', function (err, response, body) {

                try {
                    assert(!err);
                    assert.equal(3, JSON.parse(body).rows.length);
                    done();
                } catch (e) {
                    done(e);
                }

            });

        });

        it('provides list of first events of a channel', function (done) {

            async.series([
                function (callback) {
                    fixture.addLogEntry({message: 'New message', channel: 'http.test'}, callback);
                },
                function (callback) {
                    request(fixture.location() + '/_design/main/_rewrite/all/http.test', function (err, response, body) {

                        try {
                            assert(!err);
                            assert.equal(1, JSON.parse(body).rows.length);
                            callback();
                        } catch (e) {
                            callback(e);
                        }

                    });
                }
            ], done);

        });

        it('has an entry for registering new events', function (done) {

            request({
                    method: 'POST',
                    uri: fixture.location() + '/_design/main/_rewrite/new',
                    body: JSON.stringify(fixture.validLogEntry)
                },
                function (err, response, body) {
                    try {
                        assert(!err);
                        assert.strictEqual(true, JSON.parse(body).ok);
                        done();
                    } catch (e) {
                        done(e);
                    }
                }
            );

        });

        it('gives a document by its ID', function (done) {
            request(fixture.location() + '/_all_docs', function (err, response, body) {
                var docId = JSON.parse(body).rows[0].id;

                request(fixture.location() + '/_design/main/_rewrite/record/' + docId, function (err, response, body) {

                    try {
                        assert(!err);
                        assert.deepEqual(
                            ["_id","_rev","message","channel","timestamp"],
                            Object.keys(JSON.parse(body)),
                            body
                        );
                        done();
                    } catch (e) {
                        done(e);
                    }
                });
            });
        });
    });

}());<commit_msg>Fix the broken http.test.js by filtering out the _design/main from _all_docs<commit_after>(function (undefined) {
    "use strict";

    var async = require("async"),
        assert = require("assert"),
        request = require('request'),
        fixture = require("./fixture.js");

    describe('HTTP access', function () {

        beforeEach(function (done) {
            fixture.install('tests-couchdb-logger-service', function (err) {
                try {
                    assert(!err);
                    fixture.populate(done);
                } catch (e) {
                    console.log(err);
                    done(e);
                }
            });
        });

        it('does rewriting to index page', function (done) {
            request(fixture.location() + '/_design/main/_rewrite/', function (err, response, body) {
                try {
                    assert(!err);
                    assert.strictEqual(0, body.indexOf('<!DOCTYPE html>'), body);
                    done();
                } catch (e) {
                    done(e);
                }
            });
        });

        it('provides limited list of events sorted by timestamp', function (done) {
            request(fixture.location() + '/_design/main/_rewrite/all/0/2', function (err, response, body) {
                try {
                    assert(!err);
                    assert.equal(2, JSON.parse(body).rows.length);
                    done();
                } catch (e) {
                    done(e);
                }
            });

        });

        it('provides list of first events sorted by timestamp', function (done) {
            request(fixture.location() + '/_design/main/_rewrite/all', function (err, response, body) {

                try {
                    assert(!err);
                    assert.equal(3, JSON.parse(body).rows.length);
                    done();
                } catch (e) {
                    done(e);
                }

            });

        });

        it('provides list of first events of a channel', function (done) {

            async.series([
                function (callback) {
                    fixture.addLogEntry({message: 'New message', channel: 'http.test'}, callback);
                },
                function (callback) {
                    request(fixture.location() + '/_design/main/_rewrite/all/http.test', function (err, response, body) {

                        try {
                            assert(!err);
                            assert.equal(1, JSON.parse(body).rows.length);
                            callback();
                        } catch (e) {
                            callback(e);
                        }

                    });
                }
            ], done);

        });

        it('has an entry for registering new events', function (done) {

            request({
                    method: 'POST',
                    uri: fixture.location() + '/_design/main/_rewrite/new',
                    body: JSON.stringify(fixture.validLogEntry)
                },
                function (err, response, body) {
                    try {
                        assert(!err);
                        assert.strictEqual(true, JSON.parse(body).ok);
                        done();
                    } catch (e) {
                        done(e);
                    }
                }
            );

        });

        it('gives a document by its ID', function (done) {
            request(fixture.location() + '/_all_docs', function (err, response, body) {
                var docId = JSON.parse(body).rows.filter(
                        function (row) { return row.id[0] !== '_'; }
                    )[0].id;

                request(
                    fixture.location() + '/_design/main/_rewrite/record/' + docId,

                    function (err, response, body) {
                        try {
                            assert(!err);

                            assert.deepEqual(
                                ['_id', '_rev', 'message', 'channel', 'timestamp'],
                                Object.keys(JSON.parse(body)),
                                body
                            );

                            done();
                        }
                        catch (e) {
                            done(e);
                        }
                    }
                );
            });
        });
    });
}());
<|endoftext|>


<commit_before>'use strict';

var assert = require('chai').assert,
    ST = require('../subtask.js');

describe('subtask.before()', function () {
    it('should return a new task creator', function (done) {
        var st = ST.before(function () {}, function () {});
        assert.equal('function', typeof st);
        assert.equal(true, ST.isSubtask(st()));
        done();
    });

    it('should keep original task context', function (done) {
        var originalTask = function () {
            var task = ST(1);
            task.test ='OK';
            return task;
        },
        newTask = ST.before(originalTask, function () {
            assert.equal('O!', this.test);
        });

        newTask.apply({test: 'O!'}).execute(function () {
            assert.equal('OK', this.test);
            done();
        });
    });

    it('should return task by return new task', function (done) {
        var originalTask = function () {
            var task = ST(1);
            task.test ='OK';
            return task;
        },
        newTask = ST.before(originalTask, function (task, args) {
            if (args.length && args[0]) {
                return ST(args[0] * 2);
            }
        });

        newTask(0).execute(function (R) {
            assert.equal(1, R);
            assert.equal('OK', this.test);
            newTask(1).execute(function (R) {
                assert.equal(2, R);
                assert.equal(undefined, this.test);
                done();
            });
        });
    });

    it('should create task by return values', function (done) {
        var originalTask = function () {
            var task = ST(1);
            task.test ='OK';
            return task;
        },
        newTask = ST.before(originalTask, function (task, I) {
            return {a: 1, b: 2};
        });

        newTask(0).execute(function (R) {
            assert.deepEqual({a: 1, b: 2}, R);
            assert.equal(undefined, this.test);
            done();
        });
    });
});
<commit_msg>test change context on .before()<commit_after>'use strict';

var assert = require('chai').assert,
    ST = require('../subtask.js');

describe('subtask.before()', function () {
    it('should return a new task creator', function (done) {
        var st = ST.before(function () {}, function () {});
        assert.equal('function', typeof st);
        assert.equal(true, ST.isSubtask(st()));
        done();
    });

    it('should keep original task context', function (done) {
        var originalTask = function () {
            var task = ST(1);
            task.test ='OK';
            return task;
        },
        newTask = ST.before(originalTask, function () {
            assert.equal('O!', this.test);
        });

        newTask.apply({test: 'O!'}).execute(function () {
            assert.equal('OK', this.test);
            done();
        });
    });

    it('should use another task context', function (done) {
        var originalTask = function () {
            var task = ST(1);
            task.test ='OK';
            return task;
        },
        newTask = ST.before(originalTask, function () {
            assert.equal('K~', this.test);
        }, {test: 'K~'});

        newTask.apply({test: 'O!'}).execute(function () {
            assert.equal('OK', this.test);
            done();
        });
    });

    it('should return task by return new task', function (done) {
        var originalTask = function () {
            var task = ST(1);
            task.test ='OK';
            return task;
        },
        newTask = ST.before(originalTask, function (task, args) {
            if (args.length && args[0]) {
                return ST(args[0] * 2);
            }
        });

        newTask(0).execute(function (R) {
            assert.equal(1, R);
            assert.equal('OK', this.test);
            newTask(1).execute(function (R) {
                assert.equal(2, R);
                assert.equal(undefined, this.test);
                done();
            });
        });
    });

    it('should create task by return values', function (done) {
        var originalTask = function () {
            var task = ST(1);
            task.test ='OK';
            return task;
        },
        newTask = ST.before(originalTask, function (task, I) {
            return {a: 1, b: 2};
        });

        newTask(0).execute(function (R) {
            assert.deepEqual({a: 1, b: 2}, R);
            assert.equal(undefined, this.test);
            done();
        });
    });
});
<|endoftext|>


<commit_before>var _    = require('lodash'),
    fs   = require('fs'),
    exec = require('child_process').exec

module.exports = helpers = {

  capitalize: function(string) {

    return string.charAt(0).toUpperCase() + string.slice(1);

  },

  creators: {

    nameAndPath: function(type) {

      var name     = helpers.slugify(this.name),
          pathType = type;

      if(type == 'collection') {
        pathType = 'model';
      }

      if(type == 'collectionview') {
        pathType = 'view';
      }

      if(this.path) {

        if(type == 'template') {
          this.copy('index.hbs', 'app/templates/' + this.path + '/' + name + '.hbs')
        }

        else {
          this.template('_' + type + '.coffee', 'app/' + pathType + 's/' + this.path + '/' + name + '.coffee');
        }

      }

      else {

        if(type == 'template') {
          this.copy('index.hbs', 'app/templates/' + name + '.hbs')
        }

        else {
          this.template('_' + type + '.coffee', 'app/' + pathType + 's/' + name + '.coffee');
        }

      }

    }

  },

  generators: {

    nameAndPath: function() {

      if(this.name.indexOf('/') > -1) {

        var s = this.name.lastIndexOf('/'),
            p = this.name.substring(0, s),
            n = this.name.split('/').pop()

        this.name = n;
        this.path = p;
      }

      else {
        this.path = null;
      }

    }
  },

  deleteCurrentFolder: function() {

    var currentFolder = process.cwd().split('/').pop()

    exec('rm -rfv ' + process.cwd() + '/*')

  },

  slugify: function (str) {

    str = str.replace(/^\s+|\s+$/g, ''); // trim
    str = str.toLowerCase();

    var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;";
    var to   = "aaaaeeeeiiiioooouuuunc------";
    for (var i=0, l=from.length ; i<l ; i++) {
      str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
    }

    str = str.replace(/[^a-z0-9 -]/g, '')
      .replace(/\s+/g, '-')
      .replace(/-+/g, '-');

    return str;

  }

}
<commit_msg>Actually remove everything.<commit_after>var _    = require('lodash'),
    fs   = require('fs'),
    exec = require('child_process').exec

module.exports = helpers = {

  capitalize: function(string) {

    return string.charAt(0).toUpperCase() + string.slice(1);

  },

  creators: {

    nameAndPath: function(type) {

      var name     = helpers.slugify(this.name),
          pathType = type;

      if(type == 'collection') {
        pathType = 'model';
      }

      if(type == 'collectionview') {
        pathType = 'view';
      }

      if(this.path) {

        if(type == 'template') {
          this.copy('index.hbs', 'app/templates/' + this.path + '/' + name + '.hbs')
        }

        else {
          this.template('_' + type + '.coffee', 'app/' + pathType + 's/' + this.path + '/' + name + '.coffee');
        }

      }

      else {

        if(type == 'template') {
          this.copy('index.hbs', 'app/templates/' + name + '.hbs')
        }

        else {
          this.template('_' + type + '.coffee', 'app/' + pathType + 's/' + name + '.coffee');
        }

      }

    }

  },

  generators: {

    nameAndPath: function() {

      if(this.name.indexOf('/') > -1) {

        var s = this.name.lastIndexOf('/'),
            p = this.name.substring(0, s),
            n = this.name.split('/').pop()

        this.name = n;
        this.path = p;
      }

      else {
        this.path = null;
      }

    }
  },

  deleteCurrentFolder: function() {

    var currentFolder = process.cwd().split('/').pop()

    exec('rm -rf ' + process.cwd() + '/*')

  },

  slugify: function (str) {

    str = str.replace(/^\s+|\s+$/g, ''); // trim
    str = str.toLowerCase();

    var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;";
    var to   = "aaaaeeeeiiiioooouuuunc------";
    for (var i=0, l=from.length ; i<l ; i++) {
      str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
    }

    str = str.replace(/[^a-z0-9 -]/g, '')
      .replace(/\s+/g, '-')
      .replace(/-+/g, '-');

    return str;

  }

}
<|endoftext|>


<commit_before>$(document).ready(
	function()
	{
		$('#accounts_tbl').DataTable(accounts_table);

		// add account btn
		$('.btn[data-action=add_account]').on('click',
			function(e)
			{
				var $btn = $(this);
				var $loading = $('
 Loading
');

				ajaxRequest({
					url: baseurl+'page/fragment',
					method: 'GET',
					timeout: 3000,
					data:
					{
						fragment: 'new_account'
					},
					beforeSend: function()
					{
						$('#action_modal').html($loading);
					}
				})
				.done(
					function(result)
					{
						$('#action_modal')
							.html(result)
								.find('input[name=acct_name]')
								.trigger('focus');

						$('#action_modal')
							.find('input')
							.filter(
							function(idx)
							{
								var val = $(this).val();
								var name = $(this).attr('name');

								switch(name)
								{
									case 'acct_name':
										$(this).filter_input({regex: '[a-zA-Z|-]'});
										break;

									case 'initial_amt':
										$(this).inputmask({
											alias: 'decimal',
											autoUnmask: true,
											digits: 2,
											groupSeparator: ',',
											autoGroup: true
										});
										break;
								}
							});
					})
				.fail(
					function(a,b,c)
					{
						$('#action_modal').modal('hide');
					});
			});

		// validation of availability of account name
		var acct_name_timer;
		$('#action_modal').on('keyup','input[name=acct_name]',
			function()
			{
				var val = $(this).val();
				var $indicator = $('#action_modal').find('.fa[data-indicator=valid_name]');

				// hide check/X
				$indicator.addClass('hidden');

				// remove "account name not available"
				$('#action_modal')
					.find('.help-block[data-name=acct_name] > .label')
					.empty();

				if( ! val)
				{
					clearTimeout(acct_name_timer);
					return false;
				}

				if(acct_name_timer)
				{
					clearTimeout(acct_name_timer);
				}

				acct_name_timer = setTimeout(
					function()
					{
						ajaxRequest({
								url: baseurl+'savings_monitor/account/search',
								method: 'GET',
								data:
								{
									verify_only: true,
									acct_name: val
								}
							},true)
						.done(
							function(result)
							{
								if(typeof result === 'boolean')
								{
									var $indicator = $('#action_modal').find('.fa[data-indicator=valid_name]');
									// valid flag
									$('#action_modal').find('input[name=acct_name]').data('is_valid',result===false);

									// show indicator of valid/invalid account name
									$indicator.removeClass('hidden')
										[ ! result ? 'removeClass' : 'addClass' ]('fa-remove text-red')
										[ ! result ? 'addClass' : 'removeClass' ]('fa-check text-green');

									if(result===true)
									{
										$('#action_modal')
											.find('.help-block[data-name=acct_name] > .label')
											.html('Account name not available.');
									}
								}
								else
								{
									$('#action_modal')
											.find('.help-block[data-name=acct_name] > .label')
											.html('An error occurred.');
								}
							});
					},1000);
			})
		// save btn
		.on('click','.btn[data-action=save]',
			function()
			{
				var $modal = $('#action_modal');
				var name_val = $modal.find('input[name=acct_name]').val();
				var name_is_valid = ($modal.find('input[name=acct_name]').data('is_valid') === true);
				var account_data =
				{
					name: $modal.find('input[name=acct_name]').val(),
					amt: $modal.find('input[name=initial_amt]').val(),
				};

				if( ! name_is_valid)
				{
					$('#action_modal')
						.find('.help-block[data-name=acct_name] > .label')
						.html(name_val ? 'Account name not available.' : 'Name cannot be blank.');

				}
				else
				{
					ajaxRequest({
						url: baseurl+'savings_monitor/account/new',
						data: account_data
					})
					.done(
						function(result)
						{
							if(result['success'])
							{
								$('#page_alert')
									.slideDown()
									.delay(4000)
									.slideUp()
									.attr('class',result['success'] ? 'alert alert-success' : 'alert alert-danger')
									.html((result['success'] ? ' ' : ' ')+(result['msg'] ? result['msg'] : 'An error occurred.'));
							}
							else
							{

							}
						});
				}
			});

	});
<commit_msg>Fixed some URLs for accounts<commit_after>$(document).ready(
	function()
	{
		$('#accounts_tbl').DataTable(accounts_table);

		// add account btn
		$('.btn[data-action=add_account]').on('click',
			function(e)
			{
				var $btn = $(this);
				var $loading = $('
 Loading
');

				ajaxRequest({
					url: baseurl+'page/fragment',
					method: 'GET',
					timeout: 3000,
					data:
					{
						fragment: 'new_account'
					},
					beforeSend: function()
					{
						$('#action_modal').html($loading);
					}
				})
				.done(
					function(result)
					{
						$('#action_modal')
							.html(result)
								.find('input[name=acct_name]')
								.trigger('focus');

						$('#action_modal')
							.find('input')
							.filter(
							function(idx)
							{
								var val = $(this).val();
								var name = $(this).attr('name');

								switch(name)
								{
									case 'acct_name':
										$(this).filter_input({regex: '[a-zA-Z|-]'});
										break;

									case 'initial_amt':
										$(this).inputmask({
											alias: 'decimal',
											autoUnmask: true,
											digits: 2,
											groupSeparator: ',',
											autoGroup: true
										});
										break;
								}
							});
					})
				.fail(
					function(a,b,c)
					{
						$('#action_modal').modal('hide');
					});
			});

		// validation of availability of account name
		var acct_name_timer;
		$('#action_modal').on('keyup','input[name=acct_name]',
			function()
			{
				var val = $(this).val();
				var $indicator = $('#action_modal').find('.fa[data-indicator=valid_name]');

				// hide check/X
				$indicator.addClass('hidden');

				// remove "account name not available"
				$('#action_modal')
					.find('.help-block[data-name=acct_name] > .label')
					.empty();

				if( ! val)
				{
					clearTimeout(acct_name_timer);
					return false;
				}

				if(acct_name_timer)
				{
					clearTimeout(acct_name_timer);
				}

				acct_name_timer = setTimeout(
					function()
					{
						ajaxRequest({
								url: '/web_service/accounts/search',
								method: 'GET',
								data:
								{
									verify_only: true,
									acct_name: val
								}
							},true)
						.done(
							function(result)
							{
								if(typeof result === 'boolean')
								{
									var $indicator = $('#action_modal').find('.fa[data-indicator=valid_name]');
									// valid flag
									$('#action_modal').find('input[name=acct_name]').data('is_valid',result===false);

									// show indicator of valid/invalid account name
									$indicator.removeClass('hidden')
										[ ! result ? 'removeClass' : 'addClass' ]('fa-remove text-red')
										[ ! result ? 'addClass' : 'removeClass' ]('fa-check text-green');

									if(result===true)
									{
										$('#action_modal')
											.find('.help-block[data-name=acct_name] > .label')
											.html('Account name not available.');
									}
								}
								else
								{
									$('#action_modal')
											.find('.help-block[data-name=acct_name] > .label')
											.html('An error occurred.');
								}
							});
					},1000);
			})
		// save btn
		.on('click','.btn[data-action=save]',
			function()
			{
				var $modal = $('#action_modal');
				var name_val = $modal.find('input[name=acct_name]').val();
				var name_is_valid = ($modal.find('input[name=acct_name]').data('is_valid') === true);
				var account_data =
				{
					name: $modal.find('input[name=acct_name]').val(),
					amt: $modal.find('input[name=initial_amt]').val(),
				};

				if( ! name_is_valid)
				{
					$('#action_modal')
						.find('.help-block[data-name=acct_name] > .label')
						.html(name_val ? 'Account name not available.' : 'Name cannot be blank.');

				}
				else
				{
					ajaxRequest({
						url: '/web_service/accounts/create',
						data: account_data
					})
					.done(
						function(result)
						{
							if(result['success'])
							{
								$('#page_alert')
									.slideDown()
									.delay(4000)
									.slideUp()
									.attr('class',result['success'] ? 'alert alert-success' : 'alert alert-danger')
									.html((result['success'] ? ' ' : ' ')+(result['msg'] ? result['msg'] : 'An error occurred.'));
							}
							else
							{

							}
						});
				}
			});

	});
<|endoftext|>


<commit_before>import tryFn from './tryFn';

export default function concat(collection, iteratee) {
    let
        results = [];

    return Promise.all(collection.map((item, index, collection) => {
        return tryFn(iteratee, item, index, collection)
            .then((result) => results.push(...result));
    }))
        .then(() => results);
};<commit_msg>Update async.concat so that the results are guarenteed in order.<commit_after>import tryFn from './tryFn';

export default function concat(collection, iteratee) {
    return Promise.all(collection.map((...args) => tryFn(iteratee, ...args)))
        .then((results) => results.reduce((result, item) => result.concat(item), []));
};
<|endoftext|>