<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.LoadingBar = exports.TERMINATING_ANIMATION_TIME = exports.ANIMATION_TIME = exports.PROGRESS_INCREASE = exports.MAX_PROGRESS = exports.UPDATE_TIME = undefined;

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _reactRedux = require('react-redux');

var _loading_bar_ducks = require('./loading_bar_ducks');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var UPDATE_TIME = exports.UPDATE_TIME = 200;
var MAX_PROGRESS = exports.MAX_PROGRESS = 99;
var PROGRESS_INCREASE = exports.PROGRESS_INCREASE = 10;
var ANIMATION_TIME = exports.ANIMATION_TIME = UPDATE_TIME * 4;
var TERMINATING_ANIMATION_TIME = exports.TERMINATING_ANIMATION_TIME = UPDATE_TIME / 2;

var initialState = {
  terminatingAnimationTimeout: null,
  percent: 0,
  progressInterval: null
};

var LoadingBar = exports.LoadingBar = function (_React$Component) {
  _inherits(LoadingBar, _React$Component);

  function LoadingBar(props) {
    _classCallCheck(this, LoadingBar);

    var _this = _possibleConstructorReturn(this, (LoadingBar.__proto__ || Object.getPrototypeOf(LoadingBar)).call(this, props));

    _this.state = _extends({}, initialState, {
      hasMounted: false
    });

    _this.boundSimulateProgress = _this.simulateProgress.bind(_this);
    _this.boundResetProgress = _this.resetProgress.bind(_this);
    return _this;
  }

  _createClass(LoadingBar, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      // Re-render the component after mount to fix problems with SSR and CSP.
      //
      // Apps that use Server Side Rendering and has Content Security Policy
      // for style that doesn't allow inline styles should render an empty div
      // and replace it with the actual Loading Bar after mount
      // See: https://github.com/mironov/react-redux-loading-bar/issues/39
      //
      // eslint-disable-next-line react/no-did-mount-set-state
      this.setState({ hasMounted: true });

      if (this.props.loading > 0) {
        this.launch();
      }
    }
  }, {
    key: 'componentWillReceiveProps',
    value: function componentWillReceiveProps(nextProps) {
      if (this.shouldStart(nextProps)) {
        this.launch();
      } else if (this.shouldStop(nextProps)) {
        if (this.state.percent === 0 && !this.props.showFastActions) {
          // not even shown yet because the action finished quickly after start
          clearInterval(this.state.progressInterval);
          this.resetProgress();
        } else {
          // should progress to 100 percent
          this.setState({ percent: 100 });
        }
      }
    }
  }, {
    key: 'componentWillUnmount',
    value: function componentWillUnmount() {
      clearInterval(this.state.progressInterval);
      clearTimeout(this.state.terminatingAnimationTimeout);
    }
  }, {
    key: 'shouldStart',
    value: function shouldStart(nextProps) {
      return this.props.loading === 0 && nextProps.loading > 0;
    }
  }, {
    key: 'shouldStop',
    value: function shouldStop(nextProps) {
      return this.state.progressInterval && nextProps.loading === 0;
    }
  }, {
    key: 'shouldShow',
    value: function shouldShow() {
      return this.state.percent > 0 && this.state.percent <= 100;
    }
  }, {
    key: 'launch',
    value: function launch() {
      var _state = this.state,
          progressInterval = _state.progressInterval,
          percent = _state.percent;
      var terminatingAnimationTimeout = this.state.terminatingAnimationTimeout;

      var loadingBarNotShown = !progressInterval;
      var terminatingAnimationGoing = percent === 100;

      if (loadingBarNotShown) {
        progressInterval = setInterval(this.boundSimulateProgress, this.props.updateTime);
      }

      if (terminatingAnimationGoing) {
        clearTimeout(terminatingAnimationTimeout);
      }

      percent = 0;

      this.setState({ progressInterval: progressInterval, percent: percent });
    }
  }, {
    key: 'newPercent',
    value: function newPercent() {
      var percent = this.state.percent;
      var progressIncrease = this.props.progressIncrease;

      // Use cos as a smoothing function
      // Can be any function to slow down progress near the 100%

      var smoothedProgressIncrease = progressIncrease * Math.cos(percent * (Math.PI / 2 / 100));

      return percent + smoothedProgressIncrease;
    }
  }, {
    key: 'simulateProgress',
    value: function simulateProgress() {
      var _state2 = this.state,
          progressInterval = _state2.progressInterval,
          percent = _state2.percent,
          terminatingAnimationTimeout = _state2.terminatingAnimationTimeout;
      var maxProgress = this.props.maxProgress;

      if (percent === 100) {
        clearInterval(progressInterval);
        terminatingAnimationTimeout = setTimeout(this.boundResetProgress, TERMINATING_ANIMATION_TIME);
        progressInterval = null;
      } else if (this.newPercent() <= maxProgress) {
        percent = this.newPercent();
      }

      this.setState({ percent: percent, progressInterval: progressInterval, terminatingAnimationTimeout: terminatingAnimationTimeout });
    }
  }, {
    key: 'resetProgress',
    value: function resetProgress() {
      this.setState(initialState);
    }
  }, {
    key: 'buildStyle',
    value: function buildStyle() {
      var animationTime = this.state.percent !== 100 ? ANIMATION_TIME : TERMINATING_ANIMATION_TIME;

      var style = {
        opacity: '1',
        transform: 'scaleX(' + this.state.percent / 100 + ')',
        transformOrigin: 'left',
        transition: 'transform ' + animationTime + 'ms linear',
        width: '100%',
        willChange: 'transform, opacity'

        // Use default styling if there's no CSS class applied
      };if (!this.props.className) {
        style.height = '3px';
        style.backgroundColor = 'red';
        style.position = 'absolute';
      }

      if (this.shouldShow()) {
        style.opacity = '1';
      } else {
        style.opacity = '0';
      }

      return _extends({}, style, this.props.style);
    }
  }, {
    key: 'render',
    value: function render() {
      // In order not to violate strict style CSP it's better to make
      // an extra re-render after component mount
      if (!this.state.hasMounted) {
        return _react2.default.createElement('div', null);
      }

      return _react2.default.createElement(
        'div',
        null,
        _react2.default.createElement('div', { style: this.buildStyle(), className: this.props.className }),
        _react2.default.createElement('div', { style: { display: 'table', clear: 'both' } })
      );
    }
  }]);

  return LoadingBar;
}(_react2.default.Component);

LoadingBar.propTypes = {
  className: _propTypes.string,
  loading: _propTypes.number,
  maxProgress: _propTypes.number,
  progressIncrease: _propTypes.number,
  showFastActions: _propTypes.bool,
  updateTime: _propTypes.number,
  // eslint-disable-next-line react/no-unused-prop-types
  scope: _propTypes.string,
  // eslint-disable-next-line react/forbid-prop-types
  style: _propTypes.object
};

LoadingBar.defaultProps = {
  className: '',
  loading: 0,
  maxProgress: MAX_PROGRESS,
  progressIncrease: PROGRESS_INCREASE,
  showFastActions: false,
  style: {},
  updateTime: UPDATE_TIME,
  scope: _loading_bar_ducks.DEFAULT_SCOPE
};

var mapStateToProps = function mapStateToProps(state, ownProps) {
  return {
    loading: state.loadingBar[ownProps.scope || _loading_bar_ducks.DEFAULT_SCOPE]
  };
};

exports.default = (0, _reactRedux.connect)(mapStateToProps)(LoadingBar);<commit_msg>build<commit_after>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.LoadingBar = exports.TERMINATING_ANIMATION_TIME = exports.ANIMATION_TIME = exports.PROGRESS_INCREASE = exports.MAX_PROGRESS = exports.UPDATE_TIME = undefined;

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _reactRedux = require('react-redux');

var _loading_bar_ducks = require('./loading_bar_ducks');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var UPDATE_TIME = exports.UPDATE_TIME = 200;
var MAX_PROGRESS = exports.MAX_PROGRESS = 99;
var PROGRESS_INCREASE = exports.PROGRESS_INCREASE = 10;
var ANIMATION_TIME = exports.ANIMATION_TIME = UPDATE_TIME * 4;
var TERMINATING_ANIMATION_TIME = exports.TERMINATING_ANIMATION_TIME = UPDATE_TIME / 2;

var initialState = {
  terminatingAnimationTimeout: null,
  percent: 0,
  progressInterval: null
};

