<commit_before>;(function(exports){
// -- Popbox by otarim
// todo: show(timeout)  ---close(timeout)
function preventDefault(e){
	e = window.event || e;
	e.preventDefault ? e.preventDefault() : e.returnValue = false;
	return true;
}
function getData(el, property) {
	return 'dataset' in el ? el.dataset[property] : el.getAttribute('data-' + property);
}
function setData(el, property, value) {
	return 'dataset' in el ? (el.dataset[property] = value) : (el.setAttribute('data-' + property,value))
}
var eventHub = {};
var isIE = !-[1,];
var specialTypes = {
	mouseenter : {
		type: 'mouseover',
		target: 'fromElement'
	},
	mouseleave: {
		type: 'mouseout',
		target: 'toElement'
	},
	focus: (isIE ? 'focusin' : 'focus'),
	blur: (isIE ? 'focusout' : 'blur')
}

var addEvent = (function() {
	var contains = function(el,target){
		if(el.compareDocumentPosition){
			return (el.compareDocumentPosition(target) & 16) !== 0;
		}else{
			return el.contains(target);
		}
	}
	var bindEvent = function(el,type,callback,rpk){
		var _callback = callback,useCapture = false,
			target,_type;
		if(type === 'mouseenter' || type === 'mouseleave'){
			_type = type;
			type = specialTypes[_type]['type'];
			callback = function(e){
				var e = window.event || e;
				target = e.relatedTarget || e[specialTypes[_type]['target']];
				if(contains(el,target) || el === target){
					e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
				}else{
					_callback.call(el,e);
				}
			}
			eventHub[_type] = eventHub[_type] || [];
			eventHub[_type].push({
				_callback: _callback,
				callback: callback
			});
		}
		if(type === 'blur' || type === 'focus'){
			useCapture = true;
			type = specialTypes[type];
		}
		return rpk.call(el,type,callback,useCapture);

	}
	if (typeof addEventListener === 'function') {
		return function(el, type, callback) {
			bindEvent(el, type, callback,function(type,callback,useCapture){
				return el.addEventListener(type, callback, useCapture);
			});
		}
	} else {
		return function(el, type, callback) {
			bindEvent(el, type, callback,function(type,callback){
				return el.attachEvent('on'+type, callback);
			});
		}
	}
})();

var removeEvent = (function(){
	var digCallback = function(el,type,callback,rpk){
		var hub,_type,useCapture = false;
		if(type === 'mouseenter' || type === 'mouseleave'){
			hub = eventHub[type];
			_type = type;
			type = specialTypes[_type]['type'];
			for(var i = 0;i < hub.length;i++){
				if(callback === hub[i]['_callback']){
					callback = hub[i]['callback'];
					break;
				}
			}
		}
		if(type === 'blur' || type === 'focus'){
			useCapture = true;
			type = specialTypes[type];
		}
		return rpk.call(el,type,callback,useCapture);
	}
	if (typeof removeEventListener === 'function') {
		return function(el, type, callback) {
			digCallback(el,type,callback,function(type,callback,useCapture){
				return el.removeEventListener(type,callback,useCapture);
			})
		}
	} else {
		return function(el, type, callback) {
			digCallback(el, type, callback,function(type,callback){
				return el.attachEvent('on'+type, callback);
			});
		}
	}
})();
function Popbox(config){
	// default layout
	var wrap = this.el = document.createElement('div');
	var defaultEvent = {
		'click#popClose': this.close
	};
	this.events = config && config.events && Popbox.merge(defaultEvent,config.events) || defaultEvent;
	wrap.className = 'popbox-container_';
	wrap.style.cssText += ';position: fixed;_position: absolute;top: 50%;left: 50%;-webkit-transform: translate(-50%,-50%);-moz-transform: translate(-50%,-50%);-o-transform: translate(-50%,-50%);-ms-transform: translate(-50%,-50%);transform: translate(-50%,-50%);display: none';
	config.style && (wrap.style.cssText += Popbox.coStyle(config.style));
	wrap.innerHTML = config && config.el && config.el.call(this,this.el) || '';
	document.body.insertBefore(wrap, document.body.firstChild);
	this.bind();
}

Popbox.merge = function(obj,target){
	for(var i in target){
		if(target.hasOwnProperty(i)){
			obj[i] = target[i];
		}
	}
	return obj;
}

Popbox.coStyle = function(styleList){
	var ret = [';'];
	for(var i in styleList){
		if(styleList.hasOwnProperty(i)){
			ret.push(i + ':' + styleList[i]);
		}
	}
	return ret.join(';')
}

Popbox.prototype = {
	reDraw: function(callback,styleObj){
		styleObj && (this.el.style.cssText += Popbox.coStyle(styleObj));
		this.el.innerHTML = callback.call(this,this.el);
		this.ieFix();
		return this;
	},
	bind: function(){
		var eventList = this.events,
			self = this;
		var getEventList = function(target){
			return getData(target,'event') && getData(target,'event').split(',') || [];
		}
		var matchEvent = function(eventType,eventName){
			if(typeof [].indexOf === 'function'){
				return eventType.indexOf(eventName) !== -1
			}else{
				for(var i = 0,l = eventType.length;i < l;i++){
					if(eventType[i] === eventName){
						return true;
					}
				}
				return false;
			}
		}
		for(var i in eventList){
			if(eventList.hasOwnProperty(i)){
				(function(i){
					var customEvent = i.split('#');
					var callback = function(e){
						e = window.event || e;
						var target = e.srcElement || e.target,
							eventType = getEventList(target);
						if(matchEvent(eventType,customEvent[1])){
							eventList[i].call(self,e,target);
						}
					}
					addEvent(self.el,customEvent[0],callback);
				})(i)
			}
		}
	},
	close: function(){
		this.el.style.cssText += ';display: none;';
		return this;
	},
	show: function(){
		this.el.style.cssText += ';display: block;';
		this.ieFix();
		return this;
	},
	remove: function(){
		document.body.removeChild(this.el);
	},
	ieFix: function(){
		// Ԫò layout
		var offX,offY;
		if(!-[1,]){
			offX = -this.el.offsetWidth / 2 + 'px';
			offY = -this.el.offsetHeight / 2 + 'px';
			this.el.style.cssText += ';margin-top: ' + offY + ';margin-left: ' + offX;
		}
	}
}
exports.Popbox = Popbox;
})(window)<commit_msg>fix charset<commit_after>;(function(exports){
// -- Popbox by otarim
// todo: show(timeout)  ---close(timeout)
function preventDefault(e){
	e = window.event || e;
	e.preventDefault ? e.preventDefault() : e.returnValue = false;
	return true;
}
function getData(el, property) {
	return 'dataset' in el ? el.dataset[property] : el.getAttribute('data-' + property);
}
function setData(el, property, value) {
	return 'dataset' in el ? (el.dataset[property] = value) : (el.setAttribute('data-' + property,value))
}
var eventHub = {};
var isIE = !-[1,];
var specialTypes = {
	mouseenter : {
		type: 'mouseover',
		target: 'fromElement'
	},
	mouseleave: {
		type: 'mouseout',
		target: 'toElement'
	},
	focus: (isIE ? 'focusin' : 'focus'),
	blur: (isIE ? 'focusout' : 'blur')
}

var addEvent = (function() {
	var contains = function(el,target){
		if(el.compareDocumentPosition){
			return (el.compareDocumentPosition(target) & 16) !== 0;
		}else{
			return el.contains(target);
		}
	}
	var bindEvent = function(el,type,callback,rpk){
		var _callback = callback,useCapture = false,
			target,_type;
		if(type === 'mouseenter' || type === 'mouseleave'){
			_type = type;
			type = specialTypes[_type]['type'];
			callback = function(e){
				var e = window.event || e;
				target = e.relatedTarget || e[specialTypes[_type]['target']];
				if(contains(el,target) || el === target){
					e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
				}else{
					_callback.call(el,e);
				}
			}
			eventHub[_type] = eventHub[_type] || [];
			eventHub[_type].push({
				_callback: _callback,
				callback: callback
			});
		}
		if(type === 'blur' || type === 'focus'){
			useCapture = true;
			type = specialTypes[type];
		}
		return rpk.call(el,type,callback,useCapture);

	}
	if (typeof addEventListener === 'function') {
		return function(el, type, callback) {
			bindEvent(el, type, callback,function(type,callback,useCapture){
				return el.addEventListener(type, callback, useCapture);
			});
		}
	} else {
		return function(el, type, callback) {
			bindEvent(el, type, callback,function(type,callback){
				return el.attachEvent('on'+type, callback);
			});
		}
	}
})();

var removeEvent = (function(){
	var digCallback = function(el,type,callback,rpk){
		var hub,_type,useCapture = false;
		if(type === 'mouseenter' || type === 'mouseleave'){
			hub = eventHub[type];
			_type = type;
			type = specialTypes[_type]['type'];
			for(var i = 0;i < hub.length;i++){
				if(callback === hub[i]['_callback']){
					callback = hub[i]['callback'];
					break;
				}
			}
		}
		if(type === 'blur' || type === 'focus'){
			useCapture = true;
			type = specialTypes[type];
		}
		return rpk.call(el,type,callback,useCapture);
	}
	if (typeof removeEventListener === 'function') {
		return function(el, type, callback) {
			digCallback(el,type,callback,function(type,callback,useCapture){
				return el.removeEventListener(type,callback,useCapture);
			})
		}
	} else {
		return function(el, type, callback) {
			digCallback(el, type, callback,function(type,callback){
				return el.attachEvent('on'+type, callback);
			});
		}
	}
})();
function Popbox(config){
	// default layout
	var wrap = this.el = document.createElement('div');
	var defaultEvent = {
		'click#popClose': this.close
	};
	this.events = config && config.events && Popbox.merge(defaultEvent,config.events) || defaultEvent;
	wrap.className = 'popbox-container_';
	wrap.style.cssText += ';position: fixed;_position: absolute;top: 50%;left: 50%;-webkit-transform: translate(-50%,-50%);-moz-transform: translate(-50%,-50%);-o-transform: translate(-50%,-50%);-ms-transform: translate(-50%,-50%);transform: translate(-50%,-50%);display: none';
	config.style && (wrap.style.cssText += Popbox.coStyle(config.style));
	wrap.innerHTML = config && config.el && config.el.call(this,this.el) || '';
	document.body.insertBefore(wrap, document.body.firstChild);
	this.bind();
}

Popbox.merge = function(obj,target){
	for(var i in target){
		if(target.hasOwnProperty(i)){
			obj[i] = target[i];
		}
	}
	return obj;
}

Popbox.coStyle = function(styleList){
	var ret = [';'];
	for(var i in styleList){
		if(styleList.hasOwnProperty(i)){
			ret.push(i + ':' + styleList[i]);
		}
	}
	return ret.join(';')
}

Popbox.prototype = {
	reDraw: function(callback,styleObj){
		styleObj && (this.el.style.cssText += Popbox.coStyle(styleObj));
		this.el.innerHTML = callback.call(this,this.el);
		this.ieFix();
		return this;
	},
	bind: function(){
		var eventList = this.events,
			self = this;
		var getEventList = function(target){
			return getData(target,'event') && getData(target,'event').split(',') || [];
		}
		var matchEvent = function(eventType,eventName){
			if(typeof [].indexOf === 'function'){
				return eventType.indexOf(eventName) !== -1
			}else{
				for(var i = 0,l = eventType.length;i < l;i++){
					if(eventType[i] === eventName){
						return true;
					}
				}
				return false;
			}
		}
		for(var i in eventList){
			if(eventList.hasOwnProperty(i)){
				(function(i){
					var customEvent = i.split('#');
					var callback = function(e){
						e = window.event || e;
						var target = e.srcElement || e.target,
							eventType = getEventList(target);
						if(matchEvent(eventType,customEvent[1])){
							eventList[i].call(self,e,target);
						}
					}
					addEvent(self.el,customEvent[0],callback);
				})(i)
			}
		}
	},
	close: function(){
		this.el.style.cssText += ';display: none;';
		return this;
	},
	show: function(){
		this.el.style.cssText += ';display: block;';
		this.ieFix();
		return this;
	},
	remove: function(){
		document.body.removeChild(this.el);
	},
	ieFix: function(){
		var offX,offY;
		if(!-[1,]){
			offX = -this.el.offsetWidth / 2 + 'px';
			offY = -this.el.offsetHeight / 2 + 'px';
			this.el.style.cssText += ';margin-top: ' + offY + ';margin-left: ' + offX;
		}
	}
}
exports.Popbox = Popbox;
})(window)<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict-local
 * @format
 */

