<commit_before>/**
 *  Copyright (C) 2009 Orbeon, Inc.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the
 *  GNU Lesser General Public License as published by the Free Software Foundation; either version
 *  2.1 of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU Lesser General Public License for more details.
 *
 *  The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
 */
(function() {
    var Dom = YAHOO.util.Dom;
    var Event = YAHOO.util.Event;
    var Lang = YAHOO.lang;
    var Document = ORBEON.xforms.Document;

    /**
     * Singleton with mapping control ID to control object
     */
    var controls = {};

    /**
     * AutoComplete object constructor
     */
    ORBEON.widget.AutoComplete = function(element) { this.init(element); }
    ORBEON.widget.AutoComplete.prototype = {

        /**
         * Attributes
         */
        element: null,              // Div containing this control
        dynamicItemset: null,       // Do we need to wait for the itemset to change before we update the auto-complete?
        yuiAutoComplete: null,      // YUI object for the auto-complete

        /**
         * Constructor
         */
        init: function(element) {
            var autoComplete = this;

            autoComplete.element = element;

            var inputSpan = Dom.getElementsByClassName("fr-autocomplete-input", null, element)[0];
            var inputField = Dom.getChildren(inputSpan)[0];
            var yuiDiv = Dom.getElementsByClassName("fr-autocomplete-yui-div", null, element)[0];
            YAHOO.util.Dom.generateId(yuiDiv); // Generate ID dynamically as our implementation of XBL doesn't rewrite IDs on HTML

            // Build data source
            var dataSource;
            if (autoComplete.isDynamicItemset()) {
                // If the itemset changes dynamically, update list when we have response to an Ajax request
                dataSource = autoComplete.buildNullDataSource();
                ORBEON.xforms.Events.ajaxResponseProcessedEvent.subscribe(function() {
                    // If this YUI auto-complete is focused (otherwise don't bother updating the list)
                    if (autoComplete.yuiAutoComplete.isFocused()) {
                        // Get new list of values
                        var query = inputField.value;
                        var newList = autoComplete.getCurrentValues(query);

                        // Call YUI code to update list
                        if (newList.length != 1 || newList[0] != query) {
                            autoComplete.yuiAutoComplete._populateList(query, { results: newList }, { query: query });
                        }
                    }
                });
            } else {
                // Simply get
                dataSource = new YAHOO.util.FunctionDataSource(function(query) {
                    return autoComplete.getCurrentValues(query);
                });
            }

            // Create YUI auto-complete object
            autoComplete.yuiAutoComplete = new YAHOO.widget.AutoComplete(inputField.id, yuiDiv.id, dataSource);
            autoComplete.yuiAutoComplete.animVert = false;
        },

        /**
         * Creates a data source that never returns anything
         */
        buildNullDataSource: function() {
            var autoComplete = this;

            var WaitAjaxResponseDataSource = function(oLiveData, oConfigs) {
                this.dataType = YAHOO.util.DataSourceBase.TYPE_JSFUNCTION;
                oLiveData = oLiveData || function() {};
                this.constructor.superclass.constructor.call(this, oLiveData, oConfigs);
            };

            Lang.extend(WaitAjaxResponseDataSource, YAHOO.util.DataSourceBase, {
                makeConnection : function(oRequest, oCallback, oCaller) {
                    var dataSource = this;
                    var tId = YAHOO.util.DataSourceBase._nTransactionId++;
                    dataSource.fireEvent("requestEvent", {tId:tId,request:oRequest,callback:oCallback,caller:oCaller});
                    dataSource.responseType = YAHOO.util.DataSourceBase.TYPE_JSARRAY;
                    return tId;
                }
            });

            return new WaitAjaxResponseDataSource(function(query) { return autoComplete.getCurrentValues(query); });
        },

        /**
         * Returns the list of values currently in the itemset
         */
        isDynamicItemset: function() {
            var autoComplete = this;
            if (autoComplete.dynamicItemset === null) {
                var output = Dom.getElementsByClassName("fr-autocomplete-dynamic-itemset", null, autoComplete.element)[0];
                autoComplete.dynamicItemset = Document.getValue(output.id) == "true";
            }
            return autoComplete.dynamicItemset;
        },

        /**
         * Returns the content the values from the select1
         */
        getCurrentValues: function(query) {
            var autoComplete = this;
            var result = [];

            // Look again for the element, as on IE the <select> is recreated when the itemset changes, and so can't be cached
            var select1Element = Dom.getElementsByClassName("fr-autocomplete-select1", null, autoComplete.element)[0];
            var options = select1Element.options;
            if (query != "") {
                query = query.toLowerCase();
                for (var optionIndex = 0; optionIndex < options.length; optionIndex++) {
                    var option = options[optionIndex];
                    if (option.text.toLowerCase().indexOf(query) == 0)
                        result[result.length] = option.text;
                }
            }
            return result;
        }
    };

    ORBEON.widget.AutoComplete.containerXFormsEnabled = function() {
        var container = this;
        var controlID = container.parentNode.id;
        if (!Lang.isObject(controls[controlID])) {
            controls[controlID] = new ORBEON.widget.AutoComplete(container.parentNode);
        }
    };
})();

<commit_msg>Don't filter when in dynamic mode<commit_after>/**
 *  Copyright (C) 2009 Orbeon, Inc.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the
 *  GNU Lesser General Public License as published by the Free Software Foundation; either version
 *  2.1 of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU Lesser General Public License for more details.
 *
 *  The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
 */
(function() {
    var Dom = YAHOO.util.Dom;
    var Event = YAHOO.util.Event;
    var Lang = YAHOO.lang;
    var Document = ORBEON.xforms.Document;

    /**
     * Singleton with mapping control ID to control object
     */
    var controls = {};

    /**
     * AutoComplete object constructor
     */
    ORBEON.widget.AutoComplete = function(element) { this.init(element); }
    ORBEON.widget.AutoComplete.prototype = {

        /**
         * Attributes
         */
        element: null,              // Div containing this control
        dynamicItemset: null,       // Do we need to wait for the itemset to change before we update the auto-complete?
        yuiAutoComplete: null,      // YUI object for the auto-complete

        /**
         * Constructor
         */
        init: function(element) {
            var autoComplete = this;

            autoComplete.element = element;

            var inputSpan = Dom.getElementsByClassName("fr-autocomplete-input", null, element)[0];
            var inputField = Dom.getChildren(inputSpan)[0];
            var yuiDiv = Dom.getElementsByClassName("fr-autocomplete-yui-div", null, element)[0];
            YAHOO.util.Dom.generateId(yuiDiv); // Generate ID dynamically as our implementation of XBL doesn't rewrite IDs on HTML

            // Build data source
            var dataSource;
            if (autoComplete.isDynamicItemset()) {
                // If the itemset changes dynamically, update list when we have response to an Ajax request
                dataSource = autoComplete.buildNullDataSource();
                ORBEON.xforms.Events.ajaxResponseProcessedEvent.subscribe(function() {
                    // If this YUI auto-complete is focused (otherwise don't bother updating the list)
                    if (autoComplete.yuiAutoComplete.isFocused()) {
                        // Get new list of values
                        var query = inputField.value;
                        var newList = autoComplete.getCurrentValues(query);

                        // Call YUI code to update list
                        if (newList.length != 1 || newList[0] != query) {
                            autoComplete.yuiAutoComplete._populateList(query, { results: newList }, { query: query });
                        }
                    }
                });
            } else {
                // Simply get
                dataSource = new YAHOO.util.FunctionDataSource(function(query) {
                    return autoComplete.getCurrentValues(query);
                });
            }

            // Create YUI auto-complete object
            autoComplete.yuiAutoComplete = new YAHOO.widget.AutoComplete(inputField.id, yuiDiv.id, dataSource);
            autoComplete.yuiAutoComplete.animVert = false;
        },

        /**
         * Creates a data source that never returns anything
         */
        buildNullDataSource: function() {
            var autoComplete = this;

            var WaitAjaxResponseDataSource = function(oLiveData, oConfigs) {
                this.dataType = YAHOO.util.DataSourceBase.TYPE_JSFUNCTION;
                oLiveData = oLiveData || function() {};
                this.constructor.superclass.constructor.call(this, oLiveData, oConfigs);
            };

            Lang.extend(WaitAjaxResponseDataSource, YAHOO.util.DataSourceBase, {
                makeConnection : function(oRequest, oCallback, oCaller) {
                    var dataSource = this;
                    var tId = YAHOO.util.DataSourceBase._nTransactionId++;
                    dataSource.fireEvent("requestEvent", {tId:tId,request:oRequest,callback:oCallback,caller:oCaller});
                    dataSource.responseType = YAHOO.util.DataSourceBase.TYPE_JSARRAY;
                    return tId;
                }
            });

            return new WaitAjaxResponseDataSource(function(query) { return autoComplete.getCurrentValues(query); });
        },

        /**
         * Returns the list of values currently in the itemset
         */
        isDynamicItemset: function() {
            var autoComplete = this;
            if (autoComplete.dynamicItemset === null) {
                var output = Dom.getElementsByClassName("fr-autocomplete-dynamic-itemset", null, autoComplete.element)[0];
                autoComplete.dynamicItemset = Document.getValue(output.id) == "true";
            }
            return autoComplete.dynamicItemset;
        },

        /**
         * Returns the content the values from the select1
         */
        getCurrentValues: function(query) {
            var autoComplete = this;
            var result = [];

            // Look again for the element, as on IE the <select> is recreated when the itemset changes, and so can't be cached
            var select1Element = Dom.getElementsByClassName("fr-autocomplete-select1", null, autoComplete.element)[0];
            var options = select1Element.options;
            if (query != "") {
                query = query.toLowerCase();
                for (var optionIndex = 0; optionIndex < options.length; optionIndex++) {
                    var option = options[optionIndex];
                    // We only do filtering for the static itemset mode
                    if (autoComplete.isDynamicItemset() || option.text.toLowerCase().indexOf(query) == 0)
                        result[result.length] = option.text;
                }
            }
            return result;
        }
    };

    ORBEON.widget.AutoComplete.containerXFormsEnabled = function() {
        var container = this;
        var controlID = container.parentNode.id;
        if (!Lang.isObject(controls[controlID])) {
            controls[controlID] = new ORBEON.widget.AutoComplete(container.parentNode);
        }
    };
})();

