<commit_before>/**
* (C) Copyright IBM Corp. 2016. All Rights Reserved.
*
* 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.
*/

require('./styles.css');

var events = require('../../events');
var state = require('../../state');
var profile = require('../../profile');
var subscribe = events.subscribe;
var publish = events.publish;
var utils = require('../../utils');
var validation = require('./validation');
var activeClassName = 'IBMChat-accent-colors';
var ns = 'IBMChat-creditcard';
var widgets = [];
var templates = {
	base: require('./templates/base.html')
};

var creditCardLayout = {
	init: function() {
		subscribe('layout:cc-validator', function(data) {
			var widget = new CreditCard(data);
			widgets[data.uuid] = widget;
		});
	}
};

function CreditCard(data) {
	this.init(data);
}

CreditCard.prototype.init = function(data) {
	this.data = data.message.layout.data || {};
	this.data.acceptedCards = this.data.types;
	this.uuid = data.uuid;
	this.parentElement = data.element;
	this.layoutElement = data.layoutElement;
	this.msgElement = data.msgElement;
	this.drawForm();
	this.subscribeSend = subscribe('send', this.removeAllEventListeners.bind(this));
	publish('disable-input');
};

CreditCard.prototype.drawForm = function() {
	var text = templates.base;
	this.el = document.createElement('div');
	text = utils.compile(templates.base, {
		ns: ns
	});
	this.el.innerHTML = text;
	this.layoutElement.appendChild(this.el);
	this.cancelButton = this.el.querySelector('.' + ns + '-cancel');
	this.continueButton = this.el.querySelector('.' + ns + '-continue');
	this.formElements = {};
	this.fields = this.el.querySelectorAll('input');
	for (var i = 0; i < this.fields.length; i++) {
		var field = this.fields[i];
		var name = field.getAttribute('name');
		this.formElements[name] = field;
	}
	this.formElements['cc_full_name'].focus();
	this.addListeners();
};

CreditCard.prototype.addListeners = function() {
	this.cancelButton.addEventListener('click', this.handleCancel.bind(this));
	this.continueButton.addEventListener('click', this.handleContinue.bind(this));
};

CreditCard.prototype.addError = function(name, msg) {
	var errorElement = this.el.querySelector('[data-validation-for="' + name + '"]');
	errorElement.style.display = 'block';
	errorElement.dataset.valid = false;
	errorElement.textContent = msg;
};

CreditCard.prototype.removeError = function(name) {
	var errorElement = this.el.querySelector('[data-validation-for="' + name + '"]');
	errorElement.style.display = 'none';
	errorElement.dataset.valid = true;
	errorElement.textContent = '';
};

CreditCard.prototype.validate = function() {
	var valid = true;
	this.formData = {};
	for (var i = 0; i < this.fields.length; i++) {
		var field = this.fields[i];
		var name = field.getAttribute('name');
		this.formData[name] = field.value;
	}

	if (this.formData.cc_full_name.length === 0) {
		this.addError('cc_full_name', 'This field is required.');
		if (valid) this.formElements['cc_full_name'].focus();
		valid = false;
	} else {
		this.removeError('cc_full_name');
	}

	var cc = validation.validateCard(this.data.acceptedCards, this.formData.cc_number);
	if (!cc.valid) {
		this.addError('cc_number', cc.message);
		if (valid) this.formElements['cc_number'].focus();
		valid = false;
	} else {
		this.removeError('cc_number');
	}

	var exp = validation.validateExp(this.formData.cc_exp_date_month, this.formData.cc_exp_date_year);
	if (!exp.valid) {
		this.addError('cc_exp_date', exp.message);
		if (valid) this.formElements['cc_exp_date_month'].focus();
		valid = false;
	} else {
		this.removeError('cc_exp_date');
	}

	var cvv = validation.validateCVV(this.formData.cc_code);
	if (!cvv.valid) {
		this.addError('cc_code', cvv.message);
		if (valid) this.formElements['cc_code'].focus();
		valid = false;
	} else {
		this.removeError('cc_code');
	}
	return valid;
};

CreditCard.prototype.handleContinue = function() {
	if (this.validate()) {
		var fd = this.formData;
		fd.cc_exp_date = fd.cc_exp_date_month + '/' + fd.cc_exp_date_year;
		Object.keys(fd).map(function(key) {
			profile.set(key, fd[key]);
		});
		publish('enable-input');
		publish('send', {
			silent: true,
			text: 'success'
		});
	}
};

CreditCard.prototype.handleCancel = function() {
	this.cancelButton.classList.add(activeClassName);
	publish('enable-input');
	publish('send', {
		silent: true,
		text: 'cancel'
	});
};

CreditCard.prototype.removeAllEventListeners = function() {
	this.cancelButton.removeEventListener('click', this.handleCancel.bind(this));
	this.cancelButton.setAttribute('disabled', true);
	this.continueButton.removeEventListener('click', this.handleContinue.bind(this));
	this.continueButton.setAttribute('disabled', true);
	for (var j = 0; j < this.fields.length; j++)
		this.fields[j].setAttribute('disabled', true);

	this.subscribeSend.remove();
};

module.exports = creditCardLayout;
<commit_msg>add last four digits of cc num to profile<commit_after>/**
* (C) Copyright IBM Corp. 2016. All Rights Reserved.
*
* 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.
*/

require('./styles.css');

var events = require('../../events');
var state = require('../../state');
var profile = require('../../profile');
var subscribe = events.subscribe;
var publish = events.publish;
var utils = require('../../utils');
var validation = require('./validation');
var activeClassName = 'IBMChat-accent-colors';
var ns = 'IBMChat-creditcard';
var widgets = [];
var templates = {
	base: require('./templates/base.html')
};

var creditCardLayout = {
	init: function() {
		subscribe('layout:cc-validator', function(data) {
			var widget = new CreditCard(data);
			widgets[data.uuid] = widget;
		});
	}
};

function CreditCard(data) {
	this.init(data);
}

CreditCard.prototype.init = function(data) {
	this.data = data.message.layout.data || {};
	this.data.acceptedCards = this.data.types;
	this.uuid = data.uuid;
	this.parentElement = data.element;
	this.layoutElement = data.layoutElement;
	this.msgElement = data.msgElement;
	this.drawForm();
	this.subscribeSend = subscribe('send', this.removeAllEventListeners.bind(this));
	publish('disable-input');
};

CreditCard.prototype.drawForm = function() {
	var text = templates.base;
	this.el = document.createElement('div');
	text = utils.compile(templates.base, {
		ns: ns
	});
	this.el.innerHTML = text;
	this.layoutElement.appendChild(this.el);
	this.cancelButton = this.el.querySelector('.' + ns + '-cancel');
	this.continueButton = this.el.querySelector('.' + ns + '-continue');
	this.formElements = {};
	this.fields = this.el.querySelectorAll('input');
	for (var i = 0; i < this.fields.length; i++) {
		var field = this.fields[i];
		var name = field.getAttribute('name');
		this.formElements[name] = field;
	}
	this.formElements['cc_full_name'].focus();
	this.addListeners();
};

CreditCard.prototype.addListeners = function() {
	this.cancelButton.addEventListener('click', this.handleCancel.bind(this));
	this.continueButton.addEventListener('click', this.handleContinue.bind(this));
};

CreditCard.prototype.addError = function(name, msg) {
	var errorElement = this.el.querySelector('[data-validation-for="' + name + '"]');
	errorElement.style.display = 'block';
	errorElement.dataset.valid = false;
	errorElement.textContent = msg;
};

CreditCard.prototype.removeError = function(name) {
	var errorElement = this.el.querySelector('[data-validation-for="' + name + '"]');
	errorElement.style.display = 'none';
	errorElement.dataset.valid = true;
	errorElement.textContent = '';
};

CreditCard.prototype.validate = function() {
	var valid = true;
	this.formData = {};
	for (var i = 0; i < this.fields.length; i++) {
		var field = this.fields[i];
		var name = field.getAttribute('name');
		this.formData[name] = field.value;
	}

	if (this.formData.cc_full_name.length === 0) {
		this.addError('cc_full_name', 'This field is required.');
		if (valid) this.formElements['cc_full_name'].focus();
		valid = false;
	} else {
		this.removeError('cc_full_name');
	}

	var cc = validation.validateCard(this.data.acceptedCards, this.formData.cc_number);
	if (!cc.valid) {
		this.addError('cc_number', cc.message);
		if (valid) this.formElements['cc_number'].focus();
		valid = false;
	} else {
		this.removeError('cc_number');
	}

	var exp = validation.validateExp(this.formData.cc_exp_date_month, this.formData.cc_exp_date_year);
	if (!exp.valid) {
		this.addError('cc_exp_date', exp.message);
		if (valid) this.formElements['cc_exp_date_month'].focus();
		valid = false;
	} else {
		this.removeError('cc_exp_date');
	}

	var cvv = validation.validateCVV(this.formData.cc_code);
	if (!cvv.valid) {
		this.addError('cc_code', cvv.message);
		if (valid) this.formElements['cc_code'].focus();
		valid = false;
	} else {
		this.removeError('cc_code');
	}
	return valid;
};

CreditCard.prototype.handleContinue = function() {
	if (this.validate()) {
		var fd = this.formData;
		fd.cc_exp_date = fd.cc_exp_date_month + '/' + fd.cc_exp_date_year;
		fd.cc_last_four_digits = fd.cc_number.substr(fd.cc_number.length - 4);
		Object.keys(fd).map(function(key) {
			profile.set(key, fd[key]);
		});
		publish('enable-input');
		publish('send', {
			silent: true,
			text: 'success'
		});
	}
};

CreditCard.prototype.handleCancel = function() {
	this.cancelButton.classList.add(activeClassName);
	publish('enable-input');
	publish('send', {
		silent: true,
		text: 'cancel'
	});
};

CreditCard.prototype.removeAllEventListeners = function() {
	this.cancelButton.removeEventListener('click', this.handleCancel.bind(this));
	this.cancelButton.setAttribute('disabled', true);
	this.continueButton.removeEventListener('click', this.handleContinue.bind(this));
	this.continueButton.setAttribute('disabled', true);
	for (var j = 0; j < this.fields.length; j++)
		this.fields[j].setAttribute('disabled', true);

	this.subscribeSend.remove();
};

module.exports = creditCardLayout;
<|endoftext|>


<commit_before>/* global expect */

import Types from 'common/src/data/clusters/clusters-types';
import Store from 'common/src/data/clusters/clusters-store';
import * as Getter from 'common/src/data/clusters/clusters-getter';
import FetchResult from 'common/src/fetch-result';