var LoadingBar = exports.LoadingBar = function (_React$Component) {
  _inherits(LoadingBar, _React$Component);

  function LoadingBar(props) {
    _classCallCheck(this, LoadingBar);

    var _this = _possibleConstructorReturn(this, (LoadingBar.__proto__ || Object.getPrototypeOf(LoadingBar)).call(this, props));

    _this.state = _extends({}, initialState, {
      hasMounted: false
    });

    _this.boundSimulateProgress = _this.simulateProgress.bind(_this);
    _this.boundResetProgress = _this.resetProgress.bind(_this);
    return _this;
  }

  _createClass(LoadingBar, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      // Re-render the component after mount to fix problems with SSR and CSP.
      //
      // Apps that use Server Side Rendering and has Content Security Policy
      // for style that doesn't allow inline styles should render an empty div
      // and replace it with the actual Loading Bar after mount
      // See: https://github.com/mironov/react-redux-loading-bar/issues/39
      //
      // eslint-disable-next-line react/no-did-mount-set-state
      this.setState({ hasMounted: true });

      console.log('componentDidMount loading', this.props.loading);
      if (this.props.loading > 0) {
        this.launch();
      }
    }
  }, {
    key: 'componentWillReceiveProps',
    value: function componentWillReceiveProps(nextProps) {
      console.log('componentWillReceiveProps shouldStop', this.shouldStop(nextProps));
      if (this.shouldStart(nextProps)) {
        this.launch();
      } else if (this.shouldStop(nextProps)) {
        if (this.state.percent === 0 && !this.props.showFastActions) {
          // not even shown yet because the action finished quickly after start
          clearInterval(this.state.progressInterval);
          this.resetProgress();
        } else {
          // should progress to 100 percent
          this.setState({ percent: 100 });
        }
      }
    }
  }, {
    key: 'componentWillUnmount',
    value: function componentWillUnmount() {
      clearInterval(this.state.progressInterval);
      clearTimeout(this.state.terminatingAnimationTimeout);
    }
  }, {
    key: 'shouldStart',
    value: function shouldStart(nextProps) {
      return this.props.loading === 0 && nextProps.loading > 0;
    }
  }, {
    key: 'shouldStop',
    value: function shouldStop(nextProps) {
      console.log('shouldStop progressInterval', this.state.progressInterval);
      console.log('shouldStop loading', nextProps.loading);
      return this.state.progressInterval && nextProps.loading === 0;
    }
  }, {
    key: 'shouldShow',
    value: function shouldShow() {
      return this.state.percent > 0 && this.state.percent <= 100;
    }
  }, {
    key: 'launch',
    value: function launch() {
      var _state = this.state,
          progressInterval = _state.progressInterval,
          percent = _state.percent;
      var terminatingAnimationTimeout = this.state.terminatingAnimationTimeout;

      var loadingBarNotShown = !progressInterval;
      var terminatingAnimationGoing = percent === 100;

      if (loadingBarNotShown) {
        progressInterval = setInterval(this.boundSimulateProgress, this.props.updateTime);
      }

      if (terminatingAnimationGoing) {
        clearTimeout(terminatingAnimationTimeout);
      }

      percent = 0;

      console.log('launch progressInterval', progressInterval);
      this.setState({ progressInterval: progressInterval, percent: percent });
    }
  }, {
    key: 'newPercent',
    value: function newPercent() {
      var percent = this.state.percent;
      var progressIncrease = this.props.progressIncrease;

      // Use cos as a smoothing function
      // Can be any function to slow down progress near the 100%

      var smoothedProgressIncrease = progressIncrease * Math.cos(percent * (Math.PI / 2 / 100));

      return percent + smoothedProgressIncrease;
    }
  }, {
    key: 'simulateProgress',
    value: function simulateProgress() {
      var _state2 = this.state,
          progressInterval = _state2.progressInterval,
          percent = _state2.percent,
          terminatingAnimationTimeout = _state2.terminatingAnimationTimeout;
      var maxProgress = this.props.maxProgress;

      if (percent === 100) {
        clearInterval(progressInterval);
        terminatingAnimationTimeout = setTimeout(this.boundResetProgress, TERMINATING_ANIMATION_TIME);
        progressInterval = null;
      } else if (this.newPercent() <= maxProgress) {
        percent = this.newPercent();
      }

      console.log('simulateProgress progressInterval', progressInterval);
      this.setState({ percent: percent, progressInterval: progressInterval, terminatingAnimationTimeout: terminatingAnimationTimeout });
    }
  }, {
    key: 'resetProgress',
    value: function resetProgress() {
      this.setState(initialState);
    }
  }, {
    key: 'buildStyle',
    value: function buildStyle() {
      var animationTime = this.state.percent !== 100 ? ANIMATION_TIME : TERMINATING_ANIMATION_TIME;

      var style = {
        opacity: '1',
        transform: 'scaleX(' + this.state.percent / 100 + ')',
        transformOrigin: 'left',
        transition: 'transform ' + animationTime + 'ms linear',
        width: '100%',
        willChange: 'transform, opacity'

        // Use default styling if there's no CSS class applied
      };if (!this.props.className) {
        style.height = '3px';
        style.backgroundColor = 'red';
        style.position = 'absolute';
      }

      if (this.shouldShow()) {
        style.opacity = '1';
      } else {
        style.opacity = '0';
      }

      return _extends({}, style, this.props.style);
    }
  }, {
    key: 'render',
    value: function render() {
      // In order not to violate strict style CSP it's better to make
      // an extra re-render after component mount
      if (!this.state.hasMounted) {
        return _react2.default.createElement('div', null);
      }

      return _react2.default.createElement(
        'div',
        null,
        _react2.default.createElement('div', { style: this.buildStyle(), className: this.props.className }),
        _react2.default.createElement('div', { style: { display: 'table', clear: 'both' } })
      );
    }
  }]);

  return LoadingBar;
}(_react2.default.Component);

LoadingBar.propTypes = {
  className: _propTypes.string,
  loading: _propTypes.number,
  maxProgress: _propTypes.number,
  progressIncrease: _propTypes.number,
  showFastActions: _propTypes.bool,
  updateTime: _propTypes.number,
  // eslint-disable-next-line react/no-unused-prop-types
  scope: _propTypes.string,
  // eslint-disable-next-line react/forbid-prop-types
  style: _propTypes.object
};

LoadingBar.defaultProps = {
  className: '',
  loading: 0,
  maxProgress: MAX_PROGRESS,
  progressIncrease: PROGRESS_INCREASE,
  showFastActions: false,
  style: {},
  updateTime: UPDATE_TIME,
  scope: _loading_bar_ducks.DEFAULT_SCOPE
};

var mapStateToProps = function mapStateToProps(state, ownProps) {
  return {
    loading: state.loadingBar[ownProps.scope || _loading_bar_ducks.DEFAULT_SCOPE]
  };
};

exports.default = (0, _reactRedux.connect)(mapStateToProps)(LoadingBar);<|endoftext|>


<commit_before>import React from 'react';
import { Table, NavLink } from 'reactstrap';

import ProjectListItem from './project-list-item';

const ProjectList = ({ projects }) => {
  const renderProjectListItem = (projects) => {
    return projects.map((project, index) => {
        return (
          <ProjectListItem project = { project } index = { index + 1 }/>
        );
      }
    );
  }

  return (

            #
            Repository
            Project Description
            Technology Stack

          { renderProjectListItem(projects) }

  );
};

export default ProjectList;
<commit_msg>fixed react list key issue<commit_after>import React from 'react';
import { Table, NavLink } from 'reactstrap';

import ProjectListItem from './project-list-item';

const ProjectList = ({ projects }) => {
  const renderProjectListItem = (projects) => {
    return projects.map((project, index) => {
        return (
          <ProjectListItem key = { project.url } project = { project } index = { index + 1 }/>
        );
      }
    );
  }

  return (

            #
            Repository
            Project Description
            Technology Stack

          { renderProjectListItem(projects) }

  );
};

export default ProjectList;
<|endoftext|>


<commit_before>var express = require('express'),
	locationRouter = require("../app/routes/location"),
	flightRouter = require("../app/routes/flight")
	appRouter = express.Router();

appRouter.get('/', function(req, res) {
	res.redirect('/index.html');
});

appRouter.use('/api/location', locationRouter);
appRouter.use('/api/flight', flightRouter);
module.exports = appRouter;<commit_msg>Update backend - config routing.js<commit_after>var express = require('express'),
	locationRouter = require("../app/routes/location"),
	flightRouter = require("../app/routes/flight"),
	passengerRouter = require("../app/routes/passenger")
	appRouter = express.Router();

appRouter.get('/', function(req, res) {
	res.redirect('/index.html');
});

appRouter.use('/api/location', locationRouter);
appRouter.use('/api/flight', flightRouter);
appRouter.use('/api/passenger', passengerRouter);
module.exports = appRouter;<|endoftext|>


<commit_before>/*global cloneInheritVars, createInheritVars, createRegistryWrapper, getValue, inheritVars */

//support zepto.forEach on jQuery
if (!$.fn.forEach) {
  $.fn.forEach = function(iterator, context) {
    $.fn.each.call(this, function(index) {
      iterator.call(context || this, this, index);
    });
  };
}

var viewNameAttributeName = 'data-view-name',
    viewCidAttributeName = 'data-view-cid',
    viewHelperAttributeName = 'data-view-helper';

//view instances
var viewsIndexedByCid = {};

var Thorax = this.Thorax = {
  VERSION: '2.0.0rc1',
  templatePathPrefix: '',
  templates: {},
  //view classes
  Views: {},
  //certain error prone pieces of code (on Android only it seems)
  //are wrapped in a try catch block, then trigger this handler in
  //the catch, with the name of the function or event that was
  //trying to be executed. Override this with a custom handler
  //to debug / log / etc
  onException: function(name, err) {
    throw err;
  }
};

