<commit_before>define([
    "backbone",
    "activity/Activity",
    "datum/Datum",
    "datum/Datums",
    "comment/Comment",
    "comment/Comments"
], function(
    Backbone,
    Activity,
    Datum,
    Datums,
    Comment,
    Comments
) {
  var DataList = Backbone.Model.extend(
  /** @lends DataList.prototype */
  {
    /**
     * @class The Data List widget is used for import search, to prepare handouts and to share data on the web.
     *
     * @description
     *
     * @property {String} title The title of the Data List.
     * @property {String} dateCreated The date that this Data List was created.
     * @property {String} description The description of the Data List.
     * @property {Array<String>} datumIds An ordered list of the datum IDs of the
     *   Datums in the Data List.
     *
     * @extends Backbone.Model
     * @constructs
     */
    initialize : function() {
      // If there are no comments, give it a new one
      if (!this.get("comments")) {
        this.set("comments", new Comments());
      }

      if (!this.get("dateCreated")) {
        this.set("dateCreated", (new Date()).toDateString());
      }
    },

    defaults : {
      title : "Untitled Data List",
      description : "",
      datumIds : []
    },

    // Internal models: used by the parse function
    model : {
      comments: Comments
    },

    changeCorpus : function(corpusname, callback) {
      if(!corpusname){
        corpusname = this.get("corpusname");
        if(corpusname == undefined){
          corpusname = window.app.get("corpus").get("corpusname");
        }
      }
      if(this.pouch == undefined){
        this.pouch = Backbone.sync.pouch(Utils.androidApp() ? Utils.touchUrl + corpusname : Utils.pouchUrl + corpusname);
      }
      if(typeof callback == "function"){
        callback();
      }
    },

    /**
     * Create a permanent data list in the current corpus.
     *
     * @param callback
     */
    newDataList : function(callback) {
      //save the current data list
      var self = this;
      this.saveAndInterConnectInApp(function(){
        //clone it
        var attributes = JSON.parse(JSON.stringify(self.attributes));
        // Clear the current data list's backbone info and info which we shouldnt clone
        attributes._id = undefined;
        attributes._rev = undefined;
        attributes.comments = undefined;
        attributes.title = self.get("title")+ " copy";
        attributes.description = "Copy of: "+self.get("description");
        attributes.corpusname = app.get("corpus").get("corpusname");
        attributes.datumIds = [];
        self = new DataList(attributes);

        //TODO see if this destroys the collection in the default data list, technically it doesn't matter because this will need to be emptied and filled,a and the collciton is just part of the view, not part of the data list.
        var coll = self.datumsView.collection;
        while (coll.length > 0) {
          coll.pop();
        }

        // Display the new data list
//        appView.renderReadonlyDataListViews();
//        appView.renderEditableDataListViews();
        //Why call all data lists to render?
        self.render();
        self.saveAndInterConnectInApp(function(){
          //TOOD check this, this is used by the import to make the final datalist
          self.setAsCurrentDataList(function(){
            if(typeof callback == "function"){
              callback();
            }
          });
        });
      });
    },

    /**
     * Accepts two functions to call back when save is successful or
     * fails. If the fail callback is not overridden it will alert
     * failure to the user.
     *
     * - Adds the dataList to the corpus if it is in the right corpus, and wasnt already there
     * - Adds the dataList to the user if it wasn't already there
     * - Adds an activity to the logged in user with diff in what the user changed.
     *
     * @param successcallback
     * @param failurecallback
     */
    saveAndInterConnectInApp : function(successcallback, failurecallback){
      Utils.debug("Saving the DataList");
      var self = this;
      var idsInCollection = [];
      for(d in this.datumCollection.models){
        idsInCollection.push( this.datumCollection.models[d] );
      }
      this.set("datumIds", idsInCollection);
      var newModel = true;
      if(this.id){
        newModel = false;
      }
      //protect against users moving dataLists from one corpus to another on purpose or accidentially
      if(window.app.get("corpus").get("corpusname") != this.get("corpusname")){
        if(typeof failurecallback == "function"){
          failurecallback();
        }else{
          alert('DataList save error. I cant save this dataList in this corpus, it belongs to another corpus. ' );
        }
        return;
      }
      var oldrev = this.get("_rev");
      this.changeCorpus(null, function(){
        self.save(null, {
          success : function(model, response) {
            Utils.debug('DataList save success');
            var title = model.get("title");
            var differences = ""+title+"";
            //TODO add privacy for dataList in corpus
//            if(window.app.get("corpus").get("keepDataListDetailsPrivate")){
//              title = "";
//              differences = "";
//            }
            if(window.appView){
              window.appView.toastUser("Sucessfully saved data list: "+ title,"alert-success","Saved!");
              window.appView.addSavedDoc(model.id);
            }
            var verb = "updated";
            if(newModel){
              verb = "added";
            }
            window.app.get("authentication").get("userPrivate").get("activities").unshift(
                new Activity({
                  verb : verb,
                  directobject : "dataList ",
                  indirectobject : "in "+window.app.get("corpus").get("title"),
                  context : differences+" via Offline App.",
                  user: window.app.get("authentication").get("userPublic")
                }));

            //make sure the dataList is in this corpus, if it is the same corpusname
            if(window.app.get("corpus").get("dataLists").get(model.id) == undefined && window.app.get("corpus").get("corpusname") == model.get("corpusname")){
              window.app.get("corpus").get("dataLists").unshift(model);
              window.appView.addUnsavedDoc(window.app.get("corpus").id);
            }
            //make sure the dataList is in the history of the user
            if(window.app.get("authentication").get("userPrivate").get("dataLists").indexOf(model.id) == -1){
              window.app.get("authentication").get("userPrivate").get("dataLists").unshift(model.id);
              window.app.get("authentication").saveAndInterConnectInApp();
            }

            if(typeof successcallback == "function"){
              successcallback();
            }
          },
          error : function(e) {
            if(typeof failurecallback == "function"){
              failurecallback();
            }else{
              alert('DataList save error' + e);
            }
          }
        });
      });
    },
    /**
     * Accepts two functions success will be called if successful,
     * otherwise it will attempt to render the current dataList views. If
     * the dataList isn't in the current corpus it will call the fail
     * callback or it will alert a bug to the user. Override the fail
     * callback if you don't want the alert.
     *
     * @param successcallback
     * @param failurecallback
     */
    setAsCurrentDataList : function(successcallback, failurecallback){
      if( window.app.get("corpus").get("corpusname") != this.get("corpusname") ){
        if (typeof failurecallback == "function") {
          failurecallback();
        }else{
          alert("This is a bug, cannot load the dataList you asked for, it is not in this corpus.");
        }
        return;
      }else{
        if (window.app.get("currentDataList").id != this.id ) {
          window.app.set("currentDataList", this);
        }
        window.app.get("authentication").get("userPrivate").get("mostRecentIds").datalistid = this.id;
        window.app.get("authentication").saveAndInterConnectInApp();

        try{
          window.appView.setUpAndAssociateViewsAndModelsWithCurrentDataList(function() {
            if (typeof successcallback == "function") {
              successcallback();
            }else{
              //TODO remove this when done debugging and it is working all the time.
              var self = this;
              window.appView.toastUser("Sucessfully connected all views up to data list: "+ self.id,"alert-success","Connected!");
//            window.appView.renderEditableDataListViews();
//            window.appView.renderReadonlyDataListViews();
            }
          });
        }catch(e){
          if (typeof failurecallback == "function") {
            failurecallback();
          }else{
            alert("This is probably a bug. There was a problem rendering the current dataList's views after resetting the current session.");
          }
        }
      }
    }
  });

  return DataList;
});
<commit_msg>Stop propagation worked, getting a good work flow for the datums container<commit_after>define([
    "backbone",
    "activity/Activity",
    "datum/Datum",
    "datum/Datums",
    "comment/Comment",
    "comment/Comments"
], function(
    Backbone,
    Activity,
    Datum,
    Datums,
    Comment,
    Comments
) {
  var DataList = Backbone.Model.extend(
  /** @lends DataList.prototype */
  {
    /**
     * @class The Data List widget is used for import search, to prepare handouts and to share data on the web.
     *
     * @description
     *
     * @property {String} title The title of the Data List.
     * @property {String} dateCreated The date that this Data List was created.
     * @property {String} description The description of the Data List.
     * @property {Array<String>} datumIds An ordered list of the datum IDs of the
     *   Datums in the Data List.
     *
     * @extends Backbone.Model
     * @constructs
     */
    initialize : function() {
      // If there are no comments, give it a new one
      if (!this.get("comments")) {
        this.set("comments", new Comments());
      }

      if (!this.get("dateCreated")) {
        this.set("dateCreated", (new Date()).toDateString());
      }
    },

    defaults : {
      title : "Untitled Data List",
      description : "",
      datumIds : []
    },

    // Internal models: used by the parse function
    model : {
      comments: Comments
    },

    changeCorpus : function(corpusname, callback) {
      if(!corpusname){
        corpusname = this.get("corpusname");
        if(corpusname == undefined){
          corpusname = window.app.get("corpus").get("corpusname");
        }
      }
      if(this.pouch == undefined){
        this.pouch = Backbone.sync.pouch(Utils.androidApp() ? Utils.touchUrl + corpusname : Utils.pouchUrl + corpusname);
      }
      if(typeof callback == "function"){
        callback();
      }
    },

    /**
     * Create a permanent data list in the current corpus.
     *
     * @param callback
     */
    newDataList : function(callback) {
      //save the current data list
      var self = this;
      this.saveAndInterConnectInApp(function(){
        //clone it
        var attributes = JSON.parse(JSON.stringify(self.attributes));
        // Clear the current data list's backbone info and info which we shouldnt clone
        attributes._id = undefined;
        attributes._rev = undefined;
        attributes.comments = undefined;
        attributes.title = self.get("title")+ " copy";
        attributes.description = "Copy of: "+self.get("description");
        attributes.corpusname = app.get("corpus").get("corpusname");
        attributes.datumIds = [];
        self = new DataList(attributes);

        //TODO see if this destroys the collection in the default data list, technically it doesn't matter because this will need to be emptied and filled,a and the collciton is just part of the view, not part of the data list.
        var coll = self.datumsView.collection;
        while (coll.length > 0) {
          coll.pop();
        }

        // Display the new data list
//        appView.renderReadonlyDataListViews();
//        appView.renderEditableDataListViews();
        //Why call all data lists to render?
        self.render();
        self.saveAndInterConnectInApp(function(){
          //TOOD check this, this is used by the import to make the final datalist
          self.setAsCurrentDataList(function(){
            if(typeof callback == "function"){
              callback();
            }
          });
        });
      });
    },

    /**
     * Accepts two functions to call back when save is successful or
     * fails. If the fail callback is not overridden it will alert
     * failure to the user.
     *
     * - Adds the dataList to the corpus if it is in the right corpus, and wasnt already there
     * - Adds the dataList to the user if it wasn't already there
     * - Adds an activity to the logged in user with diff in what the user changed.
     *
     * @param successcallback
     * @param failurecallback
     */
    saveAndInterConnectInApp : function(successcallback, failurecallback){
      Utils.debug("Saving the DataList");
      var self = this;
//      var idsInCollection = [];
//      for(d in this.datumCollection.models){
//        idsInCollection.push( this.datumCollection.models[d] );
//      }
//      this.set("datumIds", idsInCollection);
      var newModel = true;
      if(this.id){
        newModel = false;
      }
      //protect against users moving dataLists from one corpus to another on purpose or accidentially
      if(window.app.get("corpus").get("corpusname") != this.get("corpusname")){
        if(typeof failurecallback == "function"){
          failurecallback();
        }else{
          alert('DataList save error. I cant save this dataList in this corpus, it belongs to another corpus. ' );
        }
        return;
      }
      var oldrev = this.get("_rev");
      this.changeCorpus(null, function(){
        self.save(null, {
          success : function(model, response) {
            Utils.debug('DataList save success');
            var title = model.get("title");
            var differences = ""+title+"";
            //TODO add privacy for dataList in corpus
//            if(window.app.get("corpus").get("keepDataListDetailsPrivate")){
//              title = "";
//              differences = "";
//            }
            if(window.appView){
              window.appView.toastUser("Sucessfully saved data list: "+ title,"alert-success","Saved!");
              window.appView.addSavedDoc(model.id);
            }
            var verb = "updated";
            if(newModel){
              verb = "added";
            }
            window.app.get("authentication").get("userPrivate").get("activities").unshift(
                new Activity({
                  verb : verb,
                  directobject : "dataList ",
                  indirectobject : "in "+window.app.get("corpus").get("title"),
                  context : differences+" via Offline App.",
                  user: window.app.get("authentication").get("userPublic")
                }));

            //make sure the dataList is in this corpus, if it is the same corpusname
            if(window.app.get("corpus").get("dataLists").get(model.id) == undefined && window.app.get("corpus").get("corpusname") == model.get("corpusname")){
              window.app.get("corpus").get("dataLists").unshift(model);
              window.appView.addUnsavedDoc(window.app.get("corpus").id);
            }
            //make sure the dataList is in the history of the user
            if(window.app.get("authentication").get("userPrivate").get("dataLists").indexOf(model.id) == -1){
              window.app.get("authentication").get("userPrivate").get("dataLists").unshift(model.id);
              window.app.get("authentication").saveAndInterConnectInApp();
            }

            if(typeof successcallback == "function"){
              successcallback();
            }
          },
          error : function(e) {
            if(typeof failurecallback == "function"){
              failurecallback();
            }else{
              alert('DataList save error' + e);
            }
          }
        });
      });
    },
    /**
     * Accepts two functions success will be called if successful,
     * otherwise it will attempt to render the current dataList views. If
     * the dataList isn't in the current corpus it will call the fail
     * callback or it will alert a bug to the user. Override the fail
     * callback if you don't want the alert.
     *
     * @param successcallback
     * @param failurecallback
     */
    setAsCurrentDataList : function(successcallback, failurecallback){
      if( window.app.get("corpus").get("corpusname") != this.get("corpusname") ){
        if (typeof failurecallback == "function") {
          failurecallback();
        }else{
          alert("This is a bug, cannot load the dataList you asked for, it is not in this corpus.");
        }
        return;
      }else{
        if (window.app.get("currentDataList").id != this.id ) {
          window.app.set("currentDataList", this);
        }
        window.app.get("authentication").get("userPrivate").get("mostRecentIds").datalistid = this.id;
        window.app.get("authentication").saveAndInterConnectInApp();

        try{
          window.appView.setUpAndAssociateViewsAndModelsWithCurrentDataList(function() {
            if (typeof successcallback == "function") {
              successcallback();
            }else{
              //TODO remove this when done debugging and it is working all the time.
              var self = this;
              window.appView.toastUser("Sucessfully connected all views up to data list: "+ self.id,"alert-success","Connected!");
//            window.appView.renderEditableDataListViews();
//            window.appView.renderReadonlyDataListViews();
            }
          });
        }catch(e){
          if (typeof failurecallback == "function") {
            failurecallback();
          }else{
            alert("This is probably a bug. There was a problem rendering the current dataList's views after resetting the current session.");
          }
        }
      }
    }
  });

  return DataList;
});
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var express = require('express');
var Prompt = require('./promptModel.js');