'use strict';

import NativeEventEmitter from '../../EventEmitter/NativeEventEmitter';
import type {EventConfig} from './AnimatedEvent';
import NativeAnimatedModule from './NativeAnimatedModule';
import type {
  EventMapping,
  AnimatedNodeConfig,
  AnimatingNodeConfig,
} from './NativeAnimatedModule';
import type {AnimationConfig, EndCallback} from './animations/Animation';
import type {InterpolationConfigType} from './nodes/AnimatedInterpolation';
import invariant from 'invariant';

let __nativeAnimatedNodeTagCount = 1; /* used for animated nodes */
let __nativeAnimationIdCount = 1; /* used for started animations */

let nativeEventEmitter;

let queueConnections = false;
let queue = [];

/**
 * Simple wrappers around NativeAnimatedModule to provide flow and autocomplete support for
 * the native module methods
 */
const API = {
  enableQueue: function(): void {
    queueConnections = true;
  },
  getValue: function(
    tag: number,
    saveValueCallback: (value: number) => void,
  ): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    if (NativeAnimatedModule.getValue) {
      NativeAnimatedModule.getValue(tag, saveValueCallback);
    }
  },
  disableQueue: function(): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    queueConnections = false;
    for (let q = 0, l = queue.length; q < l; q++) {
      const args = queue[q];
      NativeAnimatedModule.connectAnimatedNodes(args[0], args[1]);
    }
    queue.length = 0;
  },
  createAnimatedNode: function(tag: number, config: AnimatedNodeConfig): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.createAnimatedNode(tag, config);
  },
  startListeningToAnimatedNodeValue: function(tag: number) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.startListeningToAnimatedNodeValue(tag);
  },
  stopListeningToAnimatedNodeValue: function(tag: number) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag);
  },
  connectAnimatedNodes: function(parentTag: number, childTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    if (queueConnections) {
      queue.push([parentTag, childTag]);
      return;
    }
    NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag);
  },
  disconnectAnimatedNodes: function(parentTag: number, childTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag);
  },
  startAnimatingNode: function(
    animationId: number,
    nodeTag: number,
    config: AnimatingNodeConfig,
    endCallback: EndCallback,
  ): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.startAnimatingNode(
      animationId,
      nodeTag,
      config,
      endCallback,
    );
  },
  stopAnimation: function(animationId: number) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.stopAnimation(animationId);
  },
  setAnimatedNodeValue: function(nodeTag: number, value: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value);
  },
  setAnimatedNodeOffset: function(nodeTag: number, offset: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset);
  },
  flattenAnimatedNodeOffset: function(nodeTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag);
  },
  extractAnimatedNodeOffset: function(nodeTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag);
  },
  connectAnimatedNodeToView: function(nodeTag: number, viewTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag);
  },
  disconnectAnimatedNodeFromView: function(
    nodeTag: number,
    viewTag: number,
  ): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag);
  },
  restoreDefaultValues: function(nodeTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    // Backwards compat with older native runtimes, can be removed later.
    if (NativeAnimatedModule.restoreDefaultValues != null) {
      NativeAnimatedModule.restoreDefaultValues(nodeTag);
    }
  },
  dropAnimatedNode: function(tag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.dropAnimatedNode(tag);
  },
  addAnimatedEventToView: function(
    viewTag: number,
    eventName: string,
    eventMapping: EventMapping,
  ) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.addAnimatedEventToView(
      viewTag,
      eventName,
      eventMapping,
    );
  },
  removeAnimatedEventFromView(
    viewTag: number,
    eventName: string,
    animatedNodeTag: number,
  ) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.removeAnimatedEventFromView(
      viewTag,
      eventName,
      animatedNodeTag,
    );
  },
};

/**
 * Styles allowed by the native animated implementation.
 *
 * In general native animated implementation should support any numeric property that doesn't need
 * to be updated through the shadow view hierarchy (all non-layout properties).
 */
const STYLES_WHITELIST = {
  opacity: true,
  transform: true,
  borderRadius: true,
  borderBottomEndRadius: true,
  borderBottomLeftRadius: true,
  borderBottomRightRadius: true,
  borderBottomStartRadius: true,
  borderTopEndRadius: true,
  borderTopLeftRadius: true,
  borderTopRightRadius: true,
  borderTopStartRadius: true,
  elevation: true,
  zIndex: true,
  /* ios styles */
  shadowOpacity: true,
  shadowRadius: true,
  /* legacy android transform properties */
  scaleX: true,
  scaleY: true,
  translateX: true,
  translateY: true,
};

const TRANSFORM_WHITELIST = {
  translateX: true,
  translateY: true,
  scale: true,
  scaleX: true,
  scaleY: true,
  rotate: true,
  rotateX: true,
  rotateY: true,
  rotateZ: true,
  perspective: true,
};

const SUPPORTED_INTERPOLATION_PARAMS = {
  inputRange: true,
  outputRange: true,
  extrapolate: true,
  extrapolateRight: true,
  extrapolateLeft: true,
};

function addWhitelistedStyleProp(prop: string): void {
  STYLES_WHITELIST[prop] = true;
}

function addWhitelistedTransformProp(prop: string): void {
  TRANSFORM_WHITELIST[prop] = true;
}

function addWhitelistedInterpolationParam(param: string): void {
  SUPPORTED_INTERPOLATION_PARAMS[param] = true;
}

function validateTransform(
  configs: Array<
    | {
        type: 'animated',
        property: string,
        nodeTag: ?number,
        ...
      }
    | {
        type: 'static',
        property: string,
        value: number | string,
        ...
      },
  >,
): void {
  configs.forEach(config => {
    if (!TRANSFORM_WHITELIST.hasOwnProperty(config.property)) {
      throw new Error(
        `Property '${config.property}' is not supported by native animated module`,
      );
    }
  });
}

function validateStyles(styles: {[key: string]: ?number, ...}): void {
  for (const key in styles) {
    if (!STYLES_WHITELIST.hasOwnProperty(key)) {
      throw new Error(
        `Style property '${key}' is not supported by native animated module`,
      );
    }
  }
}

function validateInterpolation(config: InterpolationConfigType): void {
  for (const key in config) {
    if (!SUPPORTED_INTERPOLATION_PARAMS.hasOwnProperty(key)) {
      throw new Error(
        `Interpolation property '${key}' is not supported by native animated module`,
      );
    }
  }
}

function generateNewNodeTag(): number {
  return __nativeAnimatedNodeTagCount++;
}

function generateNewAnimationId(): number {
  return __nativeAnimationIdCount++;
}

function assertNativeAnimatedModule(): void {
  invariant(NativeAnimatedModule, 'Native animated module is not available');
}

let _warnedMissingNativeAnimated = false;

function shouldUseNativeDriver(
  config: {...AnimationConfig, ...} | EventConfig,
): boolean {
  if (config.useNativeDriver == null) {
    console.warn(
      'Animated: `useNativeDriver` was not specified. This is a required ' +
        'option and must be explicitly set to `true` or `false`',
    );
  }

  if (config.useNativeDriver === true && !NativeAnimatedModule) {
    if (!_warnedMissingNativeAnimated) {
      console.warn(
        'Animated: `useNativeDriver` is not supported because the native ' +
          'animated module is missing. Falling back to JS-based animation. To ' +
          'resolve this, add `RCTAnimation` module to this app, or remove ' +
          '`useNativeDriver`. ' +
          'Make sure to run `pod install` first. Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md',
      );
      _warnedMissingNativeAnimated = true;
    }
    return false;
  }

  return config.useNativeDriver || false;
}

function transformDataType(value: number | string): number | string {
  // Change the string type to number type so we can reuse the same logic in
  // iOS and Android platform
  if (typeof value !== 'string') {
    return value;
  }
  if (/deg$/.test(value)) {
    const degrees = parseFloat(value) || 0;
    const radians = (degrees * Math.PI) / 180.0;
    return radians;
  } else {
    return value;
  }
}

module.exports = {
  API,
  addWhitelistedStyleProp,
  addWhitelistedTransformProp,
  addWhitelistedInterpolationParam,
  validateStyles,
  validateTransform,
  validateInterpolation,
  generateNewNodeTag,
  generateNewAnimationId,
  assertNativeAnimatedModule,
  shouldUseNativeDriver,
  transformDataType,
  // $FlowExpectedError - unsafe getter lint suppresion
  get nativeEventEmitter(): NativeEventEmitter {
    if (!nativeEventEmitter) {
      nativeEventEmitter = new NativeEventEmitter(NativeAnimatedModule);
    }
    return nativeEventEmitter;
  },
};
<commit_msg>Use more inclusive language in Animated<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict-local
 * @format
 */

'use strict';

