<commit_before>/*
Copyright 2015, 2016 OpenMarket 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.
*/

'use strict';

import Matrix from 'matrix-js-sdk';
import utils from 'matrix-js-sdk/lib/utils';
import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline';
import EventTimelineSet from 'matrix-js-sdk/lib/models/event-timeline-set';

const localStorage = window.localStorage;

interface MatrixClientCreds {
    homeserverUrl: string,
    identityServerUrl: string,
    userId: string,
    deviceId: string,
    accessToken: string,
    guest: boolean,
}

/**
 * Wrapper object for handling the js-sdk Matrix Client object in the react-sdk
 * Handles the creation/initialisation of client objects.
 * This module provides a singleton instance of this class so the 'current'
 * Matrix Client object is available easily.
 */
class MatrixClientPeg {
    constructor() {
        this.matrixClient = null;

        // These are the default options used when when the
        // client is started in 'start'. These can be altered
        // at any time up to after the 'will_start_client'
        // event is finished processing.
        this.opts = {
            initialSyncLimit: 20,
        };
    }

    get(): MatrixClient {
        return this.matrixClient;
    }

    unset() {
        this.matrixClient = null;
    }

    /**
     * Replace this MatrixClientPeg's client with a client instance that has
     * Home Server / Identity Server URLs and active credentials
     */
    replaceUsingCreds(creds: MatrixClientCreds) {
        this._createClient(creds);
    }

    start() {
        const opts = utils.deepCopy(this.opts);
        // the react sdk doesn't work without this, so don't allow
        opts.pendingEventOrdering = "detached";
        this.get().startClient(opts);
    }

    getCredentials(): MatrixClientCreds {
        return {
            homeserverUrl: this.matrixClient.baseUrl,
            identityServerUrl: this.matrixClient.idBaseUrl,
            userId: this.matrixClient.credentials.userId,
            deviceId: this.matrixClient.getDeviceId(),
            accessToken: this.matrixClient.getAccessToken(),
            guest: this.matrixClient.isGuest(),
        };
    }

    _createClient(creds: MatrixClientCreds) {
        var opts = {
            baseUrl: creds.homeserverUrl,
            idBaseUrl: creds.identityServerUrl,
            accessToken: creds.accessToken,
            userId: creds.userId,
            deviceId: creds.deviceId,
            timelineSupport: true,
        };

        if (localStorage) {
            opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage);
        }

        this.matrixClient = Matrix.createClient(opts);

        // we're going to add eventlisteners for each matrix event tile, so the
        // potential number of event listeners is quite high.
        this.matrixClient.setMaxListeners(500);

        this.matrixClient.setGuest(Boolean(creds.guest));

        var notifTimelineSet = new EventTimelineSet(null, {
            timelineSupport: true
        });
        // XXX: what is our initial pagination token?! it somehow needs to be synchronised with /sync.
        notifTimelineSet.getLiveTimeline().setPaginationToken("", EventTimeline.BACKWARDS);
        this.matrixClient.setNotifTimelineSet(notifTimelineSet);
    }
}

if (!global.mxMatrixClientPeg) {
    global.mxMatrixClientPeg = new MatrixClientPeg();
}
module.exports = global.mxMatrixClientPeg;
<commit_msg>Add 'getHomeServerName' util to client peg<commit_after>/*
Copyright 2015, 2016 OpenMarket 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.
*/

'use strict';

import Matrix from 'matrix-js-sdk';
import utils from 'matrix-js-sdk/lib/utils';
import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline';
import EventTimelineSet from 'matrix-js-sdk/lib/models/event-timeline-set';

const localStorage = window.localStorage;

interface MatrixClientCreds {
    homeserverUrl: string,
    identityServerUrl: string,
    userId: string,
    deviceId: string,
    accessToken: string,
    guest: boolean,
}

/**
 * Wrapper object for handling the js-sdk Matrix Client object in the react-sdk
 * Handles the creation/initialisation of client objects.
 * This module provides a singleton instance of this class so the 'current'
 * Matrix Client object is available easily.
 */
class MatrixClientPeg {
    constructor() {
        this.matrixClient = null;

        // These are the default options used when when the
        // client is started in 'start'. These can be altered
        // at any time up to after the 'will_start_client'
        // event is finished processing.
        this.opts = {
            initialSyncLimit: 20,
        };
    }

    get(): MatrixClient {
        return this.matrixClient;
    }

    unset() {
        this.matrixClient = null;
    }

    /**
     * Replace this MatrixClientPeg's client with a client instance that has
     * Home Server / Identity Server URLs and active credentials
     */
    replaceUsingCreds(creds: MatrixClientCreds) {
        this._createClient(creds);
    }

    start() {
        const opts = utils.deepCopy(this.opts);
        // the react sdk doesn't work without this, so don't allow
        opts.pendingEventOrdering = "detached";
        this.get().startClient(opts);
    }

    getCredentials(): MatrixClientCreds {
        return {
            homeserverUrl: this.matrixClient.baseUrl,
            identityServerUrl: this.matrixClient.idBaseUrl,
            userId: this.matrixClient.credentials.userId,
            deviceId: this.matrixClient.getDeviceId(),
            accessToken: this.matrixClient.getAccessToken(),
            guest: this.matrixClient.isGuest(),
        };
    }

    /**
     * Return the server name of the user's home server
     * Throws an error if unable to deduce the home server name
     * (eg. if the user is not logged in)
     */
    getHomeServerName() {
        const matches = /^@.+:(.+)$/.exec(this.matrixClient.credentials.userId);
        if (matches === null || matches.length < 1) {
            throw new Error("Failed to derive home server name fro user ID!");
        }
        return matches[1];
    }

    _createClient(creds: MatrixClientCreds) {
        var opts = {
            baseUrl: creds.homeserverUrl,
            idBaseUrl: creds.identityServerUrl,
            accessToken: creds.accessToken,
            userId: creds.userId,
            deviceId: creds.deviceId,
            timelineSupport: true,
        };

        if (localStorage) {
            opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage);
        }

        this.matrixClient = Matrix.createClient(opts);

        // we're going to add eventlisteners for each matrix event tile, so the
        // potential number of event listeners is quite high.
        this.matrixClient.setMaxListeners(500);

        this.matrixClient.setGuest(Boolean(creds.guest));

        var notifTimelineSet = new EventTimelineSet(null, {
            timelineSupport: true
        });
        // XXX: what is our initial pagination token?! it somehow needs to be synchronised with /sync.
        notifTimelineSet.getLiveTimeline().setPaginationToken("", EventTimeline.BACKWARDS);
        this.matrixClient.setNotifTimelineSet(notifTimelineSet);
    }
}

if (!global.mxMatrixClientPeg) {
    global.mxMatrixClientPeg = new MatrixClientPeg();
}
module.exports = global.mxMatrixClientPeg;
<|endoftext|>


<commit_before>var container, stats, containerObj;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;

// detect if webgl is needed and available
if( !Detector.webgl ){
	Detector.addGetWebGLMessage();
}else{
	init();
	animate();
}

/**
 * Build ui with Data.GUI
*/
function buildGui(parameters, callback)
{
	urlCacheInit	= function(opts){
		if( !window.location.hash )	return
		var hashStr	= window.location.hash.substring(1);
		var urlParams	= JSON.parse(decodeURIComponent(hashStr));
console.log("urlParams", urlParams)
		Object.keys(urlParams).forEach(function(key){
			parameters[key]	= urlParams[key];
		}.bind(this));
console.log("parameters post cache init", parameters)
	}
	urlCacheUpdate	= function(opts){
		var urlParams	= {};
		if( window.location.hash ){
			urlParams	= JSON.parse(decodeURIComponent(location.hash.substring(1)));
		}

		Object.keys(opts).forEach(function(key){
			urlParams[key]	= opts[key];
		}.bind(this));

		window.location.hash	= '#'+encodeURIComponent(JSON.stringify(urlParams));
	}

	// Notice this belongs to the DAT.GUI class (uppercase)
	// and not an instance thereof.
	DAT.GUI.autoPlace = false;

	var change	= function(){
		// get parameters values from cache if needed
		urlCacheUpdate(parameters)
		callback && callback(parameters)
	};

	// get parameters values from cache if needed
	urlCacheInit(parameters)
	// init the cache with current parameters values
	urlCacheUpdate(parameters)

	var gui1 = new DAT.GUI({
		height	: 17 * 32 - 1
	});
	gui1.domElement.style.position	= 'absolute';
	gui1.domElement.style.top	= '0px';
	gui1.domElement.style.right	= '0px';
	gui1.domElement.style['z-index']= '9999';
	document.body.appendChild(gui1.domElement);

	gui1.add(parameters, 'emitRate').min(1).max(100)		.onFinishChange(change);
	gui1.add(parameters, 'timeToLive').min(200).max(5*1000)		.onFinishChange(change);

	gui1.add(parameters, 'originZaValue').min(-Math.PI).max(Math.PI).onFinishChange(change);
	gui1.add(parameters, 'originZaRange').min(0).max(Math.PI).onFinishChange(change);

	gui1.add(parameters, 'originZhValue').min(0).max(1)		.onFinishChange(change);
	gui1.add(parameters, 'originZhRange').min(0).max(0.5)		.onFinishChange(change);

	gui1.add(parameters, 'originRadiusValue').min(0.01).max(100)	.onFinishChange(change);
	gui1.add(parameters, 'originRadiusRange').min(0).max(30)	.onFinishChange(change);

	gui1.add(parameters, 'speedValue').min(0.2).max(2)		.onFinishChange(change);
	gui1.add(parameters, 'speedRange').min(0).max(2)		.onFinishChange(change);

	gui1.add(parameters, 'gravity').min(0).max(0.2)			.onFinishChange(change);

	gui1.add(parameters, 'opacitySrc').min(0.0).max(1.0)		.onFinishChange(change);
	gui1.add(parameters, 'opacityInc').min(-0.05).max(0)		.onFinishChange(change);

	gui1.add(parameters, 'sizeSrc').min(2).max(128)			.onFinishChange(change);
	gui1.add(parameters, 'sizeInc').min(-1).max(1)			.onFinishChange(change);

	gui1.add(parameters, 'rotationSrc').min(0.0).max(2*Math.PI)	.onFinishChange(change);
	gui1.add(parameters, 'rotationInc').min(-0.05).max(0.05)	.onFinishChange(change);

(function(){
	var gui2	= new DAT.GUI({
		height	: 7 * 32 - 1
	});
	gui2.domElement.style.position	= 'absolute';
	gui2.domElement.style.top	= '0px';
	gui2.domElement.style.left	= '0px';
	gui1.domElement.style['z-index']= '9999';
	document.body.appendChild(gui2.domElement);

	gui2.add(parameters.color, 'r').name('colorR')		.min(0.0).max(1.0).onChange(change);
	gui2.add(parameters.color, 'g').name('colorG')		.min(0.0).max(1.0).onChange(change);
	gui2.add(parameters.color, 'b').name('colorB')		.min(0.0).max(1.0).onChange(change);
	gui2.add(parameters.colorInc, 'r').name('colorIncR')	.min(-0.1).max(0.1).onChange(change);
	gui2.add(parameters.colorInc, 'g').name('colorIncG')	.min(-0.1).max(0.1).onChange(change);
	gui2.add(parameters.colorInc, 'b').name('colorIncB')	.min(-0.1).max(0.1).onChange(change);

	gui2.add(parameters, 'textureUrl').options({
		"flare"			: "images/lensFlare/Flare1.png",
		"smoke"			: "images/osg-data/smoke.png",
		"ball"			: "images/ball.png",

		"purple_particle"	: "images/tremulous/lasgun/purple_particle.jpg",
		"lcannon1"		: "images/tremulous/lcannon/primary_1.jpg",

		"shine"			: "images/lensFlare/Shine1.png",
		"continous_smoke"	: "images/osg-data/continous_smoke.png",
		"reflect"		: "images/osg-data/reflect.png"
	}).onChange(function(){
		console.log("texture change", containerObj)

		scene.removeChild(containerObj);
		containerObj	= new THREE.Object3D();
		scene.addChild(containerObj);

		// define the containerObj of all the particle
		Emitter	= new THREEx.Particle.Emitter(parameters);
		containerObj.addChild( Emitter.container() );

	});

}());

}