<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import filter from 'lodash/filter'
import map from 'lodash/map'
import isCurrentSemester from '../../../helpers/is-current-semester'

import Loading from '../../../components/loading'
import {destroySchedules} from '../../../redux/students/actions/schedules'
import {moveCourse, addCourse} from '../../../redux/students/actions/courses'
import Semester from '../components/semester'

import getSchedule from '../../../helpers/get-schedule'

export class SemesterContainer extends Component {
	static propTypes = {
		addCourse: PropTypes.func.isRequired,  // redux
		destroySchedules: PropTypes.func.isRequired,
		moveCourse: PropTypes.func.isRequired, // redux
		semester: PropTypes.number.isRequired,
		student: PropTypes.object.isRequired,
		year: PropTypes.number.isRequired,
	};

	removeSemester = () => {
		const { student, semester, year } = this.props
		const thisSemesterSchedules = filter(student.schedules, isCurrentSemester(year, semester))
		const scheduleIds = map(thisSemesterSchedules, s => s.id)
		this.props.destroySchedules(student.id, ...scheduleIds)
	};

	render() {
		const { student, semester, year, addCourse, moveCourse } = this.props
		const schedule = getSchedule(student, year, semester)

		if (schedule.isValidating) {
			return <Loading>Loading Courses…</Loading>
		}

		return (
			<Semester
				addCourse={addCourse}
				moveCourse={moveCourse}
				removeSemester={this.removeSemester}
				schedule={schedule}
				semester={semester}
				student={student}
				year={year}
			/>
		)
	}
}

const mapDispatchToProps = dispatch =>
	bindActionCreators({destroySchedules, moveCourse, addCourse}, dispatch)

const connected = connect(undefined, mapDispatchToProps)(SemesterContainer)

export default connected
<commit_msg>add a comment to <Semester/><commit_after>import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import filter from 'lodash/filter'
import map from 'lodash/map'
import isCurrentSemester from '../../../helpers/is-current-semester'

import Loading from '../../../components/loading'
import {destroySchedules} from '../../../redux/students/actions/schedules'
import {moveCourse, addCourse} from '../../../redux/students/actions/courses'
import Semester from '../components/semester'

import getSchedule from '../../../helpers/get-schedule'

export class SemesterContainer extends Component {
	static propTypes = {
		addCourse: PropTypes.func.isRequired,  // redux
		destroySchedules: PropTypes.func.isRequired, // redux
		moveCourse: PropTypes.func.isRequired, // redux
		semester: PropTypes.number.isRequired,
		student: PropTypes.object.isRequired,
		year: PropTypes.number.isRequired,
	};

	removeSemester = () => {
		const { student, semester, year } = this.props
		const thisSemesterSchedules = filter(student.schedules, isCurrentSemester(year, semester))
		const scheduleIds = map(thisSemesterSchedules, s => s.id)
		this.props.destroySchedules(student.id, ...scheduleIds)
	};

	render() {
		const { student, semester, year, addCourse, moveCourse } = this.props
		const schedule = getSchedule(student, year, semester)

		if (schedule.isValidating) {
			return <Loading>Loading Courses…</Loading>
		}

		return (
			<Semester
				addCourse={addCourse}
				moveCourse={moveCourse}
				removeSemester={this.removeSemester}
				schedule={schedule}
				semester={semester}
				student={student}
				year={year}
			/>
		)
	}
}

const mapDispatchToProps = dispatch =>
	bindActionCreators({destroySchedules, moveCourse, addCourse}, dispatch)

const connected = connect(undefined, mapDispatchToProps)(SemesterContainer)

export default connected
<|endoftext|>


<commit_before>/*
*  Name: Labor Statistics Dashboard Custom Slider
*  Author: John Denielle Hernandez
*  Desc: Custom slider component similar to input of type range with some
*    additional features such as multiple values and automatic orientation
*    detection.
*/

/*
*  TODO: Configurable handles example
*
*  TODO: Apply prop validation
*/

/*
*  LsdSliderHandle React Component
*  States:
*    dragging:  [boolean] Needed to be checked if the handle needs to be moved
*               because the mouse listener is declared globally.
*    position:  [JSON object] {
*      top: [float] Changed when a vertical slider handle is being dragged.
*      left: [float] Changed when a horizontal slider handle is being dragged.
*    }
*    dimension:  [JSON object] Offset dimension of the handle. {
*	   width: [float] Obtained from offsetWidth HTML element property.
*      height: [float] Obtained from offsetHeight HTML element property.
*    }
*    borderWidth: [float] Used for offset
*  Props:
*    computeHandlePosition= [function] Used to get new position when dragging.
*    computeHandleOffset= [function] Uses the offset height/width of handle.
*    orientation: [string] "x" | "y" Determined by LsdSlider React Component.
*    initialValue: [float] Used to show multiple handles evenly distributed
*                  across the slider initially.
*/
var LsdSliderHandle = React.createClass({
  /*
  *  TODO: Fix warning -> "getInitialState was defined on LsdSlider, a plain
  *  JavaScript class. This is only supported for classes created using
  *  React.createClass. Did you mean to define a state property instead?".
  *
  *  TODO: Fix bug, resizing window breaks offset of handle in vertical slider.
  *  The horizontal slider seems to be clear of this bug.
  *
  *  TODO: Check if clientHeight/Width or scrollHeight/Width can replace the
  *        handle offset computation using the borderWidth state.
  *
  *  TODO: Refactor all code that relies on orientation. Eliminate redundancy.
  *
  *  TODO: Try Using ReactLink
  */
  getInitialState: function() {
    return {
      dragging: false,
      position: {
        top: 0,
        left: 0
      },
      dimension: {
        width: 0,
        height: 0
      },
      borderWidth: 0
    };
  },
  componentDidMount: function() {
  	/*
    *  Binding dragStart to mousedown should also be here but:
    *  onMouseDown > refs (by simplicity).
    *  Take note that I add the event listener to the document element because:
    *  1. The mousemove relies on the mouse's coordinates relative to the
    *     document, not the handle. Otherwise, the handle will move only if the
    *     mouse is moved inside the handle.
    *  2. If the mouse is released outside the handle, the drag will stop since
    *     the document, and not the handle, listens to that event.
    */
    document.addEventListener("mousemove", this.dragEvent);
    document.addEventListener("mouseup", this.dragStop);

    /*
  	*  Get the real value of the handle element. It factors in the width of the
  	*  border and padding.
  	*/
    var newDimension = {
      width: this.componentInstance.offsetWidth,
      height: this.componentInstance.offsetHeight
    };

    var handleOffset = this.props.computeHandleOffset(newDimension);

    var newPosition =
      (this.props.orientation == "x")?
        {
          top: -handleOffset,
          left: this.props.enforcedValue-handleOffset
        }:
        {
          top: this.props.enforcedValue-handleOffset,
          left: -handleOffset
        };

    this.setState({
      dimension: newDimension,
      position: newPosition,
      borderWidth: parseInt(getComputedStyle(this.componentInstance).getPropertyValue("border-width"))
    });
  },
  componentWillUnmount: function(){
  	document.removeEventListener("mousemove", this.dragEvent);
    document.removeEventListener("mouseup", this.dragStop);
  },
  dragStart: function() {
    this.setState ({
      dragging: true
    });
  },
  dragStop: function() {
    this.setState ({
      dragging: false
    });
  },
  dragEvent: function(event) {
    if (this.state.dragging) {
      /*
      *  Prevents the cursor to select elements while dragging the handle
      */
      if(event.stopPropagation) event.stopPropagation();
      if(event.preventDefault) event.preventDefault();

      var handlePos = this.props.computeHandlePosition(
      	this.props.id,
        {
          x: event.pageX,
          y: event.pageY
        },
        this.state.dimension
      );

      // if(this.props.orientation == "x") {
      //   this.setState({
      //     position: {
      //       left: handlePos.offsetValue
      //     }
      //   });
      // }
      // else {
      //   this.setState({
      //     position: {
      //       top: handlePos.offsetValue
      //     }
      //   });
      // }
    }
  },
  render: function() {
    /*
  	*  The long computation is for centering the handle with respect to the
  	*  slider's orientation.
  	*/
  	var handleOffset = this.props.computeHandleOffset(this.state.dimension);

    var style = (this.props.orientation == "x")?
      ({
        left: this.props.enforcedValue-handleOffset + "%",
        top: -(this.state.dimension.height-this.state.borderWidth)/2 + "px"
      }):
      ({
        top: this.props.enforcedValue-handleOffset + "%",
        left: -(this.state.dimension.width-this.state.borderWidth)/2 + "px"
      });

    return (

 this.componentInstance = ref}>

    );
  }
});

/*
*  LsdSliderRange React Component
*  States:
*
*  Props:
*
*  NOTE: LsdSliderRange must only be shown when there are more than 1 handle.
*/

var LsdSliderRange = React.createClass({
  render: function() {
    return (

    );
  }
});