import NativeEventEmitter from '../../EventEmitter/NativeEventEmitter';
import type {EventConfig} from './AnimatedEvent';
import NativeAnimatedModule from './NativeAnimatedModule';
import type {
  EventMapping,
  AnimatedNodeConfig,
  AnimatingNodeConfig,
} from './NativeAnimatedModule';
import type {AnimationConfig, EndCallback} from './animations/Animation';
import type {InterpolationConfigType} from './nodes/AnimatedInterpolation';
import invariant from 'invariant';

let __nativeAnimatedNodeTagCount = 1; /* used for animated nodes */
let __nativeAnimationIdCount = 1; /* used for started animations */

let nativeEventEmitter;

let queueConnections = false;
let queue = [];

/**
 * Simple wrappers around NativeAnimatedModule to provide flow and autocomplete support for
 * the native module methods
 */
const API = {
  enableQueue: function(): void {
    queueConnections = true;
  },
  getValue: function(
    tag: number,
    saveValueCallback: (value: number) => void,
  ): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    if (NativeAnimatedModule.getValue) {
      NativeAnimatedModule.getValue(tag, saveValueCallback);
    }
  },
  disableQueue: function(): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    queueConnections = false;
    for (let q = 0, l = queue.length; q < l; q++) {
      const args = queue[q];
      NativeAnimatedModule.connectAnimatedNodes(args[0], args[1]);
    }
    queue.length = 0;
  },
  createAnimatedNode: function(tag: number, config: AnimatedNodeConfig): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.createAnimatedNode(tag, config);
  },
  startListeningToAnimatedNodeValue: function(tag: number) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.startListeningToAnimatedNodeValue(tag);
  },
  stopListeningToAnimatedNodeValue: function(tag: number) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag);
  },
  connectAnimatedNodes: function(parentTag: number, childTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    if (queueConnections) {
      queue.push([parentTag, childTag]);
      return;
    }
    NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag);
  },
  disconnectAnimatedNodes: function(parentTag: number, childTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag);
  },
  startAnimatingNode: function(
    animationId: number,
    nodeTag: number,
    config: AnimatingNodeConfig,
    endCallback: EndCallback,
  ): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.startAnimatingNode(
      animationId,
      nodeTag,
      config,
      endCallback,
    );
  },
  stopAnimation: function(animationId: number) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.stopAnimation(animationId);
  },
  setAnimatedNodeValue: function(nodeTag: number, value: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value);
  },
  setAnimatedNodeOffset: function(nodeTag: number, offset: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset);
  },
  flattenAnimatedNodeOffset: function(nodeTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag);
  },
  extractAnimatedNodeOffset: function(nodeTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag);
  },
  connectAnimatedNodeToView: function(nodeTag: number, viewTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag);
  },
  disconnectAnimatedNodeFromView: function(
    nodeTag: number,
    viewTag: number,
  ): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag);
  },
  restoreDefaultValues: function(nodeTag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    // Backwards compat with older native runtimes, can be removed later.
    if (NativeAnimatedModule.restoreDefaultValues != null) {
      NativeAnimatedModule.restoreDefaultValues(nodeTag);
    }
  },
  dropAnimatedNode: function(tag: number): void {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.dropAnimatedNode(tag);
  },
  addAnimatedEventToView: function(
    viewTag: number,
    eventName: string,
    eventMapping: EventMapping,
  ) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.addAnimatedEventToView(
      viewTag,
      eventName,
      eventMapping,
    );
  },
  removeAnimatedEventFromView(
    viewTag: number,
    eventName: string,
    animatedNodeTag: number,
  ) {
    invariant(NativeAnimatedModule, 'Native animated module is not available');
    NativeAnimatedModule.removeAnimatedEventFromView(
      viewTag,
      eventName,
      animatedNodeTag,
    );
  },
};

/**
 * Styles allowed by the native animated implementation.
 *
 * In general native animated implementation should support any numeric property that doesn't need
 * to be updated through the shadow view hierarchy (all non-layout properties).
 */
const SUPPORTED_STYLES = {
  opacity: true,
  transform: true,
  borderRadius: true,
  borderBottomEndRadius: true,
  borderBottomLeftRadius: true,
  borderBottomRightRadius: true,
  borderBottomStartRadius: true,
  borderTopEndRadius: true,
  borderTopLeftRadius: true,
  borderTopRightRadius: true,
  borderTopStartRadius: true,
  elevation: true,
  zIndex: true,
  /* ios styles */
  shadowOpacity: true,
  shadowRadius: true,
  /* legacy android transform properties */
  scaleX: true,
  scaleY: true,
  translateX: true,
  translateY: true,
};

const SUPPORTED_TRANSFORMS = {
  translateX: true,
  translateY: true,
  scale: true,
  scaleX: true,
  scaleY: true,
  rotate: true,
  rotateX: true,
  rotateY: true,
  rotateZ: true,
  perspective: true,
};

const SUPPORTED_INTERPOLATION_PARAMS = {
  inputRange: true,
  outputRange: true,
  extrapolate: true,
  extrapolateRight: true,
  extrapolateLeft: true,
};

function addWhitelistedStyleProp(prop: string): void {
  SUPPORTED_STYLES[prop] = true;
}

function addWhitelistedTransformProp(prop: string): void {
  SUPPORTED_TRANSFORMS[prop] = true;
}

function addWhitelistedInterpolationParam(param: string): void {
  SUPPORTED_INTERPOLATION_PARAMS[param] = true;
}

function validateTransform(
  configs: Array<
    | {
        type: 'animated',
        property: string,
        nodeTag: ?number,
        ...
      }
    | {
        type: 'static',
        property: string,
        value: number | string,
        ...
      },
  >,
): void {
  configs.forEach(config => {
    if (!SUPPORTED_TRANSFORMS.hasOwnProperty(config.property)) {
      throw new Error(
        `Property '${config.property}' is not supported by native animated module`,
      );
    }
  });
}

function validateStyles(styles: {[key: string]: ?number, ...}): void {
  for (const key in styles) {
    if (!SUPPORTED_STYLES.hasOwnProperty(key)) {
      throw new Error(
        `Style property '${key}' is not supported by native animated module`,
      );
    }
  }
}

function validateInterpolation(config: InterpolationConfigType): void {
  for (const key in config) {
    if (!SUPPORTED_INTERPOLATION_PARAMS.hasOwnProperty(key)) {
      throw new Error(
        `Interpolation property '${key}' is not supported by native animated module`,
      );
    }
  }
}

function generateNewNodeTag(): number {
  return __nativeAnimatedNodeTagCount++;
}

function generateNewAnimationId(): number {
  return __nativeAnimationIdCount++;
}

function assertNativeAnimatedModule(): void {
  invariant(NativeAnimatedModule, 'Native animated module is not available');
}

let _warnedMissingNativeAnimated = false;

function shouldUseNativeDriver(
  config: {...AnimationConfig, ...} | EventConfig,
): boolean {
  if (config.useNativeDriver == null) {
    console.warn(
      'Animated: `useNativeDriver` was not specified. This is a required ' +
        'option and must be explicitly set to `true` or `false`',
    );
  }

  if (config.useNativeDriver === true && !NativeAnimatedModule) {
    if (!_warnedMissingNativeAnimated) {
      console.warn(
        'Animated: `useNativeDriver` is not supported because the native ' +
          'animated module is missing. Falling back to JS-based animation. To ' +
          'resolve this, add `RCTAnimation` module to this app, or remove ' +
          '`useNativeDriver`. ' +
          'Make sure to run `pod install` first. Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md',
      );
      _warnedMissingNativeAnimated = true;
    }
    return false;
  }

  return config.useNativeDriver || false;
}

function transformDataType(value: number | string): number | string {
  // Change the string type to number type so we can reuse the same logic in
  // iOS and Android platform
  if (typeof value !== 'string') {
    return value;
  }
  if (/deg$/.test(value)) {
    const degrees = parseFloat(value) || 0;
    const radians = (degrees * Math.PI) / 180.0;
    return radians;
  } else {
    return value;
  }
}

module.exports = {
  API,
  addWhitelistedStyleProp,
  addWhitelistedTransformProp,
  addWhitelistedInterpolationParam,
  validateStyles,
  validateTransform,
  validateInterpolation,
  generateNewNodeTag,
  generateNewAnimationId,
  assertNativeAnimatedModule,
  shouldUseNativeDriver,
  transformDataType,
  // $FlowExpectedError - unsafe getter lint suppresion
  get nativeEventEmitter(): NativeEventEmitter {
    if (!nativeEventEmitter) {
      nativeEventEmitter = new NativeEventEmitter(NativeAnimatedModule);
    }
    return nativeEventEmitter;
  },
};
<|endoftext|>


<commit_before>/* Backlog Stats */

var StatsModel = Backbone.Model.extend({
    url: function() {
        return this.get('view').$el.attr('url');
    }
});

var StatsView = Backbone.View.extend({
    el: $(".user-story-stats"),

    initialize: function() {
        _.bindAll(this, 'render');
        this.model = new StatsModel({view:this});
    },

    render: function() {
        var self = this,
            deff = this.model.fetch();

        deff.done(function() {
            self.$el.html(self.model.get('stats_html'));
        });
    }
});

/* Unassigned user storyes (left block) */

var LeftBlockModel = Backbone.Model.extend({
    url: function() {
        return this.get('view').fetch_url();
    }
});

