<commit_before>/* IndieSocial
JavaScript library which provide social sharing links without foreign scripts
License: CC0 1.0, https://creativecommons.org/publicdomain/zero/1.0/
Repo: https://github.com/komachi/indiesocial */
var services = {
  'facebook': {
    'URL': 'https://facebook.com/sharer.php?u=',
    'title' : '&t=',
    'fontello': 'facebook',
    'name' : 'Facebook'
  },
  'twitter' : {
    'URL': 'https://twitter.com/share?url=',
    'title': '&text=',
    'fontello': 'twitter',
    'name' : 'Twitter'
  },
  'vk' : {
    'URL': 'http://vk.com/share.php?url=',
    'fontello': 'vkontakte-rect',
    'title' : '&title=',
    'name' : 'VK'
  },
  'googleplus' : {
    'URL': 'https://plus.google.com/share?url=',
    'fontello': 'googleplus-rect',
    'name' : 'Google+'
  },
  'odnoklassniki' : {
    'URL': 'http://odnoklassniki.ru/dk?st.cmd=addShare&st._surl=',
    'title' : '&title=',
    'fontello': 'odnoklassniki',
    'name' : 'Одноклассники'
  },
  'friendfeed' : {
    'URL': 'http://friendfeed.com/?url=',
    'title' : '&title=',
    'fontello': 'friendfeed',
    'name' : 'FriendFeed'
  },
  'linkedin' : {
    'URL': 'http://linkedin.com/shareArticle?mini=true&url=',
    'title' : '&title=',
    'fontello': 'linkedin',
    'name' : 'LinkedIn'
  },
  'tumblr' : {
    'URL': 'http://tumblr.com/share/link?url=',
    'title' : '&name=',
    'fontello': 'tumblr',
    'name' : 'Tumblr'
  },
  'blogger' : {
    'URL': 'http://blogger.com/blog_this.pyra?u=',
    'title' : '&n=',
    'fontello': 'blogger',
    'name' : 'Blogger'
  },
  'diigo' : {
    'URL': 'https://www.diigo.com/post?url=',
    'title' : '&title=',
    'fontello': 'diigo',
    'name' : 'Diigo'
  },
  'reddit' : {
    'URL': 'http://reddit.com/submit?url=',
    'title' : '&title=',
    'fontello': 'reddit',
    'name' : 'Reddit'
  },
  'delicious' : {
    'URL': 'http://delicious.com/post/?url=',
    'title' : '&title=',
    'fontello': 'delicious',
    'name' : 'Delicious'
  },
  'digg' : {
    'URL': 'http://digg.com/submit?phase=2&url=',
    'title' : '&title=',
    'fontello': 'digg',
    'name' : 'Digg'
  },
  'stumbleupon' : {
    'URL': 'http://www.stumbleupon.com/submit?url=',
    'title' : '&title=',
    'fontello': 'stumbleupon',
    'name' : 'StumbleUpon'
  },
  'pinterest' : {
    'URL': 'http://pinterest.com/pin/create/link/?url=',
    'title' : '&description=',
    'fontello': 'pinterest',
    'name' : 'Pinterest'
  },
  'evernote' : {
    'URL': 'http://www.evernote.com/clip.action?url=',
    'title' : '&title=',
    'fontello': 'evernote',
    'name' : 'Evernote'
  },
  'instapaper' : {
    'URL': 'http://www.instapaper.com/edit?url=',
    'title' : '&title=',
    'fontello': 'instapaper',
    'name' : 'Instapaper'
  },
  'hackernews' : {
    'URL': 'http://news.ycombinator.com/submitlink?u=',
    'title' : '&t=',
    'fontello': 'hackernews',
    'name' : 'Hacker News'
  }
};

if (window.addEventListener) {
  window.addEventListener("load", indieSocial, false);
} else if(window.attachEvent) {
  window.attachEvent("onload", indieSocial);
} else {
  document.addEventListener("load", indieSocial, false);
}

function indieSocial() {

  var init = document.getElementById("indiesocial-init");
  if (!init) { // if no container was created kill execution
    return;
  }

  var initServices = init.getAttribute("data-indieSocialServices");
  if (!initServices) { // no initServices attribute was created, kill
    return;
  } else {
    var seperator = "";
    if (initServices.indexOf(", ") !== -1) {
      seperator = ", ";
    } else if (initServices.indexOf(",") !== -1) {
      seperator = ",";
    } else {
      seperator = " ";
    }
    initServices = initServices.split(seperator);
  }

  var dataURL = init.getAttribute("data-URL");
  var title = init.getAttribute("data-title");
  var fontelloIcon = init.getAttribute("data-addFontelloIcon");
  var addText = init.getAttribute("data-addText");

  if (initServices[0] === "all") {
    for (var serv in services) {
      createElementService(serv);
    }
  } else {
    for (var i = 0, len = initServices.length; i < len; i++) {
      var serv = initServices[i];
      if (serv in services) {
        createElementService(serv);
      }
    }
  }

  function createElementService(service) {
    var aElement = document.createElement("a");

    if (dataURL) {
      var URL = services[service]['URL'] + dataURL;
    } else {
      var URL = services[service]['URL'] + window.location;
    }

    var titlelink = "";
    if (services[service]['title'] !== undefined && title) {
      var titlelink = services[service]['title'] + title;
    }

    aElement.setAttribute("href", encodeURI(URL + titlelink));
    aElement.setAttribute("class", "indiesocial-" + service);
    aElement.setAttribute("title", services[service]['name']);
    aElement.setAttribute("target", "_blank");

    var innerValue = "";
    if (fontelloIcon == "true") {
      var innerValue = innerValue + '';
    }
    if (addText == "true") {
      var innerValue = innerValue + services[service]['name'];
    }

    aElement.innerHTML = innerValue;
    init.appendChild(aElement);
  }
}
<commit_msg>Delete trailing spaces<commit_after>/* IndieSocial
JavaScript library which provide social sharing links without foreign scripts
License: CC0 1.0, https://creativecommons.org/publicdomain/zero/1.0/
Repo: https://github.com/komachi/indiesocial */
var services = {
  'facebook': {
    'URL': 'https://facebook.com/sharer.php?u=',
    'title' : '&t=',
    'fontello': 'facebook',
    'name' : 'Facebook'
  },
  'twitter' : {
    'URL': 'https://twitter.com/share?url=',
    'title': '&text=',
    'fontello': 'twitter',
    'name' : 'Twitter'
  },
  'vk' : {
    'URL': 'http://vk.com/share.php?url=',
    'fontello': 'vkontakte-rect',
    'title' : '&title=',
    'name' : 'VK'
  },
  'googleplus' : {
    'URL': 'https://plus.google.com/share?url=',
    'fontello': 'googleplus-rect',
    'name' : 'Google+'
  },
  'odnoklassniki' : {
    'URL': 'http://odnoklassniki.ru/dk?st.cmd=addShare&st._surl=',
    'title' : '&title=',
    'fontello': 'odnoklassniki',
    'name' : 'Одноклассники'
  },
  'friendfeed' : {
    'URL': 'http://friendfeed.com/?url=',
    'title' : '&title=',
    'fontello': 'friendfeed',
    'name' : 'FriendFeed'
  },
  'linkedin' : {
    'URL': 'http://linkedin.com/shareArticle?mini=true&url=',
    'title' : '&title=',
    'fontello': 'linkedin',
    'name' : 'LinkedIn'
  },
  'tumblr' : {
    'URL': 'http://tumblr.com/share/link?url=',
    'title' : '&name=',
    'fontello': 'tumblr',
    'name' : 'Tumblr'
  },
  'blogger' : {
    'URL': 'http://blogger.com/blog_this.pyra?u=',
    'title' : '&n=',
    'fontello': 'blogger',
    'name' : 'Blogger'
  },
  'diigo' : {
    'URL': 'https://www.diigo.com/post?url=',
    'title' : '&title=',
    'fontello': 'diigo',
    'name' : 'Diigo'
  },
  'reddit' : {
    'URL': 'http://reddit.com/submit?url=',
    'title' : '&title=',
    'fontello': 'reddit',
    'name' : 'Reddit'
  },
  'delicious' : {
    'URL': 'http://delicious.com/post/?url=',
    'title' : '&title=',
    'fontello': 'delicious',
    'name' : 'Delicious'
  },
  'digg' : {
    'URL': 'http://digg.com/submit?phase=2&url=',
    'title' : '&title=',
    'fontello': 'digg',
    'name' : 'Digg'
  },
  'stumbleupon' : {
    'URL': 'http://www.stumbleupon.com/submit?url=',
    'title' : '&title=',
    'fontello': 'stumbleupon',
    'name' : 'StumbleUpon'
  },
  'pinterest' : {
    'URL': 'http://pinterest.com/pin/create/link/?url=',
    'title' : '&description=',
    'fontello': 'pinterest',
    'name' : 'Pinterest'
  },
  'evernote' : {
    'URL': 'http://www.evernote.com/clip.action?url=',
    'title' : '&title=',
    'fontello': 'evernote',
    'name' : 'Evernote'
  },
  'instapaper' : {
    'URL': 'http://www.instapaper.com/edit?url=',
    'title' : '&title=',
    'fontello': 'instapaper',
    'name' : 'Instapaper'
  },
  'hackernews' : {
    'URL': 'http://news.ycombinator.com/submitlink?u=',
    'title' : '&t=',
    'fontello': 'hackernews',
    'name' : 'Hacker News'
  }
};

if (window.addEventListener) {
  window.addEventListener("load", indieSocial, false);
} else if(window.attachEvent) {
  window.attachEvent("onload", indieSocial);
} else {
  document.addEventListener("load", indieSocial, false);
}

function indieSocial() {

  var init = document.getElementById("indiesocial-init");
  if (!init) { // if no container was created kill execution
    return;
  }

  var initServices = init.getAttribute("data-indieSocialServices");
  if (!initServices) { // no initServices attribute was created, kill
    return;
  } else {
    var seperator = "";
    if (initServices.indexOf(", ") !== -1) {
      seperator = ", ";
    } else if (initServices.indexOf(",") !== -1) {
      seperator = ",";
    } else {
      seperator = " ";
    }
    initServices = initServices.split(seperator);
  }

  var dataURL = init.getAttribute("data-URL");
  var title = init.getAttribute("data-title");
  var fontelloIcon = init.getAttribute("data-addFontelloIcon");
  var addText = init.getAttribute("data-addText");

  if (initServices[0] === "all") {
    for (var serv in services) {
      createElementService(serv);
    }
  } else {
    for (var i = 0, len = initServices.length; i < len; i++) {
      var serv = initServices[i];
      if (serv in services) {
        createElementService(serv);
      }
    }
  }

  function createElementService(service) {
    var aElement = document.createElement("a");

    if (dataURL) {
      var URL = services[service]['URL'] + dataURL;
    } else {
      var URL = services[service]['URL'] + window.location;
    }

    var titlelink = "";
    if (services[service]['title'] !== undefined && title) {
      var titlelink = services[service]['title'] + title;
    }

    aElement.setAttribute("href", encodeURI(URL + titlelink));
    aElement.setAttribute("class", "indiesocial-" + service);
    aElement.setAttribute("title", services[service]['name']);
    aElement.setAttribute("target", "_blank");

    var innerValue = "";
    if (fontelloIcon == "true") {
      var innerValue = innerValue + '';
    }
    if (addText == "true") {
      var innerValue = innerValue + services[service]['name'];
    }

    aElement.innerHTML = innerValue;
    init.appendChild(aElement);
  }
}
<|endoftext|>