Thorax.View = Backbone.View.extend({
  constructor: function() {
    var response = Backbone.View.apply(this, arguments);
    _.each(inheritVars, function(obj) {
      if (obj.ctor) {
        obj.ctor.call(this, response);
      }
    }, this);
    return response;
  },
  _configure: function(options) {
    var self = this;

    this._objectOptionsByCid = {};
    this._boundDataObjectsByCid = {};

    // Setup object event tracking
    _.each(inheritVars, function(obj) {
      self[obj.name] = [];
    });

    viewsIndexedByCid[this.cid] = this;
    this.children = {};
    this._renderCount = 0;

    //this.options is removed in Thorax.View, we merge passed
    //properties directly with the view and template context
    _.extend(this, options || {});

    // Setup helpers
    bindHelpers.call(this);

    _.each(inheritVars, function(obj) {
      if (obj.configure) {
        obj.configure.call(this);
      }
    }, this);
  },

  setElement : function() {
    var response = Backbone.View.prototype.setElement.apply(this, arguments);
    this.name && this.$el.attr(viewNameAttributeName, this.name);
    this.$el.attr(viewCidAttributeName, this.cid);
    return response;
  },

  _addChild: function(view) {
    this.children[view.cid] = view;
    if (!view.parent) {
      view.parent = this;
    }
    this.trigger('child', view);
    return view;
  },

  _removeChild: function(view) {
    delete this.children[view.cid];
    view.parent = null;
    return view;
  },

  destroy: function(options) {
    options = _.defaults(options || {}, {
      children: true
    });
    _.each(this._boundDataObjectsByCid, this.unbindDataObject, this);
    this.trigger('destroyed');
    delete viewsIndexedByCid[this.cid];
    _.each(this.children, function(child) {
      this._removeChild(child);
      if (options.children) {
        child.destroy();
      }
    }, this);
    if (this.parent) {
      this.parent._removeChild(this);
    }
    this.remove(); // Will call stopListening()
  },

  render: function(output) {
    this._previousHelpers = _.filter(this.children, function(child) { return child._helperOptions; });

    var children = {};
    _.each(this.children, function(child, key) {
      if (!child._helperOptions) {
        children[key] = child;
      }
    });
    this.children = children;

    if (_.isUndefined(output) || (!_.isElement(output) && !Thorax.Util.is$(output) && !(output && output.el) && !_.isString(output) && typeof !_.isFunction(output))) {
      // try one more time to assign the template, if we don't
      // yet have one we must raise
      assignTemplate.call(this, 'template', {
        required: true
      });
      output = this.renderTemplate(this.template);
    } else if (_.isFunction(output)) {
      output = this.renderTemplate(output);
    }

    // Destroy any helpers that may be lingering
    _.each(this._previousHelpers, function(child) {
      child.destroy();
      child.parent = undefined;
    });
    this._previousHelpers = undefined;

    //accept a view, string, Handlebars.SafeString or DOM element
    this.html((output && output.el) || (output && output.string) || output);
    ++this._renderCount;
    this.trigger('rendered');
    return output;
  },

  context: function() {
    return (this.model && this.model.attributes) || {};
  },

  _getContext: function() {
    return _.extend({}, this, getValue(this, 'context') || {});
  },

  // Private variables in handlebars / options.data in template helpers
  _getData: function(data) {
    return {
      view: this,
      cid: _.uniqueId('t'),
      yield: function() {
        // fn is seeded by template helper passing context to data
        return data.fn && data.fn(data);
      }
    };
  },

  _getHelpers: function() {
    if (this.helpers) {
      return _.extend({}, Handlebars.helpers, this.helpers);
    } else {
      return Handlebars.helpers;
    }

  },

  renderTemplate: function(file, context, ignoreErrors) {
    var template;
    context = context || this._getContext();
    if (_.isFunction(file)) {
      template = file;
    } else {
      template = Thorax.Util.getTemplate(file, ignoreErrors);
    }
    if (!template) {
      return '';
    } else {
      return template(context, {
        helpers: this._getHelpers(),
        data: this._getData(context)
      });
    }
  },

  ensureRendered: function() {
    !this._renderCount && this.render();
  },

  appendTo: function(el) {
    this.ensureRendered();
    $(el).append(this.el);
    this.trigger('ready', {target: this});
  },

  html: function(html) {
    if (_.isUndefined(html)) {
      return this.el.innerHTML;
    } else {
      // Event for IE element fixes
      this.trigger('before:append');
      var element = this._replaceHTML(html);
      this.trigger('append');
      return element;
    }
  },

  _replaceHTML: function(html) {
    this.el.innerHTML = "";
    return this.$el.append(html);
  },

  _anchorClick: function(event) {
    var target = $(event.currentTarget),
        href = target.attr('href');
    // Route anything that starts with # or / (excluding //domain urls)
    if (href && (href[0] === '#' || (href[0] === '/' && href[1] !== '/'))) {
      Backbone.history.navigate(href, {
        trigger: true
      });
      return false;
    }
    return true;
  }
});

Thorax.View.extend = function() {
  createInheritVars(this);

  var child = Backbone.View.extend.apply(this, arguments);
  child.__parent__ = this;

  resetInheritVars(child);

  return child;
};

createRegistryWrapper(Thorax.View, Thorax.Views);

function bindHelpers() {
  if (this.helpers) {
    _.each(this.helpers, function(helper, name) {
      var view = this;
      this.helpers[name] = function() {
        var args = _.toArray(arguments),
            options = _.last(args);
        options.context = this;
        return helper.apply(view, args);
      };
    }, this);
  }
}

//$(selector).view() helper
$.fn.view = function(options) {
  options = _.defaults(options || {}, {
    helper: true
  });
  var selector = '[' + viewCidAttributeName + ']';
  if (!options.helper) {
    selector += ':not([' + viewHelperAttributeName + '])';
  }
  var el = $(this).closest(selector);
  return (el && viewsIndexedByCid[el.attr(viewCidAttributeName)]) || false;
};
<commit_msg>Remove erroneous typeof<commit_after>/*global cloneInheritVars, createInheritVars, createRegistryWrapper, getValue, inheritVars */

//support zepto.forEach on jQuery
if (!$.fn.forEach) {
  $.fn.forEach = function(iterator, context) {
    $.fn.each.call(this, function(index) {
      iterator.call(context || this, this, index);
    });
  };
}

var viewNameAttributeName = 'data-view-name',
    viewCidAttributeName = 'data-view-cid',
    viewHelperAttributeName = 'data-view-helper';

//view instances
var viewsIndexedByCid = {};

var Thorax = this.Thorax = {
  VERSION: '2.0.0rc1',
  templatePathPrefix: '',
  templates: {},
  //view classes
  Views: {},
  //certain error prone pieces of code (on Android only it seems)
  //are wrapped in a try catch block, then trigger this handler in
  //the catch, with the name of the function or event that was
  //trying to be executed. Override this with a custom handler
  //to debug / log / etc
  onException: function(name, err) {
    throw err;
  }
};

Thorax.View = Backbone.View.extend({
  constructor: function() {
    var response = Backbone.View.apply(this, arguments);
    _.each(inheritVars, function(obj) {
      if (obj.ctor) {
        obj.ctor.call(this, response);
      }
    }, this);
    return response;
  },
  _configure: function(options) {
    var self = this;

    this._objectOptionsByCid = {};
    this._boundDataObjectsByCid = {};

    // Setup object event tracking
    _.each(inheritVars, function(obj) {
      self[obj.name] = [];
    });

    viewsIndexedByCid[this.cid] = this;
    this.children = {};
    this._renderCount = 0;

    //this.options is removed in Thorax.View, we merge passed
    //properties directly with the view and template context
    _.extend(this, options || {});

    // Setup helpers
    bindHelpers.call(this);

    _.each(inheritVars, function(obj) {
      if (obj.configure) {
        obj.configure.call(this);
      }
    }, this);
  },

  setElement : function() {
    var response = Backbone.View.prototype.setElement.apply(this, arguments);
    this.name && this.$el.attr(viewNameAttributeName, this.name);
    this.$el.attr(viewCidAttributeName, this.cid);
    return response;
  },

  _addChild: function(view) {
    this.children[view.cid] = view;
    if (!view.parent) {
      view.parent = this;
    }
    this.trigger('child', view);
    return view;
  },

  _removeChild: function(view) {
    delete this.children[view.cid];
    view.parent = null;
    return view;
  },

  destroy: function(options) {
    options = _.defaults(options || {}, {
      children: true
    });
    _.each(this._boundDataObjectsByCid, this.unbindDataObject, this);
    this.trigger('destroyed');
    delete viewsIndexedByCid[this.cid];
    _.each(this.children, function(child) {
      this._removeChild(child);
      if (options.children) {
        child.destroy();
      }
    }, this);
    if (this.parent) {
      this.parent._removeChild(this);
    }
    this.remove(); // Will call stopListening()
  },

  render: function(output) {
    this._previousHelpers = _.filter(this.children, function(child) { return child._helperOptions; });

    var children = {};
    _.each(this.children, function(child, key) {
      if (!child._helperOptions) {
        children[key] = child;
      }
    });
    this.children = children;

    if (_.isUndefined(output) || (!_.isElement(output) && !Thorax.Util.is$(output) && !(output && output.el) && !_.isString(output) && !_.isFunction(output))) {
      // try one more time to assign the template, if we don't
      // yet have one we must raise
      assignTemplate.call(this, 'template', {
        required: true
      });
      output = this.renderTemplate(this.template);
    } else if (_.isFunction(output)) {
      output = this.renderTemplate(output);
    }

    // Destroy any helpers that may be lingering
    _.each(this._previousHelpers, function(child) {
      child.destroy();
      child.parent = undefined;
    });
    this._previousHelpers = undefined;

    //accept a view, string, Handlebars.SafeString or DOM element
    this.html((output && output.el) || (output && output.string) || output);
    ++this._renderCount;
    this.trigger('rendered');
    return output;
  },

  context: function() {
    return (this.model && this.model.attributes) || {};
  },

  _getContext: function() {
    return _.extend({}, this, getValue(this, 'context') || {});
  },

  // Private variables in handlebars / options.data in template helpers
  _getData: function(data) {
    return {
      view: this,
      cid: _.uniqueId('t'),
      yield: function() {
        // fn is seeded by template helper passing context to data
        return data.fn && data.fn(data);
      }
    };
  },

  _getHelpers: function() {
    if (this.helpers) {
      return _.extend({}, Handlebars.helpers, this.helpers);
    } else {
      return Handlebars.helpers;
    }

  },

  renderTemplate: function(file, context, ignoreErrors) {
    var template;
    context = context || this._getContext();
    if (_.isFunction(file)) {
      template = file;
    } else {
      template = Thorax.Util.getTemplate(file, ignoreErrors);
    }
    if (!template) {
      return '';
    } else {
      return template(context, {
        helpers: this._getHelpers(),
        data: this._getData(context)
      });
    }
  },

  ensureRendered: function() {
    !this._renderCount && this.render();
  },

  appendTo: function(el) {
    this.ensureRendered();
    $(el).append(this.el);
    this.trigger('ready', {target: this});
  },

  html: function(html) {
    if (_.isUndefined(html)) {
      return this.el.innerHTML;
    } else {
      // Event for IE element fixes
      this.trigger('before:append');
      var element = this._replaceHTML(html);
      this.trigger('append');
      return element;
    }
  },

  _replaceHTML: function(html) {
    this.el.innerHTML = "";
    return this.$el.append(html);
  },

  _anchorClick: function(event) {
    var target = $(event.currentTarget),
        href = target.attr('href');
    // Route anything that starts with # or / (excluding //domain urls)
    if (href && (href[0] === '#' || (href[0] === '/' && href[1] !== '/'))) {
      Backbone.history.navigate(href, {
        trigger: true
      });
      return false;
    }
    return true;
  }
});