var promptModel = {
  array: [
    "In order for your Angular application to work, we will have to initialize the application in our HTML file and to do so we attach a specific attribute to a DOM element where we want our Angular application to appear. ng-app is commonly given as an attribute to either <html> or <body> element, but for the purposes of our tutorial we will attach it to the <body> element. Please give ng-app the value of myApp.",

    "The application is a JavaScript file so in our app.js editor we provided you will with starter code so we can understand Angular's two-way data binding and as an example we will explore Angular models. In the <body>, create an attribute of ng-model with a value of movie at the first <input> of the <form> in the <body> of the document.",

    "Angular references data with a particular syntax, {{DATA_REFERENCE}} (double curly braces). This displays the content declared within Angular attribute also known as directives. Directives are identified in the HTML document with the ng-. Beneath the <input> create a data reference to the value of the ng-model. Test drive the output in the view and type a few characters in the input field and see what shows up. Characters should be reflecting what you type and this is one of the most simplest models for exhibiting Angular two-way binding.",

    "Following the coding style when creating a module in the app.js, we will be making another example of two-way data binding by the use of a different directive called ng-controller instead of using ng-model. In your controller called myController in the controller.js file, the myController function will be declared with $scope as a parameter. Have your function reference $scope and set a property of it called name equal to your name. Controllers are meant to be small and lightweight to manage and manipulate transient data.",

    "Angular services are generally identified as variables with dollar signs before them, i.e. $scope or $http. Services are objects with a collection of methods that Angular provides for functionality. For Angular, $scope is an object that refers to the application model that enables data coming from a controller to act in a similar fashion to ng-model.",

    "A method of $scope will be added to the controller called getMovie where you will assign the value of $scope.name to $scope.movie and afterwards re-assigning $scope.movie to an empty string. Having done so, attach a ng-submit to the <form> for the getMovie() method from myController. Attempt to place your favorite movie name into the input field and submit your selection with the button. Notice how the data has changed again to update your $scope.name value with the value taken from $scope.movie.",

    "The same way we created a controller, we will be creating a factory in factory.js. Factories are similar to controllers, but are used for persistent data that can be used to pass down to other controllers to manipulate.",

    "Create a factory called myFactory to Angular and create its function the $http service as a parameter. In order to make use of this service we have to make it available to the factory by using method on the factory called .$inject. We will then assign myFactory.$inject equivalent to a single element array with a string value of $http.",

    "This is a common practice in Angular to provide functionality amongst its toolkit. It is better known as dependency injection. The injection of $http allows for Angular to perform AJAX actions with data so the myFactory function will declare a function within it named getMovieInfo that returns the $http.get() to http://www.omdbapi.com/?t=frozen&y=&plot=short&r=json and returns a Promise with .then() for success chained with .catch() to manage failures in data retrieval.",

    "The Promise requires callback functions. Create two functions within getMovieInfo, one function called getMovieComplete that takes in a response parameter and returns response.data. The other function is called getMovieFailed that will take in an error parameter and will console.log(error). The .then() will be given getMovieComplete as a callback and .catch() will take getMovieFailed.",

    "Having retrieved the persistent data that we are requesting for the factory we must output this data from it for other Angular bits to use by returning an object with a key:value pair getMovieInfo: getMovieInfo - the property is referencing the function with the same name that is retrieving the data.",

    "Now with the creation of the factory we will be modifying myController to update your name with some movie data instead. In order to use the myFactory in the myController we have to insert it as an additional parameter for its function. We are going to retrieve year of our movie query so to display it create a variable, movieData, that is equal to the factory method we made, getMovieInfo.",

    "Afterward in the $scope.getMovie function, we are going to re-assign $scope.name to our freshly created variable. Here we've done a little bit of digging into the JSON data object that is returning for you so set $scope.name equal to movieData.$$state.value.Year.",

    "Notice that the functionality of our application has changed. Instead our form submission with our user input used to bind our selection, but it will now do an AJAX request to retrieve persistent data from our factory to retrieve the release year of the Disney movie, Frozen.",

    "You may have discovered a big ugly box that doesn't work on our application page. Well, we're going to fill that up with a partial HTML. Angular makes great use of partial HTML in its single-page application environment so in the partial.html we'll make another data reference to name from out controller. However, the partial still doesn't work because we are going to require a routing tool to deliver this page. We'll be using ui-router to do so and in the same way we will inject this as a dependency to the application itself.",

    "Where myApp was originally defined in app.js lies an empty array as a parameter and here is where we will be injecting ui-router, an open source extension for improving Angular's single-page web application functionality for HTML partials. Following the module function, a .config() function is chained to reference a function called configFunction that we will be creating in the same file.",

    "configFunction will make use of ui-router to display our partial HTML. Declare the function passing it two parameters $stateProvider, $urlRouteProvider. Inside the function use the $stateProvider.state() method, it acts similarly to HTTP request using two parameters to configure it - the first that gives it a name and the second an object that determines the configuration of the route. Assign the first parameter as a string name and within the object parameter: url: '/test', templateUrl: './partial.html', controller: 'myController'.",

    "Check out your partial HTML in the output! You're on your way to becoming a sharp Angular master."
  ],
  findPrompts: function(req, res) {
    Prompt.findOne({}, function(error, prompts) {
      console.log(prompts);
      res.send(prompts);
    });
  },
  postPrompts: function(req, res) {
    Prompt.findOne({}, function(error, prompts) {
      console.log('this is prompts' + prompts);
      if(prompts === null) {
        Prompt.create({0: JSON.stringify(promptModel.array)}, function(error, a, b) {
          if(error) {
            console.log('oh no' + error);
          } else {
            console.log('works!' + a + b);
          }
        });
      }
    });
  }
};

