<commit_before>/* Base view */

var dust = require('dustjs-linkedin'),
	app = require('./ridge'),
	Promise = require('./util/promise'),
	tagPattern = /<(\w+)[^>]*>/,
	attrPattern = /\s+(\S+)\s*=\s*("[^"]*"|'[^']*')/g;

/* Extract wrapping element, attributes and contents */
function parseElement(html, callback) {
	var m = html.match(tagPattern);    // match first start tag

	if (m) {
		var tag = m[0], tagName = m[1],
			endTag = '</' + tagName + '>',
			endIndex = html.lastIndexOf('</');

		// check that the last end matches the start tag
		// and that there is no content after it

		if (html.slice(endIndex).replace(/\s+/g, '') == endTag)
			return callback(html.slice(m.index + tag.length, endIndex), tag, endTag, tagName);
	}

	return callback(html);
}

function attributes(tag) {    // extract attributes from tag string
	var attrs = {}, m;

	while (m = attrPattern.exec(tag))
		attrs[m[1]] = m[2].slice(1, -1);

	return attrs;
}

function updateElement(html, tag, endTag, tagName) {
	if (tag && !this.rendered) {
		if (this.$el.is(tagName)) {
			this.$el.attr(attributes(tag));
		} else {
			var old = this.$el, queue = old.queue();
			old.clearQueue();
			this.setElement(tag + endTag);
			old.replaceWith(this.el);
			this.$el.queue(queue);
		}
	}
	this.el.innerHTML = html;
	this.rendered = true;

	// remove old subviews
	_.invoke(this.views, 'remove');
}

function createViews(view) {
	return _.flatten(_.map(view.subviews, function(options, name) {
		var defaults = {
			model: view.model,
			data: view.data
		};

		var Subview = app.views[name];

		var selector = options;
		if ($.isPlainObject(options)) {
			selector = options.selector;
			if (!selector) return new Subview(options);
			else _.defaults(options, defaults);
		} else {
			options = _.clone(defaults);
		}

		return _.map(view.$(selector), function(elem) {
			options.el = elem;
			return new Subview(options);
		});
	}));
}

var View = Backbone.View.extend({
	// Promise factory function using view as the context with callbacks
	Promise: function(resolver) {
		return Promise(resolver, this);
	},

	constructor: function(options) {
		_.extend(this, _.pick(options, 'template', 'parent', 'bindings'));

		// we clone to prevent views referencing the same object
		this.data = options && options.data ? _.clone(options.data) : {};

		if (!this.elements) this.elements = {};

		Backbone.View.apply(this, arguments);

		if(_.isString(this.model))
			this.model = new app.models[this.model]();

		if(_.isString(this.collection))
			this.collection = new app.collections[this.collection]();

		this.rendered = (this.el && this.el.firstChild) != null;

		if (!this.rendered) this.render();
		else if (this.attach) this.attach();

		// this.ready(callbacks)
		//

		this.ready = this.ready || $.Callbacks('once memory').fireWith(this).add;
	},

	convertElements: function() {
		var view = this;
		_.each(this.elements, function(element, key) {
			if(/^\$/.test(key)) view.elements[key.slice(1)] = element[0];
		});
	},

	initializeViews: function() {
		var _view = this;

		_view.$('[data-view]').each(function() {
			var viewName = $(this).data('view');

			var View = app.views[viewName];

			// TODO destroy/remove all nested views when a PageView is removed.
			if (View) new View({ el: this, data: _view.data });
		});
	},

	render: function() {
		if(this.unobserve) this.unobserve();

		var _view = this;

		var data = _.result(_view, 'data');

		var args = arguments[0] === true ? _.rest(arguments) : null;

		if(app.user)
			data.user = app.user.toJSON();

		if (_view.model) {
			var modelData = _view.model.toJSON();

			if(args)
				data[_view.model.name.toCamelCase()] = modelData;
			else
				_.extend(data, modelData);
		}

		_view.renderTemplate(data).ready(args || arguments);

		return _view;
	},

	// Render Dust template and update element, using the fx queue

	renderTemplate: function(data) {
		var templateName = this.template,
			rendering = this.Promise(function(resolve, reject) {
			this.$el.queue(function(next, hooks) {
				// hooks.stop() is called if queue is stopped using $el.stop() or $el.finish()
				hooks.stop = function() {
					reject();
				};

				dust.render(templateName, data || {}, function(err, out) {
					if (err)
						reject(err);
					else
						parseElement(out, resolve);
				});
			});
		}).done(updateElement, this.attach, function() { this.$el.dequeue(); })
			.fail(Promise.error);

		this.ready = rendering.done;
		this.rendering = rendering;

		return this;
	},

	attach: function() {
		this.views = createViews(this);
	},

	// animated enter
	enter: function() {
		this.$el.enter.apply(this.$el, arguments);
		return this;
	},

	preventDefault: function(e) {
		e.preventDefault();
	},

	alternate: function() {
		this.$el.alternate();
		return this;
	},

	// animated remove
	remove: function() {
		this.$el.leave();
		return this.stopListening();
	},

	stopListening: function() {
		Backbone.Events.stopListening.apply(this, arguments);
		_.invoke(this.views, 'stopListening');
	}
});

View.prototype._remove = View.prototype.remove;
View.prototype._render = View.prototype.render;

module.exports = View;
<commit_msg>Removed View.prototype.stopListening and recursively stopListening in remove instead.<commit_after>/* Base view */

var dust = require('dustjs-linkedin'),
	app = require('./ridge'),
	Promise = require('./util/promise'),
	tagPattern = /<(\w+)[^>]*>/,
	attrPattern = /\s+(\S+)\s*=\s*("[^"]*"|'[^']*')/g;

/* Extract wrapping element, attributes and contents */
function parseElement(html, callback) {
	var m = html.match(tagPattern);    // match first start tag

	if (m) {
		var tag = m[0], tagName = m[1],
			endTag = '</' + tagName + '>',
			endIndex = html.lastIndexOf('</');

		// check that the last end matches the start tag
		// and that there is no content after it

		if (html.slice(endIndex).replace(/\s+/g, '') == endTag)
			return callback(html.slice(m.index + tag.length, endIndex), tag, endTag, tagName);
	}

	return callback(html);
}

function attributes(tag) {    // extract attributes from tag string
	var attrs = {}, m;

	while (m = attrPattern.exec(tag))
		attrs[m[1]] = m[2].slice(1, -1);

	return attrs;
}

function updateElement(html, tag, endTag, tagName) {
	if (tag && !this.rendered) {
		if (this.$el.is(tagName)) {
			this.$el.attr(attributes(tag));
		} else {
			var old = this.$el, queue = old.queue();
			old.clearQueue();
			this.setElement(tag + endTag);
			old.replaceWith(this.el);
			this.$el.queue(queue);
		}
	}
	this.el.innerHTML = html;
	this.rendered = true;

	// remove old subviews
	_.invoke(this.views, 'remove');
}

function createViews(view) {
	return _.flatten(_.map(view.subviews, function(options, name) {
		var defaults = {
			model: view.model,
			data: view.data
		};

		var Subview = app.views[name];

		var selector = options;
		if ($.isPlainObject(options)) {
			selector = options.selector;
			if (!selector) return new Subview(options);
			else _.defaults(options, defaults);
		} else {
			options = _.clone(defaults);
		}

		return _.map(view.$(selector), function(elem) {
			options.el = elem;
			return new Subview(options);
		});
	}));
}

var View = Backbone.View.extend({
	// Promise factory function using view as the context with callbacks
	Promise: function(resolver) {
		return Promise(resolver, this);
	},

	constructor: function(options) {
		_.extend(this, _.pick(options, 'template', 'parent', 'bindings'));

		// we clone to prevent views referencing the same object
		this.data = options && options.data ? _.clone(options.data) : {};

		if (!this.elements) this.elements = {};

		Backbone.View.apply(this, arguments);

		if(_.isString(this.model))
			this.model = new app.models[this.model]();

		if(_.isString(this.collection))
			this.collection = new app.collections[this.collection]();

		this.rendered = (this.el && this.el.firstChild) != null;

		if (!this.rendered) this.render();
		else if (this.attach) this.attach();

		// this.ready(callbacks)
		//

		this.ready = this.ready || $.Callbacks('once memory').fireWith(this).add;
	},

	convertElements: function() {
		var view = this;
		_.each(this.elements, function(element, key) {
			if(/^\$/.test(key)) view.elements[key.slice(1)] = element[0];
		});
	},

	initializeViews: function() {
		var _view = this;

		_view.$('[data-view]').each(function() {
			var viewName = $(this).data('view');

			var View = app.views[viewName];

			// TODO destroy/remove all nested views when a PageView is removed.
			if (View) new View({ el: this, data: _view.data });
		});
	},

	render: function() {
		if(this.unobserve) this.unobserve();

		var _view = this;

		var data = _.result(_view, 'data');

		var args = arguments[0] === true ? _.rest(arguments) : null;

		if(app.user)
			data.user = app.user.toJSON();

		if (_view.model) {
			var modelData = _view.model.toJSON();

			if(args)
				data[_view.model.name.toCamelCase()] = modelData;
			else
				_.extend(data, modelData);
		}

		_view.renderTemplate(data).ready(args || arguments);

		return _view;
	},

	// Render Dust template and update element, using the fx queue

	renderTemplate: function(data) {
		var templateName = this.template,
			rendering = this.Promise(function(resolve, reject) {
			this.$el.queue(function(next, hooks) {
				// hooks.stop() is called if queue is stopped using $el.stop() or $el.finish()
				hooks.stop = function() {
					reject();
				};

				dust.render(templateName, data || {}, function(err, out) {
					if (err)
						reject(err);
					else
						parseElement(out, resolve);
				});
			});
		}).done(updateElement, this.attach, function() { this.$el.dequeue(); })
			.fail(Promise.error);

		this.ready = rendering.done;
		this.rendering = rendering;

		return this;
	},

	attach: function() {
		this.views = createViews(this);
	},

	// animated enter
	enter: function() {
		this.$el.enter.apply(this.$el, arguments);
		return this;
	},

	preventDefault: function(e) {
		e.preventDefault();
	},

	alternate: function() {
		this.$el.alternate();
		return this;
	},

	// animated remove
	remove: function() {
		this.stopListening();

		var subViews = this.views;

		while(subViews && subViews.length > 0) {
			_.invoke(subViews, 'stopListening');

			subViews = _.compact(_.flatten(_.pluck(subViews, 'views')));
		}

		this.$el.leave();

		return this;
	}
});