var LeftBlockView = Backbone.View.extend({
    el: $(".left-block"),

    events: {
        "dragstart .unassigned-us .un-us-item": "unassigned_us_dragstart",
        "dragover .left-block .unassigned-us": "left_block_dragover",
        "dragleave .left-block .unassigned-us": "left_block_dragleave",
        "drop .left-block .unassigned-us": "left_block_drop",

        /* Iniline edit */
        "click .unassigned-us .config-us-inline": "on_us_edit_inline",
        "click .unassigned-us .user-story-inline-submit": "on_us_edit_inline_submit",
        "click .unassigned-us .user-story-inline-cancel": "on_us_edit_form_cancel",

        "click .un-us-item .delete": "unassign_us",

        /* Ordering */
        "click .unassigned-us .head-title .row a": "on_order_link_clicked",
    },

    initialize: function() {
        _.bindAll(this, 'render', 'rehash', 'fetch_url');

        this.options.order_by = "-priority";

        this.model = new LeftBlockModel({view:this});
        this.model.on('change', this.render);
        this.model.fetch();
    },

    render: function() {
        this.$('.unassigned-us').html(this.model.get('html'))
    },

    fetch_url: function() {
        var base_url = this.$el.attr('url');
        return base_url + "?order_by=" + this.options.order_by;
    },

    /*
     * Reload state fetching new content from server.
    */

    rehash: function() {
        this.model.fetch({success:this.render});
    },

    on_order_link_clicked: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget);
        var opt = self.attr('order_opt') || undefined;
        if (opt === undefined || opt == "") {
            this.options.order_by = self.attr('order_by');
        } else {
            this.options.order_by = "-" + self.attr('order_by');
        }
        this.model.fetch({success:this.render});
    },

    /*
     * On click to delete button on unassigned user story list.
    */

    unassign_us: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget);
        var buttons = {};
        buttons[gettext('Delete')] = function() {
            $(this).dialog('close');
            $.post(self.attr('href'), {}, function(data) {
                console.log(data);
                self.parents('.un-us-item').remove();
            });
        };

        buttons[gettext('Cancel')] = function() {
            $(this).dialog('close');
        };

        $(".delete-us-dialog").dialog({
            modal: true,
            width: '220px',
            buttons: buttons
        });
    },

    left_block_drop: function(event) {
        var self = $(event.currentTarget);
        if (self.hasClass('drag-over')) {
            self.removeClass('drag-over');
        }

        var source_id = event.originalEvent.dataTransfer.getData('source_id');
        var source = $("#" + source_id);
        var unassign_url = source.attr('unassignurl');
        var stats_view = this.options.stats_view;

        $.post(unassign_url, {}, function(data) {
            self.append(data);
            if(source.parent().find(".us-item").length == 1) {
                source.find(".us-meta").remove()
                source.find(".us-title").html(gettext("No user storys"));
                source.addClass('us-item-empty');
                source.attr('draggable', 'false');
                source.attr('unassignurl', '');
            } else {
                source.remove();
            }

            // Refresh stats
            stats_view.render();
        }, 'html');

    },

    left_block_dragleave: function(event) {
        var self = $(event.currentTarget);
        if (self.hasClass('drag-over')) {
            self.removeClass('drag-over');
        }
        event.preventDefault();
    },

    left_block_dragover: function(event) {
        var self = $(event.currentTarget);
        event.originalEvent.dataTransfer.dropEffect = 'copy';
        event.preventDefault();
    },

    unassigned_us_dragstart: function(event) {
        var self = $(event.currentTarget);
        event.originalEvent.dataTransfer.effectAllowed = 'copy'; // only dropEffect='copy' will be dropable
        event.originalEvent.dataTransfer.setData('source_id', self.attr('id')); // required otherwise doesn't work
    },

    /*
     * On request visualize a inline edit user story form.
    */

    on_us_edit_inline: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget);
        $.get(self.attr('href'), function(data) {
            self.closest('.un-us-item').find('.form-inline').html(data).show();
        }, 'html');
    },

    /*
     * On inline user story edit form submit changes
    */

    on_us_edit_inline_submit: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget),
            form = self.closest('form'),
            stats_view = this.options.stats_view;

        $.post(form.attr('action'), form.serialize(), function(data) {
            if (data.valid) {
                var usitem = self.closest('.un-us-item');
                usitem.find('.form-inline').hide();

                if (data.action == 'save') {
                    usitem.replaceWith(data.html);
                } else {
                    var ml_id = form.find("#id_milestone").val();
                    var milestone = $("#milestone-" + ml_id);

                    // hide empty entries.
                    milestone.find(".us-item-empty").remove()
                    milestone.find(".milestone-userstorys").append(data.html);
                    usitem.remove();
                }
            } else {
                form.find('.errorlist').remove();
                $.each(data.errors, function(index, value) {
                    var ul = $(document.createElement('ul'))
                        .attr('class', 'errorlist');
                    for(var i=0; i<value.length; i++){
                        $(document.createElement('li')).html(value[i]).appendTo(ul);
                    }

                    form.find('[name='+index+']').before(ul);
                });
            }

            // Refresh stats
            stats_view.render();
        }, 'json');

    },

    on_us_edit_form_cancel: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget);
        self.closest('.un-us-item').find('.form-inline').hide();
    },
});

/* Milestones (right block) */

var MilestonesModel = Backbone.Model.extend({
    url: function() {
        return this.get('view').$el.attr('url');
    }
});

var RightBlockView = Backbone.View.extend({
    el: $(".right-block"),

    events: {
        "dragover .milestones .milestone-item": "milestones_dragover",
        "dragleave .milestones .milestone-item": "milestones_drageleave",
        "drop .milestones .milestone-item": "milestones_on_drop",
        "dragstart .milestones .us-item": "milestones_dragstart",

        /* Milestone delete */
        "click .milestone-item .milestone-title a.delete": "on_milestone_delete_click"
    },

    initialize: function() {
        _.bindAll(this, 'render');
        this.model = new MilestonesModel({view:this});
        this.model.on('change', this.render);
        this.model.fetch();
    },

    render: function() {
        var self = this;
        self.$(".milestones").html(this.model.get('html'));
    },

    milestones_dragover: function(event) {
        event.originalEvent.dataTransfer.dropEffect = 'copy';
        event.preventDefault();

        var self = $(event.currentTarget);

        if (!self.hasClass("drag-over")) {
            self.addClass("drag-over");
        }
    },

    milestones_drageleave: function(event) {
        event.preventDefault();

        var self = $(event.currentTarget);
        if (self.hasClass('drag-over')) {
            self.removeClass('drag-over');
        }
    },

    milestones_on_drop: function(event) {
        var self = $(event.currentTarget);
        if (self.hasClass('drag-over')) {
            self.removeClass('drag-over');
        }

        var source_id = event.originalEvent.dataTransfer.getData('source_id');
        var source = $("#" + source_id);
        var assign_url = source.attr('assignurl');
        var milestone_id = self.attr('ref');
        var stats_view = this.options.stats_view;

        $.post(assign_url, {mid: milestone_id}, function(data) {
            var data_object = $(data);
            self.find(".us-item-empty").remove()
            self.find(".milestone-userstorys").append(data_object);
            source.remove()
            stats_view.render();
        }, 'html');
    },

    milestones_dragstart: function(event) {
        var self = $(event.currentTarget);
        event.originalEvent.dataTransfer.effectAllowed = 'copy';
        event.originalEvent.dataTransfer.setData('source_id', self.attr('id'));
    },

    on_milestone_delete_click: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget),
            buttons = {},
            left_block = this.options.parent.left_block,
            stats_view = this.options.stats_view;

        var buttons = {};
        buttons[gettext('Delete')] = function() {
            $(this).dialog('close');
            $.post(self.attr('href'), {}, function(data) {
                if (data.valid) {
                    self.parents('.milestone-item').remove();
                }
                stats_view.render();
                left_block.rehash();
            }, 'json');
        };

        buttons[gettext('Cancel')] = function() {
            $(this).dialog('close');
        };

        $(".delete-milestone-dialog").dialog({
            modal: true,
            width: '220px',
            buttons: buttons
        });
    }
});

var Backlog = Backbone.View.extend({
    el: $("#dashboard"),

    initialize: function() {
        _.bindAll(this, 'render');

        var stats_view = new StatsView();
        stats_view.render();

        this.left_block = new LeftBlockView({stats_view:stats_view, parent:this});
        this.right_block = new RightBlockView({stats_view:stats_view, parent:this});
    },

    render: function() {},
});

$(function() {
    var backlog = new Backlog();
});
<commit_msg>Improved ordering on backlog. (now required localStorage)<commit_after>/* Backlog Stats */

var StatsModel = Backbone.Model.extend({
    url: function() {
        return this.get('view').$el.attr('url');
    }
});

var StatsView = Backbone.View.extend({
    el: $(".user-story-stats"),

    initialize: function() {
        _.bindAll(this, 'render');
        this.model = new StatsModel({view:this});
    },

    render: function() {
        var self = this,
            deff = this.model.fetch();

        deff.done(function() {
            self.$el.html(self.model.get('stats_html'));
        });
    }
});

/* Unassigned user storyes (left block) */

var LeftBlockModel = Backbone.Model.extend({
    url: function() {
        return this.get('view').fetch_url();
    }
});

var LeftBlockView = Backbone.View.extend({
    el: $(".left-block"),

    events: {
        "dragstart .unassigned-us .un-us-item": "unassigned_us_dragstart",
        "dragover .left-block .unassigned-us": "left_block_dragover",
        "dragleave .left-block .unassigned-us": "left_block_dragleave",
        "drop .left-block .unassigned-us": "left_block_drop",

        /* Iniline edit */
        "click .unassigned-us .config-us-inline": "on_us_edit_inline",
        "click .unassigned-us .user-story-inline-submit": "on_us_edit_inline_submit",
        "click .unassigned-us .user-story-inline-cancel": "on_us_edit_form_cancel",

        "click .un-us-item .delete": "unassign_us",

        /* Ordering */
        "click .unassigned-us .head-title .row a": "on_order_link_clicked",
    },

    initialize: function() {
        _.bindAll(this, 'render', 'rehash', 'fetch_url');

        this.options.order_by = "-priority";

        this.model = new LeftBlockModel({view:this});
        this.model.on('change', this.render);
        this.model.fetch();
    },

    render: function() {
        this.$('.unassigned-us').html(this.model.get('html'))
    },

    fetch_url: function() {
        var base_url = this.$el.attr('url');
        return base_url + "?order_by=" + this.options.order_by;
    },

    /*
     * Reload state fetching new content from server.
    */

    rehash: function() {
        this.model.fetch({success:this.render});
    },

    on_order_link_clicked: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget);

        var order_by = self.attr('order_by');
        var opt_key = "backlog_order_by_" + order_by + "_opt";
        var opt = localStorage.getItem(opt_key)

        if (opt == "" || opt === null) {
            this.options.order_by = order_by;
            localStorage.setItem(opt_key, "-")
        } else {
            this.options.order_by = "-" + order_by;
            localStorage.setItem(opt_key, "");
        }

        this.model.fetch({success:this.render});
    },

    /*
     * On click to delete button on unassigned user story list.
    */

    unassign_us: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget);
        var buttons = {};
        buttons[gettext('Delete')] = function() {
            $(this).dialog('close');
            $.post(self.attr('href'), {}, function(data) {
                console.log(data);
                self.parents('.un-us-item').remove();
            });
        };

        buttons[gettext('Cancel')] = function() {
            $(this).dialog('close');
        };

        $(".delete-us-dialog").dialog({
            modal: true,
            width: '220px',
            buttons: buttons
        });
    },

    left_block_drop: function(event) {
        var self = $(event.currentTarget);
        if (self.hasClass('drag-over')) {
            self.removeClass('drag-over');
        }

        var source_id = event.originalEvent.dataTransfer.getData('source_id');
        var source = $("#" + source_id);
        var unassign_url = source.attr('unassignurl');
        var stats_view = this.options.stats_view;

        $.post(unassign_url, {}, function(data) {
            self.append(data);
            if(source.parent().find(".us-item").length == 1) {
                source.find(".us-meta").remove()
                source.find(".us-title").html(gettext("No user storys"));
                source.addClass('us-item-empty');
                source.attr('draggable', 'false');
                source.attr('unassignurl', '');
            } else {
                source.remove();
            }

            // Refresh stats
            stats_view.render();
        }, 'html');

    },

    left_block_dragleave: function(event) {
        var self = $(event.currentTarget);
        if (self.hasClass('drag-over')) {
            self.removeClass('drag-over');
        }
        event.preventDefault();
    },

    left_block_dragover: function(event) {
        var self = $(event.currentTarget);
        event.originalEvent.dataTransfer.dropEffect = 'copy';
        event.preventDefault();
    },

    unassigned_us_dragstart: function(event) {
        var self = $(event.currentTarget);
        event.originalEvent.dataTransfer.effectAllowed = 'copy'; // only dropEffect='copy' will be dropable
        event.originalEvent.dataTransfer.setData('source_id', self.attr('id')); // required otherwise doesn't work
    },

    /*
     * On request visualize a inline edit user story form.
    */

    on_us_edit_inline: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget);
        $.get(self.attr('href'), function(data) {
            self.closest('.un-us-item').find('.form-inline').html(data).show();
        }, 'html');
    },

    /*
     * On inline user story edit form submit changes
    */

    on_us_edit_inline_submit: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget),
            form = self.closest('form'),
            stats_view = this.options.stats_view;

        $.post(form.attr('action'), form.serialize(), function(data) {
            if (data.valid) {
                var usitem = self.closest('.un-us-item');
                usitem.find('.form-inline').hide();

                if (data.action == 'save') {
                    usitem.replaceWith(data.html);
                } else {
                    var ml_id = form.find("#id_milestone").val();
                    var milestone = $("#milestone-" + ml_id);

                    // hide empty entries.
                    milestone.find(".us-item-empty").remove()
                    milestone.find(".milestone-userstorys").append(data.html);
                    usitem.remove();
                }
            } else {
                form.find('.errorlist').remove();
                $.each(data.errors, function(index, value) {
                    var ul = $(document.createElement('ul'))
                        .attr('class', 'errorlist');
                    for(var i=0; i<value.length; i++){
                        $(document.createElement('li')).html(value[i]).appendTo(ul);
                    }

                    form.find('[name='+index+']').before(ul);
                });
            }

            // Refresh stats
            stats_view.render();
        }, 'json');

    },

    on_us_edit_form_cancel: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget);
        self.closest('.un-us-item').find('.form-inline').hide();
    },
});

