<commit_before>import React from 'react/';

import { Navbar, Row, Col, Button } from 'react-bootstrap/lib/';

import Scroll from 'react-scroll';

import { safeMerge } from 'js-utility-belt/es6';

import Accounts from '../../../lib/js/react/components/accounts';
import Assets from './assets';
import AssetMatrix from './asset_matrix';

import AssetActions from '../../../lib/js/react/actions/asset_actions';
import AssetStore from '../../../lib/js/react/stores/asset_store';

import AccountStore from '../../../lib/js/react/stores/account_store';

const ShareTrader = React.createClass({

    getInitialState() {
        const assetStore = AssetStore.getState();
        const accountStore = AccountStore.getState();

        return safeMerge(
            {
                activeAccount: null,
                activeAsset: null,
                searchQuery: null
            },
            assetStore,
            accountStore
        );
    },

    componentDidMount() {
        AssetStore.listen(this.onChange);
        AccountStore.listen(this.onChange);

        this.fetchAssetList();
        Scroll.animateScroll.scrollToBottom();
    },

    componentWillUnmount() {
        AssetStore.unlisten(this.onChange);
        AccountStore.unlisten(this.onChange);
    },

    onChange(state) {
        this.setState(state);
    },

    setActiveAccount(account) {
        this.setState({
            activeAccount: account
        });
    },

    resetActiveAccount() {
        this.setState({
            activeAccount: null
        });
    },

    setActiveAsset(asset) {
        this.setState({
            activeAsset: asset
        });
    },

    mapAccountsOnStates(accountList) {
        const states = { 'default': 'available' };

        if (!accountList) {
            return states;
        }

        for (let i = 0; i < accountList.length; i++) {
            states[accountList[i].vk] = `state${i}`;
        }

        return states;
    },

    fetchAssetList() {
        AssetActions.flushAssetList();
        const { activeAccount, searchQuery } = this.state;
        const accountPublicKey = activeAccount ? activeAccount.vk : null;

        AssetActions.fetchAssetList({ accountToFetch: accountPublicKey, search: searchQuery });

        setTimeout(this.fetchAssetList, 1000);
    },

    handleSearch(query) {
        this.setState({
            searchQuery: query
        });
    },

    render() {
        const { activeAccount, accountList, activeAsset, assetList, assetMeta } = this.state;
        const states = this.mapAccountsOnStates(accountList);

        return (

                <Navbar fixedTop inverse>

Share Trader

                </Navbar>

                                <Button
                                    onClick={this.resetActiveAccount}>
                                    Select All
                                </Button>

                            <Accounts
                                activeAccount={activeAccount}
                                appName="sharetrader"
                                handleAccountClick={this.setActiveAccount} />

                            <Row>
                                <Col className="asset-matrix" md={8} xs={6}>

                                            <AssetMatrix
                                                cols={8}
                                                handleAssetClick={this.setActiveAsset}
                                                rows={8}
                                                states={states} />

                                </Col>
                                <Col className="asset-history" md={4} xs={6}>
                                    <Assets
                                        accountList={accountList}
                                        activeAccount={activeAccount}
                                        activeAsset={activeAsset}
                                        assetClasses={states}
                                        assetList={assetList}
                                        handleAssetClick={this.setActiveAsset} />
                                </Col>
                            </Row>

        );
    }
});

export default ShareTrader;
<commit_msg>remove search from sharetrader<commit_after>import React from 'react/';

import { Navbar, Row, Col, Button } from 'react-bootstrap/lib/';

import Scroll from 'react-scroll';

import { safeMerge } from 'js-utility-belt/es6';

import Accounts from '../../../lib/js/react/components/accounts';
import Assets from './assets';
import AssetMatrix from './asset_matrix';

import AssetActions from '../../../lib/js/react/actions/asset_actions';
import AssetStore from '../../../lib/js/react/stores/asset_store';

import AccountStore from '../../../lib/js/react/stores/account_store';

const ShareTrader = React.createClass({

    getInitialState() {
        const assetStore = AssetStore.getState();
        const accountStore = AccountStore.getState();

        return safeMerge(
            {
                activeAccount: null,
                activeAsset: null,
                searchQuery: null
            },
            assetStore,
            accountStore
        );
    },

    componentDidMount() {
        AssetStore.listen(this.onChange);
        AccountStore.listen(this.onChange);

        this.fetchAssetList();
        Scroll.animateScroll.scrollToBottom();
    },

    componentWillUnmount() {
        AssetStore.unlisten(this.onChange);
        AccountStore.unlisten(this.onChange);
    },

    onChange(state) {
        this.setState(state);
    },

    setActiveAccount(account) {
        this.setState({
            activeAccount: account
        });
    },

    resetActiveAccount() {
        this.setState({
            activeAccount: null
        });
    },

    setActiveAsset(asset) {
        this.setState({
            activeAsset: asset
        });
    },

    mapAccountsOnStates(accountList) {
        const states = { 'default': 'available' };

        if (!accountList) {
            return states;
        }

        for (let i = 0; i < accountList.length; i++) {
            states[accountList[i].vk] = `state${i}`;
        }

        return states;
    },

    fetchAssetList() {
        AssetActions.flushAssetList();
        const { activeAccount, searchQuery } = this.state;
        const accountPublicKey = activeAccount ? activeAccount.vk : null;

        AssetActions.fetchAssetList({ accountToFetch: accountPublicKey, search: searchQuery });

        setTimeout(this.fetchAssetList, 1000);
    },

    render() {
        const { activeAccount, accountList, activeAsset, assetList } = this.state;
        const states = this.mapAccountsOnStates(accountList);

        return (

                <Navbar fixedTop inverse>

Share Trader

                </Navbar>

                                <Button
                                    onClick={this.resetActiveAccount}>
                                    Select All
                                </Button>

                            <Accounts
                                activeAccount={activeAccount}
                                appName="sharetrader"
                                handleAccountClick={this.setActiveAccount} />

                            <Row>
                                <Col className="asset-matrix" md={8} xs={6}>

                                            <AssetMatrix
                                                cols={8}
                                                handleAssetClick={this.setActiveAsset}
                                                rows={8}
                                                states={states} />

                                </Col>
                                <Col className="asset-history" md={4} xs={6}>
                                    <Assets
                                        accountList={accountList}
                                        activeAccount={activeAccount}
                                        activeAsset={activeAsset}
                                        assetClasses={states}
                                        assetList={assetList}
                                        handleAssetClick={this.setActiveAsset} />
                                </Col>
                            </Row>

        );
    }
});

export default ShareTrader;
<|endoftext|>


<commit_before>'use strict';

var schedule = require('node-schedule');

var dbPool = require('./dbpool');
var Session = require('./session');
var SessionList = require('./sessionlist');

function SessionManager() {
    this._sessions = new SessionList();
}

SessionManager.prototype.hasOpenSession = function(sessionId, userId) {
    return this._sessions.has(sessionId, userId);
};

SessionManager.prototype.openSession = function(userId, callback) {
    if (this._sessions.hasForUser(userId)) {
        callback(403, { error: "a session is already open for user id " + userId });
        return;
    }

    var that = this;

    dbPool.connect(function(err, client, done) {
        if (err) {
            callback(503, { error: 'error fetching client from pool: ' + err });
            return;
        }

        client.query('SELECT id FROM sessions WHERE user_id=$1::integer AND end_date IS NULL', [ userId ], function(err, result) {
            if (err) {
                done();
                callback(500, { error: 'error running query: ' + err });
                return;
            }

            if (result.rowCount != 0) {
                done();
                console.error("An open session was present in the database for user " + userId);
                callback(403, { error: "a session is already open for user id " + userId });
                return;
            }

            client.query('INSERT INTO sessions VALUES (DEFAULT, $1::integer, DEFAULT, NULL) RETURNING *', [ userId ], function(err, result) {
                done();

                if (err) {
                    callback(500, { error: 'error running query: ' + err });
                    return;
                }

                var row = result.rows[0];
                var session = new Session(row.id, row.user_id, row.start_date);
                that._sessions.add(session);

                console.log("opening session " + session.id + " for user " + session.userId);

                callback(200, { session_id: session.id, start_date: session.startDate });
            });
        });
    });
};

SessionManager.prototype.closeSession = function(sessionId, userId, callback) {
    if (!this._sessions.has(sessionId)) {
        callback(400, { error: "session " + sessionId + " is not an open session for user " + userId });
        return;
    }

    var session = this._sessions.get(sessionId);

    if (session.userId != userId) {
        callback(400, { error: "session " + sessionId + " is not an open session for user " + userId });
        return;
    }

    var that = this;

    dbPool.connect(function(err, client, done) {
        if (err) {
            callback(503, { message: 'error fetching client from pool: ' + err });
            return;
        }

        client.query('UPDATE sessions SET end_date = now() WHERE id=$1::integer AND user_id=$2::integer AND end_date IS NULL', [ sessionId, userId ], function(err, result) {
            if (err) {
                callback(500, { message: 'error running query: ' + err });
                return;
            }

            that._sessions.remove(sessionId);

            console.log("closing session " + sessionId + " for user " + userId);

            that.releaseSessionBuildings([ sessionId ], client, function(err) {
                done();

                if (err) {
                    callback(500, { message: 'error running query: ' + err });
                    return;
                }

                callback(200, { message: 'session closed' });
            });
        });
    });
};

SessionManager.prototype.closeOpenSessions = function() {
    var that = this;

    dbPool.connect(function(err, client, done) {
        if (err) {
            console.error('Error fetching client from pool: ' + err);
            return;
        }

        client.query('UPDATE sessions SET end_date = now() WHERE end_date IS NULL RETURNING id', [ ], function(err, result) {
            done();

            if (err) {
                console.error('Error running query: ' + err);
                return;
            }

            that._sessions.clear();

            if (result.rowCount > 0) {
                console.log(result.rowCount + ' open sessions closed');

                var sessionIds = result.rows.map(function(row) {
                    return row.id;
                });

                that.releaseSessionBuildings(sessionIds, client, function(err) {
                    done();
                });
            }
        });
    });
};

SessionManager.prototype.scheduleSessionClosing = function() {
    var that = this;

    var rule = new schedule.RecurrenceRule();
    //rule.minute = [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 ];
    rule.second = [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 ];
    schedule.scheduleJob(rule, function() {
        dbPool.connect(function(err, client, done) {
            if (err) {
                console.error('Error fetching client from pool: ' + err);
                return;
            }

            client.query('UPDATE sessions SET end_date = now() WHERE start_date < now() - INTERVAL \'1 minutes\' AND end_date IS NULL RETURNING id', [ ], function(err, result) {
                if (err) {
                    console.error('Error running query: ' + err);
                    return;
                }

                for (var i = 0; i < result.rowCount; i++) {
                    that._sessions.remove(result.rows[i].id);
                }

                if (result.rowCount > 0) {
                    console.log(result.rowCount + ' open sessions closed');

                    var sessionIds = result.rows.map(function(row) {
                        return row.id;
                    });

                    that.releaseSessionBuildings(sessionIds, client, function(err) {
                        done();
                    });
                } else {
                    done();
                }
            });
        });
    });
};