var clusters = [
    {
      'alias': 'playground',
      'environment': 'playground',
      'id': 'c-1'
    },
    {
      'alias': 'stups-test',
      'environment': 'test',
      'id': 'c-2'
    },
    {
      'alias': 'stups',
      'environment': 'production',
      'id': 'c-3'
    },
    {
      'alias': 'overarching',
      'environment': 'production',
      'id': 'c-4'
    },
    {
      'alias': 'db',
      'environment': 'production',
      'id': 'c-5'
    },
    {
      'alias': 'fashion-store',
      'environment': 'production',
      'id': 'c-6'
    },
    {
      'alias': 'fashion-store-test',
      'environment': 'test',
      'id': 'c-7'
    },
    {
      'alias': 'distributed-commerce',
      'environment': 'production',
      'id': 'c-8'
    },
    {
      'alias': 'distributed-commerce-test',
      'environment': 'test',
      'id': 'c-9'
    },
    {
      'alias': 'teapot',
      'environment': 'test',
      'id': 'c-10'
    }  ];

describe('The redux cluster store', () => {
    it.skip('should set a pending fetch result for clusters', () => {
        let state = Store(Store(), {
                type: Types.BEGIN_FETCH_CLUSTERS,
                payload: [null, {items:clusters}]
            }),
            resource = Getter.getAllClusters(state);
        expect(resource instanceof FetchResult).to.be.true;
        expect(resource.isPending()).to.be.true;
    });

    it.skip('should set a failed fetch result for a clusters', () => {
      expect(true).to.be.true;
    });
});<commit_msg>#275 clean code<commit_after>/* global expect */

import Types from 'common/src/data/clusters/clusters-types';
import Store from 'common/src/data/clusters/clusters-store';
import * as Getter from 'common/src/data/clusters/clusters-getter';
import FetchResult from 'common/src/fetch-result';

var clusters = [
  {
    'alias': 'st',
    'environment': 'pg',
    'id': 'c-1'
  },
  {
    'alias': 'st-t',
    'environment': 't',
    'id': 'c-2'
  },
  {
    'alias': 'st',
    'environment': 'production',
    'id': 'c-3'
  },
  {
    'alias': 'ovra',
    'environment': 'production',
    'id': 'c-4'
  },
  {
    'alias': 'database',
    'environment': 'production',
    'id': 'c-5'
  },
  {
    'alias': 'f-store',
    'environment': 'production',
    'id': 'c-6'
  },
  {
    'alias': 'f-store-test',
    'environment': 't',
    'id': 'c-7'
  },
  {
    'alias': 'dist',
    'environment': 'production',
    'id': 'c-8'
  },
  {
    'alias': 'dist-test',
    'environment': 't',
    'id': 'c-9'
  },
  {
    'alias': 'tp',
    'environment': 't',
    'id': 'c-10'
  }  ];

describe('The redux cluster store', () => {
    it.skip('should set a pending fetch result for clusters', () => {
        let state = Store(Store(), {
                type: Types.BEGIN_FETCH_CLUSTERS,
                payload: [null, {items:clusters}]
            }),
            resource = Getter.getAllClusters(state);
        expect(resource instanceof FetchResult).to.be.true;
        expect(resource.isPending()).to.be.true;
    });

    it.skip('should set a failed fetch result for a clusters', () => {
      expect(true).to.be.true;
    });
});<|endoftext|>


<commit_before>Accounts.ui.config(
		{ passwordSignupFields: 'USERNAME_AND_EMAIL' }
);

Template.nav.notRegistered = function(){
	var currentUser = Meteor.user();
	return !(currentUser.emails[0]["verified"]);
}

Template.nav.events = {
	'click button[name=verify]': function(){
		Meteor.call("sendEmail",Meteor.userId());
	}
}
<commit_msg>extras<commit_after>Accounts.ui.config(
		{ passwordSignupFields: 'USERNAME_AND_EMAIL' }
);

Template.nav.notRegistered = function(){
	var currentUser = Meteor.user();
	if(currentUser.emails.length<0){
		return false;
	}
	return !(currentUser.emails[0]["verified"]);
}

Template.nav.events = {
	'click button[name=verify]': function(){
		Meteor.call("sendEmail",Meteor.userId());
	}
}
<|endoftext|>


<commit_before>// Text rendering style

import Builders from '../builders';
import Texture from '../../gl/texture';
import WorkerBroker from '../../utils/worker_broker';
import Utils from '../../utils/utils';
import {Sprites} from '../sprites/sprites';
import Label from './label';

export let TextStyle = Object.create(Sprites);

Object.assign(TextStyle, {
    name: 'text',
    super: Sprites,
    built_in: true,

    init() {

        this.super.init.apply(this);

        // Provide a hook for this object to be called from worker threads
        if (Utils.isMainThread) {
            WorkerBroker.addTarget('TextStyle', this);
        }

        this.texts = {}; // unique texts, keyed by tile
        this.texture = {};
        this.canvas = {};
        this.bboxes = {};
        this.geometries = {};

        this.font_style = {
            typeface: 'Helvetica',
            size: '12px',
            fill: 'white',
            stroke: 'black'
        };

        // default label style
        this.label_style = {
            lines: { exceed: 60 }
        };
    },

    // Set font style params for canvas drawing
    setFont (tile, { size, typeface, fill, stroke }) {
        this.size = parseInt(size);
        this.buffer = 6; // pixel padding around text
        let ctx = this.canvas[tile].context;

        ctx.font = size + ' ' + typeface;
        ctx.strokeStyle = stroke;
        ctx.fillStyle = fill;
        ctx.lineWidth = 4;
        ctx.miterLimit = 2;
    },

    // Width and height of text based on current font style
    textSize (text, tile) {
        return [
            Math.ceil(this.canvas[tile].context.measureText(text).width) + this.buffer * 2,
            this.size + this.buffer * 2
        ];
    },

    // Draw text at specified location, adjusting for buffer and baseline
    drawText (text, [x, y], tile) {
        // TODO: optional stroke
        this.canvas[tile].context.strokeText(text, x + this.buffer, y + this.buffer + this.size);
        this.canvas[tile].context.fillText(text, x + this.buffer, y + this.buffer + this.size);
    },

    setTextureTextPositions (texts) {
        // Find widest label and sum of all label heights
        let widest = 0, height = 0;

        for (let style in texts) {
            let text_infos = texts[style];

            for (let text in text_infos) {
                let text_info = text_infos[text];
                let size = text_info.size;

                text_info.position = [0, height];

                if (size[0] > widest) {
                    widest = size[0];
                }

                height += size[1];
            }
        }

        return [ widest, height ];
    },

    getTextSizes (tile, texts) {
        // create a canvas
        if(this.canvas[tile] === undefined) {
            let canvas = document.createElement('canvas');
            this.canvas[tile] = {
                canvas: canvas,
                context: canvas.getContext('2d')
            };
        }

        for (let style in texts) {
            let text_infos = texts[style];

            for (let text in text_infos) {
                // update text sizes
                this.setFont(tile, text_infos[text].text_style);
                text_infos[text].size = this.textSize(text, tile);
            }
        }

        return Promise.resolve(texts);
    },

    rasterize (tile, texts, texture_size) {
        for (let style in texts) {
            let text_infos = texts[style];

            for (let text in text_infos) {
                let info = text_infos[text];

                this.setFont(tile, info.text_style);
                this.drawText(text, info.position, tile);

                info.texcoords = Builders.getTexcoordsForSprite(
                    info.position,
                    info.size,
                    texture_size
                );
            }
        }
    },

    // Called on main thread from worker, to create atlas of labels for a tile
    addTexts (tile, texts) {
        this.texts[tile] = texts;

        let texture_size = this.setTextureTextPositions(texts);
        let context = this.canvas[tile].context;

        console.log(`text summary for tile ${tile}: fits in ${texture_size[0]}x${texture_size[1]}px`);

        // update the canvas "context"
        this.canvas[tile].canvas.width = texture_size[0];
        this.canvas[tile].canvas.height = texture_size[1];
        context.clearRect(0, 0, texture_size[0], texture_size[1]);

        // create a texture
        this.texture[tile] = new Texture(this.gl, 'labels-' + tile, { filtering: 'linear' });
        this.texture[tile].setCanvas(this.canvas[tile].canvas);

        // ask for rasterization for the text set
        this.rasterize(tile, texts, texture_size);

        this.texture[tile].update();

        return Promise.resolve(this.texts[tile]);
    },

    // Override
    startData () {
        let tile_data = this.super.startData.apply(this);
        tile_data.queue = [];
        return tile_data;
    },

    // Override
    endData (tile_data) {
        // Count collected text
        let tile, count;
        if (tile_data.queue.length > 0) {
            tile = tile_data.queue[0][2].tile.key;
            count = Object.keys(this.texts[tile]||{}).length;
            console.log(`# texts for tile ${tile}: ${count}`);
        }
        if (!count) {
            return Promise.resolve();
        }

        // Attach tile-specific label atlas to mesh as a texture uniform
        tile_data.uniforms = { u_textures: ['labels-'+tile] };

        // first call to main thread, ask for text pixel sizes
        return WorkerBroker.postMessage('TextStyle', 'getTextSizes', tile, this.texts[tile]).then(texts => {
            this.bboxes[tile] = [];

            // cleanup of texts that should be removed after occlusion test
            for (let style in texts) {
                let text_infos = texts[style];

                for (let text in text_infos) {
                    let text_info = text_infos[text];
                    let label;
                    let keep_in_tile;
                    let move_in_tile;
                    let geometry = this.geometries[tile][style][text];
                    let exceed_heuristic = this.label_style.lines.exceed;

                    if (geometry.type === "LineString") {
                        let lines = geometry.coordinates;
                        let line = [lines[0]];

                        keep_in_tile = true;
                        move_in_tile = true;

                        label = new Label(text, line[0], text_info.size, lines);
                    } else if (geometry.type === "Point") {
                        let points = [geometry.coordinates];

                        keep_in_tile = true;
                        move_in_tile = false;

                        label = new Label(text, points[0], text_info.size);
                    }

                    if (label.discard(move_in_tile, keep_in_tile, this.bboxes[tile], exceed_heuristic)) {
                        // remove the text from the map
                        delete text_infos[text];
                    }

                    text_info.label = label;
                }
            }

            if (Object.keys(texts).length === 0) {
                // early exit
                return;
            }

            // second call to main thread, for rasterizing the set of texts
            return WorkerBroker.postMessage('TextStyle', 'addTexts', tile, texts).then(texts => {
                this.texts[tile] = texts;

                // Build queued features
                tile_data.queue.forEach(q => this.super.addFeature.apply(this, q));
                tile_data.queue = [];

                return this.super.endData.call(this, tile_data);
            });
        });
    },

    // Override to queue features instead of processing immediately
    addFeature (feature, rule, context, tile_data) {
        // Collect text
        let text = feature.properties.name;

        if (text) {
            let tile = context.tile.key;
            if (!this.texts[tile]) {
                this.texts[tile] = {};
            }

            if (!this.geometries[tile]) {
                this.geometries[tile] = {};
            }

            let style = this.constructFontStyle(rule);
            let style_key = this.constructStyleKey(style);

            if (!this.texts[tile][style_key]) {
                this.texts[tile][style_key] = {};
            }

            if (!this.geometries[tile][style_key]) {
                this.geometries[tile][style_key] = feature.geometry;
            }

            this.texts[tile][style_key][text] = {
                text_style: style
            };

            this.geometries[tile][style_key][text] = feature.geometry;
        }

        tile_data.queue.push([feature, rule, context, tile_data]);
    },

    constructFontStyle (rule) {
        let style = this.font_style;

        if (rule.font) {
            style = {
                typeface: rule.font.typeface || this.font_style.typeface,
                size: rule.font.size || this.font_size.font_size,
                fill: rule.font.fill === undefined ? this.font_style.fill : Utils.toCanvasColor(rule.font.fill),
                stroke: rule.font.stroke === undefined ? this.font_style.stroke : Utils.toCanvasColor(rule.font.stroke)
            };
        }

        return style;
    },

    constructStyleKey ({ typeface, size, fill, stroke }) {
        return `${typeface}/${size}/${fill}/${stroke}`;
    },

    build (style, vertex_data) {
        let vertex_template = this.makeVertexTemplate(style);

        Builders.buildSpriteQuadsForPoints(
            [ style.label.position ],
            Utils.scaleInt16(style.label.size[0], 128), Utils.scaleInt16(style.label.size[1], 128),
            Utils.scaleInt16(Utils.radToDeg(style.label.angle), 360),
            Utils.scaleInt16(1, 256),
            vertex_data,
            vertex_template,
            this.vertex_layout.index.a_shape,
            { texcoord_index: this.vertex_layout.index.a_texcoord, texcoord_scale: this.texcoord_scale }
        );
    },

    buildLines (lines, style, vertex_data) {
        if (style.discarded) {
            return;
        }

        this.build(style, vertex_data);
    },

    buildPoints (points, style, vertex_data) {
        if (style.discarded) {
            return;
        }

        this.build(style, vertex_data);
    },

    _parseFeature (feature, rule_style, context) {
        let style = this.feature_style;
        let tile = context.tile.key;
        let text = feature.properties.name;

        let font_style = this.constructFontStyle(rule_style);
        let style_key = this.constructStyleKey(font_style);

        let discarded = this.texts[tile][style_key][text] === undefined;

        style.discarded = discarded;

        if (!discarded) {
            let text_info = this.texts[tile][style_key][text];
            this.texcoord_scale = text_info.texcoords;

            style.text = text;

            // to store bbox by tiles
            style.tile = tile;
            style.label = text_info.label;
        }

        return style;
    }

});