<commit_before>import { createStore, compose, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import { routeReducer, syncHistory } from 'react-router-redux';

// custom reducers
import searchReducer from '../reducers/search_reducer.js';

// add history to reducer and thunk to dispatch functions as actions
const ConfigureStore = (initialState, history) => {
  const reducerObj = {
    searchResults: searchReducer,
    routing: routeReducer,
  };
  const reducer = combineReducers(reducerObj);

  const store = compose(
    applyMiddleware(thunk),
    applyMiddleware(syncHistory(history))
  )(createStore)(reducer, initialState);
  return store;
};

export default ConfigureStore;
<commit_msg>dev test changes<commit_after>import { createStore, compose, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import { routeReducer, syncHistory } from 'react-router-redux';

// custom reducers
import searchReducer from '../reducers/search_reducer.js';

// add history to reducer and thunk to dispatch functions as actions
const ConfigureStore = (initialState, history) => {
  const reducerObj = {
    searchResults: searchReducer,
    routing: routeReducer,
  };
  const reducer = combineReducers(reducerObj);
  if (process.env.NODE_ENV == 'development'){
    //redux debugging
    const store = compose(applyMiddleware(thunk), applyMiddleware(syncHistory(history)))(createStore)(reducer, initialState, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
    return store;
  }
  else{
    const store = compose(applyMiddleware(thunk), applyMiddleware(syncHistory(history)))(createStore)(reducer, initialState);
    return store;
  }

};

export default ConfigureStore;
<|endoftext|>


<commit_before>'use strict';

module.exports =

/*@ngInject*/
function ProofreadingPlayCtrl(
  $scope, $state, ProofreadingService, RuleService, _
) {
  $scope.id = $state.params.uid;

  //If brainpop is truthy, we setup some scope state
  //that the template will react to. The template
  //adds the brainpop script and assigns an id to the div
  if ($state.params.brainpop) {
    $scope.brainpop = 'BrainPOPsnapArea';
  }

  function error(e) {
    $state.go('index');
  }

  $scope.obscure = function(key) {
    return btoa(key);
  };

  $scope.ubObscure = function(o) {
    return atob(o);
  };

  ProofreadingService.getProofreading($scope.id).then(function(pf) {
    pf.passage = ProofreadingService.prepareProofreading(pf.passage, $scope);
    $scope.pf = pf;
    fetchListedRules();
  }, error);

  /*
   * Functions for interacting with the referenced rules in the
   * passage questions.
   */

  function fetchListedRules() {
    var ruleIds = _.pluck($scope.passageQuestions, 'ruleNumber');
    RuleService.getRules(ruleIds).then(function(rules) {
      $scope.referencedRules = rules;
    });
  }

  $scope.getRuleInfoBy = function(ruleNumber) {
    return _.findWhere($scope.referencedRules, {ruleNumber: Number(ruleNumber)}).title;
  };

  /*
   * These functions below handle submission errors
   * and state/$scope updates after the student has submitted
   * their passage.
   */

  $scope.UNSOLVED_ERROR = 'UNSOLVED_ERROR';
  $scope.INTRODUCED_ERROR = 'INTRODUCED_ERROR';
  $scope.SOLVED_PROBLEM = 'SOLVED_PROBLEM';

  $scope.hasIntroducedError = function(word) {
    return word.type === $scope.INTRODUCED_ERROR;
  };

  $scope.hasUnsolvedError = function(word) {
    return word.type === $scope.UNSOLVED_ERROR;
  };

  $scope.hasSolvedProblem = function(word) {
    return word.type === $scope.SOLVED_PROBLEM;
  };

  $scope.groupNameBy = function(key) {
    if (key === $scope.UNSOLVED_ERROR) {
      return  'Unsolved Problem(s)';
    } else if (key === $scope.INTRODUCED_ERROR) {
      return 'Introduced Problem(s)';
    } else if (key === $scope.SOLVED_PROBLEM) {
      return 'Solved Problems(s)';
    }
  };

  $scope.submitPassage = function() {
    var passage = $scope.pf.passage;
    $scope.submitted = true;
    function isValid(passageEntry) {
      if (_.has(passageEntry, 'minus')) {
        //A grammar entry
        return passageEntry.responseText === passageEntry.plus;
      } else {
        //A regular word
        return passageEntry.text === passageEntry.responseText;
      }
    }
    function getErrorType(passageEntry) {
      return _.has(passageEntry, 'minus') ? $scope.UNSOLVED_ERROR : $scope.INTRODUCED_ERROR;
    }
    var results = [];
    _.each(passage, function(p, i) {
      if (!isValid(p)) {
        results.push({index: i, passageEntry: p, type: getErrorType(p)});
      }
      if (isValid(p) && _.has(p, 'minus')) {
        results.push({index: i, passageEntry: p, type: $scope.SOLVED_PROBLEM});
      }
    });
    var numErrorsToSolve = _.keys($scope.passageQuestions).length;
    var numErrorsFound = _.where(results, {type: $scope.SOLVED_PROBLEM}).length;
    console.log(numErrorsFound, numErrorsToSolve);
    if (numErrorsFound < numErrorsToSolve / 2) {
      showModalNotEnoughFound();
    } else if (results.length > 1) {
      showResults(results);
    } else {
      showNext();
    }
  };

  /*
   * Modal settings
   */
  function showModalNotEnoughFound() {
    $scope.pf.modal = {
      title: 'Keep Trying!',
      message: 'You need to find at least 50% of the errors.',
      buttonMessage: 'Find Errors',
      buttonClick: function() {
        $scope.pf.modal.show = false;
      },
      show: true
    };
  }

  /*
   * Convience html methods
   */

  $scope.needsUnderlining = function(p) {
    if ($scope.pf && $scope.pf.underlineErrorsInProofreader && _.has(p, 'minus')) {
      return true;
    }
  };

  $scope.isBr = function(text) {
    return ProofreadingService.htmlMatches(text) !== null;
  };

  function showResults(passageResults) {
    _.each(passageResults, function(pr) {
      $scope.pf.passage[pr.index].type = pr.type;
    });
    $scope.results = passageResults;
    var ruleNumbers = _.chain(passageResults)
      .pluck('passageEntry')
      .reject(function(r) {
        return r.type !== $scope.UNSOLVED_ERROR;
      })
      .pluck('ruleNumber')
      .reject(_.isUndefined)
      .uniq()
      .value();
    generateLesson(ruleNumbers);
    captureReady();
  }

  /*
   * Below when handle building the lesson and showing
   * the appropriate ui.
   */

  function generateLesson(ruleNumbers) {
    $scope.goToLesson = function() {
      $state.go('play-sw-gen', {
        ids: ruleNumbers
      });
    };
    $scope.hasLesson = true;
  }

  /*
   * Below handles setting the state, if the lesson
   * was completed without error.
   */

  function showNext() {

  }
};
<commit_msg>Show results modal if greater than 50% errors found<commit_after>'use strict';

module.exports =

/*@ngInject*/
function ProofreadingPlayCtrl(
  $scope, $state, ProofreadingService, RuleService, _
) {
  $scope.id = $state.params.uid;

  //If brainpop is truthy, we setup some scope state
  //that the template will react to. The template
  //adds the brainpop script and assigns an id to the div
  if ($state.params.brainpop) {
    $scope.brainpop = 'BrainPOPsnapArea';
  }

  function error(e) {
    $state.go('index');
  }

  $scope.obscure = function(key) {
    return btoa(key);
  };

  $scope.ubObscure = function(o) {
    return atob(o);
  };

  ProofreadingService.getProofreading($scope.id).then(function(pf) {
    pf.passage = ProofreadingService.prepareProofreading(pf.passage, $scope);
    $scope.pf = pf;
    fetchListedRules();
  }, error);

  /*
   * Functions for interacting with the referenced rules in the
   * passage questions.
   */

  function fetchListedRules() {
    var ruleIds = _.pluck($scope.passageQuestions, 'ruleNumber');
    RuleService.getRules(ruleIds).then(function(rules) {
      $scope.referencedRules = rules;
    });
  }

  $scope.getRuleInfoBy = function(ruleNumber) {
    return _.findWhere($scope.referencedRules, {ruleNumber: Number(ruleNumber)}).title;
  };

  /*
   * These functions below handle submission errors
   * and state/$scope updates after the student has submitted
   * their passage.
   */

  $scope.UNSOLVED_ERROR = 'UNSOLVED_ERROR';
  $scope.INTRODUCED_ERROR = 'INTRODUCED_ERROR';
  $scope.SOLVED_PROBLEM = 'SOLVED_PROBLEM';

  $scope.hasIntroducedError = function(word) {
    return word.type === $scope.INTRODUCED_ERROR;
  };

  $scope.hasUnsolvedError = function(word) {
    return word.type === $scope.UNSOLVED_ERROR;
  };

  $scope.hasSolvedProblem = function(word) {
    return word.type === $scope.SOLVED_PROBLEM;
  };

  $scope.groupNameBy = function(key) {
    if (key === $scope.UNSOLVED_ERROR) {
      return  'Unsolved Problem(s)';
    } else if (key === $scope.INTRODUCED_ERROR) {
      return 'Introduced Problem(s)';
    } else if (key === $scope.SOLVED_PROBLEM) {
      return 'Solved Problems(s)';
    }
  };

  $scope.submitPassage = function() {
    var passage = $scope.pf.passage;
    $scope.submitted = true;
    function isValid(passageEntry) {
      if (_.has(passageEntry, 'minus')) {
        //A grammar entry
        return passageEntry.responseText === passageEntry.plus;
      } else {
        //A regular word
        return passageEntry.text === passageEntry.responseText;
      }
    }
    function getErrorType(passageEntry) {
      return _.has(passageEntry, 'minus') ? $scope.UNSOLVED_ERROR : $scope.INTRODUCED_ERROR;
    }
    var results = [];
    _.each(passage, function(p, i) {
      if (!isValid(p)) {
        results.push({index: i, passageEntry: p, type: getErrorType(p)});
      }
      if (isValid(p) && _.has(p, 'minus')) {
        results.push({index: i, passageEntry: p, type: $scope.SOLVED_PROBLEM});
      }
    });
    var numErrorsToSolve = _.keys($scope.passageQuestions).length;
    var numErrorsFound = _.where(results, {type: $scope.SOLVED_PROBLEM}).length;
    if (numErrorsFound < numErrorsToSolve / 2) {
      showModalNotEnoughFound();
    } else if (results.length > 1) {
      showResultsModal(results, numErrorsFound, numErrorsToSolve);
    } else {
      showNext();
    }
  };

  /*
   * Modal settings
   */
  function showModalNotEnoughFound() {
    $scope.pf.modal = {
      title: 'Keep Trying!',
      message: 'You need to find at least 50% of the errors.',
      buttonMessage: 'Find Errors',
      buttonClick: function() {
        $scope.pf.modal.show = false;
      },
      show: true
    };
  }

  function showResultsModal(results, numErrorsFound, numErrorsToSolve) {
    var title = numErrorsFound === numErrorsToSolve ? 'Congratulations!' : 'Good Work!';
    var nf = numErrorsFound === numErrorsToSolve ? 'all ' + String(numErrorsFound) : String(numErrorsFound) + ' of ' + String(numErrorsToSolve);
    $scope.pf.modal = {
      title: title,
      message: 'You found ' + nf + ' errors',
      buttonMessage: 'Review Your Work',
      buttonClick: function() {
        $scope.pf.modal.show = false;
        showResults(results);
      },
      show: true
    };
  }

  /*
   * Convience html methods
   */

  $scope.needsUnderlining = function(p) {
    if ($scope.pf && $scope.pf.underlineErrorsInProofreader && _.has(p, 'minus')) {
      return true;
    }
  };

  $scope.isBr = function(text) {
    return ProofreadingService.htmlMatches(text) !== null;
  };

  function showResults(passageResults) {
    _.each(passageResults, function(pr) {
      $scope.pf.passage[pr.index].type = pr.type;
    });
    $scope.results = passageResults;
    var ruleNumbers = _.chain(passageResults)
      .pluck('passageEntry')
      .reject(function(r) {
        return r.type !== $scope.UNSOLVED_ERROR;
      })
      .pluck('ruleNumber')
      .reject(_.isUndefined)
      .uniq()
      .value();
    generateLesson(ruleNumbers);
    captureReady();
  }

  /*
   * Below when handle building the lesson and showing
   * the appropriate ui.
   */

  function generateLesson(ruleNumbers) {
    $scope.goToLesson = function() {
      $state.go('play-sw-gen', {
        ids: ruleNumbers
      });
    };
    $scope.hasLesson = true;
  }

  /*
   * Below handles setting the state, if the lesson
   * was completed without error.
   */

  function showNext() {

  }
};
<|endoftext|>


<commit_before>(function(global){

	function Fusen(canvas, ds, _id, text, color, fusenNumber) {
		var self = this;
		this.id = _id;
		this.ds = ds;
    this.pos = {x : 0, y : 0};
		this.text = text;
		this.linkedText = fusen_util.linknize( fusen_util.htmlEscape(text) );
		this.color = color;
		this.canvas = canvas;
		this.fusenNumber = fusenNumber;
		this.$el_fusen = $("#"+self.id);
		this.dragging = false;

		// 削除ボタンのレイアウト等
    if (fusen_util.getDevice() == "mobile") {
      this.canvas.append( self.mobilehtml() );
    } else {
      this.canvas.append( self.pchtml() );
    }

	}

	Fusen.prototype.setAllListeners = function(){
		var self = this;
    self.setEditListener();
    self.setFavoriteListener();
    self.setDragListener();
    self.setCrossListener();
    if (fusen_util.getDevice() == "mobile") self.setMobileDelete();
	}
			/*
			* Private Listeners
			*/
			Fusen.prototype.setMobileDelete = function(){
		    var interval = 720;

		    $("#"+self.id).bind( "touchstart", function(e){
		      timer = setTimeout( function(){
		        if ( confirm("このメッセージを削除しますか？") === true ){
		          self.ds.remove(self.id);
		        }
		      }, interval );

		      function clearFunction(){
		        clearTimeout( timer );
		      }

		      $("#"+self.id).bind( "touchend touchmove touchcancel", clearFunction );
		      e.stopPropagation();
		    });

			}

			Fusen.prototype.setEditListener = function(){
				var self = this;

				// 「再生」後の付箋は不可っぽい
				$("#"+self.id).click(function(e){
					e.stopPropagation();

					if(self.dragging == false){
						$self = $(this);
						var $el_acm = $self.html();
						var when_clicked_text = $self.find("span").text();
						$self.find("span").hide();
						$input = $self.find("input");
						$input.val(when_clicked_text);
						$input.css("display", "inline");
						$input.focus();
						$input.off("keyup").on("keyup", function(e){
							$_input = $(this);
							var when_entered_text = $_input.val();

							// ENTER
							if(e.which == 13){
								self.ds.set(self.id+"", {text: when_entered_text},function(err, datum){
									hideInput(when_entered_text);
								});
							}

							// ESC
			       	if (e.which == 27) hideInput();
							function hideInput() {
								$input.hide();
								$self.html($el_acm);
							}
						});
					}
				});
				$("#"+self.id).find("a").click(function(e){ e.stopPropagation(); });
			}

			Fusen.prototype.setCrossListener = function(){
				var self = this;

				// 削除ボタン
		    var cross = $(".p-husen__cross", "#"+this.id);
				// ばってんクリック時の削除処理
		    cross.click(function(e) {
		      self.ds.remove(self.id);
		      e.stopPropagation();
		    });
			}

			Fusen.prototype.setDragListener = function(){
				var self = this;

				// ドラッグボタン
				var zoom = ($('.body-zoom').css('zoom')) ? $('.body-zoom').css('zoom') : 1;
				console.log(zoom);
				var factor = ((1 / zoom) -1);
		    $("#"+self.id).draggable({
		      start: function(e, ui) {
						self.dragging = true;
		      },
		      drag: function(e, ui) {
						var pos = ui.position;

						// 変換前にオブジェクトに保存してはいけない
		        ui.position.top += Math.round((ui.position.top - ui.originalPosition.top) * factor);
		        ui.position.left += Math.round((ui.position.left - ui.originalPosition.left) * factor);

						// 変換後にオブジェクトに保存すると健全
		        self.pos.x = ui.position.left;
		        self.pos.y = ui.position.top;
		      },
		      stop: function(e, ui) {
		        self.ds.set(self.id, {
		          x : self.pos.x,
		          y : self.pos.y,
							text : $("#"+self.id+" span:first").text()
		        });
		        self.setPos(self.pos.x, self.pos.y);
						setTimeout(function(){ self.dragging = false;}, 300);
		      }
		    });
			}

	Fusen.prototype.setPos = function(x, y) {
		var self = this;

		self.pos.x = x;
		self.pos.y = y;
		$("#" + self.id).offset({top : self.pos.y, left : self.pos.x});

		if( (self.pos.y + $("#"+self.id).height()) > self.canvas.height()){
			self.canvas.css( "height", (self.pos.y + $("#"+self.id).outerHeight())+"px" );
		}
		if( (self.pos.x + $("#"+self.id).width()) > self.canvas.width()){
			self.canvas.css( "width", (self.pos.x + $("#"+self.id).outerWidth())+"px" );
      $("#header").css( "width", (self.pos.x + $("#"+self.id).outerWidth())+"px" );
		}
	}

	Fusen.prototype.setText = function(text) {
		this.text = text;
		this.linkedText = fusen_util.linknize( fusen_util.htmlEscape(text) );
		var self = this;

		$("#" + this.id).find("span").html(self.linkedText);
	}

	Fusen.prototype.removeSelf = function() {
		var self = this;
		$("#" + self.id).remove();
	}

	Fusen.prototype.colorAdjust = function(){
		var self = this;
		var fusen_color = self.$el_fusen.css("border-color");
		var brighter_color = chroma(fusen_color).saturate(2);
		var darker_color = chroma(fusen_color).darken();
		var ratio = self.fusenNumber/100;
		if(ratio > 1) ratio = 1;
		var new_color = chroma.scale([darker_color, brighter_color])(ratio).hex();
		self.$el_fusen.css("color", new_color);
		self.$el_fusen.css("border-color", new_color);
	}

	Fusen.prototype.pchtml = function(){
		var self = this;
		return ''+
			'
'+
				''+self.linkedText+''+
				'<input type="text" style="display:none;" />'+
				'
×
'+
				'
★
'+
			'
';
	}

	Fusen.prototype.setFavoriteListener = function () {
		var self = this;
		var ds_star = milkcocoa.dataStore("fusen-stars__"+self.id);

		ds_star.stream().size(999).next(function(err, data) {
			var $star = $("#"+self.id).find(".p-husen__star-ever");
			if(data.length > 0){
				$star.removeClass("p-husen__star-ever");
				$star.addClass("p-husen__star-pushed");
			}
			$star.text("★"+data.length);
		});

		ds_star.on("push", function(data){
			var $star = $("#"+self.id).find("[class^='p-husen__star-']");
			var num = parseInt( $star.text().substr(1) );
			$star.text("★"+(num+1));
		});

		ds_star.on("remove", function(data){
			var $star = $("#"+self.id).find(".p-husen__star-ever");
			var num = parseInt( $star.text().substr(1) );
			$star.text("★"+(num-1));
		});

		$("#"+self.id).find(".p-husen__star-ever").off().click(function(e){
			e.stopPropagation();
			$(this).removeClass("p-husen__star-ever");
			$(this).addClass("p-husen__star-pushed");
			ds_star.push({});
		});

		$("#"+self.id).find(".p-husen__star-pushed").off().click(function(e){
			e.stopPropagation();
			$(this).removeClass("p-husen__star-pushed");
			$(this).addClass("p-husen__star-ever");
			ds_star.stream().size(1).next(function(err, data){
				ds_star.remove(data[0].id);
			});
		});

	}

	Fusen.prototype.mobilehtml = function(){
		var self = this;
		return ''+
			'
'+
				''+self.linkedText+''+
				'<input type="text" style="display:none;" />'+
				'
★
'+
			'
';
	}

	global.Fusen = Fusen;
}(window));
<commit_msg>onblur ESC<commit_after>(function(global){

	function Fusen(canvas, ds, _id, text, color, fusenNumber) {
		var self = this;
		this.id = _id;
		this.ds = ds;
    this.pos = {x : 0, y : 0};
		this.text = text;
		this.linkedText = fusen_util.linknize( fusen_util.htmlEscape(text) );
		this.color = color;
		this.canvas = canvas;
		this.fusenNumber = fusenNumber;
		this.$el_fusen = $("#"+self.id);
		this.dragging = false;

		// 削除ボタンのレイアウト等
    if (fusen_util.getDevice() == "mobile") {
      this.canvas.append( self.mobilehtml() );
    } else {
      this.canvas.append( self.pchtml() );
    }

	}

	Fusen.prototype.setAllListeners = function(){
		var self = this;
    self.setEditListener();
    self.setFavoriteListener();
    self.setDragListener();
    self.setCrossListener();
    if (fusen_util.getDevice() == "mobile") self.setMobileDelete();
	}
			/*
			* Private Listeners
			*/
			Fusen.prototype.setMobileDelete = function(){
		    var interval = 720;

		    $("#"+self.id).bind( "touchstart", function(e){
		      timer = setTimeout( function(){
		        if ( confirm("このメッセージを削除しますか？") === true ){
		          self.ds.remove(self.id);
		        }
		      }, interval );

		      function clearFunction(){
		        clearTimeout( timer );
		      }

		      $("#"+self.id).bind( "touchend touchmove touchcancel", clearFunction );
		      e.stopPropagation();
		    });

			}

			Fusen.prototype.setEditListener = function(){
				var self = this;

				// 「再生」後の付箋は不可っぽい
				$("#"+self.id).click(function(e){
					e.stopPropagation();

					if(self.dragging == false){
						$self = $(this);
						var $el_acm = $self.html();
						var when_clicked_text = $self.find("span").text();
						$self.find("span").hide();
						$input = $self.find("input");
						$input.val(when_clicked_text);
						$input.css("display", "inline");
						$input.focus();

						$input.off("blur").on("blur", function(e){
							hideInput();
						});
						$input.off("keyup").on("keyup", function(e){
							$_input = $(this);
							var when_entered_text = $_input.val();

							// ENTER
							if(e.which == 13){
								self.ds.set(self.id+"", {text: when_entered_text},function(err, datum){
									hideInput(when_entered_text);
								});
							}

							// ESC
			       	if (e.which == 27) hideInput();
						});
						function hideInput() {
							$input.hide();
							$self.html($el_acm);
						}
					}
				});
				$("#"+self.id).find("a").click(function(e){ e.stopPropagation(); });
			}

			Fusen.prototype.setCrossListener = function(){
				var self = this;

				// 削除ボタン
		    var cross = $(".p-husen__cross", "#"+this.id);
				// ばってんクリック時の削除処理
		    cross.click(function(e) {
		      self.ds.remove(self.id);
		      e.stopPropagation();
		    });
			}

			Fusen.prototype.setDragListener = function(){
				var self = this;

				// ドラッグボタン
				var zoom = ($('.body-zoom').css('zoom')) ? $('.body-zoom').css('zoom') : 1;
				console.log(zoom);
				var factor = ((1 / zoom) -1);
		    $("#"+self.id).draggable({
		      start: function(e, ui) {
						self.dragging = true;
		      },
		      drag: function(e, ui) {
						var pos = ui.position;

						// 変換前にオブジェクトに保存してはいけない
		        ui.position.top += Math.round((ui.position.top - ui.originalPosition.top) * factor);
		        ui.position.left += Math.round((ui.position.left - ui.originalPosition.left) * factor);

						// 変換後にオブジェクトに保存すると健全
		        self.pos.x = ui.position.left;
		        self.pos.y = ui.position.top;
		      },
		      stop: function(e, ui) {
		        self.ds.set(self.id, {
		          x : self.pos.x,
		          y : self.pos.y,
							text : $("#"+self.id+" span:first").text()
		        });
		        self.setPos(self.pos.x, self.pos.y);
						setTimeout(function(){ self.dragging = false;}, 300);
		      }
		    });
			}

	Fusen.prototype.setPos = function(x, y) {
		var self = this;

		self.pos.x = x;
		self.pos.y = y;
		$("#" + self.id).offset({top : self.pos.y, left : self.pos.x});

		if( (self.pos.y + $("#"+self.id).height()) > self.canvas.height()){
			self.canvas.css( "height", (self.pos.y + $("#"+self.id).outerHeight())+"px" );
		}
		if( (self.pos.x + $("#"+self.id).width()) > self.canvas.width()){
			self.canvas.css( "width", (self.pos.x + $("#"+self.id).outerWidth())+"px" );
      $("#header").css( "width", (self.pos.x + $("#"+self.id).outerWidth())+"px" );
		}
	}

	Fusen.prototype.setText = function(text) {
		this.text = text;
		this.linkedText = fusen_util.linknize( fusen_util.htmlEscape(text) );
		var self = this;

		$("#" + this.id).find("span").html(self.linkedText);
	}

	Fusen.prototype.removeSelf = function() {
		var self = this;
		$("#" + self.id).remove();
	}

	Fusen.prototype.colorAdjust = function(){
		var self = this;
		var fusen_color = self.$el_fusen.css("border-color");
		var brighter_color = chroma(fusen_color).saturate(2);
		var darker_color = chroma(fusen_color).darken();
		var ratio = self.fusenNumber/100;
		if(ratio > 1) ratio = 1;
		var new_color = chroma.scale([darker_color, brighter_color])(ratio).hex();
		self.$el_fusen.css("color", new_color);
		self.$el_fusen.css("border-color", new_color);
	}

	Fusen.prototype.pchtml = function(){
		var self = this;
		return ''+
			'
'+
				''+self.linkedText+''+
				'<input type="text" style="display:none;" />'+
				'
×
'+
				'
★
'+
			'
';
	}

	Fusen.prototype.setFavoriteListener = function () {
		var self = this;
		var ds_star = milkcocoa.dataStore("fusen-stars__"+self.id);

		ds_star.stream().size(999).next(function(err, data) {
			var $star = $("#"+self.id).find(".p-husen__star-ever");
			if(data.length > 0){
				$star.removeClass("p-husen__star-ever");
				$star.addClass("p-husen__star-pushed");
			}
			$star.text("★"+data.length);
		});

		ds_star.on("push", function(data){
			var $star = $("#"+self.id).find("[class^='p-husen__star-']");
			var num = parseInt( $star.text().substr(1) );
			$star.text("★"+(num+1));
		});

		ds_star.on("remove", function(data){
			var $star = $("#"+self.id).find(".p-husen__star-ever");
			var num = parseInt( $star.text().substr(1) );
			$star.text("★"+(num-1));
		});

		$("#"+self.id).find(".p-husen__star-ever").off().click(function(e){
			e.stopPropagation();
			$(this).removeClass("p-husen__star-ever");
			$(this).addClass("p-husen__star-pushed");
			ds_star.push({});
		});

		$("#"+self.id).find(".p-husen__star-pushed").off().click(function(e){
			e.stopPropagation();
			$(this).removeClass("p-husen__star-pushed");
			$(this).addClass("p-husen__star-ever");
			ds_star.stream().size(1).next(function(err, data){
				ds_star.remove(data[0].id);
			});
		});

	}

	Fusen.prototype.mobilehtml = function(){
		var self = this;
		return ''+
			'
'+
				''+self.linkedText+''+
				'<input type="text" style="display:none;" />'+
				'
★
'+
			'
';
	}

	global.Fusen = Fusen;
}(window));
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 David Wolverton
 * Available under MIT license <https://raw.githubusercontent.com/dwolverton/my/master/LICENSE.txt>
 */
define([
    "lodash", "dojo/_base/lang", "dojo/_base/declare",
    "dojo/dom-construct", "dojo/dom-attr", "dojo/on", "dojo/query", "dojo/Evented",
    "dijit/_WidgetBase",
    "mytime/widget/TaskPickerCombo",
    "mytime/model/TimeEntry",
    "mytime/command/UpdateTimeEntryCommand",
    "mytime/util/Colors", "mytime/util/whenAllPropertiesSet", "mytime/util/store/TransformingStoreView",
    "mytime/util/store/StoreDrivenDom",
    "dojo/text!mytime/widget/DailyTimeList/templates/entry.html",
    "dojo/text!mytime/widget/DailyTimeList/templates/entry-edit.html"
],
function (
    _, lang, declare,
    domConstruct, domAttr, on, query, Evented,
    _WidgetBase,
    TaskPickerCombo,
    TimeEntry,
    UpdateTimeEntryCommand,
    Colors, whenAllPropertiesSet, TransformingStoreView,
    StoreDrivenDom,
    template, editTemplate) {

    /**
     *
     */
    return declare([_WidgetBase, Evented], {

        baseClass: "timelist",

        date: null,
        timeEntryStore: null,
        taskStore: null,

        selectedIds: null,
        editingId: null,
        _editingStartData: null,

        _internalStore: null,
        _list: null,

        _taskCombo: null,

        buildRendering: function() {
            this.inherited(arguments);
        },

        postCreate: function() {
            var _this = this;
            this.own(
                whenAllPropertiesSet(this, ["date", "timeEntryStore", "taskStore"], lang.hitch(this, "_initialize")),
                on(this.domNode, on.selector(".timeentry", "click"), function() {
                    // NOTE: for 'on' with selector, 'this' is the node identified by the selector.
                    _this._onEntryClick(this);
                })
            );
        },

        _initialize: function() {
            this._setupTaskCombo();
            this._internalStore = new TransformingStoreView({
                sourceStore: this.timeEntryStore,
                sourceQuery: {date: this.date},
                transform: lang.hitch(this, function(input) {
                    var entry = new TimeEntry(input);
                    entry.selected = _.contains(this.selectedIds, entry.id);
                    entry.editing = entry.id === this.editingId;
                    return entry;
                })
            }).getObservable();
            this._list = new StoreDrivenDom({
                store: this._internalStore,
                queryOptions: {sort: [{attribute: "startHour"}]},
                renderNode: lang.hitch(this, "_renderEntry")
            });

            this._list.placeAt(this.domNode);

            this.own(
                this.watch("date", lang.hitch(this, "_dateChanged")),
                this.watch("editingId", lang.hitch(this, "_editingIdChanged"))
            );
        },

        _setupTaskCombo: function() {
            this._taskCombo = new TaskPickerCombo({
                store: this.taskStore
            });
            this.own(
                on(this._taskCombo, "change", lang.hitch(this, "_onTaskComboChange"))
            );
        },

        _renderEntry: function(timeEntry) {
            var task = null;
            if (timeEntry.taskId) {
                task = this.taskStore.get(timeEntry.taskId);
            }
            return this._renderEntryWithTask(timeEntry, task);
        },

        _renderEntryWithTask: function(timeEntry, task) {
            var data = {
                Colors: Colors,
                timeEntryId: timeEntry.id,
                taskId: "",
                text: timeEntry.text || "",
                duration: timeEntry.endHour - timeEntry.startHour,
                code: "[   ]",
                name: "No Task",
                color: null,
                jiraLoggable: false
            };
            if (task) {
                data.taskId = task.id || "";
                data.code = task.code || " ";
                data.name = task.name || "";
                data.color = task.color || null;
                data.jiraLoggable = task.code.indexOf('CAYENNE-') == 0 || task.code.indexOf('PSP-') == 0;
            }
            if (timeEntry.editing) {
                return this._renderEditingEntry(timeEntry, task, data);
            } else {
                var html = _.template(template, data);
                return domConstruct.toDom(html);
            }
        },

        _renderEditingEntry: function(timeEntry, task, data) {
            var html = _.template(editTemplate, data);
            var dom = domConstruct.toDom(html);

            this._editingStartData = {
                taskId: task ? task.id : null,
                text: timeEntry.text
            };

            var comboContainer = query(".task", dom)[0];
            this._taskCombo.set("task", task);
            this._taskCombo.placeAt(comboContainer);
            this._taskCombo.startup();

            return dom;
        },

        _dateChanged: function() {
            this._internalStore.set("sourceQuery", {date: this.date});
        },

        _onEntryClick: function(entryNode) {
            var id = domAttr.get(entryNode, "data-timeentry-id");
            this.set("editingId", id);
        },

        _editingIdChanged: function(prop, prevValue, value) {
            if (value !== prevValue) {
                if (prevValue) {
                    this._internalStore.refreshItem(prevValue);
                }
                if (value) {
                    this._internalStore.refreshItem(value);
                    this._taskCombo.focusAndSelectAll();
                }
            }
        },

        _onTaskComboChange: function() {
            console.log('dtChange');
            var task = this._taskCombo.get('task');
            var taskId = task ? task.id : null;
            if (taskId !== this._editingStartData.taskId) {
                this._editingStartData.taskId = taskId;
                new UpdateTimeEntryCommand({timeEntry: {
                    id: this.editingId,
                    taskId: taskId
                }}).exec();
            }
        }

    });
});<commit_msg>Select editor for a timeEntry as soon as it's created<commit_after>/**
 * @license
 * Copyright 2014 David Wolverton
 * Available under MIT license <https://raw.githubusercontent.com/dwolverton/my/master/LICENSE.txt>
 */
define([
    "lodash", "dojo/_base/lang", "dojo/_base/declare",
    "dojo/dom-construct", "dojo/dom-attr", "dojo/on", "dojo/query", "dojo/Evented",
    "dijit/_WidgetBase",
    "mytime/widget/TaskPickerCombo",
    "mytime/model/TimeEntry",
    "mytime/command/UpdateTimeEntryCommand",
    "mytime/util/Colors", "mytime/util/whenAllPropertiesSet", "mytime/util/store/TransformingStoreView",
    "mytime/util/store/StoreDrivenDom", "mytime/util/store/delegateObserve",
    "dojo/text!mytime/widget/DailyTimeList/templates/entry.html",
    "dojo/text!mytime/widget/DailyTimeList/templates/entry-edit.html"
],
function (
    _, lang, declare,
    domConstruct, domAttr, on, query, Evented,
    _WidgetBase,
    TaskPickerCombo,
    TimeEntry,
    UpdateTimeEntryCommand,
    Colors, whenAllPropertiesSet, TransformingStoreView,
    StoreDrivenDom, delegateObserve,
    template, editTemplate) {

    /**
     *
     */
    return declare([_WidgetBase, Evented], {

        baseClass: "timelist",

        date: null,
        timeEntryStore: null,
        taskStore: null,

        selectedIds: null,
        editingId: null,
        _editingStartData: null,

        _internalStore: null,
        _list: null,

        _taskCombo: null,

        buildRendering: function() {
            this.inherited(arguments);
        },

        postCreate: function() {
            var _this = this;
            this.own(
                whenAllPropertiesSet(this, ["date", "timeEntryStore", "taskStore"], lang.hitch(this, "_initialize")),
                on(this.domNode, on.selector(".timeentry", "click"), function() {
                    // NOTE: for 'on' with selector, 'this' is the node identified by the selector.
                    _this._onEntryClick(this);
                })
            );
        },

        _initialize: function() {
            this._setupTaskCombo();
            this._internalStore = new TransformingStoreView({
                sourceStore: this.timeEntryStore,
                sourceQuery: {date: this.date},
                transform: lang.hitch(this, function(input) {
                    var entry = new TimeEntry(input);
                    entry.selected = _.contains(this.selectedIds, entry.id);
                    entry.editing = entry.id === this.editingId;
                    return entry;
                })
            }).getObservable();
            this._list = new StoreDrivenDom({
                store: this._internalStore,
                queryOptions: {sort: [{attribute: "startHour"}]},
                renderNode: lang.hitch(this, "_renderEntry")
            });

            this._list.placeAt(this.domNode);

            this.own(
                this.watch("date", lang.hitch(this, "_dateChanged")),
                this.watch("editingId", lang.hitch(this, "_editingIdChanged")),
                this._internalStore.observe(delegateObserve("_onTimeEntryAdded", null, null, this))
            );
        },

        _setupTaskCombo: function() {
            this._taskCombo = new TaskPickerCombo({
                store: this.taskStore
            });
            this.own(
                on(this._taskCombo, "change", lang.hitch(this, "_onTaskComboChange"))
            );
        },

        _renderEntry: function(timeEntry) {
            var task = null;
            if (timeEntry.taskId) {
                task = this.taskStore.get(timeEntry.taskId);
            }
            return this._renderEntryWithTask(timeEntry, task);
        },

        _renderEntryWithTask: function(timeEntry, task) {
            var data = {
                Colors: Colors,
                timeEntryId: timeEntry.id,
                taskId: "",
                text: timeEntry.text || "",
                duration: timeEntry.endHour - timeEntry.startHour,
                code: "[   ]",
                name: "No Task",
                color: null,
                jiraLoggable: false
            };
            if (task) {
                data.taskId = task.id || "";
                data.code = task.code || " ";
                data.name = task.name || "";
                data.color = task.color || null;
                data.jiraLoggable = task.code.indexOf('CAYENNE-') == 0 || task.code.indexOf('PSP-') == 0;
            }
            if (timeEntry.editing) {
                return this._renderEditingEntry(timeEntry, task, data);
            } else {
                var html = _.template(template, data);
                return domConstruct.toDom(html);
            }
        },

        _renderEditingEntry: function(timeEntry, task, data) {
            var html = _.template(editTemplate, data);
            var dom = domConstruct.toDom(html);

            this._editingStartData = {
                taskId: task ? task.id : null,
                text: timeEntry.text
            };

            var comboContainer = query(".task", dom)[0];
            this._taskCombo.set("task", task);
            this._taskCombo.placeAt(comboContainer);
            this._taskCombo.startup();

            return dom;
        },

        _dateChanged: function() {
            this._internalStore.set("sourceQuery", {date: this.date});
        },

        _onEntryClick: function(entryNode) {
            var id = domAttr.get(entryNode, "data-timeentry-id");
            this.set("editingId", id);
        },

        _editingIdChanged: function(prop, prevValue, value) {
            if (value !== prevValue) {
                if (prevValue) {
                    this._internalStore.refreshItem(prevValue);
                }
                if (value) {
                    this._internalStore.refreshItem(value);
                    this._taskCombo.focusAndSelectAll();
                }
            }
        },

        _onTaskComboChange: function() {
            var task = this._taskCombo.get('task');
            var taskId = task ? task.id : null;
            if (taskId !== this._editingStartData.taskId) {
                this._editingStartData.taskId = taskId;
                new UpdateTimeEntryCommand({timeEntry: {
                    id: this.editingId,
                    taskId: taskId
                }}).exec();
            }
        },

        _onTimeEntryAdded: function(timeEntry) {
            _.defer(lang.hitch(this, function() {
                this.set("editingId", timeEntry.id);
            }));
        }

    });
});<|endoftext|>


<commit_before>"use strict";
var _ = require('underscore'),
    k = _(process.argv).indexOf('html-cov') >= 0 ? require('../lib-cov/k') : require('../lib/k'),
    async = require('async'),
    __should = require('should'),
    glob = require('glob-whatev');

describe('D', function(){
	it('should be able to chain, and execute in order', function(done){
		var x = k();
		x.D.wait(200).wait(200).wait(200).then(done);
	});
});

// make a new deferred
// import a method
// import an async method  <commit_msg>a better deferred test<commit_after>"use strict";
var _ = require('underscore'),
	D = _(process.argv).indexOf('html-cov') >= 0 ? require('../lib-cov/defer') : require('../lib/defer'),
	async = require('async'),
	__should = require('should');

describe('D', function() {
	beforeEach(function() {
		this.x = {
			a: function(cb) {
				this.b(cb);
			},
			b: function(cb) {
				cb();
			},
			c: function(cb) {
				cb();
			}
		};
		D.deferMethod('a');
		D.deferMethod('c');

		this.x.D = new D({
			host: this.x
		});
	});
	describe('import', function() {
		it('should import a method as a deferred version');
		it('should import a regular method, that can still be chained');
		it('should be able to chain, and execute in order', function(done) {
			this.x.D.a().c().then(done);
		});
	});

});

// make a new deferred
// import a method
// import an async method<|endoftext|>


<commit_before>// Newsroom sections
Newsroom = new Mongo.Collection('newsroom'),

// How many list items to load
quantity = new ReactiveVar(5),

// Regular Expression for Search field
search = new ReactiveVar(),

/**
 * Handle searching
 * @method
 *   @param {Event} event
 */
handleSearch = function (event) {
    var value = event.target.value;

    // If field is empty, clear reactive search variable
    if (value.length === 0) search.set();

    // Otherwise, create RegExp for searching fields
    else search.set(new RegExp('.*' + value + '.*', 'gi') );
},

/**
 * Produce a Friendly Date string
 * @function
 *   @param {Collection} this
 * @returns {string}
 */
friendlyDate = function () {
    var date   = new Date(this.date),
        days   = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
                    'Friday', 'Saturday', 'Sunday'],
        months = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
                    'August', 'September', 'October', 'November', 'December'];

    // Create friendly date string
    return days[date.getDay()] + ', ' + date.getDate() + ' ' +
        months[date.getMonth()] + ' ' + date.getFullYear();
};

function removeActiveClass(){
    $('.newsContent li').removeClass('active');
    $('.newsTabs li').removeClass('active');
}

// Subscriptions
Meteor.subscribe('inTheNews');
Meteor.subscribe('pressReleases');
Meteor.subscribe('actionAlerts');

// Populate templates
Template.inTheNews.helpers({
    news: function () {
        return Newsroom.find({
            type: 'inTheNews',
            $or: search.get() instanceof RegExp ? [{
                title: search.get() },{
                publisher: search.get()
            }] : [{}]
        }, {
            limit: quantity.get(),
            sort: { date: -1 }
        });
    },
    friendlyDate: friendlyDate
});
Template.pressReleases.helpers({
    news: function () {
        return Newsroom.find({
            type: 'pressRelease',
            $or: search.get() instanceof RegExp ? [{
                title: search.get() },{
                content: search.get()
            }] : [{}]
        }, {
            limit: quantity.get(),
            sort: { date: -1 }
        });
    },
    friendlyDate: friendlyDate
});
Template.actionAlerts.helpers({
    news: function () {
        return Newsroom.find({
            type: 'actionAlert',
            $or: search.get() instanceof RegExp ? [{
                title: search.get() },{
                content1: search.get()
            }] : [{}]
        }, {
            limit: quantity.get(),
            sort: { date: -1 }
        });
    },
    friendlyDate: friendlyDate
});

// Events
Template.news.events({
    // Switch tabs
    'click ul.newsTabs > li:not(:last-child)': function (event) {
        var index = $(event.target).index() + 1;

        // Set the active tab
        $('ul.newsTabs > li').removeClass('active');
        $(event.target).addClass('active');

        // Set the active content
        $('ul.newsContent > li').removeClass('active');
        $('ul.newsContent > li:nth-child(' + index + ')').addClass('active');

        // Restore number of search results to 5
        quantity.set(5);
        $('button.loadMore.everything').removeClass('everything');
    },

    'click button.loadMore': function (event) {
        quantity.set(0); // get all results

        // Hide "Load More Results" button
        if (event && event.target && event.target.classList)
            event.target.classList.add('everything');
    },

    // "Load More" Results buttons
    'click button.newsroomButton': function (event) {
        $('li.accountDetails').click();
        $('.accountDetailsTabs li:nth-child(2)').click();
    },

    // Search field
    'keyup  #searchNews': handleSearch,
    'search #searchNews': handleSearch,

    // Don't allow search to submit form on enter; it doesn't go anywhere
    'submit aside.searchFieldContainer.form': function (event) {
        event.preventDefault(); event.stopPropagation();
    },

    // "Load More" Results buttons
    'click li.newsTabMenu': function (event) {
        removeActiveClass();
    },

    //Mobile subscription management
    'click .subscriptionsMob button': function (event) {
        //Not sure where this is being called
        event.preventDefault();
        $('.mobileOverlay').click();
        $('button.accountToggle').click();
        $('li.subscriptionsManagerMob').click();
    }
});

Template.news.onRendered(function () {
    if (window.innerWidth < 768) {
        removeActiveClass();
    }
});
<commit_msg>Added event for login for newsroom.<commit_after>// Newsroom sections
Newsroom = new Mongo.Collection('newsroom'),

// How many list items to load
quantity = new ReactiveVar(5),

// Regular Expression for Search field
search = new ReactiveVar(),

/**
 * Handle searching
 * @method
 *   @param {Event} event
 */
handleSearch = function (event) {
    var value = event.target.value;

    // If field is empty, clear reactive search variable
    if (value.length === 0) search.set();

    // Otherwise, create RegExp for searching fields
    else search.set(new RegExp('.*' + value + '.*', 'gi') );
},

/**
 * Produce a Friendly Date string
 * @function
 *   @param {Collection} this
 * @returns {string}
 */
friendlyDate = function () {
    var date   = new Date(this.date),
        days   = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
                    'Friday', 'Saturday', 'Sunday'],
        months = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
                    'August', 'September', 'October', 'November', 'December'];

    // Create friendly date string
    return days[date.getDay()] + ', ' + date.getDate() + ' ' +
        months[date.getMonth()] + ' ' + date.getFullYear();
};