SessionManager.prototype.releaseSessionBuildings = function(sessionIds, client, callback) {
    client.query('UPDATE buildings SET session_id = NULL WHERE session_id = ANY($1::integer[]) AND changeset_id IS NULL', [ sessionIds ], function(err, result) {
        if (err) {
            console.error('Error running query: ' + err);
            callback(err);
            return;
        }

        if (result.rowCount > 0) {
            console.log(result.rowCount + ' buildings released from sessions [' + sessionIds + ']');
        }

        callback();
    });
};

var sessionManager = new SessionManager();

module.exports = sessionManager;
<commit_msg>Remove debug code<commit_after>'use strict';

var schedule = require('node-schedule');

var dbPool = require('./dbpool');
var Session = require('./session');
var SessionList = require('./sessionlist');

function SessionManager() {
    this._sessions = new SessionList();
}

SessionManager.prototype.hasOpenSession = function(sessionId, userId) {
    return this._sessions.has(sessionId, userId);
};

SessionManager.prototype.openSession = function(userId, callback) {
    if (this._sessions.hasForUser(userId)) {
        callback(403, { error: "a session is already open for user id " + userId });
        return;
    }

    var that = this;

    dbPool.connect(function(err, client, done) {
        if (err) {
            callback(503, { error: 'error fetching client from pool: ' + err });
            return;
        }

        client.query('SELECT id FROM sessions WHERE user_id=$1::integer AND end_date IS NULL', [ userId ], function(err, result) {
            if (err) {
                done();
                callback(500, { error: 'error running query: ' + err });
                return;
            }

            if (result.rowCount != 0) {
                done();
                console.error("An open session was present in the database for user " + userId);
                callback(403, { error: "a session is already open for user id " + userId });
                return;
            }

            client.query('INSERT INTO sessions VALUES (DEFAULT, $1::integer, DEFAULT, NULL) RETURNING *', [ userId ], function(err, result) {
                done();

                if (err) {
                    callback(500, { error: 'error running query: ' + err });
                    return;
                }

                var row = result.rows[0];
                var session = new Session(row.id, row.user_id, row.start_date);
                that._sessions.add(session);

                console.log("opening session " + session.id + " for user " + session.userId);

                callback(200, { session_id: session.id, start_date: session.startDate });
            });
        });
    });
};

SessionManager.prototype.closeSession = function(sessionId, userId, callback) {
    if (!this._sessions.has(sessionId)) {
        callback(400, { error: "session " + sessionId + " is not an open session for user " + userId });
        return;
    }

    var session = this._sessions.get(sessionId);

    if (session.userId != userId) {
        callback(400, { error: "session " + sessionId + " is not an open session for user " + userId });
        return;
    }

    var that = this;

    dbPool.connect(function(err, client, done) {
        if (err) {
            callback(503, { message: 'error fetching client from pool: ' + err });
            return;
        }

        client.query('UPDATE sessions SET end_date = now() WHERE id=$1::integer AND user_id=$2::integer AND end_date IS NULL', [ sessionId, userId ], function(err, result) {
            if (err) {
                callback(500, { message: 'error running query: ' + err });
                return;
            }

            that._sessions.remove(sessionId);

            console.log("closing session " + sessionId + " for user " + userId);

            that.releaseSessionBuildings([ sessionId ], client, function(err) {
                done();

                if (err) {
                    callback(500, { message: 'error running query: ' + err });
                    return;
                }

                callback(200, { message: 'session closed' });
            });
        });
    });
};

SessionManager.prototype.closeOpenSessions = function() {
    var that = this;

    dbPool.connect(function(err, client, done) {
        if (err) {
            console.error('Error fetching client from pool: ' + err);
            return;
        }

        client.query('UPDATE sessions SET end_date = now() WHERE end_date IS NULL RETURNING id', [ ], function(err, result) {
            done();

            if (err) {
                console.error('Error running query: ' + err);
                return;
            }

            that._sessions.clear();

            if (result.rowCount > 0) {
                console.log(result.rowCount + ' open sessions closed');

                var sessionIds = result.rows.map(function(row) {
                    return row.id;
                });

                that.releaseSessionBuildings(sessionIds, client, function(err) {
                    done();
                });
            }
        });
    });
};

SessionManager.prototype.scheduleSessionClosing = function() {
    var that = this;

    var rule = new schedule.RecurrenceRule();
    rule.minute = [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 ];
    schedule.scheduleJob(rule, function() {
        dbPool.connect(function(err, client, done) {
            if (err) {
                console.error('Error fetching client from pool: ' + err);
                return;
            }

            client.query('UPDATE sessions SET end_date = now() WHERE start_date < now() - INTERVAL \'2 hours\' AND end_date IS NULL RETURNING id', [ ], function(err, result) {
                if (err) {
                    console.error('Error running query: ' + err);
                    return;
                }

                for (var i = 0; i < result.rowCount; i++) {
                    that._sessions.remove(result.rows[i].id);
                }

                if (result.rowCount > 0) {
                    console.log(result.rowCount + ' open sessions closed');

                    var sessionIds = result.rows.map(function(row) {
                        return row.id;
                    });

                    that.releaseSessionBuildings(sessionIds, client, function(err) {
                        done();
                    });
                } else {
                    done();
                }
            });
        });
    });
};

SessionManager.prototype.releaseSessionBuildings = function(sessionIds, client, callback) {
    client.query('UPDATE buildings SET session_id = NULL WHERE session_id = ANY($1::integer[]) AND changeset_id IS NULL', [ sessionIds ], function(err, result) {
        if (err) {
            console.error('Error running query: ' + err);
            callback(err);
            return;
        }

        if (result.rowCount > 0) {
            console.log(result.rowCount + ' buildings released from sessions [' + sessionIds + ']');
        }

        callback();
    });
};

var sessionManager = new SessionManager();

module.exports = sessionManager;
<|endoftext|>


<commit_before>/**
 * Created by meathill on 15/4/28.
 */
'use strict';
(function (ns) {
  ns.BaseList = Backbone.View.extend({
    autoFetch: true,
    fragment: '',
    initialize: function (options) {
      this.template = Handlebars.compile(this.$('script').remove().html().replace(/\s{2,}|\n/g, ''));
      this.container = options.container ? this.$(options.container) : this.$el;
      this.collection = this.getCollection(options);
      this.collection.on('add', this.collection_addHandler, this);
      this.collection.on('change', this.collection_changeHandler, this);
      this.collection.on('remove', this.collection_removeHandler, this);
      this.collection.on('sync', this.collection_syncHandler, this);
      this.collection.on('reset', this.collection_resetHandler, this);
      this.collection.on('error', this.collection_errorHandler, this);
      if (options.autoFetch || !('autoFetch' in options) && this.autoFetch) {
        this.refresh(options);
      }
    },
    remove: function () {
      this.collection.off(null, null, this);
      Backbone.View.prototype.remove.call(this);
    },
    render: function () {
      this.$('.waiting').remove();
      this.container.append(this.fragment);
      this.fragment = '';
      this.$el.removeClass('loading');
    },
    getCollection: function (options) {
      if (this.collection) {
        return this.collection;
      }

      var init = this.$el.data();
      if ('url' in init) {
        init.url = init.url.replace('{{API}}', tp.API);
      }
      options = _.extend(options, init);

      this.params = tp.utils.decodeURLParam(options.params);
      // 起止日期
      if (options.defaults && _.isString(options.defaults)) {
        options.defaults = tp.utils.decodeURLParam(options.defaults);
      }
      if (options.start || options.end) {
        options.defaults = _.extend(options.defaults, _.pick(options, 'start', 'end'));
      }

      return tp.model.ListCollection.getInstance(options);
    },
    refresh: function (options) {
      options = options || {};
      options.data = _.extend(options.data, this.params);
      this.collection.fetch(options);
    },
    collection_addHandler: function (model, collection, options) {
      this.fragment += this.template(model instanceof Backbone.Model ? model.toJSON() : model);
      if (options && options.immediately) {
        var item = $(this.fragment);
        item.attr('id', model.id || model.cid);
        this.container[options.prepend ? 'prepend' : 'append'](item);
        this.fragment = '';
        return item;
      }
    },
    collection_changeHandler: function (model) {
      var html = this.template(model.toJSON());
      $(document.getElementById(model.id || model.cid)).replaceWith(html); // 因为id里可能有.
    },
    collection_errorHandler: function (collection, response, options) {
      console.log('error', collection, response, options);
    },
    collection_removeHandler: function (model, collection, options) {
      var item = $(document.getElementById(model.id || model.cid));
      if (options.fadeOut) {
        item.fadeOut(function () {
          $(this).remove();
        });
      } else {
        item.remove();
      }
    },
    collection_resetHandler: function () {
      this.container.empty();
      this.collection.each(function (model) {
        this.collection_addHandler(model);
      }, this);
      this.render();
    },
    collection_syncHandler: function () {
      this.render();
    }
  });
}(Nervenet.createNameSpace('tp.component')));<commit_msg>修复初始化 defaults 的问题<commit_after>/**
 * Created by meathill on 15/4/28.
 */