<commit_msg>labels: return before rendering when all labels are discarded<commit_after>// Text rendering style

import Builders from '../builders';
import Texture from '../../gl/texture';
import WorkerBroker from '../../utils/worker_broker';
import Utils from '../../utils/utils';
import {Sprites} from '../sprites/sprites';
import Label from './label';

export let TextStyle = Object.create(Sprites);

Object.assign(TextStyle, {
    name: 'text',
    super: Sprites,
    built_in: true,

    init() {

        this.super.init.apply(this);

        // Provide a hook for this object to be called from worker threads
        if (Utils.isMainThread) {
            WorkerBroker.addTarget('TextStyle', this);
        }

        this.texts = {}; // unique texts, keyed by tile
        this.texture = {};
        this.canvas = {};
        this.bboxes = {};
        this.geometries = {};

        this.font_style = {
            typeface: 'Helvetica',
            size: '12px',
            fill: 'white',
            stroke: 'black'
        };

        // default label style
        this.label_style = {
            lines: { exceed: 60 }
        };
    },

    // Set font style params for canvas drawing
    setFont (tile, { size, typeface, fill, stroke }) {
        this.size = parseInt(size);
        this.buffer = 6; // pixel padding around text
        let ctx = this.canvas[tile].context;

        ctx.font = size + ' ' + typeface;
        ctx.strokeStyle = stroke;
        ctx.fillStyle = fill;
        ctx.lineWidth = 4;
        ctx.miterLimit = 2;
    },

    // Width and height of text based on current font style
    textSize (text, tile) {
        return [
            Math.ceil(this.canvas[tile].context.measureText(text).width) + this.buffer * 2,
            this.size + this.buffer * 2
        ];
    },

    // Draw text at specified location, adjusting for buffer and baseline
    drawText (text, [x, y], tile) {
        // TODO: optional stroke
        this.canvas[tile].context.strokeText(text, x + this.buffer, y + this.buffer + this.size);
        this.canvas[tile].context.fillText(text, x + this.buffer, y + this.buffer + this.size);
    },

    setTextureTextPositions (texts) {
        // Find widest label and sum of all label heights
        let widest = 0, height = 0;

        for (let style in texts) {
            let text_infos = texts[style];

            for (let text in text_infos) {
                let text_info = text_infos[text];
                let size = text_info.size;

                text_info.position = [0, height];

                if (size[0] > widest) {
                    widest = size[0];
                }

                height += size[1];
            }
        }

        return [ widest, height ];
    },

    getTextSizes (tile, texts) {
        // create a canvas
        if(this.canvas[tile] === undefined) {
            let canvas = document.createElement('canvas');
            this.canvas[tile] = {
                canvas: canvas,
                context: canvas.getContext('2d')
            };
        }

        for (let style in texts) {
            let text_infos = texts[style];

            for (let text in text_infos) {
                // update text sizes
                this.setFont(tile, text_infos[text].text_style);
                text_infos[text].size = this.textSize(text, tile);
            }
        }

        return Promise.resolve(texts);
    },

    rasterize (tile, texts, texture_size) {
        for (let style in texts) {
            let text_infos = texts[style];

            for (let text in text_infos) {
                let info = text_infos[text];

                this.setFont(tile, info.text_style);
                this.drawText(text, info.position, tile);

                info.texcoords = Builders.getTexcoordsForSprite(
                    info.position,
                    info.size,
                    texture_size
                );
            }
        }
    },

    // Called on main thread from worker, to create atlas of labels for a tile
    addTexts (tile, texts) {
        this.texts[tile] = texts;

        let texture_size = this.setTextureTextPositions(texts);
        let context = this.canvas[tile].context;

        console.log(`text summary for tile ${tile}: fits in ${texture_size[0]}x${texture_size[1]}px`);

        // update the canvas "context"
        this.canvas[tile].canvas.width = texture_size[0];
        this.canvas[tile].canvas.height = texture_size[1];
        context.clearRect(0, 0, texture_size[0], texture_size[1]);

        // create a texture
        this.texture[tile] = new Texture(this.gl, 'labels-' + tile, { filtering: 'linear' });
        this.texture[tile].setCanvas(this.canvas[tile].canvas);

        // ask for rasterization for the text set
        this.rasterize(tile, texts, texture_size);

        this.texture[tile].update();

        return Promise.resolve(this.texts[tile]);
    },

    // Override
    startData () {
        let tile_data = this.super.startData.apply(this);
        tile_data.queue = [];
        return tile_data;
    },

    // Override
    endData (tile_data) {
        // Count collected text
        let tile, count;
        if (tile_data.queue.length > 0) {
            tile = tile_data.queue[0][2].tile.key;
            count = Object.keys(this.texts[tile]||{}).length;
            console.log(`# texts for tile ${tile}: ${count}`);
        }
        if (!count) {
            return Promise.resolve();
        }

        // Attach tile-specific label atlas to mesh as a texture uniform
        tile_data.uniforms = { u_textures: ['labels-'+tile] };

        // first call to main thread, ask for text pixel sizes
        return WorkerBroker.postMessage('TextStyle', 'getTextSizes', tile, this.texts[tile]).then(texts => {
            this.bboxes[tile] = [];

            // cleanup of texts that should be removed after occlusion test
            for (let style in texts) {
                let text_infos = texts[style];

                for (let text in text_infos) {
                    let text_info = text_infos[text];
                    let label;
                    let keep_in_tile;
                    let move_in_tile;
                    let geometry = this.geometries[tile][style][text];
                    let exceed_heuristic = this.label_style.lines.exceed;

                    if (geometry.type === "LineString") {
                        let lines = geometry.coordinates;
                        let line = [lines[0]];

                        keep_in_tile = true;
                        move_in_tile = true;

                        label = new Label(text, line[0], text_info.size, lines);
                    } else if (geometry.type === "Point") {
                        let points = [geometry.coordinates];

                        keep_in_tile = true;
                        move_in_tile = false;

                        label = new Label(text, points[0], text_info.size);
                    }

                    if (label.discard(move_in_tile, keep_in_tile, this.bboxes[tile], exceed_heuristic)) {
                        // remove the text from the map
                        delete text_infos[text];
                    }

                    text_info.label = label;
                }

                // No labels for this style
                if (Object.keys(text_infos).length === 0) {
                    delete texts[style];
                }
            }

            // No labels for this tile
            if (Object.keys(texts).length === 0) {
                // early exit
                return;
            }

            // second call to main thread, for rasterizing the set of texts
            return WorkerBroker.postMessage('TextStyle', 'addTexts', tile, texts).then(texts => {
                this.texts[tile] = texts;
                // Build queued features
                tile_data.queue.forEach(q => this.super.addFeature.apply(this, q));
                tile_data.queue = [];
                return this.super.endData.call(this, tile_data);
            });
        });
    },

    // Override to queue features instead of processing immediately
    addFeature (feature, rule, context, tile_data) {
        // Collect text
        let text = feature.properties.name;

        if (text) {
            let tile = context.tile.key;
            if (!this.texts[tile]) {
                this.texts[tile] = {};
            }

            if (!this.geometries[tile]) {
                this.geometries[tile] = {};
            }

            let style = this.constructFontStyle(rule);
            let style_key = this.constructStyleKey(style);

            if (!this.texts[tile][style_key]) {
                this.texts[tile][style_key] = {};
            }

            if (!this.geometries[tile][style_key]) {
                this.geometries[tile][style_key] = feature.geometry;
            }

            this.texts[tile][style_key][text] = {
                text_style: style
            };

            this.geometries[tile][style_key][text] = feature.geometry;
        }

        tile_data.queue.push([feature, rule, context, tile_data]);
    },

    constructFontStyle (rule) {
        let style = this.font_style;

        if (rule.font) {
            style = {
                typeface: rule.font.typeface || this.font_style.typeface,
                size: rule.font.size || this.font_size.font_size,
                fill: rule.font.fill === undefined ? this.font_style.fill : Utils.toCanvasColor(rule.font.fill),
                stroke: rule.font.stroke === undefined ? this.font_style.stroke : Utils.toCanvasColor(rule.font.stroke)
            };
        }

        return style;
    },

    constructStyleKey ({ typeface, size, fill, stroke }) {
        return `${typeface}/${size}/${fill}/${stroke}`;
    },

    build (style, vertex_data) {
        let vertex_template = this.makeVertexTemplate(style);

        Builders.buildSpriteQuadsForPoints(
            [ style.label.position ],
            Utils.scaleInt16(style.label.size[0], 128), Utils.scaleInt16(style.label.size[1], 128),
            Utils.scaleInt16(Utils.radToDeg(style.label.angle), 360),
            Utils.scaleInt16(1, 256),
            vertex_data,
            vertex_template,
            this.vertex_layout.index.a_shape,
            { texcoord_index: this.vertex_layout.index.a_texcoord, texcoord_scale: this.texcoord_scale }
        );
    },

    buildLines (lines, style, vertex_data) {
        if (style.discarded) {
            return;
        }

        this.build(style, vertex_data);
    },

    buildPoints (points, style, vertex_data) {
        if (style.discarded) {
            return;
        }

        this.build(style, vertex_data);
    },

    _parseFeature (feature, rule_style, context) {
        let style = this.feature_style;
        let tile = context.tile.key;
        let text = feature.properties.name;

        let font_style = this.constructFontStyle(rule_style);
        let style_key = this.constructStyleKey(font_style);

        style.discarded  = (!this.texts[tile] || !this.texts[tile][style_key] || !this.texts[tile][style_key][text]);

        if (!style.discarded) {
            let text_info = this.texts[tile][style_key][text];
            this.texcoord_scale = text_info.texcoords;

            style.text = text;

            // to store bbox by tiles
            style.tile = tile;
            style.label = text_info.label;
        }

        return style;
    }

});