Thorax.View.extend = function() {
  createInheritVars(this);

  var child = Backbone.View.extend.apply(this, arguments);
  child.__parent__ = this;

  resetInheritVars(child);

  return child;
};

createRegistryWrapper(Thorax.View, Thorax.Views);

function bindHelpers() {
  if (this.helpers) {
    _.each(this.helpers, function(helper, name) {
      var view = this;
      this.helpers[name] = function() {
        var args = _.toArray(arguments),
            options = _.last(args);
        options.context = this;
        return helper.apply(view, args);
      };
    }, this);
  }
}

//$(selector).view() helper
$.fn.view = function(options) {
  options = _.defaults(options || {}, {
    helper: true
  });
  var selector = '[' + viewCidAttributeName + ']';
  if (!options.helper) {
    selector += ':not([' + viewHelperAttributeName + '])';
  }
  var el = $(this).closest(selector);
  return (el && viewsIndexedByCid[el.attr(viewCidAttributeName)]) || false;
};
<|endoftext|>


<commit_before>/* The deKardashianier
 * This is the code that does all the work on HuffingtonPost pages to remove things you might not want to keep up with
 * The names of the elements would need to be changed for this code to work on other sites
 * Of course changes to the HuffPo site could break some or all of the patterns I've coded to
 *
 * Description of patterns in HuffPo pages:
 *
 * Containing Element                       Elements to Match On
 * -------------------------------------------------------------
 * #center_entries_container                div.entry
 * #rc_lower                                div.entry
 * #recent-blogs-overflow-container-right   div.entry
 * div.widget_children                      div.related_news_item
 * div.most_popular_entry_wrapper           div.most_popular_entry_wrapper
 * div.snp_most_popular_entry               div.snp_most_popular_entry
 * div.big_news_pages_story                 div.big_news_pages_story
 * div.big_news_pages_story-fp              div.big_news_pages_story-fp
 * div.menu                                 li
 * div.mp_cycle                             li
 * td                                       div
 * article                                  article
 * div.entry                                h4.subhead
 *
 * Elements that show up in individual article pages but not in category or home pages (things get messy here)
 * An optimization could be to only do the scans that are necessary on the particular page type
 *
 * span.entrytag                            span.entrytag
 * section.around-the-web                   p
 * li.hp_carousel_item                      li.hp_carousel_item
 * li.grv_article                           li.grv_article
 *
 * Most things are well contained except for that last one where a subhead containing links to other articles
 * is stuffed into the bottom of a div.entry
 *
 * In individual articles the "entry" class is combined with "wrapper" or "column" but these should NOT be removed
 */

console.log("dekardashianizer.js");

var Kards = 0; // How many things we remove. Will be an overestimate since there could be multiple elements with a common ancestor
var Keywords = []; // initialize here to establish scope
var divEntry = "div.entry:not('div.wrapper,div.column')"; // qualified div.entry
var HTMLelements = [ // various possible elements that could contain the keywords we're looking for
  "span.entrytag",
  "li.hp_carousel_item",
  "li.grv_article",
  "div.related_news_item",
  "div.most_popular_entry_wrapper",
  "div.snp_most_popular_entry",
  "div.big_news_pages_story",
  "div.big_news_pages_story-fp",
  "div.trc_spotlight_item",
  "article:not('article.entry')",
  divEntry
]; // ORDER MATTERS! We want to delete from small to big to avoid over-eager deletions

var fgtimer = 300000; // 5 minutes between retries when window is visible
var bgtimer = 60000; // 1 minute between retries when window is not visible (in case it becomes visible)
var dbg = false; // debug switch

$('body').keyup( function(e){ // Extra goodie, bind ESC key to close any open lightbox
  if (e.keyCode==27){         // This has nothing to do with deKardashinizing but it's a feature that HuffPo needs :)
    $('div.qr_close_a').trigger('click');
  }
});

$.expr[":"].cicontains = $.expr.createPseudo(function(arg) { // extend jQuery with a case insensitive contains function
  return function( elem ) {
    return $(elem).text().toLowerCase().indexOf(arg.toLowerCase()) >= 0;
  };
});

$.fn.nuke = function(){ // extend jQuery with a function that removes offending elements
  Kards += this.length; // increment the removal counter.
  if (dbg){
    if ( this.length > 0 ){ console.log(this);}
    this.css("background-color","red"); // wonderful for debugging as an alternative to .remove()
  }
  else {
    this.remove();
  }
}

function scanner(element, index, array){ // the function that actually examines elements and decides which to nuke
  var matchOn = ":cicontains("+element+")"; // set up case insensitive matching
  var selector = "li"+matchOn; // menu items
  $('div.menu').find(selector).nuke();

  $('div.mp_cycle').find(selector).nuke(); // Most popular articles (also a list)

  selector = "div"+matchOn;
  $('td').find(selector).nuke(); // weird 3rd party articles in right column which use tables for layout. It's 2014 people!

  selector = "h4"+matchOn; // "more" teasers that are unfortunately stuffed into the bottom of div.entry elements
  $(divEntry).find(selector).nuke();

  selector = "p"+matchOn; // "around the web" items, these are in paragraphs inside a section
  $('section.around-the-web').find(selector).nuke();

  HTMLelements.forEach( function (el,i) {
    selector = el+matchOn;
    $(selector).nuke();
  });
  return;
}

chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { // this listener is required to get the Keywords over from
  Keywords = request.Keywords;                                                  // localStorage in the context of the popup and background script
  if (dbg) {
    console.log("Received keywords from background script.");
    console.log(Keywords);
  }
  if ( typeof(Keywords)=="object" && Keywords.length>0 ){
    deKardashianize();
  }
  else if ( itypeof(Keywords)=="object" && Keywords.length==0 ) {
    console.log("List of Keywords is empty!");
  }
  else {
    console.log("'Keywords' is of type "+typeof(Keywords)+" should be 'object'");
  }
  return;
});

function deKardashianize(){ // This is just the supervisor function
  if ( !document.webkitHidden ) {
    var startTime = (new Date).getTime();
    console.log('deKardashianizing!');
    Kards = 0;
    Keywords.forEach(scanner);
    console.log(' Removed '+Kards+' things I didn\'t need to keep up with in '
      +((new Date).getTime()-startTime)/1000+' seconds!'); // eventually want to show a count on the pageAction icon
    setTimeout( function(){deKardashianize();},fgtimer);
  }
  else {
    setTimeout( function(){deKardashianize();},bgtimer);
  }
}

/* I tried triggering on changes to the DOM but HuffPo updates the DOM as often as every 2 seconds, sometimes even faster
 * That would have been wasteful. HuffPo seems to be quite expensive in terms of CPU and RAM when visible
 * At least it quiesces when invisible
 */
<commit_msg>Misc code cleanup<commit_after>/* The deKardashianier
 * This is the code that does all the work on HuffingtonPost pages to remove things you might not want to keep up with
 * The names of the elements would need to be changed for this code to work on other sites
 * Of course changes to the HuffPo site could break some or all of the patterns I've coded to
 *
 * Description of patterns in HuffPo pages:
 *
 * Containing Element                       Elements to Match On
 * -------------------------------------------------------------
 * #center_entries_container                div.entry
 * #rc_lower                                div.entry
 * #recent-blogs-overflow-container-right   div.entry
 * div.widget_children                      div.related_news_item
 * div.most_popular_entry_wrapper           div.most_popular_entry_wrapper
 * div.snp_most_popular_entry               div.snp_most_popular_entry
 * div.big_news_pages_story                 div.big_news_pages_story
 * div.big_news_pages_story-fp              div.big_news_pages_story-fp
 * div.menu                                 li
 * div.mp_cycle                             li
 * td                                       div
 * article                                  article
 * div.entry                                h4.subhead
 *
 * Elements that show up in individual article pages but not in category or home pages (things get messy here)
 * An optimization would be to only do the scans that are necessary on the particular page type
 *
 * span.entrytag                            span.entrytag
 * section.around-the-web                   p
 * li.hp_carousel_item                      li.hp_carousel_item
 * li.grv_article                           li.grv_article
 *
 * Most things are well contained except for that last one where a subhead containing links to other articles
 * is stuffed into the bottom of a div.entry
 *
 * In individual articles the "entry" class is combined with "wrapper" or "column" but these should NOT be removed
 */

console.log("dekardashianizer.js");

var Kards = 0; // How many things we remove. Will be an overestimate since there could be multiple elements with a common ancestor
var Keywords = []; // initialize here to establish scope
var divEntry = "div.entry:not('div.wrapper,div.column')"; // qualified div.entry
var HTMLelements = [ // various possible elements that could contain the keywords we're looking for
  "span.entrytag",
  "li.hp_carousel_item",
  "li.grv_article",
  "div.related_news_item",
  "div.most_popular_entry_wrapper",
  "div.snp_most_popular_entry",
  "div.big_news_pages_story",
  "div.big_news_pages_story-fp",
  "div.trc_spotlight_item",
  "article:not('article.entry')",
  divEntry
]; // ORDER MATTERS! We want to delete from small to big to avoid over-eager deletions