function init()
{
	// create the container
	container = document.createElement( 'div' );
	document.body.appendChild( container );

	// init the renderer
	renderer	= new THREE.WebGLRenderer({
		antialias		: true,
		preserveDrawingBuffer	: true
	});
	//renderer.sortObjects = true;
	renderer.setSize( window.innerWidth, window.innerHeight );
	container.appendChild( renderer.domElement );

	// create the Camera
	if( false ){
		camera = new THREE.Camera(30, window.innerWidth / window.innerHeight, 1, 100000 );
		camera.position.z	= 400;
	}else{
		camera = new THREE.TrackballCamera({
			minDistance	: 10,
			maxDistance	: 500,

			fov		: 25,
			aspect		: window.innerWidth / window.innerHeight,
			near		: 5,
			far		: 1e7,

			rotateSpeed	: 1.0,
			zoomSpeed	: 1.2,
			panSpeed	: 0.2,

			noZoom	: false,
			noPan	: false,

			staticMoving: false,
			dynamicDampingFactor: 0.3,

			keys	: [ 65, 83, 68 ], // [ rotateKey, zoomKey, panKey ],

			domElement: renderer.domElement,
		});
		camera.position.z	= 100;
	}

	// call THREEx.WindowResize
	THREEx.WindowResize(renderer, camera);
	// support screenshot
	THREEx.Screenshot.bindKey(renderer);

	// FIXME failed attemps
	// - seems to fail if the data url
	THREEx.ImageDrop(renderer, function(image){
		var material		= Emitter.container().materials[0];
		var uniforms		= material.uniforms;
		var texture		= uniforms['texture'].texture;
		//texture.image.src	= image.src;
		texture.image		= image;
		texture.needsUpdate	= true;
		//uniforms['texture'].needsUpdate	= true;
console.log("object3d", texture, "uniforms", uniforms['texture'], "newimage", image, "oldimage", texture.image);
	})

	// build the scene
	scene = new THREE.Scene();

	// define the containerObj of all the particle
	containerObj	= new THREE.Object3D();
	scene.addChild(containerObj)

	// parameters
	var parameters	= {
		nbItems		: 10000,
		textureUrl	: "images/lensFlare/Flare1.png",

		emitRate	: 30,
		timeToLive	: 2000,

		originZaValue	: Math.PI/2,
		originZaRange	: 30 * Math.PI/180,
		originZhValue	: 0,
		originZhRange	: 0,
		originRadiusValue	: 0.5,
		originRadiusRange	: 0.5,

		speedValue	: 1.5,
		speedRange	: 0.5,

		gravity		: 0.05,

		color		: { r: 1.0,  g: 0.33, b: 0.0},
		colorInc	: { r: 0,  g: 0, b: 0},

		opacitySrc	: 1.0,
		opacityInc	: 0.0,

		sizeSrc		: 16.0,
		sizeInc		:  0.0,

		rotationSrc	:  0.0,
		rotationInc	:  0.0
	};
	buildGui(parameters);

	// build the emitter
	Emitter	= new THREEx.Particle.Emitter(parameters);
	containerObj.addChild( Emitter.container() );

	// init the Stats
	stats	= new Stats();
	stats.domElement.style.position	= 'absolute';
	stats.domElement.style.bottom	= '0px';
	container.appendChild( stats.domElement );

	// listen to mousemove to animate the scene
	document.addEventListener( 'mousemove', onDocumentMouseMove, false );
}

//

function onDocumentMouseMove(event)
{
	mouseX = event.clientX - window.innerWidth / 2;
	mouseY = event.clientY - window.innerHeight / 2;
}

//
function animate() {

	requestAnimationFrame( animate );

	Emitter.update();

	render();
	stats.update();
}

function render()
{
	// move the camera
	if( false ){
		camera.position.x += (   mouseX - camera.position.x ) * .05;
		camera.position.y += ( - mouseY - camera.position.y ) * .05;
	}

	// animate the cube
	if( false ){
		containerObj.rotation.x += 0.4*0.02;
		containerObj.rotation.y += 0.4*0.0225;
		containerObj.rotation.z += 0.4*0.0175;
	}

	// actually render the scene
	renderer.render( scene, camera );
}
<commit_msg>particle-emitter: made gravity negative possible + hide dat.gui if loaded in iframe (for embeddable)<commit_after>var container, stats, containerObj;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;

// detect if webgl is needed and available
if( !Detector.webgl ){
	Detector.addGetWebGLMessage();
}else{
	init();
	animate();
}

/**
 * Build ui with Data.GUI
*/
function buildGui(parameters, callback)
{
	urlCacheInit	= function(opts){
		if( !window.location.hash )	return
		var hashStr	= window.location.hash.substring(1);
		var urlParams	= JSON.parse(decodeURIComponent(hashStr));
console.log("urlParams", urlParams)
		Object.keys(urlParams).forEach(function(key){
			parameters[key]	= urlParams[key];
		}.bind(this));
console.log("parameters post cache init", parameters)
	}
	urlCacheUpdate	= function(opts){
		var urlParams	= {};
		if( window.location.hash ){
			urlParams	= JSON.parse(decodeURIComponent(location.hash.substring(1)));
		}

		Object.keys(opts).forEach(function(key){
			urlParams[key]	= opts[key];
		}.bind(this));

		window.location.hash	= '#'+encodeURIComponent(JSON.stringify(urlParams));
	}

	// Notice this belongs to the DAT.GUI class (uppercase)
	// and not an instance thereof.
	DAT.GUI.autoPlace = false;

	var change	= function(){
		// get parameters values from cache if needed
		urlCacheUpdate(parameters)
		callback && callback(parameters)
	};

	// get parameters values from cache if needed
	urlCacheInit(parameters)
	// init the cache with current parameters values
	urlCacheUpdate(parameters)

	var gui1 = new DAT.GUI({
		height	: 17 * 32 - 1
	});
	gui1.domElement.style.position	= 'absolute';
	gui1.domElement.style.top	= '0px';
	gui1.domElement.style.right	= '0px';
	gui1.domElement.style['z-index']= '9999';
	document.body.appendChild(gui1.domElement);

	gui1.add(parameters, 'emitRate').min(1).max(100)		.onFinishChange(change);
	gui1.add(parameters, 'timeToLive').min(200).max(5*1000)		.onFinishChange(change);

	gui1.add(parameters, 'originZaValue').min(-Math.PI).max(Math.PI).onFinishChange(change);
	gui1.add(parameters, 'originZaRange').min(0).max(Math.PI).onFinishChange(change);

	gui1.add(parameters, 'originZhValue').min(0).max(1)		.onFinishChange(change);
	gui1.add(parameters, 'originZhRange').min(0).max(0.5)		.onFinishChange(change);

	gui1.add(parameters, 'originRadiusValue').min(0.01).max(100)	.onFinishChange(change);
	gui1.add(parameters, 'originRadiusRange').min(0).max(30)	.onFinishChange(change);

	gui1.add(parameters, 'speedValue').min(0.2).max(2)		.onFinishChange(change);
	gui1.add(parameters, 'speedRange').min(0).max(2)		.onFinishChange(change);

	gui1.add(parameters, 'gravity').min(-0.2).max(0.2)		.onFinishChange(change);

	gui1.add(parameters, 'opacitySrc').min(0.0).max(1.0)		.onFinishChange(change);
	gui1.add(parameters, 'opacityInc').min(-0.05).max(0)		.onFinishChange(change);

	gui1.add(parameters, 'sizeSrc').min(2).max(128)			.onFinishChange(change);
	gui1.add(parameters, 'sizeInc').min(-1).max(1)			.onFinishChange(change);

	gui1.add(parameters, 'rotationSrc').min(0.0).max(2*Math.PI)	.onFinishChange(change);
	gui1.add(parameters, 'rotationInc').min(-0.05).max(0.05)	.onFinishChange(change);

(function(){
	var gui2	= new DAT.GUI({
		height	: 7 * 32 - 1
	});
	gui2.domElement.style.position	= 'absolute';
	gui2.domElement.style.top	= '0px';
	gui2.domElement.style.left	= '0px';
	gui1.domElement.style['z-index']= '9999';
	document.body.appendChild(gui2.domElement);

	gui2.add(parameters.color, 'r').name('colorR')		.min(0.0).max(1.0).onChange(change);
	gui2.add(parameters.color, 'g').name('colorG')		.min(0.0).max(1.0).onChange(change);
	gui2.add(parameters.color, 'b').name('colorB')		.min(0.0).max(1.0).onChange(change);
	gui2.add(parameters.colorInc, 'r').name('colorIncR')	.min(-0.1).max(0.1).onChange(change);
	gui2.add(parameters.colorInc, 'g').name('colorIncG')	.min(-0.1).max(0.1).onChange(change);
	gui2.add(parameters.colorInc, 'b').name('colorIncB')	.min(-0.1).max(0.1).onChange(change);

	gui2.add(parameters, 'textureUrl').options({
		"flare"			: "images/lensFlare/Flare1.png",
		"smoke"			: "images/osg-data/smoke.png",
		"ball"			: "images/ball.png",

		"purple_particle"	: "images/tremulous/lasgun/purple_particle.jpg",
		"lcannon1"		: "images/tremulous/lcannon/primary_1.jpg",

		"shine"			: "images/lensFlare/Shine1.png",
		"continous_smoke"	: "images/osg-data/continous_smoke.png",
		"reflect"		: "images/osg-data/reflect.png"
	}).onChange(function(){
		console.log("texture change", containerObj)

		scene.removeChild(containerObj);
		containerObj	= new THREE.Object3D();
		scene.addChild(containerObj);

		// define the containerObj of all the particle
		Emitter	= new THREEx.Particle.Emitter(parameters);
		containerObj.addChild( Emitter.container() );

	});
}());

	// hide DAT.GUI if this page is loaded in a iframe
	var inIFrame	= (window.location != window.parent.location) ? true : false;
	if( inIFrame )	DAT.GUI.toggleHide();

}