function removeActiveClass(){
    $('.newsContent li').removeClass('active');
    $('.newsTabs li').removeClass('active');
}

// Subscriptions
Meteor.subscribe('inTheNews');
Meteor.subscribe('pressReleases');
Meteor.subscribe('actionAlerts');

// Populate templates
Template.inTheNews.helpers({
    news: function () {
        return Newsroom.find({
            type: 'inTheNews',
            $or: search.get() instanceof RegExp ? [{
                title: search.get() },{
                publisher: search.get()
            }] : [{}]
        }, {
            limit: quantity.get(),
            sort: { date: -1 }
        });
    },
    friendlyDate: friendlyDate
});
Template.pressReleases.helpers({
    news: function () {
        return Newsroom.find({
            type: 'pressRelease',
            $or: search.get() instanceof RegExp ? [{
                title: search.get() },{
                content: search.get()
            }] : [{}]
        }, {
            limit: quantity.get(),
            sort: { date: -1 }
        });
    },
    friendlyDate: friendlyDate
});
Template.actionAlerts.helpers({
    news: function () {
        return Newsroom.find({
            type: 'actionAlert',
            $or: search.get() instanceof RegExp ? [{
                title: search.get() },{
                content1: search.get()
            }] : [{}]
        }, {
            limit: quantity.get(),
            sort: { date: -1 }
        });
    },
    friendlyDate: friendlyDate
});