<|endoftext|>


<commit_before>'use-strict';

(function DropdownList() {
  const dropdownCollapseLabel = '.dropdown-list__item--collapse .dropdown-list__label',
        dropdownItem          = [ ...document.querySelectorAll(dropdownCollapseLabel) ],
        openClass             = 'dropdown-list__item--open',
        contentClass          = 'dropdown-list__content',
        mq                    = '(min-width: 768px)';

  function setListHeight(item) {
    return Array.from(item.children)
      .map(elem => elem.clientHeight)
      .reduce((a, b) => a + b, 0);
  }

  function setAriaAttributes(label, content, expanded) {
    if (expanded) {
      label.setAttribute('aria-expanded', 'false');
      content.setAttribute('aria-hidden', 'true');
    }
    else {
      label.setAttribute('aria-expanded', 'true');
      content.setAttribute('aria-hidden', 'false');
    }
  }

  function isMediumOpen(dropdownBlock) {
    return (dropdownBlock.classList.contains('dropdown-list--is-open@screen-m')) && window.matchMedia(mq).matches;
  }

  function resetMqMediumOpen(item) {
    const dropdownItem = item.parentNode,
          dropdownContent = dropdownItem.querySelector(`.${contentClass}`);

    if (window.matchMedia(mq).matches) {
      dropdownContent.style.height = 'auto';
      dropdownItem.classList.remove(openClass);
      setAriaAttributes(item, dropdownContent, true);
    }
    else {
      dropdownContent.style.height = 0;
      dropdownItem.classList.remove(openClass);
      setAriaAttributes(item, dropdownContent, false);
    }
  }

  function toggleContent(item) {
    const dropdownId      = item.dataset.dropdown,
          dropdownItem    = item.parentNode,
          dropdownContent = dropdownItem.querySelector(`.${contentClass}[data-content="${dropdownId}"]`),
          dropdownBlock   = item.closest('.dropdown-list');

    if (!isMediumOpen(dropdownBlock)) {
      if (dropdownContent.clientHeight > 0) {
        dropdownContent.style.height = 0;
        dropdownItem.classList.remove(openClass);
        setAriaAttributes(item, dropdownContent, true);
      }
      else {
        dropdownContent.style.height = `${setListHeight(dropdownContent)}px`;
        dropdownItem.classList.add(openClass);
        setAriaAttributes(item, dropdownContent, false);
      }
    }
    else {
      dropdownContent.style.height = 'auto';
      dropdownItem.classList.remove(openClass);
      setAriaAttributes(item, dropdownContent, false);
    }
  }

  dropdownItem.forEach(
    key => key.addEventListener('click', (e) => {
      e.preventDefault();
      toggleContent(key, false);
    }, false)
  );

  window.addEventListener('resize', () => {
    const dropdownMediumOpen = document.querySelector('.dropdown-list--is-open\\@screen-m');
    if (dropdownMediumOpen) {
      const dropdownItems =  [ ...dropdownMediumOpen.querySelectorAll(dropdownCollapseLabel)];
      dropdownItems.forEach(key => resetMqMediumOpen(key));
    }
  });
})();
<commit_msg>#35910 Dropdown-list: Quick fix for content height bug.<commit_after>'use-strict';

(function DropdownList() {
  const dropdownCollapseLabel = '.dropdown-list__item--collapse .dropdown-list__label',
        dropdownItem          = [ ...document.querySelectorAll(dropdownCollapseLabel) ],
        openClass             = 'dropdown-list__item--open',
        contentClass          = 'dropdown-list__content',
        mq                    = '(min-width: 768px)';

  function setAriaAttributes(label, content, expanded) {
    if (expanded) {
      label.setAttribute('aria-expanded', 'false');
      content.setAttribute('aria-hidden', 'true');
    }
    else {
      label.setAttribute('aria-expanded', 'true');
      content.setAttribute('aria-hidden', 'false');
    }
  }

  function isMediumOpen(dropdownBlock) {
    return (dropdownBlock.classList.contains('dropdown-list--is-open@screen-m')) && window.matchMedia(mq).matches;
  }

  function resetMqMediumOpen(item) {
    const dropdownItem = item.parentNode,
          dropdownContent = dropdownItem.querySelector(`.${contentClass}`);

    if (window.matchMedia(mq).matches) {
      dropdownContent.style.height = 'auto';
      dropdownItem.classList.remove(openClass);
      setAriaAttributes(item, dropdownContent, true);
    }
    else {
      dropdownContent.style.height = 0;
      dropdownItem.classList.remove(openClass);
      setAriaAttributes(item, dropdownContent, false);
    }
  }

  function toggleContent(item) {
    const dropdownId      = item.dataset.dropdown,
          dropdownItem    = item.parentNode,
          dropdownContent = dropdownItem.querySelector(`.${contentClass}[data-content="${dropdownId}"]`),
          dropdownBlock   = item.closest('.dropdown-list');

    if (!isMediumOpen(dropdownBlock)) {
      if (dropdownContent.clientHeight > 0) {
        dropdownContent.style.height = 0;
        dropdownItem.classList.remove(openClass);
        setAriaAttributes(item, dropdownContent, true);
      }
      else {
        dropdownContent.style.height = 'auto';
        dropdownItem.classList.add(openClass);
        setAriaAttributes(item, dropdownContent, false);
      }
    }
    else {
      dropdownContent.style.height = 'auto';
      dropdownItem.classList.remove(openClass);
      setAriaAttributes(item, dropdownContent, false);
    }
  }

  dropdownItem.forEach(
    key => key.addEventListener('click', (e) => {
      e.preventDefault();
      toggleContent(key, false);
    }, false)
  );

  window.addEventListener('resize', () => {
    const dropdownMediumOpen = document.querySelector('.dropdown-list--is-open\\@screen-m');
    if (dropdownMediumOpen) {
      const dropdownItems =  [ ...dropdownMediumOpen.querySelectorAll(dropdownCollapseLabel)];
      dropdownItems.forEach(key => resetMqMediumOpen(key));
    }
  });
})();
<|endoftext|>


<commit_before>import assert from 'assert';
import sinon from 'sinon';
import {
  promiseThat,
  assertThat,
  fulfilled,
  isFulfilledWith,
  allOf,
  equalTo,
  is,
  truthy,
  falsy
} from 'hamjest';

assert.called = sinon.assert.called;
assert.calledWith = sinon.assert.calledWith;

describe('', function() {

  class File {}

  class JsonFile {
    constructor(readFile, writeFile) {
      this.readFile = readFile;
      this.writeFile = writeFile;
      this.fileContent = null;
    }
    read(file) {
      this.fileContent = this.readFile(file);
      return this;
    }
    minify() {
      this.fileContent = this.fileContent.then(content => JSON.stringify(JSON.parse(content)));
      return this;
    }
    write(file) {
      return this.fileContent.then(content => this.writeFile(file, content));
    }
  }

  describe('reads the file', function() {

    let readFile;

    function readJsonFile(file) {
      return new JsonFile(readFile).read(file).minify().fileContent;
    }

    it('and minifies the JSON', function() {
      const payload = {a:1};
      const beautifiedJson = JSON.stringify(payload, null, 4);
      const minifiedJson = JSON.stringify(payload);
      readFile = () => Promise.resolve(beautifiedJson);

      return promiseThat(readJsonFile(), isFulfilledWith(minifiedJson));
    });

    it('from the given path', function() {
      const payload = {a:1};
      const beautifiedJson = JSON.stringify(payload, null, 4);
      const file = new File();
      readFile = sinon.stub();
      readFile.returns(Promise.resolve(beautifiedJson));

      readJsonFile(file);

      assert.calledWith(readFile, file);
    });

  });

  describe('writes file content', function() {

    it('and returns a promise when done', function() {
      const fileContent = 'file content';
      const readFile = () => Promise.resolve(fileContent);
      const writeFile = sinon.stub();
      const file = new File();
      let jsonFile = new JsonFile(readFile, writeFile);

      return promiseThat(jsonFile.read().write(file), fulfilled());
    });

    it('to given path', function(done) {
      const fileContent = 'file content';
      const readFile = () => Promise.resolve(fileContent);
      const writeFile = sinon.stub();
      const file = new File();
      let jsonFile = new JsonFile(readFile, writeFile);

      //return promiseThat(jsonFile.read().write(file), allOf(fulfilled(), is(truthy(writeFile.calledWith(file, fileContent)))));

      jsonFile.read().write(file).then(() => {
        assert.calledWith(writeFile, file, fileContent);
        done();
      }).catch(() => {
        done(new Error('promise was rejected'));
      });
    });

  });

});
<commit_msg>Refactoring tests a bit more readable.<commit_after>import assert from 'assert';
import sinon from 'sinon';
import {
  promiseThat,
  assertThat,
  fulfilled,
  isFulfilledWith,
  allOf,
  equalTo,
  is,
  truthy,
  falsy
} from 'hamjest';