function init()
{
	// create the container
	container = document.createElement( 'div' );
	document.body.appendChild( container );

	// init the renderer
	renderer	= new THREE.WebGLRenderer({
		antialias		: true,
		preserveDrawingBuffer	: true
	});
	//renderer.sortObjects = true;
	renderer.setSize( window.innerWidth, window.innerHeight );
	container.appendChild( renderer.domElement );

	// create the Camera
	if( false ){
		camera = new THREE.Camera(30, window.innerWidth / window.innerHeight, 1, 100000 );
		camera.position.z	= 400;
	}else{
		camera = new THREE.TrackballCamera({
			minDistance	: 10,
			maxDistance	: 500,

			fov		: 25,
			aspect		: window.innerWidth / window.innerHeight,
			near		: 5,
			far		: 1e7,

			rotateSpeed	: 1.0,
			zoomSpeed	: 1.2,
			panSpeed	: 0.2,

			noZoom	: false,
			noPan	: false,

			staticMoving: false,
			dynamicDampingFactor: 0.3,

			keys	: [ 65, 83, 68 ], // [ rotateKey, zoomKey, panKey ],

			domElement: renderer.domElement,
		});
		camera.position.z	= 100;
	}

	// call THREEx.WindowResize
	THREEx.WindowResize(renderer, camera);
	// support screenshot
	THREEx.Screenshot.bindKey(renderer);

	// FIXME failed attemps
	// - seems to fail if the data url
	THREEx.ImageDrop(renderer, function(image){
		var material		= Emitter.container().materials[0];
		var uniforms		= material.uniforms;
		var texture		= uniforms['texture'].texture;
		//texture.image.src	= image.src;
		texture.image		= image;
		texture.needsUpdate	= true;
		//uniforms['texture'].needsUpdate	= true;
console.log("object3d", texture, "uniforms", uniforms['texture'], "newimage", image, "oldimage", texture.image);
	})

	// build the scene
	scene = new THREE.Scene();

	// define the containerObj of all the particle
	containerObj	= new THREE.Object3D();
	scene.addChild(containerObj)

	// parameters
	var parameters	= {
		nbItems		: 10000,
		textureUrl	: "images/lensFlare/Flare1.png",

		emitRate	: 30,
		timeToLive	: 2000,

		originZaValue	: Math.PI/2,
		originZaRange	: 30 * Math.PI/180,
		originZhValue	: 0,
		originZhRange	: 0,
		originRadiusValue	: 0.5,
		originRadiusRange	: 0.5,

		speedValue	: 1.5,
		speedRange	: 0.5,

		gravity		: 0.05,

		color		: { r: 1.0,  g: 0.33, b: 0.0},
		colorInc	: { r: 0,  g: 0, b: 0},

		opacitySrc	: 1.0,
		opacityInc	: 0.0,

		sizeSrc		: 16.0,
		sizeInc		:  0.0,

		rotationSrc	:  0.0,
		rotationInc	:  0.0
	};
	buildGui(parameters);

	// build the emitter
	Emitter	= new THREEx.Particle.Emitter(parameters);
	containerObj.addChild( Emitter.container() );

	// init the Stats
	stats	= new Stats();
	stats.domElement.style.position	= 'absolute';
	stats.domElement.style.bottom	= '0px';
	container.appendChild( stats.domElement );

	// listen to mousemove to animate the scene
	document.addEventListener( 'mousemove', onDocumentMouseMove, false );
}

//

function onDocumentMouseMove(event)
{
	mouseX = event.clientX - window.innerWidth / 2;
	mouseY = event.clientY - window.innerHeight / 2;
}

//
function animate() {

	requestAnimationFrame( animate );

	Emitter.update();

	render();
	stats.update();
}

function render()
{
	// move the camera
	if( false ){
		camera.position.x += (   mouseX - camera.position.x ) * .05;
		camera.position.y += ( - mouseY - camera.position.y ) * .05;
	}

	// animate the cube
	if( false ){
		containerObj.rotation.x += 0.4*0.02;
		containerObj.rotation.y += 0.4*0.0225;
		containerObj.rotation.z += 0.4*0.0175;
	}

	// actually render the scene
	renderer.render( scene, camera );
}
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket 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.
*/

'use strict';

import Matrix from 'matrix-js-sdk';
import utils from 'matrix-js-sdk/lib/utils';

const localStorage = window.localStorage;

interface MatrixClientCreds {
    homeserverUrl: string,
    identityServerUrl: string,
    userId: string,
    deviceId: string,
    accessToken: string,
    guest: boolean,
}

/**
 * Wrapper object for handling the js-sdk Matrix Client object in the react-sdk
 * Handles the creation/initialisation of client objects.
 * This module provides a singleton instance of this class so the 'current'
 * Matrix Client object is available easily.
 */
class MatrixClientPeg {
    constructor() {
        this.matrixClient = null;

        // These are the default options used when when the
        // client is started in 'start'. These can be altered
        // at any time up to after the 'will_start_client'
        // event is finished processing.
        this.opts = {
            initialSyncLimit: 20,
        };
    }

    get(): MatrixClient {
        return this.matrixClient;
    }

    unset() {
        this.matrixClient = null;
    }

    /**
     * Replace this MatrixClientPeg's client with a client instance that has
     * Home Server / Identity Server URLs and active credentials
     */
    replaceUsingCreds(creds: MatrixClientCreds) {
        this._createClient(creds);
    }

    start() {
        const opts = utils.deepCopy(this.opts);
        // the react sdk doesn't work without this, so don't allow
        opts.pendingEventOrdering = "detached";
        this.get().startClient(opts);
    }

    getCredentials(): MatrixClientCreds {
        return {
            homeserverUrl: this.matrixClient.baseUrl,
            identityServerUrl: this.matrixClient.idBaseUrl,
            userId: this.matrixClient.credentials.userId,
            deviceId: this.matrixClient.getDeviceId(),
            accessToken: this.matrixClient.getAccessToken(),
            guest: this.matrixClient.isGuest(),
        };
    }

    _createClient(creds: MatrixClientCreds) {
        var opts = {
            baseUrl: creds.homeserverUrl,
            idBaseUrl: creds.identityServerUrl,
            accessToken: creds.accessToken,
            userId: creds.userId,
            deviceId: creds.deviceId,
            timelineSupport: true,
        };

        if (localStorage) {
            opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage);
        }

        this.matrixClient = Matrix.createClient(opts);

        // we're going to add eventlisteners for each matrix event tile, so the
        // potential number of event listeners is quite high.
        this.matrixClient.setMaxListeners(500);

        this.matrixClient.setGuest(Boolean(creds.guest));
    }
}

if (!global.mxMatrixClientPeg) {
    global.mxMatrixClientPeg = new MatrixClientPeg();
}
module.exports = global.mxMatrixClientPeg;
<commit_msg>create a global notif timeline set for each client<commit_after>/*
Copyright 2015, 2016 OpenMarket 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.
*/

'use strict';

import Matrix from 'matrix-js-sdk';
import utils from 'matrix-js-sdk/lib/utils';
import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline';
import EventTimelineSet from 'matrix-js-sdk/lib/models/event-timeline-set';

const localStorage = window.localStorage;

interface MatrixClientCreds {
    homeserverUrl: string,
    identityServerUrl: string,
    userId: string,
    deviceId: string,
    accessToken: string,
    guest: boolean,
}

/**
 * Wrapper object for handling the js-sdk Matrix Client object in the react-sdk
 * Handles the creation/initialisation of client objects.
 * This module provides a singleton instance of this class so the 'current'
 * Matrix Client object is available easily.
 */
class MatrixClientPeg {
    constructor() {
        this.matrixClient = null;

        // These are the default options used when when the
        // client is started in 'start'. These can be altered
        // at any time up to after the 'will_start_client'
        // event is finished processing.
        this.opts = {
            initialSyncLimit: 20,
        };
    }

    get(): MatrixClient {
        return this.matrixClient;
    }

    unset() {
        this.matrixClient = null;
    }

    /**
     * Replace this MatrixClientPeg's client with a client instance that has
     * Home Server / Identity Server URLs and active credentials
     */
    replaceUsingCreds(creds: MatrixClientCreds) {
        this._createClient(creds);
    }

    start() {
        const opts = utils.deepCopy(this.opts);
        // the react sdk doesn't work without this, so don't allow
        opts.pendingEventOrdering = "detached";
        this.get().startClient(opts);
    }

    getCredentials(): MatrixClientCreds {
        return {
            homeserverUrl: this.matrixClient.baseUrl,
            identityServerUrl: this.matrixClient.idBaseUrl,
            userId: this.matrixClient.credentials.userId,
            deviceId: this.matrixClient.getDeviceId(),
            accessToken: this.matrixClient.getAccessToken(),
            guest: this.matrixClient.isGuest(),
        };
    }

    _createClient(creds: MatrixClientCreds) {
        var opts = {
            baseUrl: creds.homeserverUrl,
            idBaseUrl: creds.identityServerUrl,
            accessToken: creds.accessToken,
            userId: creds.userId,
            deviceId: creds.deviceId,
            timelineSupport: true,
        };

        if (localStorage) {
            opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage);
        }

        this.matrixClient = Matrix.createClient(opts);

        // we're going to add eventlisteners for each matrix event tile, so the
        // potential number of event listeners is quite high.
        this.matrixClient.setMaxListeners(500);

        this.matrixClient.setGuest(Boolean(creds.guest));

        var notifTimelineSet = new EventTimelineSet(null, null, {
            timelineSupport: true
        });
        // XXX: what is our initial pagination token?! it somehow needs to be synchronised with /sync.
        notifTimelineSet.getLiveTimeline().setPaginationToken("", EventTimeline.BACKWARDS);
        this.matrixClient.setNotifTimelineSet(notifTimelineSet);
    }
}

if (!global.mxMatrixClientPeg) {
    global.mxMatrixClientPeg = new MatrixClientPeg();
}
module.exports = global.mxMatrixClientPeg;
<|endoftext|>


<commit_before>module.exports = {
  port: process.env.OPENSHIFT_NODEJS_PORT || 3000,
  ipAddress: process.env.OPENSHIFT_NODEJS_IP || '192.168.1.5' || '127.0.0.1'
};<commit_msg>switched back to using local host<commit_after>module.exports = {
  port: process.env.OPENSHIFT_NODEJS_PORT || 3000,
  ipAddress: process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1'
};<|endoftext|>


<commit_before>// put-spot.js
module.exports = function(db) {
  return function(req, res) {
    var spots = db.collection('spots');
    spots.update({_id: req.params.id}, {$set: req.body}, function(err, result) {
      if(err) throw err;

      res.json(result);
    });
  }
}
<commit_msg>Update put-spot.js<commit_after>// put-spot.js
module.exports = function(db) {
  return function(req, res) {
    var spots = db.collection('spots');
    spots.update({_id: req.params.id}, {$set: req.body}, function(err, result) {
      if(err) return res.status(500).json(code: 'DbError', err: err);

      res.json(result);
    });
  }
}
<|endoftext|>