module.exports = promptModel;
<commit_msg>Update promptController.js<commit_after>var mongoose = require('mongoose');
var express = require('express');
var Prompt = require('./promptModel.js');

var promptModel = {
  array: [
    "In order for your Angular application to work, we will have to initialize the application in our HTML file and to do so we attach a specific attribute to a DOM element where we want our Angular application to appear. ng-app is commonly given as an attribute to either <html> or <body> element, but for the purposes of our tutorial we will attach it to the <body> element. Please give ng-app the value of myApp.",

    "The application is a JavaScript file so in our app.js editor we provided you will with starter code so we can understand Angular's two-way data binding and as an example we will explore Angular models. In the <body>, create an attribute of ng-model with a value of movie at the first <input> of the <form> in the <body> of the document.",

    "Angular references data with a particular syntax, {{DATA_REFERENCE}} (double curly braces). This displays the content declared within Angular attribute also known as directives. Directives are identified in the HTML document with the ng-. Beneath the <input> create a data reference to the value of the ng-model. Test drive the output in the view and type a few characters in the input field and see what shows up. Characters should be reflecting what you type and this is one of the most simplest models for exhibiting Angular two-way binding.",

    "Following the coding style when creating a module in the app.js, we will be making another example of two-way data binding by the use of a different directive called ng-controller instead of using ng-model. In your controller called myController in the controller.js file, the myController function will be declared with $scope as a parameter. Have your function reference $scope and set a property of it called name equal to your name. Controllers are meant to be small and lightweight to manage and manipulate transient data.",

    "Angular services are generally identified as variables with dollar signs before them, i.e. $scope or $http. Services are objects with a collection of methods that Angular provides for functionality. For Angular, $scope is an object that refers to the application model that enables data coming from a controller to act in a similar fashion to ng-model.",

    "A method of $scope will be added to the controller called getMovie where you will assign the value of $scope.name to $scope.movie and afterwards re-assigning $scope.movie to an empty string. Having done so, attach a ng-submit to the <form> for the getMovie() method from myController. Attempt to place your favorite movie name into the input field and submit your selection with the button. Notice how the data has changed again to update your $scope.name value with the value taken from $scope.movie.",

    "The same way we created a controller, we will be creating a factory in factory.js. Factories are similar to controllers, but are used for persistent data that can be used to pass down to other controllers to manipulate.",

    "Create a factory called myFactory to Angular and create its function the $http service as a parameter. In order to make use of this service we have to make it available to the factory by using method on the factory called .$inject. We will then assign myFactory.$inject equivalent to a single element array with a string value of $http.",

    "This is a common practice in Angular to provide functionality amongst its toolkit. It is better known as dependency injection. The injection of $http allows for Angular to perform AJAX actions with data so the myFactory function will declare a function within it named getMovieInfo that returns the $http.get() to http://www.omdbapi.com/?t=frozen&y=&plot=short&r=json and returns a Promise with .then() for success chained with .catch() to manage failures in data retrieval.",

    "The Promise requires callback functions. Create two functions within getMovieInfo, one function called getMovieComplete that takes in a response parameter and returns response.data. The other function is called getMovieFailed that will take in an error parameter and will console.log(error). The .then() will be given getMovieComplete as a callback and .catch() will take getMovieFailed.",

    "Having retrieved the persistent data that we are requesting for the factory we must output this data from it for other Angular bits to use by returning an object with a key:value pair getMovieInfo: getMovieInfo - the property is referencing the function with the same name that is retrieving the data.",

    "Now with the creation of the factory we will be modifying myController to update your name with some movie data instead. In order to use the myFactory in the myController we have to insert it as an additional parameter for its function. We are going to retrieve year of our movie query so to display it create a variable, movieData, that is equal to the factory method we made, getMovieInfo.",

    "Afterward in the $scope.getMovie function, we are going to re-assign $scope.name to our freshly created variable. Here we've done a little bit of digging into the JSON data object that is returning for you so set $scope.name equal to movieData.$$state.value.Year.",

    "Notice that the functionality of our application has changed. Instead our form submission with our user input used to bind our selection, but it will now do an AJAX request to retrieve persistent data from our factory to retrieve the release year of the Disney movie, Frozen.",

    "You may have discovered a big ugly box that doesn't work on our application page. Well, we're going to fill that up with a partial HTML. Angular makes great use of partial HTML in its single-page application environment so in the partial.html we'll make another data reference to name from out controller. However, the partial still doesn't work because we are going to require a routing tool to deliver this page. We'll be using ui-router to do so and in the same way we will inject this as a dependency to the application itself.",

    "Where myApp was originally defined in app.js lies an empty array as a parameter and here is where we will be injecting ui-router, an open source extension for improving Angular's single-page web application functionality for HTML partials. Following the module function, a .config() function is chained to reference a function called configFunction that we will be creating in the same file.",

    "configFunction will make use of ui-router to display our partial HTML. Declare the function passing it two parameters $stateProvider, $urlRouteProvider. Inside the function use the $stateProvider.state() method, it acts similarly to HTTP request using two parameters to configure it - the first that gives it a name and the second an object that determines the configuration of the route. Assign the first parameter as a string name and within the object parameter: url: '/test', templateUrl: './partial.html', controller: 'myController'.",

    "Check out your partial HTML in the output! You're on your way to becoming a sharp Angular master."
  ],
  findPrompts: function(req, res) {
    Prompt.findOne({}, function(error, prompts) {
      res.send(prompts);
    });
  },
  postPrompts: function(req, res) {
    Prompt.findOne({}, function(error, prompts) {
      console.log('this is prompts' + prompts);
      if(prompts === null) {
        Prompt.create({0: JSON.stringify(promptModel.array)}, function(error, a, b) {
          if(error) {
            console.log('oh no' + error);
          } else {
            console.log('works!' + a + b);
          }
        });
      }
    });
  }
};

