<commit_before>describe("luga.ajaxform", function(){

	it("Lives inside its own namespace", function(){
		expect(luga.ajaxform).toBeDefined();
	});

	describe(".version", function(){
		it("Reports the current version number", function(){
			expect(luga.ajaxform.version).toBeDefined();
		});
	});

	describe(".Sender", function(){

		var basicSender, attributesSender, customSender, configSender, customSuccessHandler, customErrorHandler, customBefore, customAfter;

		beforeEach(function(){
			loadFixtures("ajaxform/form.htm");

			basicSender = new luga.ajaxform.Sender({
				formNode: jQuery("#basic")
			});

			attributesSender = new luga.ajaxform.Sender({
				formNode: jQuery("#attributes")
			});

			customSender = new luga.ajaxform.Sender({
				formNode: jQuery("#customAttributes")
			});

			configSender = new luga.ajaxform.Sender({
				formNode: jQuery("#basic"),
				action: "configAction",
				method: "PUT",
				timeout: 40000,
				success: "customSuccessHandler",
				successmsg: "Success",
				error: "customErrorHandler",
				errormsg: "Error",
				before: "customBefore",
				after: "customAfter"
			});

			customSuccessHandler = function(){
			};
			customErrorHandler = function(){
			};
			customBefore = function(){
			};
			customAfter = function(){
			};

		});

		it("Throws an exception if the associated form node does not exists", function(){
			expect(function(){
				var formHandler = new luga.ajaxform.Sender({
					formNode: jQuery("#missing")
				});
			}).toThrow();
		});

		describe("Accepts an Options object as single argument", function(){

			describe("options.formNode", function(){

				it("Is mandatory", function(){
					expect(function(){
						var formHandler = new luga.ajaxform.Sender({});
					}).toThrow();
				});

			});

			describe("options.action either:", function(){

				it("Default to the current URL", function(){
					expect(basicSender.config.action).toEqual(document.location.href);
				});
				it("Retrieves the value from the form's action attribute", function(){
					expect(attributesSender.config.action).toEqual("attributeAction");
				});
				it("Retrieves the value from the form's data-lugajax-action custom attribute", function(){
					expect(customSender.config.action).toEqual("customAction");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.action).toEqual("configAction");
				});

			});

			describe("options.method either:", function(){

				it("Default to GET", function(){
					expect(basicSender.config.method).toEqual("GET");
				});
				it("Retrieves the value from the form's method attribute", function(){
					expect(attributesSender.config.method).toEqual("POST");
				});

				it("Retrieves the value from the form's data-lugajax-method custom attribute", function(){
					expect(customSender.config.method).toEqual("DELETE");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.method).toEqual("PUT");
				});

			});

			describe("options.timeout either:", function(){

				it("Default to 30s", function(){
					expect(basicSender.config.timeout).toEqual(30000);
				});
				it("Retrieves the value from the form's data-lugajax-timeout custom attribute", function(){
					expect(customSender.config.timeout).toEqual(20000);
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.timeout).toEqual(40000);
				});

			});

			describe("options.success either:", function(){

				it("Default to: 'luga.ajaxform.handlers.replaceForm'", function(){
					expect(basicSender.config.success).toEqual('luga.ajaxform.handlers.replaceForm');
				});
				it("Retrieves the value from the form's data-lugajax-success custom attribute", function(){
					expect(customSender.config.success).toEqual("customSuccessHandler");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.success).toEqual("customSuccessHandler");
				});

			});

			describe("options.successmsg either:", function(){

				it("Default to: " + luga.ajaxform.CONST.MESSAGES.SUCCESS, function(){
					expect(basicSender.config.successmsg).toEqual(luga.ajaxform.CONST.MESSAGES.SUCCESS);
				});
				it("Retrieves the value from the form's data-lugajax-successmsg custom attribute", function(){
					expect(customSender.config.successmsg).toEqual("Test success");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.successmsg).toEqual("Success");
				});

			});

			describe("options.error either:", function(){

				it("Default to: 'luga.ajaxform.handlers.errorAlert'", function(){
					expect(basicSender.config.error).toEqual('luga.ajaxform.handlers.errorAlert');
				});
				it("Retrieves the value from the form's data-lugajax-error custom attribute", function(){
					expect(customSender.config.error).toEqual("customErrorHandler");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.error).toEqual("customErrorHandler");
				});

			});

			describe("options.errormsg either:", function(){

				it("Default to: " + luga.ajaxform.CONST.MESSAGES.ERROR, function(){
					expect(basicSender.config.errormsg).toEqual(luga.ajaxform.CONST.MESSAGES.ERROR);
				});
				it("Retrieves the value from the form's data-lugajax-errormsg custom attribute", function(){
					expect(customSender.config.errormsg).toEqual("Test error");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.errormsg).toEqual("Error");
				});

			});

			describe("options.before either:", function(){

				it("Default to: null", function(){
					expect(basicSender.config.before).toBeNull();
				});
				it("Retrieves the value from the form's data-lugajax-before custom attribute", function(){
					expect(customSender.config.before).toEqual("customBefore");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.before).toEqual("customBefore");
				});

			});

			describe("options.after either:", function(){

				it("Default to: null", function(){
					expect(basicSender.config.after).toBeNull();
				});
				it("Retrieves the value from the form's data-lugajax-after custom attribute", function(){
					expect(customSender.config.after).toEqual("customAfter");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.after).toEqual("customAfter");
				});

			});

		});

		describe(".send()", function(){

			xit("Is invoked whenever the form is submitted", function(){
				var formHandler = new luga.ajaxform.Sender({formNode: jQuery("#basicAction")});

				jQuery("#basicAction")[0].submit();
				expect(basicSender.config.after).toBeNull();
			});

		});

	});

});<commit_msg>Ajaxfor: clean-up tests<commit_after>describe("luga.ajaxform", function(){

	it("Lives inside its own namespace", function(){
		expect(luga.ajaxform).toBeDefined();
	});

	describe(".version", function(){
		it("Reports the current version number", function(){
			expect(luga.ajaxform.version).toBeDefined();
		});
	});

	describe(".Sender", function(){

		var basicSender, attributesSender, customSender, configSender, customSuccessHandler, customErrorHandler, customBefore, customAfter;

		beforeEach(function(){
			loadFixtures("ajaxform/form.htm");

			basicSender = new luga.ajaxform.Sender({
				formNode: jQuery("#basic")
			});

			attributesSender = new luga.ajaxform.Sender({
				formNode: jQuery("#attributes")
			});

			customSender = new luga.ajaxform.Sender({
				formNode: jQuery("#customAttributes")
			});

			configSender = new luga.ajaxform.Sender({
				formNode: jQuery("#basic"),
				action: "configAction",
				method: "PUT",
				timeout: 40000,
				success: "customSuccessHandler",
				successmsg: "Success",
				error: "customErrorHandler",
				errormsg: "Error",
				before: "customBefore",
				after: "customAfter"
			});

			customSuccessHandler = function(){
			};
			customErrorHandler = function(){
			};
			customBefore = function(){
			};
			customAfter = function(){
			};

		});

		it("Throws an exception if the associated form node does not exists", function(){
			expect(function(){
				var formHandler = new luga.ajaxform.Sender({
					formNode: jQuery("#missing")
				});
			}).toThrow();
		});

		describe("Accepts an Options object as single argument", function(){

			describe("options.formNode", function(){

				it("Is mandatory", function(){
					expect(function(){
						var formHandler = new luga.ajaxform.Sender({});
					}).toThrow();
				});

			});

			describe("options.action either:", function(){

				it("Default to the current URL", function(){
					expect(basicSender.config.action).toEqual(document.location.href);
				});
				it("Retrieves the value from the form's action attribute", function(){
					expect(attributesSender.config.action).toEqual("attributeAction");
				});
				it("Retrieves the value from the form's data-lugajax-action custom attribute", function(){
					expect(customSender.config.action).toEqual("customAction");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.action).toEqual("configAction");
				});

			});

			describe("options.method either:", function(){

				it("Default to GET", function(){
					expect(basicSender.config.method).toEqual("GET");
				});
				it("Retrieves the value from the form's method attribute", function(){
					expect(attributesSender.config.method).toEqual("POST");
				});

				it("Retrieves the value from the form's data-lugajax-method custom attribute", function(){
					expect(customSender.config.method).toEqual("DELETE");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.method).toEqual("PUT");
				});

			});

			describe("options.timeout either:", function(){

				it("Default to 30s", function(){
					expect(basicSender.config.timeout).toEqual(30000);
				});
				it("Retrieves the value from the form's data-lugajax-timeout custom attribute", function(){
					expect(customSender.config.timeout).toEqual(20000);
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.timeout).toEqual(40000);
				});

			});

			describe("options.success either:", function(){

				it("Default to: 'luga.ajaxform.handlers.replaceForm'", function(){
					expect(basicSender.config.success).toEqual('luga.ajaxform.handlers.replaceForm');
				});
				it("Retrieves the value from the form's data-lugajax-success custom attribute", function(){
					expect(customSender.config.success).toEqual("customSuccessHandler");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.success).toEqual("customSuccessHandler");
				});

			});

			describe("options.successmsg either:", function(){

				it("Default to: " + luga.ajaxform.CONST.MESSAGES.SUCCESS, function(){
					expect(basicSender.config.successmsg).toEqual(luga.ajaxform.CONST.MESSAGES.SUCCESS);
				});
				it("Retrieves the value from the form's data-lugajax-successmsg custom attribute", function(){
					expect(customSender.config.successmsg).toEqual("Test success");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.successmsg).toEqual("Success");
				});

			});

			describe("options.error either:", function(){

				it("Default to: 'luga.ajaxform.handlers.errorAlert'", function(){
					expect(basicSender.config.error).toEqual('luga.ajaxform.handlers.errorAlert');
				});
				it("Retrieves the value from the form's data-lugajax-error custom attribute", function(){
					expect(customSender.config.error).toEqual("customErrorHandler");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.error).toEqual("customErrorHandler");
				});

			});

			describe("options.errormsg either:", function(){

				it("Default to: " + luga.ajaxform.CONST.MESSAGES.ERROR, function(){
					expect(basicSender.config.errormsg).toEqual(luga.ajaxform.CONST.MESSAGES.ERROR);
				});
				it("Retrieves the value from the form's data-lugajax-errormsg custom attribute", function(){
					expect(customSender.config.errormsg).toEqual("Test error");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.errormsg).toEqual("Error");
				});

			});

			describe("options.before either:", function(){

				it("Default to: null", function(){
					expect(basicSender.config.before).toBeNull();
				});
				it("Retrieves the value from the form's data-lugajax-before custom attribute", function(){
					expect(customSender.config.before).toEqual("customBefore");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.before).toEqual("customBefore");
				});

			});

			describe("options.after either:", function(){

				it("Default to: null", function(){
					expect(basicSender.config.after).toBeNull();
				});
				it("Retrieves the value from the form's data-lugajax-after custom attribute", function(){
					expect(customSender.config.after).toEqual("customAfter");
				});
				it("Uses the value specified inside the option argument", function(){
					expect(configSender.config.after).toEqual("customAfter");
				});

			});

		});

		describe(".send()", function(){

		});

	});

});<|endoftext|>