View.prototype._remove = View.prototype.remove;
View.prototype._render = View.prototype.render;

module.exports = View;
<|endoftext|>


<commit_before>//@flow
/*
Copyright 2016 Aviral Dasgupta
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider';
import {PillCompletion} from './Components';
import sdk from '../index';
import FuzzyMatcher from './FuzzyMatcher';
import _pull from 'lodash/pull';
import _sortBy from 'lodash/sortBy';
import MatrixClientPeg from '../MatrixClientPeg';

import type {Room, RoomMember} from 'matrix-js-sdk';

const USER_REGEX = /@\S*/g;

let instance = null;

export default class UserProvider extends AutocompleteProvider {
    users: Array<RoomMember> = [];

    constructor() {
        super(USER_REGEX, {
            keys: ['name'],
        });
        this.matcher = new FuzzyMatcher([], {
            keys: ['name'],
            shouldMatchPrefix: true,
        });
    }

    async getCompletions(query: string, selection: {start: number, end: number}, force = false) {
        const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar');

        let completions = [];
        let {command, range} = this.getCurrentCommand(query, selection, force);
        if (command) {
            completions = this.matcher.match(command[0]).slice(0, 4).map((user) => {
                let displayName = (user.name || user.userId || '').replace(' (IRC)', ''); // FIXME when groups are done
                let completion = displayName;
                if (range.start === 0) {
                    completion += ': ';
                } else {
                    completion += ' ';
                }
                return {
                    completion,
                    component: (
                        <PillCompletion
                            initialComponent={<MemberAvatar member={user} width={24} height={24}/>}
                            title={displayName}
                            description={user.userId} />
                    ),
                    range,
                };
            });
        }
        return completions;
    }

    getName() {
        return '👥 ' + _t('Users');
    }

    setUserListFromRoom(room: Room) {
        const events = room.getLiveTimeline().getEvents();
        const lastSpoken = {};

        for(const event of events) {
            lastSpoken[event.getSender()] = event.getTs();
        }

        const currentUserId = MatrixClientPeg.get().credentials.userId;
        this.users = room.getJoinedMembers().filter((member) => {
            if (member.userId !== currentUserId) return true;
        });

        this.users = _sortBy(this.users, (member) =>
            1E20 - lastSpoken[member.userId] || 1E20,
        );

        this.matcher.setObjects(this.users);
    }

    onUserSpoke(user: RoomMember) {
        if(user.userId === MatrixClientPeg.get().credentials.userId) return;

        this.users = this.users.splice(
            this.users.findIndex((user2) => user2.userId === user.userId), 1);
        this.users = [user, ...this.users];

        this.matcher.setObjects(this.users);
    }

    static getInstance(): UserProvider {
        if (instance == null) {
            instance = new UserProvider();
        }
        return instance;
    }

    renderCompletions(completions: [React.Component]): ?React.Component {
        return

            {completions}

;
    }

    shouldForceComplete(): boolean {
        return true;
    }
}
<commit_msg>Fix bug where a received message would remove completions for users<commit_after>//@flow
/*
Copyright 2016 Aviral Dasgupta
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider';
import {PillCompletion} from './Components';
import sdk from '../index';
import FuzzyMatcher from './FuzzyMatcher';
import _pull from 'lodash/pull';
import _sortBy from 'lodash/sortBy';
import MatrixClientPeg from '../MatrixClientPeg';

import type {Room, RoomMember} from 'matrix-js-sdk';

const USER_REGEX = /@\S*/g;

let instance = null;

export default class UserProvider extends AutocompleteProvider {
    users: Array<RoomMember> = [];

    constructor() {
        super(USER_REGEX, {
            keys: ['name'],
        });
        this.matcher = new FuzzyMatcher([], {
            keys: ['name'],
            shouldMatchPrefix: true,
        });
    }

    async getCompletions(query: string, selection: {start: number, end: number}, force = false) {
        const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar');

        let completions = [];
        let {command, range} = this.getCurrentCommand(query, selection, force);
        if (command) {
            completions = this.matcher.match(command[0]).slice(0, 4).map((user) => {
                let displayName = (user.name || user.userId || '').replace(' (IRC)', ''); // FIXME when groups are done
                let completion = displayName;
                if (range.start === 0) {
                    completion += ': ';
                } else {
                    completion += ' ';
                }
                return {
                    completion,
                    component: (
                        <PillCompletion
                            initialComponent={<MemberAvatar member={user} width={24} height={24}/>}
                            title={displayName}
                            description={user.userId} />
                    ),
                    range,
                };
            });
        }
        return completions;
    }

    getName() {
        return '👥 ' + _t('Users');
    }

    setUserListFromRoom(room: Room) {
        const events = room.getLiveTimeline().getEvents();
        const lastSpoken = {};

        for(const event of events) {
            lastSpoken[event.getSender()] = event.getTs();
        }

        const currentUserId = MatrixClientPeg.get().credentials.userId;
        this.users = room.getJoinedMembers().filter((member) => {
            if (member.userId !== currentUserId) return true;
        });

        this.users = _sortBy(this.users, (member) =>
            1E20 - lastSpoken[member.userId] || 1E20,
        );

        this.matcher.setObjects(this.users);
    }

    onUserSpoke(user: RoomMember) {
        if(user.userId === MatrixClientPeg.get().credentials.userId) return;

        // Move the user that spoke to the front of the array
        this.users.splice(
            this.users.findIndex((user2) => user2.userId === user.userId), 1);
        this.users = [user, ...this.users];

        this.matcher.setObjects(this.users);
    }

    static getInstance(): UserProvider {
        if (instance == null) {
            instance = new UserProvider();
        }
        return instance;
    }

    renderCompletions(completions: [React.Component]): ?React.Component {
        return

            {completions}

;
    }

    shouldForceComplete(): boolean {
        return true;
    }
}
<|endoftext|>


<commit_before>
/*
   Mixin to enable scrolling from one anchor point to another
   within a same page.

   Mix the mixin into View classes like:
   e.g. App.YourView = Ember.View.extend(App.GoTo, {});

   And, In your template,

   Source

   Or,

   Source
 */
App.GoTo = Ember.Mixin.create({
    click: function(e) {
        var $target = $(e.target);

        if ($target.hasClass('goto')) {
            this.goTo($target.data('target'));
            e.preventDefault();
        }
    },

    goTo: function(target) {
        $('html, body').stop().animate({
            scrollTop: $(target).offset().top
        }, 500);
    }
});

App.PageView = Ember.View.extend(App.GoTo, {
    templateName: 'page',

    showTitle: function(){
        // Don't show title for styled pages
        if (this.get('controller.id') == 'about')return false;
        if (this.get('controller.id') == 'get-involved')return false;
        if (this.get('controller.id') == 'business')return false;
        if (this.get('controller.id') == 'fmo')return false;
        return true;
    }.property('controller.id'),

    classNames: 'page static-page'.w(),

    setup: function() {
        Ember.run.scheduleOnce('afterRender', this, function() {
            if (!Em.isNone(this.$())) {
                this.renderSections();
                this.bindEvents();
            }
        });
    }.observes('controller.body'),

    willDestroyElement: function() {
        this.unbindEvents();
    },

    bindEvents: function() {
        $(window).on('resize', $.proxy(this.renderSections, this));
    },

    unbindEvents: function() {
        $(window).off('resize', $.proxy(this.renderSections, this));
    },

    renderSections: function(e) {
        var windowHeight = $(window).height();
        this.$('.static-onepage-section').css('height', windowHeight + 'px');
        this.$('.static-onepage-content').each(function() {
            // Reset first to get correct height
            $(this).css({
                'position' : 'relative',
                'height' : 'auto'
            });
            $(this).css({
                'height' : $(this).height() + 'px',
                'position' : 'absolute'
            });
        });
    },

    didInsertElement: function(e){
		this.$().find('.carousel').unslider({
            dots: true,
            fluid: true,
            delay: 10000
        });
        if (this.get('controller.id') == 'meet-team') {
            var typeKeys = [72, 69, 76, 76, 79],
                something_index = 0,
                handler = function (e) {
                    if (e.keyCode === typeKeys[something_index++]) {
                        if (something_index === typeKeys.length) {
                            $(document).unbind("keydown", handler);
                            var snd = new Audio('/static/assets/media/hello.mp3');
                            var moust = $('')
                            $('div.image').css('position', 'relative');

                            var loc = [
                                {top: '124px', left: '113px', rotate: -5}, // AC
                                {top: '126px', left: '134px', rotate: 12}, // BL
                                {top: '114px', left: '126px', rotate: -5}, // MP
                                {top: '114px', left: '92px', rotate: -10}, //NJ
                                {top: '126px', left: '94px', rotate: 23}, //NE
                                {top: '89px', left: '124px', rotate: 0}, //LG
                                {top: '114px', left: '113px', rotate: -11}, //NT
                                {top: '117px', left: '112px', rotate: -9}, //LM
                                {top: '124px', left: '123px', rotate: 0}, // MG
                                {top: '118px', left: '126px', rotate: 3}, // MH
                                {top: '123px', left: '109px', rotate: -3}, // SS
                                {top: '1000px', left: '-1000px', rotate: 7}
                            ]

                            var t = 0;
                            var m = [];
                            $('div.image').each(function(crew){
                                m[t] = moust.clone();
                                $(this).append(m[t]);
                                if (loc[t] != undefined) {
                                    var degree = loc[t].rotate;
                                    m[t].fadeOut(0);
                                    m[t].fadeIn(1000);
                                    m[t].css({
                                                '-webkit-transform': 'rotate(' + degree + 'deg)',
                                                '-moz-transform': 'rotate(' + degree + 'deg)',
                                                '-ms-transform': 'rotate(' + degree + 'deg)',
                                                '-o-transform': 'rotate(' + degree + 'deg)',
                                                'transform': 'rotate(' + degree + 'deg)',
                                                'zoom': 1
                                    }, 5000);
                                    m[t].animate(loc[t], 10000);
                                }
                                t++;
                            });
                            snd.play()
                        }
                    } else {
                        something_index = 0;
                    }
                };
            $(document).bind("keydown", handler);
        }
    }
});
<commit_msg>Fix for static pages on low resolution<commit_after>
/*
   Mixin to enable scrolling from one anchor point to another
   within a same page.

   Mix the mixin into View classes like:
   e.g. App.YourView = Ember.View.extend(App.GoTo, {});

   And, In your template,

   Source

   Or,

   Source
 */