'use strict';
(function (ns) {
  ns.BaseList = Backbone.View.extend({
    autoFetch: true,
    fragment: '',
    initialize: function (options) {
      this.template = Handlebars.compile(this.$('script').remove().html().replace(/\s{2,}|\n/g, ''));
      this.container = options.container ? this.$(options.container) : this.$el;
      this.collection = this.getCollection(options);
      this.collection.on('add', this.collection_addHandler, this);
      this.collection.on('change', this.collection_changeHandler, this);
      this.collection.on('remove', this.collection_removeHandler, this);
      this.collection.on('sync', this.collection_syncHandler, this);
      this.collection.on('reset', this.collection_resetHandler, this);
      this.collection.on('error', this.collection_errorHandler, this);
      if (options.autoFetch || !('autoFetch' in options) && this.autoFetch) {
        this.refresh(options);
      }
    },
    remove: function () {
      this.collection.off(null, null, this);
      Backbone.View.prototype.remove.call(this);
    },
    render: function () {
      this.$('.waiting').remove();
      this.container.append(this.fragment);
      this.fragment = '';
      this.$el.removeClass('loading');
    },
    getCollection: function (options) {
      if (this.collection) {
        return this.collection;
      }

      var init = this.$el.data();
      if ('url' in init) {
        init.url = init.url.replace('{{API}}', tp.API);
      }
      options = _.extend(options, init);

      this.params = tp.utils.decodeURLParam(options.params);
      // 起止日期
      if (options.defaults && _.isString(options.defaults)) {
        options.defaults = tp.utils.decodeURLParam(options.defaults);
      }
      if (!options.defaults) {
        options.defaults = {};
      }
      if (options.start || options.end) {
        options.defaults = _.extend(options.defaults, _.pick(options, 'start', 'end'));
      }

      return tp.model.ListCollection.getInstance(options);
    },
    refresh: function (options) {
      options = options || {};
      options.data = _.extend(options.data, this.params);
      this.collection.fetch(options);
    },
    collection_addHandler: function (model, collection, options) {
      this.fragment += this.template(model instanceof Backbone.Model ? model.toJSON() : model);
      if (options && options.immediately) {
        var item = $(this.fragment);
        item.attr('id', model.id || model.cid);
        this.container[options.prepend ? 'prepend' : 'append'](item);
        this.fragment = '';
        return item;
      }
    },
    collection_changeHandler: function (model) {
      var html = this.template(model.toJSON());
      $(document.getElementById(model.id || model.cid)).replaceWith(html); // 因为id里可能有.
    },
    collection_errorHandler: function (collection, response, options) {
      console.log('error', collection, response, options);
    },
    collection_removeHandler: function (model, collection, options) {
      var item = $(document.getElementById(model.id || model.cid));
      if (options.fadeOut) {
        item.fadeOut(function () {
          $(this).remove();
        });
      } else {
        item.remove();
      }
    },
    collection_resetHandler: function () {
      this.container.empty();
      this.collection.each(function (model) {
        this.collection_addHandler(model);
      }, this);
      this.render();
    },
    collection_syncHandler: function () {
      this.render();
    }
  });
}(Nervenet.createNameSpace('tp.component')));<|endoftext|>


<commit_before>/**
 * @constructor
 */
function SearchController(search) {
  this.search_ = search;

  $('#search-button').click(this.onSearchButton_.bind(this));
  $('#search-input').bind('input', this.onChange_.bind(this));
  $('#search-input').keydown(this.onKeydown_.bind(this));
  $('#search-next-button').click(this.onFindNext_.bind(this));
  $('#search-previous-button').click(this.onFindPrevious_.bind(this));
  $('body').focusin(this.onChangeFocus_.bind(this));
}

SearchController.prototype.updateSearchCount_ = function() {
  if ($('#search-input').val().length === 0) {
    $('#search-counting').text('');
    return;
  }
  var searchCount = this.search_.getResultsCount();
  var searchIndex = this.search_.getCurrentIndex();
  $('#search-counting').text(chrome.i18n.getMessage('searchCounting',
      [searchIndex, searchCount]));
  if (searchCount === 0) {
    $('#search-counting').addClass('nomatches');
  } else {
    $('#search-counting').removeClass('nomatches');
  }
};

SearchController.prototype.findNext_ = function(opt_reverse) {
  if (this.search_.getQuery()) {
    this.search_.findNext(opt_reverse);
    this.showSearchCount_(opt_reverse);
  }
};

SearchController.prototype.onSearchButton_ = function() {
  this.search_.clear();
  var timeout = 200; // keep in sync with the CSS transition.
  setTimeout(function() {$('#search-input').select();}, timeout);
  $('header').addClass('search-active');

  return false;
};

SearchController.prototype.onChangeFocus_ = function() {
  if (document.activeElement === document.body ||
      $(document.activeElement).parents('.search-container').length) {
    return;
  }
  $('#search-input').val('');
  $('#search-counting').text('');
  $('header').removeClass('search-active');
  this.search_.clear();
};

SearchController.prototype.onChange_ = function() {
  var searchString = $('#search-input').val();
  if (searchString === this.search_.getQuery())
    return;
  if (searchString) {
    this.search_.find(searchString);
  } else {
    this.search_.clear();
  }
  this.showSearchCount_();
};

SearchController.prototype.onKeydown_ = function(e) {
  switch (e.keyCode) {
    case 13:
      e.stopPropagation();
      this.findNext_(e.shiftKey /* reverse */);
      break;

    case 27:
      e.stopPropagation();
      this.search_.unfocus();
      break;
  }
};

SearchController.prototype.onFindNext_ = function() {
  this.findNext_();
};

SearchController.prototype.onFindPrevious_ = function() {
  this.findNext_(true /* reverse */);
};
<commit_msg>Fix search count.<commit_after>/**
 * @constructor
 */
function SearchController(search) {
  this.search_ = search;

  $('#search-button').click(this.onSearchButton_.bind(this));
  $('#search-input').bind('input', this.onChange_.bind(this));
  $('#search-input').keydown(this.onKeydown_.bind(this));
  $('#search-next-button').click(this.onFindNext_.bind(this));
  $('#search-previous-button').click(this.onFindPrevious_.bind(this));
  $('body').focusin(this.onChangeFocus_.bind(this));
}

SearchController.prototype.updateSearchCount_ = function() {
  if ($('#search-input').val().length === 0) {
    $('#search-counting').text('');
    return;
  }
  var searchCount = this.search_.getResultsCount();
  var searchIndex = this.search_.getCurrentIndex();
  $('#search-counting').text(chrome.i18n.getMessage('searchCounting',
      [searchIndex, searchCount]));
  if (searchCount === 0) {
    $('#search-counting').addClass('nomatches');
  } else {
    $('#search-counting').removeClass('nomatches');
  }
};

SearchController.prototype.findNext_ = function(opt_reverse) {
  if (this.search_.getQuery()) {
    this.search_.findNext(opt_reverse);
    this.updateSearchCount_(opt_reverse);
  }
};

SearchController.prototype.onSearchButton_ = function() {
  this.search_.clear();
  var timeout = 200; // keep in sync with the CSS transition.
  setTimeout(function() {$('#search-input').select();}, timeout);
  $('header').addClass('search-active');

  return false;
};

SearchController.prototype.onChangeFocus_ = function() {
  if (document.activeElement === document.body ||
      $(document.activeElement).parents('.search-container').length) {
    return;
  }
  $('#search-input').val('');
  $('#search-counting').text('');
  $('header').removeClass('search-active');
  this.search_.clear();
};

SearchController.prototype.onChange_ = function() {
  var searchString = $('#search-input').val();
  if (searchString === this.search_.getQuery())
    return;
  if (searchString) {
    this.search_.find(searchString);
  } else {
    this.search_.clear();
  }
  this.updateSearchCount_();
};

SearchController.prototype.onKeydown_ = function(e) {
  switch (e.keyCode) {
    case 13:
      e.stopPropagation();
      this.findNext_(e.shiftKey /* reverse */);
      break;

    case 27:
      e.stopPropagation();
      this.search_.unfocus();
      break;
  }
};

SearchController.prototype.onFindNext_ = function() {
  this.findNext_();
};

SearchController.prototype.onFindPrevious_ = function() {
  this.findNext_(true /* reverse */);
};
<|endoftext|>


<commit_before>const keybindings = require('keybindings.js')
var webviews = require('webviews.js')
var webviewGestures = require('webviewGestures.js')
var browserUI = require('browserUI.js')
var focusMode = require('focusMode.js')
var modalMode = require('modalMode.js')
var tabEditor = require('navbar/tabEditor.js')