/* Milestones (right block) */

var MilestonesModel = Backbone.Model.extend({
    url: function() {
        return this.get('view').$el.attr('url');
    }
});

var RightBlockView = Backbone.View.extend({
    el: $(".right-block"),

    events: {
        "dragover .milestones .milestone-item": "milestones_dragover",
        "dragleave .milestones .milestone-item": "milestones_drageleave",
        "drop .milestones .milestone-item": "milestones_on_drop",
        "dragstart .milestones .us-item": "milestones_dragstart",

        /* Milestone delete */
        "click .milestone-item .milestone-title a.delete": "on_milestone_delete_click"
    },

    initialize: function() {
        _.bindAll(this, 'render');
        this.model = new MilestonesModel({view:this});
        this.model.on('change', this.render);
        this.model.fetch();
    },

    render: function() {
        var self = this;
        self.$(".milestones").html(this.model.get('html'));
    },

    milestones_dragover: function(event) {
        event.originalEvent.dataTransfer.dropEffect = 'copy';
        event.preventDefault();

        var self = $(event.currentTarget);

        if (!self.hasClass("drag-over")) {
            self.addClass("drag-over");
        }
    },

    milestones_drageleave: function(event) {
        event.preventDefault();

        var self = $(event.currentTarget);
        if (self.hasClass('drag-over')) {
            self.removeClass('drag-over');
        }
    },

    milestones_on_drop: function(event) {
        var self = $(event.currentTarget);
        if (self.hasClass('drag-over')) {
            self.removeClass('drag-over');
        }

        var source_id = event.originalEvent.dataTransfer.getData('source_id');
        var source = $("#" + source_id);
        var assign_url = source.attr('assignurl');
        var milestone_id = self.attr('ref');
        var stats_view = this.options.stats_view;

        $.post(assign_url, {mid: milestone_id}, function(data) {
            var data_object = $(data);
            self.find(".us-item-empty").remove()
            self.find(".milestone-userstorys").append(data_object);
            source.remove()
            stats_view.render();
        }, 'html');
    },

    milestones_dragstart: function(event) {
        var self = $(event.currentTarget);
        event.originalEvent.dataTransfer.effectAllowed = 'copy';
        event.originalEvent.dataTransfer.setData('source_id', self.attr('id'));
    },

    on_milestone_delete_click: function(event) {
        event.preventDefault();
        var self = $(event.currentTarget),
            buttons = {},
            left_block = this.options.parent.left_block,
            stats_view = this.options.stats_view;

        var buttons = {};
        buttons[gettext('Delete')] = function() {
            $(this).dialog('close');
            $.post(self.attr('href'), {}, function(data) {
                if (data.valid) {
                    self.parents('.milestone-item').remove();
                }
                stats_view.render();
                left_block.rehash();
            }, 'json');
        };

        buttons[gettext('Cancel')] = function() {
            $(this).dialog('close');
        };

        $(".delete-milestone-dialog").dialog({
            modal: true,
            width: '220px',
            buttons: buttons
        });
    }
});

var Backlog = Backbone.View.extend({
    el: $("#dashboard"),

    initialize: function() {
        _.bindAll(this, 'render');

        var stats_view = new StatsView();
        stats_view.render();

        this.left_block = new LeftBlockView({stats_view:stats_view, parent:this});
        this.right_block = new RightBlockView({stats_view:stats_view, parent:this});
    },

    render: function() {},
});

$(function() {
    var backlog = new Backlog();
});
<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var http = require('http').Server(app);

app.use('/assets', express.static(__dirname + '/assets'));

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});
app.get('/camera.html', function(req, res){
  res.sendFile(__dirname + '/camera.html');
});
app.get('/battery.json', function(req, res){
  res.setHeader('Content-Type', 'application/json');
    res.send(JSON.stringify({ a: 1 }));
});

http.listen(3000, function(){
  console.log('En attente sur *:3000');
});

process.stdin.setRawMode(true);
process.stdin.resume();
<commit_msg>Correction fichier serveur<commit_after>var express = require('express');
var app = express();
var http = require('http').Server(app);

app.use('/assets', express.static(__dirname + '/assets'));

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});
app.get('/camera.html', function(req, res){
  res.sendFile(__dirname + '/camera.html');
});
app.get('/battery.json', function(req, res){
  res.setHeader('Content-Type', 'application/json');
    res.send(JSON.stringify({ a: 1 }));
});

http.listen(3000, function(){
  console.log('En attente sur *:3000');
});

//process.stdin.setRawMode(true);
//process.stdin.resume();
<|endoftext|>


<commit_before>
$('#top').change(function(){update_words()})
$('#language').change(function(){update_words()})
$('#country').change(function(){update_words()})
$('#genre').change(function(){update_words()})
$('#start_year').change(function(){update_words()})
$('#end_year').change(function(){update_words()})

jQuery(document).ready(function(){
  jQuery(".chosen").chosen();
  update_words()

});

function update_words(){
  var _top = $('#top').val()
  var language = $('#language').val()
  var country = $('#country').val()
  var genre = $('#genre').val()
  var start_year = $('#start_year').val()
  var end_year = $('#end_year').val()

  url = 'http://localhost:5000/api/keywords?'

  if (_top.length>0){url = url + 'top=' + _top + '&'}
  if (language.length>0){url = url + 'language=' + language + '&'}
  if (country.length>0){url = url + 'country=' + country + '&'}
  if (genre.length>0){url = url + 'genre=' + genre + '&'}
  if (start_year.length>0){url = url + 'start_year=' + start_year + '&'}
  if (end_year.length>0){url = url + 'end_year=' + end_year + '&'}

  var words = $.get(url)
  words.done(function(data){
    $('#word_cloud').html('')
    $('#word_cloud').jQCloud(words.responseJSON, {
  width: 500,
  height: 350,
  classPattern: null,
  colors: ['#800026', '#bd0026', '#e31a1c', '#fc4e2a', '#fd8d3c', '#feb24c', '#fed976', '#ffeda0', '#ffffcc'],
  fontSize: {
    from: 0.1,
    to: 0.02
  }
});

  })
}

<commit_msg>removed localhost from url<commit_after>
$('#top').change(function(){update_words()})
$('#language').change(function(){update_words()})
$('#country').change(function(){update_words()})
$('#genre').change(function(){update_words()})
$('#start_year').change(function(){update_words()})
$('#end_year').change(function(){update_words()})

jQuery(document).ready(function(){
  jQuery(".chosen").chosen();
  update_words()

});

function update_words(){
  var _top = $('#top').val()
  var language = $('#language').val()
  var country = $('#country').val()
  var genre = $('#genre').val()
  var start_year = $('#start_year').val()
  var end_year = $('#end_year').val()

  url = '/api/keywords?'

  if (_top.length>0){url = url + 'top=' + _top + '&'}
  if (language.length>0){url = url + 'language=' + language + '&'}
  if (country.length>0){url = url + 'country=' + country + '&'}
  if (genre.length>0){url = url + 'genre=' + genre + '&'}
  if (start_year.length>0){url = url + 'start_year=' + start_year + '&'}
  if (end_year.length>0){url = url + 'end_year=' + end_year + '&'}

  var words = $.get(url)
  words.done(function(data){
    $('#word_cloud').html('')
    $('#word_cloud').jQCloud(words.responseJSON, {
  width: 500,
  height: 350,
  classPattern: null,
  colors: ['#800026', '#bd0026', '#e31a1c', '#fc4e2a', '#fd8d3c', '#feb24c', '#fed976', '#ffeda0', '#ffffcc'],
  fontSize: {
    from: 0.1,
    to: 0.02
  }
});

  })
}

<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict
 * @format
 */

'use strict';

const Systrace = require('../Performance/Systrace');

const infoLog = require('./infoLog');
const performanceNow: () => number =
  global.nativeQPLTimestamp ?? global.performance.now.bind(global.performance);

type Timespan = {
  startTime: number,
  endTime?: number,
  totalTime?: number,
};

// Extra values should be serializable primitives
type ExtraValue = number | string | boolean;