App.GoTo = Ember.Mixin.create({
    click: function(e) {
        var $target = $(e.target);

        if ($target.hasClass('goto')) {
            this.goTo($target.data('target'));
            e.preventDefault();
        }
    },

    goTo: function(target) {
        $('html, body').stop().animate({
            scrollTop: $(target).offset().top
        }, 500);
    }
});

App.PageView = Ember.View.extend(App.GoTo, {
    templateName: 'page',

    showTitle: function(){
        // Don't show title for styled pages
        if (this.get('controller.id') == 'about')return false;
        if (this.get('controller.id') == 'get-involved')return false;
        if (this.get('controller.id') == 'business')return false;
        if (this.get('controller.id') == 'fmo')return false;
        return true;
    }.property('controller.id'),

    classNames: 'page static-page'.w(),

    setup: function() {
        Ember.run.scheduleOnce('afterRender', this, function() {
            if (!Em.isNone(this.$())) {
                this.renderSections();
                this.bindEvents();
            }
        });
    }.observes('controller.body'),

    willDestroyElement: function() {
        this.unbindEvents();
    },

    bindEvents: function() {
        $(window).on('resize', $.proxy(this.renderSections, this));
    },

    unbindEvents: function() {
        $(window).off('resize', $.proxy(this.renderSections, this));
    },

    renderSections: function(e) {
        var windowHeight = $(window).height();

        this.$('.static-onepage-content').each(function() {
            // Reset first to get correct height
            $(this).css({
                'position' : 'relative',
                'height' : 'auto'
            });
            // Set static height for centering if not higher then section
            if ($(this).height() <= $(window).height() - 100) {
                $(this).css({
                    'height' : $(this).height() + 'px',
                    'position' : 'absolute'
                });
                // Set section height to window height
                $(this).closest( ".static-onepage-section" ).css('height', windowHeight + 'px');
            }
        });
    },

    didInsertElement: function(e){
		this.$().find('.carousel').unslider({
            dots: true,
            fluid: true,
            delay: 10000
        });
        if (this.get('controller.id') == 'meet-team') {
            var typeKeys = [72, 69, 76, 76, 79],
                something_index = 0,
                handler = function (e) {
                    if (e.keyCode === typeKeys[something_index++]) {
                        if (something_index === typeKeys.length) {
                            $(document).unbind("keydown", handler);
                            var snd = new Audio('/static/assets/media/hello.mp3');
                            var moust = $('')
                            $('div.image').css('position', 'relative');

                            var loc = [
                                {top: '124px', left: '113px', rotate: -5}, // AC
                                {top: '126px', left: '134px', rotate: 12}, // BL
                                {top: '114px', left: '126px', rotate: -5}, // MP
                                {top: '114px', left: '92px', rotate: -10}, //NJ
                                {top: '126px', left: '94px', rotate: 23}, //NE
                                {top: '89px', left: '124px', rotate: 0}, //LG
                                {top: '114px', left: '113px', rotate: -11}, //NT
                                {top: '117px', left: '112px', rotate: -9}, //LM
                                {top: '124px', left: '123px', rotate: 0}, // MG
                                {top: '118px', left: '126px', rotate: 3}, // MH
                                {top: '123px', left: '109px', rotate: -3}, // SS
                                {top: '1000px', left: '-1000px', rotate: 7}
                            ]

                            var t = 0;
                            var m = [];
                            $('div.image').each(function(crew){
                                m[t] = moust.clone();
                                $(this).append(m[t]);
                                if (loc[t] != undefined) {
                                    var degree = loc[t].rotate;
                                    m[t].fadeOut(0);
                                    m[t].fadeIn(1000);
                                    m[t].css({
                                                '-webkit-transform': 'rotate(' + degree + 'deg)',
                                                '-moz-transform': 'rotate(' + degree + 'deg)',
                                                '-ms-transform': 'rotate(' + degree + 'deg)',
                                                '-o-transform': 'rotate(' + degree + 'deg)',
                                                'transform': 'rotate(' + degree + 'deg)',
                                                'zoom': 1
                                    }, 5000);
                                    m[t].animate(loc[t], 10000);
                                }
                                t++;
                            });
                            snd.play()
                        }
                    } else {
                        something_index = 0;
                    }
                };
            $(document).bind("keydown", handler);
        }
    }
});
<|endoftext|>


<commit_before>!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.VMAP=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VMAPAdBreak, VMAPAdSource;

VMAPAdSource = _dereq_('./adsource');

VMAPAdBreak = (function() {
  function VMAPAdBreak(xml) {
    var node, subnode, _i, _j, _len, _len1, _ref, _ref1;
    this.timeOffset = xml.getAttribute('timeOffset');
    this.breakType = xml.getAttribute('breakType');
    this.breakId = xml.getAttribute('breakId');
    this.repeatAfter = xml.getAttribute('repeatAfter');
    this.adSource = null;
    this.trackingEvents = [];
    this.extensions = [];
    _ref = xml.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      switch (node.nodeName) {
        case 'AdSource':
          this.adSource = new VMAPAdSource(node);
          break;
        case 'TrackingEvents':
          _ref1 = node.childNodes;
          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
            subnode = _ref1[_j];
            if (subnode.nodeName === 'Tracking') {
              this.trackingEvents.push = {
                event: subnode.getAttribute('event'),
                url: (subnode.textContent || subnode.text || '').trim()
              };
            }
          }
          break;
        case 'Extensions':
          this.extensions = node.childNodes;
      }
    }
  }

  return VMAPAdBreak;

})();

module.exports = VMAPAdBreak;

},{"./adsource":2}],2:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VMAPAdSource;

VMAPAdSource = (function() {
  function VMAPAdSource(xml) {
    var node, _i, _len, _ref;
    this.id = null;
    this.allowMultipleAds = true;
    this.followRedirects = true;
    this.vastAdData = null;
    this.adTagURI = null;
    this.customData = null;
    _ref = node.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      switch (node.nodeName) {
        case 'AdTagURI':
          this.adTagURI = {
            templateType: node.getAttribute('templateType'),
            uri: (node.textContent || node.text || '').trim()
          };
          break;
        case 'VASTAdData':
          this.vastAdData = node;
          break;
        case 'CustomAdData':
          this.customData = node;
      }
    }
  }

  return VMAPAdSource;

})();

module.exports = VMAPAdSource;

},{}],3:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
module.exports = _dereq_('./vmap');

},{"./vmap":4}],4:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VMAP, VMAPAdBreak;

VMAPAdBreak = _dereq_('./adbreak');

VMAP = (function() {
  function VMAP(xml) {
    var node, _i, _len, _ref;
    if (!(((xml != null ? xml.documentElement : void 0) != null) && xml.documentElement.nodeName === "VMAP")) {
      throw new Error('Not a VMAP document');
    }
    this.version = xml.documentElement.getAttribute('version');
    this.adBreaks = [];
    this.extensions = [];
    _ref = xml.documentElement.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      switch (node.nodeName) {
        case 'AdBreak':
          this.adBreaks.push(new VMAPAdBreak(node));
          break;
        case 'Extensions':
          this.extensions = node.childNodes;
      }
    }
  }

  return VMAP;

})();

module.exports = VMAP;

},{"./adbreak":1}]},{},[3])
(3)
});<commit_msg>Update JS bundle<commit_after>!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.VMAP=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VMAPAdBreak, VMAPAdSource;

VMAPAdSource = _dereq_('./adsource');

VMAPAdBreak = (function() {
  function VMAPAdBreak(xml) {
    var node, subnode, _i, _j, _len, _len1, _ref, _ref1;
    this.timeOffset = xml.getAttribute('timeOffset');
    this.breakType = xml.getAttribute('breakType');
    this.breakId = xml.getAttribute('breakId');
    this.repeatAfter = xml.getAttribute('repeatAfter');
    this.adSource = null;
    this.trackingEvents = [];
    this.extensions = [];
    _ref = xml.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      switch (node.localName) {
        case 'AdSource':
          this.adSource = new VMAPAdSource(node);
          break;
        case 'TrackingEvents':
          _ref1 = node.childNodes;
          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
            subnode = _ref1[_j];
            if (subnode.localName === 'Tracking') {
              this.trackingEvents.push({
                event: subnode.getAttribute('event'),
                uri: (subnode.textContent || subnode.text || '').trim()
              });
            }
          }
          break;
        case 'Extensions':
          this.extensions = node.childNodes;
      }
    }
  }

  return VMAPAdBreak;

})();

module.exports = VMAPAdBreak;

},{"./adsource":2}],2:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VMAPAdSource;

VMAPAdSource = (function() {
  function VMAPAdSource(xml) {
    var node, _i, _len, _ref;
    this.id = xml.getAttribute('id');
    this.allowMultipleAds = xml.getAttribute('allowMultipleAds');
    this.followRedirects = xml.getAttribute('followRedirects');
    this.vastAdData = null;
    this.adTagURI = null;
    this.customData = null;
    _ref = xml.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      switch (node.localName) {
        case 'AdTagURI':
          this.adTagURI = {
            templateType: node.getAttribute('templateType'),
            uri: (node.textContent || node.text || '').trim()
          };
          break;
        case 'VASTAdData':
          this.vastAdData = node;
          break;
        case 'CustomAdData':
          this.customData = node;
      }
    }
  }

  return VMAPAdSource;

})();

module.exports = VMAPAdSource;

},{}],3:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
module.exports = _dereq_('./vmap');

},{"./vmap":4}],4:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VMAP, VMAPAdBreak;