<commit_before>import { evaluateXPathToNumber, evaluateXPathToBoolean } from 'fontoxpath';
import * as slimdom from 'slimdom';

const cacheId = {};
describe('performance', () => {
	// Warm up the cache
	// Counting to 10 milion takes a couple of seconds.
	before(function () {
		this.timeout(100000);
		evaluateXPathToNumber('count(0 to 10000000)', document, null, {}, {cacheId});
	});

	it('can reuse cached results', function () {
		evaluateXPathToNumber('count(0 to 10000000)', document, null, {}, {cacheId});
	});

	it('can reuse cached sub-results', function () {
		chai.assert.isTrue(evaluateXPathToBoolean('10000001 = count(0 to 10000000)', document, null, {}, {cacheId}));
	});
});

function timeXPath (xpath, document) {
	const then = performance.now();
	chai.assert(evaluateXPathToBoolean(xpath, document), `The passed XPath ${xpath} should resolve to true`);
	const now =  performance.now();
	return now - then;
}

function fillDocument (document, element, depth) {
	element.setAttribute('depth', depth);
	if (depth === 0) {
		return element;
	}
	var prototypeElement = element.appendChild(
		fillDocument(
			document,
			document.createElement('ele'),
			depth - 1));

	for (let i = 1, l = 10; i < l; ++i) {
		element.appendChild(prototypeElement.cloneNode(true));
	}
	return element;
}
function runTests (document) {
	let fullTraversalCost;
	before(function () {
		this.timeout(30000);
		fillDocument(document, document.appendChild(document.createElement('root')), 5);

		fullTraversalCost = timeXPath('/descendant::element() => count() > 10', document);
	});

	it('Makes queries exit early by streaming them and only consuming the first item', function () {
		this.timeout(10000);
		chai.assert.isAtMost(
			timeXPath('(/descendant::element()["4" = @depth]) => head() => count() = 1', document),
			fullTraversalCost * 0.5,
			'Revaluating a filtered xpath must not cost significantly more then an unfiltered one');
	});

	it('Saves variable results', function () {
		this.timeout(10000);
		const timeWithoutExtraSteps = timeXPath('(/descendant::*) => count() > 10', document);
		// Variables should only be evaluated once, not n times
		chai.assert.isAtMost(
			timeXPath('let $c := (/descendant::*) => count() return $c + $c + $c + $c + $c + $c', document),
			timeWithoutExtraSteps * 3);
	});

	it('can memoize context free expressions', () => {
		// The filters use no context, so they must be instant
		chai.assert.isAtMost(timeXPath('(1 to 10000)[1 mod 2][1] or true()', document), 15);
	});
}

describe('performance of descendant axis', () => {
	describe('in browser DOM', () => runTests(window.document.implementation.createDocument(null, null)));
	describe('in slimdom', () => runTests(new slimdom.Document()));
});
<commit_msg>Disable frequently failing performance test<commit_after>import { evaluateXPathToNumber, evaluateXPathToBoolean } from 'fontoxpath';
import * as slimdom from 'slimdom';

const cacheId = {};
describe('performance', () => {
	// Warm up the cache
	// Counting to 10 milion takes a couple of seconds.
	before(function () {
		this.timeout(100000);
		evaluateXPathToNumber('count(0 to 10000000)', document, null, {}, {cacheId});
	});

	it('can reuse cached results', function () {
		evaluateXPathToNumber('count(0 to 10000000)', document, null, {}, {cacheId});
	});

	it('can reuse cached sub-results', function () {
		chai.assert.isTrue(evaluateXPathToBoolean('10000001 = count(0 to 10000000)', document, null, {}, {cacheId}));
	});
});

function timeXPath (xpath, document) {
	const then = performance.now();
	chai.assert(evaluateXPathToBoolean(xpath, document), `The passed XPath ${xpath} should resolve to true`);
	const now =  performance.now();
	return now - then;
}

function fillDocument (document, element, depth) {
	element.setAttribute('depth', depth);
	if (depth === 0) {
		return element;
	}
	var prototypeElement = element.appendChild(
		fillDocument(
			document,
			document.createElement('ele'),
			depth - 1));

	for (let i = 1, l = 10; i < l; ++i) {
		element.appendChild(prototypeElement.cloneNode(true));
	}
	return element;
}
function runTests (document) {
	let fullTraversalCost;
	before(function () {
		this.timeout(30000);
		fillDocument(document, document.appendChild(document.createElement('root')), 5);

		fullTraversalCost = timeXPath('/descendant::element() => count() > 10', document);
	});

	it('Makes queries exit early by streaming them and only consuming the first item', function () {
		this.timeout(10000);
		chai.assert.isAtMost(
			timeXPath('(/descendant::element()["4" = @depth]) => head() => count() = 1', document),
			fullTraversalCost * 0.5,
			'Revaluating a filtered xpath must not cost significantly more then an unfiltered one');
	});

	it('Saves variable results', function () {
		this.timeout(10000);
		const timeWithoutExtraSteps = timeXPath('(/descendant::*) => count() > 10', document);
		// Variables should only be evaluated once, not n times
		chai.assert.isAtMost(
			timeXPath('let $c := (/descendant::*) => count() return $c + $c + $c + $c + $c + $c', document),
			timeWithoutExtraSteps * 3);
	});

	it.skip('can memoize context free expressions', () => {
		// Disables because of a rather unstable CI environment
		// The filters use no context, so they must be instant
		chai.assert.isAtMost(timeXPath('(1 to 10000)[1 mod 2][1] or true()', document), 15);
	});
}

describe('performance of descendant axis', () => {
	describe('in browser DOM', () => runTests(window.document.implementation.createDocument(null, null)));
	describe('in slimdom', () => runTests(new slimdom.Document()));
});
<|endoftext|>


<commit_before>
let sinon from 'sinon/pkg/sinon.js');
var _ from 'lodash');
import React from 'react';
var TestUtils from 'react-addons-test-utils');
var Geo from '../../../../lib/js/app/components/common/geo.js');
var TestHelpers from '../../../support/TestHelpers');

describe('components/common/geo', () => {
  before(() => {
    this.filter = TestHelpers.createFilters().geo;
    this.component = TestUtils.renderIntoDocument(<Geo filter={this.filter} handleGeoSelection={sinon.stub} />);
  });

  describe('setup', () => {
    it('is of the right type', () => {
      assert.isTrue(TestUtils.isCompositeComponentWithType(this.component, Geo));
    });
  });
  it('has three inputs', () => {
    assert.lengthOf(TestUtils.scryRenderedDOMComponentsWithTag(this.component, 'input'), 3);
  });
});
<commit_msg>fix tests for geo<commit_after>
import _ from 'lodash';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
import Geo from '../../../../lib/js/app/components/common/geo.js';
import TestHelpers from '../../../support/TestHelpers';

describe('components/common/geo', () => {
  let filter;
  let component;
  beforeAll(() => {
    filter = TestHelpers.createFilters().geo;
    component = TestUtils.renderIntoDocument(<Geo filter={filter} handleGeoSelection={jest.fn()} />);
  });

  describe('setup', () => {
    it('is of the right type', () => {
      expect(TestUtils.isCompositeComponentWithType(component, Geo)).toBe(true);
    });
  });
  it('has three inputs', () => {
    expect(TestUtils.scryRenderedDOMComponentsWithTag(component, 'input')).toHaveLength(3);
  });
});
<|endoftext|>


<commit_before>import Vue from 'vue/dist/vue.common.js';
import InfiniteLoading from '../../../src/components/InfiniteLoading';

function isShow(elm) {
  const styles = getComputedStyle(elm);

  return styles.getPropertyValue('display') !== 'none';
}