assert.called = sinon.assert.called;
assert.calledWith = sinon.assert.calledWith;

describe('', function() {

  class File {}

  class JsonFile {
    constructor(readFile, writeFile) {
      this.readFile = readFile;
      this.writeFile = writeFile;
      this.fileContent = null;
    }
    read(file) {
      this.fileContent = this.readFile(file);
      return this;
    }
    minify() {
      this.fileContent = this.fileContent.then(content => JSON.stringify(JSON.parse(content)));
      return this;
    }
    write(file) {
      return this.fileContent.then(content => this.writeFile(file, content));
    }
  }

  describe('reads the file', function() {

    const payload = {a:1};
    const beautifiedJson = JSON.stringify(payload, null, 4);
    const minifiedJson = JSON.stringify(payload);
    const file = new File();

    function readJsonFile(readFile, file) {
      return new JsonFile(readFile).read(file).minify().fileContent;
    }

    it('and minifies the JSON', function() {
      let readFile = () => Promise.resolve(beautifiedJson);

      const fileContent = readJsonFile(readFile);

      return promiseThat(fileContent, isFulfilledWith(minifiedJson));
    });

    it('from the given path', function() {
      let readFile = sinon.stub();
      readFile.returns(Promise.resolve(beautifiedJson));

      readJsonFile(readFile, file);

      assert.calledWith(readFile, file);
    });

  });

  describe('writes file content', function() {

    it('and returns a promise when done', function() {
      const fileContent = 'file content';
      const readFile = () => Promise.resolve(fileContent);
      const writeFile = sinon.stub();
      const file = new File();
      let jsonFile = new JsonFile(readFile, writeFile);

      return promiseThat(jsonFile.read().write(file), fulfilled());
    });

    it('to given path', function(done) {
      const fileContent = 'file content';
      const readFile = () => Promise.resolve(fileContent);
      const writeFile = sinon.stub();
      const file = new File();
      let jsonFile = new JsonFile(readFile, writeFile);

      //return promiseThat(jsonFile.read().write(file), allOf(fulfilled(), is(truthy(writeFile.calledWith(file, fileContent)))));

      jsonFile.read().write(file).then(() => {
        assert.calledWith(writeFile, file, fileContent);
        done();
      }).catch(() => {
        done(new Error('promise was rejected'));
      });
    });

  });

});
<|endoftext|>


<commit_before>"use strict";

Object.defineProperty(exports, "__esModule", {
	value: true
});
exports.save = save;
exports.load = load;
exports.combineLoads = combineLoads;
exports.clear = clear;

var _immutable = require("immutable");

var NAMESPACE_DEFAULT = "redux_localstorage_simple";

var localStorageMock = {
	removeItem: function removeItem(key) {
		delete this[key];
	}
}

var localStorage = (typeof window === "undefined") ? localStorageMock : window.localStorage

// when running in a non-browser environment, for example during unit tests, then mock localStorage
if (typeof window === "undefined") {
	console.warn("LocalStorage not detected. Package 'redux-localstorage-simple' will mock it to prevent crashing.");
}

/**
	Saves specified parts of the Redux state tree into localstorage
	Note: this is Redux middleware. Read this for an explanation:
	http://redux.js.org/docs/advanced/Middleware.html

	PARAMETERS
	----------
	@config (Object) - 	Contains configuration options (leave blank to save entire state tree to localstorage)

						Properties:
							states (Array of Strings, optional) - States to save e.g. ["user", "products"]
							namespace (String, optional) - Namespace to add before your LocalStorage items

	Usage examples:

		// save entire state tree - EASIEST OPTION
		save()

		// save specific parts of the state tree
		save({
			states: ["user", "products"]
		})

		// save the entire state tree under the namespace "my_cool_app". The key "my_cool_app" will appear in LocalStorage
		save({
			namespace: "my_cool_app"
		})

		// save specific parts of the state tree with the namespace "my_cool_app". The keys "my_cool_app_user" and "my_cool_app_products" will appear in LocalStorage
		save({
		    states: ["user", "products"],
		    namespace: "my_cool_app"
		})
*/

function save() {
	var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	var _ref$states = _ref.states;
	var states = _ref$states === undefined ? [] : _ref$states;
	var _ref$namespace = _ref.namespace;
	var namespace = _ref$namespace === undefined ? NAMESPACE_DEFAULT : _ref$namespace;

	return function (store) {
		return function (next) {
			return function (action) {

				next(action);

				if (states.length === 0) {

					localStorage[namespace] = JSON.stringify(store.getState());
				} else {

					states.forEach(function (state) {
						localStorage[namespace + "_" + state] = JSON.stringify(store.getState()[state]);
					});
				}
			};
		};
	};
}

/**
	Loads specified states from localstorage into the Redux state tree.

	PARAMETERS
	----------
	@config (Object) - 	Contains configuration options (leave blank to load entire state tree, if it was saved previously that is)
						Properties:
							states (Array of Strings, optional) - Parts of state tree to load e.g. ["user", "products"]
							namespace (String, optional) - Namespace required to retrieve your LocalStorage items, if any
							immutablejs (Boolean, optional) - If dealing with Immutable.js data structures, set this to true to load them correctly

	Usage examples:

		// load entire state tree - EASIEST OPTION
		load()

		// load specific parts of the state tree
		load({
			states: ["user", "products"]
		})

		// load the entire state tree which was previously saved with the namespace "my_cool_app"
		load({
			namespace: "my_cool_app"
		})

		// load specific parts of the state tree which use Immutable.js data structures
		load({
		    states: ["user", "products"],
		    immutablejs: true
		})

		// load specific parts of the state tree which was previously saved with the namespace "my_cool_app"
		load({
		    states: ["user", "products"],
		    namespace: "my_cool_app"
		})

*/

function load() {
	var _ref2 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	var _ref2$states = _ref2.states;
	var states = _ref2$states === undefined ? [] : _ref2$states;
	var _ref2$immutablejs = _ref2.immutablejs;
	var immutablejs = _ref2$immutablejs === undefined ? false : _ref2$immutablejs;
	var _ref2$namespace = _ref2.namespace;
	var namespace = _ref2$namespace === undefined ? NAMESPACE_DEFAULT : _ref2$namespace;

	var loadedState = {};

	if (states.length === 0) {

		if (localStorage[namespace]) {
			loadedState = JSON.parse(localStorage[namespace]);

			if (immutablejs) {
				for (var key in loadedState) {
					loadedState[key] = (0, _immutable.fromJS)(loadedState[key]);
				}
			}
		}
	} else {

		states.forEach(function (state) {

			if (localStorage[namespace + "_" + state]) {

				loadedState[state] = JSON.parse(localStorage[namespace + "_" + state]);
			}
		});

		if (immutablejs) {
			for (var _key in loadedState) {
				loadedState[_key] = (0, _immutable.fromJS)(loadedState[_key]);
			}
		}
	}

	return loadedState;
}

/**
	Combines multiple 'load' method calls to return a single state for use in Redux's createStore method.
	Use this when parts of the loading process need to be handled differently e.g. some parts of your state tree are immutable and some are not

	PARAMETERS
	----------
	@loads - 'load' method calls passed into this method as normal arguments

	Usage example:

		// load both vanilla JavaScript and Immutable.js parts of the state tree from LocalStorage
		combineLoads(
			load({ states: ["user"] }), // loading normal object
			load({ states: ["products"], immutablejs: true ) // this part of the state tree is an Immutable.js structure
		)

		// Load parts of the state tree saved with different namespaces
		combineLoads(
		    load({ states: ["user"], namespace: "account_stuff" }),
		    load({ states: ["products", "categories"], namespace: "site_stuff" )
		)
*/

function combineLoads() {

	var combinedLoad = {};

	for (var _len = arguments.length, loads = Array(_len), _key2 = 0; _key2 < _len; _key2++) {
		loads[_key2] = arguments[_key2];
	}

	loads.forEach(function (load) {
		for (var state in load) {
			combinedLoad[state] = load[state];
		}
	});

	return combinedLoad;
}

/**
	Clears all Redux state tree data from LocalStorage
	Remember to provide a namespace if you used one during the save process

	PARAMETERS
	----------
	@config (Object) - 	Contains configuration options (leave blank to clear entire state tree from LocalStorage, if it was saved without a namespace)
						Properties:
							namespace (String, optional) - Namespace that you used during the save process

	Usage example:

		// clear all Redux state tree data saved without a namespace
		clear()

		// clear Redux state tree data saved with a namespace
		clear({
			namespace: "my_cool_app"
		})
*/

function clear() {
	var _ref3 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	var _ref3$namespace = _ref3.namespace;
	var namespace = _ref3$namespace === undefined ? NAMESPACE_DEFAULT : _ref3$namespace;

	for (var key in localStorage) {

		// key starts with namespace
		if (key.slice(0, namespace.length) === namespace) {
			localStorage.removeItem(key);
		}
	}
}<commit_msg>New package build<commit_after>"use strict";

Object.defineProperty(exports, "__esModule", {
	value: true
});
exports.save = save;
exports.load = load;
exports.combineLoads = combineLoads;
exports.clear = clear;

var _immutable = require("immutable");

var NAMESPACE_DEFAULT = "redux_localstorage_simple";

/**
	Saves specified parts of the Redux state tree into localstorage
	Note: this is Redux middleware. Read this for an explanation:
	http://redux.js.org/docs/advanced/Middleware.html

	PARAMETERS
	----------
	@config (Object) - 	Contains configuration options (leave blank to save entire state tree to localstorage)

						Properties:
							states (Array of Strings, optional) - States to save e.g. ["user", "products"]
							namespace (String, optional) - Namespace to add before your LocalStorage items

	Usage examples:

		// save entire state tree - EASIEST OPTION
		save()

		// save specific parts of the state tree
		save({
			states: ["user", "products"]
		})

		// save the entire state tree under the namespace "my_cool_app". The key "my_cool_app" will appear in LocalStorage
		save({
			namespace: "my_cool_app"
		})

		// save specific parts of the state tree with the namespace "my_cool_app". The keys "my_cool_app_user" and "my_cool_app_products" will appear in LocalStorage
		save({
		    states: ["user", "products"],
		    namespace: "my_cool_app"
		})
*/

function save() {
	var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	var _ref$states = _ref.states;
	var states = _ref$states === undefined ? [] : _ref$states;
	var _ref$namespace = _ref.namespace;
	var namespace = _ref$namespace === undefined ? NAMESPACE_DEFAULT : _ref$namespace;

	return function (store) {
		return function (next) {
			return function (action) {

				next(action);

				if (states.length === 0) {

					localStorage[namespace] = JSON.stringify(store.getState());
				} else {

					states.forEach(function (state) {
						localStorage[namespace + "_" + state] = JSON.stringify(store.getState()[state]);
					});
				}
			};
		};
	};
}