VMAPAdBreak = _dereq_('./adbreak');

VMAP = (function() {
  function VMAP(xml) {
    var node, _i, _len, _ref;
    if (!(((xml != null ? xml.documentElement : void 0) != null) && xml.documentElement.localName === "VMAP")) {
      throw new Error('Not a VMAP document');
    }
    this.version = xml.documentElement.getAttribute('version');
    this.adBreaks = [];
    this.extensions = [];
    _ref = xml.documentElement.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      switch (node.localName) {
        case 'AdBreak':
          this.adBreaks.push(new VMAPAdBreak(node));
          break;
        case 'Extensions':
          this.extensions = node.childNodes;
      }
    }
  }

  return VMAP;

})();

module.exports = VMAP;

},{"./adbreak":1}]},{},[3])
(3)
});<|endoftext|>


<commit_before>define(function(require, exports, module) {
    main.consumes = [
        "TestRunner", "settings", "preferences", "proc", "util", "fs",
        "watcher", "language"
    ];
    main.provides = ["test.mocha"];
    return main;

    function main(options, imports, register) {
        var TestRunner = imports.TestRunner;
        // var settings = imports.settings;
        // var prefs = imports.preferences;
        var proc = imports.proc;
        var util = imports.util;
        var fs = imports.fs;
        var language = imports.language;
        var watcher = imports.watcher;

        var dirname = require("path").dirname;
        var parseLcov = require("./lcov-parse");

        /***** Initialization *****/

        var plugin = new TestRunner("Ajax.org", main.consumes, {
            caption: "Mocha Javascript Tests"
        });
        // var emit = plugin.getEmitter();

        var SCRIPT = "";
        var MATCH_PATTERN = '^\\s*describe\\(';
        var INCLUDE_PATTERN = "";
        var EXCLUDE_PATTERN = 'node_modules';
        var EXCLUDE_LIST = [];

        // TODO: Implement the pure find files with pattern feature in nak
        // grep -ls -E "^\\s*describe\\(" * -R --exclude-dir node_modules

        var lastList = "";
        var lookup = {};
        var currentPty;

        function load() {
            // Potentially listen to the save event and run specific tests

            // prefs...

        }

        /***** Methods *****/

        function fetch(callback) {
            var cmd, args;

            return callback(null, "plugins/c9.analytics/analytics_test.js\nplugins/c9.api/base_test.js\nplugins/c9.api/collab_test.js\nplugins/c9.api/docker_test.js\nplugins/c9.api/package_test.js\nplugins/c9.api/quota_test.js\nplugins/c9.api/settings_test.js\nplugins/c9.api/sitemap-writer_test.js\nplugins/c9.api/stats_test.js\nplugins/c9.api/vfs_test.js");

            if (SCRIPT) {
                args = SCRIPT.split(" ");
                cmd = args.shift();
            }
            else {
                cmd = "grep";
                args = ["-lsR", "-E", MATCH_PATTERN];

                if (EXCLUDE_PATTERN)
                    args.push("--exclude-dir", EXCLUDE_PATTERN);

                if (INCLUDE_PATTERN)
                    args.push("--include", INCLUDE_PATTERN);
            }

            proc.spawn("bash", {
                args: ["-l", "-c", cmd + " '" + args.join("' '") + "' *"]
            }, function(err, p) {
                if (err) return callback(err);

                var stdout = "", stderr = "";
                p.stdout.on("data", function(c){
                    stdout += c;
                });
                p.stderr.on("data", function(c){
                    stderr += c;
                });
                p.on("exit", function(){
                    // if (!SCRIPT) {
                    //     var filter = new RegExp("^(?:"
                    //         + EXCLUDE_LIST.map(util.escapeRegExp).join("|")
                    //         + ")(?:\n|$)", "gm");

                    //     stdout = stdout.replace(stdout, filter);
                    // }

                    lastList = stdout;

                    callback(null, stdout);
                });

            });
        }

        function init(root, callback) {
            /*
                Set hooks to update list
                - Strategies:
                    - Periodically
                    * Based on fs/watcher events
                    - Based on opening the test panel
                    - Refresh button

                Do initial populate
            */

            var isUpdating;
            function update(){
                if (isUpdating) return fsUpdate(null, 10000);

                isUpdating = true;
                fetch(function(err, list){
                    isUpdating = false;

                    if (err) return callback(err);

                    var items = [];
                    var lastLookup = lookup;
                    lookup = {};

                    list.split("\n").forEach(function(name){
                        if (lastLookup[name]) {
                            items.push(lookup[name] = lastLookup[name]);
                            delete lastLookup[name];
                            return;
                        }

                        var item = {
                            label: name,
                            path: "/" + name,
                            type: "file",
                            status: "pending"
                        };
                        items.push(item);
                        lookup[name] = item;
                    });

                    plugin.root.items = items;

                    callback();
                });
            }

            var timer;
            function fsUpdate(e, time){
                clearTimeout(timer);
                timer = setTimeout(update, time || 1000);
            }

            function fsUpdateCheck(e){
                var reTest = new RegExp("^" + util.escapeRegExp(e.path) + "$", "m");

                if (lastList.match(reTest))
                    fsUpdate();
            }

            fs.on("afterWriteFile", fsUpdate);
            fs.on("afterUnlink", fsUpdateCheck);
            fs.on("afterRmfile", fsUpdateCheck);
            fs.on("afterRmdir", fsUpdateCheck);
            fs.on("afterCopy", fsUpdateCheck);
            fs.on("afterRename", fsUpdateCheck);

            // Or when a watcher fires
            watcher.on("delete", fsUpdateCheck);
            watcher.on("directory", fsUpdate);

            // Hook into the language
            language.registerLanguageHandler("plugins/c9.ide.test.mocha/mocha_outline_worker");

            // Initial Fetch
            update();
        }

        var wid = 0;
        function populate(node, callback) {
            fs.readFile(node.path, function(err, contents){
                if (err) return callback(err);

                // Invoke in the UI like:
                language.getWorker(function(err, worker) {
                    worker.emit("mocha_outline", { data: { id: ++wid, code: contents } });
                    worker.on("mocha_outline_result", function onResponse(e) {
                        if (e.data.id !== wid) return;
                        worker.off("mocha_outline_result", onResponse);

                        node.items = e.data.result;

                        callback();
                    });
                });
            });
        }

        function getTestNode(node, id, name){
            var count = 0;
            var found = (function recur(items, pname){
                for (var j, i = 0; i < items.length; i++) {
                    j = items[i];

                    if (j.type == "test") count++;
                    if (pname + j.label == name || count == id)
                        return j;

                    if (j.items) {
                        var found = recur(j.items,
                            pname + (j.type == "describe" ? j.label + " " : ""));
                        if (found) return found;
                    }
                }
            })([node], "");

            // TODO optional fallback to using id

            return found;
        }

        function findNextTest(node){
            return (function recur(node, down){
                if (!node.parent) return false;

                var i, items;
                if (down) {
                    items = node.items;
                    i = 0;
                }
                else {
                    i = node.parent.items.indexOf(node) + 1;
                    node = node.parent;
                    items = node.items;
                }

                for (var j; i < items.length; i++) {
                    j = items[i];

                    if (j.type == "test" || j.type == "prepare")
                        return j;

                    if (j.items) {
                        var found = recur(j, true);
                        if (found) return found;
                    }
                }

                return recur(node);
            })(node, node.type != "test");
        }

        function findFileNode(node){
            while (node.type != "file") node = node.parent;
            return node;
        }

        function getFullTestName(node){
            var name = [];

            do {
                name.unshift(node.label)
                node = node.parent;
            } while (node.type != "file");

            return name.join(" ");
        }

        function getAllTestNodes(node){
            var nodes = [];
            (function recur(items){
                for (var j, i = 0; i < items.length; i++) {
                    j = items[i];
                    if (j.type == "test") nodes.push(j);
                    else if (j.items) recur(j.items);
                }
            })([node]);

            return nodes;
        }

        var uniqueId = 0;
        function run(node, progress, options, callback){
            if (typeof options == "function")
                callback = options, options = null;

            var fileNode, path, passed = true;
            var exec = "mocha", args = ["--reporter", "tap"];

            var allTests = getAllTestNodes(node);
            var allTestIndex = 0;

            if (!allTests.length) return callback();

            if (node.type == "file") {
                fileNode = node;
                progress.start(allTests[allTestIndex]);
            }
            else {
                fileNode = findFileNode(node);
                progress.start(node.type == "test" ? node : allTests[allTestIndex]);

                args.push("--grep", util.escapeRegExp(getFullTestName(node))  //"^" +
                    + (node.type == "test" ? "$" : ""));
            }

            // TODO: --debug --debug-brk
            args.push(fileNode.label);

            var withCodeCoverage = options && options.withCodeCoverage;
            var coveragePath = "~/.c9/coverage/run" + ++uniqueId;
            if (withCodeCoverage) {
                exec = "istanbul";
                args.unshift("cover", "--print", "none", "--report",
                    "lcovonly", "--dir", coveragePath, "_mocha", "--");
            }

            proc.pty(exec, {
                args: args,
                cwd: dirname(path)
            }, function(err, pty){
                if (err) return callback(err);

                currentPty = pty;

                var lastResultNode, testCount, bailed;
                var output = "", totalTests = 0;
                pty.on("data", function(c){
                    // Log to the raw viewer
                    progress.log(c);

                    // Number of tests
                    if (c.match(/^(\d+)\.\.(\d+)$/m)) {
                        testCount = parseInt(RegExp.$2, 10);
                    }

                    // Bail
                    else if (c.match(/^Bail out!(.*)$/m)) {
                        bailed = RegExp.$1;
                    }

                    // Update parsed nodes (set, test)
                    else if (c.match(/^(ok|not ok)\s+(\d+)\s+(.*)$/m)) {
                        var pass = RegExp.$1 == "ok" ? 1 : 0;
                        var id = RegExp.$2;
                        var name = RegExp.$3;

                        if (name.match(/"(before all|before each|after all|after each)" hook/, "$1")) {
                            name = name.replace(/"(before all|before each|after all|after each)" hook/, "$1");
                            if (!pass) bailed = true, pass = 2;
                        }

                        // Set file passed state
                        if (!pass) passed = false;

                        // Update Node
                        var resultNode = node.type == "test"
                            ? node
                            : getTestNode(node, id, name);

                        if (resultNode) {
                            lastResultNode = resultNode;

                            // Set Results
                            resultNode.output = output;
                            resultNode.passed = pass;
                            delete resultNode.stackTrace;
                            // resultNode.assertion = {
                            //     line: 0,
                            //     col: 10,
                            //     message: ""
                            // };

                            // Reset output
                            output = "";

                            // Count the tests
                            totalTests++;

                            // Update progress
                            progress.end(resultNode);
                        }
                        else {
                            debugger;
                        }

                        if (bailed) return;

                        var nextTest = allTests[++allTestIndex]; //findNextTest(resultNode);
                        if (nextTest) progress.start(nextTest);
                    }

                    // Output
                    else {
                        // Detect stack trace
                        if (c.match(/^\s+at .*:\d+:\d+\)?$/m)) {
                            var stackTrace = parseTrace(c);
                            if (!lastResultNode.stackTrace && !withCodeCoverage) {
                                lastResultNode.stackTrace = stackTrace;
                            }
                            else if ((stackTrace.message + stackTrace[0].file).indexOf("mocha/lib/runner.js") == -1) {
                                lastResultNode.output += c;
                            }
                            return;
                        }

                        output += c;
                    }
                });
                pty.on("exit", function(c){
                    // totalTests == testCount
                    currentPty = null;

                    if (withCodeCoverage) {
                        fs.readFile(coveragePath + "/lcov.info", function(err, data){
                            if (err) debugger;

                            parseLcov(data, function(err, result){
                                // TODO clear coverage of all sub-nodes
                                // TODO remove coveragePath
                                node.coverage = result;
                                node.coveragePath = coveragePath;

                                done();
                            });
                        });
                    }
                    else done();

                    function done(){
                        // Cleanup for before/after failure
                        allTests.forEach(function(n){
                            if (n.status != "loaded")
                                progress.end(n);
                        });

                        callback(null, node);
                    }
                });
            });

            return stop;
        }

        /**
         * This parses the different stack traces and puts them into one format
         * This borrows heavily from TraceKit (https://github.com/occ/TraceKit)
         * From: https://github.com/errwischt/stacktrace-parser/blob/master/lib/stacktrace-parser.js
         */
        var UNKNOWN_FUNCTION = '<unknown>';
        function parseTrace(stackString){
            var node  = /^\s*at (?:((?:\[object object\])?\S+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i;
            var lines = stackString.split('\n');
            var stack = [];
            var message = [];
            var parts, started;

            for (var i = 0, j = lines.length; i < j; ++i) {
                if ((parts = node.exec(lines[i]))) {
                    stack.push({
                        'file': parts[2],
                        'methodName': parts[1] || UNKNOWN_FUNCTION,
                        'lineNumber': +parts[3],
                        'column': parts[4] ? +parts[4] : null
                    });
                    started = true;
                }
                else if (!started) {
                    message.push(lines[i]);
                }
            }

            stack.message = message.join(" ");

            return stack;
        }

        function coverage(){

        }

        function stop(){
            if (currentPty)
                currentPty.kill();
        }

        /***** Lifecycle *****/

        plugin.on("load", function() {
            load();
        });
        plugin.on("unload", function() {

        });

        /***** Register and define API *****/

        plugin.freezePublicAPI({
            /**
             *
             */
            init: init,

            /**
             *
             */
            populate: populate,

            /**
             *
             */
            run: run,

            /**
             *
             */
            stop: stop,

            /**
             *
             */
            coverage: coverage
        });

        register(null, {
            "test.mocha": plugin
        });
    }
});<commit_msg>Added very basic coverage panel<commit_after>define(function(require, exports, module) {
    main.consumes = [
        "TestRunner", "settings", "preferences", "proc", "util", "fs",
        "watcher", "language"
    ];
    main.provides = ["test.mocha"];
    return main;

    function main(options, imports, register) {
        var TestRunner = imports.TestRunner;
        // var settings = imports.settings;
        // var prefs = imports.preferences;
        var proc = imports.proc;
        var util = imports.util;
        var fs = imports.fs;
        var language = imports.language;
        var watcher = imports.watcher;

        var dirname = require("path").dirname;
        var parseLcov = require("./lcov-parse");

        /***** Initialization *****/

        var plugin = new TestRunner("Ajax.org", main.consumes, {
            caption: "Mocha Javascript Tests"
        });
        // var emit = plugin.getEmitter();

        var SCRIPT = "";
        var MATCH_PATTERN = '^\\s*describe\\(';
        var INCLUDE_PATTERN = "";
        var EXCLUDE_PATTERN = 'node_modules';
        var EXCLUDE_LIST = [];

        // TODO: Implement the pure find files with pattern feature in nak
        // grep -ls -E "^\\s*describe\\(" * -R --exclude-dir node_modules

        var lastList = "";
        var lookup = {};
        var currentPty;

        function load() {
            // Potentially listen to the save event and run specific tests

            // prefs...

        }

        /***** Methods *****/

        function fetch(callback) {
            var cmd, args;

            return callback(null, "plugins/c9.analytics/analytics_test.js\nplugins/c9.api/base_test.js\nplugins/c9.api/collab_test.js\nplugins/c9.api/docker_test.js\nplugins/c9.api/package_test.js\nplugins/c9.api/quota_test.js\nplugins/c9.api/settings_test.js\nplugins/c9.api/sitemap-writer_test.js\nplugins/c9.api/stats_test.js\nplugins/c9.api/vfs_test.js");

            if (SCRIPT) {
                args = SCRIPT.split(" ");
                cmd = args.shift();
            }
            else {
                cmd = "grep";
                args = ["-lsR", "-E", MATCH_PATTERN];

                if (EXCLUDE_PATTERN)
                    args.push("--exclude-dir", EXCLUDE_PATTERN);

                if (INCLUDE_PATTERN)
                    args.push("--include", INCLUDE_PATTERN);
            }

            proc.spawn("bash", {
                args: ["-l", "-c", cmd + " '" + args.join("' '") + "' *"]
            }, function(err, p) {
                if (err) return callback(err);

                var stdout = "", stderr = "";
                p.stdout.on("data", function(c){
                    stdout += c;
                });
                p.stderr.on("data", function(c){
                    stderr += c;
                });
                p.on("exit", function(){
                    // if (!SCRIPT) {
                    //     var filter = new RegExp("^(?:"
                    //         + EXCLUDE_LIST.map(util.escapeRegExp).join("|")
                    //         + ")(?:\n|$)", "gm");

                    //     stdout = stdout.replace(stdout, filter);
                    // }

                    lastList = stdout;

                    callback(null, stdout);
                });

            });
        }

        function init(root, callback) {
            /*
                Set hooks to update list
                - Strategies:
                    - Periodically
                    * Based on fs/watcher events
                    - Based on opening the test panel
                    - Refresh button

                Do initial populate
            */

            var isUpdating;
            function update(){
                if (isUpdating) return fsUpdate(null, 10000);

                isUpdating = true;
                fetch(function(err, list){
                    isUpdating = false;

                    if (err) return callback(err);

                    var items = [];
                    var lastLookup = lookup;
                    lookup = {};

                    list.split("\n").forEach(function(name){
                        if (lastLookup[name]) {
                            items.push(lookup[name] = lastLookup[name]);
                            delete lastLookup[name];
                            return;
                        }

                        var item = {
                            label: name,
                            path: "/" + name,
                            type: "file",
                            status: "pending"
                        };
                        items.push(item);
                        lookup[name] = item;
                    });

                    plugin.root.items = items;

                    callback();
                });
            }

            var timer;
            function fsUpdate(e, time){
                clearTimeout(timer);
                timer = setTimeout(update, time || 1000);
            }

            function fsUpdateCheck(e){
                var reTest = new RegExp("^" + util.escapeRegExp(e.path) + "$", "m");

                if (lastList.match(reTest))
                    fsUpdate();
            }

            fs.on("afterWriteFile", fsUpdate);
            fs.on("afterUnlink", fsUpdateCheck);
            fs.on("afterRmfile", fsUpdateCheck);
            fs.on("afterRmdir", fsUpdateCheck);
            fs.on("afterCopy", fsUpdateCheck);
            fs.on("afterRename", fsUpdateCheck);

            // Or when a watcher fires
            watcher.on("delete", fsUpdateCheck);
            watcher.on("directory", fsUpdate);

            // Hook into the language
            language.registerLanguageHandler("plugins/c9.ide.test.mocha/mocha_outline_worker");

            // Initial Fetch
            update();
        }

        var wid = 0;
        function populate(node, callback) {
            // node.on("change", updateOutline);

            fs.readFile(node.path, function(err, contents){
                if (err) return callback(err);

                language.getWorker(function(err, worker) {
                    worker.emit("mocha_outline", { data: { id: ++wid, code: contents } });
                    worker.on("mocha_outline_result", function onResponse(e) {
                        if (e.data.id !== wid) return;
                        worker.off("mocha_outline_result", onResponse);

                        node.items = e.data.result;

                        callback();
                    });
                });
            });
        }

        // TODO
        // - Start using data objects (emitter based, tree walker to find certain node types)
        // - Implement change event and create updateOutline
        // - Instead of .stackTrace do .annotations = {<linenr>: <message>}
        // session = tab.document.getSession().session;
        //     session && session.on("changeMode", onChange);
        //     session && session.on("change", onChange);
        // function updateOutline(now) {
        //     if (!isActive)
        //         return;
        //     dirty = true;
        //     if (now && tabs.focussedTab && !scheduled) {
        //         if (!worker) {
        //             return language.getWorker(function(err, _worker) {
        //                 worker = _worker;
        //                 updateOutline(true);
        //             });
        //         }

        //         // have to use timeout since worker uses timeout as well
        //         setTimeout(function () {
        //             dirty = false;
        //             worker.emit("outline", { data: {
        //                 ignoreFilter: false,
        //                 path: tabs.focussedTab && tabs.focussedTab.path
        //             }});
        //         });

        //         // Don't schedule new job until data received or timeout
        //         scheduled = true;
        //         clearTimeout(scheduleWatcher);
        //         scheduleWatcher = setTimeout(function() {
        //             scheduled = false;
        //         }, 10000);
        //     }
        // }

        function getTestNode(node, id, name){
            var count = 0;
            var found = (function recur(items, pname){
                for (var j, i = 0; i < items.length; i++) {
                    j = items[i];

                    if (j.type == "test") count++;
                    if (pname + j.label == name || count == id)
                        return j;

                    if (j.items) {
                        var found = recur(j.items,
                            pname + (j.type == "describe" ? j.label + " " : ""));
                        if (found) return found;
                    }
                }
            })([node], "");

            // TODO optional fallback to using id

            return found;
        }

        function findNextTest(node){
            return (function recur(node, down){
                if (!node.parent) return false;

                var i, items;
                if (down) {
                    items = node.items;
                    i = 0;
                }
                else {
                    i = node.parent.items.indexOf(node) + 1;
                    node = node.parent;
                    items = node.items;
                }

                for (var j; i < items.length; i++) {
                    j = items[i];

                    if (j.type == "test" || j.type == "prepare")
                        return j;

                    if (j.items) {
                        var found = recur(j, true);
                        if (found) return found;
                    }
                }

                return recur(node);
            })(node, node.type != "test");
        }

        function findFileNode(node){
            while (node.type != "file") node = node.parent;
            return node;
        }

        function getFullTestName(node){
            var name = [];

            do {
                name.unshift(node.label)
                node = node.parent;
            } while (node.type != "file");

            return name.join(" ");
        }

        function getAllTestNodes(node){
            var nodes = [];
            (function recur(items){
                for (var j, i = 0; i < items.length; i++) {
                    j = items[i];
                    if (j.type == "test") nodes.push(j);
                    else if (j.items) recur(j.items);
                }
            })([node]);

            return nodes;
        }

        var uniqueId = 0;
        function run(node, progress, options, callback){
            if (typeof options == "function")
                callback = options, options = null;

            var fileNode, path, passed = true;
            var exec = "mocha", args = ["--reporter", "tap"];

            var allTests = getAllTestNodes(node);
            var allTestIndex = 0;

            if (!allTests.length) return callback();

            if (node.type == "file") {
                fileNode = node;
                progress.start(allTests[allTestIndex]);
            }
            else {
                fileNode = findFileNode(node);
                progress.start(node.type == "test" ? node : allTests[allTestIndex]);

                args.push("--grep", util.escapeRegExp(getFullTestName(node))  //"^" +
                    + (node.type == "test" ? "$" : ""));
            }

            // TODO: --debug --debug-brk
            args.push(fileNode.label);

            var withCodeCoverage = options && options.withCodeCoverage;
            var coveragePath = "~/.c9/coverage/run" + ++uniqueId;
            if (withCodeCoverage) {
                exec = "istanbul";
                args.unshift("cover", "--print", "none", "--report",
                    "lcovonly", "--dir", coveragePath, "_mocha", "--");
            }

            proc.pty(exec, {
                args: args,
                cwd: dirname(path)
            }, function(err, pty){
                if (err) return callback(err);

                currentPty = pty;

                var lastResultNode, testCount, bailed;
                var output = "", totalTests = 0;
                pty.on("data", function(c){
                    // Log to the raw viewer
                    progress.log(fileNode, c);

                    // Number of tests
                    if (c.match(/^(\d+)\.\.(\d+)$/m)) {
                        testCount = parseInt(RegExp.$2, 10);
                    }

                    // Bail
                    else if (c.match(/^Bail out!(.*)$/m)) {
                        bailed = RegExp.$1;
                    }

                    // Update parsed nodes (set, test)
                    else if (c.match(/^(ok|not ok)\s+(\d+)\s+(.*)$/m)) {
                        var pass = RegExp.$1 == "ok" ? 1 : 0;
                        var id = RegExp.$2;
                        var name = RegExp.$3;

                        if (name.match(/"(before all|before each|after all|after each)" hook/, "$1")) {
                            name = name.replace(/"(before all|before each|after all|after each)" hook/, "$1");
                            if (!pass) bailed = true, pass = 2;
                        }

                        // Set file passed state
                        if (!pass) passed = false;

                        // Update Node
                        var resultNode = node.type == "test"
                            ? node
                            : getTestNode(node, id, name);

                        if (resultNode) {
                            lastResultNode = resultNode;

                            // Set Results
                            resultNode.output = output;
                            resultNode.passed = pass;
                            delete resultNode.stackTrace;
                            // resultNode.assertion = {
                            //     line: 0,
                            //     col: 10,
                            //     message: ""
                            // };

                            // Reset output
                            output = "";

                            // Count the tests
                            totalTests++;

                            // Update progress
                            progress.end(resultNode);
                        }
                        else {
                            debugger;
                        }

                        if (bailed) return;

                        var nextTest = allTests[++allTestIndex]; //findNextTest(resultNode);
                        if (nextTest) progress.start(nextTest);
                    }

                    // Output
                    else {
                        // Detect stack trace
                        if (c.match(/^\s+at .*:\d+:\d+\)?$/m)) {
                            var stackTrace = parseTrace(c);
                            if (!lastResultNode.stackTrace && !withCodeCoverage) {
                                lastResultNode.stackTrace = stackTrace;
                            }
                            else if ((stackTrace.message + stackTrace[0].file).indexOf("mocha/lib/runner.js") == -1) {
                                lastResultNode.output += c;
                            }
                            return;
                        }

                        output += c;
                    }
                });
                pty.on("exit", function(c){
                    // totalTests == testCount
                    currentPty = null;

                    if (withCodeCoverage) {
                        fs.readFile(coveragePath + "/lcov.info", function(err, data){
                            if (err) debugger;

                            parseLcov(data, function(err, result){
                                // TODO clear coverage of all sub-nodes
                                // TODO remove coveragePath
                                node.coverage = result;
                                node.coveragePath = coveragePath;

                                done();
                            });
                        });
                    }
                    else done();

                    function done(){
                        // Cleanup for before/after failure
                        allTests.forEach(function(n){
                            if (n.status != "loaded")
                                progress.end(n);
                        });

                        callback(null, node);
                    }
                });
            });

            return stop;
        }

        /**
         * This parses the different stack traces and puts them into one format
         * This borrows heavily from TraceKit (https://github.com/occ/TraceKit)
         * From: https://github.com/errwischt/stacktrace-parser/blob/master/lib/stacktrace-parser.js
         */
        var UNKNOWN_FUNCTION = '<unknown>';
        function parseTrace(stackString){
            var node  = /^\s*at (?:((?:\[object object\])?\S+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i;
            var lines = stackString.split('\n');
            var stack = [];
            var message = [];
            var parts, started;

            for (var i = 0, j = lines.length; i < j; ++i) {
                if ((parts = node.exec(lines[i]))) {
                    stack.push({
                        'file': parts[2],
                        'methodName': parts[1] || UNKNOWN_FUNCTION,
                        'lineNumber': +parts[3],
                        'column': parts[4] ? +parts[4] : null
                    });
                    started = true;
                }
                else if (!started) {
                    message.push(lines[i]);
                }
            }

            stack.message = message.join(" ");

            return stack;
        }

        function coverage(){

        }

        function stop(){
            if (currentPty)
                currentPty.kill();
        }

        /***** Lifecycle *****/

        plugin.on("load", function() {
            load();
        });
        plugin.on("unload", function() {

        });

        /***** Register and define API *****/

        plugin.freezePublicAPI({
            /**
             *
             */
            init: init,

            /**
             *
             */
            populate: populate,

            /**
             *
             */
            run: run,

            /**
             *
             */
            stop: stop,

            /**
             *
             */
            coverage: coverage
        });

        register(null, {
            "test.mocha": plugin
        });
    }
});<|endoftext|>


<commit_before>
/*!
 * Skeleton.js - Model
 * Copyright(c) 2012 Rubén Norte <rubennorte@gmail.com>
 * MIT Licensed
 */

define([
  'backbone',
  'underscore'
], function(Backbone, _){

  'use strict';

  /**
   * Skeleton model definition
   */
  var Model = Backbone.Model.extend({

    /**
     * Backbone fetch function, redefined to provide support for reload option
     * and loading/loaded flags and events
     */
    fetch: function(options){
      options = options ? _.clone(options) : {};

      // If not reload and model is not empty, sync is not necessary
      if (options.reload === undefined) options.reload = true;
      if (!options.reload && this.isLoaded()){
        options.success && options.success(this);
        // TODO return something that implements the promise interface
        return;
      }

      // Increment loading count (o set as 1)
      if (!this._loading)
        this._loading = 1;
      else
        this._loading++;

      // Set new success and error callbacks
      var self = this,
          success = options.success,
          error = options.error;
      options.success = function(){
        self._loading--;
        self._loaded = true;
        success && success();
      };
      options.error = function(){
        self._loading--;
        error && error();
      };

      // Trigger syncing event
      this.trigger('syncing', this, options);

      // return super.fetch(options);
      return Backbone.Model.prototype.fetch.call(this, options);
    },

    /**
     * Returns true if the model is being loaded from the server
     */
    isLoading: function(){
      return !!this._loading;
    },

    /**
     * Returns true if the model has ever been loaded from the server
     */
    isLoaded: function(){
      return !!this._loaded;
    },

    /**
     * Backbone toJSON function, redefined to provide support for
     * persistAttributes and discardAttributes options.
     */
    toJSON: function(key, value, options){
      var json = Backbone.Model.prototype.toJSON.apply(this, arguments);

      if (this.persistAttributes || this.discardAttributes){

        // If persistAttributes is defined, keep only selected attributes
        var persist = selectKeys(json, this.persistAttributes);
        if (!persist)
          persist = _(json).keys();

        // If discardAttributes is defined, remove selected attributes
        var discard = selectKeys(json, this.discardAttributes);
        if (discard){
          persist = _(persist).difference(discard);
        }

        // Pick the selected attributes
        json = _(json).pick(persist);
      }

      return json;
    }

  });

  /**
   * Returns the selected keys of the specified object.
   * If selected is an array, the selected keys are those.
   * If selected is an object, the selected keys are which has non-falsy values.
   * If selected is a function, the selected keys are which makes the function
   * return a non-falsy value.
   */
  function selectKeys(object, selected){
    if (_(selected).isArray()){
      return selected;
    } else if (_(selected).isFunction()){
      return _(object).chain().map(function(value, key){
        return selected(key, value) ? key : null;
      }).compact().value();
    } else if (_(selected).isObject()){
      return _(object).chain().map(function(value, key){
        return value ? key : null;
      }).compact().value();
    }
  }

  return Model;

});<commit_msg>Defined all used model properties in class definition object.<commit_after>
/*!
 * Skeleton.js - Model
 * Copyright(c) 2012 Rubén Norte <rubennorte@gmail.com>
 * MIT Licensed
 */

define([
  'backbone',
  'underscore'
], function(Backbone, _){

  'use strict';

  /**
   * Skeleton model definition
   */
  var Model = Backbone.Model.extend({

    _loading: false,
    _loaded: 0,
    _data: {},

    /**
     * Backbone fetch function, redefined to provide support for reload option
     * and loading/loaded flags and events
     */
    fetch: function(options){
      options = options ? _.clone(options) : {};

      // If not reload and model is not empty, sync is not necessary
      if (options.reload === undefined) options.reload = true;
      if (!options.reload && this.isLoaded()){
        options.success && options.success(this);
        // TODO return something that implements the promise interface
        return;
      }

      // Increment loading count (o set as 1)
      if (!this._loading)
        this._loading = 1;
      else
        this._loading++;

      // Set new success and error callbacks
      var self = this,
          success = options.success,
          error = options.error;
      options.success = function(){
        self._loading--;
        self._loaded = true;
        success && success();
      };
      options.error = function(){
        self._loading--;
        error && error();
      };

      // Trigger syncing event
      this.trigger('syncing', this, options);

      // return super.fetch(options);
      return Backbone.Model.prototype.fetch.call(this, options);
    },

    /**
     * Returns true if the model is being loaded from the server
     */
    isLoading: function(){
      return !!this._loading;
    },

    /**
     * Returns true if the model has ever been loaded from the server
     */
    isLoaded: function(){
      return !!this._loaded;
    },

    /**
     * Backbone toJSON function, redefined to provide support for
     * persistAttributes and discardAttributes options.
     */
    toJSON: function(key, value, options){
      var json = Backbone.Model.prototype.toJSON.apply(this, arguments);

      if (this.persistAttributes || this.discardAttributes){

        // If persistAttributes is defined, keep only selected attributes
        var persist = selectKeys(json, this.persistAttributes);
        if (!persist)
          persist = _(json).keys();

        // If discardAttributes is defined, remove selected attributes
        var discard = selectKeys(json, this.discardAttributes);
        if (discard){
          persist = _(persist).difference(discard);
        }

        // Pick the selected attributes
        json = _(json).pick(persist);
      }

      return json;
    }

  });

  /**
   * Returns the selected keys of the specified object.
   * If selected is an array, the selected keys are those.
   * If selected is an object, the selected keys are which has non-falsy values.
   * If selected is a function, the selected keys are which makes the function
   * return a non-falsy value.
   */
  function selectKeys(object, selected){
    if (_(selected).isArray()){
      return selected;
    } else if (_(selected).isFunction()){
      return _(object).chain().map(function(value, key){
        return selected(key, value) ? key : null;
      }).compact().value();
    } else if (_(selected).isObject()){
      return _(object).chain().map(function(value, key){
        return value ? key : null;
      }).compact().value();
    }
  }

  return Model;

});<|endoftext|>


<commit_before>var bcv_parser = require("./en_bcv_parser.js").bcv_parser;
var bcv = new bcv_parser;

var db;
var Server = require('mongodb').Server;
var MongoClient = require('mongodb').MongoClient;

var mongoClient = new MongoClient(new Server('localhost', 27017));
mongoClient.open(function(err, mongoClient) {
    db = mongoClient.db("bible-api");
    db.collection('bible', {strict:true}, function(err, collection) {
        if (err) {
            console.log("Error!");
        }
    });
});

var mongoQuery = [];

var fetchBcv = function(passage, type) {
  var pTranslation = 'RST';

  var query = {
    'tran':pTranslation,
    'bookRef':passage.start.b
  }

  if (type === 'bc') {
    query.chapter = passage.start.c;
  }
  else if (type === 'bcv') {
    query.chapter = passage.start.c;
    query.verse = passage.start.v;
  }

  // display passage for each translation
  if (passage.translations != null) {
    if (type === 'bcv') {
      for (var i=0; i<passage.translations.length; i++) {
        query.tran = passage.translations[i].osis;
        mongoQuery.push(query);
      }
    }
    else {
      query.tran = passage.translations[0].osis;
      mongoQuery.push(query);
    }
  } // one translation only
  else {
    mongoQuery.push(query);
  }
};

var fetchRange = function(passage) {
  var translationInfo = bcv.translation_info("");

  var pTranslation = 'RST';
  if (passage.translations != null) {
    pTranslation = passage.translations[0].osis;
  }

  // passage of the same book
  if (passage.start.b === passage.end.b) {
    // passage of one chapter
    if (passage.start.c === passage.end.c) {
      mongoQuery.push({
        'tran':pTranslation,
        'bookRef':passage.start.b,
        'chapter':passage.start.c,
        'verse':{$gte:passage.start.v, $lte:passage.end.v}
      });
    }
    else { // passage of many chapters
      var chapters = [];
      for (var ch=passage.start.c; ch<=passage.end.c; ch++) {
        var startVerse = 1;
        var endVerse = translationInfo.chapters[passage.start.b][ch-1];

        if (ch === passage.start.c) {
          startVerse = passage.start.v;
        }
        if (ch === passage.end.c) {
          endVerse = passage.end.v;
        }

        chapters.push({
          'tran':pTranslation,
          'bookRef':passage.start.b,
          'chapter':ch,
          'verse':{$gte:startVerse, $lte:endVerse}
        });
      }

      mongoQuery.push({
        $or: chapters
      });
    }
  } // passage of many books
  else {
    var chapters = [];
    var startBook = translationInfo.order[passage.start.b];
    var endBook = translationInfo.order[passage.end.b];

    for (var b=startBook; b<=endBook; b++) {
      var bookRef = translationInfo.books[b-1];

      // passage includes the whole book in the middle
      if (b != startBook && b != endBook) {
        chapters.push({
          'tran':pTranslation,
          'bookRef':bookRef
        });
      }
      else { // other half-books parts
        var startChapter = 1;
        var endChapter = translationInfo.chapters[bookRef].length;

        if (b === startBook) {
          startChapter = passage.start.c;
        }
        if (b === endBook) {
          endChapter = passage.end.c;
        }

        for (var ch=startChapter; ch<=endChapter; ch++) {
          var startVerse = 1;
          var endVerse = translationInfo.chapters[bookRef][ch-1];

          // first chapter, first verse in range
          if (b === startBook && ch === startChapter) {
            startVerse = passage.start.v;
            chapters.push({
              'tran':pTranslation,
              'bookRef':bookRef,
              'chapter':startChapter,
              'verse':{$gte:startVerse, $lte:endVerse}
            });
          } // last chapter, last verse in range
          else if (b === endBook && ch === endChapter) {
            endVerse = passage.end.v;
            chapters.push({
              'tran':pTranslation,
              'bookRef':bookRef,
              'chapter':ch,
              'verse':{$gte:startVerse, $lte:endVerse}
            });
          }
          else { // other whole chapters in range
            chapters.push({
              'tran':pTranslation,
              'bookRef':bookRef,
              'chapter':ch
            });
          }
        }
      }
    }

    mongoQuery.push({
      $or: chapters
    });
  }
};

exports.parsePassage = function(req, res) {
  mongoQuery = [];
  var entities = bcv.parse(req.params.passage).entities;

  for (var i=0; i<entities.length; i++) {
    var entity = entities[i];
    // passage contains whole book, whole chapter or verse also
    if (entity.type === 'b' || entity.type === 'bc' || entity.type === 'bcv') {
      // bcv has only one passage
      fetchBcv(entity.passages[0], entity.type);
    } // range of verses
    else if (entity.type === 'range') {
      // range has only one passage
      fetchRange(entity.passages[0]);
    } // sequence of passages
    else if(entity.type === 'sequence') {
      for (var j=0; j<entity.passages.length; j++) {
        var passage = entity.passages[j];
        // passage sequence includes bcv
        if (passage.type === 'bcv' || passage.type === 'integer') {
          fetchBcv(passage, 'bcv');
        } // passage sequence includes range
        else if(passage.type === 'range') {
          fetchRange(passage);
        }
      }
    }
  }

  db.collection('bible', function(err, collection) {
    collection.find({
      $or: mongoQuery
    }).toArray(function(err, items) {
      res.jsonp(items);
    });
  });
};
<commit_msg>query filtering added<commit_after>var bcv_parser = require("./en_bcv_parser.js").bcv_parser;
var bcv = new bcv_parser;

var db;
var Server = require('mongodb').Server;
var MongoClient = require('mongodb').MongoClient;

var mongoClient = new MongoClient(new Server('localhost', 27017));
mongoClient.open(function(err, mongoClient) {
    db = mongoClient.db("bible-api");
    db.collection('bible', {strict:true}, function(err, collection) {
        if (err) {
            console.log("Error!");
        }
    });
});

var mongoQuery = [];

var fetchBcv = function(passage, type) {
  var pTranslation = 'RST';

  var query = {
    'tran':pTranslation,
    'bookRef':passage.start.b
  }

  if (type === 'bc') {
    query.chapter = passage.start.c;
  }
  else if (type === 'bcv') {
    query.chapter = passage.start.c;
    query.verse = passage.start.v;
  }

  // display passage for each translation
  if (passage.translations != null) {
    if (type === 'bcv') {
      for (var i=0; i<passage.translations.length; i++) {
        query.tran = passage.translations[i].osis;
        mongoQuery.push(query);
      }
    }
    else {
      query.tran = passage.translations[0].osis;
      mongoQuery.push(query);
    }
  } // one translation only
  else {
    mongoQuery.push(query);
  }
};

var fetchRange = function(passage) {
  var translationInfo = bcv.translation_info("");

  var pTranslation = 'RST';
  if (passage.translations != null) {
    pTranslation = passage.translations[0].osis;
  }

  // passage of the same book
  if (passage.start.b === passage.end.b) {
    // passage of one chapter
    if (passage.start.c === passage.end.c) {
      mongoQuery.push({
        'tran':pTranslation,
        'bookRef':passage.start.b,
        'chapter':passage.start.c,
        'verse':{$gte:passage.start.v, $lte:passage.end.v}
      });
    }
    else { // passage of many chapters
      var chapters = [];
      for (var ch=passage.start.c; ch<=passage.end.c; ch++) {
        var startVerse = 1;
        var endVerse = translationInfo.chapters[passage.start.b][ch-1];

        if (ch === passage.start.c) {
          startVerse = passage.start.v;
        }
        if (ch === passage.end.c) {
          endVerse = passage.end.v;
        }

        chapters.push({
          'tran':pTranslation,
          'bookRef':passage.start.b,
          'chapter':ch,
          'verse':{$gte:startVerse, $lte:endVerse}
        });
      }

      mongoQuery.push({
        $or: chapters
      });
    }
  } // passage of many books
  else {
    var chapters = [];
    var startBook = translationInfo.order[passage.start.b];
    var endBook = translationInfo.order[passage.end.b];

    for (var b=startBook; b<=endBook; b++) {
      var bookRef = translationInfo.books[b-1];

      // passage includes the whole book in the middle
      if (b != startBook && b != endBook) {
        chapters.push({
          'tran':pTranslation,
          'bookRef':bookRef
        });
      }
      else { // other half-books parts
        var startChapter = 1;
        var endChapter = translationInfo.chapters[bookRef].length;

        if (b === startBook) {
          startChapter = passage.start.c;
        }
        if (b === endBook) {
          endChapter = passage.end.c;
        }

        for (var ch=startChapter; ch<=endChapter; ch++) {
          var startVerse = 1;
          var endVerse = translationInfo.chapters[bookRef][ch-1];

          // first chapter, first verse in range
          if (b === startBook && ch === startChapter) {
            startVerse = passage.start.v;
            chapters.push({
              'tran':pTranslation,
              'bookRef':bookRef,
              'chapter':startChapter,
              'verse':{$gte:startVerse, $lte:endVerse}
            });
          } // last chapter, last verse in range
          else if (b === endBook && ch === endChapter) {
            endVerse = passage.end.v;
            chapters.push({
              'tran':pTranslation,
              'bookRef':bookRef,
              'chapter':ch,
              'verse':{$gte:startVerse, $lte:endVerse}
            });
          }
          else { // other whole chapters in range
            chapters.push({
              'tran':pTranslation,
              'bookRef':bookRef,
              'chapter':ch
            });
          }
        }
      }
    }

    mongoQuery.push({
      $or: chapters
    });
  }
};

exports.parsePassage = function(req, res) {
  mongoQuery = [];
  var entities = bcv.parse(req.params.passage).entities;

  for (var i=0; i<entities.length; i++) {
    var entity = entities[i];
    // passage contains whole book, whole chapter or verse also
    if (entity.type === 'b' || entity.type === 'bc' || entity.type === 'bcv') {
      // bcv has only one passage
      fetchBcv(entity.passages[0], entity.type);
    } // range of verses
    else if (entity.type === 'range') {
      // range has only one passage
      fetchRange(entity.passages[0]);
    } // sequence of passages
    else if(entity.type === 'sequence') {
      for (var j=0; j<entity.passages.length; j++) {
        var passage = entity.passages[j];
        // passage sequence includes bcv
        if (passage.type === 'bcv' || passage.type === 'integer') {
          fetchBcv(passage, 'bcv');
        } // passage sequence includes range
        else if(passage.type === 'range') {
          fetchRange(passage);
        }
      }
    }
  }

  db.collection('bible', function(err, collection) {
    collection.find({
      $or: mongoQuery
    }, {
      _id: 0
    }).toArray(function(err, items) {
      res.jsonp(items);
    });
  });
};
<|endoftext|>


<commit_before>/**********************************************************************
*
*
*
**********************************************************************/

//var DEBUG = DEBUG != null ? DEBUG : true

/*********************************************************************/

// data store...
// Format:
// 	{
// 		<path>: {
// 			text: <text>,
//
// 			links: [
// 				<offset>: <link>,
// 			],
// 		}
// 	}
var data = {
	'/': {
		text: 'base page...'
	},
	'dir/page': {
		text: 'some text...'
	},
}

var path2lst = path =>
	(path instanceof Array ?
	 		path
			: path.split(/[\\\/]+/g))
		.map(p => p.trim())
		.filter(p =>
			p != '' && p != '.')

var normalizePath = path =>
	path2lst(path).join('/')

var Wiki = {
	__wiki_data: data,

	// current location...
	get location(){
		return this.__location || '/' },
	set location(value){
		this.__location = normalizePath(value) },

	// page path...
	//
	// Format:
	// 	<dir>/<title>
	//
	// NOTE: changing this will move the page to the new path and change
	// 		.location acordingly...
	// NOTE: same applies to path parts below...
	get path(){
		return this.location },
	set path(value){
		var l = this.location
		value = normalizePath(value)

		this.__wiki_data[value] = this.__wiki_data[l] || {}
		this.location = value
		delete this.__wiki_data[l]
	},

	// path parts: directory...
	//
	// NOTE: see .path for details...
	get dir(){
		return path2lst(this.location).slice(0, -1).join('/') },
	set dir(value){
		this.path = value +'/'+ this.title },

	// path parts: title...
	//
	// NOTE: see .path for details...
	get title(){
		return path2lst(this.location).pop() },
	set title(value){
		this.path = this.dir +'/'+ value },

	// page content...
	get text(){
		return (this.__wiki_data[this.location] || {}).text || ''
	},
	set text(value){
		var l = this.location
		this.__wiki_data[l] = this.__wiki_data[l] || {}
		this.__wiki_data[l].text = value
	},

	// XXX
	get links(){
	},
	set links(value){
	},

	// XXX
	get list(){
	},
	set list(value){
	},

	// serialization...
	get json(){
		return {
			path: this.path,
			text: this.text,
		}
	},
	set json(value){
		if(value.title){
			this.title = value.title
		}
		if(value.text){
			this.text = value.text
		}
	},
}

/**********************************************************************
* vim:set ts=4 sw=4 :                                                */
<commit_msg>added basic aquisition mechanics + started templates...<commit_after>/**********************************************************************
*
*
*
**********************************************************************/

//var DEBUG = DEBUG != null ? DEBUG : true

/*********************************************************************/

// data store...
// Format:
// 	{
// 		<path>: {
// 			text: <text>,
//
// 			links: [
// 				<offset>: <link>,
// 			],
// 		}
// 	}
var data = {
	'TemplatePages/DefaultPage': {
		text: 'This page is empty.

WikiHome',
	},
}

var path2lst = path =>
	(path instanceof Array ?
	 		path
			: path.split(/[\\\/]+/g))
		.map(p => p.trim())
		.filter(p =>
			p != '' && p != '.')

var normalizePath = path =>
	path2lst(path).join('/')

var Wiki = {
	__wiki_data: data,

	__home_page__: 'WikiHome',
	__default_page__: 'DefaultPage',
	__templates__: 'TemplatePages',

	// current location...
	get location(){
		return this.__location || this.__home_page__ },
	set location(value){
		this.__location = normalizePath(value) },

	// page path...
	//
	// Format:
	// 	<dir>/<title>
	//
	// NOTE: changing this will move the page to the new path and change
	// 		.location acordingly...
	// NOTE: same applies to path parts below...
	get path(){
		return this.location },
	set path(value){
		var l = this.location
		value = normalizePath(value)

		this.__wiki_data[value] = this.__wiki_data[l] || {}
		this.location = value
		delete this.__wiki_data[l]
	},

	// path parts: directory...
	//
	// NOTE: see .path for details...
	get dir(){
		return path2lst(this.location).slice(0, -1).join('/') },
	set dir(value){
		this.path = value +'/'+ this.title },

	// path parts: title...
	//
	// NOTE: see .path for details...
	get title(){
		return path2lst(this.location).pop() },
	set title(value){
		this.path = this.dir +'/'+ value },

	// page content...
	//
	// NOTE: if this page has not text, this will get the DefaultPage...
	// XXX should this get the DefaultPage or the EmptyPage???
	get text(){
		return (this.__wiki_data[this.location] || {}).text
			|| (this.acquire(this.__default_page__) || {}).text
			|| ''
	},
	set text(value){
		var l = this.location
		this.__wiki_data[l] = this.__wiki_data[l] || {}
		this.__wiki_data[l].text = value
	},

	// XXX
	get links(){
	},
	set links(value){
	},

	// XXX
	get list(){
	},
	set list(value){
	},

	exists: function(path){
		return normalizePath(path) in this.__wiki_data },
	// get title from dir and then go up the tree...
	acquire: function(title){
		title = title || this.__default_page__
		var templates = this.__templates__
		var data = this.__wiki_data
		var that = this

		var path = path2lst(this.dir)

		var _res = function(p){
			return {
				dir: normalizePath(p.slice(0, -1)),
				title: title,
				text: that.__wiki_data[normalizePath(p)].text
			}
		}

		while(true){
			// get title from path...
			var p = path.concat([title])
			if(this.exists(p)){
				return _res(p)
			}

			// get title from templates in path...
			var p = path.concat([templates, title])
			if(this.exists(p)){
				return _res(p)
			}

			if(path.length == 0){
				return
			}

			path.pop()
		}
	},

	// serialization...
	json: function(path){
		return path == null ? JSON.parse(JSON.stringify(this.__wiki_data))
			: path == '.' ? {
					path: this.location,
					text: this.text,
				}
			: {
				path: path,
				text: (this.__wiki_data[path] || {}).text,
			}
	},
	// XXX should we inherit from the default???
	load: function(json){
		this.__wiki_data = json
	},
}

/**********************************************************************
* vim:set ts=4 sw=4 :                                                */
<|endoftext|>