const defaultKeybindings = {
  initialize: function () {
    keybindings.defineShortcut('quitMin', function () {
      ipc.send('quit')
    })

    keybindings.defineShortcut('addTab', function () {
      /* new tabs can't be created in modal mode */
      if (modalMode.enabled()) {
        return
      }

      /* new tabs can't be created in focus mode */
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      browserUI.addTab()
    })

    keybindings.defineShortcut('addPrivateTab', function () {
      /* new tabs can't be created in modal mode */
      if (modalMode.enabled()) {
        return
      }

      /* new tabs can't be created in focus mode */
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      browserUI.addTab(tabs.add({
        private: true
      }))
    })

    keybindings.defineShortcut('duplicateTab', function () {
      if (modalMode.enabled()) {
        return
      }

      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      const sourceTab = tabs.get(tabs.getSelected())
      // strip tab id so that a new one is generated
      const newTab = tabs.add({ ...sourceTab, id: undefined })

      browserUI.addTab(newTab, { enterEditMode: false })
    })

    keybindings.defineShortcut('enterEditMode', function (e) {
      tabEditor.show(tabs.getSelected())
      return false
    })

    keybindings.defineShortcut('runShortcut', function (e) {
      tabEditor.show(tabs.getSelected(), '!')
    })

    keybindings.defineShortcut('closeTab', function (e) {
      browserUI.closeTab(tabs.getSelected())
    })

    keybindings.defineShortcut('moveTabLeft', function (e) {
      browserUI.moveTabLeft(tabs.getSelected())
    })

    keybindings.defineShortcut('moveTabRight', function (e) {
      browserUI.moveTabRight(tabs.getSelected())
    })

    keybindings.defineShortcut('restoreTab', function (e) {
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      var restoredTab = tasks.getSelected().tabHistory.pop()

      // The tab history stack is empty
      if (!restoredTab) {
        return
      }

      browserUI.addTab(tabs.add(restoredTab), {
        enterEditMode: false
      })
    })

    keybindings.defineShortcut('addToFavorites', function (e) {
      tabEditor.show(tabs.getSelected(), null, false) // we need to show the bookmarks button, which is only visible in edit mode
      tabEditor.container.querySelector('.bookmarks-button').click()
    })

    keybindings.defineShortcut('showBookmarks', function () {
      tabEditor.show(tabs.getSelected(), '!bookmarks ')
    })

    // cmd+x should switch to tab x. Cmd+9 should switch to the last tab

    for (var i = 1; i < 9; i++) {
      (function (i) {
        keybindings.defineShortcut({ keys: 'mod+' + i }, function (e) {
          var currentIndex = tabs.getIndex(tabs.getSelected())
          var newTab = tabs.getAtIndex(currentIndex + i) || tabs.getAtIndex(currentIndex - i)
          if (newTab) {
            browserUI.switchToTab(newTab.id)
          }
        })

        keybindings.defineShortcut({ keys: 'shift+mod+' + i }, function (e) {
          var currentIndex = tabs.getIndex(tabs.getSelected())
          var newTab = tabs.getAtIndex(currentIndex - i) || tabs.getAtIndex(currentIndex + i)
          if (newTab) {
            browserUI.switchToTab(newTab.id)
          }
        })
      })(i)
    }

    keybindings.defineShortcut('gotoLastTab', function (e) {
      browserUI.switchToTab(tabs.getAtIndex(tabs.count() - 1).id)
    })

    keybindings.defineShortcut('gotoFirstTab', function (e) {
      browserUI.switchToTab(tabs.getAtIndex(0).id)
    })

    keybindings.defineShortcut({ keys: 'esc' }, function (e) {
      if (webviews.placeholderRequests.length === 0 && document.activeElement.tagName !== 'INPUT') {
        webviews.callAsync(tabs.getSelected(), 'stop')
      }

      tabEditor.hide()

      if (modalMode.enabled() && modalMode.onDismiss) {
        modalMode.onDismiss()
        modalMode.onDismiss = null
      }

      // exit full screen mode
      webviews.callAsync(tabs.getSelected(), 'executeJavaScript', 'if(document.webkitIsFullScreen){document.webkitExitFullscreen()}')

      webviews.callAsync(tabs.getSelected(), 'focus')
    })

    keybindings.defineShortcut('goBack', function (d) {
      webviews.callAsync(tabs.getSelected(), 'goBack')
    })

    keybindings.defineShortcut('goForward', function (d) {
      webviews.callAsync(tabs.getSelected(), 'goForward')
    })

    keybindings.defineShortcut('switchToPreviousTab', function (d) {
      var currentIndex = tabs.getIndex(tabs.getSelected())
      var previousTab = tabs.getAtIndex(currentIndex - 1)

      if (previousTab) {
        browserUI.switchToTab(previousTab.id)
      } else {
        browserUI.switchToTab(tabs.getAtIndex(tabs.count() - 1).id)
      }
    })

    keybindings.defineShortcut('switchToNextTab', function (d) {
      var currentIndex = tabs.getIndex(tabs.getSelected())
      var nextTab = tabs.getAtIndex(currentIndex + 1)

      if (nextTab) {
        browserUI.switchToTab(nextTab.id)
      } else {
        browserUI.switchToTab(tabs.getAtIndex(0).id)
      }
    })

    keybindings.defineShortcut('switchToNextTask', function (d) {
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      const taskSwitchList = tasks.filter(t => !tasks.isCollapsed(t.id))

      const currentTaskIdx = taskSwitchList.findIndex(t => t.id === tasks.getSelected().id)

      const nextTask = taskSwitchList[currentTaskIdx + 1] || taskSwitchList[0]
      browserUI.switchToTask(nextTask.id)
    })

    keybindings.defineShortcut('switchToPreviousTask', function (d) {
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      const taskSwitchList = tasks.filter(t => !tasks.isCollapsed(t.id))

      const currentTaskIdx = taskSwitchList.findIndex(t => t.id === tasks.getSelected().id)
      taskCount = taskSwitchList.length

      const previousTask = taskSwitchList[currentTaskIdx - 1] || taskSwitchList[taskCount - 1]
      browserUI.switchToTask(previousTask.id)
    })

    // shift+option+cmd+x should switch to task x

    for (var i = 1; i < 10; i++) {
      (function (i) {
        keybindings.defineShortcut({ keys: 'shift+option+mod+' + i }, function (e) {
          if (focusMode.enabled()) {
            focusMode.warn()
            return
          }

          const taskSwitchList = tasks.filter(t => !tasks.isCollapsed(t.id))
          if (taskSwitchList[i - 1]) {
            browserUI.switchToTask(taskSwitchList[i - 1].id)
          }
        })
      })(i)
    }

    keybindings.defineShortcut('closeAllTabs', function (d) { // destroys all current tabs, and creates a new, empty tab. Kind of like creating a new window, except the old window disappears.
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      var tset = tabs.get()
      for (var i = 0; i < tset.length; i++) {
        browserUI.destroyTab(tset[i].id)
      }

      browserUI.addTab() // create a new, blank tab
    })

    var lastReload = 0

    keybindings.defineShortcut('reload', function () {
      var time = Date.now()

      // pressing mod+r twice in a row reloads the whole browser
      if (time - lastReload < 500) {
        ipc.send('destroyAllViews')
        ipc.invoke('reloadWindow')
      } else if (tabs.get(tabs.getSelected()).url.startsWith(webviews.internalPages.error)) {
        // reload the original page rather than show the error page again
        webviews.update(tabs.getSelected(), new URL(tabs.get(tabs.getSelected()).url).searchParams.get('url'))
      } else {
        // this can't be an error page, use the normal reload method
        webviews.callAsync(tabs.getSelected(), 'reload')
      }

      lastReload = time
    })

    keybindings.defineShortcut('reloadIgnoringCache', function () {
        webviews.callAsync(tabs.getSelected(), 'reloadIgnoringCache')
    })

    keybindings.defineShortcut({ keys: 'mod+=' }, function () {
      webviewGestures.zoomWebviewIn(tabs.getSelected())
    })

    keybindings.defineShortcut('showHistory', function () {
      tabEditor.show(tabs.getSelected(), '!history ')
    })
  }
}

module.exports = defaultKeybindings
<commit_msg>fix double zoom in<commit_after>const keybindings = require('keybindings.js')
var webviews = require('webviews.js')
var webviewGestures = require('webviewGestures.js')
var browserUI = require('browserUI.js')
var focusMode = require('focusMode.js')
var modalMode = require('modalMode.js')
var tabEditor = require('navbar/tabEditor.js')

const defaultKeybindings = {
  initialize: function () {
    keybindings.defineShortcut('quitMin', function () {
      ipc.send('quit')
    })

    keybindings.defineShortcut('addTab', function () {
      /* new tabs can't be created in modal mode */
      if (modalMode.enabled()) {
        return
      }

      /* new tabs can't be created in focus mode */
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      browserUI.addTab()
    })

    keybindings.defineShortcut('addPrivateTab', function () {
      /* new tabs can't be created in modal mode */
      if (modalMode.enabled()) {
        return
      }

      /* new tabs can't be created in focus mode */
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      browserUI.addTab(tabs.add({
        private: true
      }))
    })

    keybindings.defineShortcut('duplicateTab', function () {
      if (modalMode.enabled()) {
        return
      }

      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      const sourceTab = tabs.get(tabs.getSelected())
      // strip tab id so that a new one is generated
      const newTab = tabs.add({ ...sourceTab, id: undefined })

      browserUI.addTab(newTab, { enterEditMode: false })
    })

    keybindings.defineShortcut('enterEditMode', function (e) {
      tabEditor.show(tabs.getSelected())
      return false
    })

    keybindings.defineShortcut('runShortcut', function (e) {
      tabEditor.show(tabs.getSelected(), '!')
    })

    keybindings.defineShortcut('closeTab', function (e) {
      browserUI.closeTab(tabs.getSelected())
    })

    keybindings.defineShortcut('moveTabLeft', function (e) {
      browserUI.moveTabLeft(tabs.getSelected())
    })

    keybindings.defineShortcut('moveTabRight', function (e) {
      browserUI.moveTabRight(tabs.getSelected())
    })

    keybindings.defineShortcut('restoreTab', function (e) {
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      var restoredTab = tasks.getSelected().tabHistory.pop()

      // The tab history stack is empty
      if (!restoredTab) {
        return
      }

      browserUI.addTab(tabs.add(restoredTab), {
        enterEditMode: false
      })
    })

    keybindings.defineShortcut('addToFavorites', function (e) {
      tabEditor.show(tabs.getSelected(), null, false) // we need to show the bookmarks button, which is only visible in edit mode
      tabEditor.container.querySelector('.bookmarks-button').click()
    })

    keybindings.defineShortcut('showBookmarks', function () {
      tabEditor.show(tabs.getSelected(), '!bookmarks ')
    })

    // cmd+x should switch to tab x. Cmd+9 should switch to the last tab

    for (var i = 1; i < 9; i++) {
      (function (i) {
        keybindings.defineShortcut({ keys: 'mod+' + i }, function (e) {
          var currentIndex = tabs.getIndex(tabs.getSelected())
          var newTab = tabs.getAtIndex(currentIndex + i) || tabs.getAtIndex(currentIndex - i)
          if (newTab) {
            browserUI.switchToTab(newTab.id)
          }
        })

        keybindings.defineShortcut({ keys: 'shift+mod+' + i }, function (e) {
          var currentIndex = tabs.getIndex(tabs.getSelected())
          var newTab = tabs.getAtIndex(currentIndex - i) || tabs.getAtIndex(currentIndex + i)
          if (newTab) {
            browserUI.switchToTab(newTab.id)
          }
        })
      })(i)
    }

    keybindings.defineShortcut('gotoLastTab', function (e) {
      browserUI.switchToTab(tabs.getAtIndex(tabs.count() - 1).id)
    })

    keybindings.defineShortcut('gotoFirstTab', function (e) {
      browserUI.switchToTab(tabs.getAtIndex(0).id)
    })

    keybindings.defineShortcut({ keys: 'esc' }, function (e) {
      if (webviews.placeholderRequests.length === 0 && document.activeElement.tagName !== 'INPUT') {
        webviews.callAsync(tabs.getSelected(), 'stop')
      }

      tabEditor.hide()

      if (modalMode.enabled() && modalMode.onDismiss) {
        modalMode.onDismiss()
        modalMode.onDismiss = null
      }

      // exit full screen mode
      webviews.callAsync(tabs.getSelected(), 'executeJavaScript', 'if(document.webkitIsFullScreen){document.webkitExitFullscreen()}')

      webviews.callAsync(tabs.getSelected(), 'focus')
    })

    keybindings.defineShortcut('goBack', function (d) {
      webviews.callAsync(tabs.getSelected(), 'goBack')
    })

    keybindings.defineShortcut('goForward', function (d) {
      webviews.callAsync(tabs.getSelected(), 'goForward')
    })

    keybindings.defineShortcut('switchToPreviousTab', function (d) {
      var currentIndex = tabs.getIndex(tabs.getSelected())
      var previousTab = tabs.getAtIndex(currentIndex - 1)

      if (previousTab) {
        browserUI.switchToTab(previousTab.id)
      } else {
        browserUI.switchToTab(tabs.getAtIndex(tabs.count() - 1).id)
      }
    })

    keybindings.defineShortcut('switchToNextTab', function (d) {
      var currentIndex = tabs.getIndex(tabs.getSelected())
      var nextTab = tabs.getAtIndex(currentIndex + 1)

      if (nextTab) {
        browserUI.switchToTab(nextTab.id)
      } else {
        browserUI.switchToTab(tabs.getAtIndex(0).id)
      }
    })

    keybindings.defineShortcut('switchToNextTask', function (d) {
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      const taskSwitchList = tasks.filter(t => !tasks.isCollapsed(t.id))

      const currentTaskIdx = taskSwitchList.findIndex(t => t.id === tasks.getSelected().id)

      const nextTask = taskSwitchList[currentTaskIdx + 1] || taskSwitchList[0]
      browserUI.switchToTask(nextTask.id)
    })

    keybindings.defineShortcut('switchToPreviousTask', function (d) {
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      const taskSwitchList = tasks.filter(t => !tasks.isCollapsed(t.id))

      const currentTaskIdx = taskSwitchList.findIndex(t => t.id === tasks.getSelected().id)
      taskCount = taskSwitchList.length

      const previousTask = taskSwitchList[currentTaskIdx - 1] || taskSwitchList[taskCount - 1]
      browserUI.switchToTask(previousTask.id)
    })

    // shift+option+cmd+x should switch to task x

    for (var i = 1; i < 10; i++) {
      (function (i) {
        keybindings.defineShortcut({ keys: 'shift+option+mod+' + i }, function (e) {
          if (focusMode.enabled()) {
            focusMode.warn()
            return
          }

          const taskSwitchList = tasks.filter(t => !tasks.isCollapsed(t.id))
          if (taskSwitchList[i - 1]) {
            browserUI.switchToTask(taskSwitchList[i - 1].id)
          }
        })
      })(i)
    }

    keybindings.defineShortcut('closeAllTabs', function (d) { // destroys all current tabs, and creates a new, empty tab. Kind of like creating a new window, except the old window disappears.
      if (focusMode.enabled()) {
        focusMode.warn()
        return
      }

      var tset = tabs.get()
      for (var i = 0; i < tset.length; i++) {
        browserUI.destroyTab(tset[i].id)
      }

      browserUI.addTab() // create a new, blank tab
    })

    var lastReload = 0

    keybindings.defineShortcut('reload', function () {
      var time = Date.now()

      // pressing mod+r twice in a row reloads the whole browser
      if (time - lastReload < 500) {
        ipc.send('destroyAllViews')
        ipc.invoke('reloadWindow')
      } else if (tabs.get(tabs.getSelected()).url.startsWith(webviews.internalPages.error)) {
        // reload the original page rather than show the error page again
        webviews.update(tabs.getSelected(), new URL(tabs.get(tabs.getSelected()).url).searchParams.get('url'))
      } else {
        // this can't be an error page, use the normal reload method
        webviews.callAsync(tabs.getSelected(), 'reload')
      }

      lastReload = time
    })

    keybindings.defineShortcut('reloadIgnoringCache', function () {
      webviews.callAsync(tabs.getSelected(), 'reloadIgnoringCache')
    })

    keybindings.defineShortcut('showHistory', function () {
      tabEditor.show(tabs.getSelected(), '!history ')
    })
  }
}