export interface IPerformanceLogger {
  addTimespan(key: string, startTime: number, endTime: number): void;
  startTimespan(key: string): void;
  stopTimespan(key: string, options?: {update?: boolean}): void;
  clear(): void;
  clearCompleted(): void;
  currentTimestamp(): number;
  getTimespans(): {[key: string]: Timespan, ...};
  hasTimespan(key: string): boolean;
  setExtra(key: string, value: ExtraValue): void;
  getExtras(): {[key: string]: ExtraValue, ...};
  removeExtra(key: string): ExtraValue | void;
  markPoint(key: string, timestamp?: number): void;
  getPoints(): {[key: string]: number, ...};
  logEverything(): void;
}

const _cookies: {[key: string]: number, ...} = {};

const PRINT_TO_CONSOLE: false = false; // Type as false to prevent accidentally committing `true`;

class PerformanceLogger implements IPerformanceLogger {
  _timespans: {[key: string]: Timespan} = {};
  _extras: {[key: string]: ExtraValue} = {};
  _points: {[key: string]: number} = {};

  addTimespan(key: string, startTime: number, endTime: number) {
    if (this._timespans[key]) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to add a timespan that already exists ',
          key,
        );
      }
      return;
    }

    this._timespans[key] = {
      startTime,
      endTime,
      totalTime: endTime - (startTime || 0),
    };
  }

  startTimespan(key: string) {
    if (this._timespans[key]) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to start a timespan that already exists ',
          key,
        );
      }
      return;
    }

    this._timespans[key] = {
      startTime: performanceNow(),
    };
    _cookies[key] = Systrace.beginAsyncEvent(key);
    if (PRINT_TO_CONSOLE) {
      infoLog('PerformanceLogger.js', 'start: ' + key);
    }
  }

  stopTimespan(key: string, options?: {update?: boolean}) {
    const timespan = this._timespans[key];
    if (!timespan || timespan.startTime == null) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to end a timespan that has not started ',
          key,
        );
      }
      return;
    }
    if (timespan.endTime != null && !options?.update) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to end a timespan that has already ended ',
          key,
        );
      }
      return;
    }

    timespan.endTime = performanceNow();
    timespan.totalTime = timespan.endTime - (timespan.startTime || 0);
    if (PRINT_TO_CONSOLE) {
      infoLog('PerformanceLogger.js', 'end: ' + key);
    }

    if (_cookies[key] != null) {
      Systrace.endAsyncEvent(key, _cookies[key]);
      delete _cookies[key];
    }
  }

  clear() {
    this._timespans = {};
    this._extras = {};
    this._points = {};
    if (PRINT_TO_CONSOLE) {
      infoLog('PerformanceLogger.js', 'clear');
    }
  }

  clearCompleted() {
    for (const key in this._timespans) {
      if (this._timespans[key].totalTime != null) {
        delete this._timespans[key];
      }
    }
    this._extras = {};
    this._points = {};
    if (PRINT_TO_CONSOLE) {
      infoLog('PerformanceLogger.js', 'clearCompleted');
    }
  }

  currentTimestamp() {
    return performanceNow();
  }

  getTimespans() {
    return this._timespans;
  }

  hasTimespan(key: string) {
    return !!this._timespans[key];
  }

  setExtra(key: string, value: ExtraValue) {
    if (this._extras.hasOwnProperty(key)) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to set an extra that already exists ',
          {key, currentValue: this._extras[key], attemptedValue: value},
        );
      }
      return;
    }
    this._extras[key] = value;
  }

  getExtras() {
    return this._extras;
  }

  removeExtra(key: string): ExtraValue | void {
    const value = this._extras[key];
    delete this._extras[key];
    return value;
  }

  markPoint(key: string, timestamp?: number) {
    if (this._points[key]) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to mark a point that has been already logged ',
          key,
        );
      }
      return;
    }
    this._points[key] = timestamp ?? performanceNow();
  }

  getPoints() {
    return this._points;
  }

  logEverything() {
    if (PRINT_TO_CONSOLE) {
      // log timespans
      for (const key in this._timespans) {
        if (this._timespans[key].totalTime != null) {
          infoLog(key + ': ' + this._timespans[key].totalTime + 'ms');
        }
      }

      // log extras
      infoLog(this._extras);

      // log points
      for (const key in this._points) {
        infoLog(key + ': ' + this._points[key] + 'ms');
      }
    }
  }
}

/**
 * This function creates performance loggers that can be used to collect and log
 * various performance data such as timespans, points and extras.
 * The loggers need to have minimal overhead since they're used in production.
 */
function createPerformanceLogger(): IPerformanceLogger {
  return new PerformanceLogger();
}

module.exports = createPerformanceLogger;
<commit_msg>Remove update option from stopTimestamp method in performance loggers<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict
 * @format
 */

'use strict';

const Systrace = require('../Performance/Systrace');

const infoLog = require('./infoLog');
const performanceNow: () => number =
  global.nativeQPLTimestamp ?? global.performance.now.bind(global.performance);

type Timespan = {
  startTime: number,
  endTime?: number,
  totalTime?: number,
};

// Extra values should be serializable primitives
type ExtraValue = number | string | boolean;

export interface IPerformanceLogger {
  addTimespan(key: string, startTime: number, endTime: number): void;
  startTimespan(key: string): void;
  stopTimespan(key: string): void;
  clear(): void;
  clearCompleted(): void;
  currentTimestamp(): number;
  getTimespans(): {[key: string]: Timespan, ...};
  hasTimespan(key: string): boolean;
  setExtra(key: string, value: ExtraValue): void;
  getExtras(): {[key: string]: ExtraValue, ...};
  removeExtra(key: string): ExtraValue | void;
  markPoint(key: string, timestamp?: number): void;
  getPoints(): {[key: string]: number, ...};
  logEverything(): void;
}

const _cookies: {[key: string]: number, ...} = {};

const PRINT_TO_CONSOLE: false = false; // Type as false to prevent accidentally committing `true`;

class PerformanceLogger implements IPerformanceLogger {
  _timespans: {[key: string]: Timespan} = {};
  _extras: {[key: string]: ExtraValue} = {};
  _points: {[key: string]: number} = {};

  addTimespan(key: string, startTime: number, endTime: number) {
    if (this._timespans[key]) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to add a timespan that already exists ',
          key,
        );
      }
      return;
    }

    this._timespans[key] = {
      startTime,
      endTime,
      totalTime: endTime - (startTime || 0),
    };
  }

  startTimespan(key: string) {
    if (this._timespans[key]) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to start a timespan that already exists ',
          key,
        );
      }
      return;
    }

    this._timespans[key] = {
      startTime: performanceNow(),
    };
    _cookies[key] = Systrace.beginAsyncEvent(key);
    if (PRINT_TO_CONSOLE) {
      infoLog('PerformanceLogger.js', 'start: ' + key);
    }
  }

  stopTimespan(key: string) {
    const timespan = this._timespans[key];
    if (!timespan || timespan.startTime == null) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to end a timespan that has not started ',
          key,
        );
      }
      return;
    }
    if (timespan.endTime != null) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to end a timespan that has already ended ',
          key,
        );
      }
      return;
    }

    timespan.endTime = performanceNow();
    timespan.totalTime = timespan.endTime - (timespan.startTime || 0);
    if (PRINT_TO_CONSOLE) {
      infoLog('PerformanceLogger.js', 'end: ' + key);
    }

    if (_cookies[key] != null) {
      Systrace.endAsyncEvent(key, _cookies[key]);
      delete _cookies[key];
    }
  }

  clear() {
    this._timespans = {};
    this._extras = {};
    this._points = {};
    if (PRINT_TO_CONSOLE) {
      infoLog('PerformanceLogger.js', 'clear');
    }
  }

  clearCompleted() {
    for (const key in this._timespans) {
      if (this._timespans[key].totalTime != null) {
        delete this._timespans[key];
      }
    }
    this._extras = {};
    this._points = {};
    if (PRINT_TO_CONSOLE) {
      infoLog('PerformanceLogger.js', 'clearCompleted');
    }
  }

  currentTimestamp() {
    return performanceNow();
  }

  getTimespans() {
    return this._timespans;
  }

  hasTimespan(key: string) {
    return !!this._timespans[key];
  }

  setExtra(key: string, value: ExtraValue) {
    if (this._extras.hasOwnProperty(key)) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to set an extra that already exists ',
          {key, currentValue: this._extras[key], attemptedValue: value},
        );
      }
      return;
    }
    this._extras[key] = value;
  }

  getExtras() {
    return this._extras;
  }

  removeExtra(key: string): ExtraValue | void {
    const value = this._extras[key];
    delete this._extras[key];
    return value;
  }

  markPoint(key: string, timestamp?: number) {
    if (this._points[key]) {
      if (PRINT_TO_CONSOLE && __DEV__) {
        infoLog(
          'PerformanceLogger: Attempting to mark a point that has been already logged ',
          key,
        );
      }
      return;
    }
    this._points[key] = timestamp ?? performanceNow();
  }

  getPoints() {
    return this._points;
  }

  logEverything() {
    if (PRINT_TO_CONSOLE) {
      // log timespans
      for (const key in this._timespans) {
        if (this._timespans[key].totalTime != null) {
          infoLog(key + ': ' + this._timespans[key].totalTime + 'ms');
        }
      }

      // log extras
      infoLog(this._extras);

      // log points
      for (const key in this._points) {
        infoLog(key + ': ' + this._points[key] + 'ms');
      }
    }
  }
}

/**
 * This function creates performance loggers that can be used to collect and log
 * various performance data such as timespans, points and extras.
 * The loggers need to have minimal overhead since they're used in production.
 */
function createPerformanceLogger(): IPerformanceLogger {
  return new PerformanceLogger();
}

module.exports = createPerformanceLogger;
<|endoftext|>


<commit_before>
/**;
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , redis = require("redis")
  , client = redis.createClient()
  , uuid = require('node-uuid');

/**
 * Add the FIFO functionality to Array class.
 **/
Array.prototype.store = function (info) {
  this.push(info);
}

Array.prototype.fetch = function() {
  if (this.length <= 0) { return ''; }  // nothing in array
  return this.shift();
}

Array.prototype.display = function() {
  return this.join('\n');
}

var app = module.exports = express.createServer();