module.exports = promptModel;
<|endoftext|>


<commit_before>import d3 from 'd3'
import React from 'react'
import raw_income_data from './clean_income.js'

export default class Min extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      income_data: raw_income_data,
    }
    //this.loadDataFromServer = this.loadDataFromServer.bind(this);
  }

  calculate_cost(basic_income) {
    var income_range_index = 0;
    var sum_households_below = 0;
    var sum_income_delta = 0;
    for (var index = 0; index < raw_income_data.length; index++) {
      var element = raw_income_data[index];
      var households = parseInt(element["households_thousands"])
      sum_households_below = sum_households_below + households
      var income_range = parseInt(element["income_range"])
      sum_income_delta = sum_income_delta + ((basic_income - income_range) * households * 1000)
      if (income_range <= basic_income) {
        income_range_index = index
        return sum_income_delta;
      }
    }
  }

  render() {
    var x = this.calculate_cost(30000);
    console.log("val: " + x);
    return (
     /*

      {JSON.stringify(this.state.income_data)}

      */

      <input type="text" className="form-control" />

{this.calculate_cost(30000)}

    );
  }

  /*
  loadDataFromServer() {
    d3.csv("./data/income.csv", (data) => {
      console.log(this);
        this.setState({
          income_data: data
        });
        console.log("Data has been set");
    });
  }

  componentDidMount() {
    //this.loadDataFromServer();
  }
  */
}

export default Min
<commit_msg>new data<commit_after>import d3 from 'd3'
import React from 'react'
import raw_income_data from './clean_income.js'

export default class Min extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      income_data: raw_income_data,
    }
    //this.loadDataFromServer = this.loadDataFromServer.bind(this);
  }

  calculate_cost(basic_income) {
    var income_range_index = 0;
    var sum_households_below = 0;
    var sum_income_delta = 0;
    for (var index = 0; index < raw_income_data.length; index++) {
      var element = raw_income_data[index];
      var income_range_upper = element["range_upper"]
    if (income_range_upper > basic_income) {
      income_range_index = index
      return sum_income_delta;
    }
      var households = element["households"]
      sum_households_below = element["cumulative"]
      var average = element["average"]
      sum_income_delta = sum_income_delta + ((basic_income - average) * households)
    }
  }

  render() {
    var x = this.calculate_cost(15000);
    console.log("val: " + x);
    return (
     /*

      {JSON.stringify(this.state.income_data)}

      */

      <input type="text" className="form-control" />

{this.calculate_cost(30000)}

    );
  }

  /*
  loadDataFromServer() {
    d3.csv("./data/income.csv", (data) => {
      console.log(this);
        this.setState({
          income_data: data
        });
        console.log("Data has been set");
    });
  }

  componentDidMount() {
    //this.loadDataFromServer();
  }
  */
}

export default Min
<|endoftext|>