<commit_before>define(['sprd/data/SprdModel', 'sprd/entity/Address', 'underscore'], function (SprdModel, AddressEntity, _) {

    /**
     * User Address shares the same interface and methods like Address but with some extensions
     *
     */
    var defaults = _.extend({
        shippingAddress: true,
        billingAddress: true,
        defaultBillingAddress: false,
        defaultShippingAddress: false
    }, AddressEntity.prototype.defaults);

    var schema = _.extend({
        shippingAddress: Boolean,
        billingAddress: Boolean,
        defaultBillingAddress: Boolean,
        defaultShippingAddress: Boolean
    }, AddressEntity.prototype.schema);

    var UserAddress = SprdModel.inherit('sprd.model.UserAddress', {
        defaults: defaults,
        schema: schema,
        validators: AddressEntity.prototype.validators,
        transformers: AddressEntity.prototype.transformers,
        parse: AddressEntity.prototype.parse,
        compose: AddressEntity.prototype.compose,
        _commitChangedAttributes: AddressEntity.prototype._commitChangedAttributes,
        isPackStation: AddressEntity.prototype.isPackStation,
        needsCounty: AddressEntity.prototype.needsCounty,
        needsZipCode: AddressEntity.prototype.needsZipCode,
        isStateRequired: AddressEntity.prototype.isStateRequired,
        isCompany: AddressEntity.prototype.isCompany,
        _commitType: function (type) {
            this.set('billingAddress', type != AddressEntity.ADDRESS_TYPES.PACKSTATION);
        }
    });

    UserAddress.ADDRESS_TYPES = AddressEntity.ADDRESS_TYPES;

    return UserAddress;
});<commit_msg>DEV-72297 - Validation error on mandatory fields are not triggered in address book<commit_after>define(['sprd/data/SprdModel', 'sprd/entity/Address', 'underscore'], function (SprdModel, AddressEntity, _) {

    /**
     * User Address shares the same interface and methods like Address but with some extensions
     *
     */
    var defaults = _.extend({
        shippingAddress: true,
        billingAddress: true,
        defaultBillingAddress: false,
        defaultShippingAddress: false
    }, AddressEntity.prototype.defaults);

    var schema = _.extend({
        shippingAddress: Boolean,
        billingAddress: Boolean,
        defaultBillingAddress: Boolean,
        defaultShippingAddress: Boolean
    }, AddressEntity.prototype.schema);

    var UserAddress = SprdModel.inherit('sprd.model.UserAddress', {
        defaults: defaults,
        schema: schema,
        validators: AddressEntity.prototype.validators,
        transformers: AddressEntity.prototype.transformers,
        parse: AddressEntity.prototype.parse,
        compose: AddressEntity.prototype.compose,
        _commitChangedAttributes: AddressEntity.prototype._commitChangedAttributes,
        isPackStation: AddressEntity.prototype.isPackStation,
        needsCounty: AddressEntity.prototype.needsCounty,
        needsZipCode: AddressEntity.prototype.needsZipCode,
        isStateRequired: AddressEntity.prototype.isStateRequired,
        hasStates: AddressEntity.prototype.hasStates,
        isCompany: AddressEntity.prototype.isCompany,
        _commitType: function (type) {
            this.set('billingAddress', type != AddressEntity.ADDRESS_TYPES.PACKSTATION);
        }
    });

    UserAddress.ADDRESS_TYPES = AddressEntity.ADDRESS_TYPES;

    return UserAddress;
});<|endoftext|>


<commit_before>var sqrt2 = Math.sqrt(2),
    π = Math.PI,
    lines

var width = 750,
    height = 500

var zoom = d3.behavior.zoom()
    .scaleExtent([1, 1 << 16])
    .on('zoom', function(){
      svg.attr('transform',
        ['translate(', d3.event.translate, ') scale(', d3.event.scale, ')'].join(''))
    })

var svg = d3.select('#dragon-curve')
    .append('svg')
      .attr({width: width, height: height})
    .append('g')
      .call(zoom)

function addLine(a, b, m, θ, isLeft, level){
  var ℓ = length(a, b)
  var line = svg.append('path')
      .attr('d', ['M', a, 'L', m].join(''))
      .attr('vector-effect', 'non-scaling-stroke')
  line.transition().duration(1000)
      .attr('d', ['M', a, 'L', b].join(''))
      .each('end', function(){
      })
  var datum = {line: line, level: level, addRect: addRect, done: false, a: a}
  lines.push(datum)

  var rectAdded = false
  function addRect(delay){
    if (rectAdded) return
    rectAdded = true
    var rect = svg.append('rect')
    rect.attr({x: b[0], y: b[1], height: 0, width: 0})
        .attr('transform', ['rotate(', -θ + 225,',', b, ')'].join(''))
        .attr('class', isLeft ? 'left' : 'right')
        .classed('hoverrect', true)
      .transition().duration(1000).delay(delay*1000)
        .attr({height: ℓ/sqrt2, width: ℓ/sqrt2})
    rect
        .on('mouseover', function(){
          if (datum.done) return rect.remove()
          var ℓ1 = ℓ/2*sqrt2
          //calc midpoint to animate from
          var m1 = [(a[0] + b[0])/2, (a[1] + b[1])/2]

          var θ1 = (360 + θ - 45) % 360
          var b1 = extendLine(a, ℓ1, θ1)
          addLine(a, b1, m1, θ1, true, level + 1)

          var θ2 = (360 + θ - 135) % 360
          var b2 = extendLine(b, ℓ1, θ2)
          addLine(b, b2, m1, θ2, false, level + 1)

          line.style('opacity', .2)
          rect.style('opacity', .05).remove()
          datum.done = true

          var scale = zoom.scale()
          var halfWidth  = width/ (2*scale)
          var halfHeight = height/(2*scale)
          var center = zoom.translate()
              .map(function(d, i){ return -d + (i ? halfHeight : halfWidth) })
          var levelCompleted = lines.every(function(d){
            if (d.level != level || d.done) return true
            // check to that all of the same level that aren't completed are off screen
            return Math.abs(d.a[0] - center[0]) > halfWidth ||
                   Math.abs(d.a[1] - center[1]) > halfHeight
          })
          if (levelCompleted){
            console.log('levelCompleted')
            var nextLevel = lines.filter(function(d){ return d.level == level + 1 })
            nextLevel.forEach(function(d, i){  d.addRect(i/nextLevel.length) })
          }
    })
  }
}

function extendLine(a, ℓ, θ){
  return [a[0] + ℓ*Math.sin(θ*π/180), a[1] + ℓ*Math.cos(θ*π/180)]
}

function length(a, b){
  var x2 = Math.pow(a[0] - b[0], 2)
  var y2 = Math.pow(a[1] - b[1], 2)
  return Math.sqrt(x2 + y2)
}

function midPoint(a, b){
  return [(a[0] + b[0])/2, (a[1] + b[1])/2]
}

d3.select('#step').on('click', function(){
  d3.selectAll('.hoverrect').filter(function(d, i){ return i < 4000 })
      .each(function(){ d3.select(this).on('mouseover')() })
})

d3.select('#reset')
    .on('click', function(){
      svg.selectAll('*').remove()

      svg.append('rect')
          .attr({width: width, height: height})
          .style('fill-opacity', 0)

      svg.attr('transform', 'translate(0, 0) scale(1)')
      zoom.scale(1).translate([0, 0])

      lines = []
      addLine([150, height/3], [width - 230, height/3], [0, height/2], 90, true, 0)
      lines[0].addRect(0)
    })
    .on('click')()

function centerDebug(){
  var scale = zoom.scale()
  var halfWidth  = width/ (2*scale)
  var halfHeight = height/(2*scale)
  var center = zoom.translate()
      .map(function(d, i){ return -d/scale + (i ? halfHeight : halfWidth) })
  console.log(center)
  svg.append('circle')
      .attr({r: 10, cx: center[0], cy: center[1]})
  var level = 0
  var levelCompleted = lines.every(function(d){
    if (d.level != level || d.done) return true
    // check to that all of the same level that aren't completed are off screen
    return Math.abs(d.a[0] - center[0]) > halfWidth ||
           Math.abs(d.a[1] - center[1]) > halfHeight
  })
}
<commit_msg>fiddle with zoomed translates<commit_after>var sqrt2 = Math.sqrt(2),
    π = Math.PI,
    lines

var width = 750,
    height = 500

var zoom = d3.behavior.zoom()
    .scaleExtent([1, 1 << 16])
    .on('zoom', function(){
      var scale = d3.event.scale
      var translate = d3.event.translate//.map(function(d){ return d/scale })
      svg.attr('transform',
        ['translate(', translate, ') scale(', scale, ')'].join(''))
    })

var svg = d3.select('#dragon-curve')
    .append('svg')
      .attr({width: width, height: height})
    .append('g')
      .call(zoom)

function addLine(a, b, m, θ, isLeft, level){
  var ℓ = length(a, b)
  var line = svg.append('path')
      .attr('d', ['M', a, 'L', m].join(''))
      .attr('vector-effect', 'non-scaling-stroke')
  line.transition().duration(1000)
      .attr('d', ['M', a, 'L', b].join(''))
      .each('end', function(){
      })
  var datum = {line: line, level: level, addRect: addRect, done: false, a: a}
  lines.push(datum)

  var rectAdded = false
  function addRect(delay){
    if (rectAdded) return
    rectAdded = true
    var rect = svg.append('rect')
    rect.attr({x: b[0], y: b[1], height: 0, width: 0})
        .attr('transform', ['rotate(', -θ + 225,',', b, ')'].join(''))
        .attr('class', isLeft ? 'left' : 'right')
        .classed('hoverrect', true)
      .transition().duration(1000).delay(delay*1000)
        .attr({height: ℓ/sqrt2, width: ℓ/sqrt2})
    rect
        .on('mouseover', function(){
          if (datum.done) return rect.remove()
          var ℓ1 = ℓ/2*sqrt2
          //calc midpoint to animate from
          var m1 = [(a[0] + b[0])/2, (a[1] + b[1])/2]

          var θ1 = (360 + θ - 45) % 360
          var b1 = extendLine(a, ℓ1, θ1)
          addLine(a, b1, m1, θ1, true, level + 1)

          var θ2 = (360 + θ - 135) % 360
          var b2 = extendLine(b, ℓ1, θ2)
          addLine(b, b2, m1, θ2, false, level + 1)

          line.style('opacity', .2).style('stroke-width', 1)
          rect.style('opacity', .05).remove()
          datum.done = true

          var scale = zoom.scale()
          var halfWidth  = width/ (2*scale)
          var halfHeight = height/(2*scale)
          var center = zoom.translate()
              .map(function(d, i){ return -d/scale + (i ? halfHeight : halfWidth) })
          var levelCompleted = lines.every(function(d){
            if (d.level != level || d.done) return true
            // check to that all of the same level that aren't completed are off screen
            return Math.abs(d.a[0] - center[0]) > halfWidth ||
                   Math.abs(d.a[1] - center[1]) > halfHeight
          })
          if (levelCompleted){
            console.log('levelCompleted')
            var nextLevel = lines.filter(function(d){ return d.level == level + 1 })
            nextLevel.forEach(function(d, i){  d.addRect(i/nextLevel.length) })
          }
    })
  }
}

function extendLine(a, ℓ, θ){
  return [a[0] + ℓ*Math.sin(θ*π/180), a[1] + ℓ*Math.cos(θ*π/180)]
}

function length(a, b){
  var x2 = Math.pow(a[0] - b[0], 2)
  var y2 = Math.pow(a[1] - b[1], 2)
  return Math.sqrt(x2 + y2)
}

function midPoint(a, b){
  return [(a[0] + b[0])/2, (a[1] + b[1])/2]
}

d3.select('#step').on('click', function(){
  d3.selectAll('.hoverrect').filter(function(d, i){ return i < 4000 })
      .each(function(){ d3.select(this).on('mouseover')() })
})

d3.select('#reset')
    .on('click', function(){
      svg.selectAll('*').remove()

      svg.append('rect')
          .attr({width: width, height: height})
          .style('fill-opacity', 0)

      svg.attr('transform', 'translate(0, 0) scale(1)')
      zoom.scale(1).translate([0, 0])

      lines = []
      addLine([150, height/3], [width - 230, height/3], [0, height/2], 90, true, 0)
      lines[0].addRect(0)
    })
    .on('click')()

function centerDebug(){
  var scale = zoom.scale()
  var halfWidth  = width/ (2*scale)
  var halfHeight = height/(2*scale)
  var center = zoom.translate()
      .map(function(d, i){ return -d/scale + (i ? halfHeight : halfWidth) })
  console.log(center)
  svg.append('circle')
      .attr({r: 10, cx: center[0], cy: center[1]})
  var level = 0
  var levelCompleted = lines.every(function(d){
    if (d.level != level || d.done) return true
    // check to that all of the same level that aren't completed are off screen
    return Math.abs(d.a[0] - center[0]) > halfWidth ||
           Math.abs(d.a[1] - center[1]) > halfHeight
  })
}
<|endoftext|>


<commit_before>let INTERVAL_ID = 'not_touched';
// the same members as storage.local's
const SETTINGS = {
  update_check : true,
  update_check_interval : 14000,
  mute_by_key : false,
  block_by_key : false,
};
const STORE_NAME = 'pptw_settings';