var fgtimer = 300000; // 5 minutes between retries when window is visible
var bgtimer =  60000; // 1 minute between retries when window is not visible (in case it becomes visible)
var dbg = false; // debug switch

$('body').keyup( function(e){ // Extra goodie, bind ESC key to close any open lightbox
  if (e.keyCode==27){         // This has nothing to do with deKardashinizing but it's a feature that HuffPo needs :)
    $('div.qr_close_a').trigger('click');
  }
});

$.expr[":"].cicontains = $.expr.createPseudo( function(arg) { // extend jQuery with a case insensitive contains function
  return function( elem ) {
    return $(elem).text().toLowerCase().indexOf(arg.toLowerCase()) >= 0;
  };
});

$.fn.nuke = function(){ // extend jQuery with a function that removes offending elements
  Kards += this.length; // increment the removal counter.
  if (dbg){
    if ( this.length > 0 ){ console.log(this);}
    this.css("background-color","red"); // wonderful for debugging as an alternative to .remove()
  }
  else {
    this.remove();
  }
}

function scanner(element, index, array){ // the function that actually examines elements and decides which to nuke
  var matchOn = ":cicontains("+element+")"; // set up case insensitive matching
  var selector = "li"+matchOn; // menu items
  $('div.menu').find(selector).nuke();

  $('div.mp_cycle').find(selector).nuke(); // Most popular articles (also a list)

  selector = "div"+matchOn;
  $('td').find(selector).nuke(); // weird 3rd party articles in right column which use tables for layout. It's 2014 people!

  selector = "h4"+matchOn; // "more" teasers that are unfortunately stuffed into the bottom of div.entry elements
  $(divEntry).find(selector).nuke();

  selector = "p"+matchOn; // "around the web" items, these are in paragraphs inside a section
  $('section.around-the-web').find(selector).nuke();

  HTMLelements.forEach( function (el,i) {
    selector = el+matchOn;
    $(selector).nuke();
  });
  return;
}

chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { // this listener is required to get the Keywords over from
  Keywords = request.Keywords;                                                  // localStorage in the context of the popup and background script
  if (dbg) {
    console.log("Received keywords from background script.");
    console.log(Keywords);
  }
  if ( typeof(Keywords)=="object" && Keywords.length>0 ){
    deKardashianize();
  }
  else if ( itypeof(Keywords)=="object" && Keywords.length==0 ) {
    console.log("List of Keywords is empty!");
  }
  else {
    console.log("'Keywords' is of type "+typeof(Keywords)+" should be 'object'");
  }
  return;
});

function deKardashianize(){ // This is just the supervisor function
  if ( !document.webkitHidden ) {
    var startTime = (new Date).getTime();
    console.log('deKardashianizing!');
    Kards = 0;
    Keywords.forEach(scanner);
    console.log(' Removed '+Kards+' things I didn\'t need to keep up with in '
      +((new Date).getTime()-startTime)/1000+' seconds!'); // eventually want to show a count on the pageAction icon
    setTimeout( function(){deKardashianize();},fgtimer);
  }
  else {
    setTimeout( function(){deKardashianize();},bgtimer);
  }
}

/* I tried triggering on changes to the DOM but HuffPo updates the DOM as often as every 2 seconds
 * That would have been wasteful. HuffPo seems to be quite expensive in terms of CPU and RAM when visible
 * At least it quiesces when the tab is not visible
 */
<|endoftext|>


<commit_before>  $(function() {
    if(urlParam('viewer_pane') === '1'){
      console.log('*********************** AJAX MODE ***********************');
      var $pageBody = $('body');
      window.loggedIn = false;
      // Intercept all link clicks
      window.asyncClickHandler = function(e) {
        e.preventDefault();
        // Grab the url from the anchor tag
        var url = $(this).attr('href');
        return window.replacePage(url);
      }

      function rerenderBody(html){
        var body = html.replace(/^[\S\s]*]*?>/i, "").replace(/<\/body[\S\s]*$/i, "");
        $pageBody.html(body);
        window.bindGlobalClickHandler();
        window.searchHandler(jQuery);
        window.packageVersionToggleHandler(jQuery);
        window.scrollTo(0,0);
        MathJax.Hub.Queue(["Typeset",MathJax.Hub])
        return false;
      }

      /************************************************************************************************************************************************
      rebinding and executing trough ajax requests
      ************************************************************************************************************************************************/

      window.bindGlobalClickHandler = function(){
        $('a:not(.js-external)').unbind('click', window.asyncClickHandler);
        $('a:not(.js-external)').bind('click', window.asyncClickHandler);
        $('#js-examples').unbind('click',window.runExamples);
        $('#js-examples').bind('click',window.runExamples);
        $('#js-install').unbind('click',window.installpackage);
        $('#js-install').bind('click',window.installpackage);
        $('#js-hideviewer').unbind('click',window.hideViewer);
        $('#js-hideviewer').bind('click',window.hideViewer);
        $('#js-makedefault').unbind('click',window.setDefault);
        $('#js-makedefault').bind('click',window.setDefault);
        $( "form" ).submit(function( event ) {
            event.preventDefault();
            var action = $("form")[0].action;
            var type = "GET";
            if (typeof $("form")[1] != 'undefined'){
              action = $("form")[1].action;
              type = "POST";
            }
            var dataToWrite= $(this).serialize();
            $.ajax({
              type: type,
              url: action,
              data: dataToWrite,
              contentType:"application/x-www-form-urlencoded",
              crossDomain:true,
              xhrFields: {
                withCredentials: true
              }
            }).then(function(html,textData,xhr){
              if(action.indexOf("/login")>-1 && !window.loggedIn){
                window.loggedIn=true;
                _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),
                  ["write('"+dataToWrite+"', file = paste0(.libPaths()[1],'/Rdocumentation/config/creds.txt')) \n Rdocumentation::login()"])
                .then(rerenderBody(html));
              }
              else{
                rerenderBody(html);
              }
            });
        });
      };

      // Helper function to grab new HTML
      // and replace the content
      window.replacePage = function(url) {
        if(url.indexOf('#')==0){
          url = url.substring(1,url.length);
          document.getElementById(url).scrollIntoView();
        }
        else{
          url = url.replace("../","");
          if(url.charAt(0)!="/"){
            url="/"+url;
          }
          var base = $('base').attr('href');
          if(url.indexOf('?')>-1){
            url = url + '&viewer_pane=1&Rstudio_XS_Secret=' + urlParam("Rstudio_XS_Secret")+"&Rstudio_port=" + urlParam("Rstudio_port");
          }
          else{
            url=url+'?viewer_pane=1&Rstudio_XS_Secret=' + urlParam("Rstudio_XS_Secret")+"&Rstudio_port=" + urlParam("Rstudio_port");
          }
          return $.ajax({
            type: 'GET',
            url : url,
            cache: false,
            dataType: 'html',
            xhrFields: {
              withCredentials: true
            }
          })
          .then(rerenderBody);
        }

      };

            /************************************************************************************************************************************************
      button press functions (running examples, installing packages);
      ************************************************************************************************************************************************/
      window.runExamples=function(e){
        console.log("called");
        e.preventDefault();
        var package="";
        $('a').attr('href',function(i,link){
          if(typeof link != "undefined" && link.indexOf("/packages/")>=0 && link.indexOf("/versions/">0)){
            package=link.substring(link.indexOf("/packages/")+10,link.indexOf("/versions/"))
          }
        });
        window.checkPackageVersion(package).then(function(installed){
          if(installed!=false){
            var examples= $('.topic').find('.topic--title').filter(function(i,el){
              return $(this).text()=="Examples";
            }).parent().find('.R').text();
            _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),["require("+package+")\n"+examples])
          }
        });
        return false;
      };

      window.setDefault=function(e){
        e.preventDefault();
        _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),["Rdocumentation::makeDefault()"]);
        return false;
      };
      window.hideViewer=function(e){
        e.preventDefault();
        _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),["Rdocumentation::hideViewer()"]);
        return false;
      };
      /************************************************************************************************************************************************
      checking installation of package and package version
      ************************************************************************************************************************************************/

      window.checkPackageVersion=function(package){
        var installed =true;
        var found=false;
        return _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),["check_package('"+package+"')"])
        .then(function(){
          return _rStudioRequest('/events/get_events','get_events',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),[0])
          .then(function(result){
            for(var i=0;i<result.result.length;i++){
              if(typeof result.result[i] != "undefined" && result.result[i].type=="console_output"){
                if(result.result[i].data.indexOf("FALSE\n")>0){
                  installed = false;
                }
                else{
                  installed=result.result[i].data;
                }
                found=true;
              }
            }
            //Rstudio runs the get_events request periodically. It could happen that we accidently missed the response(small chance), so run it again then
            if(!found){
              installed = window.checkPackageVersion(package);
            }
            return installed;
          })
        });
      };

      window.packageVersionControl=function(){
        var versions = $('#packageVersionSelect').find('option');
        if(versions.length>0){
          var packageInfo=$('.versionCheck> p:eq(0)').text().trim();
          var packageName=packageInfo.split(',')[0];
          window.checkPackageVersion(packageName).then(function(installed){
            if(installed==false){
              $('.versionCheck').append('<button type="button" id="js-install" class="btn btn-primary js-external">Install</button>');
            }
            else{
              installedVersion=installed.split('‘')[1];
              installedVersion=installedVersion.substring(0,installedVersion.length-2).replace('-','.');
              var upToDate=true;
              for(var i=0;i<versions.length;i++){
                if($(versions[i]).text().trim()!="@VERSION@"&& _versionCompare($(versions[i]).text().trim(),installedVersion)){
                  $('.versionCheck').append('<button type="button" id="js-install" class="btn btn-primary js-external">Update</button>');
                  upToDate=false
                }
              }
              if(upToDate){
                $('.versionCheck').text('you currently have the latest version  ');
                $('.versionCheck').append('')
              }
            }
            $('#js-install').unbind('click',window.installpackage);
            $('#js-install').bind('click',window.installpackage);
          });
        }
      };

      window.installpackage=function(e){
        e.preventDefault();
        var packageInfo=$('.versionCheck> p:eq(0)').text().trim();
        var packageName=packageInfo.split(',')[0];
        var packageSource=packageInfo.split(',')[1];
        _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),
                  ["install_package('"+packageName+"',"+packageSource+")"])
        return false;
      };
      //check the packageversion
      window.packageVersionControl();
      window.bindGlobalClickHandler();
      window.scrollTo(0,0);
    }
  });