// Events
Template.news.events({
    // Switch tabs
    'click ul.newsTabs > li:not(:last-child)': function (event) {
        var index = $(event.target).index() + 1;

        // Set the active tab
        $('ul.newsTabs > li').removeClass('active');
        $(event.target).addClass('active');

        // Set the active content
        $('ul.newsContent > li').removeClass('active');
        $('ul.newsContent > li:nth-child(' + index + ')').addClass('active');

        // Restore number of search results to 5
        quantity.set(5);
        $('button.loadMore.everything').removeClass('everything');
    },

    'click button.loadMore': function (event) {
        quantity.set(0); // get all results

        // Hide "Load More Results" button
        if (event && event.target && event.target.classList)
            event.target.classList.add('everything');
    },

    // "Load More" Results buttons
    'click button.newsroomButton': function (event) {
        $('li.accountDetails').click();
        $('.accountDetailsTabs li:nth-child(2)').click();
    },

    // Search field
    'keyup  #searchNews': handleSearch,
    'search #searchNews': handleSearch,

    // Don't allow search to submit form on enter; it doesn't go anywhere
    'submit aside.searchFieldContainer.form': function (event) {
        event.preventDefault(); event.stopPropagation();
    },

    // "Load More" Results buttons
    'click li.newsTabMenu': function (event) {
        removeActiveClass();
    },

    //Mobile subscription management
    'click .subscriptionsMob button': function (event) {
        //Not sure where this is being called
        event.preventDefault();
        $('.mobileOverlay').click();
        $('button.accountToggle').click();
        $('li.subscriptionsManagerMob').click();
    },
    'click .subscriptionsRegister': function (event) {
        //Not sure where this is being called
        event.preventDefault();
        $('li.login').click();
    }
});