module.exports = defaultKeybindings
<|endoftext|>


<commit_before>'use strict';

angular.module('ui.avgrund', []);
angular.module('ui.avgrund').directive('avgrund', function ($document) {
    return {
        template: '

',
        restrict: 'E',
        transclude: true,
        replace: true,
        scope: {
            ngShow: '='
        },
        /**
         * @param {angular.Scope} scope
         * @param {angular.element} element
         * @param {Attributes} attrs
         */
        link: function postLink(scope, element, attrs) {
            console.log(scope, element, attrs);

            var currentState = null;

            /**
             * @type {Node}
             */
            var _cover = document.querySelector('.avgrund-cover');

            /**
             * @type {angular.element}
             */
            var cover = null;

            if (_cover === null) {
                var _div = document.createElement('div');
                _div.className = 'avgrund-cover';
                document.body.appendChild(_div);
                _cover = document.querySelector('.avgrund-cover');
            }

            cover = angular.element(_cover);

            /**
             * @type {angular.element}
             */
            var container = angular.element(document.documentElement);
            container.addClass('avgrund-ready');

            function onDocumentKeyUp(event) {
                var ESCAPE_KEY_CODE = 27
                if (event.keyCode === ESCAPE_KEY_CODE) {
                    deactivate();
                }
            }

            // Deactivate on click outside
            function onDocumentClick(event) {
                if (event.target === cover) {
                    deactivate();
                }
            }

            function activate(state) {
                $document.bind('keyup', onDocumentKeyUp, false);
                $document.bind('click', onDocumentClick, false);
                $document.bind('touchstart', onDocumentClick, false);

                element.removeClass(currentState);
                element.addClass('no-transition');
                element.addClass(state);

                setTimeout(function () {
                    scope.$apply(function () {
                        element.removeClass('no-transition');
                        container.addClass('avgrund-active');
                    });
                }, 0);

                currentState = state;
            }

            function deactivate() {
                $document.bind('keyup', onDocumentKeyUp, false);
                $document.bind('click', onDocumentClick, false);
                $document.bind('touchstart', onDocumentClick, false);

                container.removeClass('avgrund-active');
                element.removeClass('avgrund-popup-animate');
            }

            scope.$watch('ngShow', function update(newValue, oldValue) {
                console.log('scope.$watch(ngShow)', newValue, oldValue);
                if (newValue) {
                    // show;
                    element.addClass('avgrund-popup-animate');
                    activate();
                } else {
                    // hide;
                    deactivate();
                }
            });

        }
    };
});
<commit_msg>Update<commit_after>'use strict';

angular.module('ui.avgrund', []);
angular.module('ui.avgrund').directive('avgrund', function ($document, $timeout) {
    return {
        template: '

',
        restrict: 'E',
        transclude: true,
        replace: true,
        scope: {
            ngShow: '='
        },
        /**
         * @param {angular.Scope} scope
         * @param {angular.element} element
         * @param {Attributes} attrs
         */
        link: function postLink(scope, element, attrs) {
            console.log(scope, element, attrs);

            /**
             * @type {Node}
             */
            var _cover = document.querySelector('.avgrund-cover');

            /**
             * @type {angular.element}
             */
            var cover = null;

            if (_cover === null) {
                var _div = document.createElement('div');
                _div.className = 'avgrund-cover';
                document.body.appendChild(_div);
                _cover = document.querySelector('.avgrund-cover');
            }

            cover = angular.element(_cover);

            /**
             * @type {angular.element}
             */
            var container = angular.element(document.documentElement);
            container.addClass('avgrund-ready');

            function onDocumentKeyUp(event) {
                var ESCAPE_KEY_CODE = 27;
                if (event.keyCode === ESCAPE_KEY_CODE) {
                    scope.$apply(function() {
                        deactivate();
                        scope.ngShow = false;
                    });
                }
            }

            // Deactivate on click outside
            function onDocumentClick(event) {
                if (event.target === _cover) {
                    scope.$apply(function() {
                        deactivate();
                        scope.ngShow = false;
                    });
                }
            }

            function activate(state) {
                $document.bind('keyup', onDocumentKeyUp, false);
                $document.bind('click', onDocumentClick, false);
                $document.bind('touchstart', onDocumentClick, false);

                element.addClass('no-transition');

                $timeout(function () {
                    element.removeClass('no-transition');
                    container.addClass('avgrund-active');
                }, 0);
            }

            function deactivate() {
                $document.unbind('keyup', onDocumentKeyUp, false);
                $document.unbind('click', onDocumentClick, false);
                $document.unbind('touchstart', onDocumentClick, false);

                container.removeClass('avgrund-active');
                element.removeClass('avgrund-popup-animate');
            }

            scope.$watch('ngShow', function update(newValue, oldValue) {
                console.log('scope.$watch(ngShow)', newValue, oldValue);
                if (newValue) {
                    // show;
                    element.addClass('avgrund-popup-animate');
                    activate();
                    console.log('activate();');
                } else if (!oldValue && !newValue) {
                    // do nothing, no change;
                    console.info('do nothing, no change;');
                } else {
                    // hide = deactivate();
                    deactivate();
                    console.info('deactivate();');
                }
            });

        }
    };
});
<|endoftext|>


<commit_before>const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');
const jsonpath = require('jsonpath');
const SplatNet = require('../splatnet');
const raven = require('raven');

const dataPath = path.resolve('public/data');
const splatnetAssetPath = path.resolve('public/assets/splatnet');

class Updater {
    constructor(options = {}) {
        this.options = options;
    }

    async update() {
        this.info('Updating data...');

        // Retrieve the data
        let data = await this.handleRequest(this.getData());

        // Filter the root keys if necessary
        data = this.filterRootKeys(data);

        // Convert the data to a JSON string
        let dataString = JSON.stringify(data);

        // Write the data to disk
        let localPath = `${dataPath}/${this.options.filename}`;
        this.writeFile(localPath, dataString);

        // Download images if necessary
        await this.downloadImages(data);

        this.info('Done.');
    }

    getData() {
        let splatnet = new SplatNet;
        return this.options.request(splatnet);
    }

    async handleRequest(request) {
        try {
            return await request;
        }
        catch (e) {
            // Send the error to Sentry
            raven.captureException(e);

            // Log the message to the console
            this.error(`Couldn't handle request: ${e.toString()}`);

            // Re-throw
            throw e;
        }
    }

    filterRootKeys(data) {
        if (this.options.rootKeys) {
            let result = {};

            for (let key of this.options.rootKeys) {
                let value = data[key];
                result[key] = (this.shouldIncludeRootValue(value)) ? value : null;
            }

            return result;
        }

        return data;
    }

    shouldIncludeRootValue(value) {
        if (!value)
            return false;

        // Remove timeline items with an importance of -1
        if (value.hasOwnProperty('importance'))
            return value.importance > -1;

        return true;
    }

    writeFile(filename, data) {
        mkdirp(path.dirname(filename));
        fs.writeFileSync(filename, data);
    }

    async downloadImages(data) {
        if (this.options.imagePaths) {
            for (let expression of this.options.imagePaths) {
                let splatnetImages = jsonpath.query(data, expression);
                for (let splatnetImage of splatnetImages)
                    await this.maybeDownloadImage(splatnetImage);
            }
        }
    }

    async maybeDownloadImage(imagePath) {
        if (!imagePath)
            return;

        let localPath = splatnetAssetPath + imagePath;

        // Check whether the image has already been downloaded
        if (fs.existsSync(localPath))
            return;

        // Otherwise, download the image
        try {
            this.info(`Downloading image: ${imagePath}`);
            let splatnet = new SplatNet;
            let image = await this.handleRequest(splatnet.getImage(imagePath));
            this.writeFile(localPath, image);
        } catch (e) { }
    }

    /**
     * Log helpers
     */

    formatLogMessage(message) {
        return `[Updater] [${this.options.name}] ${message}`;
    }

    log(message) {
        console.log(this.formatLogMessage(message));
    }

    info(message) {
        console.info(this.formatLogMessage(message));
    }

    error(message) {
        console.error(this.formatLogMessage(message));
    }
}

module.exports = Updater;
<commit_msg>Save images to the old path as well for now<commit_after>const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');
const jsonpath = require('jsonpath');
const SplatNet = require('../splatnet');
const raven = require('raven');

const dataPath = path.resolve('public/data');
const splatnetAssetPath = path.resolve('public/assets/splatnet');

class Updater {
    constructor(options = {}) {
        this.options = options;
    }

