<commit_before>import React from 'react';
import {
  BrowserRouter,
  Route,
  Switch,
  Redirect
} from "react-router-dom";
import Header from './Header';
import Home from './Home';
import AddWord from './AddWord';
import Translate from './Translate';
import Dictionary from './Dictionary';
import FlashCards from './FlashCards';
import Notes from './Notes';
import AddNote from './AddNote';
import ViewNote from './ViewNote';
import EditWord from './EditWord';
import Setup from './Setup';
import './App.css';

class App extends React.Component {
  constructor() {
    super();
    // Initialize words and notes from local storage.
    if ( ! localStorage.getItem('words')) localStorage.setItem('words', JSON.stringify([]));
    if ( ! localStorage.getItem('notes')) localStorage.setItem('notes', JSON.stringify(Setup.DEFAULT_NOTES));
    this.state = {
      words: JSON.parse(localStorage.getItem('words')),
      flashCardWord: '',
      translateTextarea: '',
      translatedWords: [],
      notes: JSON.parse(localStorage.getItem('notes'))
    };
  }

  componentDidMount() {
    let flashCardWord = this.getRandomValue(this.state.words);
    this.setState({flashCardWord: flashCardWord});
  }

  handleAddWordFormSubmit(mainWord, secretWord) {
    let words = [...this.state.words];
    words.push({
      mainWord: mainWord,
      secretWord: secretWord
    });
    this.setState({
      words: words
    });
    localStorage.setItem('words', JSON.stringify(words));
  }

  handleTranslateTextareaChange(event) {
    this.setState({
      translateTextarea: event.target.value,
      translatedWords: []
    });

    let mainText = event.target.value;
    let translatedWords = [];
    mainText = mainText.split(" ");

    // Loop through the english textarea text
    for (let i = 0; i < mainText.length; i++) {
      let isWordInDictionary = false;     // Whether the word is in the dictionary or not.
      let specialChar = "";  // The special character that is at the end of the word.

      // Check if the word ends in a special character
      let specialCharsList = [',', '.', ';', ':', '?', '!'];
      if (specialCharsList.indexOf(mainText[i].charAt(mainText[i].length - 1)) !== -1) {
        specialChar = mainText[i].charAt(mainText[i].length - 1);
        mainText[i] = mainText[i].substring(0, mainText[i].length - 1);
      }

      // Loop through the dictionary and check if the word has been defined yet.
      for (let j = 0; j < this.state.words.length; j++) {
        // if it is found, add it to the translatedWords array
        if (mainText[i].toUpperCase() === this.state.words[j].mainWord.toUpperCase()) {
          // The word to add to the translated words array
          let newWord = this.state.words[j].secretWord;
          newWord += specialChar + ' ';
          translatedWords.push({
            word: newWord,
            hasClick: false
          });
          this.setState({
            translatedWords: translatedWords
          });
          isWordInDictionary = true;
          break;
        }
      }
      if (!isWordInDictionary) {
        let newWord = mainText[i]; // The word to add to the translated words array.
        translatedWords.push({
          word: newWord,
          hasClick: true
        });
        translatedWords.push({
          word: specialChar +  ' ',
          hasClick: false
        });

        this.setState({
          translatedWords: translatedWords
        });
      }
    }
  }

  handleClearTranslationClick() {
    this.setState({
      translateTextarea: '',
      translatedWords: []
    });
  }

  handleTranslateNewWordFormSubmit(word) {
    let words = [...this.state.words];
    words.push({
      mainWord: word.main,
      secretWord: word.secret
    });
    this.setState({
      words: words
    });
    localStorage.setItem('words', JSON.stringify(words));
  }

  /**
  * Get a random word from the dictionary of words.
  * @returns {String}
  */
  getRandomValue(arr) {
      var randNum = Math.floor(Math.random() * arr.length);
      if (arr[randNum]) {
          return arr[randNum];
      }
      else {
          return "";
      }
  }

  flashCardNextWord(event) {
    this.setState({
      flashCardWord: this.getRandomValue(this.state.words)
    });
  }

  wordToEdit(pathWord) {
    return this.state.words.find((element) => element.mainWord === pathWord);
  }

  handleEditWordSubmit(word) {
    let words = [...this.state.words];
    let index = words.map(function(el) { return el.mainWord; }).indexOf(word.mainWord);
    words[index] = {
      mainWord: word.mainWord,
      secretWord: word.secretWord
    };
    this.setState({
      words: words
    });
    localStorage.setItem('words', JSON.stringify(words));
  }

  deleteWord(mainWord) {
    let words = [...this.state.words];
    let index = words.map(function(el) { return el.mainWord; }).indexOf(mainWord);
    words.splice(index, 1);
    this.setState({
      words: words
    });
    localStorage.setItem('words', JSON.stringify(words));
  }

  addToCategory(category) {
    return category;
  }

  handleAddNoteFormSubmit(category, title, description) {
    let notes = [...this.state.notes];
    let index = notes.map(function(el) { return el.categoryTitle; }).indexOf(category);
    notes[index].categoryNotes.push({
      title: title,
      description: description
    });
    this.setState({
      notes: notes
    });
    localStorage.setItem('notes', JSON.stringify(notes));
  }

  getNote(category, index) {
    let categoryGroup = this.state.notes.find(function(el) { return el.categoryTitle === category});
    if (categoryGroup.categoryNotes[index]) return categoryGroup.categoryNotes[index];
    return {categoryTitle: '', categoryNotes: []};
  }

  editNote(category, index, noteTitle, noteDescription) {
    let categoryGroupIndex = this.state.notes.map(function(el) { return el.categoryTitle; }).indexOf(category);
    let notes = [...this.state.notes];
    notes[categoryGroupIndex].categoryNotes[index] = {
      title: noteTitle,
      description: noteDescription
    };
    this.setState({
      notes: notes
    });
    localStorage.setItem('notes', JSON.stringify(notes));
  }

  deleteNote(category, index) {
    let categoryGroupIndex = this.state.notes.map(function(el) { return el.categoryTitle; }).indexOf(category);
    let notes = [...this.state.notes];
    notes[categoryGroupIndex].categoryNotes.splice(index, 1);
    this.setState({
      notes: notes
    });
    localStorage.setItem('notes', JSON.stringify(notes));
  }

  render() {
    const addWord = () => {
      return (
        <AddWord
          onAddWordFormSubmit={(mainWord, secretWord) => this.handleAddWordFormSubmit(mainWord, secretWord)} />
      )
    };
    const translate = () => {
      return (
        <Translate
          translateText={this.state.translateTextarea}
          onTextareaChange={(e) => this.handleTranslateTextareaChange(e)}
          translatedWords={this.state.translatedWords}
          onClearTranslationClick={() => this.handleClearTranslationClick()}
          onNewWordFormSubmit={(e) => this.handleTranslateNewWordFormSubmit(e)} />
      )
    };
    const dictionary = () => {
      return (
        <Dictionary
          words={this.state.words} />
      );
    };
    const flashCards = () => {
      return (
        <FlashCards
          word={this.state.flashCardWord}
          onNextWordClick={(e) => this.flashCardNextWord(e)} />
      );
    };
    const notes = () => {
      return (
        <Notes
          notes={this.state.notes} />
      );
    };
    const editWord = ({match}) => {
      return (
        <EditWord
          word={this.wordToEdit(match.params.word)}
          onEditWordFormSubmit={(word) => this.handleEditWordSubmit(word)}
          onDeleteWordClick={(word) => this.deleteWord(word)} />
      );
    }
    const addNote = ({match}) => {
      return (
        <AddNote
          category={this.addToCategory(match.params.category)}
          onAddNoteFormSubmit={(category, title, description) => this.handleAddNoteFormSubmit(category, title, description)} />
      );
    };
    const viewNote = ({match}) => {
      return (
        <ViewNote
          note={this.getNote(match.params.category, match.params.id)}
          category={this.addToCategory(match.params.category)}
          index={match.params.id}
          onDeleteNoteClick={(category, index) => this.deleteNote(category, index)}
          onEditNoteFormSubmit={(category, index, noteTitle, noteDescription) => this.editNote(category, index, noteTitle, noteDescription)} />
      );
    };

    return (
      <BrowserRouter>

            <Switch>
              <Route path='/' exact component={Home} />
              <Route path='/add-word' render={addWord} />
              <Route path='/translate' render={translate} />
              <Route path='/dictionary' render={dictionary} />
              <Route path='/flash-cards' render={flashCards} />
              <Route path='/notes' render={notes} />
              <Route path='/edit-word/:word' render={editWord} />
              <Route path='/add-note/:category' render={addNote} />
              <Route path='/view-note/:category/:id' render={viewNote} />
              <Redirect from='/add-note' to='/notes' />
            </Switch>

      </BrowserRouter>
    );
  }
}

export default App;
<commit_msg>Fix highlight not being removed when saving new word from translate page<commit_after>import React from 'react';
import {
  BrowserRouter,
  Route,
  Switch,
  Redirect
} from "react-router-dom";
import Header from './Header';
import Home from './Home';
import AddWord from './AddWord';
import Translate from './Translate';
import Dictionary from './Dictionary';
import FlashCards from './FlashCards';
import Notes from './Notes';
import AddNote from './AddNote';
import ViewNote from './ViewNote';
import EditWord from './EditWord';
import Setup from './Setup';
import './App.css';

class App extends React.Component {
  constructor() {
    super();
    // Initialize words and notes from local storage.
    if ( ! localStorage.getItem('words')) localStorage.setItem('words', JSON.stringify([]));
    if ( ! localStorage.getItem('notes')) localStorage.setItem('notes', JSON.stringify(Setup.DEFAULT_NOTES));
    this.state = {
      words: JSON.parse(localStorage.getItem('words')),
      flashCardWord: '',
      translateTextarea: '',
      translatedWords: [],
      notes: JSON.parse(localStorage.getItem('notes'))
    };
  }

  componentDidMount() {
    let flashCardWord = this.getRandomValue(this.state.words);
    this.setState({flashCardWord: flashCardWord});
  }

  handleAddWordFormSubmit(mainWord, secretWord) {
    let words = [...this.state.words];
    words.push({
      mainWord: mainWord,
      secretWord: secretWord
    });
    this.setState({
      words: words
    });
    localStorage.setItem('words', JSON.stringify(words));
  }

  handleTranslateTextareaChange(event) {
    let mainText = event.target.value;
    this.setState({
      translateTextarea: mainText,
      translatedWords: []
    });

    this.updateTranslatedWords(mainText);
  }