/**
	Loads specified states from localstorage into the Redux state tree.

	PARAMETERS
	----------
	@config (Object) - 	Contains configuration options (leave blank to load entire state tree, if it was saved previously that is)
						Properties:
							states (Array of Strings, optional) - Parts of state tree to load e.g. ["user", "products"]
							namespace (String, optional) - Namespace required to retrieve your LocalStorage items, if any
							immutablejs (Boolean, optional) - If dealing with Immutable.js data structures, set this to true to load them correctly

	Usage examples:

		// load entire state tree - EASIEST OPTION
		load()

		// load specific parts of the state tree
		load({
			states: ["user", "products"]
		})

		// load the entire state tree which was previously saved with the namespace "my_cool_app"
		load({
			namespace: "my_cool_app"
		})

		// load specific parts of the state tree which use Immutable.js data structures
		load({
		    states: ["user", "products"],
		    immutablejs: true
		})

		// load specific parts of the state tree which was previously saved with the namespace "my_cool_app"
		load({
		    states: ["user", "products"],
		    namespace: "my_cool_app"
		})

*/

function load() {
	var _ref2 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	var _ref2$states = _ref2.states;
	var states = _ref2$states === undefined ? [] : _ref2$states;
	var _ref2$immutablejs = _ref2.immutablejs;
	var immutablejs = _ref2$immutablejs === undefined ? false : _ref2$immutablejs;
	var _ref2$namespace = _ref2.namespace;
	var namespace = _ref2$namespace === undefined ? NAMESPACE_DEFAULT : _ref2$namespace;

	var loadedState = {};

	if (states.length === 0) {

		if (localStorage[namespace]) {
			loadedState = JSON.parse(localStorage[namespace]);

			if (immutablejs) {
				loadedState = (0, _immutable.fromJS)(loadedState);
			}
		}
	} else {

		states.forEach(function (state) {

			if (localStorage[namespace + "_" + state]) {

				loadedState[state] = JSON.parse(localStorage[namespace + "_" + state]);
			}
		});

		if (immutablejs) {
			for (var key in loadedState) {
				loadedState[key] = (0, _immutable.fromJS)(loadedState[key]);
			}
		}
	}

	return loadedState;
}

/**
	Combines multiple 'load' method calls to return a single state for use in Redux's createStore method.
	Use this when parts of the loading process need to be handled differently e.g. some parts of your state tree are immutable and some are not

	PARAMETERS
	----------
	@loads - 'load' method calls passed into this method as normal arguments

	Usage example:

		// load both vanilla JavaScript and Immutable.js parts of the state tree from LocalStorage
		combineLoads(
			load({ states: ["user"] }), // loading normal object
			load({ states: ["products"], immutablejs: true ) // this part of the state tree is an Immutable.js structure
		)

		// Load parts of the state tree saved with different namespaces
		combineLoads(
		    load({ states: ["user"], namespace: "account_stuff" }),
		    load({ states: ["products", "categories"], namespace: "site_stuff" )
		)
*/

function combineLoads() {

	var combinedLoad = {};

	for (var _len = arguments.length, loads = Array(_len), _key = 0; _key < _len; _key++) {
		loads[_key] = arguments[_key];
	}

	loads.forEach(function (load) {
		for (var state in load) {
			combinedLoad[state] = load[state];
		}
	});

	return combinedLoad;
}

/**
	Clears all Redux state tree data from LocalStorage
	Remember to provide a namespace if you used one during the save process

	PARAMETERS
	----------
	@config (Object) - 	Contains configuration options (leave blank to clear entire state tree from LocalStorage, if it was saved without a namespace)
						Properties:
							namespace (String, optional) - Namespace that you used during the save process

	Usage example:

		// clear all Redux state tree data saved without a namespace
		clear()

		// clear Redux state tree data saved with a namespace
		clear({
			namespace: "my_cool_app"
		})
*/

function clear() {
	var _ref3 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

	var _ref3$namespace = _ref3.namespace;
	var namespace = _ref3$namespace === undefined ? NAMESPACE_DEFAULT : _ref3$namespace;

	for (var key in localStorage) {

		// key starts with namespace
		if (key.slice(0, namespace.length) === namespace) {
			localStorage.removeItem(key);
		}
	}
}<|endoftext|>


<commit_before>let {Component, View, SetModule, Inject, MeteorReactive} = angular2now;

SetModule('socially');

@Component({selector: 'parties-list'})
@View({
  templateUrl: () => {
    if (Meteor.isCordova) {
      return '/packages/socially-mobile/client/parties/parties-list/parties-list.html';
    }

    return '/packages/socially-browser/client/parties/parties-list/parties-list.html';
  }
})
@Inject('$mdDialog', '$filter')
@MeteorReactive
class partiesList {
  constructor($mdDialog, $filter) {
    this.perPage = 3;
    this.page = 1;
    this.sort = {
      name: 1
    };
    this.orderProperty = '1';
    this.searchText = '';

    this.helpers({
      parties: () => {
        return Parties.find({}, {sort: this.getReactively('sort')});
      },
      users: () => {
        return Meteor.users.find({});
      },
      partiesCount: () => {
        return Counts.get('numberOfParties');
      },
      isLoggedIn: () => {
        return Meteor.userId() !== null;
      },
      currentUserId: () => {
        return Meteor.userId();
      },
      images: () => {
        return Images.find({});
      }
    });

    this.subscribe('images');

    this.map = {
      center: {
        latitude: 45,
        longitude: -73
      },
      options: {
        maxZoom: 10,
        styles: [{
          "featureType": "administrative",
          "elementType": "labels.text.fill",
          "stylers": [{"color": "#444444"}]
        }, {
          "featureType": "landscape",
          "elementType": "all",
          "stylers": [{"color": "#f2f2f2"}]
        }, {
          "featureType": "poi",
          "elementType": "all",
          "stylers": [{"visibility": "off"}]
        }, {
          "featureType": "road",
          "elementType": "all",
          "stylers": [{"saturation": -100}, {"lightness": 45}]
        }, {
          "featureType": "road.highway",
          "elementType": "all",
          "stylers": [{"visibility": "simplified"}]
        }, {
          "featureType": "road.arterial",
          "elementType": "labels.icon",
          "stylers": [{"visibility": "off"}]
        }, {
          "featureType": "transit",
          "elementType": "all",
          "stylers": [{"visibility": "off"}]
        }, {
          "featureType": "water",
          "elementType": "all",
          "stylers": [{"color": "#46bcec"}, {"visibility": "on"}]
        }]
      },
      zoom: 8
    };

    this.subscribe('users');

    this.subscribe('parties', () => {
      return [
        {
          limit: parseInt(this.perPage),
          skip: parseInt((this.getReactively('page') - 1) * this.perPage),
          sort: this.getReactively('sort')
        },
        this.getReactively('searchText')
      ]
    });

    this.removeParty = (party) => {
      Parties.remove({_id: party._id});
    };

    this.pageChanged = (newPage) => {
      this.page = newPage;
    };

    this.updateSort = () => {
      this.sort = {
        name: parseInt(this.orderProperty)
      }
    };

    this.getPartyCreator = function (party) {
      if (!party) {
        return '';
      }

      let owner = Meteor.users.findOne(party.owner);

      if (!owner) {
        return 'nobody';
      }

      if (Meteor.userId() !== null && owner._id === Meteor.userId()) {
        return 'me';
      }

      return owner;
    };

    this.rsvp = (partyId, rsvp) => {
      Meteor.call('rsvp', partyId, rsvp, (error) => {
        if (error) {
          console.log('Oops, unable to rsvp!');
        }
        else {
          console.log('RSVP Done!');
        }
      });
    };

    this.getUserById = (userId) => {
      return Meteor.users.findOne(userId);
    };

    this.outstandingInvitations = (party) => {
      return _.filter(this.users, (user) => {
        return (_.contains(party.invited, user._id) && !_.findWhere(party.rsvps, {user: user._id}));
      });
    };

    this.openAddNewPartyModal = function () {
      $mdDialog.show({
        template: '<add-new-party-modal></add-new-party-modal>',
        clickOutsideToClose: true
      });
    };

    this.isRSVP = (rsvp, party) => {
      if (Meteor.userId() == null) {
        return false;
      }

      let rsvpIndex = party.myRsvpIndex;
      rsvpIndex = rsvpIndex || _.indexOf(_.pluck(party.rsvps, 'user'), Meteor.userId());

      if (rsvpIndex !== -1) {
        party.myRsvpIndex = rsvpIndex;
        return party.rsvps[rsvpIndex].rsvp === rsvp;
      }
    };

    this.getMainImage = (images, onlyUrl) => {
      if (images && images.length && images[0] && images[0]) {
        var url = $filter('filter')(this.images, {_id: images[0]})[0].url();

        if (onlyUrl) {
          return url;
        }

        return {
          'background-image': 'url("' + url + '")'
        }
      }
    };
  }
}<commit_msg>Step 23.8: Update parties list component to be real class<commit_after>let {Component, View, SetModule, Inject, MeteorReactive} = angular2now;

SetModule('socially');

@Component({selector: 'parties-list'})
@View({
  templateUrl: () => {
    if (Meteor.isCordova) {
      return '/packages/socially-mobile/client/parties/parties-list/parties-list.html';
    }

    return '/packages/socially-browser/client/parties/parties-list/parties-list.html';
  }
})
@Inject('$mdDialog', '$filter')
@MeteorReactive
class partiesList {
  constructor($mdDialog, $filter) {
    this.perPage = 3;
    this.page = 1;
    this.sort = {
      name: 1
    };
    this.orderProperty = '1';
    this.searchText = '';

    this.helpers({
      parties: this._partiesCollection,
      users: this._usersCollection,
      partiesCount: this._partiesCount,
      isLoggedIn: this._isLoggedIn,
      currentUserId: this._currentUserId,
      images: this._imagesCollection
    });

    this.subscribe('images');
    this.subscribe('users');
    this.subscribe('parties', this._partiesSubscription.bind(this));
    this.defineMapProperties();
  }

  _imagesCollection() {
    return Images.find({});
  }

  _currentUserId() {
    return Meteor.userId();
  }

  _isLoggedIn() {
    return Meteor.userId() !== null;
  }

  _partiesCount() {
    return Counts.get('numberOfParties');
  }

  _usersCollection() {
    return Meteor.users.find({});
  }

  _partiesCollection() {
    return Parties.find({}, {sort: this.getReactively('sort')});
  }