Template.news.onRendered(function () {
    if (window.innerWidth < 768) {
        removeActiveClass();
    }
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import SLDSPopover from '../../SLDSPopover/index';
import Moment from 'moment';

var ListItemComponent = React.createClass( {

  getDefaultProps: function(){
    return {
      moment: Moment(),
      onSelect: function(moment){
        console.log('onSelect should be defined');
      }
    }
  },

  handleClick() {
    if(this.props.onSelect && this.props.value){
      this.props.onSelect(this.props.moment.set('year', this.props.value));
    }
  },

  render() {
    return (

        { this.props.value }

    )
  }
});

module.exports = React.createClass( {

  getDefaultProps: function(){
    return {
      moment:Moment(),
      relativeFrom:-3,
      relativeTo:15,
      onChange:function(moment){
        console.log('onChange should be defined');
      }
    }
  },

  componentWillReceiveProps(nextProps){
    this.setState({isOpen:false});
  },

  handleSelectDate(day) {
    this.setState({selectedDate:day})
  },

  handleClose() {
    this.setState({isOpen:false})
  },

  handleClick() {
    this.setState({isOpen:true})
  },

  handleFocus() {
    this.setState({isOpen:true})
  },

  handleSelect(moment) {
    if(this.props.onSelect){
      this.props.onSelect(moment);
    }
    this.setState({isOpen:false});
  },

  listItems() {
    var listItems = [];
    var currentYear = this.props.moment.years();
    var from = currentYear+this.props.relativeFrom;
    var to = currentYear+this.props.relativeTo;

    for(var i=from;i<to;i++){
      listItems.push(<ListItemComponent
          onSelect={this.handleSelect}
          isSelected={currentYear===i}
          moment={this.props.moment}
          value={i} />);
    }
    return listItems;
  },

  popover() {
    if(this.state && this.state.isOpen){
      return (
        <SLDSPopover targetElement={this.refs.date}>

            { this.listItems() }

        </SLDSPopover>
      );
    }
    return ;
  },

  render() {
    return (

            <button id="year"
              className="sds-button sds-button--neutral sds-picklist__label"
              onClick={this.handleClick.bind(this)}
              onFocus={this.handleFocus.bind(this)}
              aria-haspopup="true"
              aria-expanded="false">{this.props.moment.format('YYYY')}
                ↓
            </button>

        {this.popover()}

    );
  }
});<commit_msg>remove warnings<commit_after>import React, { Component } from 'react';
import SLDSPopover from '../../SLDSPopover/index';
import Moment from 'moment';

var ListItemComponent = React.createClass( {

  getDefaultProps: function(){
    return {
      moment: Moment(),
      onSelect: function(moment){
        console.log('onSelect should be defined');
      }
    }
  },

  handleClick() {
    if(this.props.onSelect && this.props.value){
      this.props.onSelect(this.props.moment.set('year', this.props.value));
    }
  },

  render() {
    return (

        { this.props.value }

    )
  }
});

module.exports = React.createClass( {

  getDefaultProps: function(){
    return {
      moment:Moment(),
      relativeFrom:-3,
      relativeTo:15,
      onChange:function(moment){
        console.log('onChange should be defined');
      }
    }
  },

  componentWillReceiveProps(nextProps){
    this.setState({isOpen:false});
  },

  handleSelectDate(day) {
    this.setState({selectedDate:day})
  },

  handleClose() {
    this.setState({isOpen:false})
  },

  handleClick() {
    this.setState({isOpen:true})
  },

  handleFocus() {
    this.setState({isOpen:true})
  },

  handleSelect(moment) {
    if(this.props.onSelect){
      this.props.onSelect(moment);
    }
    this.setState({isOpen:false});
  },

  listItems() {
    var listItems = [];
    var currentYear = this.props.moment.years();
    var from = currentYear+this.props.relativeFrom;
    var to = currentYear+this.props.relativeTo;

    for(var i=from;i<to;i++){
      listItems.push(<ListItemComponent
          onSelect={this.handleSelect}
          isSelected={currentYear===i}
          moment={this.props.moment}
          value={i} />);
    }
    return listItems;
  },

  popover() {
    if(this.state && this.state.isOpen){
      return (
        <SLDSPopover targetElement={this.refs.date}>

            { this.listItems() }

        </SLDSPopover>
      );
    }
    return ;
  },

  render() {
    return (

            <button id="year"
              className="sds-button sds-button--neutral sds-picklist__label"
              onClick={this.handleClick}
              onFocus={this.handleFocus}
              aria-haspopup="true"
              aria-expanded="false">{this.props.moment.format('YYYY')}
                ↓
            </button>

        {this.popover()}

    );
  }
});<|endoftext|>


<commit_before>(function(window, document, ionic) {

  var readyCallbacks = [];
  var isDomReady = false;

  function domReady() {
    isDomReady = true;
    for(var x=0; x<readyCallbacks.length; x++) {
      ionic.requestAnimationFrame(readyCallbacks[x]);
    }
    readyCallbacks = [];
    document.removeEventListener('DOMContentLoaded', domReady);
  }
  document.addEventListener('DOMContentLoaded', domReady);

  // From the man himself, Mr. Paul Irish.
  // The requestAnimationFrame polyfill
  // Put it on window just to preserve its context
  // without having to use .call
  window._rAF = (function(){
    return  window.requestAnimationFrame       ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            function( callback ){
              window.setTimeout(callback, 16);
            };
  })();

  var vendors = ['webkit', 'moz'];
  for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
    window.cancelAnimationFrame =
      window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
  }
  window.cancelAnimationFrame =
        window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];

  /**
  * @ngdoc utility
  * @name ionic.DomUtil
  * @module ionic
  */
  ionic.DomUtil = {
    //Call with proper context
    /**
     * @ngdoc method
     * @name ionic.DomUtil#requestAnimationFrame
     * @alias ionic.requestAnimationFrame
     * @description Calls [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame), or a polyfill if not available.
     * @param {function} callback The function to call when the next frame
     * happens.
     */
    requestAnimationFrame: function(cb) {
      window._rAF(cb);
    },

    cancelAnimationFrame: function(cb) {
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#animationFrameThrottle
     * @alias ionic.animationFrameThrottle
     * @description
     * When given a callback, if that callback is called 100 times between
     * animation frames, adding Throttle will make it only run the last of
     * the 100 calls.
     *
     * @param {function} callback a function which will be throttled to
     * requestAnimationFrame
     * @returns {function} A function which will then call the passed in callback.
     * The passed in callback will receive the context the returned function is
     * called with.
     */
    animationFrameThrottle: function(cb) {
      var args, isQueued, context;
      return function() {
        args = arguments;
        context = this;
        if (!isQueued) {
          isQueued = true;
          ionic.requestAnimationFrame(function() {
            cb.apply(context, args);
            isQueued = false;
          });
        }
      };
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#getPositionInParent
     * @description
     * Find an element's scroll offset within its container.
     * @param {DOMElement} element The element to find the offset of.
     * @returns {object} A position object with the following properties:
     *   - `{number}` `left` The left offset of the element.
     *   - `{number}` `top` The top offset of the element.
     */
    getPositionInParent: function(el) {
      return {
        left: el.offsetLeft,
        top: el.offsetTop
      };
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#ready
     * @description
     * Call a function when the DOM is ready, or if it is already ready
     * call the function immediately.
     * @param {function} callback The function to be called.
     */
    ready: function(cb) {
      if(isDomReady || document.readyState === "complete") {
        ionic.requestAnimationFrame(cb);
      } else {
        readyCallbacks.push(cb);
      }
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#getTextBounds
     * @description
     * Get a rect representing the bounds of the given textNode.
     * @param {DOMElement} textNode The textNode to find the bounds of.
     * @returns {object} An object representing the bounds of the node. Properties:
     *   - `{number}` `left` The left positton of the textNode.
     *   - `{number}` `right` The right positton of the textNode.
     *   - `{number}` `top` The top positton of the textNode.
     *   - `{number}` `bottom` The bottom position of the textNode.
     *   - `{number}` `width` The width of the textNode.
     *   - `{number}` `height` The height of the textNode.
     */
    getTextBounds: function(textNode) {
      if(document.createRange) {
        var range = document.createRange();
        range.selectNodeContents(textNode);
        if(range.getBoundingClientRect) {
          var rect = range.getBoundingClientRect();
          if(rect) {
            var sx = window.scrollX;
            var sy = window.scrollY;

            return {
              top: rect.top + sy,
              left: rect.left + sx,
              right: rect.left + sx + rect.width,
              bottom: rect.top + sy + rect.height,
              width: rect.width,
              height: rect.height
            };
          }
        }
      }
      return null;
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#getChildIndex
     * @description
     * Get the first index of a child node within the given element of the
     * specified type.
     * @param {DOMElement} element The element to find the index of.
     * @param {string} type The nodeName to match children of element against.
     * @returns {number} The index, or -1, of a child with nodeName matching type.
     */
    getChildIndex: function(element, type) {
      if(type) {
        var ch = element.parentNode.children;
        var c;
        for(var i = 0, k = 0, j = ch.length; i < j; i++) {
          c = ch[i];
          if(c.nodeName && c.nodeName.toLowerCase() == type) {
            if(c == element) {
              return k;
            }
            k++;
          }
        }
      }
      return Array.prototype.slice.call(element.parentNode.children).indexOf(element);
    },

    /**
     * @private
     */
    swapNodes: function(src, dest) {
      dest.parentNode.insertBefore(src, dest);
    },

    /**
     * @private
     */
    centerElementByMargin: function(el) {
      el.style.marginLeft = (-el.offsetWidth) / 2 + 'px';
      el.style.marginTop = (-el.offsetHeight) / 2 + 'px';
    },
    //Center twice, after raf, to fix a bug with ios and showing elements
    //that have just been attached to the DOM.
    centerElementByMarginTwice: function(el) {
      ionic.requestAnimationFrame(function() {
        ionic.DomUtil.centerElementByMargin(el);
        setTimeout(function() {
          ionic.DomUtil.centerElementByMargin(el);
          setTimeout(function() {
            ionic.DomUtil.centerElementByMargin(el);
          });
        });
      });
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#getParentWithClass
     * @param {DOMElement} element
     * @param {string} className
     * @returns {DOMElement} The closest parent of element matching the
     * className, or null.
     */
    getParentWithClass: function(e, className, depth) {
      depth = depth || 10;
      while(e.parentNode && depth--) {
        if(e.parentNode.classList && e.parentNode.classList.contains(className)) {
          return e.parentNode;
        }
        e = e.parentNode;
      }
      return null;
    },
    /**
     * @ngdoc method
     * @name ionic.DomUtil#getParentWithClass
     * @param {DOMElement} element
     * @param {string} className
     * @returns {DOMElement} The closest parent or self matching the
     * className, or null.
     */
    getParentOrSelfWithClass: function(e, className, depth) {
      depth = depth || 10;
      while(e && depth--) {
        if(e.classList && e.classList.contains(className)) {
          return e;
        }
        e = e.parentNode;
      }
      return null;
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#rectContains
     * @param {number} x
     * @param {number} y
     * @param {number} x1
     * @param {number} y1
     * @param {number} x2
     * @param {number} y2
     * @returns {boolean} Whether {x,y} fits within the rectangle defined by
     * {x1,y1,x2,y2}.
     */
    rectContains: function(x, y, x1, y1, x2, y2) {
      if(x < x1 || x > x2) return false;
      if(y < y1 || y > y2) return false;
      return true;
    }
  };

  //Shortcuts
  ionic.requestAnimationFrame = ionic.DomUtil.requestAnimationFrame;
  ionic.cancelAnimationFrame = ionic.DomUtil.cancelAnimationFrame;
  ionic.animationFrameThrottle = ionic.DomUtil.animationFrameThrottle;
})(window, document, ionic);
<commit_msg>docs(domUtil): Correcting getParentOrSelfWithClass documentation. It previously duplicated getParentWithClass. Closes #1535<commit_after>(function(window, document, ionic) {

  var readyCallbacks = [];
  var isDomReady = false;

  function domReady() {
    isDomReady = true;
    for(var x=0; x<readyCallbacks.length; x++) {
      ionic.requestAnimationFrame(readyCallbacks[x]);
    }
    readyCallbacks = [];
    document.removeEventListener('DOMContentLoaded', domReady);
  }
  document.addEventListener('DOMContentLoaded', domReady);

  // From the man himself, Mr. Paul Irish.
  // The requestAnimationFrame polyfill
  // Put it on window just to preserve its context
  // without having to use .call
  window._rAF = (function(){
    return  window.requestAnimationFrame       ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            function( callback ){
              window.setTimeout(callback, 16);
            };
  })();

  var vendors = ['webkit', 'moz'];
  for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
    window.cancelAnimationFrame =
      window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
  }
  window.cancelAnimationFrame =
        window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];

  /**
  * @ngdoc utility
  * @name ionic.DomUtil
  * @module ionic
  */
  ionic.DomUtil = {
    //Call with proper context
    /**
     * @ngdoc method
     * @name ionic.DomUtil#requestAnimationFrame
     * @alias ionic.requestAnimationFrame
     * @description Calls [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame), or a polyfill if not available.
     * @param {function} callback The function to call when the next frame
     * happens.
     */
    requestAnimationFrame: function(cb) {
      window._rAF(cb);
    },

    cancelAnimationFrame: function(cb) {
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#animationFrameThrottle
     * @alias ionic.animationFrameThrottle
     * @description
     * When given a callback, if that callback is called 100 times between
     * animation frames, adding Throttle will make it only run the last of
     * the 100 calls.
     *
     * @param {function} callback a function which will be throttled to
     * requestAnimationFrame
     * @returns {function} A function which will then call the passed in callback.
     * The passed in callback will receive the context the returned function is
     * called with.
     */
    animationFrameThrottle: function(cb) {
      var args, isQueued, context;
      return function() {
        args = arguments;
        context = this;
        if (!isQueued) {
          isQueued = true;
          ionic.requestAnimationFrame(function() {
            cb.apply(context, args);
            isQueued = false;
          });
        }
      };
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#getPositionInParent
     * @description
     * Find an element's scroll offset within its container.
     * @param {DOMElement} element The element to find the offset of.
     * @returns {object} A position object with the following properties:
     *   - `{number}` `left` The left offset of the element.
     *   - `{number}` `top` The top offset of the element.
     */
    getPositionInParent: function(el) {
      return {
        left: el.offsetLeft,
        top: el.offsetTop
      };
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#ready
     * @description
     * Call a function when the DOM is ready, or if it is already ready
     * call the function immediately.
     * @param {function} callback The function to be called.
     */
    ready: function(cb) {
      if(isDomReady || document.readyState === "complete") {
        ionic.requestAnimationFrame(cb);
      } else {
        readyCallbacks.push(cb);
      }
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#getTextBounds
     * @description
     * Get a rect representing the bounds of the given textNode.
     * @param {DOMElement} textNode The textNode to find the bounds of.
     * @returns {object} An object representing the bounds of the node. Properties:
     *   - `{number}` `left` The left positton of the textNode.
     *   - `{number}` `right` The right positton of the textNode.
     *   - `{number}` `top` The top positton of the textNode.
     *   - `{number}` `bottom` The bottom position of the textNode.
     *   - `{number}` `width` The width of the textNode.
     *   - `{number}` `height` The height of the textNode.
     */
    getTextBounds: function(textNode) {
      if(document.createRange) {
        var range = document.createRange();
        range.selectNodeContents(textNode);
        if(range.getBoundingClientRect) {
          var rect = range.getBoundingClientRect();
          if(rect) {
            var sx = window.scrollX;
            var sy = window.scrollY;

            return {
              top: rect.top + sy,
              left: rect.left + sx,
              right: rect.left + sx + rect.width,
              bottom: rect.top + sy + rect.height,
              width: rect.width,
              height: rect.height
            };
          }
        }
      }
      return null;
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#getChildIndex
     * @description
     * Get the first index of a child node within the given element of the
     * specified type.
     * @param {DOMElement} element The element to find the index of.
     * @param {string} type The nodeName to match children of element against.
     * @returns {number} The index, or -1, of a child with nodeName matching type.
     */
    getChildIndex: function(element, type) {
      if(type) {
        var ch = element.parentNode.children;
        var c;
        for(var i = 0, k = 0, j = ch.length; i < j; i++) {
          c = ch[i];
          if(c.nodeName && c.nodeName.toLowerCase() == type) {
            if(c == element) {
              return k;
            }
            k++;
          }
        }
      }
      return Array.prototype.slice.call(element.parentNode.children).indexOf(element);
    },

    /**
     * @private
     */
    swapNodes: function(src, dest) {
      dest.parentNode.insertBefore(src, dest);
    },

    /**
     * @private
     */
    centerElementByMargin: function(el) {
      el.style.marginLeft = (-el.offsetWidth) / 2 + 'px';
      el.style.marginTop = (-el.offsetHeight) / 2 + 'px';
    },
    //Center twice, after raf, to fix a bug with ios and showing elements
    //that have just been attached to the DOM.
    centerElementByMarginTwice: function(el) {
      ionic.requestAnimationFrame(function() {
        ionic.DomUtil.centerElementByMargin(el);
        setTimeout(function() {
          ionic.DomUtil.centerElementByMargin(el);
          setTimeout(function() {
            ionic.DomUtil.centerElementByMargin(el);
          });
        });
      });
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#getParentWithClass
     * @param {DOMElement} element
     * @param {string} className
     * @returns {DOMElement} The closest parent of element matching the
     * className, or null.
     */
    getParentWithClass: function(e, className, depth) {
      depth = depth || 10;
      while(e.parentNode && depth--) {
        if(e.parentNode.classList && e.parentNode.classList.contains(className)) {
          return e.parentNode;
        }
        e = e.parentNode;
      }
      return null;
    },
    /**
     * @ngdoc method
     * @name ionic.DomUtil#getParentOrSelfWithClass
     * @param {DOMElement} element
     * @param {string} className
     * @returns {DOMElement} The closest parent or self matching the
     * className, or null.
     */
    getParentOrSelfWithClass: function(e, className, depth) {
      depth = depth || 10;
      while(e && depth--) {
        if(e.classList && e.classList.contains(className)) {
          return e;
        }
        e = e.parentNode;
      }
      return null;
    },

    /**
     * @ngdoc method
     * @name ionic.DomUtil#rectContains
     * @param {number} x
     * @param {number} y
     * @param {number} x1
     * @param {number} y1
     * @param {number} x2
     * @param {number} y2
     * @returns {boolean} Whether {x,y} fits within the rectangle defined by
     * {x1,y1,x2,y2}.
     */
    rectContains: function(x, y, x1, y1, x2, y2) {
      if(x < x1 || x > x2) return false;
      if(y < y1 || y > y2) return false;
      return true;
    }
  };

  //Shortcuts
  ionic.requestAnimationFrame = ionic.DomUtil.requestAnimationFrame;
  ionic.cancelAnimationFrame = ionic.DomUtil.cancelAnimationFrame;
  ionic.animationFrameThrottle = ionic.DomUtil.animationFrameThrottle;
})(window, document, ionic);
<|endoftext|>


<commit_before>angular.module('vtortola.GitHub.io')

.config(['commandBrokerProvider', function (commandBrokerProvider) {

    commandBrokerProvider.appendCommandHandler({
        command: 'version',
        description: ['Shows this software version.'],
        handle: function (session) {
            session.output.push({ output: true, text: ['Version 0.1 Beta'], breakLine: true });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'clear',
        description: ['Clears the screen.'],
        handle: function (session) {
            session.commands.push({ command: 'clear' });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'echo',
        description: ['Echoes input.'],
        handle: function (session) {
            var a = Array.prototype.slice.call(arguments, 1);
            session.output.push({ output: true, text: [a.join(' ')], breakLine: true });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'eval',
        description: ['Evaluates input as javascript.','Example: eval alert(1)'],
        handle: function (session, param) {
            var a = Array.prototype.slice.call(arguments, 1);
            var param = eval(a.join(' '));
            param = param ? param.toString() : '';
            session.output.push({ output: true, text: [param], breakLine: true });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'break',
        description: ['Tests how commands are broken down in segments.',"Example: break 'aaa aaa' aaa aaa"],
        handle: function (session) {
            var a = Array.prototype.slice.call(arguments, 1);
            session.output.push({ output: true, text: a, breakLine: true });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'websocket',
        description: ['Starts a websocket session.',
                      'Syntax: websocket <url> [protocol]',
                      'Example: websocket wss://echo.websocket.org'],
        handle: function (session, url, protocol) {
            if (!url) {
                throw new Error("The parameter 'url' is required, type 'help websocket' to get help.")
            }

            session.output.push({
                output: true,
                text: ["Openning connection to " + url + (protocol ? " with protocol " + protocol : "") + " ...",
                       "Type 'exit' to exit."],
                breakLine: true
            });
            session.commands.push({ command: 'startcontext', prompt: 'websocket:/>' });
            session.contextName = "websocket";
            session.context = function () {
                var me = {};
                var ws = protocol ? new WebSocket(url, protocol) : new WebSocket(url);
                ws.onopen = function () {
                    session.output.push({ output: true, text: ["Connection established."], breakLine: true });
                    session.$scope.$apply();
                };

                ws.onerror = function () {
                    session.output.push({ output: true, text: ["Connection error."], breakLine: true });
                    session.$scope.$apply();
                    me.execute(session, "exit");
                };

                ws.onmessage = function (msg) {
                    session.output.push({ output: true, text: [msg.data], breakLine: true });
                    session.$scope.$apply();
                };

                me.execute = function (s, c) {
                    if (c == 'exit') {
                        ws.close();
                        s.contextName = "";
                        delete s.context;
                        s.commands.push({ command: 'endcontext' });
                        s.output.push({ output: true, text: ["Websocket ended."], breakLine: true });
                        return;
                    }
                    ws.send(c);
                };
                return me;
            }();
        }
    });

    var helpCommandHandler = function () {
        var me = {};
        var list = commandBrokerProvider.describe();
        me.command= 'help';
        me.description= ['Provides instructions about how to use this terminal'];
        me.handle = function (session, cmd) {
            var outText = [];
            if (cmd) {
                for (var i = 0; i < list.length; i++) {
                    if (list[i].command == cmd) {
                        var l = list[i];
                        outText.push("Command help for: " + cmd);
                        for (var j = 0; j < l.description.length; j++) {
                            outText.push(l.description[j]);
                        }
                        break;
                    }
                }
            }
            else {
                outText.push("Available commands:");
                for (var i = 0; i < list.length; i++) {
                    outText.push("  " + list[i].command);
                }
                outText.push("");
                outText.push("Enter 'help <command>' to get help for a particular command.");
            }
            session.output.push({ output: true, text: outText, breakLine: true });
        };
        return me;
    };
    commandBrokerProvider.appendCommandHandler(helpCommandHandler());

    //var gaCommandHandler = function () {
    //    var me = {};
    //    var _ga = null;
    //    me.command = 'ga';
    //    me.description = ['Manipulates Google Analytics'];
    //    me.init = ['$ga', function ($ga) {
    //        _ga = $ga;
    //    }];
    //    me.handle = function (session, param) {
    //        //_ga.apply(_ga, Array.prototype.slice.call(arguments, 1));

    //        ga('set', { userId: '1234' });
    //    }
    //    return me;
    //};
    //commandBrokerProvider.appendCommandHandler(gaCommandHandler());

    var feedbackCommandHandler = function () {
        var me = {};
        var _ga = null;
        me.command = 'feedback';
        me.description = ['Sends a feedback message to the author.'];
        me.init = ['$ga', function ($ga) {
            _ga = $ga;
        }];
        me.handle = function (session, param) {
            var a = Array.prototype.slice.call(arguments, 1);
            var param = a.join(' ');
            _ga('send', 'event', 'Console', 'Feedback', param);
            session.output.push({ output: true, text: ["Your message have been sent.", "Thanks for the feedback!."], breakLine: true });
        }
        return me;
    };
    commandBrokerProvider.appendCommandHandler(feedbackCommandHandler());
}])

;<commit_msg>Feedback command<commit_after>angular.module('vtortola.GitHub.io')

.config(['commandBrokerProvider', function (commandBrokerProvider) {

    commandBrokerProvider.appendCommandHandler({
        command: 'version',
        description: ['Shows this software version.'],
        handle: function (session) {
            session.output.push({ output: true, text: ['Version 0.1 Beta'], breakLine: true });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'clear',
        description: ['Clears the screen.'],
        handle: function (session) {
            session.commands.push({ command: 'clear' });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'echo',
        description: ['Echoes input.'],
        handle: function (session) {
            var a = Array.prototype.slice.call(arguments, 1);
            session.output.push({ output: true, text: [a.join(' ')], breakLine: true });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'eval',
        description: ['Evaluates input as javascript.','Example: eval alert(1)'],
        handle: function (session, param) {
            var a = Array.prototype.slice.call(arguments, 1);
            var param = eval(a.join(' '));
            param = param ? param.toString() : '';
            session.output.push({ output: true, text: [param], breakLine: true });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'break',
        description: ['Tests how commands are broken down in segments.',"Example: break 'aaa aaa' aaa aaa"],
        handle: function (session) {
            var a = Array.prototype.slice.call(arguments, 1);
            session.output.push({ output: true, text: a, breakLine: true });
        }
    });

    commandBrokerProvider.appendCommandHandler({
        command: 'websocket',
        description: ['Starts a websocket session.',
                      'Syntax: websocket <url> [protocol]',
                      'Example: websocket wss://echo.websocket.org'],
        handle: function (session, url, protocol) {
            if (!url) {
                throw new Error("The parameter 'url' is required, type 'help websocket' to get help.")
            }

            session.output.push({
                output: true,
                text: ["Openning connection to " + url + (protocol ? " with protocol " + protocol : "") + " ...",
                       "Type 'exit' to exit."],
                breakLine: true
            });
            session.commands.push({ command: 'startcontext', prompt: 'websocket:/>' });
            session.contextName = "websocket";
            session.context = function () {
                var me = {};
                var ws = protocol ? new WebSocket(url, protocol) : new WebSocket(url);
                ws.onopen = function () {
                    session.output.push({ output: true, text: ["Connection established."], breakLine: true });
                    session.$scope.$apply();
                };

                ws.onerror = function () {
                    session.output.push({ output: true, text: ["Connection error."], breakLine: true });
                    session.$scope.$apply();
                    me.execute(session, "exit");
                };

                ws.onmessage = function (msg) {
                    session.output.push({ output: true, text: [msg.data], breakLine: true });
                    session.$scope.$apply();
                };

                me.execute = function (s, c) {
                    if (c == 'exit') {
                        ws.close();
                        s.contextName = "";
                        delete s.context;
                        s.commands.push({ command: 'endcontext' });
                        s.output.push({ output: true, text: ["Websocket ended."], breakLine: true });
                        return;
                    }
                    ws.send(c);
                };
                return me;
            }();
        }
    });

    //var gaCommandHandler = function () {
    //    var me = {};
    //    var _ga = null;
    //    me.command = 'ga';
    //    me.description = ['Manipulates Google Analytics'];
    //    me.init = ['$ga', function ($ga) {
    //        _ga = $ga;
    //    }];
    //    me.handle = function (session, param) {
    //        //_ga.apply(_ga, Array.prototype.slice.call(arguments, 1));

    //        ga('set', { userId: '1234' });
    //    }
    //    return me;
    //};
    //commandBrokerProvider.appendCommandHandler(gaCommandHandler());

    var feedbackCommandHandler = function () {
        var me = {};
        var _ga = null;
        me.command = 'feedback';
        me.description = ['Sends a feedback message to the author.', "Example: feedback This application is awesome! Where may I donate?"];
        me.init = ['$ga', function ($ga) {
            _ga = $ga;
        }];
        me.handle = function (session, param) {
            param = Array.prototype.slice.call(arguments, 1);
            param = param.join(' ');
            var outText = [];
            if (!param) {
                outText.push("You need to provide a message, type 'help feedback' to get a hint.");
            }
            else {
                outText.push("Your message have been sent.");
                outText.push("Thanks for the feedback!.");
                _ga('send', 'event', 'Console', 'Feedback', param);
            }
            session.output.push({ output: true, text: outText, breakLine: true });
        }
        return me;
    };
    commandBrokerProvider.appendCommandHandler(feedbackCommandHandler());

    // this must be the last
    var helpCommandHandler = function () {
        var me = {};
        var list = commandBrokerProvider.describe();
        me.command = 'help';
        me.description = ['Provides instructions about how to use this terminal'];
        me.handle = function (session, cmd) {
            var outText = [];
            if (cmd) {
                for (var i = 0; i < list.length; i++) {
                    if (list[i].command == cmd) {
                        var l = list[i];
                        outText.push("Command help for: " + cmd);
                        for (var j = 0; j < l.description.length; j++) {
                            outText.push(l.description[j]);
                        }
                        break;
                    }
                }
            }
            else {
                outText.push("Available commands:");
                for (var i = 0; i < list.length; i++) {
                    outText.push("  " + list[i].command);
                }
                outText.push("");
                outText.push("Enter 'help <command>' to get help for a particular command.");
            }
            session.output.push({ output: true, text: outText, breakLine: true });
        };
        return me;
    };
    commandBrokerProvider.appendCommandHandler(helpCommandHandler());
}])

;<|endoftext|>