const pptw = {

  /**
   * click 'update' button, unless overlay appear in the topmost.
   */
  clickUpdateButton : () => {
    let wk_elm = document.getElementById('permalink-overlay');
    let goClick = true;
    if(wk_elm) {
      const computedStyle = window.getComputedStyle(wk_elm);
      if(computedStyle === undefined
        || computedStyle.display === undefined
        || computedStyle.display === 'block'
        || computedStyle.opacity === 1) {
        goClick = false;
      }
    }
    if(goClick) {
      wk_elm = document.getElementsByClassName('new-tweets-bar');
      if(wk_elm && wk_elm.length > 0) {
        wk_elm[0].click();
      }
    }
  },

  getTweetList : () => {
    const root = document.getElementById('stream-items-id');
    if(!root) {
      return;
    }
    const tweetTextArr = [];
    const tweetContainerList = root.querySelectorAll('.js-stream-item');
    if(tweetContainerList && tweetContainerList.length > 0) {
      tweetContainerList.forEach(elm => {
        const textContainer = elm.querySelector('.tweet-text');
        if(textContainer) {
          tweetTextArr.push(textContainer.textContent.trim());
        }
      });
    }
    return tweetTextArr;
  },

  handleKeydown : (evt) => {
    if(SETTINGS.block_by_key === false && evt.key === 'b') {
      pptw.preventKeydown(evt);
    }
    else if(SETTINGS.mute_by_key === false && evt.key === 'u') {
      pptw.preventKeydown(evt);
    }
  },

  preventKeydown : (evt) => {
    if(evt.target.isContentEditable
      || evt.target.nodeName.toUpperCase() === 'INPUT'
      || evt.target.nodeName.toUpperCase() === 'TEXTAREA') {
      return;
    }
    evt.preventDefault();
  },

  scrollToTweet : (ord) => {
    const tweetContainerList = document.querySelectorAll('#stream-items-id .js-stream-item');
    if(tweetContainerList && tweetContainerList.length > 0 && ord < tweetContainerList.length) {
      tweetContainerList[ord].scrollIntoView();
    }
  },

  setUpdateCheck : (goEnable) => {
    if(INTERVAL_ID === 'not_touched') {
      if(goEnable) {
        INTERVAL_ID = setInterval(pptw.clickUpdateButton, SETTINGS.update_check_interval);
      }
      SETTINGS.update_check = goEnable;
      pptw.updatePageAction();
    }
    else if(goEnable && SETTINGS.update_check === false) {
      INTERVAL_ID = setInterval(pptw.clickUpdateButton, SETTINGS.update_check_interval);
      SETTINGS.update_check = goEnable;
      pptw.updatePageAction();
    }
    else if(goEnable === false && SETTINGS.update_check) {
      clearInterval(INTERVAL_ID);
      SETTINGS.update_check = goEnable;
      pptw.updatePageAction();
    }
  },

  updateSettings : (newSettings) => {
    if(newSettings) {
      Object.keys(newSettings).forEach(key => {
        if(SETTINGS.hasOwnProperty(key)) {
          SETTINGS[key] = newSettings[key];
        }
      });
      // console.log(`${JSON.stringify(SETTINGS, null, 2)}`);
    }
    pptw.setUpdateCheck(SETTINGS.update_check);
  },

  updatePageAction : () => {
    browser.runtime.sendMessage({ task:'setIcon', icon: SETTINGS.update_check, });
  },

};

const start = () => {
  browser.storage.local.get(STORE_NAME).then(store_obj => {
    const result = store_obj[STORE_NAME];
    pptw.updateSettings(result);
    document.addEventListener('keydown', pptw.handleKeydown);
  }).catch(err => {
    console.log(`Error: start: ${err}`);
  });
};

browser.runtime.onMessage.addListener((message, _sender) => {
  if(message.task === 'tweetList' && message.from === 'popup') {
    browser.runtime.sendMessage({
      task: message.task,
      replyTo: message.from,
      tweetList: pptw.getTweetList(),
    });
  }
  else if(message.task === 'scrollToTweet' && message.from === 'popup') {
    pptw.scrollToTweet(message.ord);
  }
  else if(message.task === 'toggleUpdateCheck' && message.from === 'popup') {
    pptw.setUpdateCheck(!SETTINGS.update_check);
  }
});

start();

// vim:expandtab ff=dos fenc=utf-8 sw=2
<commit_msg>refactor: clean up<commit_after>let INTERVAL_ID = 'not_touched';
// the same members as storage.local's
const SETTINGS = {
  update_check : true,
  update_check_interval : 14000,
  mute_by_key : false,
  block_by_key : false,
};
const STORE_NAME = 'pptw_settings';

const pptw = {

  /**
   * click 'update' button, unless overlay appear in the topmost.
   */
  clickUpdateButton : () => {
    let wk_elm = document.getElementById('permalink-overlay');
    let goClick = true;
    if(wk_elm) {
      const computedStyle = window.getComputedStyle(wk_elm);
      if(computedStyle === undefined
        || computedStyle.display === undefined
        || computedStyle.display === 'block'
        || computedStyle.opacity === 1) {
        goClick = false;
      }
    }
    if(goClick) {
      wk_elm = document.getElementsByClassName('new-tweets-bar');
      if(wk_elm && wk_elm.length > 0) {
        wk_elm[0].click();
      }
    }
  },

  getTweetList : () => {
    const root = document.getElementById('stream-items-id');
    if(!root) {
      return;
    }
    const tweetTextArr = [];
    const tweetContainerList = root.querySelectorAll('.js-stream-item');
    if(tweetContainerList && tweetContainerList.length > 0) {
      tweetContainerList.forEach(elm => {
        const textContainer = elm.querySelector('.tweet-text');
        if(textContainer) {
          tweetTextArr.push(textContainer.textContent.trim());
        }
      });
    }
    return tweetTextArr;
  },

  handleKeydown : (evt) => {
    if(SETTINGS.block_by_key === false && evt.key === 'b') {
      pptw.preventKeydown(evt);
    }
    else if(SETTINGS.mute_by_key === false && evt.key === 'u') {
      pptw.preventKeydown(evt);
    }
  },

  preventKeydown : (evt) => {
    if(evt.target.isContentEditable
      || evt.target.nodeName.toUpperCase() === 'INPUT'
      || evt.target.nodeName.toUpperCase() === 'TEXTAREA') {
      return;
    }
    evt.preventDefault();
  },

  scrollToTweet : (ord) => {
    const tweetContainerList = document.querySelectorAll('#stream-items-id .js-stream-item');
    if(tweetContainerList && tweetContainerList.length > 0 && ord < tweetContainerList.length) {
      tweetContainerList[ord].scrollIntoView();
    }
  },

  setUpdateCheck : (goEnable) => {
    if(INTERVAL_ID === 'not_touched') {
      if(goEnable) {
        INTERVAL_ID = setInterval(pptw.clickUpdateButton, SETTINGS.update_check_interval);
      }
      SETTINGS.update_check = goEnable;
      pptw.updatePageAction();
    }
    else if(goEnable && SETTINGS.update_check === false) {
      INTERVAL_ID = setInterval(pptw.clickUpdateButton, SETTINGS.update_check_interval);
      SETTINGS.update_check = goEnable;
      pptw.updatePageAction();
    }
    else if(goEnable === false && SETTINGS.update_check) {
      clearInterval(INTERVAL_ID);
      SETTINGS.update_check = goEnable;
      pptw.updatePageAction();
    }
  },

  updateSettings : (newSettings) => {
    if(newSettings) {
      Object.keys(newSettings).forEach(key => {
        if(SETTINGS.hasOwnProperty(key)) {
          SETTINGS[key] = newSettings[key];
        }
      });
    }
    pptw.setUpdateCheck(SETTINGS.update_check);
  },

  updatePageAction : () => {
    browser.runtime.sendMessage({ task:'setIcon', icon: SETTINGS.update_check, });
  },

};

const start = () => {
  browser.storage.local.get(STORE_NAME).then(store_obj => {
    const result = store_obj[STORE_NAME];
    pptw.updateSettings(result);
    document.addEventListener('keydown', pptw.handleKeydown);
  }).catch(err => {
    console.log(`Error: start: ${err}`);
  });
};

browser.runtime.onMessage.addListener((message, _sender) => {
  if(message.task === 'tweetList' && message.from === 'popup') {
    browser.runtime.sendMessage({
      task: message.task,
      replyTo: message.from,
      tweetList: pptw.getTweetList(),
    });
  }
  else if(message.task === 'scrollToTweet' && message.from === 'popup') {
    pptw.scrollToTweet(message.ord);
  }
  else if(message.task === 'toggleUpdateCheck' && message.from === 'popup') {
    pptw.setUpdateCheck(!SETTINGS.update_check);
  }
});

start();

// vim:expandtab ff=dos fenc=utf-8 sw=2
<|endoftext|>