  updateTranslatedWords(mainText) {
    let translatedWords = [];
    mainText = mainText.split(" ");

    // Loop through the english textarea text
    for (let i = 0; i < mainText.length; i++) {
      let isWordInDictionary = false;     // Whether the word is in the dictionary or not.
      let specialChar = "";  // The special character that is at the end of the word.

      // Check if the word ends in a special character
      let specialCharsList = [',', '.', ';', ':', '?', '!'];
      if (specialCharsList.indexOf(mainText[i].charAt(mainText[i].length - 1)) !== -1) {
        specialChar = mainText[i].charAt(mainText[i].length - 1);
        mainText[i] = mainText[i].substring(0, mainText[i].length - 1);
      }

      // Loop through the dictionary and check if the word has been defined yet.
      for (let j = 0; j < this.state.words.length; j++) {
        // if it is found, add it to the translatedWords array
        if (mainText[i].toUpperCase() === this.state.words[j].mainWord.toUpperCase()) {
          // The word to add to the translated words array
          let newWord = this.state.words[j].secretWord;
          newWord += specialChar + ' ';
          translatedWords.push({
            word: newWord,
            hasClick: false
          });
          this.setState({
            translatedWords: translatedWords
          });
          isWordInDictionary = true;
          break;
        }
      }
      if (!isWordInDictionary) {
        let newWord = mainText[i]; // The word to add to the translated words array.
        translatedWords.push({
          word: newWord,
          hasClick: true
        });
        translatedWords.push({
          word: specialChar +  ' ',
          hasClick: false
        });

        this.setState({
          translatedWords: translatedWords
        });
      }
    }
  }

  handleClearTranslationClick() {
    this.setState({
      translateTextarea: '',
      translatedWords: []
    });
  }

  handleTranslateNewWordFormSubmit(word) {
    let words = [...this.state.words];
    words.push({
      mainWord: word.main,
      secretWord: word.secret
    });
    localStorage.setItem('words', JSON.stringify(words));
    this.setState({
      words: words
    }, () => this.updateTranslatedWords(this.state.translateTextarea));
  }

  /**
  * Get a random word from the dictionary of words.
  * @returns {String}
  */
  getRandomValue(arr) {
      var randNum = Math.floor(Math.random() * arr.length);
      if (arr[randNum]) {
          return arr[randNum];
      }
      else {
          return "";
      }
  }

  flashCardNextWord(event) {
    this.setState({
      flashCardWord: this.getRandomValue(this.state.words)
    });
  }

  wordToEdit(pathWord) {
    return this.state.words.find((element) => element.mainWord === pathWord);
  }

  handleEditWordSubmit(word) {
    let words = [...this.state.words];
    let index = words.map(function(el) { return el.mainWord; }).indexOf(word.mainWord);
    words[index] = {
      mainWord: word.mainWord,
      secretWord: word.secretWord
    };
    this.setState({
      words: words
    });
    localStorage.setItem('words', JSON.stringify(words));
  }

  deleteWord(mainWord) {
    let words = [...this.state.words];
    let index = words.map(function(el) { return el.mainWord; }).indexOf(mainWord);
    words.splice(index, 1);
    this.setState({
      words: words
    });
    localStorage.setItem('words', JSON.stringify(words));
  }

  addToCategory(category) {
    return category;
  }

  handleAddNoteFormSubmit(category, title, description) {
    let notes = [...this.state.notes];
    let index = notes.map(function(el) { return el.categoryTitle; }).indexOf(category);
    notes[index].categoryNotes.push({
      title: title,
      description: description
    });
    this.setState({
      notes: notes
    });
    localStorage.setItem('notes', JSON.stringify(notes));
  }

  getNote(category, index) {
    let categoryGroup = this.state.notes.find(function(el) { return el.categoryTitle === category});
    if (categoryGroup.categoryNotes[index]) return categoryGroup.categoryNotes[index];
    return {categoryTitle: '', categoryNotes: []};
  }

  editNote(category, index, noteTitle, noteDescription) {
    let categoryGroupIndex = this.state.notes.map(function(el) { return el.categoryTitle; }).indexOf(category);
    let notes = [...this.state.notes];
    notes[categoryGroupIndex].categoryNotes[index] = {
      title: noteTitle,
      description: noteDescription
    };
    this.setState({
      notes: notes
    });
    localStorage.setItem('notes', JSON.stringify(notes));
  }

  deleteNote(category, index) {
    let categoryGroupIndex = this.state.notes.map(function(el) { return el.categoryTitle; }).indexOf(category);
    let notes = [...this.state.notes];
    notes[categoryGroupIndex].categoryNotes.splice(index, 1);
    this.setState({
      notes: notes
    });
    localStorage.setItem('notes', JSON.stringify(notes));
  }

  render() {
    const addWord = () => {
      return (
        <AddWord
          onAddWordFormSubmit={(mainWord, secretWord) => this.handleAddWordFormSubmit(mainWord, secretWord)} />
      )
    };
    const translate = () => {
      return (
        <Translate
          translateText={this.state.translateTextarea}
          onTextareaChange={(e) => this.handleTranslateTextareaChange(e)}
          translatedWords={this.state.translatedWords}
          onClearTranslationClick={() => this.handleClearTranslationClick()}
          onNewWordFormSubmit={(e) => this.handleTranslateNewWordFormSubmit(e)} />
      )
    };
    const dictionary = () => {
      return (
        <Dictionary
          words={this.state.words} />
      );
    };
    const flashCards = () => {
      return (
        <FlashCards
          word={this.state.flashCardWord}
          onNextWordClick={(e) => this.flashCardNextWord(e)} />
      );
    };
    const notes = () => {
      return (
        <Notes
          notes={this.state.notes} />
      );
    };
    const editWord = ({match}) => {
      return (
        <EditWord
          word={this.wordToEdit(match.params.word)}
          onEditWordFormSubmit={(word) => this.handleEditWordSubmit(word)}
          onDeleteWordClick={(word) => this.deleteWord(word)} />
      );
    }
    const addNote = ({match}) => {
      return (
        <AddNote
          category={this.addToCategory(match.params.category)}
          onAddNoteFormSubmit={(category, title, description) => this.handleAddNoteFormSubmit(category, title, description)} />
      );
    };
    const viewNote = ({match}) => {
      return (
        <ViewNote
          note={this.getNote(match.params.category, match.params.id)}
          category={this.addToCategory(match.params.category)}
          index={match.params.id}
          onDeleteNoteClick={(category, index) => this.deleteNote(category, index)}
          onEditNoteFormSubmit={(category, index, noteTitle, noteDescription) => this.editNote(category, index, noteTitle, noteDescription)} />
      );
    };

    return (
      <BrowserRouter>

            <Switch>
              <Route path='/' exact component={Home} />
              <Route path='/add-word' render={addWord} />
              <Route path='/translate' render={translate} />
              <Route path='/dictionary' render={dictionary} />
              <Route path='/flash-cards' render={flashCards} />
              <Route path='/notes' render={notes} />
              <Route path='/edit-word/:word' render={editWord} />
              <Route path='/add-note/:category' render={addNote} />
              <Route path='/view-note/:category/:id' render={viewNote} />
              <Redirect from='/add-note' to='/notes' />
            </Switch>

      </BrowserRouter>
    );
  }
}

export default App;
<|endoftext|>


<commit_before>var JX = require('javelin').JX;

var fs = require('fs');
var util = require('util');

JX.install('AphlictLog', {
  construct: function() {
    this._writeToLogs = [];
    this._writeToConsoles = [];
  },

  members: {
    _writeToConsoles: null,
    _writeToLogs: null,

    addLogfile: function(path) {
      var options = {
        flags: 'a',
        encoding: 'utf8',
        mode: 066
      };

      var logfile = fs.createWriteStream(path, options);

      this._writeToLogs.push(logfile);

      return this;
    },

    addConsole: function(console) {
      this._writeToConsoles.push(console);
      return this;
    },

    log: function() {
      var str = util.format.apply(null, arguments);
      var date = new Date().toLocaleString();
      str = '[' + date + '] ' + str;

      var ii;
      for (ii = 0; ii < this._writeToConsoles.length; ii++) {
        this._writeToConsoles[ii].log(str);
      }

      for (ii = 0; ii < this._writeToLogs.length; ii++) {
        this._writeToLogs[ii].write(str + '\n');
      }
    }

  }

});
<commit_msg>Fix permissions on Aphlict log<commit_after>var JX = require('javelin').JX;

var fs = require('fs');
var util = require('util');

JX.install('AphlictLog', {
  construct: function() {
    this._writeToLogs = [];
    this._writeToConsoles = [];
  },

  members: {
    _writeToConsoles: null,
    _writeToLogs: null,

    addLogfile: function(path) {
      var options = {
        flags: 'a',
        encoding: 'utf8',
        mode: 0664,
      };

      var logfile = fs.createWriteStream(path, options);

      this._writeToLogs.push(logfile);

      return this;
    },

    addConsole: function(console) {
      this._writeToConsoles.push(console);
      return this;
    },

    log: function() {
      var str = util.format.apply(null, arguments);
      var date = new Date().toLocaleString();
      str = '[' + date + '] ' + str;

      var ii;
      for (ii = 0; ii < this._writeToConsoles.length; ii++) {
        this._writeToConsoles[ii].log(str);
      }

      for (ii = 0; ii < this._writeToLogs.length; ii++) {
        this._writeToLogs[ii].write(str + '\n');
      }
    }

  }

});
<|endoftext|>


<commit_before>require('moonstone');

/**
* Contains the declaration for the {@link module:moonstone/ExpandableInput~ExpandableInput} kind.
* @module moonstone/ExpandableInput
*/

var
	kind = require('enyo/kind'),
	Control = require('enyo/Control'),
	Drawer = require('enyo/Drawer');

var
	Spotlight = require('spotlight');

var
	ExpandableListItem = require('../ExpandableListItem'),
	Item = require('../Item'),
	Input = require('../Input'),
	InputDecorator = require('../InputDecorator'),
	Marquee = require('../Marquee'),
	MarqueeText = Marquee.Text;

/**
* Fires when the current text changes. This passes through {@link module:enyo/Input~Input#onChange}.
*
* @event moon.ExpandableInput#onChange
* @type {Object}
* @property {String} value - The value of the input.
* @public
*/