/*
*  LsdSlider React Component
*  States:
*    position: [JSON object] {
*      top: [float]
*      left: [float]
*    orientation: [string]
*    }
*  Props:
*    width: [float] Used in normalization of mouse coords - horizontal.
*    height: [float] Used in normalization of mouse coords - vertical.
*    min: [float]
*    max: [float]
*    multiple: [integer] Determines the number of handles in the slider.
*
*  TODO: Fix handle offset computation when slider width is not 5px. uhmm. nvm
*        Do this instead, receive alignment prop with values:
*        left/top, middle, right/bottom. default is left/top.
*/
var LsdSlider = React.createClass({
  getInitialState: function() {
    return {
      position: {
        top: 0,
        left: 0
      },
      dimension: {
      	width: 0,
      	height: 0
      },
      orientation: "",
      values: []
    };
  },
  componentWillMount: function() {
  	if(!(this.props.width || this.props.height)){
      console.error("Warning: LsdSlider's width and height properties are both null. Please declare at least one property.");
  	}

  	var correctWidth = parseInt(this.props.width) || 5;
  	var correctHeight = parseInt(this.props.height) || 5;

    /*
    *  Computation for distributing multiple handles evenly along the slider.
    */
  	var handleCount = this.props.multiple || 1;
  	var percentInterval = (handleCount > 1)?100/(handleCount-1):0;
  	var values = [];

  	for(var i=0; i<handleCount; i++){
  		values.push(percentInterval*i);
  	}

    /*
    *  Automatic orientation identification lmao.
    *  This state is passed to LsdSliderHandle.
    */
    var orientation = (correctWidth>correctHeight)?"x":"y";

    this.setState({
      dimension: {
      	width: correctWidth,
      	height: correctHeight
      },
      orientation: orientation,
      handleCount: handleCount,
      values: values
    });
  },
  componentDidMount: function() {
    /*
    *  Identify the position of this component after it has been rendered on
    *  the DOM. This state is passed to LsdSliderHandle.
    */
    var componentPosition = cumulativeOffset(this.componentInstance);

    this.setState({
      position: {
      	top: componentPosition.top,
        left: componentPosition.left
      }
    });
  },
  /*
  *  Normalization of mouse coordinates relative to the slider.
  */
  normalizeMouse: function(mouseCoords, handleDimension) {
    if(this.state.orientation == "x")
      return ((mouseCoords.x-this.state.position.left-handleDimension.width/2)/this.state.dimension.width)*100;
    else
      return ((mouseCoords.y-this.state.position.top-handleDimension.height/2)/this.state.dimension.height)*100;
  },
  /*
  *  Forces a threshold to the drag value to prevent handle from going
  *  outside the slider.
  */
  computeHandleOffset: function(handleDimension) {
    if(this.state.orientation == "x")
      return ((handleDimension.width/2)/this.state.dimension.width)*100;
    else
      return ((handleDimension.height/2)/this.state.dimension.height)*100;
  },
  applyThreshold: function(value) {
  	/*
  	*  Percentage only in here that's why min == 0 and max == 100.
  	*  Actual value with respect to the min/max parameters would be computed
  	*  somewhere else.
  	*/
    return (value<0)?0:((value>100)?100:value);
  },
  computeHandlePosition: function(handleId, mouseCoords, handleDimension) {
    /*
  	*  NOTE: When adding support for min/max parameters, compute it here.
  	*/
    var realValue = this.normalizeMouse(mouseCoords, handleDimension);
    realValue = this.applyThreshold(realValue);
    var offsetValue = realValue-this.computeHandleOffset(handleDimension);
    this.updateHandleValue(handleId, realValue);

    var values = this.state.values;

    /*
    *  Looks through the array of values and determines if a certain (or some)
    *  of the other handles aside from the one being dragged need to be dragged
    *  too when the allowPass property is not specified or is false.
    *
    *  TODO: Optimize. Must be able to handle 2000 handles or more.
    */
    var hndlCt = this.state.handleCount;
    if(this.props.allowPass != "true"){
      for(var i=hndlCt; i--;){
        if(i<handleId && this.state.values[i]>this.state.values[handleId] || i>handleId && this.state.values[i]<this.state.values[handleId]){
          values[i] = realValue;
        }
      }
    }

    this.setState({
      values: values
    });

    return {realValue, offsetValue};
  },
  updateHandleValue: function(handleId, value) {
    var values = this.state.values;

    values[handleId] = value;

    this.setState({
      values: values
    });
  },
  render: function() {
    /*
    *  Sets orientation based on dimension.
    *  By default, a slider's rail is 5px thick.
    *
    *  TODO:
    */
    var style = (this.state.orientation == "x")?
      ({width: this.props.width + "px", height: this.state.dimension.height + "px"}):
      ({height: this.props.height + "px", width: this.state.dimension.width + "px"});

    var handles = [];

    for(var i=0; i<this.state.handleCount; i++){
      handles.push(
        <LsdSliderHandle
          key={i}
          id={i}
          computeHandlePosition={this.computeHandlePosition}
          computeHandleOffset={this.computeHandleOffset}
          orientation={this.state.orientation}
          enforcedValue={this.state.values[i]}/>
      );
    }

    return (

 this.componentInstance = ref}> {/*Refs! Must be a pro.*/}
        <LsdSliderRange />
        {handles}

    );
  }
});

ReactDOM.render(
  <LsdSlider key="1" width="300" multiple="2000" min="1" max="8"/>,
  document.getElementById('lsd-slider-1')
);

ReactDOM.render(
  <LsdSlider key="2" height="240"/>,
  document.getElementById('lsd-slider-2')
);<commit_msg>Removed redundant orientation check and position assignment in handle component.<commit_after>/*
*  Name: Labor Statistics Dashboard Custom Slider
*  Author: John Denielle Hernandez
*  Desc: Custom slider component similar to input of type range with some
*    additional features such as multiple values and automatic orientation
*    detection.
*/

/*
*  TODO: Configurable handles example
*
*  TODO: Apply prop validation
*/

/*
*  LsdSliderHandle React Component
*  States:
*    dragging:  [boolean] Needed to be checked if the handle needs to be moved
*               because the mouse listener is declared globally.
*    position:  [JSON object] {
*      top: [float] Changed when a vertical slider handle is being dragged.
*      left: [float] Changed when a horizontal slider handle is being dragged.
*    }
*    dimension:  [JSON object] Offset dimension of the handle. {
*	   width: [float] Obtained from offsetWidth HTML element property.
*      height: [float] Obtained from offsetHeight HTML element property.
*    }
*    borderWidth: [float] Used for offset
*  Props:
*    computeHandlePosition= [function] Used to get new position when dragging.
*    computeHandleOffset= [function] Uses the offset height/width of handle.
*    orientation: [string] "x" | "y" Determined by LsdSlider React Component.
*    initialValue: [float] Used to show multiple handles evenly distributed
*                  across the slider initially.
*/
var LsdSliderHandle = React.createClass({
  /*
  *  TODO: Fix warning -> "getInitialState was defined on LsdSlider, a plain
  *  JavaScript class. This is only supported for classes created using
  *  React.createClass. Did you mean to define a state property instead?".
  *
  *  TODO: Fix bug, resizing window breaks offset of handle in vertical slider.
  *  The horizontal slider seems to be clear of this bug.
  *
  *  TODO: Check if clientHeight/Width or scrollHeight/Width can replace the
  *        handle offset computation using the borderWidth state.
  *
  *  TODO: Refactor all code that relies on orientation. Eliminate redundancy.
  *
  *  TODO: Try Using ReactLink
  */
  getInitialState: function() {
    return {
      dragging: false,
      position: {
        top: 0,
        left: 0
      },
      dimension: {
        width: 0,
        height: 0
      },
      borderWidth: 0
    };
  },
  componentDidMount: function() {
  	/*
    *  Binding dragStart to mousedown should also be here but:
    *  onMouseDown > refs (by simplicity).
    *  Take note that I add the event listener to the document element because:
    *  1. The mousemove relies on the mouse's coordinates relative to the
    *     document, not the handle. Otherwise, the handle will move only if the
    *     mouse is moved inside the handle.
    *  2. If the mouse is released outside the handle, the drag will stop since
    *     the document, and not the handle, listens to that event.
    */
    document.addEventListener("mousemove", this.dragEvent);
    document.addEventListener("mouseup", this.dragStop);

    /*
  	*  Get the real value of the handle element. It factors in the width of the
  	*  border and padding.
  	*/
    var newDimension = {
      width: this.componentInstance.offsetWidth,
      height: this.componentInstance.offsetHeight
    };

    var handleOffset = this.props.computeHandleOffset(newDimension);

    this.setState({
      dimension: newDimension,
      borderWidth: parseInt(getComputedStyle(this.componentInstance).getPropertyValue("border-width"))
    });
  },
  componentWillUnmount: function(){
  	document.removeEventListener("mousemove", this.dragEvent);
    document.removeEventListener("mouseup", this.dragStop);
  },
  dragStart: function() {
    this.setState ({
      dragging: true
    });
  },
  dragStop: function() {
    this.setState ({
      dragging: false
    });
  },
  dragEvent: function(event) {
    if (this.state.dragging) {
      /*
      *  Prevents the cursor to select elements while dragging the handle
      */
      if(event.stopPropagation) event.stopPropagation();
      if(event.preventDefault) event.preventDefault();

      var handlePos = this.props.computeHandlePosition(
      	this.props.id,
        {
          x: event.pageX,
          y: event.pageY
        },
        this.state.dimension
      );
    }
  },
  render: function() {
    /*
  	*  The long computation is for centering the handle with respect to the
  	*  slider's orientation.
  	*/
  	var handleOffset = this.props.computeHandleOffset(this.state.dimension);

    var style = (this.props.orientation == "x")?
      ({
        left: this.props.enforcedValue-handleOffset + "%",
        top: -(this.state.dimension.height-this.state.borderWidth)/2 + "px"
      }):
      ({
        top: this.props.enforcedValue-handleOffset + "%",
        left: -(this.state.dimension.width-this.state.borderWidth)/2 + "px"
      });

    return (

 this.componentInstance = ref}>

    );
  }
});

/*
*  LsdSliderRange React Component
*  States:
*
*  Props:
*
*  NOTE: LsdSliderRange must only be shown when there are more than 1 handle.
*/

var LsdSliderRange = React.createClass({
  render: function() {
    return (

    );
  }
});