<commit_before>YUI.add('aui-surface-tests', function(Y) {

    var suite = new Y.Test.Suite('aui-surface');

    suite.add(new Y.Test.Case({
        name: 'Surface Tests',

        init: function() {
            this.regexRoute = /^\/regex\?foo=\d$/;
            this.currentPath = this.getCurrentPath();

            this.app = new Y.SurfaceApp({
                basePath: '/base',
                linkSelector: 'a'
            });

            this.app.addScreenRoutes([
                new Y.ScreenRoute({
                    path: '/page',
                    screen: Y.PageScreen
                }),
                {
                    path: '/locked',
                    screen: Y.LockedScreen
                },
                {
                    path: '/lazy',
                    screen: Y.LazySurfaceScreen
                },
                {
                    path: this.regexRoute,
                    screen: Y.RegexScreen
                },
                {
                    path: function(value) {
                        return value === '/delayed';
                    },
                    screen: Y.DelayedScreen
                },
                {
                    path: {
                        unknown: true
                    },
                    screen: Y.Screen
                }
            ]);

            this.app.addSurfaces([
                new Y.Surface({
                    id: 'header'
                }),
                'body',
                'unknown'
            ]);
        },

        destroy: function() {
            this.app = null;
            Y.config.win.history.pushState(null, '', this.currentPath);
        },

        'should match screen routes': function() {
            var route = null;

            route = this.app.matchesRoute('/base/unknown');
            Y.Assert.isNull(route);

            route = this.app.matchesRoute('/base/page');
            Y.Assert.isInstanceOf(Y.ScreenRoute, route);
            Y.Assert.areEqual('/page', route.get('path'));

            route = this.app.matchesRoute('/base/regex?foo=1');
            Y.Assert.isInstanceOf(Y.ScreenRoute, route);
            Y.Assert.areEqual(this.regexRoute, route.get('path'));
        },

        'should throw error when surface id is not found': function() {
            Y.Assert.throwsError(Error, function() {
                new Y.Surface({
                    id: ''
                });
            });
        },

        'should match surface elements': function() {
            Y.Assert.areEqual(Y.one('#body'), this.app.surfaces.body.getEl());
            Y.Assert.areEqual(Y.one('#header'), this.app.surfaces.header.getEl());
        },

        'should update surfaces and title using HTMLScreen': function() {
            var path = this.getBasePath() + 'content.txt';

            this.app.set('basePath', this.getBasePath());
            this.app.addScreenRoutes({
                path: 'content.txt',
                screen: Y.HTMLScreen
            });
            this.app.navigate(path);
            this.wait(function() {
                this.app.set('basePath', '/base');
                this.assertEqualCurrentPath(path);
                this.assertEqualSurfaceContent('body', 'body-html');
                this.assertEqualSurfaceContent('header', 'header-html');
                Y.Assert.areEqual('HTML', Y.config.doc.title);
            }, 100);
        },

        'should update surfaces using HTMLScreen': function() {
            var path = this.getBasePath() + 'notitle.txt';

            this.app.set('basePath', this.getBasePath());
            this.app.addScreenRoutes({
                path: 'notitle.txt',
                screen: Y.HTMLScreen
            });
            this.app.navigate(path);
            this.wait(function() {
                this.app.set('basePath', '/base');
                this.assertEqualCurrentPath(path);
                this.assertEqualSurfaceContent('body', 'body-html');
                this.assertEqualSurfaceContent('header', 'header-html');
            }, 100);
        },

        'should navigate fail using HTMLScreen': function() {
            var path = this.getBasePath() + 'notitle.txt',
                path404 = this.getBasePath() + '404.txt';

            this.app.set('basePath', this.getBasePath());
            this.app.addScreenRoutes({
                path: '404.txt',
                screen: Y.HTML404Screen
            });
            this.app.navigate(path404);
            this.wait(function() {
                this.app.set('basePath', '/base');
                this.assertEqualCurrentPath(path);
                this.assertEqualSurfaceContent('body', 'body-html');
                this.assertEqualSurfaceContent('header', 'header-html');
            }, 100);
        },

        'should lazily find surface element': function() {
            this.app.addSurfaces(
                new Y.Surface({
                    id: 'lazy'
                })
            );
            Y.Assert.isNull(this.app.surfaces.lazy.getEl());

            this.app.navigate('/base/lazy');

            setTimeout(function() {
                this.app.navigate('/base/page');
            }.bind(this), 10);

            setTimeout(function() {
                Y.one('body').append('<div id="lazy"/>');
                Y.Assert.isNotNull(this.app.surfaces.lazy.getEl());
                this.app.navigate('/base/lazy');
            }.bind(this), 20);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/lazy');
                this.assertEqualSurfaceContent('lazy', 'lazy');
                this.assertEqualSurfaceContent('body', 'body-default');
                this.assertEqualSurfaceContent('header', 'header-default');
            }, 30);
        },

        'should navigate to /base/delayed asynchronously': function() {
            this.app.navigate('/base/delayed');

            // When navigate the url updates after navigation lifecycle
            setTimeout(function() {
                this.assertNotSameCurrentPath('/base/delayed');
            }.bind(this), 10);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/delayed');
                this.assertEqualSurfaceContent('body', 'body-delayed');
                this.assertEqualSurfaceContent('header', 'header-delayed');
                Y.Assert.areEqual('Delayed', Y.config.doc.title);
            }, 60);
        },

        'should navigate to /base/page': function() {
            this.app.navigate('/base/page');
            this.wait(function() {
                this.assertEqualCurrentPath('/base/page');
                this.assertEqualSurfaceContent('body', 'body-page');
                this.assertEqualSurfaceContent('header', 'header-page');
                Y.Assert.areEqual('Page', Y.config.doc.title);
            }, 10);
        },

        'should navigate to /base/regex?foo=1': function() {
            this.app.navigate('/base/regex?foo=1');
            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 10);
        },

        'should navigate to previous page': function() {
            Y.config.win.history.back();
            this.wait(function() {
                this.assertEqualCurrentPath('/base/page');
                this.assertEqualSurfaceContent('body', 'body-page');
                this.assertEqualSurfaceContent('header', 'header-page');
                Y.Assert.areEqual('Page', Y.config.doc.title);
            }, 50);
        },

        'should navigate to previous /base/delayed asynchronously': function() {
            Y.config.win.history.back();

            // When popstate happens the url updates first than navigation lifecycle
            setTimeout(function() {
                this.assertEqualCurrentPath('/base/delayed');
            }.bind(this), 50);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/delayed');
                this.assertEqualSurfaceContent('body', 'body-delayed');
                this.assertEqualSurfaceContent('header', 'header-delayed');
                Y.Assert.areEqual('Delayed', Y.config.doc.title);
            }, 100);
        },

        'should navigate to next page': function() {
            Y.config.win.history.forward();
            this.wait(function() {
                this.assertEqualCurrentPath('/base/page');
                this.assertEqualSurfaceContent('body', 'body-page');
                this.assertEqualSurfaceContent('header', 'header-page');
                Y.Assert.areEqual('Page', Y.config.doc.title);
            }, 50);
        },

        'should remember the scroll position': function() {
            var docScrollXAfterNavigate = 0,
                docScrollYAfterNavigate = 0;

            Y.config.win.scrollTo(200, 200);

            setTimeout(function() {
                this.app.navigate('/base/regex?foo=1');
            }.bind(this), 2000);

            setTimeout(function() {
                docScrollXAfterNavigate = Y.DOM.docScrollX();
                docScrollYAfterNavigate = Y.DOM.docScrollY();
                Y.config.win.history.back();
            }.bind(this), 4000);

            this.wait(function() {
                Y.Assert.areEqual(0, docScrollXAfterNavigate);
                Y.Assert.areEqual(0, docScrollYAfterNavigate);
                Y.Assert.areEqual(200, Y.DOM.docScrollY());
                Y.Assert.areEqual(200, Y.DOM.docScrollX());
            }, 4050);
        },

        'should cancel pending navigate': function() {
            this.app.navigate('/base/delayed');

            setTimeout(function() {
                this.app.navigate('/base/page');
            }.bind(this), 10);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/page');
                this.assertEqualSurfaceContent('body', 'body-page');
                this.assertEqualSurfaceContent('header', 'header-page');
                Y.Assert.areEqual('Page', Y.config.doc.title);
            }, 20);
        },

        'should dispatch to the current url': function() {
            Y.config.win.history.pushState(null, '', '/base/regex?foo=1');

            setTimeout(function() {
                this.app.dispatch();
            }.bind(this), 25);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 35);
        },

        'should not handle history states that are not ours': function() {
            Y.config.win.history.pushState({}, '', '/unknown/state');

            setTimeout(function() {
                this.app.navigate('/base/page');
            }.bind(this), 25);

            setTimeout(function() {
                Y.config.win.history.back();
            }.bind(this), 50);

            this.wait(function() {
                this.assertEqualCurrentPath('/unknown/state');
                this.assertEqualSurfaceContent('body', 'body-page');
                this.assertEqualSurfaceContent('header', 'header-page');
                Y.Assert.areEqual('Page', Y.config.doc.title);
            }, 100);
        },

        'should navigate on link click': function() {
            Y.one('a[href="/base/regex?foo=1"]').simulate('click');
            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 10);
        },

        'should not navigate on offsite link click': function() {
            var external = Y.one('a[href="http://alloyui.com/external"]');

            external.on('click', function(event) {
                event.preventDefault();
            });

            external.simulate('click');

            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 10);
        },

        'should not navigate to unrouted link': function() {
            var external = Y.one('a[href="/base/unrouted"]');

            external.on('click', function(event) {
                event.preventDefault();
            });

            external.simulate('click');

            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 10);
        },

        'should not navigate to unrouted route': function() {
            Y.Assert.isFalse(this.app.navigate('/base/unrouted'));
            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 10);
        },

        'should not navigate to link outside base path': function() {
            this.app.navigate('/outside');
            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 10);
        },

        'should not navigate when navigation cancelled by active screen': function() {
            this.app.navigate('/base/locked');

            setTimeout(function() {
                this.app.navigate('/base/page');
            }.bind(this), 10);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/locked');
                this.assertEqualSurfaceContent('body', 'body-default');
                this.assertEqualSurfaceContent('header', 'header-default');
            }, 20);
        }
    }));

    Y.Test.Runner.add(suite);

}, '', {
    requires: ['test', 'tests-aui-surface-utils', 'dom-screen', 'node-event-simulate', 'aui-surface']
});
<commit_msg>AUI-1173 Disable tests on browsers that don't support HTML5 History and increase some timeouts in order to work-around the asynchronous scrollTo behavior<commit_after>YUI.add('aui-surface-tests', function(Y) {

    var noHTML5 = !(Y.config.win &&
        Y.config.win.history.pushState &&
        Y.config.win.history.replaceState &&
        ('onpopstate' in Y.config.win || Y.UA.gecko >= 2));

    var suite = new Y.Test.Suite('aui-surface');

    suite.add(new Y.Test.Case({
        name: 'Surface Tests',

        _should: {
            // Ignore all tests in browsers without HTML5 history support.
            ignore: {
                'should cancel pending navigate': noHTML5,
                'should dispatch to the current url': noHTML5,
                'should lazily find surface element': noHTML5,
                'should match surface elements': noHTML5,
                'should navigate fail using HTMLScreen': noHTML5,
                'should navigate on link click': noHTML5,
                'should navigate to /base/delayed asynchronously': noHTML5,
                'should navigate to /base/page': noHTML5,
                'should navigate to /base/regex?foo=1': noHTML5,
                'should navigate to next page': noHTML5,
                'should navigate to previous /base/delayed asynchronously': noHTML5,
                'should navigate to previous page': noHTML5,
                'should not handle history states that are not ours': noHTML5,
                'should not navigate on offsite link click': noHTML5,
                'should not navigate to link outside base path': noHTML5,
                'should not navigate to unrouted link': noHTML5,
                'should not navigate to unrouted route': noHTML5,
                'should not navigate when navigation cancelled by active screen': noHTML5,
                'should remember the scroll position': noHTML5 || Y.UA.ie,
                'should throw error when surface id is not found': noHTML5,
                'should update surfaces and title using HTMLScreen': noHTML5,
                'should update surfaces using HTMLScreen': noHTML5
            }
        },

        init: function() {
            this.regexRoute = /^\/regex\?foo=\d+$/;
            this.currentPath = this.getCurrentPath();

            this.app = new Y.SurfaceApp({
                basePath: '/base',
                linkSelector: 'a'
            });

            this.app.addScreenRoutes([
                new Y.ScreenRoute({
                    path: '/page',
                    screen: Y.PageScreen
                }),
                {
                    path: '/locked',
                    screen: Y.LockedScreen
                },
                {
                    path: '/lazy',
                    screen: Y.LazySurfaceScreen
                },
                {
                    path: this.regexRoute,
                    screen: Y.RegexScreen
                },
                {
                    path: function(value) {
                        return value === '/delayed';
                    },
                    screen: Y.DelayedScreen
                },
                {
                    path: {
                        unknown: true
                    },
                    screen: Y.Screen
                }
            ]);

            this.app.addSurfaces([
                new Y.Surface({
                    id: 'header'
                }),
                'body',
                'unknown'
            ]);
        },

        destroy: function() {
            this.app = null;
            Y.config.win.history.pushState(null, '', this.currentPath);
        },

        'should match screen routes': function() {
            var route = null;

            route = this.app.matchesRoute('/base/unknown');
            Y.Assert.isNull(route);

            route = this.app.matchesRoute('/base/page');
            Y.Assert.isInstanceOf(Y.ScreenRoute, route);
            Y.Assert.areEqual('/page', route.get('path'));

            route = this.app.matchesRoute('/base/regex?foo=1');
            Y.Assert.isInstanceOf(Y.ScreenRoute, route);
            Y.Assert.areEqual(this.regexRoute, route.get('path'));
        },

        'should throw error when surface id is not found': function() {
            Y.Assert.throwsError(Error, function() {
                new Y.Surface({
                    id: ''
                });
            });
        },

        'should match surface elements': function() {
            Y.Assert.areEqual(Y.one('#body'), this.app.surfaces.body.getEl());
            Y.Assert.areEqual(Y.one('#header'), this.app.surfaces.header.getEl());
        },

        'should update surfaces and title using HTMLScreen': function() {
            var path = this.getBasePath() + 'content.txt';

            this.app.set('basePath', this.getBasePath());
            this.app.addScreenRoutes({
                path: 'content.txt',
                screen: Y.HTMLScreen
            });
            this.app.navigate(path);
            this.wait(function() {
                this.app.set('basePath', '/base');
                this.assertEqualCurrentPath(path);
                this.assertEqualSurfaceContent('body', 'body-html');
                this.assertEqualSurfaceContent('header', 'header-html');
                Y.Assert.areEqual('HTML', Y.config.doc.title);
            }, 100);
        },

        'should update surfaces using HTMLScreen': function() {
            var path = this.getBasePath() + 'notitle.txt';

            this.app.set('basePath', this.getBasePath());
            this.app.addScreenRoutes({
                path: 'notitle.txt',
                screen: Y.HTMLScreen
            });
            this.app.navigate(path);
            this.wait(function() {
                this.app.set('basePath', '/base');
                this.assertEqualCurrentPath(path);
                this.assertEqualSurfaceContent('body', 'body-html');
                this.assertEqualSurfaceContent('header', 'header-html');
            }, 100);
        },

        'should navigate fail using HTMLScreen': function() {
            var path = this.getBasePath() + 'notitle.txt',
                path404 = this.getBasePath() + '404.txt';

            this.app.set('basePath', this.getBasePath());
            this.app.addScreenRoutes({
                path: '404.txt',
                screen: Y.HTML404Screen
            });
            this.app.navigate(path404);
            this.wait(function() {
                this.app.set('basePath', '/base');
                this.assertEqualCurrentPath(path);
                this.assertEqualSurfaceContent('body', 'body-html');
                this.assertEqualSurfaceContent('header', 'header-html');
            }, 100);
        },

        'should lazily find surface element': function() {
            this.app.addSurfaces(
                new Y.Surface({
                    id: 'lazy'
                })
            );
            Y.Assert.isNull(this.app.surfaces.lazy.getEl());

            this.app.navigate('/base/lazy');

            setTimeout(function() {
                this.app.navigate('/base/page');
            }.bind(this), 100);

            setTimeout(function() {
                Y.one('body').append('<div id="lazy"/>');
                Y.Assert.isNotNull(this.app.surfaces.lazy.getEl());
                this.app.navigate('/base/lazy');
            }.bind(this), 200);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/lazy');
                this.assertEqualSurfaceContent('lazy', 'lazy');
                this.assertEqualSurfaceContent('body', 'body-default');
                this.assertEqualSurfaceContent('header', 'header-default');
            }, 300);
        },

        'should navigate to /base/delayed asynchronously': function() {
            this.app.navigate('/base/delayed');

            setTimeout(function() {
                this.assertNotSameCurrentPath('/base/delayed');
            }.bind(this), 30);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/delayed');
                this.assertEqualSurfaceContent('body', 'body-delayed');
                this.assertEqualSurfaceContent('header', 'header-delayed');
                Y.Assert.areEqual('Delayed', Y.config.doc.title);
            }, 100);
        },

        'should navigate to /base/page': function() {
            this.app.navigate('/base/page');
            this.wait(function() {
                this.assertEqualCurrentPath('/base/page');
                this.assertEqualSurfaceContent('body', 'body-page');
                this.assertEqualSurfaceContent('header', 'header-page');
                Y.Assert.areEqual('Page', Y.config.doc.title);
            }, 50);
        },

        'should navigate to /base/regex?foo=1': function() {
            this.app.navigate('/base/regex?foo=1');
            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 50);
        },

        'should navigate to previous page': function() {
            this.app.navigate('/base/regex?foo=10');

            setTimeout(function() {
                this.app.navigate('/base/regex?foo=20');
            }.bind(this), 100);

            setTimeout(function() {
                Y.config.win.history.back();
            }.bind(this), 200);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=10');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 300);
        },

        'should navigate to previous /base/delayed asynchronously': function() {
            this.app.navigate('/base/delayed');

            setTimeout(function() {
                this.app.navigate('/base/regex?foo=30');
            }.bind(this), 200);

            setTimeout(function() {
                Y.config.win.history.back();
            }.bind(this), 300);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/delayed');
                this.assertEqualSurfaceContent('body', 'body-delayed');
                this.assertEqualSurfaceContent('header', 'header-delayed');
                Y.Assert.areEqual('Delayed', Y.config.doc.title);
            }, 600);
        },

        'should navigate to next page': function() {
            this.app.navigate('/base/regex?foo=40');

            setTimeout(function() {
                this.app.navigate('/base/regex?foo=50');
            }.bind(this), 100);

            setTimeout(function() {
                Y.config.win.history.back();
            }.bind(this), 200);

            setTimeout(function() {
                Y.config.win.history.forward();
            }.bind(this), 400);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=50');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 600);
        },

        'should remember the scroll position': function() {
            var pageXOffsetAfterNavigate = 0,
                pageYOffsetAfterNavigate = 0;

            this.app.navigate('/base/regex?foo=60');

            setTimeout(function() {
                Y.config.win.scrollTo(10, 10);
            }.bind(this), 1000);

            setTimeout(function() {
                this.app.navigate('/base/regex?foo=70');
            }.bind(this), 2000);

            setTimeout(function() {
                pageXOffsetAfterNavigate = Y.config.win.pageXOffset;
                pageYOffsetAfterNavigate = Y.config.win.pageYOffset;
                Y.config.win.history.back();
            }.bind(this), 3000);

            this.wait(function() {
                Y.Assert.areEqual(0, pageXOffsetAfterNavigate);
                Y.Assert.areEqual(0, pageYOffsetAfterNavigate);
                Y.Assert.areEqual(10, Y.config.win.pageXOffset);
                Y.Assert.areEqual(10, Y.config.win.pageYOffset);
            }, 10000);
        },

        'should cancel pending navigate': function() {
            this.app.navigate('/base/delayed');

            setTimeout(function() {
                this.app.navigate('/base/page');
            }.bind(this), 20);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/page');
                this.assertEqualSurfaceContent('body', 'body-page');
                this.assertEqualSurfaceContent('header', 'header-page');
                Y.Assert.areEqual('Page', Y.config.doc.title);
            }, 100);
        },

        'should dispatch to the current url': function() {
            Y.config.win.history.pushState(null, '', '/base/regex?foo=1');

            setTimeout(function() {
                this.app.dispatch();
            }.bind(this), 100);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 200);
        },

        'should not handle history states that are not ours': function() {
            Y.config.win.history.pushState({}, '', '/unknown/state');

            setTimeout(function() {
                this.app.navigate('/base/page');
            }.bind(this), 100);

            setTimeout(function() {
                Y.config.win.history.back();
            }.bind(this), 200);

            this.wait(function() {
                this.assertEqualCurrentPath('/unknown/state');
                this.assertEqualSurfaceContent('body', 'body-page');
                this.assertEqualSurfaceContent('header', 'header-page');
                Y.Assert.areEqual('Page', Y.config.doc.title);
            }, 400);
        },

        'should navigate on link click': function() {
            Y.one('a[href="/base/regex?foo=1"]').simulate('click');
            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 50);
        },

        'should not navigate on offsite link click': function() {
            var external = Y.one('a[href="http://alloyui.com/external"]');

            external.on('click', function(event) {
                event.preventDefault();
            });

            external.simulate('click');

            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 50);
        },

        'should not navigate to unrouted link': function() {
            var external = Y.one('a[href="/base/unrouted"]');

            external.on('click', function(event) {
                event.preventDefault();
            });

            external.simulate('click');

            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 50);
        },

        'should not navigate to unrouted route': function() {
            Y.Assert.isFalse(this.app.navigate('/base/unrouted'));
            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 50);
        },

        'should not navigate to link outside base path': function() {
            this.app.navigate('/outside');
            this.wait(function() {
                this.assertEqualCurrentPath('/base/regex?foo=1');
                this.assertEqualSurfaceContent('body', 'body-regex');
                this.assertEqualSurfaceContent('header', 'header-regex');
                Y.Assert.areEqual('Regex', Y.config.doc.title);
            }, 50);
        },

        'should not navigate when navigation cancelled by active screen': function() {
            this.app.navigate('/base/locked');

            setTimeout(function() {
                this.app.navigate('/base/page');
            }.bind(this), 50);

            this.wait(function() {
                this.assertEqualCurrentPath('/base/locked');
                this.assertEqualSurfaceContent('body', 'body-default');
                this.assertEqualSurfaceContent('header', 'header-default');
            }, 100);
        }
    }));

    Y.Test.Runner.add(suite);

}, '', {
    requires: ['test', 'tests-aui-surface-utils', 'node-event-simulate', 'aui-surface']
});
<|endoftext|>