    async update() {
        this.info('Updating data...');

        // Retrieve the data
        let data = await this.handleRequest(this.getData());

        // Filter the root keys if necessary
        data = this.filterRootKeys(data);

        // Convert the data to a JSON string
        let dataString = JSON.stringify(data);

        // Write the data to disk
        let localPath = `${dataPath}/${this.options.filename}`;
        this.writeFile(localPath, dataString);

        // Download images if necessary
        await this.downloadImages(data);

        this.info('Done.');
    }

    getData() {
        let splatnet = new SplatNet;
        return this.options.request(splatnet);
    }

    async handleRequest(request) {
        try {
            return await request;
        }
        catch (e) {
            // Send the error to Sentry
            raven.captureException(e);

            // Log the message to the console
            this.error(`Couldn't handle request: ${e.toString()}`);

            // Re-throw
            throw e;
        }
    }

    filterRootKeys(data) {
        if (this.options.rootKeys) {
            let result = {};

            for (let key of this.options.rootKeys) {
                let value = data[key];
                result[key] = (this.shouldIncludeRootValue(value)) ? value : null;
            }

            return result;
        }

        return data;
    }

    shouldIncludeRootValue(value) {
        if (!value)
            return false;

        // Remove timeline items with an importance of -1
        if (value.hasOwnProperty('importance'))
            return value.importance > -1;

        return true;
    }

    writeFile(filename, data) {
        mkdirp(path.dirname(filename));
        fs.writeFileSync(filename, data);
    }

    async downloadImages(data) {
        if (this.options.imagePaths) {
            for (let expression of this.options.imagePaths) {
                let splatnetImages = jsonpath.query(data, expression);
                for (let splatnetImage of splatnetImages)
                    await this.maybeDownloadImage(splatnetImage);
            }
        }
    }

    async maybeDownloadImage(imagePath) {
        if (!imagePath)
            return;

        let localPath = splatnetAssetPath + imagePath;

        // Check whether the image has already been downloaded
        if (fs.existsSync(localPath))
            return;

        // Otherwise, download the image
        try {
            this.info(`Downloading image: ${imagePath}`);
            let splatnet = new SplatNet;
            let image = await this.handleRequest(splatnet.getImage(imagePath));
            this.writeFile(localPath, image);

            // Temporary: Also save the file to the old path for now
            // This allows for old versions of the site to continue downloading images
            let oldPath = path.resolve('public/assets/img/splatnet') + '/' + path.basename(imagePath);
            this.writeFile(oldPath, image);
        } catch (e) { }
    }

    /**
     * Log helpers
     */

    formatLogMessage(message) {
        return `[Updater] [${this.options.name}] ${message}`;
    }

    log(message) {
        console.log(this.formatLogMessage(message));
    }

    info(message) {
        console.info(this.formatLogMessage(message));
    }

    error(message) {
        console.error(this.formatLogMessage(message));
    }
}

module.exports = Updater;
<|endoftext|>