<commit_before>define(["underscore", "sprd/util/ArrayUtil", "js/core/List", "sprd/model/ProductType", "flow", "sprd/entity/Price"], function (_, ArrayUtil, List, ProductType, flow, Price) {

    return {

        sortPrintTypeByWeight: function(a, b) {
            return a.$.weight - b.$.weight;
        },

        getPossiblePrintTypesForDesignOnPrintArea: function(design, printArea, appearance) {

            if (!(design && design.$.printTypes)) {
                return [];
            }

            return ArrayUtil.average(design.$.printTypes.$items,
                this.getPossiblePrintTypesForPrintAreas([printArea], appearance))
                .sort(this.sortPrintTypeByWeight);
        },

        getPossiblePrintTypesForDesignOnProduct: function (design, product) {
            var defaultPrintArea = product.$.view.getDefaultPrintArea();

            if (!defaultPrintArea) {
                return [];
            }

            return this.getPossiblePrintTypesForDesignOnPrintArea(design, defaultPrintArea, product.$.appearance);

        },

        getPossiblePrintTypesForTextOnPrintArea: function(fontFamily, printArea, appearance) {
            return ArrayUtil.average(fontFamily.$.printTypes.$items,
                this.getPossiblePrintTypesForPrintAreas([printArea], appearance))
                .sort(this.sortPrintTypeByWeight);
        },

        getPossiblePrintTypesForPrintAreas: function(printAreas, appearance) {
            var ret = [];

            printAreas = ArrayUtil.getAsArray(printAreas);

            _.each(printAreas, function (printArea) {

                var productType = printArea.$parent;

                if (appearance) {
                    _.each(appearance.$.printTypes.$items, function (printType) {
                        if (!_.contains(printArea.$.restrictions.$.excludedPrintTypes.$items, printType) && !_.contains(ret, printType)) {
                            ret.push(printType);
                        }
                    });
                }
            });

            ret.sort(this.sortPrintTypeByWeight);

            return ret;
        },

        getPossiblePrintTypesForSpecialText: function(printArea, appearance) {
            return _.filter(this.getPossiblePrintTypesForPrintAreas([printArea], appearance) || [],
                function (printType) {
                    // just digital print types
                    return !printType.isPrintColorColorSpace() && printType.isScalable();
                });
        },

        getCheapestPriceForDesignOnProduct: function (design, product) {
            var possiblePrintTypes = this.getPossiblePrintTypesForDesignOnProduct(design, product),
                cheapestPrintTypePrice = null;
            if (possiblePrintTypes.length) {
                for (var i = 0; i < possiblePrintTypes.length; i++) {
                    var price = new Price();
                    var printType = possiblePrintTypes[i];
                    if (printType.isPrintColorColorSpace()) {
                        var firstColor = design.$.colors.at(0);
                        var printColor = printType.getClosestPrintColor(firstColor.get('default') || firstColor.get("origin"));
                        if (!printColor) {
                            continue;
                        }
                        price.add(printColor.$.price);
                    }
                    price.add(printType.$.price);
                    price.add(design.$.price);

                    if (!cheapestPrintTypePrice || cheapestPrintTypePrice.$.vatIncluded > price.$.vatIncluded) {
                        cheapestPrintTypePrice = price;
                    }

                }
            }
            return cheapestPrintTypePrice;
        },

        fetchColorsForProductTypes: function (productTypes, minDistance, callback) {
            minDistance = minDistance || 2;

            var colors = new List();

            flow()
                .parEach(productTypes, function (item, cb) {
                    item.fetch(null, cb);
                })
                .seqEach(productTypes, function (productType, cb) {
                    productType.$.appearances.each(function (appearance) {
                        var merge = false;
                        colors.each(function (color) {
                            merge = appearance.$.color.distanceTo(color) < minDistance;
                        });
                        if (!merge) {
                            colors.add(appearance.$.color);
                        }
                    });
                })
                .exec(function (err) {
                    callback(err, colors);
                });
        }
    };

});
<commit_msg>DEV-114541<commit_after>define(["underscore", "sprd/util/ArrayUtil", "js/core/List", "sprd/model/ProductType", "flow", "sprd/entity/Price"], function (_, ArrayUtil, List, ProductType, flow, Price) {

    return {

        sortPrintTypeByWeight: function(a, b) {
            return a.$.weight - b.$.weight;
        },

        getPossiblePrintTypesForDesignOnPrintArea: function(design, printArea, appearance) {

            if (!(design && design.$.printTypes)) {
                return [];
            }

            return ArrayUtil.average(design.$.printTypes.$items,
                this.getPossiblePrintTypesForPrintAreas([printArea], appearance))
                .sort(this.sortPrintTypeByWeight);
        },

        getPossiblePrintTypesForDesignOnProduct: function (design, product) {
            var defaultPrintArea = product.$.view.getDefaultPrintArea();

            if (!defaultPrintArea) {
                return [];
            }

            return this.getPossiblePrintTypesForDesignOnPrintArea(design, defaultPrintArea, product.$.appearance);

        },

        getPossiblePrintTypesForTextOnPrintArea: function(fontFamily, printArea, appearance) {
            return ArrayUtil.average(fontFamily.$.printTypes.$items,
                this.getPossiblePrintTypesForPrintAreas([printArea], appearance))
                .sort(this.sortPrintTypeByWeight);
        },

        getPossiblePrintTypesForPrintAreas: function(printAreas, appearance) {
            var ret = [];

            printAreas = ArrayUtil.getAsArray(printAreas);

            _.each(printAreas, function (printArea) {

                if (appearance) {
                    _.each(appearance.$.printTypes.$items, function (printType) {
                        if (!_.contains(printArea.$.restrictions.$.excludedPrintTypes.$items, printType) && !_.contains(ret, printType)) {
                            ret.push(printType);
                        }
                    });
                }
            });

            ret.sort(this.sortPrintTypeByWeight);

            return ret;
        },

        getPossiblePrintTypesForSpecialText: function(printArea, appearance) {
            return _.filter(this.getPossiblePrintTypesForPrintAreas([printArea], appearance) || [],
                function (printType) {
                    // just digital print types
                    return !printType.isPrintColorColorSpace() && printType.isScalable();
                });
        },

        getCheapestPriceForDesignOnProduct: function (design, product) {
            var possiblePrintTypes = this.getPossiblePrintTypesForDesignOnProduct(design, product),
                cheapestPrintTypePrice = null;
            if (possiblePrintTypes.length) {
                for (var i = 0; i < possiblePrintTypes.length; i++) {
                    var price = new Price();
                    var printType = possiblePrintTypes[i];
                    if (printType.isPrintColorColorSpace()) {
                        var firstColor = design.$.colors.at(0);
                        var printColor = printType.getClosestPrintColor(firstColor.get('default') || firstColor.get("origin"));
                        if (!printColor) {
                            continue;
                        }
                        price.add(printColor.$.price);
                    }
                    price.add(printType.$.price);
                    price.add(design.$.price);

                    if (!cheapestPrintTypePrice || cheapestPrintTypePrice.$.vatIncluded > price.$.vatIncluded) {
                        cheapestPrintTypePrice = price;
                    }

                }
            }
            return cheapestPrintTypePrice;
        },

        fetchColorsForProductTypes: function (productTypes, minDistance, callback) {
            minDistance = minDistance || 2;

            var colors = new List();

            flow()
                .parEach(productTypes, function (item, cb) {
                    item.fetch(null, cb);
                })
                .seqEach(productTypes, function (productType, cb) {
                    productType.$.appearances.each(function (appearance) {
                        var merge = false;
                        colors.each(function (color) {
                            merge = appearance.$.color.distanceTo(color) < minDistance;
                        });
                        if (!merge) {
                            colors.add(appearance.$.color);
                        }
                    });
                })
                .exec(function (err) {
                    callback(err, colors);
                });
        }
    };

});
<|endoftext|>


<commit_before>/* DEFAULT */
module.exports = function override(config, env) {
  /* Modify the config as needed*/
  return config;
};
/* ALTERNATIVE */
/*
module.exports = {
  webpack: function (config, env) {
    return config;
  },
  jest: function (config) {
    return config;
  }
}
*/<commit_msg>Add example webpackDevServer config override.<commit_after>/* DEFAULT */
module.exports = function override(config, env) {
  /* Modify the config as needed*/
  return config;
};
/* ALTERNATIVE */
/*
module.exports = {
  webpack: function (config, env) {
    return config;
  },
  jest: function (config) {
    return config;
  },
  // configFunction is the original react-scripts function that creates the
  // Webpack Dev Server config based on the settings for proxy/allowedHost.
  // react-scripts injects this into your function (so you can use it to
  // create the standard config to start from), and needs to receive back a
  // function that takes the same arguments as the original react-scripts
  // function so that it can be used as a replacement for the original one.
  devServer: function (configFunction) {
    return function(proxy, allowedHost) {
      const config = configFunction(proxy, allowedHost);
      // Edit config here - example: set your own certificates.
      //
      // const fs = require('fs');
      // config.https = {
      //   key: fs.readFileSync(process.env.REACT_HTTPS_KEY, 'utf8'),
      //   cert: fs.readFileSync(process.env.REACT_HTTPS_CERT, 'utf8'),
      //   ca: fs.readFileSync(process.env.REACT_HTTPS_CA, 'utf8'),
      //   passphrase: process.env.REACT_HTTPS_PASS
      // };

      return config;
    };
  }
}
*/
<|endoftext|>


<commit_before>/**
 * jQuery yiiactiveform plugin file.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright © 2008-2010 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * @version $Id$
 * @since 1.1.1
 */

;(function($) {
	/**
	 * yiiactiveform set function.
	 * @param map settings for the active form plugin. Please see {@link CActiveForm::options} for availablel options.
	 */
	$.fn.yiiactiveform = function(settings) {
		var settings = $.extend({}, $.fn.yiiactiveform.defaults, settings || {});
		return this.each(function() {
			var $form = $(this);
			var id = $form.attr('id');
			if(settings.validationUrl == undefined)
				settings.validationUrl = $form.attr('action');
			$.each(settings.attributes, function(i,attribute){
				settings.attributes[i] = $.extend({
					validationDelay : settings.validationDelay,
					validateOnChange : settings.validateOnChange,
					validateOnType : settings.validateOnType,
					hideErrorMessage : settings.hideErrorMessage,
					inputContainer : settings.inputContainer,
					errorCssClass : settings.errorCssClass,
					successCssClass : settings.successCssClass,
					validatingCssClass : settings.validatingCssClass
				}, attribute);
				settings.attributes[i].value = $('#'+attribute.inputID).val();
			});
			$.fn.yiiactiveform.settings[id] = settings;

			var getInputContainer = function(attribute) {
				if(attribute.container == undefined)
					return $('#'+attribute.inputID).closest('div');
				else
					return $(attribute.container).filter(':has("#'+attribute.inputID+'")');
			};

			// updates the error message and the input container for a particular attribute
			var updateInput = function(attribute, messages) {
				attribute.status = 1;
				var hasError = messages && $.isArray(messages[attribute.inputID]) && messages[attribute.inputID].length>0;
				var $error = $('#'+attribute.errorID);
				var $container = getInputContainer(attribute);
				$container.removeClass(attribute.validatingCssClass)
					.removeClass(attribute.errorCssClass)
					.removeClass(attribute.successCssClass);

				if(hasError) {
					$error.html(messages[attribute.inputID][0]);
					$container.addClass(attribute.errorCssClass);
				}
				else {
					$container.addClass(attribute.successCssClass);
				}
				if(!attribute.hideErrorMessage)
					$error.toggle(hasError);

				attribute.value = $('#'+attribute.inputID).val();

				return hasError;
			};

			// updates the error summary
			var updateSummary = function(messages) {
				if (settings.summaryID == undefined)
					return;
				var content = '';
				$.each(settings.attributes, function(i, attribute){
					if(messages && $.isArray(messages[attribute.inputID])) {
						$.each(messages[attribute.inputID],function(j,message){
							content = content + '
' + message + '
';
						});
					}
				});
				$('#'+settings.summaryID+' ul').html(content);
				$('#'+settings.summaryID).toggle(content!='');
			}

			// performs AJAX validation
			var ajaxValidate = function(successCallback) {
				$.ajax({
					url : settings.validationUrl,
					type : $form.attr('method'),
					data : $form.serialize()+'&'+settings.ajaxVar+'='+id,
					dataType : 'json',
					success : successCallback,
					error : function() {
						$.each(settings.attributes, function(i, attribute){
							//updateInput(attribute, []);
						});
					}
				});
			};

			var validate = function(attribute, forceValidate) {
				if (forceValidate)
					attribute.status = 2;
				$.each(settings.attributes, function(){
					if (this.value != $('#'+this.inputID).val()) {
						this.status = 2;
						forceValidate = true;
					}
				});
				if (!forceValidate)
					return;

				if(settings.timer!=undefined)
					clearTimeout(settings.timer);
				settings.timer = setTimeout(function(){
					$.each(settings.attributes, function(){
						if (this.status == 2) {
							this.status = 3;
							getInputContainer(this).addClass(this.validatingCssClass);
						}
					});
					ajaxValidate(function(data) {
						$.each(settings.attributes, function(){
							if (this.status == 3) {
								updateInput(this, data);
							}
						});
					});
				}, attribute.validationDelay);
			};

			$.each(settings.attributes, function(i, attribute) {
				if (attribute.validateOnChange) {
					$('#'+attribute.inputID).change(function(){
						validate(attribute,false);
					}).blur(function(){
						if(attribute.status!=2 && attribute.status!=3)
							validate(attribute, !attribute.status);
					});
				}
				if (attribute.validateOnType) {
					$('#'+attribute.inputID).keyup(function(){
						if (attribute.value != $('#'+attribute.inputID).val())
							validate(attribute, false);
					});
				}
			});

			if (settings.validateOnSubmit) {
				var validated = false;
				$form.submit(function(){
					if (validated)
						return true;
					ajaxValidate(function(data){
						var hasError = false;
						$.each(settings.attributes, function(i, attribute){
							hasError = updateInput(attribute, data) || hasError;
						});
						updateSummary(data);
						if(!hasError) {
							validated = true;
							$form.submit();
							validated = false;
						}
					});
					return false;
				});
			}
		});
	};

	$.fn.yiiactiveform.defaults = {
		ajaxVar: 'ajax',
		validationUrl: undefined,
		validationDelay: 100,
		validateOnSubmit : false,
		validateOnChange : true,
		validateOnType : false,
		hideErrorMessage : false,
		inputContainer : undefined,
		errorCssClass : 'error',
		successCssClass : 'success',
		validatingCssClass : 'validating',
		summaryID : undefined,
		timer: undefined,
		/**
		 * list of attributes to be validated. Each array element is of the following structure:
		 * {
		 *     inputID : 'input-tag-id',
		 *     errorID : 'error-tag-id',
		 *     value : undefined,
		 *     status : 0,  // 0: not validated,  1: validated, 2: pending validation, 3: validating
		 *     validationDelay: 100,
		 *     validateOnChange : true,
		 *     validateOnType : false,
		 *     hideErrorMessage : false,
		 *     inputContainer : undefined,
		 *     errorCssClass : 'error',
		 *     successCssClass : 'success',
		 *     validatingCssClass : 'validating',
		 * }
		 */
		attributes : []
	};

	$.fn.yiiactiveform.settings = {};

})(jQuery);<commit_msg><commit_after>/**
 * jQuery yiiactiveform plugin file.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright © 2008-2010 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * @version $Id$
 * @since 1.1.1
 */