describe('InfiniteLoading.vue', () => {
  let vm;
  const initConf = {
    data() {
      return {
        list: [],
        distance: 50,
        isLoadedAll: false,
        isDivScroll: true,
        isCustomSpinner: false,
        listContainerHeight: 200,
        listItemHeight: 20,
        direction: 'bottom',
      };
    },
    template: `

        <infinite-loading :distance="distance"
                          :direction="direction"
                          :on-infinite="onInfinite"
                          v-if="!isLoadedAll"
                          ref="infiniteLoading">

        </infinite-loading>

    `,
    components: { InfiniteLoading },
    methods: {
      onInfinite() {},
    },
  };

  // create new Vue instance for every test case
  beforeEach(() => {
    const container = document.createElement('div');
    container.setAttribute('id', 'app');
    document.body.appendChild(container);

    vm = new Vue(initConf);
  });

  afterEach(() => {
    /**
     * because of call the $destroy method of parent cannot trigger
     * destroy event for child component in Vue.js 2.0.0-rc6
     */
    vm.$refs.infiniteLoading && vm.$refs.infiniteLoading.$destroy();
    vm.$destroy(true);
    /**
     * because of pass true as the argument for destroy method cannot
     * remove element from DOM in Vue.js 2.0.0-rc6
     */
    vm.$el && vm.$el.remove();
  });

  it('should render a basic template', (done) => {
    vm.isDivScroll = false;
    setTimeout(() => {
      vm.$mount('#app');
      expect(vm.$el.querySelector('.loading-default')).to.be.ok;
      done();
    }, 1);
  });

  it('should execute callback and display a spinner immediately after initialize', (done) => {
    vm.onInfinite = function test() {
      Vue.nextTick(() => {
        expect(isShow(vm.$el.querySelector('.loading-default'))).to.be.true;
        done();
      });
    };

    vm.$mount('#app');
  });

  it('should not to execute callback if the previous loading has not be completed', (done) => {
    vm.onInfinite = function test() {
      const len = this.list.length + 1;
      for (let i = len; i < len + 20; i++) {
        this.list.push(i);
      }

      Vue.nextTick(() => {
        if (this.list.length === 20) {
          vm.$el.addEventListener('scroll', () => {
            expect(this.list).to.have.lengthOf(20);
            done();
          });

          // trigger scroll event manually
          vm.$el.scrollTop = vm.$el.scrollHeight;
        }
      });
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should be destroyed completely by v-if', (done) => {
    vm.onInfinite = function test() {
      this.isLoadedAll = true;
      Vue.nextTick(() => {
        expect(vm.$el.querySelector('.loading-default')).to.not.be.ok;
        done();
      });
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should display no results prompt', (done) => {
    vm.onInfinite = function test() {
      this.$refs.infiniteLoading.$emit('$InfiniteLoading:complete');
      Vue.nextTick(() => {
        expect(isShow(vm.$el.querySelectorAll('.infinite-status-prompt')[0])).to.be.true;
        done();
      });
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should display no more data prompt', (done) => {
    vm.onInfinite = function test() {
      this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
      this.$refs.infiniteLoading.$emit('$InfiniteLoading:complete');
      // test for whether trigger again after complete
      this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
      Vue.nextTick(() => {
        expect(isShow(vm.$el.querySelectorAll('.infinite-status-prompt')[1])).to.be.true;
        done();
      });
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should load results to fill up the container', (done) => {
    const expectedCount = Math.floor(vm.listContainerHeight / vm.listItemHeight);
    let i = 0;
    let timer;

    vm.onInfinite = function test() {
      setTimeout(() => {
        this.list.push(++i);
        this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
        clearTimeout(timer);
        timer = setTimeout(() => {
          if (i >= expectedCount) {
            done();
          } else {
            done(new Error('List not be fill up!'));
          }
        }, 100);
      }, 1);
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should reset component and call onInfinite again', (done) => {
    let callCount = 0;
    vm.onInfinite = function test() {
      if (!callCount++) {
        this.$refs.infiniteLoading.$emit('$InfiniteLoading:reset');
      } else {
        done();
      }
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should display the custom spinner if customize it with slot', (done) => {
    vm.isCustomSpinner = true;
    vm.distance = 100;
    vm.$mount('#app');

    Vue.nextTick(() => {
      expect(vm.$el.querySelector('.custom-spinner')).to.be.ok;
      done();
    });
  });

  it('should load data when scroll top (direction attribute)', (done) => {
    vm.direction = 'top';
    vm.onInfinite = function test() {
      Vue.nextTick(() => {
        expect(isShow(vm.$el.querySelector('.loading-default'))).to.be.true;
        done();
      });
    };

    vm.$mount('#app');
  });

  it('should load data once when deactivated by keep-alive feature', (done) => {
    let callCount = 0;
    let app;

    const InfiniteComponent = {
      data: initConf.data,
      template: initConf.template,
      components: initConf.components,
      methods: {
        onInfinite() {
          callCount++;
          if (callCount === 1) {
            this.$parent.currentView = null;
            Vue.nextTick(() => {
              this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
              setTimeout(() => {
                expect(callCount).to.equal(1);
                app.$destroy(true);
                app.$el && app.$el.remove();
                done();
              }, 1000);
            });
          }
        },
      },
    };

    app = new Vue({
      data() {
        return {
          currentView: 'InfiniteComponent',
        };
      },
      template: `
        <keep-alive>
          <component :is="currentView"></component>
        </keep-alive>
      `,
      components: {
        InfiniteComponent,
      },
    });

    app.$mount('#app');
  });
});
<commit_msg>Add unit test for the infinite-wrapper attribute<commit_after>import Vue from 'vue/dist/vue.common.js';
import InfiniteLoading from '../../../src/components/InfiniteLoading';

function isShow(elm) {
  const styles = getComputedStyle(elm);

  return styles.getPropertyValue('display') !== 'none';
}

describe('InfiniteLoading.vue', () => {
  let vm;
  const initConf = {
    data() {
      return {
        list: [],
        distance: 50,
        isLoadedAll: false,
        isDivScroll: true,
        isCustomSpinner: false,
        listContainerHeight: 200,
        listItemHeight: 20,
        direction: 'bottom',
      };
    },
    template: `

        <infinite-loading :distance="distance"
                          :direction="direction"
                          :on-infinite="onInfinite"
                          v-if="!isLoadedAll"
                          ref="infiniteLoading">

        </infinite-loading>

    `,
    components: { InfiniteLoading },
    methods: {
      onInfinite() {},
    },
  };

  // create new Vue instance for every test case
  beforeEach(() => {
    const container = document.createElement('div');
    container.setAttribute('id', 'app');
    document.body.appendChild(container);

    vm = new Vue(initConf);
  });

  afterEach(() => {
    /**
     * because of call the $destroy method of parent cannot trigger
     * destroy event for child component in Vue.js 2.0.0-rc6
     */
    vm.$refs.infiniteLoading && vm.$refs.infiniteLoading.$destroy();
    vm.$destroy(true);
    /**
     * because of pass true as the argument for destroy method cannot
     * remove element from DOM in Vue.js 2.0.0-rc6
     */
    vm.$el && vm.$el.remove();
  });

  it('should render a basic template', (done) => {
    vm.isDivScroll = false;
    setTimeout(() => {
      vm.$mount('#app');
      expect(vm.$el.querySelector('.loading-default')).to.be.ok;
      done();
    }, 1);
  });

  it('should execute callback and display a spinner immediately after initialize', (done) => {
    vm.onInfinite = function test() {
      Vue.nextTick(() => {
        expect(isShow(vm.$el.querySelector('.loading-default'))).to.be.true;
        done();
      });
    };

    vm.$mount('#app');
  });

  it('should not to execute callback if the previous loading has not be completed', (done) => {
    vm.onInfinite = function test() {
      const len = this.list.length + 1;
      const infiniteWrapper = this.$refs.infiniteLoading.scrollParent;

      for (let i = len; i < len + 20; i++) {
        this.list.push(i);
      }

      Vue.nextTick(() => {
        if (this.list.length === 20) {
          infiniteWrapper.addEventListener('scroll', () => {
            expect(this.list).to.have.lengthOf(20);
            done();
          });

          // trigger scroll event manually
          infiniteWrapper.scrollTop = infiniteWrapper.scrollHeight;
        }
      });
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should be destroyed completely by v-if', (done) => {
    vm.onInfinite = function test() {
      this.isLoadedAll = true;
      Vue.nextTick(() => {
        expect(vm.$el.querySelector('.loading-default')).to.not.be.ok;
        done();
      });
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should display no results prompt', (done) => {
    vm.onInfinite = function test() {
      this.$refs.infiniteLoading.$emit('$InfiniteLoading:complete');
      Vue.nextTick(() => {
        expect(isShow(vm.$el.querySelectorAll('.infinite-status-prompt')[0])).to.be.true;
        done();
      });
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should display no more data prompt', (done) => {
    vm.onInfinite = function test() {
      this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
      this.$refs.infiniteLoading.$emit('$InfiniteLoading:complete');
      // test for whether trigger again after complete
      this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
      Vue.nextTick(() => {
        expect(isShow(vm.$el.querySelectorAll('.infinite-status-prompt')[1])).to.be.true;
        done();
      });
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should load results to fill up the container', (done) => {
    const expectedCount = Math.floor(vm.listContainerHeight / vm.listItemHeight);
    let i = 0;
    let timer;

    vm.onInfinite = function test() {
      setTimeout(() => {
        this.list.push(++i);
        this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
        clearTimeout(timer);
        timer = setTimeout(() => {
          if (i >= expectedCount) {
            done();
          } else {
            done(new Error('List not be fill up!'));
          }
        }, 100);
      }, 1);
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should reset component and call onInfinite again', (done) => {
    let callCount = 0;
    vm.onInfinite = function test() {
      if (!callCount++) {
        this.$refs.infiniteLoading.$emit('$InfiniteLoading:reset');
      } else {
        done();
      }
    }.bind(vm);

    vm.$mount('#app');
  });

  it('should display the custom spinner if customize it with slot', (done) => {
    vm.isCustomSpinner = true;
    vm.distance = 100;
    vm.$mount('#app');

    Vue.nextTick(() => {
      expect(vm.$el.querySelector('.custom-spinner')).to.be.ok;
      done();
    });
  });

  it('should load data when scroll top (direction attribute)', (done) => {
    vm.direction = 'top';
    vm.onInfinite = function test() {
      Vue.nextTick(() => {
        expect(isShow(vm.$el.querySelector('.loading-default'))).to.be.true;
        done();
      });
    };

    vm.$mount('#app');
  });

  it('should load data once when deactivated by keep-alive feature', (done) => {
    let callCount = 0;
    let app;

    const InfiniteComponent = {
      data: initConf.data,
      template: initConf.template,
      components: initConf.components,
      methods: {
        onInfinite() {
          callCount++;
          if (callCount === 1) {
            this.$parent.currentView = null;
            Vue.nextTick(() => {
              this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
              setTimeout(() => {
                expect(callCount).to.equal(1);
                app.$destroy(true);
                app.$el && app.$el.remove();
                done();
              }, 1000);
            });
          }
        },
      },
    };

    app = new Vue({
      data() {
        return {
          currentView: 'InfiniteComponent',
        };
      },
      template: `
        <keep-alive>
          <component :is="currentView"></component>
        </keep-alive>
      `,
      components: {
        InfiniteComponent,
      },
    });

    app.$mount('#app');
  });

  it('should work with customize scroll plugin like iScroll', (done) => {
    const infiniteWrapper = document.createElement('div');
    const wrapper = document.createElement('div');

    vm.isDivScroll = false;
    infiniteWrapper.setAttribute('infinite-wrapper', '');
    document.getElementById('app').appendChild(infiniteWrapper);
    infiniteWrapper.appendChild(wrapper);

    vm.$mount(wrapper);

    Vue.nextTick(() => {
      expect(vm.$refs.infiniteLoading.scrollParent).to.equal(infiniteWrapper);
      done();
    }, 1);
  });
});
<|endoftext|>


<commit_before>const checkValidConfig = require('./configCheck.js')
const getRSS = require('../rss/rss.js')
var rssConfig = require('../config.json')
var guildList = rssConfig.sources
const sqlCmds = require('../rss/sql/commands.js')
const sqlConnect = require('../rss/sql/connect.js')

module.exports = function (bot, feedIndex) {
  var rssConfig = require('../config.json')
  var guildList = rssConfig.sources

  function validChannel(guildIndex, rssIndex) {
    if (isNaN(parseInt(guildList[guildIndex][rssIndex].channel,10))) {
      let channel = bot.channels.find("name",guildList[guildIndex][rssIndex].channel);
      if (channel == null) {
        console.log(`RSS Warning: ${guildList[guildIndex][rssIndex].name}'s string-defined channel was not found, skipping...`)
        return false;
      }
      else return channel;
    }
    else {
      let channel = bot.channels.get(`${guildList[guildIndex][rssIndex].channel}`);
      if (channel == null) {
        console.log(`RSS Warning: ${guildList[guildIndex][rssIndex].name}'s integer-defined channel was not found. skipping...`)
        return false;
      }
      else return channel;
    }
  }

var feedLength = 0
var feedProcessed = 0

for (let x in guildList)
  for (let y in guildList[x])
    feedLength++

  var con = sqlConnect(startFeed)

  function startFeed () {
    console.log("RSS Info: Starting feed retrieval cycle.")
    rssConfig = require('../config.json')
    rssList = rssConfig.sources
    for (let guildIndex in guildList)
      for (let rssIndex in guildList[guildIndex])
        if (checkValidConfig(guildIndex, rssIndex, false))
          if (validChannel(guildIndex, rssIndex) !== false)
            getRSS(con, rssIndex , validChannel(guildIndex, rssIndex), false, function () {
              feedProcessed++
              if (feedProcessed == feedLength) {
                feedProcessed = 0;
                sqlCmds.end(con, function(err) {
                  console.log("RSS Info: Finished feed retrieval cycle.")
                });
              }
            });
  }

  setInterval(startFeed, rssConfig.refreshTimeMinutes*60000)

}
<commit_msg>fixed sql loop<commit_after>const checkValidConfig = require('./configCheck.js')
const getRSS = require('../rss/rss.js')
var rssConfig = require('../config.json')
var guildList = rssConfig.sources
const sqlCmds = require('../rss/sql/commands.js')
const sqlConnect = require('../rss/sql/connect.js')

module.exports = function (bot, feedIndex) {
  var rssConfig = require('../config.json')
  var guildList = rssConfig.sources

  function validChannel(guildIndex, rssIndex) {
    if (isNaN(parseInt(guildList[guildIndex][rssIndex].channel,10))) {
      let channel = bot.channels.find("name",guildList[guildIndex][rssIndex].channel);
      if (channel == null) {
        console.log(`RSS Warning: ${guildList[guildIndex][rssIndex].name}'s string-defined channel was not found, skipping...`)
        return false;
      }
      else return channel;
    }
    else {
      let channel = bot.channels.get(`${guildList[guildIndex][rssIndex].channel}`);
      if (channel == null) {
        console.log(`RSS Warning: ${guildList[guildIndex][rssIndex].name}'s integer-defined channel was not found. skipping...`)
        return false;
      }
      else return channel;
    }
  }

var feedLength = 0
var feedProcessed = 0

for (let x in guildList)
  for (let y in guildList[x])
    feedLength++

var con;

  function connect () {
    con = sqlConnect(startFeed)
  }

  function startFeed () {
    console.log("RSS Info: Starting feed retrieval cycle.")
    rssConfig = require('../config.json')
    rssList = rssConfig.sources
    for (let guildIndex in guildList)
      for (let rssIndex in guildList[guildIndex])
        if (checkValidConfig(guildIndex, rssIndex, false))
          if (validChannel(guildIndex, rssIndex) !== false)
            getRSS(con, rssIndex , validChannel(guildIndex, rssIndex), false, function () {
              feedProcessed++
              if (feedProcessed == feedLength) {
                feedProcessed = 0;
                sqlCmds.end(con, function(err) {
                  console.log("RSS Info: Finished feed retrieval cycle.")
                });
              }
            });
  }

  connect()
  setInterval(connect, rssConfig.refreshTimeMinutes*60000)

}
<|endoftext|>


<commit_before>var app = angular.module('mybanjir', ['ngRoute', 'ngDisqus', 'ui.bootstrap', 'jmdobry.angular-cache'])

    .controller('FeedsController', function($scope, $filter, $routeParams){
        $scope.param = $routeParams.param ? $routeParams.param.split('::') : false;
        $scope.updateFeeds();
        $scope.filteredFeedsLength = $scope.feeds.length;
        $scope.filteredFeeds = [];
        $scope.currentPage = 1;
        $scope.numPerPage = 4;
        $scope.maxSize = 7;
        $scope.setFilteredFeeds = function() {
            var begin = (($scope.currentPage - 1) * $scope.numPerPage)
            , end = begin + $scope.numPerPage;
            $scope.filteredFeeds = $scope.feeds.sort(function(a,b){
                return (new Date(a.Timestamp)).getTime() < (new Date(b.Timestamp)).getTime() ? 1: -1
            }).filter(function(feed){
                if($scope.param) {
                    return (feed[$scope.param[0]] || 'others') === $scope.param[1].replace(/_/g, ' ');
                }
                return true;
            }).slice(begin, end);
            $scope.filteredFeedsLength = $scope.feeds.filter(function(feed){
                if($scope.param) {
                    return (feed[$scope.param[0]] || 'others') === $scope.param[1].replace(/_/g, ' ');
                }
                return true;
            }).length;
        };
        $scope.$watch('currentPage + numPerPage + feeds.length', $scope.setFilteredFeeds);
        $scope.pageChanged = $scope.setFilteredFeeds;
    })
    .controller('FeedController', function($scope, $routeParams){
        if($routeParams.ID) {
            $scope.$watch('feeds.length', function(){
                $scope.feed = $scope.feeds.filter(function(feed){
                    return feed.ID === parseInt($routeParams.ID, 10);
                }).pop();
            });
        }
    })
    .controller('RiverLevelController', function($scope, $routeParams, $http, $angularCacheFactory){
        $scope.state = $scope.riverLevels.filter(function(state){
            return state.code === $routeParams.state_code;
        }).pop();
        if(!$scope.state.rivers.length) {
            $http.get('http://www.mybanjir.com/api/riverlevel/' + $routeParams.state_code, {
                cache: $angularCacheFactory.get('riverDataCache')
            })
            .success(function(rivers){
                $scope.state.rivers = rivers;
            })
            .error(function(){
                $scope.error = 'Feed unavailable at the moment'
            });
        }
        $scope.$watch('state.rivers.length', function(){
            $scope.state = $scope.riverLevels.filter(function(state){
                return state.code === $routeParams.state_code;
            }).pop();
        });
    })
    .controller('WeatherForecastController', function($scope, $routeParams, $http, $angularCacheFactory){
        $scope.filteredForecasts = [];
        $scope.dates = [];
        $scope.state = $scope.weatherForecasts.filter(function(state){
            return state.code === $routeParams.state_code;
        }).pop();
        if(!Object.keys($scope.state.forecasts).length) {
            $http.get('http://www.mybanjir.com/met/met.php?states=' + $routeParams.state_code, {
                cache: 3600000
            })
            .success(function(forecasts){
                $scope.state.forecasts = forecasts;
            })
            .error(function(){
                $scope.error = 'Feed unavailable at the moment'
            });
        }
        $scope.setFilteredFeeds = function() {
            if(Object.keys($scope.state.forecasts).length) {
                $scope.filteredForecasts = $.map($scope.state.forecasts, function(v, k){
                    if(!$scope.dates.length)
                        $scope.dates = v.results.map(function(result){
                            return moment(result.date);
                        });
                    v.location = k;
                    if(!$routeParams.selected_date)
                        return $.extend({}, v, v.results[0]);
                    return $.extend({}, v, v.results.filter(function(res){
                        return res.date === $routeParams.selected_date;
                    }).pop());
                });
                var dateTxt = $routeParams.selected_date ? moment($routeParams.selected_date) : $scope.dates[0];
                $scope.dateTxt = dateTxt.format('dddd LL');
            }
        }
        $scope.classActive = function(date) {
            if(!$routeParams.selected_date)
                return date === $scope.dates[0] ? 'btn btn-primary' : 'btn btn-default';
            return date.format('YYYY-MM-DD') === $routeParams.selected_date ? 'btn btn-primary' : 'btn btn-default';
        }
        $scope.$watch('state.forecasts', $scope.setFilteredFeeds);
        $scope.dateUrl = function(state, date) {
            return '#!/weatherforecast/' + state.code + '/' + date.format('YYYY-MM-DD');
        }

    })
    .controller('RiverLevelsController', function($scope, $routeParams){})
    .controller('WeatherForecastsController', function($scope, $routeParams){})
    .controller('FrequencyController', function($scope, $routeParams){

    })
    .filter('fromNow', function($sce){
        return function(val) {
            console.log(val)
            return moment(val).fromNow();
        };
    })
    .filter('rawHtml', ['$sce', function($sce){
        return function(val) {
            return $sce.trustAsHtml(val);
        };
    }])
    .filter('titleCase', function(){
        return function(val) {
            return val.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
        };
    })
    .filter('encodeUrl', function(){
        return function(val) {
            return val.replace(/\s+/g, '_');
        };
    })
    .filter('riverStatusClass', function(){
        return function(river) {
            if(river.RiverLevel <= river.AlertLevel)
                return  'label-success';
            if(river.RiverLevel <= river.WarningLevel)
                return 'label-info';
            if(river.RiverLevel <= river.DangerLevel)
                return 'label-warning';
            return 'label-danger';
        };
    })
    .filter('riverStatus', function(){
        return function(river) {
            if(river.RiverLevel <= river.AlertLevel)
                return  'Normal';
            if(river.RiverLevel <= river.WarningLevel)
                return 'Alert';
            if(river.RiverLevel <= river.DangerLevel)
                return 'Warning';
            return 'Danger';
        };
    })
    .config(['$routeProvider', '$locationProvider', '$disqusProvider',
        function($routeProvider, $locationProvider, $disqusProvider) {
            $disqusProvider.setShortname('mybanjirinfo');
            $routeProvider.
            when('/feeds/:param?', {
                templateUrl: 'templates/feeds.html',
                controller: 'FeedsController'
            }).
            when('/feed/:ID', {
                templateUrl: 'templates/feed.html',
                controller: 'FeedController'
            }).
            when('/riverlevels', {
                templateUrl: 'templates/riverlevels.html',
                controller: 'RiverLevelsController'
            }).
            when('/riverlevel/:state_code', {
                templateUrl: 'templates/riverlevel.html',
                controller: 'RiverLevelController'
            }).
            when('/weatherforecasts', {
                templateUrl: 'templates/weatherforecasts.html',
                controller: 'WeatherForecastsController'
            }).
            when('/weatherforecast/:state_code/:selected_date?', {
                templateUrl: 'templates/weatherforecast.html',
                controller: 'WeatherForecastController'
            }).
            when('/frequencies', {
                templateUrl: 'templates/frequencies.html',
                controller: 'FrequencyController'
            }).
            otherwise({
                redirectTo: '/feeds'
            });
            $locationProvider.hashPrefix('!');
        }
    ])
    .run(function($rootScope, $location, $http, $angularCacheFactory){
        $rootScope.feeds = [];
        $rootScope.riverLevels = [{name: 'Perlis', code: 'PLS', rivers: []},
            {name: 'Kedah', code: 'KDH', rivers: []},
            {name: 'Pulau Pinang', code: 'PNG', rivers: []},
            {name: 'Perak', code: 'PRK', rivers: []},
            {name: 'Selangor', code: 'SEL', rivers: []},
            {name: 'KL', code: 'WLH', rivers: []},
            {name: 'Negeri Sembilan', code: 'NSN', rivers: []},
            {name: 'Melaka', code: 'MLK', rivers: []},
            {name: 'Johor', code: 'JHR', rivers: []},
            {name: 'Pahang', code: 'PHG', rivers: []},
            {name: 'Terengganu', code: 'TRG', rivers: []},
            {name: 'Kelantan', code: 'KEL', rivers: []},
            {name: 'Sarawak', code: 'SRK', rivers: []},
            {name: 'Sabah', code: 'SAB', rivers: []},
        ];
        $rootScope.weatherForecasts = [{name: 'Perlis', code: 'perlis', forecasts: {}},
            {name: 'Kedah', code: 'kedah', forecasts: {}},
            {name: 'Pulau Pinang', code: 'pulau pinang', forecasts: {}},
            {name: 'Perak', code: 'perak', forecasts: {}},
            {name: 'Selangor', code: 'selangor', forecasts: {}},
            {name: 'KL', code: 'kuala lumpur', forecasts: {}},
            {name: 'Negeri Sembilan', code: 'negeri sembilan', forecasts: {}},
            {name: 'Melaka', code: 'melaka', forecasts: {}},
            {name: 'Johor', code: 'johor', forecasts: {}},
            {name: 'Pahang', code: 'pahang', forecasts: {}},
            {name: 'Terengganu', code: 'terengganu', forecasts: {}},
            {name: 'Kelantan', code: 'kelantan', forecasts: {}},
            {name: 'Sarawak', code: 'sarawak', forecasts: {}},
            {name: 'Sabah', code: 'sabah', forecasts: {}},
        ];
        $rootScope.moment = moment;
        $rootScope.credentials = {email: '', password: ''};

        $angularCacheFactory('riverDataCache', {
            maxAge: 900000,
            cacheFlushInterval: 3600000,
            deleteOnExpire: 'aggressive'
        });

        $angularCacheFactory('weatherForecastsCache', {
            maxAge: 900000,
            cacheFlushInterval: 3600000,
            deleteOnExpire: 'aggressive'
        });

        $rootScope.updateFeeds = function() {
            $http.get('http://www.mybanjir.com/api/items')
                .success(function(datas){
                    $rootScope.feeds = datas;
                    $rootScope.locations = datas.map(function(data){
                        if(!data.Location)
                            return 'others'
                        return data.Location;
                    });
                })
                .error(function(){
                    // console.log()
                })
        }
        $rootScope.nl2br = function(str, is_xhtml) {
            var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br ' + '/>' : '<br>'; // Adjust comment to avoid issue on phpjs.org display
            return (str + '')
                .replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
        }
        $rootScope.slugify = function(str) {
            str = str.replace(/^\s+|\s+$/g, '').toLowerCase();
            var from = "ãàáäâẽèéëêìíïîõòóöôùúüûñç·/_,:;";
            var to   = "aaaaaeeeeeiiiiooooouuuunc------";
            for (var i=0, l=from.length ; i<l ; i++) {
                str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
            }
            str = str.replace(/[^a-z0-9 -]/g, '')
            .replace(/\s+/g, '-')
            .replace(/-+/g, '-');
            var rand = '', chars = '0123456789abcdefghijklmnopqrstuvwxyz';
            for (var i = 4; i > 0; --i) rand += chars[Math.round(Math.random() * (chars.length - 1))];
            return str + '-' + rand;
        };

        $rootScope.$on('$routeChangeSuccess', function(){
            ga('send', 'pageview');
        });
        $rootScope.updateFeeds();
    });<commit_msg>Check devtools is open<commit_after>var app = angular.module('mybanjir', ['ngRoute', 'ngDisqus', 'ui.bootstrap', 'jmdobry.angular-cache'])

    .controller('FeedsController', function($scope, $filter, $routeParams){
        $scope.param = $routeParams.param ? $routeParams.param.split('::') : false;
        $scope.updateFeeds();
        $scope.filteredFeedsLength = $scope.feeds.length;
        $scope.filteredFeeds = [];
        $scope.currentPage = 1;
        $scope.numPerPage = 4;
        $scope.maxSize = 7;
        $scope.setFilteredFeeds = function() {
            var begin = (($scope.currentPage - 1) * $scope.numPerPage)
            , end = begin + $scope.numPerPage;
            $scope.filteredFeeds = $scope.feeds.sort(function(a,b){
                return (new Date(a.Timestamp)).getTime() < (new Date(b.Timestamp)).getTime() ? 1: -1
            }).filter(function(feed){
                if($scope.param) {
                    return (feed[$scope.param[0]] || 'others') === $scope.param[1].replace(/_/g, ' ');
                }
                return true;
            }).slice(begin, end);
            $scope.filteredFeedsLength = $scope.feeds.filter(function(feed){
                if($scope.param) {
                    return (feed[$scope.param[0]] || 'others') === $scope.param[1].replace(/_/g, ' ');
                }
                return true;
            }).length;
        };
        $scope.$watch('currentPage + numPerPage + feeds.length', $scope.setFilteredFeeds);
        $scope.pageChanged = $scope.setFilteredFeeds;
    })
    .controller('FeedController', function($scope, $routeParams){
        if($routeParams.ID) {
            $scope.$watch('feeds.length', function(){
                $scope.feed = $scope.feeds.filter(function(feed){
                    return feed.ID === parseInt($routeParams.ID, 10);
                }).pop();
            });
        }
    })
    .controller('RiverLevelController', function($scope, $routeParams, $http, $angularCacheFactory){
        $scope.state = $scope.riverLevels.filter(function(state){
            return state.code === $routeParams.state_code;
        }).pop();
        if(!$scope.state.rivers.length) {
            $http.get('http://www.mybanjir.com/api/riverlevel/' + $routeParams.state_code, {
                cache: $angularCacheFactory.get('riverDataCache')
            })
            .success(function(rivers){
                $scope.state.rivers = rivers;
            })
            .error(function(){
                $scope.error = 'Feed unavailable at the moment'
            });
        }
        $scope.$watch('state.rivers.length', function(){
            $scope.state = $scope.riverLevels.filter(function(state){
                return state.code === $routeParams.state_code;
            }).pop();
        });
    })
    .controller('WeatherForecastController', function($scope, $routeParams, $http, $angularCacheFactory){
        $scope.filteredForecasts = [];
        $scope.dates = [];
        $scope.state = $scope.weatherForecasts.filter(function(state){
            return state.code === $routeParams.state_code;
        }).pop();
        if(!Object.keys($scope.state.forecasts).length) {
            $http.get('http://www.mybanjir.com/met/met.php?states=' + $routeParams.state_code, {
                cache: 3600000
            })
            .success(function(forecasts){
                $scope.state.forecasts = forecasts;
            })
            .error(function(){
                $scope.error = 'Feed unavailable at the moment'
            });
        }
        $scope.setFilteredFeeds = function() {
            if(Object.keys($scope.state.forecasts).length) {
                $scope.filteredForecasts = $.map($scope.state.forecasts, function(v, k){
                    if(!$scope.dates.length)
                        $scope.dates = v.results.map(function(result){
                            return moment(result.date);
                        });
                    v.location = k;
                    if(!$routeParams.selected_date)
                        return $.extend({}, v, v.results[0]);
                    return $.extend({}, v, v.results.filter(function(res){
                        return res.date === $routeParams.selected_date;
                    }).pop());
                });
                var dateTxt = $routeParams.selected_date ? moment($routeParams.selected_date) : $scope.dates[0];
                $scope.dateTxt = dateTxt.format('dddd LL');
            }
        }
        $scope.classActive = function(date) {
            if(!$routeParams.selected_date)
                return date === $scope.dates[0] ? 'btn btn-primary' : 'btn btn-default';
            return date.format('YYYY-MM-DD') === $routeParams.selected_date ? 'btn btn-primary' : 'btn btn-default';
        }
        $scope.$watch('state.forecasts', $scope.setFilteredFeeds);
        $scope.dateUrl = function(state, date) {
            return '#!/weatherforecast/' + state.code + '/' + date.format('YYYY-MM-DD');
        }

    })
    .controller('RiverLevelsController', function($scope, $routeParams){})
    .controller('WeatherForecastsController', function($scope, $routeParams){})
    .controller('FrequencyController', function($scope, $routeParams){

    })
    .filter('fromNow', function($sce){
        return function(val) {
            console.log(val)
            return moment(val).fromNow();
        };
    })
    .filter('rawHtml', ['$sce', function($sce){
        return function(val) {
            return $sce.trustAsHtml(val);
        };
    }])
    .filter('titleCase', function(){
        return function(val) {
            return val.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
        };
    })
    .filter('encodeUrl', function(){
        return function(val) {
            return val.replace(/\s+/g, '_');
        };
    })
    .filter('riverStatusClass', function(){
        return function(river) {
            if(river.RiverLevel <= river.AlertLevel)
                return  'label-success';
            if(river.RiverLevel <= river.WarningLevel)
                return 'label-info';
            if(river.RiverLevel <= river.DangerLevel)
                return 'label-warning';
            return 'label-danger';
        };
    })
    .filter('riverStatus', function(){
        return function(river) {
            if(river.RiverLevel <= river.AlertLevel)
                return  'Normal';
            if(river.RiverLevel <= river.WarningLevel)
                return 'Alert';
            if(river.RiverLevel <= river.DangerLevel)
                return 'Warning';
            return 'Danger';
        };
    })
    .config(['$routeProvider', '$locationProvider', '$disqusProvider',
        function($routeProvider, $locationProvider, $disqusProvider) {
            $disqusProvider.setShortname('mybanjirinfo');
            $routeProvider.
            when('/feeds/:param?', {
                templateUrl: 'templates/feeds.html',
                controller: 'FeedsController'
            }).
            when('/feed/:ID', {
                templateUrl: 'templates/feed.html',
                controller: 'FeedController'
            }).
            when('/riverlevels', {
                templateUrl: 'templates/riverlevels.html',
                controller: 'RiverLevelsController'
            }).
            when('/riverlevel/:state_code', {
                templateUrl: 'templates/riverlevel.html',
                controller: 'RiverLevelController'
            }).
            when('/weatherforecasts', {
                templateUrl: 'templates/weatherforecasts.html',
                controller: 'WeatherForecastsController'
            }).
            when('/weatherforecast/:state_code/:selected_date?', {
                templateUrl: 'templates/weatherforecast.html',
                controller: 'WeatherForecastController'
            }).
            when('/frequencies', {
                templateUrl: 'templates/frequencies.html',
                controller: 'FrequencyController'
            }).
            otherwise({
                redirectTo: '/feeds'
            });
            $locationProvider.hashPrefix('!');
        }
    ])
    .run(function($rootScope, $location, $http, $angularCacheFactory){
        $rootScope.feeds = [];
        $rootScope.riverLevels = [{name: 'Perlis', code: 'PLS', rivers: []},
            {name: 'Kedah', code: 'KDH', rivers: []},
            {name: 'Pulau Pinang', code: 'PNG', rivers: []},
            {name: 'Perak', code: 'PRK', rivers: []},
            {name: 'Selangor', code: 'SEL', rivers: []},
            {name: 'KL', code: 'WLH', rivers: []},
            {name: 'Negeri Sembilan', code: 'NSN', rivers: []},
            {name: 'Melaka', code: 'MLK', rivers: []},
            {name: 'Johor', code: 'JHR', rivers: []},
            {name: 'Pahang', code: 'PHG', rivers: []},
            {name: 'Terengganu', code: 'TRG', rivers: []},
            {name: 'Kelantan', code: 'KEL', rivers: []},
            {name: 'Sarawak', code: 'SRK', rivers: []},
            {name: 'Sabah', code: 'SAB', rivers: []},
        ];
        $rootScope.weatherForecasts = [{name: 'Perlis', code: 'perlis', forecasts: {}},
            {name: 'Kedah', code: 'kedah', forecasts: {}},
            {name: 'Pulau Pinang', code: 'pulau pinang', forecasts: {}},
            {name: 'Perak', code: 'perak', forecasts: {}},
            {name: 'Selangor', code: 'selangor', forecasts: {}},
            {name: 'KL', code: 'kuala lumpur', forecasts: {}},
            {name: 'Negeri Sembilan', code: 'negeri sembilan', forecasts: {}},
            {name: 'Melaka', code: 'melaka', forecasts: {}},
            {name: 'Johor', code: 'johor', forecasts: {}},
            {name: 'Pahang', code: 'pahang', forecasts: {}},
            {name: 'Terengganu', code: 'terengganu', forecasts: {}},
            {name: 'Kelantan', code: 'kelantan', forecasts: {}},
            {name: 'Sarawak', code: 'sarawak', forecasts: {}},
            {name: 'Sabah', code: 'sabah', forecasts: {}},
        ];
        $rootScope.moment = moment;
        $rootScope.credentials = {email: '', password: ''};

        $angularCacheFactory('riverDataCache', {
            maxAge: 900000,
            cacheFlushInterval: 3600000,
            deleteOnExpire: 'aggressive'
        });

        $angularCacheFactory('weatherForecastsCache', {
            maxAge: 900000,
            cacheFlushInterval: 3600000,
            deleteOnExpire: 'aggressive'
        });

        $rootScope.updateFeeds = function() {
            $http.get('http://www.mybanjir.com/api/items')
                .success(function(datas){
                    $rootScope.feeds = datas;
                    $rootScope.locations = datas.map(function(data){
                        if(!data.Location)
                            return 'others'
                        return data.Location;
                    });
                })
                .error(function(){
                    // console.log()
                })
        }
        $rootScope.nl2br = function(str, is_xhtml) {
            var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br ' + '/>' : '<br>'; // Adjust comment to avoid issue on phpjs.org display
            return (str + '')
                .replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
        }
        $rootScope.slugify = function(str) {
            str = str.replace(/^\s+|\s+$/g, '').toLowerCase();
            var from = "ãàáäâẽèéëêìíïîõòóöôùúüûñç·/_,:;";
            var to   = "aaaaaeeeeeiiiiooooouuuunc------";
            for (var i=0, l=from.length ; i<l ; i++) {
                str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
            }
            str = str.replace(/[^a-z0-9 -]/g, '')
            .replace(/\s+/g, '-')
            .replace(/-+/g, '-');
            var rand = '', chars = '0123456789abcdefghijklmnopqrstuvwxyz';
            for (var i = 4; i > 0; --i) rand += chars[Math.round(Math.random() * (chars.length - 1))];
            return str + '-' + rand;
        };

        $rootScope.$on('$routeChangeSuccess', function(){
            ga('send', 'pageview');
        });
        $rootScope.updateFeeds();
    });

(function () {
    var devtools = {open: false};
    var threshold = 160;
    var emitEvent = function (state) {
        window.dispatchEvent(new CustomEvent('devtoolschange', {
            detail: {
                open: state
            }
        }));
    };
    setInterval(function () {
        if ((window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized) || window.outerWidth - window.innerWidth > threshold ||
            window.outerHeight - window.innerHeight > threshold) {
            if (!devtools.open) {
                emitEvent(true);
            }
            devtools.open = true;
        } else {
            if (devtools.open) {
                emitEvent(false);
            }
            devtools.open = false;
        }
    }, 500);
    if (typeof module !== 'undefined' && module.exports) {
        module.exports = devtools;
    } else {
        window.devtools = devtools;
    }
})();

window.addEventListener('devtoolschange', function (e) {
    console.log('Care to help? Fork us on github: https://github.com/zulfajuniadi/mybanjirinfo');
});<|endoftext|>


<commit_before>console.log("안녕하세요 이상헌 입니다.");<commit_msg>conflict resolve<commit_after>console.log("안녕하세요 이상헌 입니다.");
console.log("저는 세종대학교에 재학 중 입니다.");<|endoftext|>


<commit_before>'use strict';

const getDictionaries = require('./hunspell-dictionaries').getDictionaries;
const getSpellChecker = require('./hunspell-checker');
const webframe = require('web-frame');

function createAndRegisterSpellchecker(language) {
  getDictionaries()
    .then(dictionaries => {
      return dictionaries[language];
    })
    .then(getSpellChecker)
    .then(checker => {
      registerSpellChecker(language, checker);
    })
    .catch(exception => {
      console.log(exception);
    })
  ;
}

function registerSpellChecker(language, checker) {
  webframe.setSpellCheckProvider(language, true, {
    spellCheck: word => {
      return checker.check(word);
    }
  });
}

exports.initialise = createAndRegisterSpellchecker;
<commit_msg>Disable (really annoying) spelling auto correct.<commit_after>'use strict';

const getDictionaries = require('./hunspell-dictionaries').getDictionaries;
const getSpellChecker = require('./hunspell-checker');
const webframe = require('web-frame');

function createAndRegisterSpellchecker(language) {
  getDictionaries()
    .then(dictionaries => {
      return dictionaries[language];
    })
    .then(getSpellChecker)
    .then(checker => {
      registerSpellChecker(language, checker);
    })
    .catch(exception => {
      console.log(exception);
    })
  ;
}

function registerSpellChecker(language, checker) {
  webframe.setSpellCheckProvider(language, false, {
    spellCheck: word => {
      return checker.check(word);
    }
  });
}

exports.initialise = createAndRegisterSpellchecker;
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////
////
//// code.js -- a replacement for org-info.js
////
//// Written by Masataro Asai (guicho2.71828@gmail.com)
//// Licenced under GPLv3.
////
////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////
// helper functions ////////////////////////////////////////////
////////////////////////////////////////////////////////////////

var identity=function(){};

jQuery.fn.visible = function() {
    return this.css('visibility', 'visible');
};

jQuery.fn.invisible = function() {
    return this.css('visibility', 'hidden');
};

jQuery.fn.emerge = function() {
    return this.addClass("emerge");
};

function text(){
    return $(".outline-text-1,"+
             ".outline-text-2,"+
             ".outline-text-3,"+
             ".outline-text-4",slide.current).first();
}

function expand(){
    console.log("clicked!");
    var tx = text();
    var result =
        $("li.expanded + li:not(.expanded),"+
          "li:first-child:not(.expanded)",tx).first().addClass("expanded emerging-list");
    $("li.expanded > ul:not(.expanded)",tx).first().addClass("expanded emerging");
    return result;
}

function setExpanders(){
    $("outline-1,outline-2,outline-3,outline-4").click(expand);
}

function outline(n){
    return ".outline-"+n;
}
function outlineContents(n){
    return ".outline-text-"+n+", h"+n;
}

function container(){
    return Array.prototype.reduce.call(
        arguments,
        function(prev,arg){
            return prev+"-"+arg;
        },
        "#outline-container-sec"
    );
}

function unparseSection(id){
    var re = /outline-container-sec-(.*)/;
    return (id.match(re)||[null,"1"])[1].split("-");
}

function clip(low,x,high,when_low,when_high){
    if (x < low){
        return when_low || low;
    }else if (high || x > high){
        return when_high || high;
    }else {
        return x;
    }
}

function adjustVerticalCenter(){
    var top = 0.4 * ($(window).height() - $(document.body).height());
    var high = 0.2 * $(window).height();
    if (top > high){
        $(document.body)
            .delay( 100 )
            .animate({"margin-top": high});
        slide.headline()
            .delay( 300 )
            .animate({"margin-bottom": top - high});
    }else{
        $(document.body)
            .delay( 100 )
            .animate({"margin-top": clip(20,top)});
    }
}

////////////////////////////////////////////////////////////////
//// Slide objects /////////////////////////////////////////////
////////////////////////////////////////////////////////////////

var nullp = $.isEmptyObject;

function Slide(arg,prev){
    this.previous = prev;
    if (!nullp(arg) && arg.length!=0){
        this.current = arg;
        var matched = arg.get(0).className.match(/outline-([0-9]*)/);
        if(matched){
            this.level=(+matched[1]);
        }else{
            throw new Error("arg is not of class outline-x.");
        }
        return this;
    }else{
        throw new Error("arg is null / jquery object with no match");
    }
}

Slide.prototype = {
    current : undefined, // jquery object
    previous : undefined, // Slide object
    level : 1,
    // hide: function(){
    //   this.current.hide();
    // },
    headline: function(){
        return $("h1,h2,h3,h4",slide.current).first();
    },
    hideParents: function(){
        for(var i = 1;i<this.level;i++){
            $(outlineContents(i)).hide();
        }
    },
    hideSiblings: function(){
        $(outlineContents(this.level)).hide();
    },
    hideChildren: function(){
        for(var i=this.level+1;0<($(outline(i)).length);i++){
            $(outlineContents(i)).hide();
        }
    },
    showSelf: function(){
        this.current.children(outlineContents(this.level)).show().emerge();
    },
    show: function(){
        this.hideParents();
        this.hideSiblings();
        this.hideChildren();
        this.showSelf();
        adjustVerticalCenter();
        return this;
    },
    nochild : function(){
        return nullp(this.current.children(outline(1+this.level)));
    },
    // if sustain is true, it doesn't add the current slide to the slide history
    new : function(next,sustain){
        return new Slide(next,(sustain?this.previous:this));
    },
    up : function(sustain){return this.new(this.current.parent(),sustain);},
    down : function(sustain){
        return this.new(this.current.children(outline(1+this.level)).first(),sustain);},
    left : function(sustain){return this.new(this.current.prev(),sustain)},
    right : function(sustain){return this.new(this.current.next(),sustain)},
    next : function(){
        try{return this.down();} catch (x) {}
        try{return this.right();} catch (x) {}

        var slide = this;
        while(true){
            try{
                slide = slide.up();
            } catch (x) {
                throw new Error("no next slide");
                // tells that there is no next slide
            }
            try{
                // if the upper slide has the following slide,
                // then it is the next slide
                return slide.right(true);
            } catch (x) {
            }
        }
    },
    prev : function(){
        if (this.previous){
            return this.previous;
        }else{
            throw new Error("no previous slide");
        }
    },
};

var slide;

////////////////////////////////////////////////////////////////
//// Keyboard event handlers ///////////////////////////////////
////////////////////////////////////////////////////////////////

// a hash table with {"key strokes":function}.
// functions should take zero argument and
// should return true on success, false otherwise.
var keyManager = {};

var keystrokeManager = {
    _stroke: "",
    _minibuffer: $("

"),
    _prompt: $(""),
    _input: $(""),
    init: function(def_stroke,def_prompt){
        this.stroke=(def_stroke||"");
        this._prompt.text(def_prompt||"");
        return this;
    },
    push: function(c){
        this.stroke=this.stroke.concat(c);
        return this;
    },
    backspace: function(){
        this.stroke=this.stroke.slice(0,-1);
        return this;
    },
    setup: function(){
        this._minibuffer
            .append(this._prompt)
            .append(this._input);
        $("body").prepend(this._minibuffer);
    },
    query: function(message,fn,def,enteredByDefault){
        // message : string
        // fn : callback
        // def : string -- default value
        // enteredByDefault : boolean
        var old = this._prompt.text();
        $(window).off("keypress",keyboardHandler);
        this.init(((def && enteredByDefault) ?
                   def : ""),
                  (enteredByDefault ?
                   message : (message+" (Default:"+def+") ")));
        var handler=(function(e){
            try{
                enterHandler(
                    backspaceHandler(
                        cancelHandler(
                            printHandler())))(e);
            } catch (x) {
                if (x=="enter") {
                    var result = this._input.text();
                    keystrokeManager.init("",old);
                    $(window).off("keypress",handler);
                    $(window).on("keypress",keyboardHandler);
                    fn((result=="")?def:result);
                }
                else throw x;
            }
        }).bind(this);
        $(window).on("keypress", handler);
        return true;
    }
};

keystrokeManager.__defineSetter__(
    "stroke",function(str){
        this._stroke = str;
        this._input.text(str);
        return this;
    });
keystrokeManager.__defineGetter__(
    "stroke",function(){
        return this._stroke;
    });

function available_p(e){ return (32 <= e.charCode && e.charCode <= 126)}
function backspace_p(e){ return (e.keyCode == 8)}
function enter_p(e){ return (e.keyCode == 13)}
function cancel_p(e){
    return (e.charCode == 103 && e.ctrlKey) // Ctrl-g
        || (e.keyCode == 27);  // Esc
}

function enterHandler(next){
    return function(e){
        if (enter_p(e)){
            e.stopPropagation();
            e.preventDefault();
            throw "enter";
        } else return (next||identity)(e);
    };
}

function backspaceHandler(next){
    return function(e){
        if (backspace_p(e)){
            e.stopPropagation();
            e.preventDefault();
            keystrokeManager.backspace();
        } else return (next||identity)(e);
    };
}

function cancelHandler(next){
    return function(e){
        if (cancel_p(e)){
            e.stopPropagation();
            e.preventDefault();
            console.log("cancelled");
            keystrokeManager.init();
        } else return (next||identity)(e);
    };
}

function printHandler(next){
    return function(e){
        if (available_p(e)){
            keystrokeManager.push(String.fromCharCode(e.charCode));
        } else return (next||identity)(e);
    };
}

function dispatchHandler(next){
    return function(e){
        if (available_p(e)){
            keystrokeManager.push(String.fromCharCode(e.charCode));
            var handler = keyManager[keystrokeManager.stroke];
            if (typeof handler == "function"){
                console.log("Handler function "
                            + keystrokeManager.stroke +" found");
                try{
                    if (!handler(e)){
                        console.log(
                            "Handler function returned a false value.  Resetting the strokemanager state.");
                        keystrokeManager.init();
                    }else {
                        console.log("Handler function returned!");
                    }
                } catch (x) {
                    console.error(x);
                    keystrokeManager.init();
                }
            }
        } else return (next||identity)(e);
    };
}

function keyboardHandler(e){
    console.log("charCode:"+e.charCode
                +" keyCode:"+e.keyCode
                +" which:"+e.which
                +" Modifier:"
                +(e.ctrlKey?"Ctrl":"")
                +(e.shiftKey?"Shift":"")
                +(e.metaKey?"Meta":"")
                +(e.altKey?"Alt":""));
    backspaceHandler(
        cancelHandler(
            dispatchHandler()))(e);
    console.log(keystrokeManager.stroke);
}

////////////////////////////////////////////////////////////////
//// Initialization
////

window.onload = function(){
    $("#content").addClass("outline-1");
    slide = new Slide($("#content"));
    slide.show();
    setExpanders();
    keystrokeManager.setup();
    $(window).keypress(keyboardHandler);

    var href = location.href;
    var re = /.*#(.*)/;
    var result = href.match(re);
    if(result){
        var secnums = result[1].split("-");
        try{
            console.log(container.apply(this,secnums));
            slide = slide.new($(container.apply(this,secnums)));
            slide.show();
        } catch (x) {

        }
    }
};

////////////////////////////////////////////////////////////////
//// keymanager functions

// expand one element in the list in the current slide, or go to the next slide
keyManager.n = keyManager[" "] = function(){
    $(".title").hide();
    console.log(slide.level);
    try{
        if(expand().length==0){
            slide = slide.next();
            slide.show();
        }
    } catch (x) {
        console.warn("This is the last slide!");
    }
};

// expand all elements in the current slide
keyManager.N = function(){
    $(".title").hide();
    console.log(slide.level);
    if(expand().length==0){keyManager.n();}
    while (expand().length>0){}
};

keyManager.p = function(){
    console.log(slide.level);
    try{
        slide = slide.prev();
        slide.show();
    } catch (x) {
        console.warn("This is the first slide!");
    }
};

keyManager.u = keyManager["^"] = function(){
    console.log(slide.level);
    try{
        slide = slide.up();
        slide.show();
    } catch (x) {
        console.warn("There is no parent section!");
    }
};

keyManager.s = keyManager.go = function(){
    return sectionPrompt2("Enter a section number");
};

function sectionPrompt2(message){
    return keystrokeManager.query(
        message,function(result){
            var secnums = result.split(".");
            try{
                console.log(container.apply(this,secnums));
                slide = slide.new($(container.apply(this,secnums)));
                slide.show();
            } catch (x) {
                sectionPrompt2(container.apply(this,secnums) + " does not exists.");
            }
        },
        unparseSection(slide.current.get(0).id).join("-"));
}

// debug

var debug = false;

function toggleDebug(){
    if (!debug){
        debug = true;
        return (function(){
                    $(this).addClass("debug-border");
                });
    }else{
        debug = false;
        return (function(){
                    $(this).removeClass("debug-border");
                });
    }
}

keyManager.d = function(){
    $(".outline-1,.outline-2,.outline-3,.outline-4"+
      ",li,ul,ol,h1,h2,h3,h4,.outline-text-2, .outline-text-3, .outline-text-4")
        .map(toggleDebug());
    console.log("debug : "+debug);
};

// unfolding the presentation and shows all slides at once
keyManager.unfold = function(){
    $("*").visible().show();
    $(".note").css({position:"static",top:"1em"});
    $("body").css({overflow:"auto"});
};

keyManager["-"] = function(){
    var maxwidth = parseFloat($("#content").css("max-width"))*0.91;
    var size = parseFloat($("body").css("font-size"))*0.91;
    $("#content").css("max-width",maxwidth);
    $("body").css("font-size",size);
};

keyManager["+"] = function(){
    var maxwidth = parseFloat($("#content").css("max-width"))*1.1;
    var size = parseFloat($("body").css("font-size"))*1.1;
    $("#content").css("max-width",maxwidth);
    $("body").css("font-size",size);
};

keyManager.toggle = function(){
    $("#minibuffer").toggle();
};

keyManager.banner = function(){
    $("#banner").toggle();
};

keyManager.help = keyManager.h = keyManager["?"] = function(){
    keystrokeManager.query(
        "Supported commands: \""+
            Object.keys(keyManager).join("\", \"") +
            "\". Hit Enter to escape.",
        function(result){
            if (result==""){
                console.log("empty help message");
            }else{
                console.log("help message:" + result);
            }},
        "",
        true);
    return true;
};

keyManager.R = keyManager.reload = function(){
    location.href = location.href
    return true;
};

// a simple countdown timer

var timers = [];

function Timer(){
    this._timer = $("");
    keystrokeManager._minibuffer.append(this._timer);
}

Timer.prototype.destroy = function(){
    this._timer.remove();
    this.stop();
}

Timer.prototype.start = function(seconds,callback){
    var self = this;
    var update = function(){
        var rem = (seconds%60);
        var quo = (seconds-rem)/60;
        console.log("timer updated: "+quo+":"+rem);
        self._timer.text(quo+":"+rem);
    }
    var decrease = function(){
        --seconds;
        update();
        if(seconds<=0){
            stop();
        }
    }
    var stop = function(){
        (callback||identity)();
        clearInterval(id);
    }
    this.stop = stop;
    var id = setInterval(decrease,1000);
}

keyManager.timer = function(){
    var t = new Timer();
    keystrokeManager.query(
        "Enter the limit by sec",
        function(result){
            t.start(parseInt(result,10),
                    function(){
                        t._timer
                            .addClass("highlighted")
                            .css({"font-weight":"bold"});
                    });
        }, 300, false);
    return true;
};

keyManager["remove-timer"] = function(){
    timers.map(function(t){
        t.destroy();
    });
}

keyManager.color = function(){
    keystrokeManager.query(
        "Enter the style file name",
        function(result){
            $(document.head).append("<link rel='stylesheet' href='css/" + result + ".css' />");
        }, "", false);
    return true;
}
<commit_msg>expand dl,dd,dt (only add .expanded class)<commit_after>////////////////////////////////////////////////////////////////
////
//// code.js -- a replacement for org-info.js
////
//// Written by Masataro Asai (guicho2.71828@gmail.com)
//// Licenced under GPLv3.
////
////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////
// helper functions ////////////////////////////////////////////
////////////////////////////////////////////////////////////////

var identity=function(){};

jQuery.fn.visible = function() {
    return this.css('visibility', 'visible');
};

jQuery.fn.invisible = function() {
    return this.css('visibility', 'hidden');
};

jQuery.fn.emerge = function() {
    return this.addClass("emerge");
};

function text(){
    return $(".outline-text-1,"+
             ".outline-text-2,"+
             ".outline-text-3,"+
             ".outline-text-4",slide.current).first();
}

function expand(){
    console.log("clicked!");
    var tx = text();
    var result =
        $(".expanded + li:not(.expanded),"+
          ".expanded + dt + dd:not(.expanded),"+
          "li:first-child:not(.expanded),"+
          "dd:first-of-type:not(.expanded)",tx).first().addClass("expanded emerging-list");
    $(".expanded > ul:not(.expanded)"+
      ".expanded > dl:not(.expanded)",tx).first().addClass("expanded emerging");
    return result;
}

function setExpanders(){
    $("outline-1,outline-2,outline-3,outline-4").click(expand);
}

function outline(n){
    return ".outline-"+n;
}
function outlineContents(n){
    return ".outline-text-"+n+", h"+n;
}

function container(){
    return Array.prototype.reduce.call(
        arguments,
        function(prev,arg){
            return prev+"-"+arg;
        },
        "#outline-container-sec"
    );
}

function unparseSection(id){
    var re = /outline-container-sec-(.*)/;
    return (id.match(re)||[null,"1"])[1].split("-");
}

function clip(low,x,high,when_low,when_high){
    if (x < low){
        return when_low || low;
    }else if (high || x > high){
        return when_high || high;
    }else {
        return x;
    }
}

function adjustVerticalCenter(){
    var top = 0.4 * ($(window).height() - $(document.body).height());
    var high = 0.2 * $(window).height();
    if (top > high){
        $(document.body)
            .delay( 100 )
            .animate({"margin-top": high});
        slide.headline()
            .delay( 300 )
            .animate({"margin-bottom": top - high});
    }else{
        $(document.body)
            .delay( 100 )
            .animate({"margin-top": clip(20,top)});
    }
}

////////////////////////////////////////////////////////////////
//// Slide objects /////////////////////////////////////////////
////////////////////////////////////////////////////////////////

var nullp = $.isEmptyObject;

function Slide(arg,prev){
    this.previous = prev;
    if (!nullp(arg) && arg.length!=0){
        this.current = arg;
        var matched = arg.get(0).className.match(/outline-([0-9]*)/);
        if(matched){
            this.level=(+matched[1]);
        }else{
            throw new Error("arg is not of class outline-x.");
        }
        return this;
    }else{
        throw new Error("arg is null / jquery object with no match");
    }
}

Slide.prototype = {
    current : undefined, // jquery object
    previous : undefined, // Slide object
    level : 1,
    // hide: function(){
    //   this.current.hide();
    // },
    headline: function(){
        return $("h1,h2,h3,h4",slide.current).first();
    },
    hideParents: function(){
        for(var i = 1;i<this.level;i++){
            $(outlineContents(i)).hide();
        }
    },
    hideSiblings: function(){
        $(outlineContents(this.level)).hide();
    },
    hideChildren: function(){
        for(var i=this.level+1;0<($(outline(i)).length);i++){
            $(outlineContents(i)).hide();
        }
    },
    showSelf: function(){
        this.current.children(outlineContents(this.level)).show().emerge();
    },
    show: function(){
        this.hideParents();
        this.hideSiblings();
        this.hideChildren();
        this.showSelf();
        adjustVerticalCenter();
        return this;
    },
    nochild : function(){
        return nullp(this.current.children(outline(1+this.level)));
    },
    // if sustain is true, it doesn't add the current slide to the slide history
    new : function(next,sustain){
        return new Slide(next,(sustain?this.previous:this));
    },
    up : function(sustain){return this.new(this.current.parent(),sustain);},
    down : function(sustain){
        return this.new(this.current.children(outline(1+this.level)).first(),sustain);},
    left : function(sustain){return this.new(this.current.prev(),sustain)},
    right : function(sustain){return this.new(this.current.next(),sustain)},
    next : function(){
        try{return this.down();} catch (x) {}
        try{return this.right();} catch (x) {}

        var slide = this;
        while(true){
            try{
                slide = slide.up();
            } catch (x) {
                throw new Error("no next slide");
                // tells that there is no next slide
            }
            try{
                // if the upper slide has the following slide,
                // then it is the next slide
                return slide.right(true);
            } catch (x) {
            }
        }
    },
    prev : function(){
        if (this.previous){
            return this.previous;
        }else{
            throw new Error("no previous slide");
        }
    },
};

var slide;

////////////////////////////////////////////////////////////////
//// Keyboard event handlers ///////////////////////////////////
////////////////////////////////////////////////////////////////

// a hash table with {"key strokes":function}.
// functions should take zero argument and
// should return true on success, false otherwise.
var keyManager = {};

var keystrokeManager = {
    _stroke: "",
    _minibuffer: $("

"),
    _prompt: $(""),
    _input: $(""),
    init: function(def_stroke,def_prompt){
        this.stroke=(def_stroke||"");
        this._prompt.text(def_prompt||"");
        return this;
    },
    push: function(c){
        this.stroke=this.stroke.concat(c);
        return this;
    },
    backspace: function(){
        this.stroke=this.stroke.slice(0,-1);
        return this;
    },
    setup: function(){
        this._minibuffer
            .append(this._prompt)
            .append(this._input);
        $("body").prepend(this._minibuffer);
    },
    query: function(message,fn,def,enteredByDefault){
        // message : string
        // fn : callback
        // def : string -- default value
        // enteredByDefault : boolean
        var old = this._prompt.text();
        $(window).off("keypress",keyboardHandler);
        this.init(((def && enteredByDefault) ?
                   def : ""),
                  (enteredByDefault ?
                   message : (message+" (Default:"+def+") ")));
        var handler=(function(e){
            try{
                enterHandler(
                    backspaceHandler(
                        cancelHandler(
                            printHandler())))(e);
            } catch (x) {
                if (x=="enter") {
                    var result = this._input.text();
                    keystrokeManager.init("",old);
                    $(window).off("keypress",handler);
                    $(window).on("keypress",keyboardHandler);
                    fn((result=="")?def:result);
                }
                else throw x;
            }
        }).bind(this);
        $(window).on("keypress", handler);
        return true;
    }
};

keystrokeManager.__defineSetter__(
    "stroke",function(str){
        this._stroke = str;
        this._input.text(str);
        return this;
    });
keystrokeManager.__defineGetter__(
    "stroke",function(){
        return this._stroke;
    });

function available_p(e){ return (32 <= e.charCode && e.charCode <= 126)}
function backspace_p(e){ return (e.keyCode == 8)}
function enter_p(e){ return (e.keyCode == 13)}
function cancel_p(e){
    return (e.charCode == 103 && e.ctrlKey) // Ctrl-g
        || (e.keyCode == 27);  // Esc
}

function enterHandler(next){
    return function(e){
        if (enter_p(e)){
            e.stopPropagation();
            e.preventDefault();
            throw "enter";
        } else return (next||identity)(e);
    };
}

function backspaceHandler(next){
    return function(e){
        if (backspace_p(e)){
            e.stopPropagation();
            e.preventDefault();
            keystrokeManager.backspace();
        } else return (next||identity)(e);
    };
}

function cancelHandler(next){
    return function(e){
        if (cancel_p(e)){
            e.stopPropagation();
            e.preventDefault();
            console.log("cancelled");
            keystrokeManager.init();
        } else return (next||identity)(e);
    };
}

function printHandler(next){
    return function(e){
        if (available_p(e)){
            keystrokeManager.push(String.fromCharCode(e.charCode));
        } else return (next||identity)(e);
    };
}

function dispatchHandler(next){
    return function(e){
        if (available_p(e)){
            keystrokeManager.push(String.fromCharCode(e.charCode));
            var handler = keyManager[keystrokeManager.stroke];
            if (typeof handler == "function"){
                console.log("Handler function "
                            + keystrokeManager.stroke +" found");
                try{
                    if (!handler(e)){
                        console.log(
                            "Handler function returned a false value.  Resetting the strokemanager state.");
                        keystrokeManager.init();
                    }else {
                        console.log("Handler function returned!");
                    }
                } catch (x) {
                    console.error(x);
                    keystrokeManager.init();
                }
            }
        } else return (next||identity)(e);
    };
}

function keyboardHandler(e){
    console.log("charCode:"+e.charCode
                +" keyCode:"+e.keyCode
                +" which:"+e.which
                +" Modifier:"
                +(e.ctrlKey?"Ctrl":"")
                +(e.shiftKey?"Shift":"")
                +(e.metaKey?"Meta":"")
                +(e.altKey?"Alt":""));
    backspaceHandler(
        cancelHandler(
            dispatchHandler()))(e);
    console.log(keystrokeManager.stroke);
}

////////////////////////////////////////////////////////////////
//// Initialization
////

window.onload = function(){
    $("#content").addClass("outline-1");
    slide = new Slide($("#content"));
    slide.show();
    setExpanders();
    keystrokeManager.setup();
    $(window).keypress(keyboardHandler);

    var href = location.href;
    var re = /.*#(.*)/;
    var result = href.match(re);
    if(result){
        var secnums = result[1].split("-");
        try{
            console.log(container.apply(this,secnums));
            slide = slide.new($(container.apply(this,secnums)));
            slide.show();
        } catch (x) {

        }
    }
};

////////////////////////////////////////////////////////////////
//// keymanager functions

// expand one element in the list in the current slide, or go to the next slide
keyManager.n = keyManager[" "] = function(){
    $(".title").hide();
    console.log(slide.level);
    try{
        if(expand().length==0){
            slide = slide.next();
            slide.show();
        }
    } catch (x) {
        console.warn("This is the last slide!");
    }
};

// expand all elements in the current slide
keyManager.N = function(){
    $(".title").hide();
    console.log(slide.level);
    if(expand().length==0){keyManager.n();}
    while (expand().length>0){}
};

keyManager.p = function(){
    console.log(slide.level);
    try{
        slide = slide.prev();
        slide.show();
    } catch (x) {
        console.warn("This is the first slide!");
    }
};

keyManager.u = keyManager["^"] = function(){
    console.log(slide.level);
    try{
        slide = slide.up();
        slide.show();
    } catch (x) {
        console.warn("There is no parent section!");
    }
};

keyManager.s = keyManager.go = function(){
    return sectionPrompt2("Enter a section number");
};

function sectionPrompt2(message){
    return keystrokeManager.query(
        message,function(result){
            var secnums = result.split(".");
            try{
                console.log(container.apply(this,secnums));
                slide = slide.new($(container.apply(this,secnums)));
                slide.show();
            } catch (x) {
                sectionPrompt2(container.apply(this,secnums) + " does not exists.");
            }
        },
        unparseSection(slide.current.get(0).id).join("-"));
}

// debug

var debug = false;

function toggleDebug(){
    if (!debug){
        debug = true;
        return (function(){
                    $(this).addClass("debug-border");
                });
    }else{
        debug = false;
        return (function(){
                    $(this).removeClass("debug-border");
                });
    }
}

keyManager.d = function(){
    $(".outline-1,.outline-2,.outline-3,.outline-4"+
      ",li,ul,ol,h1,h2,h3,h4,.outline-text-2, .outline-text-3, .outline-text-4")
        .map(toggleDebug());
    console.log("debug : "+debug);
};

// unfolding the presentation and shows all slides at once
keyManager.unfold = function(){
    $("*").visible().show();
    $(".note").css({position:"static",top:"1em"});
    $("body").css({overflow:"auto"});
};

keyManager["-"] = function(){
    var maxwidth = parseFloat($("#content").css("max-width"))*0.91;
    var size = parseFloat($("body").css("font-size"))*0.91;
    $("#content").css("max-width",maxwidth);
    $("body").css("font-size",size);
};

keyManager["+"] = function(){
    var maxwidth = parseFloat($("#content").css("max-width"))*1.1;
    var size = parseFloat($("body").css("font-size"))*1.1;
    $("#content").css("max-width",maxwidth);
    $("body").css("font-size",size);
};

keyManager.toggle = function(){
    $("#minibuffer").toggle();
};

keyManager.banner = function(){
    $("#banner").toggle();
};

keyManager.help = keyManager.h = keyManager["?"] = function(){
    keystrokeManager.query(
        "Supported commands: \""+
            Object.keys(keyManager).join("\", \"") +
            "\". Hit Enter to escape.",
        function(result){
            if (result==""){
                console.log("empty help message");
            }else{
                console.log("help message:" + result);
            }},
        "",
        true);
    return true;
};

keyManager.R = keyManager.reload = function(){
    location.href = location.href
    return true;
};

// a simple countdown timer

var timers = [];

function Timer(){
    this._timer = $("");
    keystrokeManager._minibuffer.append(this._timer);
}

Timer.prototype.destroy = function(){
    this._timer.remove();
    this.stop();
}

Timer.prototype.start = function(seconds,callback){
    var self = this;
    var update = function(){
        var rem = (seconds%60);
        var quo = (seconds-rem)/60;
        console.log("timer updated: "+quo+":"+rem);
        self._timer.text(quo+":"+rem);
    }
    var decrease = function(){
        --seconds;
        update();
        if(seconds<=0){
            stop();
        }
    }
    var stop = function(){
        (callback||identity)();
        clearInterval(id);
    }
    this.stop = stop;
    var id = setInterval(decrease,1000);
}

keyManager.timer = function(){
    var t = new Timer();
    keystrokeManager.query(
        "Enter the limit by sec",
        function(result){
            t.start(parseInt(result,10),
                    function(){
                        t._timer
                            .addClass("highlighted")
                            .css({"font-weight":"bold"});
                    });
        }, 300, false);
    return true;
};

keyManager["remove-timer"] = function(){
    timers.map(function(t){
        t.destroy();
    });
}

keyManager.color = function(){
    keystrokeManager.query(
        "Enter the style file name",
        function(result){
            $(document.head).append("<link rel='stylesheet' href='css/" + result + ".css' />");
        }, "", false);
    return true;
}
<|endoftext|>