function populate_redis() {
	var test_products = [
		{title:"Dvd player with surround sound system", category:"Players", price: 100},
		{title:"Full HD Bluray and DVD player", category:"Players", price:130},
		{title:"Media player with USB 2.0 input", category:"Players", price:70},

		{title:"Full HD Camera", category:"Cameras", price:200},
		{title:"Waterproof HD Camera", category:"Cameras", price:300},
		{title:"ShockProof and Waterproof HD Camera", category:"Cameras", price:400},
		{title:"Reflex Camera", category:"Cameras", price:500},

		{title:"DualCore Android Smartphon with 64Gb SD card", category:"Phones", price:200},
		{title:"Regular Movile Phone", category:"Phones", price:20},
		{title:"Satellite phone", category:"Cameras", price:500},

		{title:"64Gb SD Card", category:"Memory", price:35},
		{title:"32Gb SD Card", category:"Memory", price:27},
		{title:"16Gb SD Card", category:"Memory", price:5},

		{title:"Pink smartphone cover", category:"Covers", price:20},
		{title:"Black smartphone cover", category:"Covers", price:20},
		{title:"Kids smartphone cover", category:"Covers", price:30},

		{title:"55 Inches LED TV", category:"TVs", price:800},
		{title:"50 Inches LED TV", category:"TVs", price:700},
		{title:"42 Inches LED TV", category:"TVs", price:600},
		{title:"32 Inches LED TV", category:"TVs", price:400},

		{title:"TV Wall mount bracket 32-42 Inches", category:"Mounts", price:50},
		{title:"TV Wall mount bracket 50-55 Inches", category:"Mounts", price:80}
	];

	for(var i=0; i < test_products.length ;i++) {
		var product = test_products[i];
		product['id'] = i;
		var str = JSON.stringify(product);
		console.log("Inserting test product: [" + i  +"]:"+str);
		client.set(i, str);
		client.sadd("categories", product.category);
		client.sadd(product.category, product.id);
		client.sadd("products", product.id);
	}
}

populate_redis();

// Configuration

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

app.get('/product/:id/stats', function(req, resp) {
	var id = req.params.id;
	client.hgetall("prodcnt:"+id, function(err, res) {
		if(err!=null)
			resp.render('redis_error.jade', { title: "Error reading from redis:"+err});
		else {
			if(res!=null) {
				var title = "Stats for product:"+id;
				resp.render('stats.jade', {title: title, stats: res});
			} else {
				resp.render('not_found.jade', {title: "No stats available vor this product"});
			}
		}
	});
});

app.get('/product/:id', function(req, res) {
	var id= req.params.id;

    if(req.cookies.uid==null) {
        console.log("Unidentified User");
        var uid = uuid.v4();
        res.cookie("uid", uid,  { expires: new Date(Date.now() + 9000000000)});
    } else {
        var entry = JSON.stringify({user: req.cookies.uid, product: req.params.id, type: "PRODUCT"});
		client.lpush('navigation', entry);
    }

	client.get(id, function(err, reply) {
		if(err!=null) {
			res.render('redis_error.jade', {title: "Error reading from redis"+err});
			return ;
		}

		if(reply==null) {
			res.render('not_found.jade', {title: "Producto not found"});
			return ;
		}

		var product = JSON.parse(reply);
		res.render('product.jade', product);
	});

});

function get_all_data(fn) {
	var products = {};
    client.smembers('products', function(err, resp){
		var ids = resp;
		var readed = 0;
		for(var i = 0 ; i < ids.length ; i++) {
			client.get(ids[i], function(err, resp) {
				products[ids[readed]] = JSON.parse(resp);
				readed ++;
				if(readed == ids.length)
					fn(products);
			});
		}
    });
}

app.post('/news', function(req, res) {
	var body = "";
	console.log("NEWS!!");

	req.on('data', function (data) {
		body += data;
	});

	req.on('end', function () {
		console.log("NEWS!:"+ body);
		res.send("OK");
	});
});

app.get('/', function(req, res) {

	get_all_data(function(products){
		var data = {title: "Main page", products:products};
		console.log(JSON.stringify(data));
		res.render('index.jade', data);
	});
});