;(function($) {
	/**
	 * yiiactiveform set function.
	 * @param map settings for the active form plugin. Please see {@link CActiveForm::options} for availablel options.
	 */
	$.fn.yiiactiveform = function(settings) {
		var settings = $.extend({}, $.fn.yiiactiveform.defaults, settings || {});
		return this.each(function() {
			var $form = $(this);
			var id = $form.attr('id');
			if(settings.validationUrl == undefined)
				settings.validationUrl = $form.attr('action');
			$.each(settings.attributes, function(i,attribute){
				settings.attributes[i] = $.extend({
					validationDelay : settings.validationDelay,
					validateOnChange : settings.validateOnChange,
					validateOnType : settings.validateOnType,
					hideErrorMessage : settings.hideErrorMessage,
					inputContainer : settings.inputContainer,
					errorCssClass : settings.errorCssClass,
					successCssClass : settings.successCssClass,
					validatingCssClass : settings.validatingCssClass
				}, attribute);
				settings.attributes[i].value = $('#'+attribute.inputID).val();
			});
			$.fn.yiiactiveform.settings[id] = settings;

			var getInputContainer = function(attribute) {
				if(attribute.inputContainer == undefined)
					return $('#'+attribute.inputID).closest('div');
				else
					return $(attribute.inputContainer).filter(':has("#'+attribute.inputID+'")');
			};

			// updates the error message and the input container for a particular attribute
			var updateInput = function(attribute, messages) {
				attribute.status = 1;
				var hasError = messages && $.isArray(messages[attribute.inputID]) && messages[attribute.inputID].length>0;
				var $error = $('#'+attribute.errorID);
				var $container = getInputContainer(attribute);
				$container.removeClass(attribute.validatingCssClass)
					.removeClass(attribute.errorCssClass)
					.removeClass(attribute.successCssClass);

				if(hasError) {
					$error.html(messages[attribute.inputID][0]);
					$container.addClass(attribute.errorCssClass);
				}
				else {
					$container.addClass(attribute.successCssClass);
				}
				if(!attribute.hideErrorMessage)
					$error.toggle(hasError);

				attribute.value = $('#'+attribute.inputID).val();

				return hasError;
			};

			// updates the error summary
			var updateSummary = function(messages) {
				if (settings.summaryID == undefined)
					return;
				var content = '';
				$.each(settings.attributes, function(i, attribute){
					if(messages && $.isArray(messages[attribute.inputID])) {
						$.each(messages[attribute.inputID],function(j,message){
							content = content + '
' + message + '
';
						});
					}
				});
				$('#'+settings.summaryID+' ul').html(content);
				$('#'+settings.summaryID).toggle(content!='');
			}

			// performs AJAX validation
			var ajaxValidate = function(successCallback) {
				$.ajax({
					url : settings.validationUrl,
					type : $form.attr('method'),
					data : $form.serialize()+'&'+settings.ajaxVar+'='+id,
					dataType : 'json',
					success : successCallback,
					error : function() {
						$.each(settings.attributes, function(i, attribute){
							//updateInput(attribute, []);
						});
					}
				});
			};

			var validate = function(attribute, forceValidate) {
				if (forceValidate)
					attribute.status = 2;
				$.each(settings.attributes, function(){
					if (this.value != $('#'+this.inputID).val()) {
						this.status = 2;
						forceValidate = true;
					}
				});
				if (!forceValidate)
					return;

				if(settings.timer!=undefined)
					clearTimeout(settings.timer);
				settings.timer = setTimeout(function(){
					$.each(settings.attributes, function(){
						if (this.status == 2) {
							this.status = 3;
							getInputContainer(this).addClass(this.validatingCssClass);
						}
					});
					ajaxValidate(function(data) {
						$.each(settings.attributes, function(){
							if (this.status == 3) {
								updateInput(this, data);
							}
						});
					});
				}, attribute.validationDelay);
			};

			$.each(settings.attributes, function(i, attribute) {
				if (attribute.validateOnChange) {
					$('#'+attribute.inputID).change(function(){
						validate(attribute,false);
					}).blur(function(){
						if(attribute.status!=2 && attribute.status!=3)
							validate(attribute, !attribute.status);
					});
				}
				if (attribute.validateOnType) {
					$('#'+attribute.inputID).keyup(function(){
						if (attribute.value != $('#'+attribute.inputID).val())
							validate(attribute, false);
					});
				}
			});

			if (settings.validateOnSubmit) {
				var validated = false;
				$form.submit(function(){
					if (validated)
						return true;
					ajaxValidate(function(data){
						var hasError = false;
						$.each(settings.attributes, function(i, attribute){
							hasError = updateInput(attribute, data) || hasError;
						});
						updateSummary(data);
						if(!hasError) {
							validated = true;
							$form.submit();
							validated = false;
						}
					});
					return false;
				});
			}
		});
	};

	$.fn.yiiactiveform.defaults = {
		ajaxVar: 'ajax',
		validationUrl: undefined,
		validationDelay: 100,
		validateOnSubmit : false,
		validateOnChange : true,
		validateOnType : false,
		hideErrorMessage : false,
		inputContainer : undefined,
		errorCssClass : 'error',
		successCssClass : 'success',
		validatingCssClass : 'validating',
		summaryID : undefined,
		timer: undefined,
		/**
		 * list of attributes to be validated. Each array element is of the following structure:
		 * {
		 *     inputID : 'input-tag-id',
		 *     errorID : 'error-tag-id',
		 *     value : undefined,
		 *     status : 0,  // 0: not validated,  1: validated, 2: pending validation, 3: validating
		 *     validationDelay: 100,
		 *     validateOnChange : true,
		 *     validateOnType : false,
		 *     hideErrorMessage : false,
		 *     inputContainer : undefined,
		 *     errorCssClass : 'error',
		 *     successCssClass : 'success',
		 *     validatingCssClass : 'validating',
		 * }
		 */
		attributes : []
	};

	$.fn.yiiactiveform.settings = {};

})(jQuery);<|endoftext|>


<commit_before>import ChartWidget from "../widgets/chart_widget";
import BaseWidget from "../widgets/base_widget";
import ShortcutWidget from "../widgets/shortcut_widget";
import LinksWidget from "../widgets/links_widget";
import OnboardingWidget from "../widgets/onboarding_widget";
import NewWidget from "../widgets/new_widget";

frappe.provide('frappe.widget')

const widget_factory = {
	chart: ChartWidget,
	base: BaseWidget,
	shortcut: ShortcutWidget,
	links: LinksWidget,
	onboarding: OnboardingWidget,
	new: NewWidget
};

export default class WidgetGroup {
	constructor(opts) {
		Object.assign(this, opts);
		this.widgets_list = [];
		this.widgets_dict = {};
		this.widget_order = [];
		this.make();
	}

	make() {
		this.make_container();
		this.title && this.set_title(this.title);
		this.widgets && this.make_widgets();
	}

	make_container() {
		const widget_area = $(`

`);
		this.widget_area = widget_area;
		this.title_area = widget_area.find(".widget-group-title");
		this.control_area = widget_area.find(".widget-group-control");
		this.body = widget_area.find(".widget-group-body");
		!this.widgets.length && this.widget_area.hide();
		widget_area.appendTo(this.container);
	}

	set_title(title) {
		this.title_area[0].innerText = this.title;
	}

	make_widgets() {
		this.body.empty()
		this.widgets.forEach(widget => {
			this.add_widget(widget)
		});
	}

	add_widget(widget) {
		const widget_class = widget_factory[this.type];

		let widget_object = new widget_class({
			...widget,
			container: this.body,
			options: {
				...this.options,
				on_delete: (name) => this.on_delete(name)
			}
		});

		this.widgets_list.push(widget_object);
		this.widgets_dict[widget.name] = widget_object;
	}

	customize() {
		this.widget_area.show();
		this.widgets_list.forEach(wid => {
			wid.customize(this.options);
		})

		const max = this.options
					? this.options.max_widget_count || Number.POSITIVE_INFINITY
					: Number.POSITIVE_INFINITY;

		if (this.options.allow_create && this.widgets_list.length < max) {
			this.new_widget = new NewWidget({
				container: this.body,
				type: this.type,
				on_create: (config) => {
					this.new_widget.delete();
					this.add_widget(config);
					this.customize();
				}
			})
		}

		this.options.allow_sorting && this.setup_sortable();
	}

	on_delete(name) {
		this.widgets_list = this.widgets_list.filter(wid => name != wid.name);
		delete this.widgets_dict[name];
		this.update_widget_order();
	}

	update_widget_order() {
		this.widget_order = [];
		this.body.children().each((index, element) => {
			let name = element.dataset.widgetName;
			if (name) {
				this.widget_order.push(name);
			}
		})
	}

	setup_sortable() {
		const container = this.body[0];
		this.sortable = new Sortable(container, {
			animation: 150,
			handle: ".drag-handle",
			onEnd: () => this.update_widget_order(),
		});
	}

	get_widget_config() {
		this.update_widget_order();
		let prepared_dict = {};

		this.widgets_list.forEach(wid => {
			let config = wid.get_config()
			let name = config.docname ? config.docname : config.name
			prepared_dict[name] = config
		});

		return {
			order: this.widget_order,
			widgets: prepared_dict
		}
	}
}

frappe.widget.WidgetGroup = WidgetGroup;<commit_msg>fix: new_widget shows if max count not exceeded<commit_after>import ChartWidget from "../widgets/chart_widget";
import BaseWidget from "../widgets/base_widget";
import ShortcutWidget from "../widgets/shortcut_widget";
import LinksWidget from "../widgets/links_widget";
import OnboardingWidget from "../widgets/onboarding_widget";
import NewWidget from "../widgets/new_widget";

frappe.provide('frappe.widget')

const widget_factory = {
	chart: ChartWidget,
	base: BaseWidget,
	shortcut: ShortcutWidget,
	links: LinksWidget,
	onboarding: OnboardingWidget,
	new: NewWidget
};

export default class WidgetGroup {
	constructor(opts) {
		Object.assign(this, opts);
		this.widgets_list = [];
		this.widgets_dict = {};
		this.widget_order = [];
		this.make();
	}

	make() {
		this.make_container();
		this.title && this.set_title(this.title);
		this.widgets && this.make_widgets();
	}