/*
*  LsdSlider React Component
*  States:
*    position: [JSON object] {
*      top: [float]
*      left: [float]
*    orientation: [string]
*    }
*  Props:
*    width: [float] Used in normalization of mouse coords - horizontal.
*    height: [float] Used in normalization of mouse coords - vertical.
*    min: [float]
*    max: [float]
*    multiple: [integer] Determines the number of handles in the slider.
*
*  TODO: Fix handle offset computation when slider width is not 5px. uhmm. nvm
*        Do this instead, receive alignment prop with values:
*        left/top, middle, right/bottom. default is left/top.
*/
var LsdSlider = React.createClass({
  getInitialState: function() {
    return {
      position: {
        top: 0,
        left: 0
      },
      dimension: {
      	width: 0,
      	height: 0
      },
      orientation: "",
      values: []
    };
  },
  componentWillMount: function() {
  	if(!(this.props.width || this.props.height)){
      console.error("Warning: LsdSlider's width and height properties are both null. Please declare at least one property.");
  	}

  	var correctWidth = parseInt(this.props.width) || 5;
  	var correctHeight = parseInt(this.props.height) || 5;

    /*
    *  Computation for distributing multiple handles evenly along the slider.
    */
  	var handleCount = this.props.multiple || 1;
  	var percentInterval = (handleCount > 1)?100/(handleCount-1):0;
  	var values = [];

  	for(var i=0; i<handleCount; i++){
  		values.push(percentInterval*i);
  	}

    /*
    *  Automatic orientation identification lmao.
    *  This state is passed to LsdSliderHandle.
    */
    var orientation = (correctWidth>correctHeight)?"x":"y";

    this.setState({
      dimension: {
      	width: correctWidth,
      	height: correctHeight
      },
      orientation: orientation,
      handleCount: handleCount,
      values: values
    });
  },
  componentDidMount: function() {
    /*
    *  Identify the position of this component after it has been rendered on
    *  the DOM. This state is passed to LsdSliderHandle.
    */
    var componentPosition = cumulativeOffset(this.componentInstance);

    this.setState({
      position: {
      	top: componentPosition.top,
        left: componentPosition.left
      }
    });
  },
  /*
  *  Normalization of mouse coordinates relative to the slider.
  */
  normalizeMouse: function(mouseCoords, handleDimension) {
    if(this.state.orientation == "x")
      return ((mouseCoords.x-this.state.position.left-handleDimension.width/2)/this.state.dimension.width)*100;
    else
      return ((mouseCoords.y-this.state.position.top-handleDimension.height/2)/this.state.dimension.height)*100;
  },
  /*
  *  Forces a threshold to the drag value to prevent handle from going
  *  outside the slider.
  */
  computeHandleOffset: function(handleDimension) {
    if(this.state.orientation == "x")
      return ((handleDimension.width/2)/this.state.dimension.width)*100;
    else
      return ((handleDimension.height/2)/this.state.dimension.height)*100;
  },
  applyThreshold: function(value) {
  	/*
  	*  Percentage only in here that's why min == 0 and max == 100.
  	*  Actual value with respect to the min/max parameters would be computed
  	*  somewhere else.
  	*/
    return (value<0)?0:((value>100)?100:value);
  },
  computeHandlePosition: function(handleId, mouseCoords, handleDimension) {
    /*
  	*  NOTE: When adding support for min/max parameters, compute it here.
  	*/
    var realValue = this.normalizeMouse(mouseCoords, handleDimension);
    realValue = this.applyThreshold(realValue);
    var offsetValue = realValue-this.computeHandleOffset(handleDimension);
    this.updateHandleValue(handleId, realValue);

    var values = this.state.values;

    /*
    *  Looks through the array of values and determines if a certain (or some)
    *  of the other handles aside from the one being dragged need to be dragged
    *  too when the allowPass property is not specified or is false.
    *
    *  TODO: Optimize. Must be able to handle 2000 handles or more.
    */
    var hndlCt = this.state.handleCount;
    if(this.props.allowPass != "true"){
      for(var i=hndlCt; i--;){
        if(i<handleId && this.state.values[i]>this.state.values[handleId] || i>handleId && this.state.values[i]<this.state.values[handleId]){
          values[i] = realValue;
        }
      }
    }

    this.setState({
      values: values
    });

    return {realValue, offsetValue};
  },
  updateHandleValue: function(handleId, value) {
    var values = this.state.values;

    values[handleId] = value;

    this.setState({
      values: values
    });
  },
  render: function() {
    /*
    *  Sets orientation based on dimension.
    *  By default, a slider's rail is 5px thick.
    *
    *  TODO:
    */
    var style = (this.state.orientation == "x")?
      ({width: this.props.width + "px", height: this.state.dimension.height + "px"}):
      ({height: this.props.height + "px", width: this.state.dimension.width + "px"});

    var handles = [];

    for(var i=0; i<this.state.handleCount; i++){
      handles.push(
        <LsdSliderHandle
          key={i}
          id={i}
          computeHandlePosition={this.computeHandlePosition}
          computeHandleOffset={this.computeHandleOffset}
          orientation={this.state.orientation}
          enforcedValue={this.state.values[i]}/>
      );
    }

    return (

 this.componentInstance = ref}> {/*Refs! Must be a pro.*/}
        <LsdSliderRange />
        {handles}

    );
  }
});

ReactDOM.render(
  <LsdSlider key="1" width="300" multiple="2" min="1" max="8"/>,
  document.getElementById('lsd-slider-1')
);

ReactDOM.render(
  <LsdSlider key="2" height="240"/>,
  document.getElementById('lsd-slider-2')
);<|endoftext|>


<commit_before><commit_msg>Update animation.js<commit_after><|endoftext|>


<commit_before>'use strict';

const firebase = require('firebase');
const config = require('.././config');
const db = firebase.database();
const refIdea = db.ref().child('idea');

/*
* Metodo para listar ideas
*/
function listarIdeas (req, res) {
	let data;
	refIdea.on('value', (snap) => {
		data = snap.val();
		console.log(snap.val());
	});
	res.status(200).send(data);
}

/*
* Metodo para crear ideas
*/
function crearIdea (req, res) {
	let nuevaIdea = refIdea.child(''+req.body. numero);

	let objIdea = {
		numero : req.body.numero,
		beneficios:  req. body.beneficios,
		descripcion : req.body.descripcion,
		disposicionesFinales : req.body.disposicionesFinales,
		efectos : req.body.efectos,
		fechaActualizacion : req.body.fechaActualizacion,
		fechaElaboracion : req.body.fechaElaboracion,
		formulaLegal : req.body.formulaLegal,
		motivos : req.body.motivos,
		titular : req.body.titular,
		categoria : req.body.categoria
	};

	nuevaIdea.set(objIdea);

	res.status(200).send({msg : 'Se registro la idea'});
}

module.exports = {
	listarIdeas,
	crearIdea
};
<commit_msg>Correcion de controlador idea<commit_after>'use strict';

const firebase = require('firebase');
const config = require('.././config');
const db = firebase.database();
const refIdea = db.ref().child('idea');

/*
* Metodo para listar ideas
*/
function listarIdeas (req, res) {
	let data;
	refIdea.on('value', (snap) => {
		data = snap.val();
		console.log(snap.val());
	});
	res.status(200).send(data);
}

/*
* Metodo para crear ideas
*/
function crearIdea (req, res) {
	let nuevaIdea = refIdea.child(''+req.body.numero);

	let objIdea = {
		numero : req.body.numero,
		beneficios:  req. body.beneficios,
		descripcion : req.body.descripcion,
		disposicionesFinales : req.body.disposicionesFinales,
		efectos : req.body.efectos,
		fechaActualizacion : req.body.fechaActualizacion,
		fechaElaboracion : req.body.fechaElaboracion,
		formulaLegal : req.body.formulaLegal,
		motivos : req.body.motivos,
		titular : req.body.titular,
		categoria : req.body.categoria
	};

	nuevaIdea.set(objIdea);

	res.status(200).send({msg : 'Se registro la idea'});
}

module.exports = {
	listarIdeas,
	crearIdea
};
<|endoftext|>


<commit_before>var _ = require("lodash");
var Story = require("../models/story");