<commit_before>    var nastyGlobal = 0;    var friendCount = 0;

$(function() {

    checkTwitterApiLimit();

    $('#doWork').click(function() {
        $('ul li').remove();

        logProgress("Working..");

          var friendListCall = getTwitterFriendList($('#searchName').val());

        friendListCall.success(function(friendList) {

            friendCount = friendList.length;
            var deferredTwitterCalls = buildSetOfDeferredTwitterDetailCalls(friendList);

            $.when.apply($, deferredTwitterCalls).then(function() {
                kickOffSlowGoogleProfileSearchInWebWorker(friendList);
            });
        });

        friendListCall.error(function(jqXHR, textStatus, error){
            alert('Please ensure you use a valid twitter username');
            logProgress("Actually, not working.. double check your twitter name");
        })
    });
});

function checkTwitterApiLimit(){
    $('#doWork').attr('disabled', true);
    $('#searchName').attr('disabled', true);
    $('#sorryOverLimit').hide();
    $('#loader').hide();

    $.ajax({
        url:"http://api.twitter.com/1/account/rate_limit_status.json",
        dataType:"jsonp"
    }).success(function(rateInfo){
        if(rateInfo.remaining_hits<10){
            $('#sorryOverLimit').show();
        }else{
            $('#doWork').attr('disabled', false);
            $('#searchName').attr('disabled', false);
        };
    });
}