	make_container() {
		const widget_area = $(`

`);
		this.widget_area = widget_area;
		this.title_area = widget_area.find(".widget-group-title");
		this.control_area = widget_area.find(".widget-group-control");
		this.body = widget_area.find(".widget-group-body");
		!this.widgets.length && this.widget_area.hide();
		widget_area.appendTo(this.container);
	}

	set_title(title) {
		this.title_area[0].innerText = this.title;
	}

	make_widgets() {
		this.body.empty()
		this.widgets.forEach(widget => {
			this.add_widget(widget)
		});
	}

	add_widget(widget) {
		const widget_class = widget_factory[this.type];

		let widget_object = new widget_class({
			...widget,
			container: this.body,
			options: {
				...this.options,
				on_delete: (name) => this.on_delete(name)
			}
		});

		this.widgets_list.push(widget_object);
		this.widgets_dict[widget.name] = widget_object;

		return widget_object
	}

	customize() {
		this.widget_area.show();
		this.widgets_list.forEach(wid => {
			wid.customize(this.options);
		})

		this.options.allow_create && this.setup_new_widget();
		this.options.allow_sorting && this.setup_sortable();
	}

	setup_new_widget() {
		const max = this.options
					? this.options.max_widget_count || Number.POSITIVE_INFINITY
					: Number.POSITIVE_INFINITY;

		if (this.widgets_list.length < max) {
			this.new_widget = new NewWidget({
				container: this.body,
				type: this.type,
				on_create: (config) => {
					// Remove new widget
					this.new_widget.delete();
					delete this.new_widget;

					// Add new widget and customize it
					let wid = this.add_widget(config);
					wid.customize(this.options);

					// Put back the new widget if required
					if (this.widgets_list.length < max) {
						this.setup_new_widget();
					}
				}
			})
		}
	}

	on_delete(name) {
		this.widgets_list = this.widgets_list.filter(wid => name != wid.name);
		delete this.widgets_dict[name];
		this.update_widget_order();

		if (!this.new_widget) this.setup_new_widget();
	}

	update_widget_order() {
		this.widget_order = [];
		this.body.children().each((index, element) => {
			let name = element.dataset.widgetName;
			if (name) {
				this.widget_order.push(name);
			}
		})
	}

	setup_sortable() {
		const container = this.body[0];
		this.sortable = new Sortable(container, {
			animation: 150,
			handle: ".drag-handle",
			onEnd: () => this.update_widget_order(),
		});
	}

	get_widget_config() {
		this.update_widget_order();
		let prepared_dict = {};

		this.widgets_list.forEach(wid => {
			let config = wid.get_config()
			let name = config.docname ? config.docname : config.name
			prepared_dict[name] = config
		});

		return {
			order: this.widget_order,
			widgets: prepared_dict
		}
	}
}

frappe.widget.WidgetGroup = WidgetGroup;<|endoftext|>


<commit_before>import * as twitter from '../apis/twitter';

import {
    GraphQLSchema,
    GraphQLObjectType,
    GraphQLString,
    GraphQLNonNull,
    GraphQLInt,
    GraphQLList,
} from 'graphql';

let UserType = new GraphQLObjectType({

    name: 'TwitterUser',
    description: 'Twitter user, or as we like to say in France: a \'tweetos\'',
    fields: () => ({
        created_at: { type: GraphQLString },
        description: { type: GraphQLString },
        id: { type: GraphQLInt },
        screen_name: { type: GraphQLString },
        name: { type: GraphQLString },
        profile_image_url: { type: GraphQLString },
        url: { type: GraphQLString },
        tweets_count: {
            type: GraphQLInt,
            resolve: ({ statuses_count: tweets_count }) => tweets_count
        },
        followers_count: { type: GraphQLInt },
        tweets: {
            type: new GraphQLList(TweetType),
            description: 'Get a list of tweets for current user',
            args: {
                limit: { type: GraphQLInt }
            },

            //             user            args
            resolve: ({ id: user_id }, { limit = 10 }) => twitter.getTweets(user_id, limit)
        }
    })

});

let TweetType = new GraphQLObjectType({

    name: 'Tweet',
    description: 'A tweet object',
    fields: () => ({
        id: { type: GraphQLString },
        id_str: { type: GraphQLString },
        created_at: { type: GraphQLString },
        text: { type: GraphQLString },
        retweet_count: { type: GraphQLInt },
        user: {
            type: UserType
        },
        retweets: {
            type: new GraphQLList(RetweetType),
            description: 'Get a list of retweets',
            args: {
                limit: { type: GraphQLInt }
            },
            resolve: ({ id_str: tweetId }, { limit = 5 }) => twitter.getRetweets(tweetId, limit)
        }
    })
});

let RetweetType = new GraphQLObjectType({

    name: 'Retweet',
    description: 'Retweet of a tweet',
    fields: () => ({
        id: { type: GraphQLString },
        created_at: { type: GraphQLString },
        in_reply_to_tweet_id: {
            type: GraphQLString,
            resolve: ({ in_reply_to_status_id }) => in_reply_to_status_id
        },
        in_reply_to_user_id: { type: GraphQLInt },
        in_reply_to_screen_name: { type: GraphQLString },
        retweeted_status: {
            type: TweetType
        },
        user: {
            type: UserType
        }
    })
});

let twitterType = new GraphQLObjectType({

    name: 'TwitterAPI',
    description: 'The Twitter API',
    fields: {
        user: {
            type: UserType,
            args: {
                user_id: {
                    description: 'ID of user account',
                    type: GraphQLInt
                },
                screen_name: {
                    description: 'Screenname of the user',
                    type: GraphQLString
                }
            },
            resolve: (_, { user_id, screen_name }) => {

                const { getUser } = twitter;

                if (!user_id && !screen_name) {
                    return getUser('user_id', 9533042);
                }
                else {

                    if (isNaN(parseInt(user_id))) {
                        return getUser('screen_name', screen_name);
                    }
                    else {
                        return getUser('user_id', user_id);
                    }
                }
            }
        },
        tweet: {
            type: TweetType,
            args: {
                id: {
                    type: new GraphQLNonNull(GraphQLString),
                    description: 'Unique ID of tweet'
                }
            },
            resolve: (_, { id: tweetId }) => twitter.getTweet(tweetId)
        },
        search: {
            type: new GraphQLList(TweetType),
            description: "Returns a collection of relevant Tweets matching a specified query.",
            args: {
                q: {
                    type: new GraphQLNonNull(GraphQLString),
                    description: "A UTF-8, URL-encoded search query of 500 characters maximum, including operators. Queries may additionally be limited by complexity."
                },
                count: {
                    type: GraphQLInt,
                    description: "The number of tweets to return per page, up to a maximum of 100. Defaults to 15. This was formerly the “rpp” parameter in the old Search API."
                },
                result_type: {
                    type: GraphQLString,
                    description: `Specifies what type of search results you would prefer to receive. The current default is “mixed.” Valid values include:
                    * mixed: Include both popular and real time results in the response.
                    * recent: return only the most recent results in the response
                    * popular: return only the most popular results in the response.`
                }
            },
            resolve: (_, searchArgs) => twitter.searchFor(searchArgs)
        }
    }
});

export const Schema = {
    query: {
        type: twitterType,
        resolve() {
            return {};
        }
    }
};<commit_msg>use GraphQLID to represents object id's<commit_after>import * as twitter from '../apis/twitter';

import {
    GraphQLSchema,
    GraphQLObjectType,
    GraphQLID,
    GraphQLString,
    GraphQLNonNull,
    GraphQLInt,
    GraphQLList,
} from 'graphql';

let UserType = new GraphQLObjectType({

    name: 'TwitterUser',
    description: 'Twitter user, or as we like to say in France: a \'tweetos\'',
    fields: () => ({
        created_at: { type: GraphQLString },
        description: { type: GraphQLString },
        id: { type: GraphQLID }, // GraphQLInt would return null
        screen_name: { type: GraphQLString },
        name: { type: GraphQLString },
        profile_image_url: { type: GraphQLString },
        url: { type: GraphQLString },
        tweets_count: {
            type: GraphQLInt,
            resolve: ({ statuses_count: tweets_count }) => tweets_count
        },
        followers_count: { type: GraphQLInt },
        tweets: {
            type: new GraphQLList(TweetType),
            description: 'Get a list of tweets for current user',
            args: {
                limit: { type: GraphQLInt }
            },

            //             user            args
            resolve: ({ id: user_id }, { limit = 10 }) => twitter.getTweets(user_id, limit)
        }
    })

});

let TweetType = new GraphQLObjectType({

    name: 'Tweet',
    description: 'A tweet object',
    fields: () => ({
        id: { type: GraphQLID },
        id_str: { type: GraphQLString },
        created_at: { type: GraphQLString },
        text: { type: GraphQLString },
        retweet_count: { type: GraphQLInt },
        user: {
            type: UserType
        },
        retweets: {
            type: new GraphQLList(RetweetType),
            description: 'Get a list of retweets',
            args: {
                limit: { type: GraphQLInt }
            },
            resolve: ({ id_str: tweetId }, { limit = 5 }) => twitter.getRetweets(tweetId, limit)
        }
    })
});

let RetweetType = new GraphQLObjectType({

    name: 'Retweet',
    description: 'Retweet of a tweet',
    fields: () => ({
        id: { type: GraphQLID },
        created_at: { type: GraphQLString },
        in_reply_to_tweet_id: {
            type: GraphQLString,
            resolve: ({ in_reply_to_status_id }) => in_reply_to_status_id
        },
        in_reply_to_user_id: { type: GraphQLInt },
        in_reply_to_screen_name: { type: GraphQLString },
        retweeted_status: {
            type: TweetType
        },
        user: {
            type: UserType
        }
    })
});

let twitterType = new GraphQLObjectType({

    name: 'TwitterAPI',
    description: 'The Twitter API',
    fields: {
        user: {
            type: UserType,
            args: {
                user_id: {
                    description: 'ID of user account',
                    type: GraphQLInt
                },
                screen_name: {
                    description: 'Screenname of the user',
                    type: GraphQLString
                }
            },
            resolve: (_, { user_id, screen_name }) => {

                const { getUser } = twitter;

                if (!user_id && !screen_name) {
                    return getUser('user_id', 9533042);
                }
                else {

                    if (isNaN(parseInt(user_id))) {
                        return getUser('screen_name', screen_name);
                    }
                    else {
                        return getUser('user_id', user_id);
                    }
                }
            }
        },
        tweet: {
            type: TweetType,
            args: {
                id: {
                    type: new GraphQLNonNull(GraphQLString),
                    description: 'Unique ID of tweet'
                }
            },
            resolve: (_, { id: tweetId }) => twitter.getTweet(tweetId)
        },
        search: {
            type: new GraphQLList(TweetType),
            description: "Returns a collection of relevant Tweets matching a specified query.",
            args: {
                q: {
                    type: new GraphQLNonNull(GraphQLString),
                    description: "A UTF-8, URL-encoded search query of 500 characters maximum, including operators. Queries may additionally be limited by complexity."
                },
                count: {
                    type: GraphQLInt,
                    description: "The number of tweets to return per page, up to a maximum of 100. Defaults to 15. This was formerly the “rpp” parameter in the old Search API."
                },
                result_type: {
                    type: GraphQLString,
                    description: `Specifies what type of search results you would prefer to receive. The current default is “mixed.” Valid values include:
                    * mixed: Include both popular and real time results in the response.
                    * recent: return only the most recent results in the response
                    * popular: return only the most popular results in the response.`
                }
            },
            resolve: (_, searchArgs) => twitter.searchFor(searchArgs)
        }
    }
});

export const Schema = {
    query: {
        type: twitterType,
        resolve() {
            return {};
        }
    }
};<|endoftext|>