_rStudioRequest=function(url,method,shared_secret,port,params){
  var data={}
  data["method"]=method;
  //data["params"]=[$('.R').text()];
  data["params"]=params;
  data["clientId"]='33e600bb-c1b1-46bf-b562-ab5cba070b0e';
  data["clientVersion"]="";
  return $.ajax({
    url: 'http://127.0.0.1:'+port+url,
    headers:
    {
        'Accept':'application/json',
        'Content-Type':'application/json',
        'X-Shared-Secret':shared_secret
    },
    type: 'POST',
    dataType: 'json',
    data: JSON.stringify(data),
    processData: false,
    crossDomain:true,
    xhrFields: {
      withCredentials: true
    }
  });
}
_versionCompare = function (v1, v2) {
    v1parts = v1.split(/[.-]+/);
    v2parts = v2.split(/[.-]+/);
    while (v1parts.length < v2parts.length) v1parts.push("0");
    while (v2parts.length < v1parts.length) v2parts.push("0");
    v1parts = v1parts.map(Number);
    v2parts = v2parts.map(Number);
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return true;
        }

        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return true;
        }
        else {
            return false;
        }
    }

    if (v1parts.length != v2parts.length) {
        return false;
    }

    return 0;
}<commit_msg>solved double binding<commit_after>  $(function() {
    if(urlParam('viewer_pane') === '1'){
      console.log('*********************** AJAX MODE ***********************');
      var $pageBody = $('body');
      window.loggedIn = false;
      // Intercept all link clicks
      window.asyncClickHandler = function(e) {
        e.preventDefault();
        // Grab the url from the anchor tag
        var url = $(this).attr('href');
        return window.replacePage(url);
      }

      function rerenderBody(html){
        var body = html.replace(/^[\S\s]*]*?>/i, "").replace(/<\/body[\S\s]*$/i, "");
        $pageBody.html(body);
        window.bindGlobalClickHandler();
        window.searchHandler(jQuery);
        window.packageVersionToggleHandler(jQuery);
        window.scrollTo(0,0);
        MathJax.Hub.Queue(["Typeset",MathJax.Hub])
        return false;
      }

      /************************************************************************************************************************************************
      rebinding and executing trough ajax requests
      ************************************************************************************************************************************************/

      window.bindGlobalClickHandler = function(){
        $('a:not(.js-external)').unbind('click').bind('click', window.asyncClickHandler);
        $('#js-examples').unbind('click').bind('click',window.runExamples);
        $('#js-install').unbind('click').bind('click',window.installpackage);
        $('#js-hideviewer').unbind('click').bind('click',window.hideViewer);
        $('#js-makedefault').unbind('click').bind('click',window.setDefault);
        $( "form" ).submit(function( event ) {
            event.preventDefault();
            var action = $("form")[0].action;
            var type = "GET";
            if (typeof $("form")[1] != 'undefined'){
              action = $("form")[1].action;
              type = "POST";
            }
            var dataToWrite= $(this).serialize();
            $.ajax({
              type: type,
              url: action,
              data: dataToWrite,
              contentType:"application/x-www-form-urlencoded",
              crossDomain:true,
              xhrFields: {
                withCredentials: true
              }
            }).then(function(html,textData,xhr){
              if(action.indexOf("/login")>-1 && !window.loggedIn){
                window.loggedIn=true;
                _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),
                  ["write('"+dataToWrite+"', file = paste0(.libPaths()[1],'/Rdocumentation/config/creds.txt')) \n Rdocumentation::login()"])
                .then(rerenderBody(html));
              }
              else{
                rerenderBody(html);
              }
            });
        });
      };

      // Helper function to grab new HTML
      // and replace the content
      window.replacePage = function(url) {
        if(url.indexOf('#')==0){
          url = url.substring(1,url.length);
          document.getElementById(url).scrollIntoView();
        }
        else{
          url = url.replace("../","");
          if(url.charAt(0)!="/"){
            url="/"+url;
          }
          var base = $('base').attr('href');
          if(url.indexOf('?')>-1){
            url = url + '&viewer_pane=1&Rstudio_XS_Secret=' + urlParam("Rstudio_XS_Secret")+"&Rstudio_port=" + urlParam("Rstudio_port");
          }
          else{
            url=url+'?viewer_pane=1&Rstudio_XS_Secret=' + urlParam("Rstudio_XS_Secret")+"&Rstudio_port=" + urlParam("Rstudio_port");
          }
          return $.ajax({
            type: 'GET',
            url : url,
            cache: false,
            dataType: 'html',
            xhrFields: {
              withCredentials: true
            }
          })
          .then(rerenderBody);
        }

      };

            /************************************************************************************************************************************************
      button press functions (running examples, installing packages);
      ************************************************************************************************************************************************/
      window.runExamples=function(e){
        console.log("called");
        e.preventDefault();
        var package="";
        $('a').attr('href',function(i,link){
          if(typeof link != "undefined" && link.indexOf("/packages/")>=0 && link.indexOf("/versions/">0)){
            package=link.substring(link.indexOf("/packages/")+10,link.indexOf("/versions/"))
          }
        });
        window.checkPackageVersion(package).then(function(installed){
          if(installed!=false){
            var examples= $('.topic').find('.topic--title').filter(function(i,el){
              return $(this).text()=="Examples";
            }).parent().find('.R').text();
            _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),["require("+package+")\n"+examples])
          }
        });
        return false;
      };

      window.setDefault=function(e){
        e.preventDefault();
        _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),["Rdocumentation::makeDefault()"]);
        return false;
      };
      window.hideViewer=function(e){
        e.preventDefault();
        _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),["Rdocumentation::hideViewer()"]);
        return false;
      };
      /************************************************************************************************************************************************
      checking installation of package and package version
      ************************************************************************************************************************************************/

      window.checkPackageVersion=function(package){
        var installed =true;
        var found=false;
        return _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),["check_package('"+package+"')"])
        .then(function(){
          return _rStudioRequest('/events/get_events','get_events',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),[0])
          .then(function(result){
            for(var i=0;i<result.result.length;i++){
              if(typeof result.result[i] != "undefined" && result.result[i].type=="console_output"){
                if(result.result[i].data.indexOf("FALSE\n")>0){
                  installed = false;
                }
                else{
                  installed=result.result[i].data;
                }
                found=true;
              }
            }
            //Rstudio runs the get_events request periodically. It could happen that we accidently missed the response(small chance), so run it again then
            if(!found){
              installed = window.checkPackageVersion(package);
            }
            return installed;
          })
        });
      };

      window.packageVersionControl=function(){
        var versions = $('#packageVersionSelect').find('option');
        if(versions.length>0){
          var packageInfo=$('.versionCheck> p:eq(0)').text().trim();
          var packageName=packageInfo.split(',')[0];
          window.checkPackageVersion(packageName).then(function(installed){
            if(installed==false){
              $('.versionCheck').append('<button type="button" id="js-install" class="btn btn-primary js-external">Install</button>');
            }
            else{
              installedVersion=installed.split('‘')[1];
              installedVersion=installedVersion.substring(0,installedVersion.length-2).replace('-','.');
              var upToDate=true;
              for(var i=0;i<versions.length;i++){
                if($(versions[i]).text().trim()!="@VERSION@"&& _versionCompare($(versions[i]).text().trim(),installedVersion)){
                  $('.versionCheck').append('<button type="button" id="js-install" class="btn btn-primary js-external">Update</button>');
                  upToDate=false
                }
              }
              if(upToDate){
                $('.versionCheck').text('you currently have the latest version  ');
                $('.versionCheck').append('')
              }
            }
            $('#js-install').unbind('click',window.installpackage);
            $('#js-install').bind('click',window.installpackage);
          });
        }
      };

      window.installpackage=function(e){
        e.preventDefault();
        var packageInfo=$('.versionCheck> p:eq(0)').text().trim();
        var packageName=packageInfo.split(',')[0];
        var packageSource=packageInfo.split(',')[1];
        _rStudioRequest('/rpc/console_input','console_input',urlParam("RS_SHARED_SECRET"),urlParam("Rstudio_port"),
                  ["install_package('"+packageName+"',"+packageSource+")"])
        return false;
      };
      //check the packageversion
      window.packageVersionControl();
      window.bindGlobalClickHandler();
      window.scrollTo(0,0);
    }
  });