function logProgress(info) {
    $("#progress").append("
" + info + "
");
}

function getTwitterFriendList(searchName) {
    return $.ajax({
        url: "http://api.twitter.com/1/friends/ids.json",
        data: {screen_name: searchName},
        dataType: "jsonp",
        timeout: 5000
    });
}

function buildSetOfDeferredTwitterDetailCalls(friendList) {

    var deferreds = [];

    // chunk into calls of 100 friends
    var sliceSize = 100;
    var len = friendList.length;

    logProgress("Number of friends found: " + len);
    logProgress("Beginning fast search");
    logProgress('Retrieving details of your twitter friends');

    logProgress('--');
    logProgress("Sadly, only a small percentage of your twitter friends will be found");
    logProgress("YOU can improve your own results!");
    logProgress("Spread the word, ask folks on Twitter to go to");
    logProgress("gplus.to and get themselves a name that matches their twitter name");
    logProgress('--');

    $('#loader').show();

    // we chunk our calls to Twitter to return user details, as Twitter limits number of users we can ask for
    var numCalls = Math.floor(len / sliceSize) + 1;

    for (var i = 0; i < numCalls; i++) {
        var staticIndex = i;

        var slice;
        if (friendList.length > (staticIndex * sliceSize) + sliceSize) {
            slice = friendList.slice(staticIndex * sliceSize, (staticIndex * sliceSize) + sliceSize);
        } else {
            slice = friendList.slice(staticIndex * sliceSize);
        }

        // build up a comma delimited list of twitter user ids
        var twitterIds = "";
        $.each(slice, function(i, item) {
            twitterIds = twitterIds + "," + item;
        });
        twitterIds = twitterIds.substring(1); // strip leading comma

        deferreds.push(searchTwitterDetailsForGoogleProfileInfo(twitterIds));
    }

    return deferreds;
}

function searchTwitterDetailsForGoogleProfileInfo(friendIdSlice) {

    return $.ajax("http://api.twitter.com/1/users/lookup.json", {
        data: {user_id: friendIdSlice},
        dataType: "jsonp"
    }).success(function(twitterFriendInfo) {

            //$('#staticProgress').text($('#staticProgress').text()+'.');

            // we examine various parts to see if any Google+ info is stored
            $.each(twitterFriendInfo, function(i, item) {

                var found = false;

                var id = item.id_str;
                var url = item.url;
                var desc = item.description;
                var screenName = item.screen_name;

                var friendData = {
                    twitterId: id,
                    screen_name: screenName,
                    url: url,
                    desc: desc,
                    googleLink: ""
                };

                $.data(document.body, "friendData" + id, friendData);

                var isKnownUrl = false;
                if (url != null && url.indexOf('gplus.to') > -1) {
                    friendData.googleLink = url;
                    isKnownUrl = true;
                } else if (url != null && url.indexOf('plus.google.com') > -1) {
                    friendData.googleLink = url;
                    isKnownUrl = true;
                } else if (desc != null && desc.indexOf('gplus.to') > -1) {
                    friendData.googleLink = desc;
                } else if (desc != null && desc.indexOf('plus.google.com') > -1) {
                    friendData.googleLink = desc;
                }

                if (friendData.googleLink !== "") {
                    nastyGlobal++
                    var display = '';
                    if(isKnownUrl){
                        display = ''+friendData.screen_name+'';
                    }else{
                        display = friendData.screen_name + ", " + friendData.googleLink;
                    }

                    $("#userDetails").append("
" + display + "
");
                } else {
                    //logProgress('not found');
                }
            });
        });
}

function kickOffSlowGoogleProfileSearchInWebWorker(friendList) {
    logProgress('Beginning slow search, could take a while.. Grab a drink');
    logProgress('Google+ profile links will appear as they are found');

    var worker = new Worker("javascripts/worker.js");

    worker.onmessage = function(event) {
        var workerData = JSON.parse(event.data);

        if (workerData.messageType === "logMessage") {
            //logProgress("from worker: " + workerData.message);
            if(workerData.message.indexOf('omplete')> -1){
                logProgress('** Search Complete **');
                $("#userDetails").append("
** Search Complete **
");
                $("#userDetails").append("
--
");
                var perc = Math.floor((nastyGlobal / friendCount)*100);
                $("#userDetails").append("
Sadly, only "+perc+"% of your twitter friends were found.
");
                $("#userDetails").append("
YOU can improve your own results!
");
                $("#userDetails").append("
Spread the word, ask folks on Twitter to go to
");
                $("#userDetails").append("
gplus.to and get themselves a name that matches their twitter name
");
                $("#userDetails").append("
- and ideally, they add their gplus.to name to their twitter url or bio
");
                $("#userDetails").append("
- then come back in a while to get much better results.
");

                $('#loader').hide();
            }
            //$('#staticProgress').text($('#staticProgress').text()+'.');
        } else {
            if (workerData.found) {
                nastyGlobal++;
                var friendData = $.data(document.body, "friendData" + workerData.id);
                friendData.googleLink = "http://gplus.to/" + friendData.screen_name;

                var info = "" +friendData.screen_name +"";
                $("#userDetails").append("
" + info + "
");
            }
        }
    }

    worker.onerror = function(event) {
        alert(event.message);
        event.preventDefault();
    }

    var friendData = {};
    $.each(friendList, function(i, item) {
        var retrieved = $.data(document.body, "friendData" + item);
        friendData[item + ''] = retrieved;
    });

    var address = $('#hiddenUrl').val();
    var port = $('#hiddenPort').val();

    var url = "http://"+address+":"+port+"/search/";
//alert(url);
    var messageToWorker = {
        baseUrl: url,
        friendIdSlice: friendList,
        friendData: friendData
    };

    worker.postMessage(JSON.stringify(messageToWorker));
}

// unused, can be called directly to test server side search for google+
function findGPlusPage(screenName) {
    $.ajax({
        async:false,
        url: "http://0.0.0.0:3000/search/" + screenName,
        dataType: "json",

        success: function(data) {
            var foundIndicator = data;

            var info = screenName + ", " + foundIndicator;
            $("#userDetails").append("
" + info + "
");
            debugger;
        },
        error: function(x, t, e) {
            alert("something broke");
        }
    });
}

<commit_msg>Figuring out dotcloud issue<commit_after>    var nastyGlobal = 0;    var friendCount = 0;

$(function() {

    checkTwitterApiLimit();

    $('#doWork').click(function() {
        $('ul li').remove();

        logProgress("Working..");

          var friendListCall = getTwitterFriendList($('#searchName').val());

        friendListCall.success(function(friendList) {

            friendCount = friendList.length;
            var deferredTwitterCalls = buildSetOfDeferredTwitterDetailCalls(friendList);

            $.when.apply($, deferredTwitterCalls).then(function() {
                kickOffSlowGoogleProfileSearchInWebWorker(friendList);
            });
        });

        friendListCall.error(function(jqXHR, textStatus, error){
            alert('Please ensure you use a valid twitter username');
            logProgress("Actually, not working.. double check your twitter name");
        })
    });
});

function checkTwitterApiLimit(){
    $('#doWork').attr('disabled', true);
    $('#searchName').attr('disabled', true);
    $('#sorryOverLimit').hide();
    $('#loader').hide();

    $.ajax({
        url:"http://api.twitter.com/1/account/rate_limit_status.json",
        dataType:"jsonp"
    }).success(function(rateInfo){
        if(rateInfo.remaining_hits<10){
            $('#sorryOverLimit').show();
        }else{
            $('#doWork').attr('disabled', false);
            $('#searchName').attr('disabled', false);
        };
    });
}

function logProgress(info) {
    $("#progress").append("
" + info + "
");
}

function getTwitterFriendList(searchName) {
    return $.ajax({
        url: "http://api.twitter.com/1/friends/ids.json",
        data: {screen_name: searchName},
        dataType: "jsonp",
        timeout: 5000
    });
}

function buildSetOfDeferredTwitterDetailCalls(friendList) {

    var deferreds = [];

    // chunk into calls of 100 friends
    var sliceSize = 100;
    var len = friendList.length;

    logProgress("Number of friends found: " + len);
    logProgress("Beginning fast search");
    logProgress('Retrieving details of your twitter friends');

    logProgress('--');
    logProgress("Sadly, only a small percentage of your twitter friends will be found");
    logProgress("YOU can improve your own results!");
    logProgress("Spread the word, ask folks on Twitter to go to");
    logProgress("gplus.to and get themselves a name that matches their twitter name");
    logProgress('--');

    $('#loader').show();

    // we chunk our calls to Twitter to return user details, as Twitter limits number of users we can ask for
    var numCalls = Math.floor(len / sliceSize) + 1;

    for (var i = 0; i < numCalls; i++) {
        var staticIndex = i;

        var slice;
        if (friendList.length > (staticIndex * sliceSize) + sliceSize) {
            slice = friendList.slice(staticIndex * sliceSize, (staticIndex * sliceSize) + sliceSize);
        } else {
            slice = friendList.slice(staticIndex * sliceSize);
        }

        // build up a comma delimited list of twitter user ids
        var twitterIds = "";
        $.each(slice, function(i, item) {
            twitterIds = twitterIds + "," + item;
        });
        twitterIds = twitterIds.substring(1); // strip leading comma

        deferreds.push(searchTwitterDetailsForGoogleProfileInfo(twitterIds));
    }

    return deferreds;
}

function searchTwitterDetailsForGoogleProfileInfo(friendIdSlice) {

    return $.ajax("http://api.twitter.com/1/users/lookup.json", {
        data: {user_id: friendIdSlice},
        dataType: "jsonp"
    }).success(function(twitterFriendInfo) {

            //$('#staticProgress').text($('#staticProgress').text()+'.');

            // we examine various parts to see if any Google+ info is stored
            $.each(twitterFriendInfo, function(i, item) {

                var found = false;

                var id = item.id_str;
                var url = item.url;
                var desc = item.description;
                var screenName = item.screen_name;

                var friendData = {
                    twitterId: id,
                    screen_name: screenName,
                    url: url,
                    desc: desc,
                    googleLink: ""
                };

                $.data(document.body, "friendData" + id, friendData);

                var isKnownUrl = false;
                if (url != null && url.indexOf('gplus.to') > -1) {
                    friendData.googleLink = url;
                    isKnownUrl = true;
                } else if (url != null && url.indexOf('plus.google.com') > -1) {
                    friendData.googleLink = url;
                    isKnownUrl = true;
                } else if (desc != null && desc.indexOf('gplus.to') > -1) {
                    friendData.googleLink = desc;
                } else if (desc != null && desc.indexOf('plus.google.com') > -1) {
                    friendData.googleLink = desc;
                }

                if (friendData.googleLink !== "") {
                    nastyGlobal++
                    var display = '';
                    if(isKnownUrl){
                        display = ''+friendData.screen_name+'';
                    }else{
                        display = friendData.screen_name + ", " + friendData.googleLink;
                    }

                    $("#userDetails").append("
" + display + "
");
                } else {
                    //logProgress('not found');
                }
            });
        });
}

function kickOffSlowGoogleProfileSearchInWebWorker(friendList) {
    logProgress('Beginning slow search, could take a while.. Grab a drink');
    logProgress('Google+ profile links will appear as they are found');

    var worker = new Worker("javascripts/worker.js");

    worker.onmessage = function(event) {
        var workerData = JSON.parse(event.data);

        if (workerData.messageType === "logMessage") {
            //logProgress("from worker: " + workerData.message);
            if(workerData.message.indexOf('omplete')> -1){
                logProgress('** Search Complete **');
                $("#userDetails").append("
** Search Complete **
");
                $("#userDetails").append("
--
");
                var perc = Math.floor((nastyGlobal / friendCount)*100);
                $("#userDetails").append("
Sadly, only "+perc+"% of your twitter friends were found.
");
                $("#userDetails").append("
YOU can improve your own results!
");
                $("#userDetails").append("
Spread the word, ask folks on Twitter to go to
");
                $("#userDetails").append("
gplus.to and get themselves a name that matches their twitter name
");
                $("#userDetails").append("
- and ideally, they add their gplus.to name to their twitter url or bio
");
                $("#userDetails").append("
- then come back in a while to get much better results.
");

                $('#loader').hide();
            }
            //$('#staticProgress').text($('#staticProgress').text()+'.');
        } else {
            if (workerData.found) {
                nastyGlobal++;
                var friendData = $.data(document.body, "friendData" + workerData.id);
                friendData.googleLink = "http://gplus.to/" + friendData.screen_name;

                var info = "" +friendData.screen_name +"";
                $("#userDetails").append("
" + info + "
");
            }
        }
    }

    worker.onerror = function(event) {
        alert(event.message);
        event.preventDefault();
    }

    var friendData = {};
    $.each(friendList, function(i, item) {
        var retrieved = $.data(document.body, "friendData" + item);
        friendData[item + ''] = retrieved;
    });

    var address = $('#hiddenUrl').val();
    var port = $('#hiddenPort').val();

    var url = "http://"+address+":"+port+"/search/";
alert(url);
    var messageToWorker = {
        baseUrl: url,
        friendIdSlice: friendList,
        friendData: friendData
    };

    worker.postMessage(JSON.stringify(messageToWorker));
}

// unused, can be called directly to test server side search for google+
function findGPlusPage(screenName) {
    $.ajax({
        async:false,
        url: "http://0.0.0.0:3000/search/" + screenName,
        dataType: "json",

        success: function(data) {
            var foundIndicator = data;

            var info = screenName + ", " + foundIndicator;
            $("#userDetails").append("
" + info + "
");
            debugger;
        },
        error: function(x, t, e) {
            alert("something broke");
        }
    });
}

<|endoftext|>


<commit_before>const AUTH_KEY = 'auth_client_side'

const setAuth = () => {
    try {
        sessionStorage.setItem(AUTH_KEY, '1');
    } catch (err) { }
}

const isAuth = () => {
    try {
        return sessionStorage.getItem(AUTH_KEY) === '1';
    } catch (err) {
        return false
    }
}

export default ({
    Vue, // the version of Vue being used in the VuePress app
    options, // the options for the root Vue instance
    router, // the router instance for the app
    siteData, // site metadata
    isServer // is this enhancement applied in server-rendering or client
}) => {
    router.beforeEach((to, from, next) => {
        if (siteData.themeConfig.protected.paths.includes(to.path)) {
            if (isAuth() || prompt() == siteData.themeConfig.protected.pass) {
                setAuth()
                next()
            } else {
                next("/")
            }
        } else {
            next()
        }
    })
}<commit_msg>Fix pre-rendering<commit_after>const AUTH_KEY = 'auth_client_side'

const setAuth = () => {
    try {
        sessionStorage.setItem(AUTH_KEY, '1');
    } catch (err) { }
}

const isAuth = () => {
    try {
        return sessionStorage.getItem(AUTH_KEY) === '1';
    } catch (err) {
        return false
    }
}

const askForPass = () => {
    try {
        return prompt()
    } catch (err) {
        return ""
    }
}

export default ({
    Vue, // the version of Vue being used in the VuePress app
    options, // the options for the root Vue instance
    router, // the router instance for the app
    siteData, // site metadata
    isServer // is this enhancement applied in server-rendering or client
}) => {
    router.beforeEach((to, from, next) => {
        if (siteData.themeConfig.protected.paths.includes(to.path)) {
            if (isAuth() || askForPass() === siteData.themeConfig.protected.pass) {
                setAuth()
                next()
            } else {
                next("/")
            }
        } else {
            next()
        }
    })
}<|endoftext|>