/**
 * 从数据库中查找指定 Id 的日报。
 * @param  {String} p_id         指定的日报 Id。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.findStoryById = function (p_id, p_callback)
{
    if (_.isFunction(p_callback))
    {
        Story.findOne({ id: p_id }, p_callback);
    }
};

/**
 * 从数据库中查找指定日期的日报。
 * @param  {String} p_date       指定的日期。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.findStoriesByDate = function (p_date, p_callback)
{
    if (_.isFunction(p_callback))
    {
        Story.find({ date: p_date }, p_callback);
    }
};

/**
 * 从数据库中查找指定日期的未读日报。如果未指定，则查找所有未读日报。
 * @param  {String} p_date       指定的日期。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.findUnreadStories = function (p_date, p_callback)
{
    if (_.isFunction(p_callback))
    {
        if (_.isEmpty(_.trim(p_date)))
        {
            this.findAllUnreadStories(p_callback);
        }
        else
        {
            Story.find(
                {
                    date: p_date,
                    read: false
                },
                p_callback
            );
        }
    }
};

/**
 * 从数据库中查找所有未读日报。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.findAllUnreadStories = function (p_callback)
{
    if (_.isFunction(p_callback))
    {
        Story.find({ read: false }, p_callback);
    }
};

/**
 * 保存知乎日报至数据库。如果已存在，则更新。
 * @param  {JSONObject} p_story  指定的日报（特指从服务端获取到的 JSON Object）。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.saveStory = function (p_story, p_callback)
{
    if (p_story)
    {
        var condition = {
            id: p_story.id
        };

        var update = {
            id: p_story.id,
            date: p_story.date,
            content: JSON.stringify(p_story)
        };

        var options = {
            new: true,
            upsert: true
        };

        Story.findOneAndUpdate(condition, update, options, p_callback);
    }
    else
    {
        if (_.isFunction(p_callback))
        {
            p_callback(new Error("p_story is empty."))
        }
    }
};<commit_msg>add cached<commit_after>var _ = require("lodash");
var Story = require("../models/story");

/**
 * 从数据库中查找指定 Id 的日报。
 * @param  {String} p_id         指定的日报 Id。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.findStoryById = function (p_id, p_callback)
{
    if (_.isFunction(p_callback))
    {
        Story.findOne({ id: p_id }, p_callback);
    }
};

/**
 * 从数据库中查找指定日期的日报。
 * @param  {String} p_date       指定的日期。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.findStoriesByDate = function (p_date, p_callback)
{
    if (_.isFunction(p_callback))
    {
        Story.find({ date: p_date }, p_callback);
    }
};

/**
 * 从数据库中查找指定日期的未读日报。如果未指定，则查找所有未读日报。
 * @param  {String} p_date       指定的日期。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.findUnreadStories = function (p_date, p_callback)
{
    if (_.isFunction(p_callback))
    {
        if (_.isEmpty(_.trim(p_date)))
        {
            this.findAllUnreadStories(p_callback);
        }
        else
        {
            Story.find(
                {
                    date: p_date,
                    read: false
                },
                p_callback
            );
        }
    }
};

/**
 * 从数据库中查找所有未读日报。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.findAllUnreadStories = function (p_callback)
{
    if (_.isFunction(p_callback))
    {
        Story.find({ read: false }, p_callback);
    }
};

/**
 * 保存知乎日报至数据库。如果已存在，则更新。
 * @param  {JSONObject} p_story  指定的日报（特指从服务端获取到的 JSON Object）。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.saveStory = function (p_story, p_callback)
{
    if (p_story)
    {
        var condition = {
            id: p_story.id
        };

        var update = {
            id: p_story.id,
            date: p_story.date,
            content: JSON.stringify(p_story),
            cached: true
        };

        var options = {
            new: true,
            upsert: true
        };

        Story.findOneAndUpdate(condition, update, options, p_callback);
    }
    else
    {
        if (_.isFunction(p_callback))
        {
            p_callback(new Error("p_story is empty."))
        }
    }
};<|endoftext|>


<commit_before>/* jshint undef: true, strict:false, trailing:false, unused:false */
/* global require, exports, console, process, module, angular, Backbone */
/**
 *  Channels ---
 *  This is an INDX service that grabs data from indx and turns it into magical RDF!
 *  Complies with INDX Entity Semantics 1.0 for People, Places, and Activities
 */

angular.module('indx').factory('channels', function(client, utils)  {

    var u = utils,
        store = client.store;

    var testChannelDefs = function(srcboxid, dstboxid) {
        var test_channels = [];
        // let's make a happy indx person -> foaf channel
        var foafns = 'http://xmlns.com/foaf/0.1/',
            rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
            rdfs = 'http://www.w3.org/2000/01/rdf-schema#';
        test_channels.push({
            name:'foafiser-'+srcboxid+'-'+dstboxid,
            query: { type:'Person' },
            destbox:dstboxid,
            transform: function(pobj) {
                var foafag = {};
                foafag[rdf+'type'] = foafns+'Agent';
                foafag[foafns+'givenName'] = pobj.peek('given_name');
                foafag[foafns+'familyName'] = pobj.peek('surname');
                return foafag;
            }
        });
        return test_channels;
    };
    var defineChannel = function(id, box, definition) {
        var d = u.deferred();
        box.getObj(id).then(function(x) {
            x.set({
                type:'IndxChannel',
                name: definition.name,
                query: JSON.stringify(definition.query),
                destbox: definition.destbox,
                transform : definition.transform.toString()
            });
            x.save().then(d.resolve).fail(d.reject);
        });
        return d.promise();
    };

    // in-memory representation
    var Channel = Backbone.Model.extend({
        initialize:function(params) {
            // takes in params { obj: object }
            var obj = this.obj = params.obj,
                transformsrc = this.transformsrc = obj.peek('transform'),
                querysrc = this.querysrc = obj.peek('query'),
                name = this.name = obj.peek('name'),
                destbox = obj.peek('destbox'),
                boxd = u.deferred(),
                readyd = this.readyd = u.deferred(),
                this_ = this;

            // keeps the deferreds
            this.resultds = {};

            if (transformsrc !== undefined) {
                console.info('transformsrc ', transformsrc);
                this.transform = eval("("+transformsrc+")");
            } else {
                console.warn('no transform fn specified ', obj);
            }

            if (querysrc !== undefined) {
                this.query = JSON.parse(querysrc);
            } else {
                console.warn('Query src not available ', obj);
            }
            if (!destbox) {
                console.warn('no destination box specified for channel ', obj);
                return;
            }
            this.srcbox = obj.box;
            obj.box.store.getBox(obj.peek('destbox')).then(function(dbox) {
                this_.destbox = dbox;
                boxd.resolve();
            }).fail(boxd.reject);
            boxd.then(readyd.resolve).fail(readyd.reject);
        },
        query: {},
        start:function() {
            var startd = u.deferred(), this_ = this;
            if (this.livequery) {  this.livequery.stop();  }
            this.readyd.then(function() {
                this_.livequery = this_.srcbox.standingQuery(this_.query, function(result) {
                    // callback for new result
                    this_.trigger('incoming', result);
                    console.log('new standing query result >> ', result);
                    var resultd = this_._make_resultd(result.id);
                    this_._handleResult(result).then(function(tresult) {
                        this_.publish(tresult)
                            .then(resultd.resolve)
                            .fail(function(err) {  console.error('failure publishing ', result); resultd.reject(err) ; });
                    }).fail(function(err) { console.error('failure transforming ', result); resultd.reject(err); });
                }).then(function(livequery) {
                    this_.livequery = livequery;
                }).fail(function(err) { console.error('error starting standingQuery ... ', err); startd.reject(); });
            }).fail(startd.reject);
            return startd.promise();
        },
        _make_resultd: function(oid) {
            var d = u.deferred();
            d.then(function() { console.info('successful publishing ', oid); }).fail(function(err) { console.err('error publishing ', oid); });
            return d;
        },
        _handleResult: function(result) {
            // gets called on live query result
            return u.dresolve(this.transform(result));
        },
        stop:function() {
            if (this.livequery) { this.livequery.stop(); }
        },
        transform:function(x) { console.warn('noop transform'); return x; },
        save:function() {
            this.obj.set(
                { transform: this.transform.toString(), query: JSON.stringify(this.query) }
            );
            return this.obj.save();
        },
        publish:function(transformed) {
            // can be overridden to ...
            //   1. add to persistent queue for something
            //   2. POST it to a destination ..
            //   3. whatever you want!
            console.log('publishing >> ', transformed);
            var d = u.deferred();
            if (transformed !== undefined) {
                var toid = transformed.id  || (transformed.getID && transformed.getID()) || u.guid();
                this.destbox.obj(toid).set(transformed).save().then(d.resolve).fail(d.reject);
            }
            return d.promise;
        }
    });

    var getAllBoxes = function() {
        // select only the boxes that we have read perms on
        var D = u.deferred();
        store.getBoxList().then(function(boxlist) {
            u.when(boxlist.map(function(bid) {
                var d = u.deferred();
                // if we fail, that means we probably don't have read perms, so just skip
                store.getBox(bid).then(d.resolve).fail(function() { d.resolve(); });
                return d.promise();
            })).then(function(boxes) { D.resolve(boxes.filter(function(x) { return x; })); }).fail(D.reject);
        }).fail(D.reject);
        return D.promise();
    };

    return {
        Channel:Channel,
        getTestDefs:testChannelDefs,
        getAllBoxes:getAllBoxes,
        getChannels:function() {
            // gets all channels from all boxes you have connections to
            var d = u.deferred();
            getAllBoxes().then(function(boxes) {
                u.when(boxes.map(function(box) {
                    var dc = u.deferred();
                    box.query({type:'IndxChannel'}).then(function(chobjs) {
                        dc.resolve(chobjs.map(function(x) { return new Channel({obj:x}); }));
                    }).fail(dc.reject);
                    return dc.promise();
                })).then(function(chsets) {
                    d.resolve(chsets.reduce(function(x,y){ return x.concat(y); }, []));
                }).fail(d.reject);
            }).fail(d.reject);
            return d.promise();
        },
        define:defineChannel
    };

});

/*
    Node Service stuff

    var nodeindx = require('../../lib/services/nodejs/nodeindx'),
        nodeservice = require('../../lib/services/nodejs/service'),
        ajax = require('../../lib/services/nodejs/node_ajax')(u),
        u = nodeindx.utils,     injector = nodeindx.injector,
        _ = require('underscore'),
        jQuery = require('jquery'),
        path = require('path'),
        https = require('https'),
        output = nodeservice.output,
        Backbone = require('backbone'),
        exporter = require('./exporter'),
        entities = injector.get('entities');

    var instantiate = function(indxhost) {
        var d = u.deferred();
        var svc = Object.create(ChannelerService);
        svc.init(path.dirname(module.filename)).then(function() {
            if (indxhost){ svc.setHost(indxhost); }
            d.resolve(svc);
        }).fail(function(bail) {
            console.log('instantiate exit >> ');
            output({event:'error', message:bail.message || bail.toString()});
            process.exit(1);
            d.reject();
        });
        return d.promise();
    };

    module.exports = {  makeTestChannels : makeTestChannels  };

    if (require.main === module) {
        instantiate().then(function(service) { service.check_args(); });
    }
    var ChannelerService = Object.create(nodeservice.NodeService, {
        run: {
            value: function() {
                var this_ = this, config = this.config, store = this.store,
                    boxes = this.getAllBoxes();
            }
        },
        getAllBoxes: {
            value: function() {
                // select only the boxes that we have read perms on
                var store = this.store, D = u.deferred();
                store.getBoxList().then(function(boxlist) {
                    u.when(boxlist.map(function(bid) {
                        var d = u.deferred();
                        // if we fail, that means we probably don't have read perms, so just skip
                        store.getBox(bid).then(d.resolve).fail(function() { d.resolve(); });
                        return d.promise();
                    })).then(function(boxes) { D.resolve(boxes.filter(function(x) { return x; })); }).fail(D.reject);
                }).fail(D.reject);
                return D.promise();
            }
        },
    });

*/
<commit_msg>updated channel<commit_after>/* jshint undef: true, strict:false, trailing:false, unused:false */
/* global require, exports, console, process, module, angular, Backbone */
/**
 *  Channels ---
 *  This is an INDX service that grabs data from indx and turns it into magical RDF!
 *  Complies with INDX Entity Semantics 1.0 for People, Places, and Activities
 */