<commit_before>// Easy Responsive Tabs Plugin
// Author: Samson.Onna <Email : samson3d@gmail.com>
(function ($) {
    $.fn.extend({
        easyResponsiveTabs: function (options) {
            //Set the default values, use comma to separate the settings, example:
            var defaults = {
                type: 'default', //default, vertical, accordion;
                width: 'auto',
                fit: true
            }
            //Variables
            var options = $.extend(defaults, options);
            var opt = options, jtype = opt.type, jfit = opt.fit, jwidth = opt.width, vtabs = 'vertical', accord = 'accordion';

            //Main function
            this.each(function () {
                var $respTabs = $(this);
                $respTabs.find('ul.resp-tabs-list li').addClass('resp-tab-item');
                $respTabs.css({
                    'display': 'block',
                    'width': jwidth
                });

                $respTabs.find('.resp-tabs-container > div').addClass('resp-tab-content');
                jtab_options();
                //Properties Function
                function jtab_options() {
                    if (jtype == vtabs) {
                        $respTabs.addClass('resp-vtabs');
                    }
                    if (jfit == true) {
                        $respTabs.css({ width: '100%', margin: '0px' });
                    }
                    if (jtype == accord) {
                        $respTabs.addClass('resp-easy-accordion');
                        $respTabs.find('.resp-tabs-list').css('display', 'none');
                    }
                }

                //Assigning the h2 markup
                var $tabItemh2;
                $respTabs.find('.resp-tab-content').before("

");

                var itemCount = 0;
                $respTabs.find('.resp-accordion').each(function () {
                    $tabItemh2 = $(this);
                    var innertext = $respTabs.find('.resp-tab-item:eq(' + itemCount + ')').text();
                    $respTabs.find('.resp-accordion:eq(' + itemCount + ')').append(innertext);
                    $tabItemh2.attr('aria-controls', 'tab_item-' + (itemCount));
                    itemCount++;
                });

                //Assigning the 'aria-controls' to Tab items
                var count = 0,
                    $tabContent;
                $respTabs.find('.resp-tab-item').each(function () {
                    $tabItem = $(this);
                    $tabItem.attr('aria-controls', 'tab_item-' + (count));
                    $tabItem.attr('role', 'tab');

                    //First active tab
                    $respTabs.find('.resp-tab-item').first().addClass('resp-tab-active');
                    $respTabs.find('.resp-accordion').first().addClass('resp-tab-active');
                    $respTabs.find('.resp-tab-content').first().addClass('resp-tab-content-active').attr('style', 'display:block');

                    //Assigning the 'aria-labelledby' attr to tab-content
                    var tabcount = 0;
                    $respTabs.find('.resp-tab-content').each(function () {
                        $tabContent = $(this);
                        $tabContent.attr('aria-labelledby', 'tab_item-' + (tabcount));
                        tabcount++;
                    });
                    count++;
                });

                //Tab Click action function
                $respTabs.find("[role=tab]").each(function () {
                    var $currentTab = $(this);
                    $currentTab.click(function () {

                        var $tabAria = $currentTab.attr('aria-controls');

                        if ($currentTab.hasClass('resp-accordion') && $currentTab.hasClass('resp-tab-active')) {
                            $respTabs.find('.resp-tab-content-active').slideUp('', function () { $(this).addClass('resp-accordion-closed'); });
                            $currentTab.removeClass('resp-tab-active');
                            return false;
                        }
                        if (!$currentTab.hasClass('resp-tab-active') && $currentTab.hasClass('resp-accordion')) {
                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');
                            $respTabs.find('.resp-tab-content-active').slideUp().removeClass('resp-tab-content-active resp-accordion-closed');
                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');

                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').slideDown().addClass('resp-tab-content-active');
                        } else {
                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');
                            $respTabs.find('.resp-tab-content-active').removeAttr('style').removeClass('resp-tab-content-active').removeClass('resp-accordion-closed');
                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');
                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').addClass('resp-tab-content-active').attr('style', 'display:block');
                        }
                    });
                    //Window resize function
                    $(window).resize(function () {
                        $respTabs.find('.resp-accordion-closed').removeAttr('style');
                    });
                });
            });
        }
    });
})(jQuery);

<commit_msg>Use .html() instead of .text() to keep already used markup.<commit_after>// Easy Responsive Tabs Plugin
// Author: Samson.Onna <Email : samson3d@gmail.com>
(function ($) {
    $.fn.extend({
        easyResponsiveTabs: function (options) {
            //Set the default values, use comma to separate the settings, example:
            var defaults = {
                type: 'default', //default, vertical, accordion;
                width: 'auto',
                fit: true
            }
            //Variables
            var options = $.extend(defaults, options);
            var opt = options, jtype = opt.type, jfit = opt.fit, jwidth = opt.width, vtabs = 'vertical', accord = 'accordion';

            //Main function
            this.each(function () {
                var $respTabs = $(this);
                $respTabs.find('ul.resp-tabs-list li').addClass('resp-tab-item');
                $respTabs.css({
                    'display': 'block',
                    'width': jwidth
                });

                $respTabs.find('.resp-tabs-container > div').addClass('resp-tab-content');
                jtab_options();
                //Properties Function
                function jtab_options() {
                    if (jtype == vtabs) {
                        $respTabs.addClass('resp-vtabs');
                    }
                    if (jfit == true) {
                        $respTabs.css({ width: '100%', margin: '0px' });
                    }
                    if (jtype == accord) {
                        $respTabs.addClass('resp-easy-accordion');
                        $respTabs.find('.resp-tabs-list').css('display', 'none');
                    }
                }

                //Assigning the h2 markup
                var $tabItemh2;
                $respTabs.find('.resp-tab-content').before("

");

                var itemCount = 0;
                $respTabs.find('.resp-accordion').each(function () {
                    $tabItemh2 = $(this);
                    var innertext = $respTabs.find('.resp-tab-item:eq(' + itemCount + ')').html();
                    $respTabs.find('.resp-accordion:eq(' + itemCount + ')').append(innertext);
                    $tabItemh2.attr('aria-controls', 'tab_item-' + (itemCount));
                    itemCount++;
                });

                //Assigning the 'aria-controls' to Tab items
                var count = 0,
                    $tabContent;
                $respTabs.find('.resp-tab-item').each(function () {
                    $tabItem = $(this);
                    $tabItem.attr('aria-controls', 'tab_item-' + (count));
                    $tabItem.attr('role', 'tab');

                    //First active tab
                    $respTabs.find('.resp-tab-item').first().addClass('resp-tab-active');
                    $respTabs.find('.resp-accordion').first().addClass('resp-tab-active');
                    $respTabs.find('.resp-tab-content').first().addClass('resp-tab-content-active').attr('style', 'display:block');

                    //Assigning the 'aria-labelledby' attr to tab-content
                    var tabcount = 0;
                    $respTabs.find('.resp-tab-content').each(function () {
                        $tabContent = $(this);
                        $tabContent.attr('aria-labelledby', 'tab_item-' + (tabcount));
                        tabcount++;
                    });
                    count++;
                });

                //Tab Click action function
                $respTabs.find("[role=tab]").each(function () {
                    var $currentTab = $(this);
                    $currentTab.click(function () {

                        var $tabAria = $currentTab.attr('aria-controls');

                        if ($currentTab.hasClass('resp-accordion') && $currentTab.hasClass('resp-tab-active')) {
                            $respTabs.find('.resp-tab-content-active').slideUp('', function () { $(this).addClass('resp-accordion-closed'); });
                            $currentTab.removeClass('resp-tab-active');
                            return false;
                        }
                        if (!$currentTab.hasClass('resp-tab-active') && $currentTab.hasClass('resp-accordion')) {
                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');
                            $respTabs.find('.resp-tab-content-active').slideUp().removeClass('resp-tab-content-active resp-accordion-closed');
                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');

                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').slideDown().addClass('resp-tab-content-active');
                        } else {
                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');
                            $respTabs.find('.resp-tab-content-active').removeAttr('style').removeClass('resp-tab-content-active').removeClass('resp-accordion-closed');
                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');
                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').addClass('resp-tab-content-active').attr('style', 'display:block');
                        }
                    });
                    //Window resize function
                    $(window).resize(function () {
                        $respTabs.find('.resp-accordion-closed').removeAttr('style');
                    });
                });
            });
        }
    });
})(jQuery);

<|endoftext|>


<commit_before>function draw(){
    buffer.clearRect(
      0,
      0,
      width,
      height
    );

    // get player movement
    player_dx = 0;
    if(key_left){
        player_dx += x / 20;
    }
    if(key_right){
        player_dx -= x / 20;
    }

    // update player position
    player_position += player_dx;

    // make sure player stays in bounds
    if(player_position > x / 1.5){
        player_position = x / 1.5;

    }else if(player_position < -x / 1.5){
        player_position = -x / 1.5;
    }

    // draw ground grass
    buffer.fillStyle = '#131';
    buffer.fillRect(
      0,
      floor_position,
      width,
      y
    );

    // move player forward by moving splits closer
    var loop_counter = splits.length - 1;
    do{
        splits[loop_counter][2] -= .05;

        // if splits reach player, reset splits
        if(splits[loop_counter][2] < 0){
            splits[loop_counter][2] = 25;
            split_state[1] = 1;
        }
    }while(loop_counter--);

    // if it is time to reset split
    if(split_state[1]){
        // reset player position to start of new section
        player_position = 0;

        // switch split
        split_state[1] = 0;
        split_state[0] = !split_state[0];
    }

    buffer.fillStyle = split_state[0]
      ? '#323232'
      : '#646464';

    // precalculate left wall split position
    var precalc = (splits[0][0] * (1 / splits[0][2])) + x;

    // draw left wall extra bit
    if(player_position > 0){
        buffer.fillRect(
          0,
          0,
          1 + (player_position >= precalc ? precalc : player_position),
          height
        );
    }

    // draw left wall closer than split
    if(player_position < precalc){
        buffer.beginPath();
        buffer.moveTo(
          player_position,
          y - x
        );
        buffer.lineTo(
          precalc,
          (splits[0][1] * (1 / splits[0][2])) + y
        );
        buffer.lineTo(
          precalc,
          (splits[1][1] * (1 / splits[1][2])) + y
        );
        buffer.lineTo(
          player_position,
          y + x
        );
        buffer.closePath();
        buffer.fill();
    }

    // draw left wall further than split
    buffer.fillStyle = split_state[0]
      ? '#646464'
      : '#323232';
    buffer.beginPath();
    buffer.moveTo(
      precalc,
      (splits[0][1] * (1 / splits[0][2])) + y
    );
    buffer.lineTo(
      x,
      y
    );
    buffer.lineTo(
      precalc,
      (splits[1][1] * (1 / splits[1][2])) + y
    );
    buffer.closePath();
    buffer.fill();

    buffer.fillStyle = split_state[0]
      ? '#646464'
      : '#323232';

    // precalculate right wall split position
    precalc = (splits[2][0] * (1 / splits[2][2])) + x;

    // draw right wall extra bit
    if(player_position < 0){
        buffer.fillRect(
          width + player_position < precalc ? precalc - 1 : width + player_position - 1,
          0,
          -player_position,
          height
        );
    }

    // draw right wall closer than split
    if(width + player_position > precalc){
        buffer.beginPath();
        buffer.moveTo(
          width + player_position,
          y - x
        );
        buffer.lineTo(
          precalc,
          (splits[2][1] * (1 / splits[2][2])) + y
        );
        buffer.lineTo(
          precalc,
          (splits[3][1] * (1 / splits[3][2])) + y
        );
        buffer.lineTo(
          width + player_position,
          y + x
        );
        buffer.closePath();
        buffer.fill();
    }

    // draw right wall further than split
    buffer.fillStyle = split_state[0]
      ? '#323232'
      : '#646464';

    buffer.beginPath();
    buffer.moveTo(
      precalc,
      (splits[2][1] * (1 / splits[2][2])) + y
    );
    buffer.lineTo(
      x,
      y
    );
    buffer.lineTo(
      precalc,
      (splits[3][1] * (1 / splits[3][2])) + y
    );
    buffer.closePath();
    buffer.fill();

    // if frame counter is enabled, draw current frame count
    if(settings[2]){
        frame_counter += 1;
        buffer.fillStyle = '#fff';
        buffer.font = '23pt sans-serif';
        buffer.textAlign = 'left';
        buffer.textBaseline = 'top';
        buffer.fillText(
          frame_counter,
          5,
          5
        );
    }

    canvas.clearRect(
      0,
      0,
      width,
      height
    );
    canvas.drawImage(
      document.getElementById('buffer'),
      0,
      0
    );
}

function reset(){
    if(confirm('Reset settings?')){
        document.getElementById('audio-volume').value = 1;
        document.getElementById('frame-counter').checked = true;
        document.getElementById('movement-keys').value = 'AD';
        document.getElementById('ms-per-frame').value = 25;
        document.getElementById('restart-key').value = 'H';
        save();
    }
}

function resize(){
    if(mode > 0){
        height = window.innerHeight;
        document.getElementById('buffer').height = height;
        document.getElementById('canvas').height = height;
        y = height / 2;

        width = window.innerWidth;
        document.getElementById('buffer').width = width;
        document.getElementById('canvas').width = width;
        x = width / 2;
    }
}

function save(){
    var loop_counter = 1;
    do{
        j = [
          'audio-volume',
          'ms-per-frame'
        ][loop_counter];
        if(isNaN(document.getElementById(j).value)
          || document.getElementById(j).value === [1, 25][loop_counter]){
            window.localStorage.removeItem('fractalrunner-' + loop_counter);
            settings[i] = [
              1,
              25
            ][loop_counter];
            document.getElementById(j).value = settings[loop_counter];

        }else{
            settings[loop_counter] = parseFloat(document.getElementById(j).value);
            window.localStorage.setItem(
              'fractalrunner-' + loop_counter,
              settings[loop_counter]
            );
        }

        j = [
          'movement-keys',
          'restart-key'
        ][loop_counter];
        if(document.getElementById(j).value === ['AD', 'H'][loop_counter]){
            window.localStorage.removeItem('fractalrunner-' + (loop_counter + 4));
            settings[loop_counter + 4] = [
              'AD',
              'H'
            ][loop_counter];

        }else{
            settings[loop_counter + 4] = document.getElementById(j).value;
            window.localStorage.setItem(
              'fractalrunner-' + (loop_counter + 4),
              settings[loop_counter + 4]
            );
        }
    }while(loop_counter--);

    settings[2] = document.getElementById('frame-counter').checked;
    if(settings[2]){
        window.localStorage.removeItem('fractalrunner-2');

    }else{
        window.localStorage.setItem(
          'fractalrunner-2',
          0
        );
    }
}

function setmode(newmode, newgame){
    clearInterval(interval);

    split_state = [0, 0];

    mode = newmode;

    // new game mode
    if(mode > 0){
        splits = [
          [-50, -50, 25],
          [-50,  50, 25],
          [ 50, -50, 25],
          [ 50,  50, 25]
        ];

        frame_counter = 0;
        player_dx = 0;
        player_position = 0;

        if(newgame){
            save();

            document.getElementById('page').innerHTML = '<canvas id=canvas></canvas>';

            buffer = document.getElementById('buffer').getContext('2d');
            canvas = document.getElementById('canvas').getContext('2d');

            resize();
        }

        floor_position = y * (mode - 1);

        interval = setInterval(
          'draw()',
          settings[1]// milliseconds per frame
        );

    // main menu mode
    }else{
        buffer = 0;
        canvas = 0;

        document.getElementById('page').innerHTML = '

FractalRunner-2D3D.htm

Cling to the Ground
Walled Corridor

<input disabled style=border:0 value=ESC>Main Menu
<input id=movement-keys maxlength=2 value='
          + settings[3] + '>Move ←→
<input id=restart-key maxlength=1 value='
          + settings[4] + '>Restart

<input id=audio-volume max=1 min=0 step=.01 type=range value='
          + settings[0] + '>Audio
<input id=ms-per-frame value='
          + settings[1] + '>ms/Frame
<input '
          + (settings[2] ? 'checked ' : '') + 'id=frame-counter type=checkbox>Frame Counter
Reset Settings

';
    }
}

var buffer = 0;
var canvas = 0;
var floor_position = 0;
var frame_counter = 0;
var height = 0;
var interval = 0;
var j = 0;
var key_left = 0;
var key_right = 0;
var player_dx = 0;
var player_position = 0;
var mode = 0;
var split_state = [];
var splits = [];
var settings = [
  window.localStorage.getItem('fractalrunner-0') === null
    ? 1
    : parseFloat(window.localStorage.getItem('fractalrunner-0')),// audio volume
  window.localStorage.getItem('fractalrunner-1') === null
    ? 25
    : parseFloat(window.localStorage.getItem('fractalrunner-1')),// milliseconds per frame
  window.localStorage.getItem('fractalrunner-2') === null,// frame counter?
  window.localStorage.getItem('fractalrunner-3') === null
    ? 'AD'
    : window.localStorage.getItem('fractalrunner-3'),// movement keys
  window.localStorage.getItem('fractalrunner-4') === null
    ? 'H'
    : window.localStorage.getItem('fractalrunner-4')// restart key
];
var width = 0;
var x = 0;
var y = 0;

setmode(0, 1); // main menu

window.onkeydown = function(e){
    if(mode > 0){
        var key = window.event ? event : e;
        key = key.charCode ? key.charCode : key.keyCode;

        if(key === 27){// ESC
            setmode(0, 1); // main menu

        }else{
            key = String.fromCharCode(key);

            if(key === settings[3][0]){
                key_left = 1;

            }else if(key === settings[3][1]){
                key_right = 1;

            }else if(key === settings[4]){
                setmode(mode, 0); // new game

            }
        }
    }
};

window.onkeyup = function(e){
    var key = window.event ? event : e;
    key = String.fromCharCode(key.charCode ? key.charCode : key.keyCode);

    if(key === settings[3][0]){
        key_left = 0;

    }else if(key === settings[3][1]){
        key_right = 0;
    }
};

window.onresize = resize;
<commit_msg>replaced settings array with settings object, standardized localStorage keys<commit_after>function draw(){
    buffer.clearRect(
      0,
      0,
      width,
      height
    );

    // get player movement
    player_dx = 0;
    if(key_left){
        player_dx += x / 20;
    }
    if(key_right){
        player_dx -= x / 20;
    }

    // update player position
    player_position += player_dx;

    // make sure player stays in bounds
    if(player_position > x / 1.5){
        player_position = x / 1.5;

    }else if(player_position < -x / 1.5){
        player_position = -x / 1.5;
    }

    // draw ground grass
    buffer.fillStyle = '#131';
    buffer.fillRect(
      0,
      floor_position,
      width,
      y
    );

    // move player forward by moving splits closer
    var loop_counter = splits.length - 1;
    do{
        splits[loop_counter][2] -= .05;

        // if splits reach player, reset splits
        if(splits[loop_counter][2] < 0){
            splits[loop_counter][2] = 25;
            split_state[1] = 1;
        }
    }while(loop_counter--);

    // if it is time to reset split
    if(split_state[1]){
        // reset player position to start of new section
        player_position = 0;

        // switch split
        split_state[1] = 0;
        split_state[0] = !split_state[0];
    }

    buffer.fillStyle = split_state[0]
      ? '#323232'
      : '#646464';

    // precalculate left wall split position
    var precalc = (splits[0][0] * (1 / splits[0][2])) + x;

    // draw left wall extra bit
    if(player_position > 0){
        buffer.fillRect(
          0,
          0,
          1 + (player_position >= precalc ? precalc : player_position),
          height
        );
    }

    // draw left wall closer than split
    if(player_position < precalc){
        buffer.beginPath();
        buffer.moveTo(
          player_position,
          y - x
        );
        buffer.lineTo(
          precalc,
          (splits[0][1] * (1 / splits[0][2])) + y
        );
        buffer.lineTo(
          precalc,
          (splits[1][1] * (1 / splits[1][2])) + y
        );
        buffer.lineTo(
          player_position,
          y + x
        );
        buffer.closePath();
        buffer.fill();
    }

    // draw left wall further than split
    buffer.fillStyle = split_state[0]
      ? '#646464'
      : '#323232';
    buffer.beginPath();
    buffer.moveTo(
      precalc,
      (splits[0][1] * (1 / splits[0][2])) + y
    );
    buffer.lineTo(
      x,
      y
    );
    buffer.lineTo(
      precalc,
      (splits[1][1] * (1 / splits[1][2])) + y
    );
    buffer.closePath();
    buffer.fill();

    buffer.fillStyle = split_state[0]
      ? '#646464'
      : '#323232';

    // precalculate right wall split position
    precalc = (splits[2][0] * (1 / splits[2][2])) + x;

    // draw right wall extra bit
    if(player_position < 0){
        buffer.fillRect(
          width + player_position < precalc ? precalc - 1 : width + player_position - 1,
          0,
          -player_position,
          height
        );
    }

    // draw right wall closer than split
    if(width + player_position > precalc){
        buffer.beginPath();
        buffer.moveTo(
          width + player_position,
          y - x
        );
        buffer.lineTo(
          precalc,
          (splits[2][1] * (1 / splits[2][2])) + y
        );
        buffer.lineTo(
          precalc,
          (splits[3][1] * (1 / splits[3][2])) + y
        );
        buffer.lineTo(
          width + player_position,
          y + x
        );
        buffer.closePath();
        buffer.fill();
    }

    // draw right wall further than split
    buffer.fillStyle = split_state[0]
      ? '#323232'
      : '#646464';

    buffer.beginPath();
    buffer.moveTo(
      precalc,
      (splits[2][1] * (1 / splits[2][2])) + y
    );
    buffer.lineTo(
      x,
      y
    );
    buffer.lineTo(
      precalc,
      (splits[3][1] * (1 / splits[3][2])) + y
    );
    buffer.closePath();
    buffer.fill();

    // if frame counter is enabled, draw current frame count
    if(settings['frame-counter']){
        frame_counter += 1;
        buffer.fillStyle = '#fff';
        buffer.font = '23pt sans-serif';
        buffer.textAlign = 'left';
        buffer.textBaseline = 'top';
        buffer.fillText(
          frame_counter,
          5,
          5
        );
    }

    canvas.clearRect(
      0,
      0,
      width,
      height
    );
    canvas.drawImage(
      document.getElementById('buffer'),
      0,
      0
    );
}

function reset(){
    if(confirm('Reset settings?')){
        document.getElementById('audio-volume').value = 1;
        document.getElementById('frame-counter').checked = true;
        document.getElementById('movement-keys').value = 'AD';
        document.getElementById('ms-per-frame').value = 25;
        document.getElementById('restart-key').value = 'H';
        save();
    }
}

function resize(){
    if(mode > 0){
        height = window.innerHeight;
        document.getElementById('buffer').height = height;
        document.getElementById('canvas').height = height;
        y = height / 2;

        width = window.innerWidth;
        document.getElementById('buffer').width = width;
        document.getElementById('canvas').width = width;
        x = width / 2;
    }
}

function save(){
    // Save audio-volume setting.
    if(document.getElementById('audio-volume').value === 1){
        window.localStorage.removeItem('FractalRunner-2D3D.htm-audio-volume');
        settings['audio-volume'] = 1;

    }else{
        settings['audio-volume'] = parseFloat(document.getElementById('audio-volume').value);
        window.localStorage.setItem(
          'FractalRunner-2D3D.htm-audio-volume',
          settings['audio-volume']
        );
    }

    // Save frame-counter setting.
    if(document.getElementById('frame-counter').checked){
        window.localStorage.removeItem('FractalRunner-2D3D.htm-frame-counter');
        settings['frame-counter'] = false;

    }else{
        settings['frame-counter'] = true;
        window.localStorage.setItem(
          'FractalRunner-2D3D.htm-frame-counter',
          1
        );
    }

    // Save movement-keys setting.
    if(document.getElementById('movement-keys').value == 'AD'){
        window.localStorage.removeItem('FractalRunner-2D3D.htm-movement-keys');
        settings['movement-keys'] = 'AD';

    }else{
        settings['movement-keys'] = document.getElementById('movement-keys').value;
        window.localStorage.setItem(
          'FractalRunner-2D3D.htm-movement-keys',
          settings['movement-keys']
        );
    }

    // Save ms-per-frame setting.
    if(document.getElementById('ms-per-frame').value == 25
      || isNaN(document.getElementById('ms-per-frame').value)
      || document.getElementById('ms-per-frame').value < 1){
        window.localStorage.removeItem('FractalRunner-2D3D.htm-ms-per-frame');
        document.getElementById('ms-per-frame').value = 25;
        settings['ms-per-frame'] = 25;

    }else{
        settings['ms-per-frame'] = parseInt(document.getElementById('ms-per-frame').value);
        window.localStorage.setItem(
          'FractalRunner-2D3D.htm-ms-per-frame',
          settings['ms-per-frame']
        );
    }

    // Save restart-key setting.
    if(document.getElementById('restart-key').value == 'AD'){
        window.localStorage.removeItem('FractalRunner-2D3D.htm-restart-key');
        settings['restart-key'] = 'H';

    }else{
        settings['restart-key'] = document.getElementById('restart-key').value;
        window.localStorage.setItem(
          'FractalRunner-2D3D.htm-restart-key',
          settings['restart-key']
        );
    }
}

function setmode(newmode, newgame){
    clearInterval(interval);

    split_state = [0, 0];

    mode = newmode;

    // new game mode
    if(mode > 0){
        splits = [
          [-50, -50, 25],
          [-50,  50, 25],
          [ 50, -50, 25],
          [ 50,  50, 25]
        ];

        frame_counter = 0;
        player_dx = 0;
        player_position = 0;

        if(newgame){
            save();

            document.getElementById('page').innerHTML = '<canvas id=canvas></canvas>';

            buffer = document.getElementById('buffer').getContext('2d');
            canvas = document.getElementById('canvas').getContext('2d');

            resize();
        }

        floor_position = y * (mode - 1);

        interval = setInterval(
          'draw()',
          settings['ms-per-frame']
        );

    // main menu mode
    }else{
        buffer = 0;
        canvas = 0;

        document.getElementById('page').innerHTML = '

FractalRunner-2D3D.htm

Cling to the Ground
Walled Corridor

<input disabled style=border:0 value=ESC>Main Menu
<input id=movement-keys maxlength=2 value='
          + settings['movement-keys'] + '>Move ←→
<input id=restart-key maxlength=1 value='
          + settings['restart-key'] + '>Restart

<input id=audio-volume max=1 min=0 step=.01 type=range value='
          + settings['audio-volume'] + '>Audio
<input id=ms-per-frame value='
          + settings['ms-per-frame'] + '>ms/Frame
<input '
          + (settings['frame-counter'] ? 'checked ' : '') + 'id=frame-counter type=checkbox>Frame Counter
Reset Settings

';
    }
}

var buffer = 0;
var canvas = 0;
var floor_position = 0;
var frame_counter = 0;
var height = 0;
var interval = 0;
var j = 0;
var key_left = 0;
var key_right = 0;
var player_dx = 0;
var player_position = 0;
var mode = 0;
var split_state = [];
var splits = [];
var settings = {
  'audio-volume': window.localStorage.getItem('FractalRunner-2D3D.htm-audio-volume') === null
    ? 1
    : parseFloat(window.localStorage.getItem('FractalRunner-2D3D.htm-audio-volume')),
  'frame-counter': window.localStorage.getItem('FractalRunner-2D3D.htm-frame-counter') === null,
  'movement-keys': window.localStorage.getItem('FractalRunner-2D3D.htm-movement-keys') === null
    ? 'AD'
    : window.localStorage.getItem('FractalRunner-2D3D.htm-movement-keys'),
  'ms-per-frame': window.localStorage.getItem('FractalRunner-2D3D.htm-ms-per-frame') === null
    ? 25
    : parseFloat(window.localStorage.getItem('FractalRunner-2D3D.htm-ms-per-frame')),
  'restart-key': window.localStorage.getItem('FractalRunner-2D3D.htm-restart-key') === null
    ? 'H'
    : window.localStorage.getItem('FractalRunner-2D3D.htm-restart-key'),
};
var width = 0;
var x = 0;
var y = 0;

setmode(0, 1); // main menu

window.onkeydown = function(e){
    if(mode > 0){
        var key = window.event ? event : e;
        key = key.charCode ? key.charCode : key.keyCode;

        if(key === 27){// ESC
            setmode(0, 1); // main menu

        }else{
            key = String.fromCharCode(key);

            if(key === settings['movement-keys'][0]){
                key_left = 1;

            }else if(key === settings['movement-keys'][1]){
                key_right = 1;

            }else if(key === settings['restart-key']){
                setmode(mode, 0); // new game

            }
        }
    }
};

window.onkeyup = function(e){
    var key = window.event ? event : e;
    key = String.fromCharCode(key.charCode ? key.charCode : key.keyCode);

    if(key === settings['movement-keys'][0]){
        key_left = 0;

    }else if(key === settings['movement-keys'][1]){
        key_right = 0;
    }
};

window.onresize = resize;
<|endoftext|>