/**
* {@link module:moonstone/ExpandableInput~ExpandableInput}, which extends {@link module:moonstone/ExpandableListItem~ExpandableListItem}, is a
* drop-down input that prompts the user to enter text.
*
* @class ExpandableInput
* @extends module:moonstone/ExpandableListItem~ExpandableListItem
* @ui
* @public
*/
module.exports = kind(
	/** @lends module:moonstone/ExpandableInput~ExpandableInput.prototype */ {

	/**
	* @private
	*/
	name: 'moon.ExpandableInput',

	/**
	* @private
	*/
	kind: ExpandableListItem,

	/**
	* @private
	*/
	classes: 'moon-expandable-input',

	/**
	* @private
	*/
	events: {

		/** {@link module:moonstone/ExpandableInput~ExpandableInput#onChange} */
		onChange: ''
	},

	/**
	* @private
	* @lends module:moonstone/ExpandableInput~ExpandableInput.prototype
	*/
	published: {

		/**
		* Text to be displayed as the current value if no item is currently selected.
		*
		* @type {String}
		* @default ''
		* @public
		*/
		noneText: '',

		/**
		* Text to be displayed in the input if no text has been entered.
		*
		* @type {String}
		* @default ''
		* @public
		*/
		placeholder: '',

		/**
		* Initial value of the input.
		*
		* @type {String}
		* @default ''
		* @public
		*/
		value: ''
	},

	/**
	* @private
	*/
	autoCollapse: true,

	/**
	* @private
	*/
	lockBottom: false,

	/**
	* @private
	*/
	components: [
		{name: 'headerWrapper', kind: Item, classes: 'moon-expandable-picker-header-wrapper', onSpotlightFocus: 'headerFocus', ondown: 'headerDown', ontap: 'expandContract', components: [
			// headerContainer required to avoid bad scrollWidth returned in RTL for certain text widths (webkit bug)
			{name: 'headerContainer', kind: Control, classes: 'moon-expandable-list-item-header moon-expandable-picker-header moon-expandable-input-header', components: [
				{name: 'header', kind: MarqueeText}
			]},
			{name: 'currentValue', kind: MarqueeText, classes: 'moon-expandable-picker-current-value'}
		]},
		{name: 'drawer', kind: Drawer, resizeContainer:false, classes:'moon-expandable-list-item-client indented', components: [
			{name: 'inputDecorator', kind: InputDecorator, onSpotlightBlur: 'inputBlur', onSpotlightFocus: 'inputFocus', onSpotlightDown: 'inputDown', components: [
				{name: 'clientInput', kind: Input, onchange: 'doChange', onkeyup: 'inputKeyUp'}
			]}
		]}
	],

	/**
	* @private
	*/
	bindings: [
		{from: '.value', to: '.$.clientInput.value', oneWay: false},
		{from: '.placeholder', to: '.$.clientInput.placeholder'},
		{from: '.showCurrentValue', to: '.$.currentValue.showing'},
		{from: '.currentValueText', to: '.$.currentValue.content'},
		{from: '.disabled', to: '.$.headerWrapper.disabled'}
	],

	/**
	* @private
	*/
	computed: {
		'showCurrentValue': ['open', 'value', 'noneText'],
		'currentValueText': ['value', 'noneText']
	},

	/**
	* Computed property
	*
	* @private
	*/
	showCurrentValue: function () {
		return !this.open && this.currentValueText() !== '';
	},

	/**
	* Computed property
	*
	* @private
	*/
	currentValueText: function () {
		return (this.value === '') ? this.noneText : this.value;
	},

	/**
	* @private
	*/
	expandContract: function () {
		if (this.getOpen()) {
			this.closeDrawerAndHighlightHeader();
		} else {
			this.toggleActive();
		}
	},

	/**
	* @private
	*/
	toggleActive: function () {
		if (this.getOpen()) {
			this.setActive(false);
			this.$.clientInput.blur();
		} else {
			this.setActive(true);
			Spotlight.unspot();
			this.focusInput();
		}
	},

	/**
	* Focuses the {@link module:moonstone/Input~Input} when the input decorator receives focus.
	*
	* @private
	*/
	inputFocus: function (inSender, inEvent) {
		var direction = inEvent && inEvent.dir;
		if (this.getOpen() && direction) {
			this.focusInput();
		}
	},

	/**
	* Value should be submitted if user clicks outside control. We check for
	* `onSpotlightFocus` and `mouseover` to avoid contracting the input on an event
	* fired from itself.
	*
	* @private
	*/
	inputBlur: function (inSender, inEvent) {
		var eventType = Spotlight.getLastEvent().type;
		if (Spotlight.getPointerMode() && eventType !== 'onSpotlightFocus' && eventType !== 'mouseover') {
			this.toggleActive();
		}
	},

	/**
	* @private
	*/
	inputKeyUp: function (inSender, inEvent) {
		if (inEvent.keyCode === 13) {
			this.closeDrawerAndHighlightHeader();
		}
	},

	/**
	* @private
	*/
	headerDown: function () {
		Spotlight.unfreeze();
	},

	/**
	* Focuses the input field if navigating down from the header while the drawer is open.
	*
	* @private
	*/
	spotlightDown: function (inSender, inEvent) {
		if (inEvent.originator === this.$.headerWrapper && this.getOpen()) {
			this.focusInput();
		}
	},

	/**
	* Focuses the input field.
	*
	* @private
	*/
	focusInput: function () {
		this.$.clientInput.focus();
		// Force cursor to end of text. We were sometimes seeing the
		// cursor positioned at the start of the text, which caused
		// problems in 5-way mode (where there's no way to move the
		// cursor).
		this.$.clientInput.hasNode().selectionStart = this.value.length;
	},

	/**
	* If [lockBottom]{@link module:moonstone/ExpandableInput~ExpandableInput#lockBottom} is `true`, don't allow user
	* to navigate down from the input field; if `false`, close the drawer and return
	* `true` to keep {@glossary Spotlight} on header.
	*
	* @private
	*/
	inputDown: function (inSender, inEvent) {
		if (this.getLockBottom()) {
			this.focusInput();
		} else {
			this.closeDrawerAndHighlightHeader();
		}
		return true;
	},

	/**
	* We manually set pointer mode to `false` as this seems to be the
	* least harmful method to re-highlight the header after the drawer
	* closes. The other options had side effects of resetting the
	* current spotted control to the root, or requiring a double-press to
	* subsequently move via 5-way.
	*
	* @private
	*/
	closeDrawerAndHighlightHeader: function () {
		var mode = Spotlight.getPointerMode();
		Spotlight.setPointerMode(false);
		Spotlight.unfreeze();
		Spotlight.spot(this.$.headerWrapper);
		Spotlight.setPointerMode(mode);
		this.toggleActive();
	}
});
<commit_msg>ENYO-2081: Provide ExpandableInput access to set input's attribute Enyo-DCO-1.1-Signed-off-by: Stephen Choi <stephen.choi@lge.com><commit_after>require('moonstone');

/**
* Contains the declaration for the {@link module:moonstone/ExpandableInput~ExpandableInput} kind.
* @module moonstone/ExpandableInput
*/

var
	kind = require('enyo/kind'),
	Control = require('enyo/Control'),
	Drawer = require('enyo/Drawer');

var
	Spotlight = require('spotlight');

var
	ExpandableListItem = require('../ExpandableListItem'),
	Item = require('../Item'),
	Input = require('../Input'),
	InputDecorator = require('../InputDecorator'),
	Marquee = require('../Marquee'),
	MarqueeText = Marquee.Text;

/**
* Fires when the current text changes. This passes through {@link module:enyo/Input~Input#onChange}.
*
* @event moon.ExpandableInput#onChange
* @type {Object}
* @property {String} value - The value of the input.
* @public
*/

/**
* {@link module:moonstone/ExpandableInput~ExpandableInput}, which extends {@link module:moonstone/ExpandableListItem~ExpandableListItem}, is a
* drop-down input that prompts the user to enter text.
*
* @class ExpandableInput
* @extends module:moonstone/ExpandableListItem~ExpandableListItem
* @ui
* @public
*/
module.exports = kind(
	/** @lends module:moonstone/ExpandableInput~ExpandableInput.prototype */ {

	/**
	* @private
	*/
	name: 'moon.ExpandableInput',

	/**
	* @private
	*/
	kind: ExpandableListItem,

	/**
	* @private
	*/
	classes: 'moon-expandable-input',

	/**
	* @private
	*/
	events: {

		/** {@link module:moonstone/ExpandableInput~ExpandableInput#onChange} */
		onChange: ''
	},

	/**
	* @private
	* @lends module:moonstone/ExpandableInput~ExpandableInput.prototype
	*/
	published: {

		/**
		* Text to be displayed as the current value if no item is currently selected.
		*
		* @type {String}
		* @default ''
		* @public
		*/
		noneText: '',

		/**
		* Text to be displayed in the input if no text has been entered.
		*
		* @type {String}
		* @default ''
		* @public
		*/
		placeholder: '',

		/**
		* Initial value of the input.
		*
		* @type {String}
		* @default ''
		* @public
		*/
		value: ''
	},

	/**
	* @private
	*/
	autoCollapse: true,

	/**
	* @private
	*/
	lockBottom: false,

	/**
	* @private
	*/
	components: [
		{name: 'headerWrapper', kind: Item, classes: 'moon-expandable-picker-header-wrapper', onSpotlightFocus: 'headerFocus', ondown: 'headerDown', ontap: 'expandContract', components: [
			// headerContainer required to avoid bad scrollWidth returned in RTL for certain text widths (webkit bug)
			{name: 'headerContainer', kind: Control, classes: 'moon-expandable-list-item-header moon-expandable-picker-header moon-expandable-input-header', components: [
				{name: 'header', kind: MarqueeText}
			]},
			{name: 'currentValue', kind: MarqueeText, classes: 'moon-expandable-picker-current-value'}
		]},
		{name: 'drawer', kind: Drawer, resizeContainer:false, classes:'moon-expandable-list-item-client indented', components: [
			{name: 'inputDecorator', kind: InputDecorator, onSpotlightBlur: 'inputBlur', onSpotlightFocus: 'inputFocus', onSpotlightDown: 'inputDown', components: [
				{name: 'clientInput', kind: Input, onchange: 'doChange', onkeyup: 'inputKeyUp'}
			]}
		]}
	],

	/**
	* @private
	*/
	bindings: [
		{from: '.value', to: '.$.clientInput.value', oneWay: false},
		{from: '.placeholder', to: '.$.clientInput.placeholder'},
		{from: '.showCurrentValue', to: '.$.currentValue.showing'},
		{from: '.currentValueText', to: '.$.currentValue.content'},
		{from: '.disabled', to: '.$.headerWrapper.disabled'}
	],

	/**
	* @private
	*/
	computed: {
		'showCurrentValue': ['open', 'value', 'noneText'],
		'currentValueText': ['value', 'noneText']
	},

	/**
	* Computed property
	*
	* @private
	*/
	showCurrentValue: function () {
		return !this.open && this.currentValueText() !== '';
	},

	/**
	* Computed property
	*
	* @private
	*/
	currentValueText: function () {
		return (this.value === '') ? this.noneText : this.value;
	},

	/**
	* Assigns an attribute to a {@link module:moonstone/Input~Input}
	* @param {String} name - Attribute name to assign/remove.
	* @param {(String|Number|null)} value - The value to assign to `name`
	* @public
	*/
	setInputAttribute: function (name, value) {
		this.$.clientInput.setAttribute(name, value);
	},

	/**
	* @private
	*/
	expandContract: function () {
		if (this.getOpen()) {
			this.closeDrawerAndHighlightHeader();
		} else {
			this.toggleActive();
		}
	},

	/**
	* @private
	*/
	toggleActive: function () {
		if (this.getOpen()) {
			this.setActive(false);
			this.$.clientInput.blur();
		} else {
			this.setActive(true);
			Spotlight.unspot();
			this.focusInput();
		}
	},

	/**
	* Focuses the {@link module:moonstone/Input~Input} when the input decorator receives focus.
	*
	* @private
	*/
	inputFocus: function (inSender, inEvent) {
		var direction = inEvent && inEvent.dir;
		if (this.getOpen() && direction) {
			this.focusInput();
		}
	},

	/**
	* Value should be submitted if user clicks outside control. We check for
	* `onSpotlightFocus` and `mouseover` to avoid contracting the input on an event
	* fired from itself.
	*
	* @private
	*/
	inputBlur: function (inSender, inEvent) {
		var eventType = Spotlight.getLastEvent().type;
		if (Spotlight.getPointerMode() && eventType !== 'onSpotlightFocus' && eventType !== 'mouseover') {
			this.toggleActive();
		}
	},

	/**
	* @private
	*/
	inputKeyUp: function (inSender, inEvent) {
		if (inEvent.keyCode === 13) {
			this.closeDrawerAndHighlightHeader();
		}
	},

	/**
	* @private
	*/
	headerDown: function () {
		Spotlight.unfreeze();
	},

	/**
	* Focuses the input field if navigating down from the header while the drawer is open.
	*
	* @private
	*/
	spotlightDown: function (inSender, inEvent) {
		if (inEvent.originator === this.$.headerWrapper && this.getOpen()) {
			this.focusInput();
		}
	},

	/**
	* Focuses the input field.
	*
	* @private
	*/
	focusInput: function () {
		this.$.clientInput.focus();
		// Force cursor to end of text. We were sometimes seeing the
		// cursor positioned at the start of the text, which caused
		// problems in 5-way mode (where there's no way to move the
		// cursor).
		this.$.clientInput.hasNode().selectionStart = this.value.length;
	},

	/**
	* If [lockBottom]{@link module:moonstone/ExpandableInput~ExpandableInput#lockBottom} is `true`, don't allow user
	* to navigate down from the input field; if `false`, close the drawer and return
	* `true` to keep {@glossary Spotlight} on header.
	*
	* @private
	*/
	inputDown: function (inSender, inEvent) {
		if (this.getLockBottom()) {
			this.focusInput();
		} else {
			this.closeDrawerAndHighlightHeader();
		}
		return true;
	},

	/**
	* We manually set pointer mode to `false` as this seems to be the
	* least harmful method to re-highlight the header after the drawer
	* closes. The other options had side effects of resetting the
	* current spotted control to the root, or requiring a double-press to
	* subsequently move via 5-way.
	*
	* @private
	*/
	closeDrawerAndHighlightHeader: function () {
		var mode = Spotlight.getPointerMode();
		Spotlight.setPointerMode(false);
		Spotlight.unfreeze();
		Spotlight.spot(this.$.headerWrapper);
		Spotlight.setPointerMode(mode);
		this.toggleActive();
	}
});
<|endoftext|>