angular.module('indx').factory('channels', function(client, utils)  {

    var u = utils,
        store = client.store;

    var testChannelDefs = function(srcboxid, dstboxid) {
        var test_channels = [];
        // let's make a happy indx person -> foaf channel

        test_channels.push({
            name:'foafiser-'+srcboxid+'-'+dstboxid,
            query: { type:'Person' },
            destbox:dstboxid,
            transform: function(pobj) {
                var foafns = 'http://xmlns.com/foaf/0.1/',
                    rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
                    rdfs = 'http://www.w3.org/2000/01/rdf-schema#',
                    foafag = {};

                foafag[rdf+'type'] = foafns+'Agent';
                foafag[foafns+'givenName'] = pobj.peek('given_name');
                foafag[foafns+'familyName'] = pobj.peek('surname');
                return foafag;
            }
        });
        return test_channels;
    };
    var defineChannel = function(id, box, definition) {
        var d = u.deferred();
        box.getObj(id).then(function(x) {
            x.set({
                type:'IndxChannel',
                name: definition.name,
                query: JSON.stringify(definition.query),
                destbox: definition.destbox,
                transform : definition.transform.toString()
            });
            x.save().then(d.resolve).fail(d.reject);
        });
        return d.promise();
    };

    // in-memory representation
    var Channel = Backbone.Model.extend({
        initialize:function(params) {
            // takes in params { obj: object }
            var obj = this.obj = params.obj,
                transformsrc = this.transformsrc = obj.peek('transform'),
                querysrc = this.querysrc = obj.peek('query'),
                name = this.name = obj.peek('name'),
                destbox = obj.peek('destbox'),
                boxd = u.deferred(),
                readyd = this.readyd = u.deferred(),
                this_ = this;

            // keeps the deferreds
            this.resultds = {};

            if (transformsrc !== undefined) {
                console.info('transformsrc ', transformsrc);
                this.transform = eval("("+transformsrc+")");
            } else {
                console.warn('no transform fn specified ', obj);
            }

            if (querysrc !== undefined) {
                this.query = JSON.parse(querysrc);
            } else {
                console.warn('Query src not available ', obj);
            }
            if (!destbox) {
                console.warn('no destination box specified for channel ', obj);
                return;
            }
            this.srcbox = obj.box;
            obj.box.store.getBox(obj.peek('destbox')).then(function(dbox) {
                this_.destbox = dbox;
                boxd.resolve();
            }).fail(boxd.reject);
            boxd.then(readyd.resolve).fail(readyd.reject);
        },
        query: {},
        start:function() {
            var startd = u.deferred(), this_ = this;
            if (this.livequery) {  this.livequery.stop();  }
            this.readyd.then(function() {
                this_.livequery = this_.srcbox.standingQuery(this_.query, function(result) {
                    // callback for new result
                    this_.trigger('incoming', result);
                    console.log('new standing query result >> ', result);
                    var resultd = this_._make_resultd(result.id);
                    this_._handleResult(result).then(function(tresult) {
                        this_.publish(tresult)
                            .then(resultd.resolve)
                            .fail(function(err) {  console.error('failure publishing ', result); resultd.reject(err) ; });
                    }).fail(function(err) { console.error('failure transforming ', result); resultd.reject(err); });
                }).then(function(livequery) {
                    this_.livequery = livequery;
                }).fail(function(err) { console.error('error starting standingQuery ... ', err); startd.reject(); });
            }).fail(startd.reject);
            return startd.promise();
        },
        _make_resultd: function(oid) {
            var d = u.deferred();
            d.then(function() { console.info('successful publishing ', oid); }).fail(function(err) { console.err('error publishing ', oid); });
            return d;
        },
        _handleResult: function(result) {
            // gets called on live query result
            return u.dresolve(this.transform(result));
        },
        stop:function() {
            if (this.livequery) { this.livequery.stop(); }
        },
        transform:function(x) { console.warn('noop transform'); return x; },
        save:function() {
            this.obj.set(
                { transform: this.transform.toString(), query: JSON.stringify(this.query) }
            );
            return this.obj.save();
        },
        publish:function(transformed) {
            // can be overridden to ...
            //   1. add to persistent queue for something
            //   2. POST it to a destination ..
            //   3. whatever you want!
            console.log('publishing >> ', transformed);
            var d = u.deferred();
            if (transformed !== undefined) {
                var toid = transformed.id  || (transformed.getID && transformed.getID()) || u.guid();
                this.destbox.obj(toid).set(transformed).save().then(d.resolve).fail(d.reject);
            }
            return d.promise();
        }
    });

    var getAllBoxes = function() {
        // select only the boxes that we have read perms on
        var D = u.deferred();
        store.getBoxList().then(function(boxlist) {
            u.when(boxlist.map(function(bid) {
                var d = u.deferred();
                // if we fail, that means we probably don't have read perms, so just skip
                store.getBox(bid).then(d.resolve).fail(function() { d.resolve(); });
                return d.promise();
            })).then(function(boxes) { D.resolve(boxes.filter(function(x) { return x; })); }).fail(D.reject);
        }).fail(D.reject);
        return D.promise();
    };

    return {
        Channel:Channel,
        getTestDefs:testChannelDefs,
        getAllBoxes:getAllBoxes,
        getChannels:function() {
            // gets all channels from all boxes you have connections to
            var d = u.deferred();
            getAllBoxes().then(function(boxes) {
                u.when(boxes.map(function(box) {
                    var dc = u.deferred();
                    box.query({type:'IndxChannel'}).then(function(chobjs) {
                        dc.resolve(chobjs.map(function(x) { return new Channel({obj:x}); }));
                    }).fail(dc.reject);
                    return dc.promise();
                })).then(function(chsets) {
                    d.resolve(chsets.reduce(function(x,y){ return x.concat(y); }, []));
                }).fail(d.reject);
            }).fail(d.reject);
            return d.promise();
        },
        define:defineChannel
    };

});

/*
    Node Service stuff

    var nodeindx = require('../../lib/services/nodejs/nodeindx'),
        nodeservice = require('../../lib/services/nodejs/service'),
        ajax = require('../../lib/services/nodejs/node_ajax')(u),
        u = nodeindx.utils,     injector = nodeindx.injector,
        _ = require('underscore'),
        jQuery = require('jquery'),
        path = require('path'),
        https = require('https'),
        output = nodeservice.output,
        Backbone = require('backbone'),
        exporter = require('./exporter'),
        entities = injector.get('entities');

    var instantiate = function(indxhost) {
        var d = u.deferred();
        var svc = Object.create(ChannelerService);
        svc.init(path.dirname(module.filename)).then(function() {
            if (indxhost){ svc.setHost(indxhost); }
            d.resolve(svc);
        }).fail(function(bail) {
            console.log('instantiate exit >> ');
            output({event:'error', message:bail.message || bail.toString()});
            process.exit(1);
            d.reject();
        });
        return d.promise();
    };

    module.exports = {  makeTestChannels : makeTestChannels  };

    if (require.main === module) {
        instantiate().then(function(service) { service.check_args(); });
    }
    var ChannelerService = Object.create(nodeservice.NodeService, {
        run: {
            value: function() {
                var this_ = this, config = this.config, store = this.store,
                    boxes = this.getAllBoxes();
            }
        },
        getAllBoxes: {
            value: function() {
                // select only the boxes that we have read perms on
                var store = this.store, D = u.deferred();
                store.getBoxList().then(function(boxlist) {
                    u.when(boxlist.map(function(bid) {
                        var d = u.deferred();
                        // if we fail, that means we probably don't have read perms, so just skip
                        store.getBox(bid).then(d.resolve).fail(function() { d.resolve(); });
                        return d.promise();
                    })).then(function(boxes) { D.resolve(boxes.filter(function(x) { return x; })); }).fail(D.reject);
                }).fail(D.reject);
                return D.promise();
            }
        },
    });

*/
<|endoftext|>


<commit_before>/* A short script to check the performance of Screen.render. */

const RG = require('./client/src/battles');
const Screen = require('./client/gui/screen');

let numRenders = 0;

const startTime = new Date().getTime();

const level = RG.FACT.createLevel('arena', 80, 25);
const map = level.getMap();
const screen = new Screen(80, 25);
const actor = new RG.Actor.Rogue('rogue');
actor.setIsPlayer(true);
actor.setFOVRange(10);
level.addActor(actor, 1, 1);

for (let i = 0; i < 5000; i++) {
    const visibleCells = level.exploreCells(actor);
    screen.render(1, 1, map, visibleCells);

    const chars = screen.getCharRows();
    const classes = screen.getClassRows();
    ++numRenders;
}

const endTime = new Date().getTime();
const dur = endTime - startTime;
const fps = numRenders / dur * 1000;

console.log('FPS: ' + fps);
<commit_msg>Added vars x,y for the screen size.<commit_after>/* A short script to check the performance of Screen.render. */

const RG = require('../client/src/battles');
const Screen = require('../client/gui/screen');

let numRenders = 0;

const startTime = new Date().getTime();

const x = 80;
const y = 28;