  _partiesSubscription() {
    return [
      {
        limit: parseInt(this.perPage),
        skip: parseInt((this.getReactively('page') - 1) * this.perPage),
        sort: this.getReactively('sort')
      },
      this.getReactively('searchText')
    ]
  }

  removeParty(party) {
    Parties.remove({_id: party._id});
  }

  pageChanged(newPage) {
    this.page = newPage;
  }

  updateSort() {
    this.sort = {
      name: parseInt(this.orderProperty)
    }
  }

  getPartyCreator(party) {
    if (!party) {
      return '';
    }

    let owner = Meteor.users.findOne(party.owner);

    if (!owner) {
      return 'nobody';
    }

    if (Meteor.userId() !== null && owner._id === Meteor.userId()) {
      return 'me';
    }

    return owner;
  }

  rsvp(partyId, rsvp) {
    Meteor.call('rsvp', partyId, rsvp, (error) => {
      if (error) {
        console.log('Oops, unable to rsvp!');
      }
      else {
        console.log('RSVP Done!');
      }
    });
  }

  getUserById(userId) {
    return Meteor.users.findOne(userId);
  }

  outstandingInvitations(party) {
    return _.filter(this.users, (user) => {
      return (_.contains(party.invited, user._id) && !_.findWhere(party.rsvps, {user: user._id}));
    });
  }

  openAddNewPartyModal() {
    $mdDialog.show({
      template: '<add-new-party-modal></add-new-party-modal>',
      clickOutsideToClose: true
    });
  }

  isRSVP(rsvp, party) {
    if (Meteor.userId() == null) {
      return false;
    }

    let rsvpIndex = party.myRsvpIndex;
    rsvpIndex = rsvpIndex || _.indexOf(_.pluck(party.rsvps, 'user'), Meteor.userId());

    if (rsvpIndex !== -1) {
      party.myRsvpIndex = rsvpIndex;

      return party.rsvps[rsvpIndex].rsvp === rsvp;
    }
  }

  getMainImage(images, onlyUrl) {
    if (images && images.length && images[0] && images[0]) {
      var url = $filter('filter')(this.images, {_id: images[0]})[0].url();

      if (onlyUrl) {
        return url;
      }

      return {
        'background-image': 'url("' + url + '")'
      }
    }
  }

  defineMapProperties() {
    this.map = {
      center: {
        latitude: 45,
        longitude: -73
      },
      options: {
        maxZoom: 10,
        styles: [{
          "featureType": "administrative",
          "elementType": "labels.text.fill",
          "stylers": [{"color": "#444444"}]
        }, {
          "featureType": "landscape",
          "elementType": "all",
          "stylers": [{"color": "#f2f2f2"}]
        }, {
          "featureType": "poi",
          "elementType": "all",
          "stylers": [{"visibility": "off"}]
        }, {
          "featureType": "road",
          "elementType": "all",
          "stylers": [{"saturation": -100}, {"lightness": 45}]
        }, {
          "featureType": "road.highway",
          "elementType": "all",
          "stylers": [{"visibility": "simplified"}]
        }, {
          "featureType": "road.arterial",
          "elementType": "labels.icon",
          "stylers": [{"visibility": "off"}]
        }, {
          "featureType": "transit",
          "elementType": "all",
          "stylers": [{"visibility": "off"}]
        }, {
          "featureType": "water",
          "elementType": "all",
          "stylers": [{"color": "#46bcec"}, {"visibility": "on"}]
        }]
      },
      zoom: 8
    };
  }
}<|endoftext|>


<commit_before>/*
Copyright (c) 2010, Paul Spencer <paul@pagameba.com>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

// module.exports = require("./build/Release/mapserver.node");
module.exports = require("./build/Debug/mapserver.node");<commit_msg>switch to Release to help Travis<commit_after>/*
Copyright (c) 2010, Paul Spencer <paul@pagameba.com>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

module.exports = require("./build/Release/mapserver.node");
// module.exports = require("./build/Debug/mapserver.node");<|endoftext|>


<commit_before>/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */

var tagHandler = {
  /* End */ 0: undefined,
  /* ShowFrame */ 1: undefined,
  /* DefineShape */ 2: DEFINE_SHAPE,
  /* PlaceObject */ 4: PLACE_OBJECT,
  /* RemoveObject */ 5: REMOVE_OBJECT,
  /* DefineBits */ 6: undefined,
  /* DefineButton */ 7: undefined,
  /* JPEGTables */ 8: undefined,
  /* SetBackgroundColor */ 9: RGB,
  /* DefineFont */ 10: undefined,
  /* DefineText */ 11: undefined,
  /* DoAction */ 12: DO_ACTION,
  /* DefineFontInfo */ 13: undefined,
  /* DefineSound */ 14: undefined,
  /* StartSound */ 15: undefined,
  /* DefineButtonSound */ 17: undefined,
  /* SoundStreamHead */ 18: undefined,
  /* SoundStreamBlock */ 19: undefined,
  /* DefineBitsLossless */ 20: undefined,
  /* DefineBitsJPEG2 */ 21: undefined,
  /* DefineShape2 */ 22: DEFINE_SHAPE,
  /* DefineButtonCxform */ 23: undefined,
  /* Protect */ 24: undefined,
  /* PlaceObject2 */ 26: PLACE_OBJECT2,
  /* RemoveObject2 */ 28: REMOVE_OBJECT,
  /* DefineShape3 */ 32: DEFINE_SHAPE,
  /* DefineText2 */ 33: undefined,
  /* DefineButton2 */ 34: undefined,
  /* DefineBitsJPEG3 */ 35: undefined,
  /* DefineBitsLossless2 */ 36: undefined,
  /* DefineEditText */ 37: undefined,
  /* DefineSprite */ 39: defineSprite,
  /* FrameLabel */ 43: undefined,
  /* SoundStreamHead2 */ 45: undefined,
  /* DefineMorphShape */ 46: DEFINE_SHAPE,
  /* DefineFont2 */ 48: undefined,
  /* ExportAssets */ 56: undefined,
  /* ImportAssets */ 57: undefined,
  /* EnableDebugger */ 58: undefined,
  /* DoInitAction */ 59: DO_ACTION,
  /* DefineVideoStream */ 60: undefined,
  /* VideoFrame */ 61: undefined,
  /* DefineFontInfo2 */ 62: undefined,
  /* EnableDebugger2 */ 64: undefined,
  /* ScriptLimits */ 65: undefined,
  /* SetTabIndex */ 66: undefined,
  /* FileAttributes */ 69: FILE_ATTRIBUTES,
  /* PlaceObject3 */ 70: PLACE_OBJECT2,
  /* ImportAssets2 */ 71: undefined,
  /* DefineFontAlignZones */ 73: undefined,
  /* CSMTextSettings */ 74: undefined,
  /* DefineFont3 */ 75: undefined,
  /* SymbolClass */ 76: undefined,
  /* Metadata */ 77: METADATA,
  /* DefineScalingGrid */ 78: undefined,
  /* DoABC */ 82: undefined,
  /* DefineShape4 */ 83: DEFINE_SHAPE,
  /* DefineMorphShape2 */ 84: DEFINE_SHAPE,
  /* DefineSceneAndFrameLabelData */ 86: undefined,
  /* DefineBinaryData */ 87: undefined,
  /* DefineFontName */ 88: undefined,
  /* StartSound2 */ 89: undefined,
  /* DefineBitsJPEG4 */ 90: undefined,
  /* DefineFont4 */ 91: undefined,
};
for (var tag in tagHandler) {
  var handler = tagHandler[tag];
  if (typeof handler === 'object')
    tagHandler[tag] = generate(handler, 'version', 'tag');
}

var readHeader = generate(MOVIE_HEADER);

function readTags(bytes, stream, version) {
  var tags = [];
  do {
    var tagAndLength = readUi16(bytes, stream);
    var tag = tagAndLength >> 6;
    var length = tagAndLength & 0x3f;
    if (length === 0x3f)
      length = readUi32(bytes, stream);
    var substream = stream.substream(stream.pos, stream.pos += length);
    var handler = tagHandler[tag];
    var item = handler ? handler(substream.bytes, substream, version, tag) : { };
    item.tag = tag;
    tags.push(item);
  } while (tag);
  return tags;
}

function defineSprite(bytes, stream, version) {
  return {
    id: readUi16(bytes, stream),
    frameCount: readUi16(bytes, stream),
    tags: readTags(bytes, stream, version)
  };
}

SWF.parse = function(buffer) {
  var stream = new Stream(buffer);
  var bytes = stream.bytes;
  var magic1 = bytes[0];
  var magic2 = bytes[1];
  var magic3 = bytes[2];
  var compressed = magic1 === 67;
  if (!((magic1 === 70 || compressed) && magic2 === 87 && magic3 === 83))
    fail('unsupported file format', 'parse');
  var version = bytes[3];
  stream.pos += 4;
  var fileLength = readUi32(bytes, stream);

  // TODO: make decompression progressively
  if (compressed) {
    var hdr = stream.getUint16(stream.pos);
    stream.pos += 2;
    if (hdr & 0x0f00 != 0x0800)
      fail('unknown compression method', 'inflate');
    if (hdr % 31)
      fail('bad FCHECK', 'inflate');
    if (hdr & 0x20)
      fail('FDICT bit set', 'inflate');
    var buffer = [];
    while (buffer.length < fileLength - 8)
      inflateBlock(stream.bytes, stream, buffer);
    stream = new Stream(new Uint8Array(buffer).buffer);
    bytes = stream.bytes;
  }

  var header = readHeader(bytes, stream);
  var tags = readTags(bytes, stream, version);
  return { version: version, header: header, tags: tags };
};
<commit_msg>fix check for compression method<commit_after>/* -*- mode: javascript; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */

var tagHandler = {
  /* End */ 0: undefined,
  /* ShowFrame */ 1: undefined,
  /* DefineShape */ 2: DEFINE_SHAPE,
  /* PlaceObject */ 4: PLACE_OBJECT,
  /* RemoveObject */ 5: REMOVE_OBJECT,
  /* DefineBits */ 6: undefined,
  /* DefineButton */ 7: undefined,
  /* JPEGTables */ 8: undefined,
  /* SetBackgroundColor */ 9: RGB,
  /* DefineFont */ 10: undefined,
  /* DefineText */ 11: undefined,
  /* DoAction */ 12: DO_ACTION,
  /* DefineFontInfo */ 13: undefined,
  /* DefineSound */ 14: undefined,
  /* StartSound */ 15: undefined,
  /* DefineButtonSound */ 17: undefined,
  /* SoundStreamHead */ 18: undefined,
  /* SoundStreamBlock */ 19: undefined,
  /* DefineBitsLossless */ 20: undefined,
  /* DefineBitsJPEG2 */ 21: undefined,
  /* DefineShape2 */ 22: DEFINE_SHAPE,
  /* DefineButtonCxform */ 23: undefined,
  /* Protect */ 24: undefined,
  /* PlaceObject2 */ 26: PLACE_OBJECT2,
  /* RemoveObject2 */ 28: REMOVE_OBJECT,
  /* DefineShape3 */ 32: DEFINE_SHAPE,
  /* DefineText2 */ 33: undefined,
  /* DefineButton2 */ 34: undefined,
  /* DefineBitsJPEG3 */ 35: undefined,
  /* DefineBitsLossless2 */ 36: undefined,
  /* DefineEditText */ 37: undefined,
  /* DefineSprite */ 39: defineSprite,
  /* FrameLabel */ 43: undefined,
  /* SoundStreamHead2 */ 45: undefined,
  /* DefineMorphShape */ 46: DEFINE_SHAPE,
  /* DefineFont2 */ 48: undefined,
  /* ExportAssets */ 56: undefined,
  /* ImportAssets */ 57: undefined,
  /* EnableDebugger */ 58: undefined,
  /* DoInitAction */ 59: DO_ACTION,
  /* DefineVideoStream */ 60: undefined,
  /* VideoFrame */ 61: undefined,
  /* DefineFontInfo2 */ 62: undefined,
  /* EnableDebugger2 */ 64: undefined,
  /* ScriptLimits */ 65: undefined,
  /* SetTabIndex */ 66: undefined,
  /* FileAttributes */ 69: FILE_ATTRIBUTES,
  /* PlaceObject3 */ 70: PLACE_OBJECT2,
  /* ImportAssets2 */ 71: undefined,
  /* DefineFontAlignZones */ 73: undefined,
  /* CSMTextSettings */ 74: undefined,
  /* DefineFont3 */ 75: undefined,
  /* SymbolClass */ 76: undefined,
  /* Metadata */ 77: METADATA,
  /* DefineScalingGrid */ 78: undefined,
  /* DoABC */ 82: undefined,
  /* DefineShape4 */ 83: DEFINE_SHAPE,
  /* DefineMorphShape2 */ 84: DEFINE_SHAPE,
  /* DefineSceneAndFrameLabelData */ 86: undefined,
  /* DefineBinaryData */ 87: undefined,
  /* DefineFontName */ 88: undefined,
  /* StartSound2 */ 89: undefined,
  /* DefineBitsJPEG4 */ 90: undefined,
  /* DefineFont4 */ 91: undefined,
};
for (var tag in tagHandler) {
  var handler = tagHandler[tag];
  if (typeof handler === 'object')
    tagHandler[tag] = generate(handler, 'version', 'tag');
}

var readHeader = generate(MOVIE_HEADER);

function readTags(bytes, stream, version) {
  var tags = [];
  do {
    var tagAndLength = readUi16(bytes, stream);
    var tag = tagAndLength >> 6;
    var length = tagAndLength & 0x3f;
    if (length === 0x3f)
      length = readUi32(bytes, stream);
    var substream = stream.substream(stream.pos, stream.pos += length);
    var handler = tagHandler[tag];
    var item = handler ? handler(substream.bytes, substream, version, tag) : { };
    item.tag = tag;
    tags.push(item);
  } while (tag);
  return tags;
}

function defineSprite(bytes, stream, version) {
  return {
    id: readUi16(bytes, stream),
    frameCount: readUi16(bytes, stream),
    tags: readTags(bytes, stream, version)
  };
}

SWF.parse = function(buffer) {
  var stream = new Stream(buffer);
  var bytes = stream.bytes;
  var magic1 = bytes[0];
  var magic2 = bytes[1];
  var magic3 = bytes[2];
  var compressed = magic1 === 67;
  if (!((magic1 === 70 || compressed) && magic2 === 87 && magic3 === 83))
    fail('unsupported file format', 'parse');
  var version = bytes[3];
  stream.pos += 4;
  var fileLength = readUi32(bytes, stream);

  // TODO: make decompression progressively
    if (compressed) {
      var hdr = stream.getUint16(stream.pos);
    stream.pos += 2;
    if ((hdr & 0x0f00) !== 0x0800)
      fail('unknown compression method', 'inflate');
    if (hdr % 31)
      fail('bad FCHECK', 'inflate');
    if (hdr & 0x20)
      fail('FDICT bit set', 'inflate');
    var buffer = [];
    while (buffer.length < fileLength - 8)
      inflateBlock(stream.bytes, stream, buffer);
    stream = new Stream(new Uint8Array(buffer).buffer);
    bytes = stream.bytes;
  }

  var header = readHeader(bytes, stream);
  var tags = readTags(bytes, stream, version);
  return { version: version, header: header, tags: tags };
};
<|endoftext|>


<commit_before>$(function() {
  Chachara.ChatView = Backbone.View.extend({
    template: _.template($("#chat-view-template").html()),

    initialize: function(options) {
      _.bindAll(this, "render", "onInput", "displayMessage");

      this.shortname = options.room.split("@")[0];
      this.id = "pane-" + this.shortname;
      this.node = "#" + this.id;
    },

    render: function() {
      var template = $(this.template()).attr("id", this.id);
      $(this.el).append(template);

      $(this.node).find("span.current").text("#"+this.shortname);
      $(this.node).find(".chatinput").keypress(this.onInput);
      $(this.node).find(".chatinput").focus();
      $(this.node).find(".primary-pane").append("
Joined " + this.options.room + "
")
    },

    show: function() {
      $(this.node).show();
      $(this.node).find(".primary-pane").scrollTop(100000);
      $(this.node).find(".secondary-pane").scrollTop(100000);
      $(this.node).find(".chatinput").focus();
    },

    hide: function() {
      $(this.node).hide();
    },

    displayPresence: function(data) {
      var fromParts = data.from.split("/");
      var room      = fromParts[0];
      var who       = fromParts[1];
      var status    = data.status

      if (this.options.room === room) {
        var userAction = (status == "online") ? "joined" : "left";
        $(this.node).find(".primary-pane ul")
           .append("
" + who + "" + userAction + " the room
")
           .scrollTop(100000);
      }
    },

    displayMessage: function(message) {
      var fromParts = message.from.split("/");
      var room = fromParts[0].split("@")[0];
      var name = fromParts[1];
      var body = $("
").text(message.body).html();
      var html = message.html;

      body = body.replace(/\n/g, "
");
      body = body.replace(/\s/g, " ");

      if (this.options.room === message.room) {
        node = $(this.node).find(".primary-pane ul").append("
" + name + "" + body + "
");

        if (message.html)
          node.append("
" + name + "" + html + "
");

        node.scrollTop(100000);
      }

      $(this.node)
        .find(".secondary-pane ul")
        .append("
#" + room + " " + name + " " + body + "
")
        .scrollTop(100000);
    },

    displayEmbedly: function(message) {
      var fromParts = message.from.split("/");
      var room = fromParts[0].split("@")[0];
      var name = fromParts[1];
      var html = message.html;

      if (this.options.room === message.room) {
        node = $(this.node).find(".primary-pane ul").append("
" + name + "" + html + "
");
        node.scrollTop(100000);
      }
    },

    onInput: function(e) {
      if (e.which == '13') {
        var str = $(e.target).val();
        if (str.length > 0) {
          var data = {
            type: "message",
            body: str,
            room: this.options.room
          };
          this.trigger("input", data);
          $(this.node).find(".chatinput").val("");
        }
      }

      if (e.ctrlKey && e.which == '44') { /* < */
        e.stopPropagation();
        this.trigger("prevpane", this);
      }

      if (e.ctrlKey && e.which == '46') { /* > */
        e.stopPropagation();
        this.trigger("nextpane", this);
      }
    }
  })
});
<commit_msg>Fixes issue where [Joined NN] is persistent at the bottom<commit_after>$(function() {
  Chachara.ChatView = Backbone.View.extend({
    template: _.template($("#chat-view-template").html()),

    initialize: function(options) {
      _.bindAll(this, "render", "onInput", "displayMessage");

      this.shortname = options.room.split("@")[0];
      this.id = "pane-" + this.shortname;
      this.node = "#" + this.id;
    },

    render: function() {
      var template = $(this.template()).attr("id", this.id);
      $(this.el).append(template);

      $(this.node).find("span.current").text("#"+this.shortname);
      $(this.node).find(".chatinput").keypress(this.onInput);
      $(this.node).find(".chatinput").focus();
      $(this.node).find(".primary-pane ul").append("
Joined " + this.options.room + "
")
    },

    show: function() {
      $(this.node).show();
      $(this.node).find(".primary-pane").scrollTop(100000);
      $(this.node).find(".secondary-pane").scrollTop(100000);
      $(this.node).find(".chatinput").focus();
    },

    hide: function() {
      $(this.node).hide();
    },

    displayPresence: function(data) {
      var fromParts = data.from.split("/");
      var room      = fromParts[0];
      var who       = fromParts[1];
      var status    = data.status

      if (this.options.room === room) {
        var userAction = (status == "online") ? "joined" : "left";
        $(this.node).find(".primary-pane ul")
           .append("
" + who + "" + userAction + " the room
")
           .scrollTop(100000);
      }
    },

    displayMessage: function(message) {
      var fromParts = message.from.split("/");
      var room = fromParts[0].split("@")[0];
      var name = fromParts[1];
      var body = $("
").text(message.body).html();
      var html = message.html;

      body = body.replace(/\n/g, "
");
      body = body.replace(/\s/g, " ");

      if (this.options.room === message.room) {
        node = $(this.node).find(".primary-pane ul").append("
" + name + "" + body + "
");

        if (message.html)
          node.append("
" + name + "" + html + "
");

        node.scrollTop(100000);
      }

      $(this.node)
        .find(".secondary-pane ul")
        .append("
#" + room + " " + name + " " + body + "
")
        .scrollTop(100000);
    },

    displayEmbedly: function(message) {
      var fromParts = message.from.split("/");
      var room = fromParts[0].split("@")[0];
      var name = fromParts[1];
      var html = message.html;

      if (this.options.room === message.room) {
        node = $(this.node).find(".primary-pane ul").append("
" + name + "" + html + "
");
        node.scrollTop(100000);
      }
    },

    onInput: function(e) {
      if (e.which == '13') {
        var str = $(e.target).val();
        if (str.length > 0) {
          var data = {
            type: "message",
            body: str,
            room: this.options.room
          };
          this.trigger("input", data);
          $(this.node).find(".chatinput").val("");
        }
      }

      if (e.ctrlKey && e.which == '44') { /* < */
        e.stopPropagation();
        this.trigger("prevpane", this);
      }

      if (e.ctrlKey && e.which == '46') { /* > */
        e.stopPropagation();
        this.trigger("nextpane", this);
      }
    }
  })
});
<|endoftext|>