_rStudioRequest=function(url,method,shared_secret,port,params){
  var data={}
  data["method"]=method;
  //data["params"]=[$('.R').text()];
  data["params"]=params;
  data["clientId"]='33e600bb-c1b1-46bf-b562-ab5cba070b0e';
  data["clientVersion"]="";
  return $.ajax({
    url: 'http://127.0.0.1:'+port+url,
    headers:
    {
        'Accept':'application/json',
        'Content-Type':'application/json',
        'X-Shared-Secret':shared_secret
    },
    type: 'POST',
    dataType: 'json',
    data: JSON.stringify(data),
    processData: false,
    crossDomain:true,
    xhrFields: {
      withCredentials: true
    }
  });
}
_versionCompare = function (v1, v2) {
    v1parts = v1.split(/[.-]+/);
    v2parts = v2.split(/[.-]+/);
    while (v1parts.length < v2parts.length) v1parts.push("0");
    while (v2parts.length < v1parts.length) v2parts.push("0");
    v1parts = v1parts.map(Number);
    v2parts = v2parts.map(Number);
    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length == i) {
            return true;
        }

        if (v1parts[i] == v2parts[i]) {
            continue;
        }
        else if (v1parts[i] > v2parts[i]) {
            return true;
        }
        else {
            return false;
        }
    }

    if (v1parts.length != v2parts.length) {
        return false;
    }

    return 0;
}<|endoftext|>


<commit_before>'use strict';

var isCallable = require('./is-callable');

module.exports = function (fn) {
	if (!isCallable(fn)) {
		throw new TypeError(fn + " is not a function");
	}
	return fn;
};
<commit_msg>-- whitespace<commit_after>'use strict';

var isCallable = require('./is-callable');

module.exports = function (fn) {
	if (!isCallable(fn)) throw new TypeError(fn + " is not a function");
	return fn;
};
<|endoftext|>


<commit_before>jest.mock('app/services/Firebase', () => {});
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';

import * as Analytics from 'app/services/Analytics';
import * as sut from 'app/features/settings/metrics/SettingsMetricsActions';

const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);
var logEventSpy = null;
var store = null;

describe('what are metric tips', () => {
    beforeEach(() => {
        logEventSpy = jest.spyOn(Analytics, 'logEventWithAppState').mockImplementation(() => {});
        store = mockStore({
            collapsedSettings: {}
        });
    });

    afterEach(() => {
        logEventSpy.mockReset();
    });

    afterAll(() => {
        logEventSpy.mockRestore();
    });

    test('what are metric tips gets logged', () => {
        store.dispatch(sut.presentBigMetricsInfo());

        const event = logEventSpy.mock.calls[0][0];
        const params = logEventSpy.mock.calls[0][1];
        expect(event).toEqual('what_are_metric_tips');
        expect(params).toEqual({});
    });
});

describe('edit collapsed metric screen', () => {
    beforeEach(() => {
        logEventSpy = jest.spyOn(Analytics, 'setCurrentScreen').mockImplementation(() => {});
        store = mockStore({
            collapsedSettings: {}
        });
    });

    afterEach(() => {
        logEventSpy.mockReset();
    });

    afterAll(() => {
        logEventSpy.mockRestore();
    });

    test('edit collapsed_metric screen is set', () => {
        store.dispatch(sut.presentCollapsedMetric());

        const event = logEventSpy.mock.calls[0][0];
        expect(event).toEqual('edit_collapsed_metric');
    });
});

describe('edit quantifier screen', () => {
    beforeEach(() => {
        logEventSpy = jest.spyOn(Analytics, 'setCurrentScreen').mockImplementation(() => {});
        store = mockStore({
            collapsedSettings: {}
        });
    });

    afterEach(() => {
        logEventSpy.mockReset();
    });

    afterAll(() => {
        logEventSpy.mockRestore();
    });

    test('edit quantifier screen is set', () => {
        store.dispatch(sut.presentQuantifier());

        const event = logEventSpy.mock.calls[0][0];
        expect(event).toEqual('edit_quantifier');
    });
});
<commit_msg>Tweaked tests with renames<commit_after>jest.mock('app/services/Firebase', () => {});
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';

import * as Analytics from 'app/services/Analytics';
import * as sut from 'app/features/settings/metrics/SettingsMetricsActions';

const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);
var logEventSpy = null;
var logScreenSpy = null;
var store = null;

describe('what are metric tips', () => {
    beforeEach(() => {
        logEventSpy = jest.spyOn(Analytics, 'logEventWithAppState').mockImplementation(() => {});
        store = mockStore({
            collapsedSettings: {}
        });
    });

    afterEach(() => {
        logEventSpy.mockReset();
    });

    afterAll(() => {
        logEventSpy.mockRestore();
    });

    test('what are metric tips gets logged', () => {
        store.dispatch(sut.presentBigMetricsInfo());

        const event = logEventSpy.mock.calls[0][0];
        const params = logEventSpy.mock.calls[0][1];
        expect(event).toEqual('what_are_metric_tips');
        expect(params).toEqual({});
    });
});

describe('edit collapsed metric screen', () => {
    beforeEach(() => {
        logScreenSpy = jest.spyOn(Analytics, 'setCurrentScreen').mockImplementation(() => {});
        store = mockStore({
            collapsedSettings: {}
        });
    });

    afterEach(() => {
        logScreenSpy.mockReset();
    });

    afterAll(() => {
        logScreenSpy.mockRestore();
    });

    test('edit collapsed_metric screen is set', () => {
        store.dispatch(sut.presentCollapsedMetric());

        const event = logScreenSpy.mock.calls[0][0];
        expect(event).toEqual('edit_collapsed_metric');
    });
});

describe('edit quantifier screen', () => {
    beforeEach(() => {
        logScreenSpy = jest.spyOn(Analytics, 'setCurrentScreen').mockImplementation(() => {});
        store = mockStore({
            collapsedSettings: {}
        });
    });

    afterEach(() => {
        logScreenSpy.mockReset();
    });

    afterAll(() => {
        logScreenSpy.mockRestore();
    });

    test('edit quantifier screen is set', () => {
        store.dispatch(sut.presentQuantifier());

        const event = logScreenSpy.mock.calls[0][0];
        expect(event).toEqual('edit_quantifier');
    });
});
<|endoftext|>


<commit_before>'use strict';

/*
 * XML converter for Images.
 */
module.exports = {

  type: 'image',
  tagName: 'img',

  import: function(el, node) {
    node.src = el.attr('src');
    node.previewSrc = el.attr('preview-src');
  },

  export: function(node, el) {
    el.attr('src', node.src)
      .attr('preview-src', node.previewSrc);
  }
};
<commit_msg>Fix ImageXMLConverter.<commit_after>'use strict';

/*
 * XML converter for Images.
 */
module.exports = {

  type: 'image',
  tagName: 'image',

  import: function(el, node) {
    node.src = el.attr('src');
    node.previewSrc = el.attr('preview-src');
  },

  export: function(node, el) {
    el.attr('src', node.src)
      .attr('preview-src', node.previewSrc);
  }
};
<|endoftext|>


<commit_before><commit_msg>test<commit_after><|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import _get from 'lodash/get';
import _uniq from 'lodash/uniq';
import _range from 'lodash/range';
import _padStart from 'lodash/padStart';

import {view} from 'components';

export default class ScheduleField extends React.Component {

    static propTypes = {
        metaItem: PropTypes.object.isRequired,
        attributesMap: PropTypes.object,
        input: PropTypes.shape({
            name: PropTypes.string,
            value: PropTypes.any,
            onChange: PropTypes.func,
        }),
    };

    static hours = _range(24).map(n => _padStart(n, 2, '0'));
    static minutes = _range(4).map(n => _padStart(n * 15, 2, '0'));

    render() {
        const daysInput = _get(this.props, this.props.attributesMap[this.props.attribute]).input;
        const timeSinceInput = _get(this.props, this.props.attributesMap[this.props.metaItem.sinceTimeAttribute]).input;
        const timeTillInput = _get(this.props, this.props.attributesMap[this.props.metaItem.tillTimeAttribute]).input;

        const weekDays = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
        const selectedDays = (daysInput.value || '').split(',').filter(Boolean).map(v => parseInt(v));

        const {fieldId, metaItem, ...props} = this.props;
        const ScheduleFieldView = view.getFormView('ScheduleFieldView');
        return (
            <ScheduleFieldView
                {...props}
                weekDays={weekDays.map((label, index) => ({
                    index,
                    label,
                    isSelected: selectedDays.indexOf(index + 1) !== -1,
                    onClick: () => this.selectDay(index + 1),
                }))}
                onAllTimeClick={() => {
                    timeSinceInput.onChange('0:0');
                    timeTillInput.onChange('23:59');
                }}
                onEverydayClick={() => daysInput.onChange('1,2,3,4,5,6,7')}
                sinceHourProps={{
                    metaItem,
                    autoSelectFirst: true,
                    placeholder: '',
                    fieldId: `${fieldId}_sinceHour`,
                    input: {
                        ...timeSinceInput,
                        value: (timeSinceInput.value || '').split(':')[0] || '00',
                        onChange: v => this.setSincePartTime(0, v),
                    },
                    items: ScheduleField.hours,
                }}
                sinceMinuteProps={{
                    metaItem,
                    autoSelectFirst: true,
                    placeholder: '',
                    fieldId: `${fieldId}_sinceMinute`,
                    input: {
                        ...timeSinceInput,
                        value: (timeSinceInput.value || '').split(':')[1] || '00',
                        onChange: v => this.setSincePartTime(1, v),
                    },
                    items: ScheduleField.minutes,
                }}
                tillHourProps={{
                    metaItem,
                    autoSelectFirst: true,
                    placeholder: '',
                    fieldId: `${fieldId}_tillHour`,
                    input: {
                        ...timeTillInput,
                        value: (timeTillInput.value || '').split(':')[0] || '00',
                        onChange: v => this.setTillPartTime(0, v),
                    },
                    items: ScheduleField.hours,
                }}
                tillMinuteProps={{
                    metaItem,
                    autoSelectFirst: true,
                    placeholder: '',
                    fieldId: `${fieldId}_tillMinute`,
                    input: {
                        ...timeTillInput,
                        value: (timeTillInput.value || '').split(':')[1] || '00',
                        onChange: v => this.setTillPartTime(1, v),
                    },
                    items: ScheduleField.minutes,
                }}
            />
        );
    }