const level = RG.FACT.createLevel('arena', x, y);
const map = level.getMap();
const screen = new Screen(x, y);
const actor = new RG.Actor.Rogue('rogue');
actor.setIsPlayer(true);
actor.setFOVRange(10);
level.addActor(actor, 1, 1);

for (let i = 0; i < 5000; i++) {
    const visibleCells = level.exploreCells(actor);
    screen.render(i % x, i % y, map, visibleCells);

    const chars = screen.getCharRows();
    const classes = screen.getClassRows();
    ++numRenders;
}

const endTime = new Date().getTime();
const durationMs = endTime - startTime;
const fps = numRenders / durationMs * 1000;

console.log('FPS: ' + fps);
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2009 Simon Wistow <simon@thegestalt.org>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/**
 * Usage:
 *
 * Create a table with headers and cells containing data. One of the headers must be 'Time'
 *
 *

 *

 *            Time	Visits	ResponseTime
 *

 *

 *            1196463600000	1	200
 *

  *  .... etc ....
 *

 *
 *  Then, in your main html file include this file plus jquery.flot.js and jquery.flot.selection.js
 *  Then create divs with the ids: 'chart', 'overview' and 'choices' (or whatever you want to call them)
 *  and insert this Javascript.
 *
 *
 *
 *
 *  Feel free to customise as necessary.
 */

// helper for returning the weekends in a period
function weekendAreas(axes) {
    var markings = [];
    var d = new Date(axes.xaxis.min);
    // go to the first Saturday
    d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) % 7))
    d.setUTCSeconds(0);
    d.setUTCMinutes(0);
    d.setUTCHours(0);
    var i = d.getTime();
    do {
        // when we don't set yaxis, the rectangle automatically
        // extends to infinity upwards and downwards
        markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000 } });
        i += 7 * 24 * 60 * 60 * 1000;
    } while (i < axes.xaxis.max);

    return markings;
}

function loadHeaders(table) {
    var headers = [];
    table.find('th').each(function() {
        headers.push( $(this).text() )
    });
    return headers;
}

// returns an array of dictionarys, each with a label, a color and a data key
function loadData(table, columns) {
    var data     = [];
    var headers  = loadHeaders(table);

    var t_offset = 0;
    for (var i=0; i<headers.length; i++) {
        var name = headers[i];
        if ('Time' == name)
            t_offset=i;
        else
            data.push({ label: name, data: [] });

    }

    table.find('tr').each(function() {
        time   = $(this).find('td:eq('+t_offset+')').text();
        $(this).find('td:not(:eq('+t_offset+'))').each(function(i) {
            data[i]['color'] = i; // give each series a unique colour
            data[i]['data'].push([time, $(this).text()])
        })
    })

    // Filter the data by selected columns
    // use all columns by default
    if (columns && columns.length>0) {
        var tmp = [];
        // filter out stuff not in columns
        $.each(data, function(i){
            if ($.inArray(data[i]['label'], columns))
                tmp.push(data[i])
        })
        data = tmp;
    }
    return data;
}

function createCheckBoxes(choices, data) {
     $.each(data, function(i) {
            name = data[i]['label'];
            choices.append('
<input type="checkbox" name="' + name +
                                   '" offset="'+ i +
                                   '" checked="checked" id="id' + name  + '">' +
                                   ''
                                    + name + '');
        });

}

function show(element) {
    element.show();
    element.css('visibility', 'visible');
    element.css('display',    'block');
}

function hide(element) {
    element.hide();
    element.css('visibility', 'collapse');
    element.css('display',    'none');
}

function createPlotFunctionFromTable(table, chart, overview, choices, options, columns) {

    var data    = loadData(table, columns);

    var plotFunction = createPlotFunction(data,chart, overview, choices, options, columns);
    if (choices) {
        if (data.length>1) {
            createCheckBoxes(choices, data);
            choices.find("input").click(plotFunction);
            show(choices);
        } else {
            hide(choices);
        }
    }

    return plotFunction;
}

function createOverviewObject(data, chart, overview, overview_options) {
    if (!overview_options) {
        overview_options = {
                series: {
                    lines: { show: true, lineWidth: 1 },
                    shadowSize: 0
                },
                xaxis: { ticks: [], mode: "time" },
                yaxis: { ticks: [], min: 0, autoscaleMargin: 0.1 },
                selection: { mode: "x" }
        };
    }

    // strip out the labels
    var overview_data = [];
    for (var i=0; i<data.length; i++) {
        overview_data[i] = { color:i, data:data[i]['data'] }
    }
    // render the overview
    return $.plot(overview, overview_data, overview_options);

}

function createPlotFunction(data, chart, overview, choices, options, columns) {
        var stored_ranges;
        var plotFunction = function() {
                var live_data = [];

                // if there's more than one choice
                // then filter by checked boxes
                if (choices && data.length>1) {
                    choices.find("input:checked").each(function () {
                                var key = $(this).attr("offset");
                                if (key && data[key])
                                    live_data.push(data[key]);
                            });

                // otherwise just use all the data
                } else {
                    live_data = data;
                }

                // create the plot
                var plot = $.plot(chart, live_data, options);

                // ... create the overview plot if possible
                var ovplot;

                if (overview) {
                    ovplot = createOverviewObject(live_data, chart, overview);
                    show(overview);
                }

                var plotRangeFunction = function (event, ranges) {
                    // do the zooming
                    plot = $.plot(chart, live_data,
                                  $.extend(true, {}, options, {
                                          xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to }
                                          }
                                  )
                             );

                    if (ovplot) {
                        // don't fire event on the overview to prevent eternal loop
                        ovplot.setSelection(ranges, true);
                    }
                    // store the range incase we get recalled when the choices change
                    stored_ranges = ranges;
                }

                var ovRangeFunction = function (event, ranges) {
                     plot.setSelection(ranges);
                     // store the range incase we get recalled when the choices change
                     stored_ranges = ranges;
                }

                // now connect the two
                chart.bind("plotselected", plotRangeFunction);
                if (overview) {
                     overview.bind("plotselected", ovRangeFunction);
                }

                // if we have stored ranges then trigger the selections
                if (stored_ranges) {
                    plot.setSelection(stored_ranges);
                    if (ovplot)
                        ovplot.setSelection(stored_ranges, false);
                }

        }

        return plotFunction;
}
<commit_msg>Add a comment about having alternative x axes<commit_after>/*
 * Copyright (c) 2009 Simon Wistow <simon@thegestalt.org>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/**
 * Usage:
 *
 * Create a table with headers and cells containing data. One of the headers must be 'Time'
 *
 *

 *

 *            Time	Visits	ResponseTime
 *

 *

 *            1196463600000	1	200
 *

  *  .... etc ....
 *

 *
 *  Then, in your main html file include this file plus jquery.flot.js and jquery.flot.selection.js
 *  Then create divs with the ids: 'chart', 'overview' and 'choices' (or whatever you want to call them)
 *  and insert this Javascript.
 *
 *
 *
 *
 *  Feel free to customise as necessary.
 */

// helper for returning the weekends in a period
function weekendAreas(axes) {
    var markings = [];
    var d = new Date(axes.xaxis.min);
    // go to the first Saturday
    d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) % 7))
    d.setUTCSeconds(0);
    d.setUTCMinutes(0);
    d.setUTCHours(0);
    var i = d.getTime();
    do {
        // when we don't set yaxis, the rectangle automatically
        // extends to infinity upwards and downwards
        markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000 } });
        i += 7 * 24 * 60 * 60 * 1000;
    } while (i < axes.xaxis.max);

    return markings;
}

function loadHeaders(table) {
    var headers = [];
    table.find('th').each(function() {
        headers.push( $(this).text() )
    });
    return headers;
}

// returns an array of dictionarys, each with a label, a color and a data key
function loadData(table, columns, xaxis) {
    var data     = [];
    var headers  = loadHeaders(table);

    // Theoretically we could use this to make
    // The x axis be configurable. There are two problems
    // with this -
    //
    // Firstly that the display gets messed
    // up because we've set the options of the plot to
    // have a time based x axis although I suspect that
    // could be fixed, especially if we stuck an
    //   Column Name
    // attribute (and defaulted to it being a time or
    // something)
    //
    // Secondly we're starting to have a lots of arguments
    // which could be fixed by switching to named arguments
    // a la sIFR
    //
    if (!xaxis)
        xaxis='Time';

    var t_offset = 0;
    for (var i=0; i<headers.length; i++) {
        var name = headers[i];
        if (xaxis == name)
            x_offset=i;
        else
            data.push({ label: name, data: [] });

    }

    table.find('tr').each(function() {
        time   = $(this).find('td:eq('+x_offset+')').text();
        $(this).find('td:not(:eq('+x_offset+'))').each(function(i) {
            data[i]['color'] = i; // give each series a unique colour
            data[i]['data'].push([time, $(this).text()])
        })
    })

    // Filter the data by selected columns
    // use all columns by default
    if (columns && columns.length>0) {
        var tmp = [];
        // filter out stuff not in columns
        $.each(data, function(i){
            if ($.inArray(data[i]['label'], columns))
                tmp.push(data[i])
        })
        data = tmp;
    }
    return data;
}

function createCheckBoxes(choices, data) {
     $.each(data, function(i) {
            name = data[i]['label'];
            choices.append('
<input type="checkbox" name="' + name +
                                   '" offset="'+ i +
                                   '" checked="checked" id="id' + name  + '">' +
                                   ''
                                    + name + '');
        });

}

function show(element) {
    element.show();
    element.css('visibility', 'visible');
    element.css('display',    'block');
}

function hide(element) {
    element.hide();
    element.css('visibility', 'collapse');
    element.css('display',    'none');
}