<commit_before>const chai = require('chai');
const sinon = require('sinon');

chai.should();

const onHeadersListener = require('../../helpers/on-headers-listener');
const defaultConfig = require('../../helpers/default-config');

describe('helpers', () => {
  describe('on-headers-listener', () => {
    describe('when invoked', () => {
      let clock;
      const spans = defaultConfig.spans;

      before(() => {
        clock = sinon.useFakeTimers();
        spans.forEach((span) => {
          span.responses = [];
        });
      });

      after(() => {
        clock.restore();
      });

      it('then for all spans, responses length should equal 1', () => {
        onHeadersListener(404, process.hrtime(), spans);

        spans.forEach((span) => {
          span.responses.length.should.equal(1);
        });
      });

      describe('when invoked after 1 second', () => {
        it('then for span interval 1, responses length should equal 2', () => {
          clock.tick(1000);
          onHeadersListener(500, process.hrtime(), spans);

          spans.forEach((span) => {
            if (span.interval === 1) {
              span.responses.length.should.equal(2);
            } else {
              span.responses.length.should.equal(1);
            }
          });
        });
      });
    });
  });
});
<commit_msg>fake timers as const<commit_after>const chai = require('chai');
const sinon = require('sinon');

chai.should();

const onHeadersListener = require('../../helpers/on-headers-listener');
const defaultConfig = require('../../helpers/default-config');