    selectDay(dayNumber) {
        const daysInput = _get(this.props, this.props.name).input;
        const value = (daysInput.value || '').split(',').filter(Boolean).map(v => parseInt(v));
        const index = value.indexOf(dayNumber);
        if (index !== -1) {
            value.splice(index, 1);
        } else {
            value.push(dayNumber);
        }

        daysInput.onChange(_uniq(value.sort()).join(','));
    }

    setSincePartTime(index, partValue) {
        const timeSinceInput = _get(this.props, this.props.attributesMap[this.props.metaItem.sinceTimeAttribute]).input;
        const value = (timeSinceInput.value || '').split(':') || ['00', '00'];
        value[index] = partValue;
        timeSinceInput.onChange(value.join(':'));
    }

    setTillPartTime(index, partValue) {
        const timeTillInput = _get(this.props, this.props.attributesMap[this.props.metaItem.tillTimeAttribute]).input;
        const value = (timeTillInput.value || '').split(':') || ['00', '00'];
        value[index] = partValue;
        timeTillInput.onChange(value.join(':'));
    }

}
<commit_msg>ScheduleField fixes<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import _get from 'lodash/get';
import _uniq from 'lodash/uniq';
import _range from 'lodash/range';
import _padStart from 'lodash/padStart';

import {view} from 'components';

export default class ScheduleField extends React.Component {

    static propTypes = {
        metaItem: PropTypes.object.isRequired,
        attributesMap: PropTypes.object,
        input: PropTypes.shape({
            name: PropTypes.string,
            value: PropTypes.any,
            onChange: PropTypes.func,
        }),
    };

    static hours = _range(24).map(n => _padStart(n, 2, '0'));
    static minutes = _range(4).map(n => _padStart(n * 15, 2, '0'));

    render() {
        const daysInput = _get(this.props, this.props.attributesMap[this.props.attribute]).input;
        const timeSinceInput = _get(this.props, this.props.attributesMap[this.props.metaItem.sinceTimeAttribute]).input;
        const timeTillInput = _get(this.props, this.props.attributesMap[this.props.metaItem.tillTimeAttribute]).input;

        const weekDays = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
        const selectedDays = (daysInput.value || '').split(',').filter(Boolean).map(v => parseInt(v));

        const {fieldId, metaItem, ...props} = this.props;
        const ScheduleFieldView = view.getFormView('ScheduleFieldView');

        const extractTimeFromDateTime = dateTimeString => {
            if (!dateTimeString) {
                return '';
            }

            return dateTimeString.indexOf(' ') !== -1
                ? dateTimeString.split(' ')[1]
                : dateTimeString
        };

        return (
            <ScheduleFieldView
                {...props}
                weekDays={weekDays.map((label, index) => ({
                    index,
                    label,
                    isSelected: selectedDays.indexOf(index + 1) !== -1,
                    onClick: () => this.selectDay(index + 1),
                }))}
                onAllTimeClick={() => {
                    timeSinceInput.onChange('00:00');
                    timeTillInput.onChange('00:00');
                }}
                onEverydayClick={() => daysInput.onChange('1,2,3,4,5,6,7')}
                sinceHourProps={{
                    metaItem,
                    autoSelectFirst: true,
                    placeholder: '',
                    fieldId: `${fieldId}_sinceHour`,
                    input: {
                        ...timeSinceInput,
                        value: extractTimeFromDateTime(timeSinceInput.value).split(':')[0] || '00',
                        onChange: v => this.setSincePartTime(0, v),
                    },
                    items: ScheduleField.hours,
                }}
                sinceMinuteProps={{
                    metaItem,
                    autoSelectFirst: true,
                    placeholder: '',
                    fieldId: `${fieldId}_sinceMinute`,
                    input: {
                        ...timeSinceInput,
                        value: extractTimeFromDateTime(timeSinceInput.value).split(':')[1] || '00',
                        onChange: v => this.setSincePartTime(1, v),
                    },
                    items: ScheduleField.minutes,
                }}
                tillHourProps={{
                    metaItem,
                    autoSelectFirst: true,
                    placeholder: '',
                    fieldId: `${fieldId}_tillHour`,
                    input: {
                        ...timeTillInput,
                        value: extractTimeFromDateTime(timeTillInput.value).split(':')[0] || '00',
                        onChange: v => this.setTillPartTime(0, v),
                    },
                    items: ScheduleField.hours,
                }}
                tillMinuteProps={{
                    metaItem,
                    autoSelectFirst: true,
                    placeholder: '',
                    fieldId: `${fieldId}_tillMinute`,
                    input: {
                        ...timeTillInput,
                        value: extractTimeFromDateTime(timeTillInput.value).split(':')[1] || '00',
                        onChange: v => this.setTillPartTime(1, v),
                    },
                    items: ScheduleField.minutes,
                }}
            />
        );
    }

    selectDay(dayNumber) {
        const daysInput = _get(this.props, this.props.attributesMap[this.props.attribute]).input;
        const value = (daysInput.value || '').split(',').filter(Boolean).map(v => parseInt(v));
        const index = value.indexOf(dayNumber);
        if (index !== -1) {
            value.splice(index, 1);
        } else {
            value.push(dayNumber);
        }

        daysInput.onChange(_uniq(value.sort()).join(','));
    }

    setSincePartTime(index, partValue) {
        const timeSinceInput = _get(this.props, this.props.attributesMap[this.props.metaItem.sinceTimeAttribute]).input;
        const value = (timeSinceInput.value || '').split(':') || ['00', '00'];
        value[index] = partValue;
        timeSinceInput.onChange(value.join(':'));
    }

    setTillPartTime(index, partValue) {
        const timeTillInput = _get(this.props, this.props.attributesMap[this.props.metaItem.tillTimeAttribute]).input;
        const value = (timeTillInput.value || '').split(':') || ['00', '00'];
        value[index] = partValue;
        timeTillInput.onChange(value.join(':'));
    }

}
<|endoftext|>


<commit_before>/* jshint node:true, undef:true, unused:true */
var compileModules   = require('broccoli-es6-module-transpiler');
var merge            = require('broccoli-merge-trees');
var uglify           = require('broccoli-uglify-js');
var version          = require('git-repo-version');
var browserify       = require('broccoli-watchify');
var fs               = require('fs');

var stew   = require('broccoli-stew');

var find   = stew.find;
var mv     = stew.mv;
var rename = stew.rename;
var env    = stew.env;
var map    = stew.map;

var lib       = find('lib');
var testDir   = find('test');
var testFiles = find('test/{index.html,worker.js}');

var json3     = mv(find('node_modules/json3/lib/{json3.js}'), 'node_modules/json3/lib/', 'test/');
// mocha doesn't browserify correctly
var mocha     = mv(find('node_modules/mocha/mocha.{js,css}'), 'node_modules/mocha/',    'test/');

var testVendor = merge([ json3, mocha ]);

var rsvp = compileModules(lib, {
  format: 'bundle',
  entry: 'rsvp.umd.js',
  output: 'rsvp.js'
});

var testBundle = browserify(merge([
  mv(rsvp, 'test'),
  testDir
]), {
  browserify: { entries: ['./test/index.js'] }
});

var dist = rsvp;

env('production', function() {
  dist = merge([
    rename(uglify(dist), '.js', '.min.js'),
    dist
  ]);
});

function prependLicense(content) {
  var license = fs.readFileSync('./config/versionTemplate.txt').toString().replace(/VERSION_PLACEHOLDER_STRING/, version());

  // strip source maps for now..
  content.replace(/\/\/# sourceMappingURL=rsvp.*/,'');
  return license + '\n' + content;
}

// exclude source maps for now, until map/cat supports source maps
dist = find(dist, '!*.map');

module.exports = merge([
  map(dist, prependLicense),
  testFiles,
  testVendor,
  mv(dist, 'test'),
  mv(testBundle, 'test')
]);
<commit_msg>Fix stripping source map<commit_after>/* jshint node:true, undef:true, unused:true */
var compileModules   = require('broccoli-es6-module-transpiler');
var merge            = require('broccoli-merge-trees');
var uglify           = require('broccoli-uglify-js');
var version          = require('git-repo-version');
var browserify       = require('broccoli-watchify');
var fs               = require('fs');

var stew   = require('broccoli-stew');

var find   = stew.find;
var mv     = stew.mv;
var rename = stew.rename;
var env    = stew.env;
var map    = stew.map;

var lib       = find('lib');
var testDir   = find('test');
var testFiles = find('test/{index.html,worker.js}');

var json3     = mv(find('node_modules/json3/lib/{json3.js}'), 'node_modules/json3/lib/', 'test/');
// mocha doesn't browserify correctly
var mocha     = mv(find('node_modules/mocha/mocha.{js,css}'), 'node_modules/mocha/',    'test/');

var testVendor = merge([ json3, mocha ]);

var rsvp = compileModules(lib, {
  format: 'bundle',
  entry: 'rsvp.umd.js',
  output: 'rsvp.js'
});

var testBundle = browserify(merge([
  mv(rsvp, 'test'),
  testDir
]), {
  browserify: { entries: ['./test/index.js'] }
});

var dist = rsvp;

env('production', function() {
  dist = merge([
    rename(uglify(dist), '.js', '.min.js'),
    dist
  ]);
});

function prependLicense(content) {
  var license = fs.readFileSync('./config/versionTemplate.txt').toString().replace(/VERSION_PLACEHOLDER_STRING/, version());

  // strip source maps for now..
  content = content.replace(/\/\/# sourceMappingURL=rsvp.*/,'');
  return license + '\n' + content;
}

// exclude source maps for now, until map/cat supports source maps
dist = find(dist, '!*.map');

module.exports = merge([
  map(dist, prependLicense),
  testFiles,
  testVendor,
  mv(dist, 'test'),
  mv(testBundle, 'test')
]);
<|endoftext|>