function createPlotFunctionFromTable(table, chart, overview, choices, options, columns) {
    var data    = loadData(table, columns);

    var plotFunction = createPlotFunction(data,chart, overview, choices, options, columns);
    if (choices) {
        if (data.length>1) {
            createCheckBoxes(choices, data);
            choices.find("input").click(plotFunction);
            show(choices);
        } else {
            hide(choices);
        }
    }

    return plotFunction;
}

function createOverviewObject(data, chart, overview, overview_options) {
    if (!overview_options) {
        overview_options = {
                series: {
                    lines: { show: true, lineWidth: 1 },
                    shadowSize: 0
                },
                xaxis: { ticks: [], mode: "time" },
                yaxis: { ticks: [], min: 0, autoscaleMargin: 0.1 },
                selection: { mode: "x" }
        };
    }

    // strip out the labels
    var overview_data = [];
    for (var i=0; i<data.length; i++) {
        overview_data[i] = { color:i, data:data[i]['data'] }
    }
    // render the overview
    return $.plot(overview, overview_data, overview_options);

}

function createPlotFunction(data, chart, overview, choices, options, columns) {
        var stored_ranges;
        var plotFunction = function() {
                var live_data = [];

                // if there's more than one choice
                // then filter by checked boxes
                if (choices && data.length>1) {
                    choices.find("input:checked").each(function () {
                                var key = $(this).attr("offset");
                                if (key && data[key])
                                    live_data.push(data[key]);
                            });

                // otherwise just use all the data
                } else {
                    live_data = data;
                }

                // create the plot
                var plot = $.plot(chart, live_data, options);

                // ... create the overview plot if possible
                var ovplot;

                if (overview) {
                    ovplot = createOverviewObject(live_data, chart, overview);
                    show(overview);
                }

                var plotRangeFunction = function (event, ranges) {
                    // do the zooming
                    plot = $.plot(chart, live_data,
                                  $.extend(true, {}, options, {
                                          xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to }
                                          }
                                  )
                             );

                    if (ovplot) {
                        // don't fire event on the overview to prevent eternal loop
                        ovplot.setSelection(ranges, true);
                    }
                    // store the range incase we get recalled when the choices change
                    stored_ranges = ranges;
                }

                var ovRangeFunction = function (event, ranges) {
                     plot.setSelection(ranges);
                     // store the range incase we get recalled when the choices change
                     stored_ranges = ranges;
                }

                // now connect the two
                chart.bind("plotselected", plotRangeFunction);
                if (overview) {
                     overview.bind("plotselected", ovRangeFunction);
                }

                // if we have stored ranges then trigger the selections
                if (stored_ranges) {
                    plot.setSelection(stored_ranges);
                    if (ovplot)
                        ovplot.setSelection(stored_ranges, false);
                }

        }

        return plotFunction;
}
<|endoftext|>


<commit_before>;(function (window, document, undefined) {
  // Underscore implementation of _.defaults
  // https://github.com/jashkenas/underscore/blob/master/underscore.js#L863
  var mergeDefaults = function(obj) {
    Array.prototype.slice.call(arguments, 1).forEach(function(source) {
      if (source) {
        for (var prop in source) {
          if (obj[prop] === void 0 ) obj[prop] = source[prop];
        }
      }
    });
    return obj;
  };

  var defaults = {
    /**
     * Duration to show the notification
     */
    duration: 2500,
    /**
     * Class to add to the generated markup
     */
    class: 'notification',
    /**
     * Parent element to attach notification to
     * @returns {*|HTMLElement}
     */
    parent: function () {
      return document.body;
    },
    /**
     * Type of notification
     * This is the class name that is attached to the element upon creation
     * Intended to be used to control visual clues as to what type of notification
     * is shown.
     */
    type: 'success',
    /**
     * If true notification can be hidden on tap/click
     */
    tapToClose: false,
    /**
     * If true notification is shown immediatley
     */
    show: true,
    /**
     * Duration to delay the destruction of the DOM element created for the notification
     * If you animation is longer than the default increase this time accordingly
     */
    destroyAfter: 500
  };

  /**
   * Simple notification alert meant to be used with PhoneGap apps
   * @param text Text content of the notification
   * @param options Notification Options
   * @constructor
   */

  function Notification(text, options) {
    if (!(this instanceof Notification)) return new Notification(text, options);

    (options = options || {});

    this.options = mergeDefaults(options, defaults);

    this.el = document.createElement('div');
    this.textNode = document.createTextNode((text && typeof text !== 'object') ? text : '');
    this.el.appendChild(this.textNode);

    this.el.classList.add(this.options.class, this.options.type);

    this.parent = typeof this.options.parent === 'function' ? this.options.parent() : this.options.parent;

    this.hideHandler = this.hide.bind(this);

    this.init();
  }

  Notification.prototype = {
    constructor: Notification,
    /**
     * Notification entry point
     */
    init: function () {
      this._setupEvents();

      this.parent.appendChild(this.el);

      if (this.options.show) {
        this.show();
      }
    },

    /**
     * Show the notification manually
     * @returns {Notification}
     */
    show: function () {
      var self = this;

      requestAnimFrame(function() {
        self.el.classList.add('show');
      });

      if (!this.options.tapToClose) setTimeout(this.hide.bind(this), this.options.duration);

      return this;
    },

    /**
     * Hide the notification manually
     * @returns {Notification}
     */
    hide: function () {
      var self = this;

      requestAnimFrame(function() {
        self.el.classList.remove('show');
      });

      setTimeout(this.destroy.bind(this), this.options.destroyAfter);

      return this;
    },

    /**
     * Destroy and remove all attached events manually
     */
    destroy: function () {
      this._destroyEvents();

      this.parent.removeChild(this.el);
    },

    /**
     * Setup and attach events to the notification
     * @returns {Notification}
     * @private
     */
    _setupEvents: function () {
      if (this.options.tapToClose) this.el.addEventListener('touchstart', this.hideHandler);

      return this;
    },

    /**
     * Remove attached events from the notification
     * @returns {Notification}
     * @private
     */
    _destroyEvents: function () {
      this.el.removeEventListener('touchstart', this.hideHandler);

      return this;
    }
  };

  window.Notification = Notification;

  // requestAnimationFrame shim in case of older mobile browsers
  window.requestAnimFrame = (function(){
    return  window.requestAnimationFrame       ||
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame    ||
      window.oRequestAnimationFrame      ||
      window.msRequestAnimationFrame     ||
      function( callback ){
        window.setTimeout(callback, 1000 / 60);
      };
  })();

})(window, document);<commit_msg>fixed rendering bug where iOS would not show initial animation<commit_after>;(function (window, document, undefined) {
  // Underscore implementation of _.defaults
  // https://github.com/jashkenas/underscore/blob/master/underscore.js#L863
  var mergeDefaults = function(obj) {
    Array.prototype.slice.call(arguments, 1).forEach(function(source) {
      if (source) {
        for (var prop in source) {
          if (obj[prop] === void 0 ) obj[prop] = source[prop];
        }
      }
    });
    return obj;
  };

  var defaults = {
    /**
     * Duration to show the notification
     */
    duration: 2500,
    /**
     * Class to add to the generated markup
     */
    class: 'notification',
    /**
     * Parent element to attach notification to
     * @returns {*|HTMLElement}
     */
    parent: function () {
      return document.body;
    },
    /**
     * Type of notification
     * This is the class name that is attached to the element upon creation
     * Intended to be used to control visual clues as to what type of notification
     * is shown.
     */
    type: 'success',
    /**
     * If true notification can be hidden on tap/click
     */
    tapToClose: false,
    /**
     * If true notification is shown immediatley
     */
    show: true,
    /**
     * Duration to delay the destruction of the DOM element created for the notification
     * If you animation is longer than the default increase this time accordingly
     */
    destroyAfter: 500
  };

  /**
   * Simple notification alert meant to be used with PhoneGap apps
   * @param text Text content of the notification
   * @param options Notification Options
   * @constructor
   */

  function Notification(text, options) {
    if (!(this instanceof Notification)) return new Notification(text, options);

    (options = options || {});

    this.options = mergeDefaults(options, defaults);

    this.el = document.createElement('div');
    this.textNode = document.createTextNode((text && typeof text !== 'object') ? text : '');
    this.el.appendChild(this.textNode);

    this.el.classList.add(this.options.class, this.options.type);

    this.parent = typeof this.options.parent === 'function' ? this.options.parent() : this.options.parent;

    this.hideHandler = this.hide.bind(this);

    this.parent.appendChild(this.el);

    this.init();
  }

  Notification.prototype = {
    constructor: Notification,
    /**
     * Notification entry point
     */
    init: function () {
      this._setupEvents();

      if (this.options.show) {
        // For iOS we need to wait for the current stack to clear
        // or the initial animation will not run
        setTimeout(this.show.bind(this), 1);
      }
    },

    /**
     * Show the notification manually
     * @returns {Notification}
     */
    show: function () {
      var self = this;

      requestAnimationFrame(function() {
        self.el.classList.add('show');
      });

      if (!this.options.tapToClose) setTimeout(this.hide.bind(this), this.options.duration);

      return this;
    },

    /**
     * Hide the notification manually
     * @returns {Notification}
     */
    hide: function () {
      var self = this;

      requestAnimationFrame(function() {
        self.el.classList.remove('show');
      });

      setTimeout(this.destroy.bind(this), this.options.destroyAfter);

      return this;
    },

    /**
     * Destroy and remove all attached events manually
     */
    destroy: function () {
      this._destroyEvents();

      this.parent.removeChild(this.el);
    },

    /**
     * Setup and attach events to the notification
     * @returns {Notification}
     * @private
     */
    _setupEvents: function () {
      if (this.options.tapToClose) this.el.addEventListener('touchstart', this.hideHandler);

      return this;
    },

    /**
     * Remove attached events from the notification
     * @returns {Notification}
     * @private
     */
    _destroyEvents: function () {
      this.el.removeEventListener('touchstart', this.hideHandler);

      return this;
    }
  };

  window.Notification = Notification;

})(window, document);<|endoftext|>