describe('helpers', () => {
  describe('on-headers-listener', () => {
    describe('when invoked', () => {
      const clock = sinon.useFakeTimers();
      const spans = defaultConfig.spans;

      before(() => {
        spans.forEach((span) => {
          span.responses = [];
        });
      });

      after(() => {
        clock.restore();
      });

      it('then for all spans, responses length should equal 1', () => {
        onHeadersListener(404, process.hrtime(), spans);

        spans.forEach((span) => {
          span.responses.length.should.equal(1);
        });
      });

      describe('when invoked after 1 second', () => {
        it('then for span interval 1, responses length should equal 2', () => {
          clock.tick(1000);
          onHeadersListener(500, process.hrtime(), spans);

          spans.forEach((span) => {
            if (span.interval === 1) {
              span.responses.length.should.equal(2);
            } else {
              span.responses.length.should.equal(1);
            }
          });
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>
var nyplViewer = angular.module('nyplViewer', [
  'ngMaterial',
  'base64',
  'ui.router',
  'ui.layout',
  'ui.tinymce',
  'infinite-scroll',
  'wu.masonry',
  'ngLodash',
  'firebase',
  'ngStorage',
  'ngMessages',
])
angular.module('infinite-scroll').value('THROTTLE_MILLISECONDS', 5000)
  .config(function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('');

    $stateProvider
      .state('main', {
        url: '/search?themeName&searchTerms',
        templateUrl: 'src/grid-list/main.html',
        controller: 'GridListCtrl',
        controllerAs: 'gridList',
        params: {
          themeName: {
            value: null,
            dynamic: true
          },
          searchTerms: {
            value: null,
            dynamic: true
          }

        },
        resolve: {
          // controller will not be loaded until $waitForSignIn resolves
          // Auth refers to our $firebaseAuth wrapper in the factory below
          "currentAuth": ["Auth", function (Auth) {
            // $waitForSignIn returns a promise so the resolve waits for it to complete
            return Auth.authObj.$waitForSignIn();
          }]
        },
      })
      .state('image', {
        url: "/image/:id",
        templateUrl: 'src/image-viewer/viewer.html',
        controller: 'ImageViewerCtrl',
        controllerAs: 'imageViewer',
        params: { myParam: null },
      })
      .state('admin', {
        url: '/admin',
        templateUrl: 'src/admin/admin.html',
        controller: 'AdminCtrl',
        controllerAs: 'admin',
        resolve: {
          // controller will not be loaded until $waitForSignIn resolves
          // Auth refers to our $firebaseAuth wrapper in the factory below
          "currentAuth": ["Auth", function (Auth) {
            // $waitForSignIn returns a promise so the resolve waits for it to complete
            return Auth.authObj.$waitForSignIn();
          }]
        }
      });
  })
  .directive('stickyLoadingbar', function ($mdSticky, $compile) {
    var LOADINGBAR_TEMPLATE =
      '
' +
      '<md-progress-linear md-mode="indeterminate" md-theme="dark-yellow"></md-progress-linear>' +
      '
';
    return {
      restrict: 'E',
      scope: {
        isloading: '='
      },
      replace: true,
      template: LOADINGBAR_TEMPLATE,
      link: function (scope, element) {
        $mdSticky(scope, element, $compile(LOADINGBAR_TEMPLATE)(scope));
      }
    };
  })
  .controller('ListBottomSheetCtrl', function ($scope, $mdBottomSheet) {

    $scope.items = [
      { name: 'Share', icon: 'share-arrow' },
      { name: 'Upload', icon: 'upload' },
      { name: 'Copy', icon: 'copy' },
      { name: 'Print this page', icon: 'print' },
    ];

    $scope.listItemClick = function ($index) {
      var clickedItem = $scope.items[$index];
      $mdBottomSheet.hide(clickedItem);
    };
  })
  .directive('picViewer', function ($compile, $timeout, $mdBottomSheet, $mdToast, $mdDialog, NyplApiCalls) {
    return {
      restrict: 'AE',
      scope: {
        dataoriginal: '=',
      },
      link: function (scope, elem, attrs) {
        scope.metadata = {};
        scope.title;
        scope.names;
        scope.collection;
        //scope.startDate;
        //scope.endDate;
        scope.originInfo;
        scope.physicalDescription;
        scope.notes;
        scope.genres;
        scope.showMeta = false;
        scope.values = '';

        scope.recursJsonPrint = function (obj) {
          for (var key in obj) {
            if (typeof (obj[key]) == 'object') {
              scope.recursJsonPrint(obj[key]);
            } else {
              if (key == '$'){
                scope.values = scope.values + (obj[key]) +' ';
              }

              //alert("Key: " + key + " Values: " + obj[key]);
            }
          }
          return scope.values;
        }

        scope.showMetaData = function () {
          console.log(JSON.parse(attrs.picMetadata));
          NyplApiCalls.getDetail(JSON.parse(attrs.picMetadata)).then(function (result) {
            scope.metadata = result;
            try {
              scope.title = scope.metadata.nyplAPI.response.mods.titleInfo.title.$;
            }
            catch (err) {
              scope.title = '';
            }
            try {
              scope.names = scope.metadata.nyplAPI.response.mods.subject[0].name.namePart.$;
            }
            catch (err) {
              scope.names = '';
            }
            try {
              scope.collection = scope.metadata.nyplAPI.response.mods.location[0].physicalLocation[2].$;
            }
            catch (err) {
              scope.collection = '';
            }
            try {
              scope.values = '';
              scope.originInfo = scope.recursJsonPrint(scope.metadata.nyplAPI.response.mods.originInfo);
              //if (scope.metadata.nyplAPI.response.mods.originInfo.dateIssued.$ != undefined) {
              //  scope.startDate = scope.metadata.nyplAPI.response.mods.originInfo.dateIssued.$
             // } else if (scope.metadata.nyplAPI.response.mods.originInfo.dateCreated[0].$ != undefined) {
              //  scope.startDate = scope.metadata.nyplAPI.response.mods.originInfo.dateCreated[0].$;
              //}

            }
            catch (err) {
              console.log(err);
              scope.originInfo = '';
            }
            /*
            try {
              scope.endDate = scope.metadata.nyplAPI.response.mods.originInfo.dateCreated[1].$;
            }
            catch (err) {
              scope.endDate = '';
            }
            */
            try {
              scope.values = '';
              scope.notes = scope.recursJsonPrint(scope.metadata.nyplAPI.response.mods.note);
              //var notes = '';
              //angular.forEach(scope.metadata.nyplAPI.response.mods.note, function (note) {
                //notes = notes + '  ' + note.$;
              //})
             // scope.notes = notes;
            }
            catch (err) {
              scope.notes = '';
            }
            try {
              scope.values = '';
              scope.topics = scope.recursJsonPrint(scope.metadata.nyplAPI.response.mods.subject);
              //var topics = '';
              //angular.forEach(scope.metadata.nyplAPI.response.mods.subject, function (subject) {
              //  topics = topics + ',' + subject.topic.$;
              //})
              //scope.topics = topics;
            }
            catch (err) {
              scope.topics = '';
            }
            try {
              scope.values = '';
              scope.genres = scope.recursJsonPrint(scope.metadata.nyplAPI.response.mods.genre);
              //var genres = '';
              //angular.forEach(scope.metadata.nyplAPI.response.mods.genre, function (genre) {
               // genres = genres + ',' + genre.$;
              //})
              //scope.genres = genres;
            }
            catch (err) {
              scope.genres = '';
            }

            scope.physicalDescription = '';

          });

          scope.showMeta = !scope.showMeta;
        }

        scope.showListBottomSheet = function (ev) {
          console.log('firing bottom sheet');
          $mdDialog.show({
            controller: 'ListBottomSheetCtrl',
            templateUrl: 'src/grid-list/bottom-sheet-list-template.html',
            parent: angular.element(document.body),
            targetEvent: ev,
            clickOutsideToClose: true,
            fullscreen: true
          })
            .then(function (answer) {
              scope.status = 'You said the information was "' + answer + '".';
            }, function () {
              scope.status = 'You cancelled the dialog.';
            });
          /*
          scope.alert = '';
          $mdBottomSheet.show({
            templateUrl: 'src/grid-list/bottom-sheet-list-template.html',
            controller: 'ListBottomSheetCtrl'
          }).then(function (clickedItem) {
            scope.alert = clickedItem['name'] + ' clicked!';
          }).catch(function (error) {
            // User clicked outside or hit escape
          });
          */
        };

        scope.logThis = function () {
          console.log('king jubba');
        }
        var showViewer = function () {
          var options = {
            //minHeight: 500,
            //minWidth: element.offsetWidth,
            url: scope.original,
            inline: false,
            build: function (e) {
              // console.log(e.type);

              // ctrl.isViewerBuilt = false;
            },
            built: function (e) {
              //var myEl = angular.element(elem[0].querySelector('.viewer-container'));
              var myEl = document.getElementsByClassName("viewer-container");
              var wrappedResult = angular.element(myEl);
              /*
        $(".viewer-container").each(function () {
          console.log('running this');
          var content = $(this);
          angular.element(document).injector().invoke(function ($compile) {
            var viewerscope = angular.element(content).scope();
            $compile(content)(viewerscope);
          });
        });*/
              console.log(wrappedResult);
              $compile(wrappedResult)(scope);

              // ctrl.isViewerBuilt = true;
              scope.$apply();
            },
          };

          $(elem).viewer(options);

        }
        var viewer;

        // $compile(elem.viewer)(scope);
        //elem.viewer("shown", function () {
        //  console.log(this.viewer === viewer);
        //console.log('done building');
        //  $compile(this.viewer)(scope);
        //});
        elem.bind('click', function () {
          console.log('jubba');
          showViewer();
        });

      }
    };
  })
  .controller('MyCtrl', function ($scope) {
    $scope.anyFunc = function (var1, var2) {
      alert("I am var1 = " + var1);
      alert("I am var2 = " + var2);
    }
  })
  .config(
  [
    '$mdIconProvider',
    '$mdThemingProvider',
    function ($mdIconProvider, $mdThemingProvider) {
      // Register the user `avatar` icons
      $mdIconProvider
        .defaultIconSet("./assets/svg/avatars.svg", 128)
        .icon("search", "./assets/svg/search.svg", 24)
        .icon("settings", "./assets/svg/settings.svg", 24)
        .icon("binoculars", "./assets/svg/binoculars.svg", 48)
        .icon("menu", "./assets/svg/menu.svg", 24)
        .icon("share", "./assets/svg/share.svg", 24)
        .icon("google_plus", "./assets/svg/google_plus.svg", 24)
        .icon("hangouts", "./assets/svg/hangouts.svg", 24)
        .icon("twitter", "./assets/svg/twitter.svg", 24)
        .icon("pen", "./assets/svg/fountain-pen.svg", 24)
        .icon("open-book", "./assets/svg/open-book.svg", 24)
        .icon("google", "./assets/svg/google.svg", 24)
        .icon("account", "./assets/svg/account.svg", 24)
        .icon("sign-out", "./assets/svg/sign-out.svg", 24)
        .icon("add", "./assets/svg/add.svg", 24)
        .icon("edit", "./assets/svg/edit.svg", 24)
        .icon("delete", "./assets/svg/delete.svg", 24)
        .icon("bookmark", "./assets/svg/bookmark.svg", 24)
        .icon("phone", "./assets/svg/phone.svg", 24);

      $mdThemingProvider.theme('default')
        .primaryPalette('grey', {
          'default': '400', // by default use shade 400 from the pink palette for primary intentions
          'hue-1': '200', // use shade 100 for the md-hue-1 class
          'hue-2': '600', // use shade 600 for the md-hue-2 class
          'hue-3': '50' // use shade A100 for the md-hue-3 class
        })
        .accentPalette('amber');

      $mdThemingProvider.theme('dark-yellow').primaryPalette('yellow', {
        'default': '700'
      });

      $mdThemingProvider.theme('light-grey').primaryPalette('grey', {
        'default': 'A100'
      });

      $mdThemingProvider.theme('input', 'default')
        .primaryPalette('grey')

    }
  ]
  );
<commit_msg>improved origin info from metadata display<commit_after>
var nyplViewer = angular.module('nyplViewer', [
  'ngMaterial',
  'base64',
  'ui.router',
  'ui.layout',
  'ui.tinymce',
  'infinite-scroll',
  'wu.masonry',
  'ngLodash',
  'firebase',
  'ngStorage',
  'ngMessages',
])
angular.module('infinite-scroll').value('THROTTLE_MILLISECONDS', 5000)
  .config(function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('');

    $stateProvider
      .state('main', {
        url: '/search?themeName&searchTerms',
        templateUrl: 'src/grid-list/main.html',
        controller: 'GridListCtrl',
        controllerAs: 'gridList',
        params: {
          themeName: {
            value: null,
            dynamic: true
          },
          searchTerms: {
            value: null,
            dynamic: true
          }

        },
        resolve: {
          // controller will not be loaded until $waitForSignIn resolves
          // Auth refers to our $firebaseAuth wrapper in the factory below
          "currentAuth": ["Auth", function (Auth) {
            // $waitForSignIn returns a promise so the resolve waits for it to complete
            return Auth.authObj.$waitForSignIn();
          }]
        },
      })
      .state('image', {
        url: "/image/:id",
        templateUrl: 'src/image-viewer/viewer.html',
        controller: 'ImageViewerCtrl',
        controllerAs: 'imageViewer',
        params: { myParam: null },
      })
      .state('admin', {
        url: '/admin',
        templateUrl: 'src/admin/admin.html',
        controller: 'AdminCtrl',
        controllerAs: 'admin',
        resolve: {
          // controller will not be loaded until $waitForSignIn resolves
          // Auth refers to our $firebaseAuth wrapper in the factory below
          "currentAuth": ["Auth", function (Auth) {
            // $waitForSignIn returns a promise so the resolve waits for it to complete
            return Auth.authObj.$waitForSignIn();
          }]
        }
      });
  })
  .directive('stickyLoadingbar', function ($mdSticky, $compile) {
    var LOADINGBAR_TEMPLATE =
      '
' +
      '<md-progress-linear md-mode="indeterminate" md-theme="dark-yellow"></md-progress-linear>' +
      '
';
    return {
      restrict: 'E',
      scope: {
        isloading: '='
      },
      replace: true,
      template: LOADINGBAR_TEMPLATE,
      link: function (scope, element) {
        $mdSticky(scope, element, $compile(LOADINGBAR_TEMPLATE)(scope));
      }
    };
  })
  .controller('ListBottomSheetCtrl', function ($scope, $mdBottomSheet) {

    $scope.items = [
      { name: 'Share', icon: 'share-arrow' },
      { name: 'Upload', icon: 'upload' },
      { name: 'Copy', icon: 'copy' },
      { name: 'Print this page', icon: 'print' },
    ];

    $scope.listItemClick = function ($index) {
      var clickedItem = $scope.items[$index];
      $mdBottomSheet.hide(clickedItem);
    };
  })
  .directive('picViewer', function ($compile, $timeout, $mdBottomSheet, $mdToast, $mdDialog, NyplApiCalls) {
    return {
      restrict: 'AE',
      scope: {
        dataoriginal: '=',
      },
      link: function (scope, elem, attrs) {
        scope.metadata = {};
        scope.title;
        scope.names;
        scope.collection;
        //scope.startDate;
        //scope.endDate;
        scope.originInfo;
        scope.physicalDescription;
        scope.notes;
        scope.genres;
        scope.showMeta = false;
        scope.values = '';

        scope.recursJsonPrint = function (obj) {
          for (var key in obj) {
            if (typeof (obj[key]) == 'object') {
              scope.recursJsonPrint(obj[key]);
            } else {
              if (key == '$'){
                scope.values = scope.values + (obj[key]) +' ';
              }

              //alert("Key: " + key + " Values: " + obj[key]);
            }
          }
          return scope.values;
        }

        scope.showMetaData = function () {
          console.log(JSON.parse(attrs.picMetadata));
          NyplApiCalls.getDetail(JSON.parse(attrs.picMetadata)).then(function (result) {
            scope.metadata = result.nyplAPI.response.mods;
            try {
              scope.title = scope.metadata.nyplAPI.response.mods.titleInfo.title.$;
            }
            catch (err) {
              scope.title = '';
            }
            try {
              if (scope.metadata.originInfo.hasOwnProperty('subject')){
                if (scope.metadata.originInfo.subject.hasOwnProperty('name')){
                  scope.names = scope.metadata.nyplAPI.response.mods.subject[0].name.namePart.$;
                }
              }

            }
            catch (err) {
              scope.names = '';
            }
            try {
              scope.collection = scope.metadata.nyplAPI.response.mods.location[0].physicalLocation[2].$;
            }
            catch (err) {
              scope.collection = '';
            }
            try {
              scope.values = '';
              if (scope.metadata.originInfo.hasOwnProperty('dateIssued')){
                scope.originInfoStr = 'Date issued: ' + scope.metadata.originInfo.dateIssued.$;
              }
              if (scope.metadata.originInfo.hasOwnProperty('dateCreated')){
                if (! Array.isArray(scope.metadata.originInfo.dateCreated) ){
                  scope.originInfoStr = 'Created date: ' + scope.metadata.originInfo.dateCreated.$;
                } else {
                  scope.originInfoStr = 'Created date: ';
                  angular.forEach(scope.metadata.originInfo.dateCreated, function (date) {
                    if (date.hasOwnProperty('qualifier')){
                      scope.originInfoStr = scope.originInfoStr + date.qualifier + ' ';
                    }
                    if (date.hasOwnProperty('point')){
                      scope.originInfoStr = scope.originInfoStr + date.point + ' ';
                    }
                    if (date.hasOwnProperty('$')){
                      scope.originInfoStr = scope.originInfoStr + date.$ + ' ';
                    }

                  })

                }

              }

            }
            catch (err) {
              console.log(err);
              scope.originInfoStr = '';
            }
            /*
            try {
              scope.endDate = scope.metadata.nyplAPI.response.mods.originInfo.dateCreated[1].$;
            }
            catch (err) {
              scope.endDate = '';
            }
            */
            try {
              scope.values = '';
              scope.notes = scope.recursJsonPrint(scope.metadata.nyplAPI.response.mods.note);
              //var notes = '';
              //angular.forEach(scope.metadata.nyplAPI.response.mods.note, function (note) {
                //notes = notes + '  ' + note.$;
              //})
             // scope.notes = notes;
            }
            catch (err) {
              scope.notes = '';
            }
            try {
              scope.values = '';
              scope.topics = scope.recursJsonPrint(scope.metadata.nyplAPI.response.mods.subject);
              //var topics = '';
              //angular.forEach(scope.metadata.nyplAPI.response.mods.subject, function (subject) {
              //  topics = topics + ',' + subject.topic.$;
              //})
              //scope.topics = topics;
            }
            catch (err) {
              scope.topics = '';
            }
            try {
              scope.values = '';
              scope.genres = scope.recursJsonPrint(scope.metadata.nyplAPI.response.mods.genre);
              //var genres = '';
              //angular.forEach(scope.metadata.nyplAPI.response.mods.genre, function (genre) {
               // genres = genres + ',' + genre.$;
              //})
              //scope.genres = genres;
            }
            catch (err) {
              scope.genres = '';
            }

            scope.physicalDescription = '';

          });

          scope.showMeta = !scope.showMeta;
        }

        scope.showListBottomSheet = function (ev) {
          console.log('firing bottom sheet');
          $mdDialog.show({
            controller: 'ListBottomSheetCtrl',
            templateUrl: 'src/grid-list/bottom-sheet-list-template.html',
            parent: angular.element(document.body),
            targetEvent: ev,
            clickOutsideToClose: true,
            fullscreen: true
          })
            .then(function (answer) {
              scope.status = 'You said the information was "' + answer + '".';
            }, function () {
              scope.status = 'You cancelled the dialog.';
            });
          /*
          scope.alert = '';
          $mdBottomSheet.show({
            templateUrl: 'src/grid-list/bottom-sheet-list-template.html',
            controller: 'ListBottomSheetCtrl'
          }).then(function (clickedItem) {
            scope.alert = clickedItem['name'] + ' clicked!';
          }).catch(function (error) {
            // User clicked outside or hit escape
          });
          */
        };

        scope.logThis = function () {
          console.log('king jubba');
        }
        var showViewer = function () {
          var options = {
            //minHeight: 500,
            //minWidth: element.offsetWidth,
            url: scope.original,
            inline: false,
            build: function (e) {
              // console.log(e.type);

              // ctrl.isViewerBuilt = false;
            },
            built: function (e) {
              //var myEl = angular.element(elem[0].querySelector('.viewer-container'));
              var myEl = document.getElementsByClassName("viewer-container");
              var wrappedResult = angular.element(myEl);
              /*
        $(".viewer-container").each(function () {
          console.log('running this');
          var content = $(this);
          angular.element(document).injector().invoke(function ($compile) {
            var viewerscope = angular.element(content).scope();
            $compile(content)(viewerscope);
          });
        });*/
              console.log(wrappedResult);
              $compile(wrappedResult)(scope);

              // ctrl.isViewerBuilt = true;
              scope.$apply();
            },
          };

          $(elem).viewer(options);

        }
        var viewer;

        // $compile(elem.viewer)(scope);
        //elem.viewer("shown", function () {
        //  console.log(this.viewer === viewer);
        //console.log('done building');
        //  $compile(this.viewer)(scope);
        //});
        elem.bind('click', function () {
          console.log('jubba');
          showViewer();
        });

      }
    };
  })
  .controller('MyCtrl', function ($scope) {
    $scope.anyFunc = function (var1, var2) {
      alert("I am var1 = " + var1);
      alert("I am var2 = " + var2);
    }
  })
  .config(
  [
    '$mdIconProvider',
    '$mdThemingProvider',
    function ($mdIconProvider, $mdThemingProvider) {
      // Register the user `avatar` icons
      $mdIconProvider
        .defaultIconSet("./assets/svg/avatars.svg", 128)
        .icon("search", "./assets/svg/search.svg", 24)
        .icon("settings", "./assets/svg/settings.svg", 24)
        .icon("binoculars", "./assets/svg/binoculars.svg", 48)
        .icon("menu", "./assets/svg/menu.svg", 24)
        .icon("share", "./assets/svg/share.svg", 24)
        .icon("google_plus", "./assets/svg/google_plus.svg", 24)
        .icon("hangouts", "./assets/svg/hangouts.svg", 24)
        .icon("twitter", "./assets/svg/twitter.svg", 24)
        .icon("pen", "./assets/svg/fountain-pen.svg", 24)
        .icon("open-book", "./assets/svg/open-book.svg", 24)
        .icon("google", "./assets/svg/google.svg", 24)
        .icon("account", "./assets/svg/account.svg", 24)
        .icon("sign-out", "./assets/svg/sign-out.svg", 24)
        .icon("add", "./assets/svg/add.svg", 24)
        .icon("edit", "./assets/svg/edit.svg", 24)
        .icon("delete", "./assets/svg/delete.svg", 24)
        .icon("bookmark", "./assets/svg/bookmark.svg", 24)
        .icon("phone", "./assets/svg/phone.svg", 24);

      $mdThemingProvider.theme('default')
        .primaryPalette('grey', {
          'default': '400', // by default use shade 400 from the pink palette for primary intentions
          'hue-1': '200', // use shade 100 for the md-hue-1 class
          'hue-2': '600', // use shade 600 for the md-hue-2 class
          'hue-3': '50' // use shade A100 for the md-hue-3 class
        })
        .accentPalette('amber');

      $mdThemingProvider.theme('dark-yellow').primaryPalette('yellow', {
        'default': '700'
      });

      $mdThemingProvider.theme('light-grey').primaryPalette('grey', {
        'default': 'A100'
      });

      $mdThemingProvider.theme('input', 'default')
        .primaryPalette('grey')

    }
  ]
  );
<|endoftext|>


<commit_before>/*
 *  MainScene.js
 *  2015/09/08
 *  @auther minimo
 *  This Program is MIT license.
 */

phina.define("pbr.MainScene", {
    superClass: "phina.display.CanvasScene",

    _member: {
        score: 0,

        //再生中BGM
        bgm: null,

        //自機コントロール可能フラグ
        control: true,

        //ラベル用パラメータ
        labelParam: {
            fill: "white",
            stroke: "blue",
            strokeWidth: 2,

            fontFamily: "Orbitron",
            align: "center",
            baseline: "middle",
            fontSize: 32,
            fontWeight: ''
        },
        scorelabelParam: {
            fill: "white",
            stroke: "black",
            strokeWidth: 1,

            fontFamily: "UbuntuMono",
            align: "left",
            baseline: "middle",
            fontSize: 20,
            fontWeight: ''
        },
    },

    init: function() {
        this.superInit();
        this.$extend(this._member);

        //バックグラウンド
        var param = {
            width:SC_W,
            height:SC_H,
            fill: 'black',
            stroke: false,
            backgroundColor: 'transparent',
        };
        this.bg = phina.display.RectangleShape(param)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)

        //レイヤー準備
        this.base = phina.display.Layer().addChildTo(this).setPosition(SC_OFFSET_X, 0);
        this.layers = [];
        for (var i = 0; i < LAYER_SYSTEM+1; i++) {
            this.layers[i] = phina.display.Layer().addChildTo(this.base);
        }

        //プレイヤー準備
        this.player = pbr.Player()
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5);

//        this.pointer = pbr.PlayerPointer().addChildTo(this);
//        this.pointer.player = this.player;

        //スコア表示
        var that = this;
        this.scoreLabel = phina.display.Label({text:"SCORE:"}.$safe(this.scorelabelParam))
            .addChildTo(this)
            .setPosition(8, 32);
        this.scoreLabel.update = function() {
            this.text = "SCORE "+that.score;
        }

        //目隠し
        this.mask = phina.display.RectangleShape(param)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5);
        this.mask.alpha = 0;
    },

    update: function(app) {
    },

    //ステージ初期化
    initStage: function() {
    },

    //ステージ再スタート
    restartStage: function() {
    },

    //タッチorクリック開始処理
    onpointstart: function(e) {
    },

    //タッチorクリック移動処理
    onpointmove: function(e) {
    },

    //タッチorクリック終了処理
    onpointend: function(e) {
    },

    //addChildオーバーライド
    addChild: function(child) {
        if (child.layer === undefined) {
            return this.superClass.prototype.addChild.apply(this, arguments);
        }
        child.parentScene = this;
        return this.layers[child.layer].addChild(child);
    },
});
<commit_msg>add stage initialize<commit_after>/*
 *  MainScene.js
 *  2015/09/08
 *  @auther minimo
 *  This Program is MIT license.
 */

phina.define("pbr.MainScene", {
    superClass: "phina.display.CanvasScene",

    _member: {
        score: 0,

        //現在ステージ番号
        nowStage: 1,

        //再生中BGM
        bgm: null,

        //自機コントロール可能フラグ
        control: true,

        //ラベル用パラメータ
        labelParam: {
            fill: "white",
            stroke: "blue",
            strokeWidth: 2,

            fontFamily: "Orbitron",
            align: "center",
            baseline: "middle",
            fontSize: 32,
            fontWeight: ''
        },
        scorelabelParam: {
            fill: "white",
            stroke: "black",
            strokeWidth: 1,

            fontFamily: "UbuntuMono",
            align: "left",
            baseline: "middle",
            fontSize: 20,
            fontWeight: ''
        },
    },

    init: function(stageNumber) {
        stageNumber = stageNumber || 1;

        this.superInit();
        this.$extend(this._member);

        //バックグラウンド
        var param = {
            width:SC_W,
            height:SC_H,
            fill: 'black',
            stroke: false,
            backgroundColor: 'transparent',
        };
        this.bg = phina.display.RectangleShape(param)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)

        //レイヤー準備
        this.base = phina.display.Layer().addChildTo(this).setPosition(SC_OFFSET_X, 0);
        this.layers = [];
        for (var i = 0; i < LAYER_SYSTEM+1; i++) {
            this.layers[i] = phina.display.Layer().addChildTo(this.base);
        }

        //プレイヤー準備
        this.player = pbr.Player()
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5);

//        this.pointer = pbr.PlayerPointer().addChildTo(this);
//        this.pointer.player = this.player;

        //スコア表示
        var that = this;
        this.scoreLabel = phina.display.Label({text:"SCORE:"}.$safe(this.scorelabelParam))
            .addChildTo(this)
            .setPosition(8, 32);
        this.scoreLabel.update = function() {
            this.text = "SCORE "+that.score;
        }

        //ステージ初期化
        this.nowStage = stageNumber;
        this.initStage();

        //目隠し
        this.mask = phina.display.RectangleShape(param)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5);
        this.mask.alpha = 0;
    },

    update: function(app) {
    },

    //ステージ初期化
    initStage: function() {
        if (this.ground) this.ground.remove();
        switch (this.nowStage) {
            case 1:
                this.stage = pbr.Stage1(this, app.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
            case 2:
                this.stage = pbr.Stage1(this, app.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
            case 3:
                this.stage = pbr.Stage1(this, app.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
        }
        this.time = 0;
        this.timeVanish = 0;
        this.enemyCount = 0;
        this.enemyKill = 0;
        this.stageMiss = 0;

        //ステージ番号表示
        param = {text: "STAGE "+this.nowStage, fontFamily: "Orbitron", align: "center", baseline: "middle", fontWeight: 800, outlineWidth: 2};
        var m1 = phina.display.Label(param, 50)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)
        m1.alpha = 0;
        m1.tweener.wait(500).fadeIn(250).wait(1000).fadeOut(250).call(function(){this.remove()}.bind(m1));
    },

    //ステージ再スタート
    restartStage: function() {
    },

    //タッチorクリック開始処理
    onpointstart: function(e) {
    },

    //タッチorクリック移動処理
    onpointmove: function(e) {
    },

    //タッチorクリック終了処理
    onpointend: function(e) {
    },

    //addChildオーバーライド
    addChild: function(child) {
        if (child.layer === undefined) {
            return this.superClass.prototype.addChild.apply(this, arguments);
        }
        child.parentScene = this;
        return this.layers[child.layer].addChild(child);
    },
});
<|endoftext|>


<commit_before>'use strict';

function cleanCal (cal) {
  var clean = {
    scale: parseFloat(cal.scale) || 0
    , intercept: parseFloat(cal.intercept) || 0
    , slope: parseFloat(cal.slope) || 0
  };

  clean.valid = ! (clean.slope === 0 || clean.unfiltered === 0 || clean.scale === 0);

  return clean;
}

module.exports = function withRawGlucose (entry, cals, maxRaw) {
  var maxRaw = maxRaw || 200;

  var egv = entry.glucose || entry.sgv || 0;

  entry.unfiltered = parseInt(entry.unfiltered) || 0;
  entry.filtered = parseInt(entry.filtered) || 0;

  //TODO: add time check, but how recent should it be?
  //TODO: currently assuming the first is the best (and that there is probably just 1 cal)
  var cal = cals && cals.length > 0 && cleanCal(cals[0]);

  if (cal && cal.valid) {
    if (cal.filtered === 0 || egv < 40) {
      entry.raw = Math.round(cal.scale * (entry.unfiltered - cal.intercept) / cal.slope);
    } else {
      var ratio = cal.scale * (entry.filtered - cal.intercept) / cal.slope / egv;
      entry.raw = Math.round(cal.scale * (entry.unfiltered - cal.intercept) / cal.slope / ratio);
    }

    if ( egv < 40 ) {
        if (entry.raw) {
            entry.glucose = entry.raw;
            entry.fromRaw = true;
            if (entry.raw <= maxRaw) {
                entry.noise = 2;
            } else {
                entry.noise = 3;
            }
        } else {
            entry.noise = 3;
        }
    } else if (! entry.noise) {
        entry.noise = 0;
    }

  }
  return entry;
};
<commit_msg>#1010: filter out mbg and cal records<commit_after>'use strict';

function cleanCal (cal) {
  var clean = {
    scale: parseFloat(cal.scale) || 0
    , intercept: parseFloat(cal.intercept) || 0
    , slope: parseFloat(cal.slope) || 0
  };

  clean.valid = ! (clean.slope === 0 || clean.unfiltered === 0 || clean.scale === 0);

  return clean;
}

module.exports = function withRawGlucose (entry, cals, maxRaw) {
  var maxRaw = maxRaw || 200;

  if ( entry.type == "mbg" || entry.type == "cal" ) {
    return entry;
  }
  var egv = entry.glucose || entry.sgv || 0;

  entry.unfiltered = parseInt(entry.unfiltered) || 0;
  entry.filtered = parseInt(entry.filtered) || 0;

  //TODO: add time check, but how recent should it be?
  //TODO: currently assuming the first is the best (and that there is probably just 1 cal)
  var cal = cals && cals.length > 0 && cleanCal(cals[0]);

  if (cal && cal.valid) {
    if (cal.filtered === 0 || egv < 40) {
      entry.raw = Math.round(cal.scale * (entry.unfiltered - cal.intercept) / cal.slope);
    } else {
      var ratio = cal.scale * (entry.filtered - cal.intercept) / cal.slope / egv;
      entry.raw = Math.round(cal.scale * (entry.unfiltered - cal.intercept) / cal.slope / ratio);
    }

    if ( egv < 40 ) {
        if (entry.raw) {
            entry.glucose = entry.raw;
            entry.fromRaw = true;
            if (entry.raw <= maxRaw) {
                entry.noise = 2;
            } else {
                entry.noise = 3;
            }
        } else {
            entry.noise = 3;
        }
    } else if (! entry.noise) {
        entry.noise = 0;
    }

  }
  return entry;
};
<|endoftext|>


<commit_before>require.config({
    baseUrl: 'app/',
    paths: {
        'react':          'vendors/react/react-with-addons',
        'text':           'vendors/requirejs-text/text',
        'JSXTransformer': 'vendors/jsx-requirejs-plugin/js/JSXTransformer',
        'jsx':            'vendors/jsx-requirejs-plugin/js/jsx'
    },
    jsx: {
        fileExtension: '.jsx'
    }
});

require([
    'react',
    'jsx!src/components/Application',
    'src/services/SettingsRepository'
    ], function(React, Application, SettingsRepository) {

    Application = React.createFactory(Application);
    React.render(Application({
            settings: SettingsRepository
        }
    ), createTargetElement(SettingsRepository));

    loadStyles(SettingsRepository);
});

/**
 * @param SettingsRepository
 */
function loadStyles(SettingsRepository) {
    var css = document.createElement('link');
    css.rel = 'stylesheet';
    css.href = 'https://rawgit.com/soebbing/zeus-calc/react/app/css/app.css';

    var frame = SettingsRepository.getDocument();
    frame.getElementsByTagName('head')[0].appendChild(css);
}

/**
 *
 * @param SettingsRepository
 * @returns {HTMLElement}
 */
function createTargetElement(SettingsRepository) {
    var target = SettingsRepository.getTargetElement();
    var frame = SettingsRepository.getDocument();
    frame.getElementsByTagName('body')[0].appendChild(target);
    return target;
}<commit_msg>Behebt Pfad zum CSBehebt Pfad zum CSSS<commit_after>require.config({
    baseUrl: 'app/',
    paths: {
        'react':          'vendors/react/react-with-addons',
        'text':           'vendors/requirejs-text/text',
        'JSXTransformer': 'vendors/jsx-requirejs-plugin/js/JSXTransformer',
        'jsx':            'vendors/jsx-requirejs-plugin/js/jsx'
    },
    jsx: {
        fileExtension: '.jsx'
    }
});

require([
    'react',
    'jsx!src/components/Application',
    'src/services/SettingsRepository'
    ], function(React, Application, SettingsRepository) {

    Application = React.createFactory(Application);
    React.render(Application({
            settings: SettingsRepository
        }
    ), createTargetElement(SettingsRepository));

    loadStyles(SettingsRepository);
});

/**
 * @param SettingsRepository
 */
function loadStyles(SettingsRepository) {
    var css = document.createElement('link');
    css.rel = 'stylesheet';
    css.href = 'https://rawgit.com/soebbing/zeus-calc/master/app/css/app.css';

    var frame = SettingsRepository.getDocument();
    frame.getElementsByTagName('head')[0].appendChild(css);
}

/**
 *
 * @param SettingsRepository
 * @returns {HTMLElement}
 */
function createTargetElement(SettingsRepository) {
    var target = SettingsRepository.getTargetElement();
    var frame = SettingsRepository.getDocument();
    frame.getElementsByTagName('body')[0].appendChild(target);
    return target;
}<|endoftext|>


<commit_before>import React, { Component, PropTypes, cloneElement } from 'react'
import DocumentTitle from 'react-document-title'
import { connect } from 'react-redux'
import omit from 'lodash/object/omit'

import Sidebar from './sidebar'
import Loading from '../components/loading'
import getStudentCourses from '../helpers/get-student-courses'
import ShareSheet from './share-sheet'

import './student.scss'

export class Student extends Component {
	static propTypes = {
		actions: PropTypes.object,
		areas: PropTypes.array,
		canRedo: PropTypes.bool,
		canUndo: PropTypes.bool,
		children: PropTypes.node.isRequired,  // from react-router
		params: PropTypes.object,
		student: PropTypes.object,
	}

	static contextTypes = {
		location: PropTypes.object,
	}

	constructor() {
		super()
		this.state = {
			courses: [],
		}
	}

	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	}

	componentWillReceiveProps(nextProps) {
		if (nextProps.student) {
			window.stu = nextProps.student

			getStudentCourses(nextProps.student).then(courses => {
				this.setState({
					courses: courses,
				})
				return null
			})
		}
	}

	componentWillUnmount() {
		delete window.stu
	}

	render() {
		// console.info('Student.render')

		if (!this.props.student) {
			return <Loading>{`Loading Student ${this.props.params.id}`}</Loading>
		}

		const childProps = omit(this.props, 'children')

		return (
			<DocumentTitle title={`${this.props.student.name} | Gobbldygook`}>

					<Sidebar {...childProps} courses={this.state.courses} areas={this.props.areas} />
					{cloneElement(this.props.children, {...childProps, courses: this.state.courses, className: 'content'})}
					{'share' in this.context.location.query && <ShareSheet student={this.props.student} />}

			</DocumentTitle>
		)
	}
}

function mapStateToProps(state, ownProps) {
	// selects some state that is relevant to this component, and returns it.
	// redux-react will bind it to props.
	return {
		student: state.students.present[ownProps.params.id],
	}
}

export default connect(mapStateToProps)(Student)
<commit_msg>remove window.stu<commit_after>import React, { Component, PropTypes, cloneElement } from 'react'
import DocumentTitle from 'react-document-title'
import { connect } from 'react-redux'
import omit from 'lodash/object/omit'

import Sidebar from './sidebar'
import Loading from '../components/loading'
import getStudentCourses from '../helpers/get-student-courses'
import ShareSheet from './share-sheet'

import './student.scss'

export class Student extends Component {
	static propTypes = {
		actions: PropTypes.object,
		areas: PropTypes.array,
		canRedo: PropTypes.bool,
		canUndo: PropTypes.bool,
		children: PropTypes.node.isRequired,  // from react-router
		params: PropTypes.object,
		student: PropTypes.object,
	}

	static contextTypes = {
		location: PropTypes.object,
	}

	constructor() {
		super()
		this.state = {
			courses: [],
		}
	}

	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	}

	componentWillReceiveProps(nextProps) {
		if (nextProps.student) {
			getStudentCourses(nextProps.student).then(courses => {
				this.setState({
					courses: courses,
				})
				return null
			})
		}
	}

	render() {
		if (!this.props.student) {
			return <Loading>{`Loading Student ${this.props.params.id}`}</Loading>
		}

		const childProps = omit(this.props, 'children')

		return (
			<DocumentTitle title={`${this.props.student.name} | Gobbldygook`}>

					<Sidebar {...childProps} courses={this.state.courses} areas={this.props.areas} />
					{cloneElement(this.props.children, {...childProps, courses: this.state.courses, className: 'content'})}
					{'share' in this.context.location.query && <ShareSheet student={this.props.student} />}

			</DocumentTitle>
		)
	}
}

function mapStateToProps(state, ownProps) {
	// selects some state that is relevant to this component, and returns it.
	// redux-react will bind it to props.
	return {
		student: state.students.present[ownProps.params.id],
	}
}

export default connect(mapStateToProps)(Student)
<|endoftext|>


<commit_before>// Single var pattern of gulp (require) stuff in full effect!!!

var gulp = require("gulp"), // "require" gulp
    uncss = require("gulp-uncss"), // Remove unused css selectors
    minifyCSS = require("gulp-minify-css"), // Minify CSS
    concatCss = require("gulp-concat-css"), // Concatenate CSS only
    csslint = require("gulp-csslint"), // Lint CSS
    watch = require("gulp-watch"), // Watch files changes
    imagemin = require('gulp-imagemin'), // Minifying images
    autoprefixer = require('gulp-autoprefixer'),
    exec = require('child_process').exec, // Run CLI commands via node
    Q = require('q'); // Manage promises,;

// End single var pattern

// Needed to run grunt tasks through gulp
require("gulp-grunt")(gulp);

/*
 *  ===================================================================
 *  | STORE PREPROCESSOR FILE REFERENCES IN VARIABLES |
 *  ===================================================================
 */
var lessFiles = ["css-build/*.less", "css-build/**/*.less"], // LESS
    coffeeFiles = ["coffee/*.coffee"]; // Coffeescript

    /*
     * IGNORE ARRAY
     * ============
     * Selectors NOT to be removed when "gulp uncss" task runs.
     * Try to list them alphabetically and in the following order:
     *
     * 1. Page elements first (<nav>, <aside>, etc.)
     * 2. IDs second
     * 3. Classes third
     */
     ignoreArray = [];

/*
 *  ===================================================================
 *  | CSS BUILD TASK |
 *
 * Running "gulp buildcss" performs the following sequence of tasks...
 *
 * 1. Runs the "gulp less" task that"s passed as a "hint"(*)
 * 2. Concatenate selected .css files listed in "gulp.src"
 * 3. Remove unused CSS
 * 4. Minify CSS
 * 5. Lint CSS
 *
 * (*) gulp "hints" are cool...read more about them at:
 * https://github.com/gulpjs/gulp/blob/master/docs/API.md
 *  ===================================================================
 */

gulp.task('buildcss', ['less', 'concat', 'outputcss']);

// "gulp less" task
// ================
// Process .less files using node exec
// Returns a promise with q
gulp.task("less", function () {
  var deferred = Q.defer();
  setTimeout(function() {
    exec("lessc css-build/style.less > css-build/style.css");
    return deferred.promise;
  }, 1000);
});

// "gulp concat" task
// ==================
// Concatenate "css-build/styles.css" and "css-build/bootstrap.css"
// Takes "less" as a gulp hint
// Returns a promise with q
gulp.task('concat', ['less'], function() {
  var deferred = Q.defer();
  setTimeout(function() {
    return gulp.src(['css-build/wp-comment-block.css', 'css-build/font-awesome.css', 'css-build/bootstrap.css','css-build/style.css'])
    .pipe(concatCss('style.css'))
    .pipe(gulp.dest("wp-content/themes/kaidez-swiss/"));
    return deferred.promise;
  }, 1000);
});

gulp.task("outputcss", ['concat'],function () {
  var deferred = Q.defer();
  setTimeout(function() {
    gulp.src(['wp-content/themes/kaidez-swiss/style.css'])
    .pipe(autoprefixer({
      browsers: ['last 2 versions'],
      cascade: false
    }))
    .pipe(minifyCSS({
      keepBreaks: true
    }))
    .pipe(gulp.dest("wp-content/themes/kaidez-swiss/"))
    .pipe(csslint({
      "important": false,
      "duplicate-background-images": false,
      "ids": false,
      "text-indent": false
    }))
    return deferred.promise;
    }, 4000);
  });

/*
*  ===================================================================
*  | IMAGE MINIFICATION TASK |
*
*  Take all images in "imagemin/" & minify them out to "build/img/"
*  ===================================================================
*/
gulp.task('images', function () {
  return gulp.src('image-min/*')
  .pipe(imagemin({
    progressive: true,
    svgoPlugins: [{removeViewBox: false}]
  }))
  .pipe(gulp.dest('build/img'));
});

/*
 *  ===================================================================
 *  | "gulp-grunt" TASKS...RUN GRUNT TASKS VIA GULP!!!! |
 *  ===================================================================
 */

// Run the "grunt coffee" task
gulp.task("coffee", function () {
  gulp.run("grunt-coffee");
});

// BOWERCOPY TASKS
// Copy over ALL the Bower Components!!!
gulp.task("bowercopy", function () {
  gulp.run("grunt-bowercopy");
});

// Copy over Bootstrap core .css only
gulp.task("bowerbscss", function () {
  gulp.run("grunt-bowercopy:bscss");
});

// Copy over jQuery v.1.11.x only
gulp.task("bowerjq", function () {
  gulp.run("grunt-bowercopy:jq");
});

// Copy over Font Awesome's minified CSS file
gulp.task("bowerfa", function () {
  gulp.run("grunt-bowercopy:bsfa");
});

// Copy over Font Awesome's minified CSS file
gulp.task("bsfafont", function () {
  gulp.run("grunt-bowercopy:bsfafont");
});

/*
 *  ===================================================================
 *  | START WATCH TASK |
 *
 *  Be careful of watching a lot of files because that may eat up
 *  computer memory...at least, it does in Grunt.
 *  ===================================================================
 */

gulp.task("watch", function () {

  // Watch for CSS/JS file changes

  gulp.watch(lessFiles, ["buildcss"]);
  gulp.watch(coffeeFiles, ["coffee"]);
});

//Uncss task
gulp.task('test', function() {
  gulp.src('wp-content/themes/kaidez-swiss/style.css')
    .pipe(uncss({
      html: [
        'http://localhost:8888/', // home page
        'http://localhost:8888/404.php' // 404 page
      ]
    }))
    .pipe(gulp.dest('lib/bootstrap/css/'));
});
<commit_msg>fix comment in gulpfile.js<commit_after>// Single var pattern of gulp (require) stuff in full effect!!!

var gulp = require("gulp"), // "require" gulp
    uncss = require("gulp-uncss"), // Remove unused css selectors
    minifyCSS = require("gulp-minify-css"), // Minify CSS
    concatCss = require("gulp-concat-css"), // Concatenate CSS only
    csslint = require("gulp-csslint"), // Lint CSS
    watch = require("gulp-watch"), // Watch files changes
    imagemin = require('gulp-imagemin'), // Minifying images
    autoprefixer = require('gulp-autoprefixer'),
    exec = require('child_process').exec, // Run CLI commands via node
    Q = require('q'); // Manage promises,;

// End single var pattern

// Needed to run grunt tasks through gulp
require("gulp-grunt")(gulp);

/*
 *  ===================================================================
 *  | STORE PREPROCESSOR FILE REFERENCES IN VARIABLES |
 *  ===================================================================
 */
var lessFiles = ["css-build/*.less", "css-build/**/*.less"], // LESS
    coffeeFiles = ["coffee/*.coffee"]; // Coffeescript

    /*
     * IGNORE ARRAY
     * ============
     * Selectors NOT to be removed when "gulp uncss" task runs.
     * Try to list them alphabetically and in the following order:
     *
     * 1. Page elements first (<nav>, <aside>, etc.)
     * 2. IDs second
     * 3. Classes third
     */
     ignoreArray = [];

/*
 *  ===================================================================
 *  | CSS BUILD TASK |
 *
 * Running "gulp buildcss" performs the following sequence of tasks...
 *
 * 1. Runs the "gulp less" task that"s passed as a "hint"(*)
 * 2. Concatenate selected .css files listed in "gulp.src"
 * 3. Remove unused CSS
 * 4. Minify CSS
 * 5. Lint CSS
 *
 * (*) gulp "hints" are cool...read more about them at:
 * https://github.com/gulpjs/gulp/blob/master/docs/API.md
 *  ===================================================================
 */

gulp.task('buildcss', ['less', 'concat', 'outputcss']);

// "gulp less" task
// ================
// Process .less files using node exec
// Returns a promise with q
gulp.task("less", function () {
  var deferred = Q.defer();
  setTimeout(function() {
    exec("lessc css-build/style.less > css-build/style.css");
    return deferred.promise;
  }, 1000);
});

// "gulp concat" task
// ==================
// Concatenate "css-build/styles.css" and "css-build/bootstrap.css"
// Takes "less" as a gulp hint
// Returns a promise with q
gulp.task('concat', ['less'], function() {
  var deferred = Q.defer();
  setTimeout(function() {
    return gulp.src(['css-build/wp-comment-block.css', 'css-build/font-awesome.css', 'css-build/bootstrap.css','css-build/style.css'])
    .pipe(concatCss('style.css'))
    .pipe(gulp.dest("wp-content/themes/kaidez-swiss/"));
    return deferred.promise;
  }, 1000);
});

gulp.task("outputcss", ['concat'],function () {
  var deferred = Q.defer();
  setTimeout(function() {
    gulp.src(['wp-content/themes/kaidez-swiss/style.css'])
    .pipe(autoprefixer({
      browsers: ['last 2 versions'],
      cascade: false
    }))
    .pipe(minifyCSS({
      keepBreaks: true
    }))
    .pipe(gulp.dest("wp-content/themes/kaidez-swiss/"))
    .pipe(csslint({
      "important": false,
      "duplicate-background-images": false,
      "ids": false,
      "text-indent": false
    }))
    return deferred.promise;
    }, 4000);
  });

/*
*  ===================================================================
*  | IMAGE MINIFICATION TASK |
*
*  Take all images in "imagemin/" & minify them out to "build/img/"
*  ===================================================================
*/
gulp.task('images', function () {
  return gulp.src('image-min/*')
  .pipe(imagemin({
    progressive: true,
    svgoPlugins: [{removeViewBox: false}]
  }))
  .pipe(gulp.dest('build/img'));
});

/*
 *  ===================================================================
 *  | "gulp-grunt" TASKS...RUN GRUNT TASKS VIA GULP!!!! |
 *  ===================================================================
 */

// Run the "grunt coffee" task
gulp.task("coffee", function () {
  gulp.run("grunt-coffee");
});

// BOWERCOPY TASKS
// Copy over ALL the Bower Components!!!
gulp.task("bowercopy", function () {
  gulp.run("grunt-bowercopy");
});

// Copy over Bootstrap core .css only
gulp.task("bowerbscss", function () {
  gulp.run("grunt-bowercopy:bscss");
});

// Copy over jQuery v.1.11.x only
gulp.task("bowerjq", function () {
  gulp.run("grunt-bowercopy:jq");
});

// Copy over Font Awesome's minified CSS file
gulp.task("bowerfa", function () {
  gulp.run("grunt-bowercopy:bsfa");
});

// Copy over Font Awesome's minified CSS file
gulp.task("bsfafont", function () {
  gulp.run("grunt-bowercopy:bsfafont");
});

/*
 *  ===================================================================
 *  | START WATCH TASK |
 *
 *  Be careful of watching a lot of files because that may eat up
 *  computer memory...at least, it does in Grunt.
 *  ===================================================================
 */

gulp.task("watch", function () {

  // Watch for CSS/JS file changes

  gulp.watch(lessFiles, ["buildcss"]);
  gulp.watch(coffeeFiles, ["coffee"]);
});

// uncss task
gulp.task('test', function() {
  gulp.src('wp-content/themes/kaidez-swiss/style.css')
    .pipe(uncss({
      html: [
        'http://localhost:8888/', // home page
        'http://localhost:8888/404.php' // 404 page
      ]
    }))
    .pipe(gulp.dest('lib/bootstrap/css/'));
});
<|endoftext|>