app.listen(3000, function(){
  console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
<commit_msg>Fixed typo<commit_after>
/**;
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , redis = require("redis")
  , client = redis.createClient()
  , uuid = require('node-uuid');

/**
 * Add the FIFO functionality to Array class.
 **/
Array.prototype.store = function (info) {
  this.push(info);
}

Array.prototype.fetch = function() {
  if (this.length <= 0) { return ''; }  // nothing in array
  return this.shift();
}

Array.prototype.display = function() {
  return this.join('\n');
}

var app = module.exports = express.createServer();

function populate_redis() {
	var test_products = [
		{title:"Dvd player with surround sound system", category:"Players", price: 100},
		{title:"Full HD Bluray and DVD player", category:"Players", price:130},
		{title:"Media player with USB 2.0 input", category:"Players", price:70},

		{title:"Full HD Camera", category:"Cameras", price:200},
		{title:"Waterproof HD Camera", category:"Cameras", price:300},
		{title:"ShockProof and Waterproof HD Camera", category:"Cameras", price:400},
		{title:"Reflex Camera", category:"Cameras", price:500},

		{title:"DualCore Android Smartphon with 64Gb SD card", category:"Phones", price:200},
		{title:"Regular Movile Phone", category:"Phones", price:20},
		{title:"Satellite phone", category:"Cameras", price:500},

		{title:"64Gb SD Card", category:"Memory", price:35},
		{title:"32Gb SD Card", category:"Memory", price:27},
		{title:"16Gb SD Card", category:"Memory", price:5},

		{title:"Pink smartphone cover", category:"Covers", price:20},
		{title:"Black smartphone cover", category:"Covers", price:20},
		{title:"Kids smartphone cover", category:"Covers", price:30},

		{title:"55 Inches LED TV", category:"TVs", price:800},
		{title:"50 Inches LED TV", category:"TVs", price:700},
		{title:"42 Inches LED TV", category:"TVs", price:600},
		{title:"32 Inches LED TV", category:"TVs", price:400},

		{title:"TV Wall mount bracket 32-42 Inches", category:"Mounts", price:50},
		{title:"TV Wall mount bracket 50-55 Inches", category:"Mounts", price:80}
	];

	for(var i=0; i < test_products.length ;i++) {
		var product = test_products[i];
		product['id'] = i;
		var str = JSON.stringify(product);
		console.log("Inserting test product: [" + i  +"]:"+str);
		client.set(i, str);
		client.sadd("categories", product.category);
		client.sadd(product.category, product.id);
		client.sadd("products", product.id);
	}
}

populate_redis();

// Configuration

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

app.get('/product/:id/stats', function(req, resp) {
	var id = req.params.id;
	client.hgetall("prodcnt:"+id, function(err, res) {
		if(err!=null)
			resp.render('redis_error.jade', { title: "Error reading from redis:"+err});
		else {
			if(res!=null) {
				var title = "Stats for product:"+id;
				resp.render('stats.jade', {title: title, stats: res});
			} else {
				resp.render('not_found.jade', {title: "No stats available vor this product"});
			}
		}
	});
});

app.get('/product/:id', function(req, res) {
	var id= req.params.id;

    if(req.cookies.uid==null) {
        console.log("Unidentified User");
        var uid = uuid.v4();
        res.cookie("uid", uid,  { expires: new Date(Date.now() + 9000000000)});
    } else {
        var entry = JSON.stringify({user: req.cookies.uid, product: req.params.id, type: "PRODUCT"});
		client.lpush('navigation', entry);
    }

	client.get(id, function(err, reply) {
		if(err!=null) {
			res.render('redis_error.jade', {title: "Error reading from redis"+err});
			return ;
		}

		if(reply==null) {
			res.render('not_found.jade', {title: "Product not found"});
			return ;
		}

		var product = JSON.parse(reply);
		res.render('product.jade', product);
	});

});

function get_all_data(fn) {
	var products = {};
    client.smembers('products', function(err, resp){
		var ids = resp;
		var readed = 0;
		for(var i = 0 ; i < ids.length ; i++) {
			client.get(ids[i], function(err, resp) {
				products[ids[readed]] = JSON.parse(resp);
				readed ++;
				if(readed == ids.length)
					fn(products);
			});
		}
    });
}

app.post('/news', function(req, res) {
	var body = "";
	console.log("NEWS!!");

	req.on('data', function (data) {
		body += data;
	});

	req.on('end', function () {
		console.log("NEWS!:"+ body);
		res.send("OK");
	});
});

app.get('/', function(req, res) {

	get_all_data(function(products){
		var data = {title: "Main page", products:products};
		console.log(JSON.stringify(data));
		res.render('index.jade', data);
	});
});

app.listen(3000, function(){
  console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
<|endoftext|>


<commit_before>define([
  'jquery',
  'Magento_Customer/js/customer-data',
  'mage/url',
  'mage/cookies',
  'domReady'
], function ($, customerData, url) {
  'use strict';

  return function(config, elem) {
    const button                 = elem,
      customer                   = customerData.get('customer'),
      wishlist                   = customerData.get('wishlist'),
      items                      = wishlist().items,
      productId                  = config.addToParams.data.product.toString(),
      buttonClass                = config.class,
      isEEVersion                = config.isEEVersion,
      loginUrl                   = url.build('customer/account'),
      pdpButtonClass             = 'product-view__button--wishlist',
      swatchContainerClass       = `.swatch-opt-${productId}`,
      swatchOptionContainerClass = '.swatch',
      qtyContainerClass          = `.qty-${productId}`,
      qtyInputClass              = '.quantity-update__input',
      groupedPDPTableClass       = '.product-view__grouped-table',
      multiwishlistButtonClass   = `.multiwishlist-btn-${productId}`;

    function addButtonClass() {
      if (isEEVersion) {
        const multiwishlistBtn = document.querySelector(multiwishlistButtonClass);

        multiwishlistBtn.classList.add(buttonClass);
      } else {
        button.classList.add(buttonClass);
      }
    }

    function moreWishlistButton() {
      // for PDP on OS - if is on product view,
      // add class to all add to wishlist buttons
      if (button.classList.contains(pdpButtonClass)) {
        const pdpButton = document.querySelector(`.${pdpButtonClass}`)

        pdpButton.classList.add(buttonClass);
      }
    }

    button.addEventListener('click', () => {
      const url = config.addToParams.action,
        formKey = $.mage.cookies.get('form_key'),
        wishlistId = config.addToParams.data.wishlist_id,
        swatchContainer = document.querySelector(swatchContainerClass),
        qtyContainer = document.querySelector(qtyContainerClass),
        bundlePDPTable = document.querySelector(groupedPDPTableClass),
        data = {
          action: 'add-to-wishlist',
          form_key: formKey,
          product: productId,
          uenc: config.addToParams.data.uenc
        };

      // for condfigurable products
      // add options if selected
      if (swatchContainer) {
        const swatchOptionContainerArray = swatchContainer.querySelectorAll(swatchOptionContainerClass);

        swatchOptionContainerArray.forEach(swatchOptionContainer => {
          if (swatchOptionContainer.hasAttribute('option-selected')) {
            const key = `super_attribute[${swatchOptionContainer.getAttribute('attribute-id')}]`,
              value = swatchOptionContainer.getAttribute('option-selected');

            data[key] = value;
          }
        });
      }

      // if it's product's PDP
      // add specified qty
      if (qtyContainer) {
        const quantityInput = qtyContainer.querySelector(qtyInputClass),
          value = quantityInput.value;

        data['qty'] = value;
      }

      // for grouped products
      // add qty of every product
      if (bundlePDPTable) {
        const quantityInputArray = bundlePDPTable.querySelectorAll('.input__field.qty');

        quantityInputArray.forEach(quantityInput => {
          const key = quantityInput.getAttribute('name'),
            value = quantityInput.value;

          data[key] = value;
        })
      }

      // if it's EE
      // add item to the specified list
      if (wishlistId) {
        data['wishlist_id'] = wishlistId;
      }

      $.post(url, data).done(function() {
        if (customer().firstname) {
          const addToMessage = $.cookieStorage.get('mage-messages');
          // add class to mark that product is added to wishlist
          if (addToMessage[0].type === 'success') {
            addButtonClass();
            moreWishlistButton();
            // delay is needed, because M2 reload customer data
            // and msg dissapear after a second
            setTimeout(function() {
              customerData.set('messages', {
                messages: addToMessage
              });
              // remove msg from cookie to not show after reload the page
              $.cookieStorage.set('mage-messages', '');
            }, 2000);
          }
        }
        else {
          window.location.href = loginUrl;
        }
      });
    });

    if (items) {
      items.forEach(item => {
        if (item.product_id === productId) {
          addButtonClass();
        }
      });
    }
  };
});
<commit_msg>#70731 add bundle & downloadable product options to wishlist<commit_after>define([
  'jquery',
  'Magento_Customer/js/customer-data',
  'mage/url',
  'mage/cookies',
  'domReady'
], function ($, customerData, url) {
  'use strict';

  return function(config, elem) {
    const button                 = elem,
      customer                   = customerData.get('customer'),
      wishlist                   = customerData.get('wishlist'),
      items                      = wishlist().items,
      productId                  = config.addToParams.data.product.toString(),
      buttonClass                = config.class,
      isEEVersion                = config.isEEVersion,
      loginUrl                   = url.build('customer/account'),
      pdpButtonClass             = 'product-view__button--wishlist',
      swatchContainerClass       = `.swatch-opt-${productId}`,
      swatchOptionContainerClass = '.swatch',
      qtyContainerClass          = `.qty-${productId}`,
      qtyInputClass              = '.quantity-update__input',
      groupedPDPTableClass       = '.product-view__grouped-table',
      bundleOptionClass          = '.bundle-option',
      bundleOptionQtyClass       = '.bundle-option__qty-input',
      downloadableContainerClass = '.product-options',
      multiwishlistButtonClass   = `.multiwishlist-btn-${productId}`;

    function addButtonClass() {
      if (isEEVersion) {
        const multiwishlistBtn = document.querySelector(multiwishlistButtonClass);

        multiwishlistBtn.classList.add(buttonClass);
      } else {
        button.classList.add(buttonClass);
      }
    }

    function moreWishlistButton() {
      // for PDP on OS - if is on product view,
      // add class to all add to wishlist buttons
      if (button.classList.contains(pdpButtonClass)) {
        const pdpButton = document.querySelector(`.${pdpButtonClass}`)

        pdpButton.classList.add(buttonClass);
      }
    }

    button.addEventListener('click', () => {
      const url = config.addToParams.action,
        formKey = $.mage.cookies.get('form_key'),
        wishlistId = config.addToParams.data.wishlist_id,
        swatchContainer = document.querySelector(swatchContainerClass),
        qtyContainer = document.querySelector(qtyContainerClass),
        bundlePDPTable = document.querySelector(groupedPDPTableClass),
        bundleOptionGroupArray = document.querySelectorAll(bundleOptionClass),
        downloadableContainer = document.querySelector(downloadableContainerClass),
        data = {
          action: 'add-to-wishlist',
          form_key: formKey,
          product: productId,
          uenc: config.addToParams.data.uenc
        };

      // for condfigurable products
      // add options if selected
      if (swatchContainer) {
        const swatchOptionContainerArray = swatchContainer.querySelectorAll(swatchOptionContainerClass);

        swatchOptionContainerArray.forEach(swatchOptionContainer => {
          if (swatchOptionContainer.hasAttribute('option-selected')) {
            const key = `super_attribute[${swatchOptionContainer.getAttribute('attribute-id')}]`,
              value = swatchOptionContainer.getAttribute('option-selected');

            data[key] = value;
          }
        });
      }

      // if it's product's PDP
      // add specified qty
      if (qtyContainer) {
        const quantityInput = qtyContainer.querySelector(qtyInputClass),
          value = quantityInput.value;

        data['qty'] = value;
      }

      // for grouped products
      // add qty of every product
      if (bundlePDPTable) {
        const quantityInputArray = bundlePDPTable.querySelectorAll('.input__field.qty');

        quantityInputArray.forEach(quantityInput => {
          const key = quantityInput.getAttribute('name'),
            value = quantityInput.value;

          data[key] = value;
        })
      }

      // for bundle product
      // add options and qty if selected
      if (bundleOptionGroupArray) {
        const bundleOptionQtyArray = document.querySelectorAll(bundleOptionQtyClass);

        bundleOptionQtyArray.forEach(bundleOptionQty => {
          const key = bundleOptionQty.getAttribute('name'),
            value = bundleOptionQty.value;

          data[key] = value;
        })

        bundleOptionGroupArray.forEach(budnleOptionGroup => {
          const budnleOptionArray = budnleOptionGroup.querySelectorAll('.option')
          budnleOptionArray.forEach(bundleOption => {
            const key = bundleOption.getAttribute('name');

            // for checkbox and radio
            if (bundleOption.checked) {
              const value = bundleOption.value;

              data[key] = value;
            }

            // for select and multiselect
            bundleOption.querySelectorAll('option').forEach(selectOption => {
              if(selectOption.selected) {
                const value = selectOption.value;

                if (key in data) {
                  data[key].push(value);
                } else {
                  data[key] = [value];
                }
              }
            })
          })
        })
      }

      // for downloadable product
      // add options if selected
      if (downloadableContainer){
        const checkboxArray = downloadableContainer.querySelectorAll('.checkbox__field');

        checkboxArray.forEach(checkbox => {
          if (checkbox.checked) {
            const key = checkbox.getAttribute('name'),
              value = checkbox.value;

            if (key in data) {
              data[key].push(value);
            } else {
              data[key] = [value];
            }
          }
        })
      }

      // if it's EE
      // add item to the specified list
      if (wishlistId) {
        data['wishlist_id'] = wishlistId;
      }

      $.post(url, data).done(function() {
        if (customer().firstname) {
          const addToMessage = $.cookieStorage.get('mage-messages');
          // add class to mark that product is added to wishlist
          if (addToMessage[0].type === 'success') {
            addButtonClass();
            moreWishlistButton();
            // delay is needed, because M2 reload customer data
            // and msg dissapear after a second
            setTimeout(function() {
              customerData.set('messages', {
                messages: addToMessage
              });
              // remove msg from cookie to not show after reload the page
              $.cookieStorage.set('mage-messages', '');
            }, 2000);
          }
        }
        else {
          window.location.href = loginUrl;
        }
      });
    });

    if (items) {
      items.forEach(item => {
        if (item.product_id === productId) {
          addButtonClass();
        }
      });
    }
  };
});
<|endoftext|>


<commit_before>/**
 * Cantina
 *
 * A framework for building interconnected applications and services.
 *
 * A cantina app/service is primarily a flatiron http application.  Cantina
 * extends flatiron to use amino as well as providing useful plugins and
 * code structuring conventions.
 */

var flatiron = require('flatiron'),
    amino = require('amino'),
    path = require('path'),
    util = require('util'),
    pkginfo = require('pkginfo').read(module.parent),
    app = flatiron.app;

var cantina = module.exports = {};

// Expose bundled plugins.
cantina.plugins = flatiron.common.requireDirLazy(path.join(__dirname, 'plugins'));

// Take options and return the app.
cantina.app = function(options) {
  options = options || {};

  // Setup the app info.
  app.info = pkginfo.package;
  if (options.name) app.info.name = options.name;
  if (options.version) app.info.version = options.version;

  // Set root directory.
  app.root = path.dirname(pkginfo.dir);
  if (options.root) {
    app.root = options.root;
  }

  // Use the http plugin.
  app.use(flatiron.plugins.http);

  // Start up the application wih amino.
  app._start = app.start;
  app.start = function() {
    // Create an amno service.
    var service = amino.createService(app.info.name + '@' + app.info.version);

    // Listen for spec and then startup the http server.
    service.on('spec', function(spec) {
      app._start(spec.port, spec.host, function(err) {
        if (err) throw err;
        app.log.info(util.format('Started %s@%s on http://%s:%s', app.info.name, app.info.version, spec.host, spec.port));
      });
    });
  };

  return app;
};
<commit_msg>Small code-style change.<commit_after>/**
 * Cantina
 *
 * A framework for building interconnected applications and services.
 *
 * A cantina app/service is primarily a flatiron http application.  Cantina
 * extends flatiron to use amino as well as providing useful plugins and
 * code structuring conventions.
 */

var flatiron = require('flatiron'),
    amino = require('amino'),
    path = require('path'),
    util = require('util'),
    pkginfo = require('pkginfo').read(module.parent),
    app = flatiron.app;

var cantina = module.exports = {};

// Expose bundled plugins.
cantina.plugins = flatiron.common.requireDirLazy(path.join(__dirname, 'plugins'));

// Take options and return the app.
cantina.app = function(options) {
  options = options || {};

  // Setup the app info.
  app.info = pkginfo.package;
  if (options.name) app.info.name = options.name;
  if (options.version) app.info.version = options.version;

  // Set root directory.
  app.root = path.dirname(pkginfo.dir);
  if (options.root) app.root = options.root;

  // Use the http plugin.
  app.use(flatiron.plugins.http);

  // Start up the application wih amino.
  app._start = app.start;
  app.start = function() {
    // Create an amno service.
    var service = amino.createService(app.info.name + '@' + app.info.version);

    // Listen for spec and then startup the http server.
    service.on('spec', function(spec) {
      app._start(spec.port, spec.host, function(err) {
        if (err) throw err;
        app.log.info(util.format('Started %s@%s on http://%s:%s', app.info.name, app.info.version, spec.host, spec.port));
      });
    });
  };

  return app;
};
<|endoftext|>