<commit_before>//http://www.clearlyinnovative.com/blog/post/1484840648/titanium-appcelerator-quickie-change-text-style-in-window-title
/*
 * The Window Class makes sure all windows look identical, have the same properties and functons.
 * It also checks if the device is running ios7 and will display windows differently.
 */
function windowClass(title) {
    var version = Ti.Platform.version;
    var device = Ti.Platform.name;
    // ios 7 windows withought bar image
if (version >= 7 && (device === 'iPhone OS' || device === 'iPad OS' || device === 'iPod Touch OS')){
        var self = Ti.UI.createWindow({
        backgroundColor:'#fff',
        title:title,
    });
    }
// ios 6 and lower
else{
    //Titanium.UI.iPhone.SystemButtonStyle = 'PLAIN';
    var self = Ti.UI.createWindow({
        title:title,
        //fullscreen : true,
        barColor: '#650000',//barColor:'#980012',
        backButtonTitle:'Back',
        backgroundColor:'#fff',
    });

    // create the label
var titleLabel = Titanium.UI.createLabel({
    color:'#fff',
    //backgroundColor:'#f6f5f1',
    height:42,
    width:'100%',
    text:title,
    textAlign:'center',
    font:{fontFamily:'Helvetica Neue',fontSize:16,fontWeight:'bold'},
    shadowColor:'#000',shadowOffset:{x:0,y:-1}
});
}
// landscape orientation will hide navBar and statusBar
function changeOrientation (e) {
    if(e.orientation == '3' || e.orientation == '4'){  //landscape
        //Titanium.UI.iPhone.hideStatusBar();
        self.hideNavBar();
    } else if (e.orientation == '1' || e.orientation == '2'){ //portrait
        //Titanium.UI.iPhone.showStatusBar();
        self.showNavBar();
    }

};
// execute 'changeOrientation' when window first opens and than on every orientation change
changeOrientation(Titanium.Gesture);
Titanium.Gesture.addEventListener('orientationchange', function(e) {
    changeOrientation(Titanium.Gesture);
});

// associate label to title
self.setTitleControl(titleLabel);

    return self;
};

module.exports = windowClass;<commit_msg>background texture disabled<commit_after>//http://www.clearlyinnovative.com/blog/post/1484840648/titanium-appcelerator-quickie-change-text-style-in-window-title
/*
 * The Window Class makes sure all windows look identical, have the same properties and functons.
 * It also checks if the device is running ios7 and will display windows differently.
 */
function windowClass(title) {
    var version = Ti.Platform.version;
    var device = Ti.Platform.name;
    // ios 7 windows withought bar image
if (version >= 7 && (device === 'iPhone OS' || device === 'iPad OS' || device === 'iPod Touch OS')){
        var self = Ti.UI.createWindow({
        backgroundColor:'#fff',
        title:title,
    });
    }
// ios 6 and lower
else{
    //Titanium.UI.iPhone.SystemButtonStyle = 'PLAIN';
    var self = Ti.UI.createWindow({
        title:title,
        //fullscreen : true,
        barColor: '#650000',//barColor:'#980012',
        backButtonTitle:'Back',
        backgroundColor:'#fff',
        //backgroundImage:'images/bg.png',
        //backgroundRepeat:true,
    });

    // create the label
var titleLabel = Titanium.UI.createLabel({
    color:'#fff',
    //backgroundColor:'#f6f5f1',
    height:42,
    width:'100%',
    text:title,
    textAlign:'center',
    font:{fontFamily:'Helvetica Neue',fontSize:16,fontWeight:'bold'},
    shadowColor:'#000',shadowOffset:{x:0,y:-1}
});
}
// landscape orientation will hide navBar and statusBar
function changeOrientation (e) {
    if(e.orientation == '3' || e.orientation == '4'){  //landscape
        //Titanium.UI.iPhone.hideStatusBar();
        self.hideNavBar();
    } else if (e.orientation == '1' || e.orientation == '2'){ //portrait
        //Titanium.UI.iPhone.showStatusBar();
        self.showNavBar();
    }

};
// execute 'changeOrientation' when window first opens and than on every orientation change
changeOrientation(Titanium.Gesture);
Titanium.Gesture.addEventListener('orientationchange', function(e) {
    changeOrientation(Titanium.Gesture);
});

// associate label to title
self.setTitleControl(titleLabel);

    return self;
};

module.exports = windowClass;<|endoftext|>


<commit_before>/* @flow */
import React, { PureComponent } from 'react';

import type { InputSelectionType } from '../types';
import getAutocompletedText from './getAutocompletedText';
import getAutocompleteFilter from './getAutocompleteFilter';
import EmojiAutocomplete from './EmojiAutocomplete';
import StreamAutocomplete from './StreamAutocomplete';
import PeopleAutocomplete from './PeopleAutocomplete';
import AnimatedScaleComponent from '../animation/AnimatedScaleComponent';

const prefixToComponent = {
  ':': EmojiAutocomplete,
  '#': StreamAutocomplete,
  '@': PeopleAutocomplete,
};

type Props = {
  text: string,
  selection: InputSelectionType,
  onAutocomplete: (input: string) => void,
};

export default class AutocompleteView extends PureComponent<Props> {
  props: Props;

  handleAutocomplete = (autocomplete: string) => {
    const { text, onAutocomplete, selection } = this.props;
    const newText = getAutocompletedText(text, autocomplete, selection);
    onAutocomplete(newText);
  };

  render() {
    const { text, selection } = this.props;
    const { lastWordPrefix, filter } = getAutocompleteFilter(text, selection);

    const AutocompleteComponent = prefixToComponent[lastWordPrefix];

    return (
      <AnimatedScaleComponent visible={filter.length > 0}>
        {AutocompleteComponent && (
          <AutocompleteComponent filter={filter} onAutocomplete={this.handleAutocomplete} />
        )}
      </AnimatedScaleComponent>
    );
  }
}
<commit_msg>autocomplete: Decide consistently whether to show popup (fix #2791).<commit_after>/* @flow */
import React, { PureComponent } from 'react';

import type { InputSelectionType } from '../types';
import getAutocompletedText from './getAutocompletedText';
import getAutocompleteFilter from './getAutocompleteFilter';
import EmojiAutocomplete from './EmojiAutocomplete';
import StreamAutocomplete from './StreamAutocomplete';
import PeopleAutocomplete from './PeopleAutocomplete';
import AnimatedScaleComponent from '../animation/AnimatedScaleComponent';

const prefixToComponent = {
  ':': EmojiAutocomplete,
  '#': StreamAutocomplete,
  '@': PeopleAutocomplete,
};

type Props = {
  text: string,
  selection: InputSelectionType,
  onAutocomplete: (input: string) => void,
};

export default class AutocompleteView extends PureComponent<Props> {
  props: Props;

  handleAutocomplete = (autocomplete: string) => {
    const { text, onAutocomplete, selection } = this.props;
    const newText = getAutocompletedText(text, autocomplete, selection);
    onAutocomplete(newText);
  };

  render() {
    const { text, selection } = this.props;
    const { lastWordPrefix, filter } = getAutocompleteFilter(text, selection);
    const AutocompleteComponent = prefixToComponent[lastWordPrefix];
    const shouldShow = !!AutocompleteComponent && filter.length > 0;

    return (
      <AnimatedScaleComponent visible={shouldShow}>
        {shouldShow && (
          <AutocompleteComponent filter={filter} onAutocomplete={this.handleAutocomplete} />
        )}
      </AnimatedScaleComponent>
    );
  }
}
<|endoftext|>


<commit_before>// JavaScript Document
//heifengshui 3.0版，整体采用JSON单体写法
//API功能一览表
/*
 getByClass : 获取含className的元素
 hasClass : 检测className
 addClass : 添加className
 removeClass : 删除className
 attr :  添加属性或者获取属性
 show : 显示元素
 hide : 隐藏元素
 removeAttr : 删除属性
 getChild : 标准获取子元素，建议用非标准children
 getStyle : 获取行间非行间的样式
 cssmove : 时间版运动框架，支持CSS3，采用的是矩形阵运动，无缓存，类似transition，
 movement : 时间版运动框架
 hfs_speed ： 速度版运动框架
 hfs_spring ： 弹性运动框架，三种运动框架相互关联，支持CSS3的运动,队列运动，支持延迟
 setcss3 ： 设置CSS3的样式
 toArray ： 类数组转换成数组
 randomsort ： 数组随机排序
 randomArray ：生成k以内的随机数数组，并且长度为g
 offsetXY ：获取到BODY体的距离,忽略了边框
 toType ： 判断类型
 targrt ：判断是否是冒泡过来的事件  第一个参数是事件源判断传参   第二个参数传this
 stopBubble ：阻止事件冒泡的通用函数 参数是事件源传进来的参数 ev
 on : 绑定事件，支持事件的命名空间
 off : 解绑事件，支持事件的命名空间
 bind : 简单绑定  不存储  不支持匿名事件的解绑
 unbind ：简单绑定的解绑，不能解绑匿名事件的绑定
 delegate : 事件委托。
 trigger : 事件的主动触发
 swipe : 滑屏事件  判断是向那个方向的滑屏
 fanhui : 返回顶部框架，传值返回到那个位置  默认为0
 myLiuLanQi ：判断浏览器
 browser ：判断是否为移动端，且移动端浏览器版本
 re : 常用正则
 datatype : 获取URL中传来的参数
 getURL : 返回URL相关信息，参数为数值1-7
 Queue : 队列，出队支持延迟出队和立即出队
 Data : 缓存
 extend : 对象浅拷贝
 siblings : 获取所有兄弟节点
 prev : 获取上一个兄弟节点
 next : 获取下一个兄弟节点
 first : 获取第一个子节点
 last : 获取最后一个子节点
 deppcopy : 对象深拷贝
 stringify ： JSON对象脱离原型链深拷贝
 css ： 设置对象的CSS样式，同步运动框架所需的参数
 ajax : 向服务器提交请求，并返回数据进行回调处理
 */
 var huofengshui = {
	//获取含有class的元素集合  参数一 父级元素，即要在那个元素下获取class元素集合，  参数二 元素集合的class名称，参数三，筛选某种标签
	getByClass : function(parent,className,node){
		node ? node : node="*";
		if(parent.getElementsByClassName && node == "*"){
			return parent.getElementsByClassName(className);
		}else{
			var tagName = parent.getElementsByTagName(node);
			var classArray = [];
			var reg = new RegExp('(^|\\s)'+className+'($|\\s)');
			for (var i = 0; i < tagName.length; i++) {
				if(reg.test(tagName[i].className)){
					classArray.push(tagName[i]);
				}
			};
			return classArray;
		}
	},
	//检测obj是否有className  参数一 对象 参数二 要检测的class
	hasClass : function(obj,className){
		return obj.className.match( new RegExp( "(^|\\s)" + className + "(\\s|$)" )) ? true : false;
	},
	//为obj添加className  参数一 对象  参数二 要添加的class
	addClass : function(obj,sclass){
		var reg = new RegExp('\\b' + sclass + '\\b');
		if(!reg.test(obj.className)){
			obj.className += " " + sclass;
		}
	},
	//删除class，参数一，对象  参数二要删除的class
	removeClass : function(obj,sclass){
		var ThisClassName = obj.className;
		var reg = new RegExp('(^|\\s)' + sclass + '($|\\s)',"g");
		if(reg.test(ThisClassName)){
			obj.className = ThisClassName.replace(reg,"");
		}
	},
//获取或设置DOM元素属性  参数一 DOM元素 参数二 属性值 或者要设置的属性JSON 参数三 要设置的属性值
	attr : function(obj,key,value){
		if(key && typeof key == "object"){
			for(var shu in key){
				obj.setAttribute(shu,key[shu]);
			};
			return this;
		};
		if(value){
			obj.setAttribute(key,value);
			return this;
		};
		return obj.getAttribute(key);
	},
	removeAttr : function(obj,attr){
		obj.removeAttribute(attr);
	},
	//设置DOM节点的CSS样式，参数一  DOM   参数二 要设置的样式,除了透明度及transform ,其他要写全，不可只写数值。transform的值要分开写，与运动框架一致
	css : function(obj,json){
		for(var attr in json){
			this.setmovecss(obj,attr,json[attr]);
		};
		return this;
	},
	//显示隐藏元素时，缓存元素display值
	showhide : function(elem,bool){
		if(!this.Data.get(elem,"olddisplay")){
			var dis = this.getStyle(elem,"display");
			if(dis == "none"){
				elem.style.display = "";
				dis = this.getStyle(elem,"display");
				if(dis == "none"){
					var oD = document.createElement(elem.nodeName);
					document.body.appendChild(oD);
					dis = this.getStyle(oD,"display");
					document.body.removeChild(oD);
				}
			};
			this.Data.set(elem,"olddisplay", dis);
		};
		if(bool){
			elem.style.display = this.Data.get(elem,"olddisplay");
		}else{
			elem.style.display = "none";
		}
	},
	//显示元素
show : function(elem){
		this.showhide(elem,true);
	},
	//隐藏元素
	hide : function(elem){
		this.showhide(elem,false);
	},
	each : function(arr,callback,arg){
		var _this = this;
		var i = 0;
		var length = arr.length;
		var value;
		var array = [];
		if(this.isArray(arr) || this.isArrayHTML(arr)){
			for(;i<length;i++){
				value = callback.call(arr[i],i,arr[i]);
				if ( value === false ) {
					break;
				}
			}
		}else{
			for(i in arr){
				value = callback.call(arr[i],i,arr[i] );
				if ( value === false ) {
					break;
				}
			}
		};
		return arr;
	},
	isArrayHTML : function(elems){
		return this.toType(elems==="HTML") && elems.length
	},
	isArray : Array.isArray || function(arr){
		return this.toType(arr) === "Array";
	},
	//标准获取子元素，建议用非标准children，参数为对象，children 在低版本IE下会算上注释节点，标准不会
	getChild : function(fu){
		var oFu = null;
		if(typeof(fu) != "string"){
			oFu = fu;
		}else{
			oFu = document.getElementById(fu);
		};
		var ozis = oFu.childNodes;
		var ozi = new Array();
		for(var i=0;i<ozis.length;i++){
			if(ozis[i].nodeType ==1){
				ozi.push(ozis[i]);
			}
		}
		return ozi;
	},
	//获取所有兄弟节点 参数一 DOM节点  参数二 如果传true 排除样式脚本等标签
	siblings : function(obj,b){
		var arr = [];
		//var childs = obj.parentNode.children;
		var childs = this.getChild(obj.parentNode);
		if(b === true){
			for(var i=0;i<childs.length;i++){
				if(obj !== childs[i] && childs[i].nodeName !== "SCRIPT" && childs[i].nodeName !== "STYLE" && childs[i].nodeName !== "LINK" && childs[i].nodeName !== "META"){
					arr.push(childs[i]);
				}
			};
		}else{
			for(var i=0;i<childs.length;i++){
				if(obj !== childs[i]){
					arr.push(childs[i]);
				}
			};
		};
		return arr;
	},
	//获取上个兄弟节点
<commit_msg>Update huofengshui3.0.js<commit_after>// JavaScript Document
//heifengshui 3.0版，整体采用JSON单体写法
//API功能一览表
/*
 getByClass : 获取含className的元素
 hasClass : 检测className
 addClass : 添加className
 removeClass : 删除className
 attr :  添加属性或者获取属性
 show : 显示元素
 hide : 隐藏元素
 removeAttr : 删除属性
 getChild : 标准获取子元素，建议用非标准children
 getStyle : 获取行间非行间的样式
 cssmove : 时间版运动框架，支持CSS3，采用的是矩形阵运动，无缓存，类似transition，
 movement : 时间版运动框架
 hfs_speed ： 速度版运动框架
 hfs_spring ： 弹性运动框架，三种运动框架相互关联，支持CSS3的运动,队列运动，支持延迟
 setcss3 ： 设置CSS3的样式
 toArray ： 类数组转换成数组
 randomsort ： 数组随机排序
 randomArray ：生成k以内的随机数数组，并且长度为g
 offsetXY ：获取到BODY体的距离,忽略了边框
 toType ： 判断类型
 targrt ：判断是否是冒泡过来的事件  第一个参数是事件源判断传参   第二个参数传this
 stopBubble ：阻止事件冒泡的通用函数 参数是事件源传进来的参数 ev
 on : 绑定事件，支持事件的命名空间
 off : 解绑事件，支持事件的命名空间
 bind : 简单绑定  不存储  不支持匿名事件的解绑
 unbind ：简单绑定的解绑，不能解绑匿名事件的绑定
 delegate : 事件委托。
 trigger : 事件的主动触发
 swipe : 滑屏事件  判断是向那个方向的滑屏
 fanhui : 返回顶部框架，传值返回到那个位置  默认为0
 myLiuLanQi ：判断浏览器
 browser ：判断是否为移动端，且移动端浏览器版本
 re : 常用正则
 datatype : 获取URL中传来的参数
 getURL : 返回URL相关信息，参数为数值1-7
 Queue : 队列，出队支持延迟出队和立即出队
 Data : 缓存
 extend : 对象浅拷贝
 siblings : 获取所有兄弟节点
 prev : 获取上一个兄弟节点
 next : 获取下一个兄弟节点
 first : 获取第一个子节点
 last : 获取最后一个子节点
 deppcopy : 对象深拷贝
 stringify ： JSON对象脱离原型链深拷贝
 css ： 设置对象的CSS样式，同步运动框架所需的参数
 ajax : 向服务器提交请求，并返回数据进行回调处理
 */
 var huofengshui = {
	//获取含有class的元素集合  参数一 父级元素，即要在那个元素下获取class元素集合，  参数二 元素集合的class名称，参数三，筛选某种标签
	getByClass : function(parent,className,node){
		node ? node : node="*";
		if(parent.getElementsByClassName && node == "*"){
			return parent.getElementsByClassName(className);
		}else{
			var tagName = parent.getElementsByTagName(node);
			var classArray = [];
			var reg = new RegExp('(^|\\s)'+className+'($|\\s)');
			for (var i = 0; i < tagName.length; i++) {
				if(reg.test(tagName[i].className)){
					classArray.push(tagName[i]);
				}
			};
			return classArray;
		}
	},
	//检测obj是否有className  参数一 对象 参数二 要检测的class
	hasClass : function(obj,className){
		return obj.className.match( new RegExp( "(^|\\s)" + className + "(\\s|$)" )) ? true : false;
	},
	//为obj添加className  参数一 对象  参数二 要添加的class
	addClass : function(obj,sclass){
		var reg = new RegExp('\\b' + sclass + '\\b');
		if(!reg.test(obj.className)){
			obj.className += " " + sclass;
		}
	},
	//删除class，参数一，对象  参数二要删除的class
	removeClass : function(obj,sclass){
		var ThisClassName = obj.className;
		var reg = new RegExp('(^|\\s)' + sclass + '($|\\s)',"g");
		if(reg.test(ThisClassName)){
			obj.className = ThisClassName.replace(reg,"");
		}
	},
//获取或设置DOM元素属性  参数一 DOM元素 参数二 属性值 或者要设置的属性JSON 参数三 要设置的属性值
	attr : function(obj,key,value){
		if(key && typeof key == "object"){
			for(var shu in key){
				obj.setAttribute(shu,key[shu]);
			};
			return this;
		};
		if(value){
			obj.setAttribute(key,value);
			return this;
		};
		return obj.getAttribute(key);
	},
	removeAttr : function(obj,attr){
		obj.removeAttribute(attr);
	},
	//设置DOM节点的CSS样式，参数一  DOM   参数二 要设置的样式,除了透明度及transform ,其他要写全，不可只写数值。transform的值要分开写，与运动框架一致
	css : function(obj,json){
		for(var attr in json){
			this.setmovecss(obj,attr,json[attr]);
		};
		return this;
	},
	//显示隐藏元素时，缓存元素display值
	showhide : function(elem,bool){
		if(!this.Data.get(elem,"olddisplay")){
			var dis = this.getStyle(elem,"display");
			if(dis == "none"){
				elem.style.display = "";
				dis = this.getStyle(elem,"display");
				if(dis == "none"){
					var oD = document.createElement(elem.nodeName);
					document.body.appendChild(oD);
					dis = this.getStyle(oD,"display");
					document.body.removeChild(oD);
				}
			};
			this.Data.set(elem,"olddisplay", dis);
		};
		if(bool){
			elem.style.display = this.Data.get(elem,"olddisplay");
		}else{
			elem.style.display = "none";
		}
	},
	//显示元素
show : function(elem){
		this.showhide(elem,true);
	},
	//隐藏元素
	hide : function(elem){
		this.showhide(elem,false);
	},
	each : function(arr,callback,arg){
		var _this = this;
		var i = 0;
		var length = arr.length;
		var value;
		var array = [];
		if(this.isArray(arr) || this.isArrayHTML(arr)){
			for(;i<length;i++){
				value = callback.call(arr[i],i,arr[i]);
				if ( value === false ) {
					break;
				}
			}
		}else{
			for(i in arr){
				value = callback.call(arr[i],i,arr[i] );
				if ( value === false ) {
					break;
				}
			}
		};
		return arr;
	},
	isArrayHTML : function(elems){
		return this.toType(elems==="HTML") && elems.length
	},
	isArray : Array.isArray || function(arr){
		return this.toType(arr) === "Array";
	},
	//标准获取子元素，建议用非标准children，参数为对象，children 在低版本IE下会算上注释节点，标准不会
	getChild : function(fu){
		var oFu = null;
		if(typeof(fu) != "string"){
			oFu = fu;
		}else{
			oFu = document.getElementById(fu);
		};
		var ozis = oFu.childNodes;
		var ozi = new Array();
		for(var i=0;i<ozis.length;i++){
			if(ozis[i].nodeType ==1){
				ozi.push(ozis[i]);
			}
		}
		return ozi;
	},
	//获取所有兄弟节点 参数一 DOM节点  参数二 如果传true 排除样式脚本等标签
	siblings : function(obj,b){
		var arr = [];
		//var childs = obj.parentNode.children;
		var childs = this.getChild(obj.parentNode);
		if(b === true){
			for(var i=0;i<childs.length;i++){
				if(obj !== childs[i] && childs[i].nodeName !== "SCRIPT" && childs[i].nodeName !== "STYLE" && childs[i].nodeName !== "LINK" && childs[i].nodeName !== "META"){
					arr.push(childs[i]);
				}
			};
		}else{
			for(var i=0;i<childs.length;i++){
				if(obj !== childs[i]){
					arr.push(childs[i]);
				}
			};
		};
		return arr;
	},
	//获取上个兄弟节点
prev : function(obj){
		if( !obj || !obj.previousSibling ){
			return null;
		};
		if( obj.previousElementSibling ){
			return obj.previousElementSibling;
		};
		if( obj.previousSibling.nodeType == 1 ){
			return obj.previousSibling;
		};
		return null;
	},
	//获取下个兄弟节点
	next : function(obj){
		if( !obj || !obj.nextSibling ){
			return null;
		};
		if( obj.nextElementSibling ){
			return obj.nextElementSibling;
		};
		if( obj.nextSibling.nodeType == 1 ){
			return obj.nextSibling;
		};
		return null;
	},
	//获取第一个子节点
	first : function(obj){
		if( !obj || !obj.firstChild ){
			return null;
		}
		return obj.firstChild.nodeType == 1 ? obj.firstChild : this.next( obj.firstChild );
	},
	//获取最后一个子节点
	last : function(obj){
		if( !obj || !obj.lastChild ){
			return null;
		}
		return obj.lastChild.nodeType == 1 ? obj.lastChild : this.prev( obj.lastChild );
	},
	//获取样式值，参数一 对象，参数二要获取的样式属性
	getStyle : function(obj,attr){
		if(obj.currentStyle){
			return obj.currentStyle[attr];
		}else{
			return getComputedStyle(obj,false)[attr];
		}
	},

	//时间版运动框架  css运动框架参数检测
	detection : function(times,fx,fn,delay){
		if( typeof times == 'undefined' ){
			times = 400;
			fx = 'linear';
			delay = 0;
		};
		if( typeof times == 'string' ){
			if(typeof fx == 'function'){
				if(typeof fn == 'number'){
					delay = fn;
				}else{
					delay = 0;
				}
				fn = fx;
			}else if(typeof fx == 'number'){
				delay = fx;
				fn = null;
			}else{
				delay = 0;
			}
			fx = times;
			times = 400;
		}else if(typeof times == 'function'){
			if(typeof fx == 'number'){
				delay = fx;
			}else{
				delay = 0;
			}
			fn = times;
			times = 400;
			fx = 'linear';
		}else if(typeof times == 'number'){
			if(typeof fx == 'function'){
				if(typeof fn == 'number'){
					delay = fn;
				}else{
					delay = 0;
				}
				fn = fx;
				fx = 'linear';
			}else if(typeof fx == 'undefined'){
				fx = 'linear';
				delay = 0;
			}else if(typeof fx == 'string'){
				if(typeof fn == 'number'){
					delay = fn;
					fn = null;
				}else if(typeof fn == 'function' && !delay){
					delay = 0;
				}
			}else if(typeof fx == 'number'){
				delay = fx;
				fx = 'linear';
				fn = null;
			};
		};
		return [times,fx,fn,delay];
	},
	mousewheel : function(elem,json){
		elem.onmousewheel = mouseScroll;
		if(elem.addEventListener){
			elem.addEventListener('DOMMouseScroll',mouseScroll,false);
		};
		var fnup = json.up || function(){};
		var fndown = json.down || function(){};
		function mouseScroll(e){
			var ev = e || window.event;
			var fx = ev.wheelDelta || ev.detail;
			var bDown = true;
			if( ev.detail ){
				bDown = fx > 0 ? true : false;
			}else{
				bDown = fx > 0 ? false : true;
			};
			if( bDown ){
				fndown.call(elem);
			}else{
				fnup.call(elem);
			}
			if( ev.preventDefault ){
				ev.preventDefault();
			}
			return false;
		}
	},
	//时间版运动框架，扩展了CSS3的运动，参数一对象，参数二json形式的运动属性，参数三运动持续时间，参数四运动形式，参数五，运动结束后的回调
	movement : function(obj,json,times,fx,fn,delay){
		var arr = this.detection(times,fx,fn,delay);
		this.movement_init(obj,json,arr[0],arr[1],arr[2],arr[3],false);
		return this;
	},
	//时间版运动初始化
	movement_init : function(obj,json,times,fx,fn,delay,css){
		var _this = this;
		_this.Queue.queue(obj,"fx",function(){
			if(delay > 0 && typeof delay == "number"){
				setTimeout(function(){
					_this.movement_delay(obj,json,times,fx,fn,delay,css);
				},delay);
			}else{
				_this.movement_delay(obj,json,times,fx,fn,delay,css);
			}
		});
	},
	movement_delay : function(obj,json,times,fx,fn,delay,css){
		obj.iCur = {};
		if(css){
			this.getMoveCss(obj,obj.iCur,json);
		}else{
			if(!obj.transform){
				obj.transform = {};
			};
			this.getmovecss(obj,json,obj.iCur,false);
		}
		this.movement_move(obj,json,times,fx,fn,delay);
	},
	//时间版运动开始
	movement_move : function(obj,json,times,fx,fn,delay){
		var _this = this;
		var startTime = this.movement_now();
		clearInterval(obj.timer);
		obj.timer = setInterval(function(){
			var changeTime = _this.movement_now();
			var t = times - Math.max(0,startTime - changeTime + times);  //0到2000
			for(var attr in json){
				if(attr == 'transform'){
					var value = [];
					for(var i=0;i<obj.css_json[attr].length;i++){
						value[i] = Tween[fx](t,obj.iCur[attr][i],obj.css_json[attr][i]-obj.iCur[attr][i],times);
					}
				}else{
					var value = Tween[fx](t,obj.iCur[attr],json[attr]-obj.iCur[attr],times);
				}
				_this.setmovecss(obj,attr,value);
			}
			if(t == times){
				clearInterval(obj.timer);
				_this.Queue.dequeue(obj,"fx");
				if(fn){
					fn.call(obj);
				}
			}
		},13);
	},
	//返回当前时间 时间版运动用
	movement_now : function(){
		return (new Date()).getTime();
	},
	//css运动框架
	cssmove : function(obj,json,times,fx,fn,delay){
		var arr = this.detection(times,fx,fn,delay);
		this.movement_init(obj,json,arr[0],arr[1],arr[2],arr[3],true);
		return this;
	},
	//速度版运动框架，参数一为对象，参数二为运动参数，格式为json，参数三为运动结束后的回调，参数四为匀速运动时的速度，值必须是数值型，否则按缓冲运动
	hfs_speed : function(obj, json, fnEnd, delay, su){
		var _this = this;
		_this.Queue.queue(obj,"fx",function(){
			if(delay > 0 && typeof delay == "number"){
				setTimeout(function(){
					_this.speed_delay(obj, json, fnEnd,su);
				},delay);
			}else{
				_this.speed_delay(obj, json, fnEnd,su);
			};
		});
		return this;
	},
	speed_delay : function(obj, json, fnEnd,su){
		var _this = this;
		clearInterval(obj.timer);  //确保只有一个定时器
		obj.timer=setInterval(function(){
			var bStop=true;		//假设：所有值都已经到了
			for(var attr in json){   //遍历json
				obj.cur=0;        //声明变量，存储获取的属性值
				_this.speed_getcss(obj,attr);

				if(su && typeof su == "number"){ //如果传了速度值，做匀速运动
					var speed = 0;
					if(obj.cur < json[attr]){
						speed = su;
						if(obj.cur >= json[attr] || (json[attr]-obj.cur)<su){
							obj.cur = json[attr];
							speed = 0;
						}
					}
					if(obj.cur > json[attr]){
						speed= -su;
						if(obj.cur <= json[attr] || (obj.cur-json[attr])<su){
							obj.cur = json[attr];
							speed = 0;
						}
					}
				}else{
					var speed=(json[attr]-obj.cur)/6;
					speed=speed>0?Math.ceil(speed):Math.floor(speed);
				}
				if(obj.cur!=json[attr]){
					bStop=false;
				}
				if(Math.abs(json[attr]-obj.cur)<1){
					obj.cur = json[attr];
				}
				_this.setmovecss(obj,attr,(obj.cur+speed));
			}
			if(bStop){
				clearInterval(obj.timer);
				_this.Queue.dequeue(obj,"fx");
				if(fnEnd){
					fnEnd.call(obj);
				}
			}
		},30);
	},
	//速度版运动的获取样式
	speed_getcss : function(obj,attr){
		var _this = this;
		this.get_css(obj,attr)
	},
	//根据后盾网提供的公式做的弹性摩擦运动框架，解决了高度在低版本IE下报错的问题
	/*
	 *vx += (targetX - spriteX) * spring;
	 *spriteX += (vx *= friction);
	 *这个是公式 targetX为目标点 spriteX为初始值，会在框架运动中变化  直到跟目标点相同
	 */
	//弹性运动框架，第一个参数传对象，参数二为弹动系数JSON值，参数三为运动的json形式参数，参数四运动结束后的回调函数 参数五为延迟时间
	hfs_spring : function(obj,tx,json,fnEnd,delay){
		var _this = this;
		_this.Queue.queue(obj,"fx",function(){
			if(delay > 0 && typeof delay == "number"){
				setTimeout(function(){
					_this.spring_delay(obj,tx, json, fnEnd);
				},delay);
			}else{
				_this.spring_delay(obj,tx, json, fnEnd);
			};
		});
		return this;
	},
	//弹性运动初始化
	spring_init : function(obj,json){
		var _this = this;
		if(!obj.transform){
			obj.transform = {};
		};
		_this.getmovecss(obj,json,obj.spring_startJson,true);
	},
	spring_delay : function(obj,tx,json,fnEnd){
		var _this = this;
		obj.spring_startJson = {}; //存储初始值，运动中会变化，直到跟目标值相等
		obj.spring_vxJson = {};
		obj.spring_targetJson = {};
		if(tx && typeof tx =="object"){
			_this.spring = tx.x;
			_this.friction = tx.y;
		}else{
			_this.spring = 0.8;
			_this.friction = 0.6;
		}
		_this.spring_init(obj,json);
		clearInterval(obj.dt);
		obj.dt = setInterval(function(){
			obj.spring_bStop = true;
			_this.spring_move(obj,json);
			if(obj.spring_bStop){
				clearInterval(obj.dt);
				_this.Queue.dequeue(obj,"fx");
				if(fnEnd){
					fnEnd.call(obj);
				}
			}
		},60);
	},
	//弹性运动开始运动
<|endoftext|>


<commit_before>
$(document).ready(function () {

    var isResult = (getURLParameter("EstimateResult") != "null");

    //Load the Pricing Type drop down
    $('#pricingtype').addOption(0, "Loading....").attr('disabled', true);
    $.getJSON('ListPricingTypes', function (data) {
        var estimatetypes = data;
        $.each(estimatetypes, function (index, estimatetype) {
            var val = estimatetype.PricingTypeID;
            var text = estimatetype.Description;
            $('#pricingtype').addOption(val, text, false);
        });

        $('#pricingtype').addOption(0, "Select type").attr('disabled', false);

        var firstselected = true;
        $('#pricingtype').change(function () {
            if (firstselected) {
                firstselected = false;
                $('#pricingtype').removeOption(0);
            };
        });

    });

    //Paint and load Estimate Var List

    //aux function to get data from the url string
    function getURLParameter(name) {
        return decodeURI(
               (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]);
    }

    //Get the position ID
    var positionID = getURLParameter("PositionID");
    $("#result").hide();
    //Check pricing type changes
    $('#pricingtype').change(
            function () {
                var pricingTypeID = $('#pricingtype').val();

                //Reset the form
                $(".row").remove();
                //Get estimation variables for the Position and pricing type.
                $.getJSON('GetUserPricingVars', { PositionID: positionID, PricingTypeID: pricingTypeID },
                     function (data) {
                         var estimatevars = data;

                         //paint var tags(input/select)
                         $.each(estimatevars, function (index3, estimatevar) {
                             var varID = estimatevar.EstimateVarID; //indentifies a variable value
                             var groupID = estimatevar.GroupID; //identifies a variable group for radio lists and dropdowns
                             var name = estimatevar.UserDescription; //description showed to the user
                             var tag = estimatevar.UserTag; //Tells wich Html representation should be painted(simple input, radio list, dropdown)
                             var value = estimatevar.Value; //Default value for the variable.
                             //Paint simple input
                             if (tag == "input") {
                                 if (!$('.label' + groupID).length) {
                                     $('.inputfields').after('
' + name + '
');
                                 };
                                 $('.label' + groupID).after('<input type="hidden" id="varID" name="varID" value=' + varID + '>');
                                 $('.label' + groupID).after('
<input class="inputValue" id="varValue" name="varValue" type="text">
');
                             };
                             //Paint radio list input
                             if (tag == "radiolist") {
                                 if (!$('.label' + groupID).length) {
                                     $('.inputfields').after('
' + name + '
');
                                     $('.label' + groupID).after('<input type="hidden" id="groupID" name="groupID" value=' + groupID + '>');
                                 };
                                 $('.label' + groupID).after('
' + value + '<input type="radio" id="listValue" name="listValue" value=' + varID + '>
');
                             };
                             //Paint dropdown input
                             if (tag == "dropdown") {
                                 if (!$('.label' + groupID).length) {
                                     $('.inputfields').after('
' + name + '
');
                                     $('.label' + groupID).after('<input type="hidden" id="groupID" name="groupID" value=' + groupID + '>');
                                     $('.label' + groupID).after('
<select class=select' + groupID + ' name="listValue" id="listValue"/>
');
                                 };
                                 $('.select' + groupID).addOption(varID, value, false);
                             };
                         });
                     }
                );
            }
        );
    //Paint the result retrived by the server
    if (isResult) {
        $("#result").append(getURLParameter("EstimateResult") + ' $ (USD)');
        $("#result").show();
        update = false;
    }

});<commit_msg>comments added for Pricing Wizard script<commit_after>
$(document).ready(function () {

    var isResult = (getURLParameter("EstimateResult") != "null");

    //Load the Pricing Type drop down
    $('#pricingtype').addOption(0, "Loading....").attr('disabled', true);
    $.getJSON('ListPricingTypes', function (data) {
        var estimatetypes = data;
        $.each(estimatetypes, function (index, estimatetype) {
            var val = estimatetype.PricingTypeID;
            var text = estimatetype.Description;
            $('#pricingtype').addOption(val, text, false);
        });

        $('#pricingtype').addOption(0, "Select type").attr('disabled', false);

        var firstselected = true;
        $('#pricingtype').change(function () {
            if (firstselected) {
                firstselected = false;
                $('#pricingtype').removeOption(0);
            };
        });

    });

    //Paint and load Estimate Var List

    //aux function to get data from the url string
    function getURLParameter(name) {
        return decodeURI(
               (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]);
    }

    //Get the position ID
    var positionID = getURLParameter("PositionID");
    $("#result").hide();
    //Check pricing type changes
    $('#pricingtype').change(
            function () {
                var pricingTypeID = $('#pricingtype').val();

                //Reset the form
                $(".row").remove();
                //Get estimation variables for the Position and pricing type.
                $.getJSON('GetUserPricingVars', { PositionID: positionID, PricingTypeID: pricingTypeID },
                     function (data) {
                         var estimatevars = data;

                         //paint var tags(input/select)
                         $.each(estimatevars, function (index3, estimatevar) {
                             var varID = estimatevar.EstimateVarID; //indentifies a variable value
                             var groupID = estimatevar.GroupID; //identifies a variable group for radio lists and dropdowns
                             var name = estimatevar.UserDescription; //description showed to the user
                             var tag = estimatevar.UserTag; //Tells wich Html representation should be painted(simple input, radio list, dropdown)
                             var value = estimatevar.Value; //Default value for the variable.
                             //Paint simple input
                             if (tag == "input") {
                                 if (!$('.label' + groupID).length) {
                                     $('.inputfields').after('
' + name + '
');
                                 };
                                 $('.label' + groupID).after('<input type="hidden" id="varID" name="varID" value=' + varID + '>');
                                 $('.label' + groupID).after('
<input class="inputValue" id="varValue" name="varValue" type="text">
');
                             };
                             //Paint radio list input
                             if (tag == "radiolist") {
                                 //If is the first element of the radio list add the label for the group
                                 if (!$('.label' + groupID).length) {
                                     $('.inputfields').after('
' + name + '
');
                                     $('.label' + groupID).after('<input type="hidden" id="groupID" name="groupID" value=' + groupID + '>');
                                 };
                                 $('.label' + groupID).after('
' + value + '<input type="radio" id="listValue" name="listValue" value=' + varID + '>
');
                             };
                             //Paint dropdown input
                             if (tag == "dropdown") {
                                 //If is the first element of the dropdown add the label and the select tag for the group
                                 if (!$('.label' + groupID).length) {
                                     $('.inputfields').after('
' + name + '
');
                                     $('.label' + groupID).after('<input type="hidden" id="groupID" name="groupID" value=' + groupID + '>');
                                     $('.label' + groupID).after('
<select class=select' + groupID + ' name="listValue" id="listValue"/>
');
                                 };
                                 $('.select' + groupID).addOption(varID, value, false);
                             };
                         });
                     }
                );
            }
        );
    //Paint the result retrived by the server
    if (isResult) {
        $("#result").append(getURLParameter("EstimateResult") + ' $ (USD)');
        $("#result").show();
        update = false;
    }

});<|endoftext|>


<commit_before>(function(window, document){

var chart;
var lasttime;

function drawCurrent(data)
{
    if (data.count > 0)
    {
       lasttime = data.humidity[data.count-1][0];
       document.querySelector("span#temperature").innerHTML = data.temperature[0][1];
       document.querySelector("span#humidity").innerHTML = data.humidity[0][1];
       var date = new Date(lasttime);
       document.querySelector("span#time").innerHTML = date.toTimeString();
    }
    document.querySelector("span#lastupdate").innerHTML = new Date().toTimeString();
}

function requestDelta()
{
    $.ajax({
    url: 'weather.php?mode=delta&delta='+lasttime,
    datatype: "json",
    success: function(data)
    {
	   var i;
           if (data.count > 0) {
	   for(i=0; i<data.count;i++)
	      chart.series[0].addPoint(data.temperature[i], false, true);
           for(i=0; i<data.count;i++)
              chart.series[1].addPoint(data.humidity[i], false, true);
           chart.redraw();
	  }
	  drawCurrent(data);

    }
    });

}

function requestData()
{
    var daterange = document.querySelector("select#daterange").value;
    if (!daterange)
	daterange = "today";
    $.ajax({
    url: 'weather.php?mode='+daterange,
    datatype: "json",
    success: function(data)
    {
           chart.series[0].setData(data.temperature);
           chart.series[1].setData(data.humidity);
           drawCurrent(data);
	   setInterval(requestDelta, 5 * 60 *  1000);
    }
    });
}
$(document).ready(function() {

    Highcharts.setOptions({
        global: {
            useUTC: false
        }
    });
chart = new Highcharts.Chart({
     chart: {
        renderTo: 'graph',
        type: 'spline',
        events: {
            load: requestData
        }
     },
     title: {
        text: 'Monitoring'
     },
    tooltip: {
      shared: true
    },
     xAxis: {
        type: 'datetime',
            maxZoom: 20 * 1000
     },
     yAxis: {
	min: 10,
        minPadding: 0.2,
            maxPadding: 0.2,
            title: {
                text: 'Temperature/Humidity',
                margin: 80
            }
     },
     series: [{
        name: 'Temperature',
        data: []
     },
     {
        name: 'Humidity',
        data: []
     }]
  });
   $('select#daterange').change(function() {requestData();});
  });
})(window, document)
<commit_msg>Fixed last data<commit_after>(function(window, document){

var chart;
var lasttime;

function drawCurrent(data)
{
    if (data.count > 0)
    {
       lasttime = data.humidity[data.count-1][0];
       document.querySelector("span#temperature").innerHTML = data.temperature[data.count-1][1];
       document.querySelector("span#humidity").innerHTML = data.humidity[data.count-1][1];
       var date = new Date(lasttime);
       document.querySelector("span#time").innerHTML = date.toTimeString();
    }
    document.querySelector("span#lastupdate").innerHTML = new Date().toTimeString();
}

function requestDelta()
{
    $.ajax({
    url: 'weather.php?mode=delta&delta='+lasttime,
    datatype: "json",
    success: function(data)
    {
	   var i;
           if (data.count > 0) {
	   for(i=0; i<data.count;i++)
	      chart.series[0].addPoint(data.temperature[i], false, true);
           for(i=0; i<data.count;i++)
              chart.series[1].addPoint(data.humidity[i], false, true);
           chart.redraw();
	  }
	  drawCurrent(data);

    }
    });

}

function requestData()
{
    var daterange = document.querySelector("select#daterange").value;
    if (!daterange)
	daterange = "today";
    $.ajax({
    url: 'weather.php?mode='+daterange,
    datatype: "json",
    success: function(data)
    {
           chart.series[0].setData(data.temperature);
           chart.series[1].setData(data.humidity);
           drawCurrent(data);
	   setInterval(requestDelta, 5 * 60 *  1000);
    }
    });
}
$(document).ready(function() {

    Highcharts.setOptions({
        global: {
            useUTC: false
        }
    });
chart = new Highcharts.Chart({
     chart: {
        renderTo: 'graph',
        type: 'spline',
        events: {
            load: requestData
        }
     },
     title: {
        text: 'Monitoring'
     },
    tooltip: {
      shared: true
    },
     xAxis: {
        type: 'datetime',
            maxZoom: 20 * 1000
     },
     yAxis: {
	min: 10,
        minPadding: 0.2,
            maxPadding: 0.2,
            title: {
                text: 'Temperature/Humidity',
                margin: 80
            }
     },
     series: [{
        name: 'Temperature',
        data: []
     },
     {
        name: 'Humidity',
        data: []
     }]
  });
   $('select#daterange').change(function() {requestData();});
  });
})(window, document)
<|endoftext|>


<commit_before>on('ready', function() {
    if (!_.has(state, 'Supernotes')) {
        state.Supernotes = {
            sheet: 'Default',
            template: 'default',
            title: 'name',
            theText: '',
            sendToPlayers: true

        };
        message = 'Welcome to Supernotes! If this is your first time running it, the script is set to use the Default Roll Template. You can choose a different sheet template below, as well as decide whether you want the script to display a "Send to Players" footer at the end of every GM message. It is currently set to true.

[Default Template - any sheet](!gmnote --config|default)
[D&D 5th Edition by Roll20](!gmnote --config|dnd5e)
[DnD 5e Shaped](!gmnote --config|5eshaped)
[Pathfinder by Roll20](!gmnote --config|pfofficial)
[Pathfinder Community](!gmnote --config|pfcommunity)
[Pathfinder 2e by Roll20](!gmnote --config|pf2e)
[Starfinder by Roll20](!gmnote --config|starfinder)

[Toggle Send to Players](!gmnote --config|sendtoPlayers)';
        sendChat('Supernotes', '/w gm &{template:' + state.Supernotes.template + '}{{' + state.Supernotes.title + '=' + 'Config' + '}} {{' + state.Supernotes.theText + '=' + message + '}}');
    }
});

on('ready', () => {

    const decodeUnicode = (str) => str.replace(/%u[0-9a-fA-F]{2,4}/g, (m) => String.fromCharCode(parseInt(m.slice(2), 16)));

    const version = '0.0.7';
    log('Supernotes v' + version + ' is ready!  To set the template of choice or to toggle the send to players option, Use the command !gmnote --config');

    on('chat:message', function(msg) {
        if ('api' === msg.type && msg.content.match(/^!(gm|pc)note\b/)) {
            let match = msg.content.match(/^!gmnote-(.*)$/);

            //define command
            let command = msg.content.split(/\s+--/)[0];

            let messagePrefix = '/w gm ';
            if (command === '!pcnote') {
                messagePrefix = '';
            }

            //define option
            let option = msg.content.split(/\s+--/)[1];

            const template = state.Supernotes.template;
            const title = state.Supernotes.title;
            const theText = state.Supernotes.theText;
            const sendToPlayers = state.Supernotes.sendToPlayers;

            if (option !== undefined && option.includes('config')) {
                let templateChoice = option.split('|')[1]

                if (templateChoice === undefined) {
                    message = 'Current sheet template:
' + state.Supernotes.sheet + '
Send to Players:
' + state.Supernotes.sendToPlayers + '

Choose a template for Supernotes to use.

[Default Template - any sheet](!gmnote --config|default)
[D&D 5th Edition by Roll20](!gmnote --config|dnd5e)
[DnD 5e Shaped](!gmnote --config|5eshaped)
[Pathfinder Community](!gmnote --config|pfcommunity)
[Pathfinder by Roll20](!gmnote --config|pfofficial)
[Pathfinder 2e by Roll20](!gmnote --config|pf2e)
[Starfinder by Roll20](!gmnote --config|starfinder)

[Toggle Send to Players](!gmnote --config|sendtoPlayers)'
                    sendChat('Supernotes', messagePrefix + '&{template:' + template + '}{{' + title + '=' + 'Config' + '}} {{' + theText + '=' + message + '}}');
                }

                switch (templateChoice) {
                    case 'default':
                        state.Supernotes.sheet = 'Default';
                        state.Supernotes.template = 'default';
                        state.Supernotes.title = 'name';
                        state.Supernotes.theText = '';
                        sendChat('Supernotes', '/w gm Supernotes set to Default roll template');
                        break;
                    case 'dnd5e':
                        state.Supernotes.sheet = 'D&D 5th Edition by Roll20';
                        state.Supernotes.template = 'npcaction';
                        state.Supernotes.title = 'rname';
                        state.Supernotes.theText = 'description';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case '5eshaped':
                        state.Supernotes.sheet = 'DnD 5e Shaped';
                        state.Supernotes.template = '5e-shaped';
                        state.Supernotes.title = 'title';
                        state.Supernotes.theText = 'text_big';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'pfcommunity':
                        state.Supernotes.sheet = 'Pathfinder Community';
                        state.Supernotes.template = 'pf_generic';
                        state.Supernotes.title = 'name';
                        state.Supernotes.theText = 'description';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'pfofficial':
                        state.Supernotes.sheet = 'Pathfinder by Roll20';
                        state.Supernotes.template = 'npc';
                        state.Supernotes.title = 'name';
                        state.Supernotes.theText = 'descflag=1}} {{desc';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'pf2e':
                        state.Supernotes.sheet = 'Pathefinder 2e';
                        state.Supernotes.template = 'rolls';
                        state.Supernotes.title = 'header';
                        state.Supernotes.theText = 'notes_show=[[1]]}} {{notes';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'starfinder':
                        state.Supernotes.sheet = 'Starfinder';
                        state.Supernotes.template = 'sf_generic';
                        state.Supernotes.title = 'title';
                        state.Supernotes.theText = 'buttons0';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'sendtoPlayers':
                        if (state.Supernotes.sendToPlayers) {
                            state.Supernotes.sendToPlayers = false
                        } else {
                            state.Supernotes.sendToPlayers = true
                        };
                        sendChat('Supernotes', '/w gm Send to Players set to ' + state.Supernotes.sendToPlayers);
                        break;
                }
            } else {
                if (option !== undefined && option.includes('help')) {
                    message = 'Supernotes pulls the contents from a token's GM Notes field. If the token represents a character, you can optionally pull in the Bio or GM notes from the character, as well as the avatar, or extract just the image from the bio field. The user can decide whether to whisper the notes to the GM or broadcast them to all players. Finally, there is the option to add a footer to notes whispered to the GM. This footer creates a chat button to give the option of sending the notes on to the players.
This script as written is optimized for the D&D 5th Edition by Roll20 sheet, but can be adapted easily suing the Configuration section below.

Commands:
!gmnote whispers the note to the GM
!pcnote sends the note to all players

Paramaters

--token Pulls notes from the selected token's gm notes field. This is optional. If it is missing, the script assumes --token

--charnote Pulls notes from the gm notes field of the character assigned to a token.

--bio Pulls notes from the bio field of the character assigned to a token.

--avatar Pulls the image from the avatar field of the character assigned to a token.

--image Pulls first image from the bio field of the character assigned to a token, if any exists. Otherwise returns notice that no artwork is available

--images Pulls all images from the bio field of the character assigned to a token, if any exist. Otherwise returns notice that no artwork is available

--image[number] Pulls indexed image from the bio field of the character assigned to a token, if any exist. --image1 will pull the first image, --image2 the second and so on. Otherwise returns first image if available. If no images are available, returns notice that no artwork is available.

--help Displays help.

--config Returns a configuration dialog box that allows you to set which sheet's roll template to use, and to toggle the "Send to Players" footer.

Configuration
When first installed, Supernotes is configured for the default roll template. It will display a config dialog box at startup that will allow you to choose a roll template based on your character sheet of choice, as well as the option  to toggle whether you want the "Send to Players" footer button to appear.
You will need to edit the code of the script to create a custom configuration. The pre-installed sheets are:

Default Template
D&D 5th Edition by Roll20
5e Shaped
Pathfinder by Roll20
Pathfinder Community
Pathfinder 2e by Roll20
Starfinder
';
                    sendChat('Supernotes', messagePrefix + '&{template:' + template + '}{{' + title + '=' + 'Supernotes Help' + '}} {{' + theText + '=' + message + '}}');

                } else {
                    if (!(option + '').match(/^(bio|charnote|avatar|imag(e|es|e[1-9]))/)) {
                        option = 'token';
                    }

                    let playerButton = '';
                    if (sendToPlayers && command === '!gmnote') {
                        playerButton = '\n[Send to Players](!pcnote --' + option + ')';
                    }

                    let regex;
                    if (match && match[1]) {
                        regex = new RegExp(`^${match[1]}`, 'i');
                    }

                    let message = '';
                    let whom = '';

                    if (option === 'avatar') {
                        (msg.selected || [])
                        .map(o => getObj('graphic', o._id))
                            .filter(g => undefined !== g)
                            .map(t => getObj('character', t.get('represents')))
                            .filter(c => undefined !== c)
                            .forEach(c => {
                                message = "";
                                whom = c.get('name');
                                sendChat(whom, messagePrefix + '&{template:' + template + '}{{' + title + '=' + whom + '}} {{' + theText + '=' + message + playerButton + '}}');
                            });
                    } else {

                        if (option.match(/^imag(e|es|e[1-9])/)) {

                            (msg.selected || [])
                            .map(o => getObj('graphic', o._id))
                                .filter(g => undefined !== g)
                                .map(t => getObj('character', t.get('represents')))
                                .filter(c => undefined !== c)
                                .forEach(c => c.get('bio', (val) => {
                                    if (null !== val && 'null' !== val && val.length > 0) {
                                        if (regex) {
                                            message = _.filter(
                                                decodeUnicode(val).split(/(?:[\n\r]+|
)/),
                                                (l) => regex.test(l.replace(/<[^>]*>/g, ''))
                                            ).join('\r');
                                        } else {
                                            message = decodeUnicode(val);
                                        }
                                        if (option === "images") {
                                            artwork = message.match(/\/g)
                                        } else {
                                            artwork = message.match(/\/g);
                                            artwork = String(artwork);

                                            imageIndex = option.match(/\d+/g);

                                            if (isNaN(imageIndex) || !imageIndex) {
                                                imageIndex = 1
                                            }

                                            if (imageIndex > (artwork.split(",")).length) {
                                                imageIndex = 1
                                            }

                                            imageIndex = imageIndex - 1; //corrects from human readable

                                            artwork = artwork.split(",")[imageIndex];

                                        }
                                        log("artwork string =" + artwork);
                                        if ((''+artwork).length > 3) {
                                            message = artwork;
                                        } else {
                                            message = 'No artwork exists for this character.';
                                        }

                                        whom = c.get('name');
                                        //Sends the final message
                                        sendChat(whom, messagePrefix + '&{template:' + template + '}{{' + title + '=' + whom + '}} {{' + theText + '=' + message + playerButton + '}}');

                                    }
                                }));
                        } else {

                            if ((option === 'bio') || (option === 'charnote')) {
                                let suboption = (option === 'charnote') ? 'gmnotes' : 'bio';

                                (msg.selected || [])
                                .map(o => getObj('graphic', o._id))
                                    .filter(g => undefined !== g)
                                    .map(t => getObj('character', t.get('represents')))
                                    .filter(c => undefined !== c)
                                    .forEach(c => c.get(suboption, (val) => {
                                        if (null !== val && 'null' !== val && val.length > 0) {
                                            if (regex) {
                                                message = _.filter(
                                                    decodeUnicode(val).split(/(?:[\n\r]+|
)/),
                                                    (l) => regex.test(l.replace(/<[^>]*>/g, ''))
                                                ).join('\r');
                                            } else {
                                                message = decodeUnicode(val);
                                            }
                                            whom = c.get('name');
                                            //Sends the final message
                                            sendChat(whom, messagePrefix + '&{template:' + template + '}{{' + title + '=' + whom + '}} {{' + theText + '=' + message + playerButton + '}}');

                                        }
                                    }));
                            } else {
                                (msg.selected || [])
                                .map(o => getObj('graphic', o._id))
                                    .filter(g => undefined !== g)
                                    .filter((o) => o.get('gmnotes').length > 0)
                                    .forEach(o => {
                                        if (regex) {
                                            message = _.filter(unescape(decodeUnicode(o.get('gmnotes'))).split(/(?:[\n\r]+|
)/), (l) => regex.test(l)).join('\r');
                                        } else {
                                            message = unescape(decodeUnicode(o.get('gmnotes')));
                                        }
                                        whom = o.get('name');

                                    });
                                //Sends the final message
                                sendChat(whom, messagePrefix + '&{template:' + template + '}{{' + title + '=' + whom + '}} {{' + theText + '=' + message + playerButton + '}}');

                            }

                            [
                                `### REPORT###`,
                                `THE MESSAGE =${message}`,
                                `command = ${command}`,
                                `option = ${option}`,
                                `messagePrefix = ${messagePrefix}`,
                                `message =${message}`
                            ].forEach(m => log(m));
                        }
                    }
                }
            }
        }
    });
});
<commit_msg>Update Supernotes.js<commit_after>on('ready', function() {
    if (!_.has(state, 'Supernotes')) {
        state.Supernotes = {
            sheet: 'Default',
            template: 'default',
            title: 'name',
            theText: '',
            sendToPlayers: true

        };
        message = 'Welcome to Supernotes! If this is your first time running it, the script is set to use the Default Roll Template. You can choose a different sheet template below, as well as decide whether you want the script to display a "Send to Players" footer at the end of every GM message. It is currently set to true.

[Default Template - any sheet](!gmnote --config|default)
[D&D 5th Edition by Roll20](!gmnote --config|dnd5e)
[DnD 5e Shaped](!gmnote --config|5eshaped)
[Pathfinder by Roll20](!gmnote --config|pfofficial)
[Pathfinder Community](!gmnote --config|pfcommunity)
[Pathfinder 2e by Roll20](!gmnote --config|pf2e)
[Starfinder by Roll20](!gmnote --config|starfinder)

[Toggle Send to Players](!gmnote --config|sendtoPlayers)';
        sendChat('Supernotes', '/w gm &{template:' + state.Supernotes.template + '}{{' + state.Supernotes.title + '=' + 'Config' + '}} {{' + state.Supernotes.theText + '=' + message + '}}');
    }
});

on('ready', () => {

    const decodeUnicode = (str) => str.replace(/%u[0-9a-fA-F]{2,4}/g, (m) => String.fromCharCode(parseInt(m.slice(2), 16)));

    const version = '0.0.8';
    log('Supernotes v' + version + ' is ready!  To set the template of choice or to toggle the send to players option, Use the command !gmnote --config');

    on('chat:message', function(msg) {
        if ('api' === msg.type && msg.content.match(/^!(gm|pc)note\b/)) {
            let match = msg.content.match(/^!gmnote-(.*)$/);

            //define command
            let command = msg.content.split(/\s+--/)[0];

            let messagePrefix = '/w gm ';
            if (command === '!pcnote') {
                messagePrefix = '';
            }

            //define option
            let option = msg.content.split(/\s+--/)[1];
            let secondOption = msg.content.split(/\s+--/)[2];
            if (option === 'notitle'){
                option = secondOption;
                secondOption = 'notitle';}

            const template = state.Supernotes.template;
            const title = state.Supernotes.title;
            const theText = state.Supernotes.theText;
            const sendToPlayers = state.Supernotes.sendToPlayers;

 if (option !== undefined && option.includes('config')) {
                let templateChoice = option.split('|')[1]

                if (templateChoice === undefined) {
                    message = 'Current sheet template:
' + state.Supernotes.sheet + '
Send to Players:
' + state.Supernotes.sendToPlayers + '

Choose a template for Supernotes to use.

[Default Template - any sheet](!gmnote --config|default)
[D&D 5th Edition by Roll20](!gmnote --config|dnd5e)
[DnD 5e Shaped](!gmnote --config|5eshaped)
[Pathfinder Community](!gmnote --config|pfcommunity)
[Pathfinder by Roll20](!gmnote --config|pfofficial)
[Pathfinder 2e by Roll20](!gmnote --config|pf2e)
[Starfinder by Roll20](!gmnote --config|starfinder)

[Toggle Send to Players](!gmnote --config|sendtoPlayers)'
                    sendChat('Supernotes', messagePrefix + '&{template:' + template + '}{{' + title + '=' + 'Config' + '}} {{' + theText + '=' + message + '}}');
                }

                switch (templateChoice) {
                    case 'default':
                        state.Supernotes.sheet = 'Default';
                        state.Supernotes.template = 'default';
                        state.Supernotes.title = 'name';
                        state.Supernotes.theText = '';
                        sendChat('Supernotes', '/w gm Supernotes set to Default roll template');
                        break;
                    case 'dnd5e':
                        state.Supernotes.sheet = 'D&D 5th Edition by Roll20';
                        state.Supernotes.template = 'npcaction';
                        state.Supernotes.title = 'rname';
                        state.Supernotes.theText = 'description';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case '5eshaped':
                        state.Supernotes.sheet = 'DnD 5e Shaped';
                        state.Supernotes.template = '5e-shaped';
                        state.Supernotes.title = 'title';
                        state.Supernotes.theText = 'text_big';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'pfcommunity':
                        state.Supernotes.sheet = 'Pathfinder Community';
                        state.Supernotes.template = 'pf_generic';
                        state.Supernotes.title = 'name';
                        state.Supernotes.theText = 'description';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'pfofficial':
                        state.Supernotes.sheet = 'Pathfinder by Roll20';
                        state.Supernotes.template = 'npc';
                        state.Supernotes.title = 'name';
                        state.Supernotes.theText = 'descflag=1}} {{desc';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'pf2e':
                        state.Supernotes.sheet = 'Pathefinder 2e';
                        state.Supernotes.template = 'rolls';
                        state.Supernotes.title = 'header';
                        state.Supernotes.theText = 'notes_show=[[1]]}} {{notes';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'starfinder':
                        state.Supernotes.sheet = 'Starfinder';
                        state.Supernotes.template = 'sf_generic';
                        state.Supernotes.title = 'title';
                        state.Supernotes.theText = 'buttons0';
                        sendChat('Supernotes', '/w gm Supernotes set to ' + state.Supernotes.sheet);
                        break;
                    case 'sendtoPlayers':
                        if (state.Supernotes.sendToPlayers) {
                            state.Supernotes.sendToPlayers = false
                        } else {
                            state.Supernotes.sendToPlayers = true
                        };
                        sendChat('Supernotes', '/w gm Send to Players set to ' + state.Supernotes.sendToPlayers);
                        break;
                }
            } else {
                if (option !== undefined && option.includes('help')) {
                    message = 'Supernotes pulls the contents from a token's GM Notes field. If the token represents a character, you can optionally pull in the Bio or GM notes from the character, as well as the avatar, or extract just the image from the bio field. The user can decide whether to whisper the notes to the GM or broadcast them to all players. Finally, there is the option to add a footer to notes whispered to the GM. This footer creates a chat button to give the option of sending the notes on to the players.
This script as written is optimized for the D&D 5th Edition by Roll20 sheet, but can be adapted easily suing the Configuration section below.

Commands:
!gmnote whispers the note to the GM
!pcnote sends the note to all players

Paramaters

--token Pulls notes from the selected token's gm notes field. This is optional. If it is missing, the script assumes --token

--charnote Pulls notes from the gm notes field of the character assigned to a token.

--bio Pulls notes from the bio field of the character assigned to a token.

--avatar Pulls the image from the avatar field of the character assigned to a token.

--image Pulls first image from the bio field of the character assigned to a token, if any exists. Otherwise returns notice that no artwork is available

--images Pulls all images from the bio field of the character assigned to a token, if any exist. Otherwise returns notice that no artwork is available

--image[number] Pulls indexed image from the bio field of the character assigned to a token, if any exist. --image1 will pull the first image, --image2 the second and so on. Otherwise returns first image if available. If no images are available, returns notice that no artwork is available.

--help Displays help.

--config Returns a configuration dialog box that allows you to set which sheet's roll template to use, and to toggle the "Send to Players" footer.

Configuration
When first installed, Supernotes is configured for the default roll template. It will display a config dialog box at startup that will allow you to choose a roll template based on your character sheet of choice, as well as the option  to toggle whether you want the "Send to Players" footer button to appear.
You will need to edit the code of the script to create a custom configuration. The pre-installed sheets are:

Default Template
D&D 5th Edition by Roll20
5e Shaped
Pathfinder by Roll20
Pathfinder Community
Pathfinder 2e by Roll20
Starfinder
';
                    sendChat('Supernotes', messagePrefix + '&{template:' + template + '}{{' + title + '=' + 'Supernotes Help' + '}} {{' + theText + '=' + message + '}}');

                } else {
                    if (!(option + '').match(/^(bio|charnote|avatar|imag(e|es|e[1-9]))/)) {
                        option = 'token';
                    }

                    let playerButton = '';
                    if (sendToPlayers && command === '!gmnote') {
                        playerButton = '\n[Send to Players](!pcnote --' + option + ')';
                    }

                    let regex;
                    if (match && match[1]) {
                        regex = new RegExp(`^${match[1]}`, 'i');
                    }

                    let message = '';
                    let whom = '';

                    if (option === 'avatar') {
                        (msg.selected || [])
                        .map(o => getObj('graphic', o._id))
                            .filter(g => undefined !== g)
                            .map(t => getObj('character', t.get('represents')))
                            .filter(c => undefined !== c)
                            .forEach(c => {
                                message = "";
                                whom = c.get('name');
                                            if (secondOption === 'notitle'){whom = '';}
                                sendChat(whom, messagePrefix + '&{template:' + template + '}{{' + title + '=' + whom + '}} {{' + theText + '=' + message + playerButton + '}}');
                            });
                    } else {

                        if (option.match(/^imag(e|es|e[1-9])/)) {

                            (msg.selected || [])
                            .map(o => getObj('graphic', o._id))
                                .filter(g => undefined !== g)
                                .map(t => getObj('character', t.get('represents')))
                                .filter(c => undefined !== c)
                                .forEach(c => c.get('bio', (val) => {
                                    if (null !== val && 'null' !== val && val.length > 0) {
                                        if (regex) {
                                            message = _.filter(
                                                decodeUnicode(val).split(/(?:[\n\r]+|
)/),
                                                (l) => regex.test(l.replace(/<[^>]*>/g, ''))
                                            ).join('\r');
                                        } else {
                                            message = decodeUnicode(val);
                                        }
                                        if (option === "images") {
                                            artwork = message.match(/\/g)
                                        } else {
                                            artwork = message.match(/\/g);
                                            artwork = String(artwork);

                                            imageIndex = option.match(/\d+/g);

                                            if (isNaN(imageIndex) || !imageIndex) {
                                                imageIndex = 1
                                            }

                                            if (imageIndex > (artwork.split(",")).length) {
                                                imageIndex = 1
                                            }

                                            imageIndex = imageIndex - 1; //corrects from human readable

                                            artwork = artwork.split(",")[imageIndex];

                                        }
                                        log("artwork string =" + artwork);
                                        if ((''+artwork).length > 3) {
                                            message = artwork;
                                        } else {
                                            message = 'No artwork exists for this character.';
                                        }

                                        whom = c.get('name');
                                        //Sends the final message
                                            if (secondOption === 'notitle'){whom = '';}
                                        sendChat(whom, messagePrefix + '&{template:' + template + '}{{' + title + '=' + whom + '}} {{' + theText + '=' + message + playerButton + '}}');

                                    }
                                }));
                        } else {

                            if ((option === 'bio') || (option === 'charnote')) {
                                let suboption = (option === 'charnote') ? 'gmnotes' : 'bio';

                                (msg.selected || [])
                                .map(o => getObj('graphic', o._id))
                                    .filter(g => undefined !== g)
                                    .map(t => getObj('character', t.get('represents')))
                                    .filter(c => undefined !== c)
                                    .forEach(c => c.get(suboption, (val) => {
                                        if (null !== val && 'null' !== val && val.length > 0) {
                                            if (regex) {
                                                message = _.filter(
                                                    decodeUnicode(val).split(/(?:[\n\r]+|
)/),
                                                    (l) => regex.test(l.replace(/<[^>]*>/g, ''))
                                                ).join('\r');
                                            } else {
                                                message = decodeUnicode(val);
                                            }
                                            whom = c.get('name');
                                            //Sends the final message
                                            if (secondOption === 'notitle'){whom = '';}
                                            sendChat(whom, messagePrefix + '&{template:' + template + '}{{' + title + '=' + whom + '}} {{' + theText + '=' + message + playerButton + '}}');

                                        }
                                    }));
                            } else {
                                (msg.selected || [])
                                .map(o => getObj('graphic', o._id))
                                    .filter(g => undefined !== g)
                                    .filter((o) => o.get('gmnotes').length > 0)
                                    .forEach(o => {
                                        if (regex) {
                                            message = _.filter(unescape(decodeUnicode(o.get('gmnotes'))).split(/(?:[\n\r]+|
)/), (l) => regex.test(l)).join('\r');
                                        } else {
                                            message = unescape(decodeUnicode(o.get('gmnotes')));
                                        }
                                        whom = o.get('name');

                                    });
                                //Sends the final message
                                            if (secondOption === 'notitle'){whom = '';}
                                sendChat(whom, messagePrefix + '&{template:' + template + '}{{' + title + '=' + whom + '}} {{' + theText + '=' + message + playerButton + '}}');

                            }

                            [
                                `### REPORT###`,
                                `THE MESSAGE =${message}`,
                                `command = ${command}`,
                                `option = ${option}`,
                                `secondOption = ${secondOption}`,
                                `messagePrefix = ${messagePrefix}`,
                                `whom = ${whom}`,
                                `message =${message}`
                            ].forEach(m => log(m));
                        }
                    }
                }
            }
        }
    });
});
<|endoftext|>


<commit_before>if (!TC.Control) {
    TC.syncLoadJS(TC.apiLocation + 'TC/Control');
}

TC.control.FileImport = function () {
    var self = this;

    TC.Control.apply(self, arguments);

    if ($.isArray(self.options.formats)) {
        self.formats = self.options.formats;
    }
    else {
        self.formats = [
            TC.Consts.format.KML,
            TC.Consts.format.GML,
            TC.Consts.format.GML2,
            TC.Consts.format.GEOJSON,
            TC.Consts.format.WKT,
            TC.Consts.format.GPX
        ];
    }

    self.apiAttribution = '';
    self.mainDataAttribution = '';
    self.dataAttributions = [];
};

TC.inherit(TC.control.FileImport, TC.Control);

(function () {
    var ctlProto = TC.control.FileImport.prototype;

    ctlProto.CLASS = 'tc-ctl-file';

    if (TC.isDebug) {
        ctlProto.template = TC.apiLocation + "TC/templates/FileImport.html";
    }
    else {
        ctlProto.template = function () { dust.register(ctlProto.CLASS, body_0); function body_0(chk, ctx) { return chk.w("
").h("i18n", ctx, {}, { "$key": "openFile" }).w("

").h("i18n", ctx, {}, { "$key": "fileImport.instructions" }).w("

<input type=\"file\" class=\"tc-ctl-file-open-ipt tc-button\" accept=\"").s(ctx.get(["formats"], false), ctx, { "block": body_1 }, {}).w("\" />").h("i18n", ctx, {}, { "$key": "openFile" }).w("

"); } body_0.__dustBody = !0; function body_1(chk, ctx) { return chk.w(".").f(ctx.getPath(true, []), ctx, "h").h("sep", ctx, { "block": body_2 }, {}); } body_1.__dustBody = !0; function body_2(chk, ctx) { return chk.w(","); } body_2.__dustBody = !0; return body_0 };
    }

    ctlProto.register = function (map) {
        var self = this;
        TC.Control.prototype.register.call(self, map);

        if (self.options.enableDragAndDrop) {
            map.wrap.enableDragAndDrop(self.options);
        }

        map
            .on(TC.Consts.event.FEATURESIMPORT, function (e) {
                // Ignoramos los GPX (se supone que los gestionará Geolocation)
                var pattern = '.' + TC.Consts.format.GPX.toLowerCase();
                if (e.fileName.toLowerCase().indexOf(pattern) === e.fileName.length - pattern.length) {
                    return;
                }
                map.addLayer({
                    id: self.getUID(),
                    title: e.fileName,
                    type: TC.Consts.layerType.VECTOR
                }).then(function (layer) {
                    var geogCrs = 'EPSG:4326';
                    const flatten = function (prev, cur) {
                        return prev.concat(cur);
                    };
                    var projectGeom = function (feature) {
                        var geom = feature.geometry;
                        if (geom) {
                            var coordinates;
                            switch (true) {
                                case TC.feature.Point && feature instanceof TC.feature.Point:
                                    coordinates = [geom];
                                    break;
                                case TC.feature.MultiPoint && feature instanceof TC.feature.MultiPoint:
                                case TC.feature.Polyline && feature instanceof TC.feature.Polyline:
                                    coordinates = geom;
                                    break;
                                case TC.feature.MultiPolyline && feature instanceof TC.feature.MultiPolyline:
                                case TC.feature.Polygon && feature instanceof TC.feature.Polygon:
                                    coordinates = geom.reduce(flatten);
                                    break;
                                case TC.feature.MultiPolygon && feature instanceof TC.feature.MultiPolygon:
                                    coordinates = geom.reduce(flatten).reduce(flatten);
                                    break;
                                default:
                                    break;
                            }
                            if (coordinates.every(function (coord) {
                                return Math.abs(coord[0]) <= 180 && Math.abs(coord[1]) <= 90; // Parecen geográficas
                            })) {
                                feature.setCoords(TC.Util.reproject(geom, geogCrs, self.map.crs));
                            }
                        }

                        return feature;
                    };

                    for (var i = 0, len = e.features.length; i < len; i++) {
                        var projectedFeature = projectGeom(e.features[i]);
                        layer.addFeature(projectedFeature);
                    }
                    setTimeout(function () {
                        map.zoomToFeatures(layer.features);
                    }, 100);
                });
            })
            .on(TC.Consts.event.FEATURESIMPORTERROR, function (e) {
                var dictKey;
                var fileName = e.file.name;
                if (fileName.toLowerCase().substr(fileName.length - 4) === '.kmz') {
                    dictKey = 'fileImport.error.reasonKmz';
                }
                else {
                    dictKey = 'fileImport.error.reasonUnknown';
                }

                TC.error(self.getLocaleString(dictKey, { fileName: fileName }), TC.Consts.msgErrorMode.TOAST);

                var reader = new FileReader();
                reader.onload = function (event) {
                    TC.error("Nombre del archivo: " + fileName + " \n Contenido del archivo: \n\n" + event.target.result, TC.Consts.msgErrorMode.EMAIL,"Error en la subida de un archivo");
                };
                reader.readAsText(e.file);
            });
    };

    ctlProto.render = function () {
        var self = this;
        self.renderData({ formats: self.formats }, function () {
            self._$div.find('input[type=file]')
                // GLS: Eliminamos el archivo subido, sin ello no podemos subir el mismo archivo seguido varias veces
                .on(TC.Consts.event.CLICK, function (e) {
                    $(this).wrap('<form>').closest('form').get(0).reset();
                    $(this).unwrap();
                })
                .on('change', function (e) {
                    if (self.map) {
                        console.log('salta el change');
                        self.map.wrap.loadFiles(e.target.files);
                    }
                });
        });
    };

})();
<commit_msg>Add state import/export methods<commit_after>if (!TC.Control) {
    TC.syncLoadJS(TC.apiLocation + 'TC/Control');
}

TC.control.FileImport = function () {
    var self = this;

    TC.Control.apply(self, arguments);

    if ($.isArray(self.options.formats)) {
        self.formats = self.options.formats;
    }
    else {
        self.formats = [
            TC.Consts.format.KML,
            TC.Consts.format.GML,
            TC.Consts.format.GML2,
            TC.Consts.format.GEOJSON,
            TC.Consts.format.WKT,
            TC.Consts.format.GPX
        ];
    }

    self.layers = [];

    self.apiAttribution = '';
    self.mainDataAttribution = '';
    self.dataAttributions = [];
};

TC.inherit(TC.control.FileImport, TC.Control);

(function () {
    var ctlProto = TC.control.FileImport.prototype;

    ctlProto.CLASS = 'tc-ctl-file';

    if (TC.isDebug) {
        ctlProto.template = TC.apiLocation + "TC/templates/FileImport.html";
    }
    else {
        ctlProto.template = function () { dust.register(ctlProto.CLASS, body_0); function body_0(chk, ctx) { return chk.w("
").h("i18n", ctx, {}, { "$key": "openFile" }).w("

").h("i18n", ctx, {}, { "$key": "fileImport.instructions" }).w("

<input type=\"file\" class=\"tc-ctl-file-open-ipt tc-button\" accept=\"").s(ctx.get(["formats"], false), ctx, { "block": body_1 }, {}).w("\" />").h("i18n", ctx, {}, { "$key": "openFile" }).w("

"); } body_0.__dustBody = !0; function body_1(chk, ctx) { return chk.w(".").f(ctx.getPath(true, []), ctx, "h").h("sep", ctx, { "block": body_2 }, {}); } body_1.__dustBody = !0; function body_2(chk, ctx) { return chk.w(","); } body_2.__dustBody = !0; return body_0 };
    }

    ctlProto.register = function (map) {
        var self = this;
        TC.Control.prototype.register.call(self, map);

        if (self.options.enableDragAndDrop) {
            map.wrap.enableDragAndDrop(self.options);
        }

        map
            .on(TC.Consts.event.FEATURESIMPORT, function (e) {
                // Ignoramos los GPX (se supone que los gestionará Geolocation)
                var pattern = '.' + TC.Consts.format.GPX.toLowerCase();
                if (e.fileName.toLowerCase().indexOf(pattern) === e.fileName.length - pattern.length) {
                    return;
                }
                map.addLayer({
                    id: self.getUID(),
                    title: e.fileName,
                    type: TC.Consts.layerType.VECTOR
                }).then(function (layer) {
                    self.layers.push(layer);
                    var geogCrs = 'EPSG:4326';
                    const flatten = function (prev, cur) {
                        return prev.concat(cur);
                    };
                    var projectGeom = function (feature) {
                        var geom = feature.geometry;
                        if (geom) {
                            var coordinates;
                            switch (true) {
                                case TC.feature.Point && feature instanceof TC.feature.Point:
                                    coordinates = [geom];
                                    break;
                                case TC.feature.MultiPoint && feature instanceof TC.feature.MultiPoint:
                                case TC.feature.Polyline && feature instanceof TC.feature.Polyline:
                                    coordinates = geom;
                                    break;
                                case TC.feature.MultiPolyline && feature instanceof TC.feature.MultiPolyline:
                                case TC.feature.Polygon && feature instanceof TC.feature.Polygon:
                                    coordinates = geom.reduce(flatten);
                                    break;
                                case TC.feature.MultiPolygon && feature instanceof TC.feature.MultiPolygon:
                                    coordinates = geom.reduce(flatten).reduce(flatten);
                                    break;
                                default:
                                    break;
                            }
                            if (coordinates.every(function (coord) {
                                return Math.abs(coord[0]) <= 180 && Math.abs(coord[1]) <= 90; // Parecen geográficas
                            })) {
                                feature.setCoords(TC.Util.reproject(geom, geogCrs, self.map.crs));
                            }
                        }

                        return feature;
                    };

                    for (var i = 0, len = e.features.length; i < len; i++) {
                        var projectedFeature = projectGeom(e.features[i]);
                        layer.addFeature(projectedFeature);
                    }
                    setTimeout(function () {
                        map.zoomToFeatures(layer.features);
                    }, 100);
                });
            })
            .on(TC.Consts.event.FEATURESIMPORTERROR, function (e) {
                var dictKey;
                var fileName = e.file.name;
                if (fileName.toLowerCase().substr(fileName.length - 4) === '.kmz') {
                    dictKey = 'fileImport.error.reasonKmz';
                }
                else {
                    dictKey = 'fileImport.error.reasonUnknown';
                }

                TC.error(self.getLocaleString(dictKey, { fileName: fileName }), TC.Consts.msgErrorMode.TOAST);

                var reader = new FileReader();
                reader.onload = function (event) {
                    TC.error("Nombre del archivo: " + fileName + " \n Contenido del archivo: \n\n" + event.target.result, TC.Consts.msgErrorMode.EMAIL, "Error en la subida de un archivo");
                };
                reader.readAsText(e.file);
            })
            .on(TC.Consts.event.LAYERREMOVE, function (e) {
                const idx = self.layers.indexOf(e.layer);
                if (idx >= 0) {
                    self.layers.splice(idx, 1);
                }
            });
    };

    ctlProto.render = function () {
        var self = this;
        self.renderData({ formats: self.formats }, function () {
            self._$div.find('input[type=file]')
                // GLS: Eliminamos el archivo subido, sin ello no podemos subir el mismo archivo seguido varias veces
                .on(TC.Consts.event.CLICK, function (e) {
                    $(this).wrap('<form>').closest('form').get(0).reset();
                    $(this).unwrap();
                })
                .on('change', function (e) {
                    if (self.map) {
                        console.log('salta el change');
                        self.map.wrap.loadFiles(e.target.files);
                    }
                });
        });
    };

    ctlProto.exportState = function () {
        const self = this;
        return {
            id: self.id,
            layers: self.layers.map(function (layer) {
                return {
                    title: layer.title,
                    state: layer.exportState()
                };
            })
        };
    };

    ctlProto.importState = function (state) {
        const self = this;
        if (self.map) {
            const layerPromises = [];
            state.layers.forEach(function (layerData) {
                layerPromises.push(self.map.addLayer({
                    id: self.getUID(),
                    title: layerData.title,
                    type: TC.Consts.layerType.VECTOR
                }));
            });

            $.when.apply($, layerPromises).then(function () {
                for (var i = 0, len = arguments.length; i < len; i++) {
                    const layer = arguments[i];
                    layer.importState(state.layers[i].state);
                    self.layers.push(layer);
                }
            });
        }
    };

})();
<|endoftext|>


<commit_before>import moment from 'moment';

/**
 * A function that converts the compressed meter data into a CSV formatted string.
 * @param items The compressed meter data.
 * @returns output A string containing the CSV formatted compressed meter data.
 */

function convertToCSV(items) {
	let csvOutput = 'id:,readings:,timestamp:\n';
	items.forEach(set => {
		const data = set.exportVals;
		const id = set.id;
		let isStart = true;
		data.forEach(reading => {
			const info = reading.y;
			const timeStamp = moment(reading.x).format('dddd MMM DD YYYY hh:mm a');
			if (isStart) {
				csvOutput += `${id},${info} kwh, ${timeStamp} \n`;
				isStart = false;
			} else {
				csvOutput += `${id},${info} kwh, ${timeStamp} \n`;
			}
		});
	});
	return csvOutput;
}
/**
 * A function to download the formatted CSV file to the users computer.
 * @param inputCSV A String containing the formatted CSV data.
 */
function downloadCSV(inputCSV) {
	const csvContent = `data:text/csv;charset=utf-8,${inputCSV}`;
	const encodedUri = encodeURI(csvContent);
	const link = document.createElement('a');
	let fileName = 'exportedDataOED';
	fileName += '.csv';
	link.setAttribute('href', encodedUri);
	link.setAttribute('download', fileName);
	document.body.appendChild(link);

	link.click(); // This will download the data file
}
/**
 * Function to export compressed data from the graph currently displaying. May be used for routing if more export options are added
 * @param dataSets An Object. The compressed data from each meter currently selected in the graph.
 */
export default function graphExport(dataSets) {
	const dataToExport = convertToCSV(dataSets);
	downloadCSV(dataToExport);
}
<commit_msg>compressed filename variable in exportData.js to 1 line and removed unnecessary conditional.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import moment from 'moment';

/**
 * Function to converts the compressed meter data into a CSV formatted string.
 * @param items The compressed meter data.
 * @returns output A string containing the CSV formatted compressed meter data.
 */

function convertToCSV(items) {
	let csvOutput = 'id:,readings:,timestamp:\n';
	items.forEach(set => {
		const data = set.exportVals;
		const id = set.id;
		data.forEach(reading => {
			const info = reading.y;
			const timeStamp = moment(reading.x).format('dddd MMM DD YYYY hh:mm a');
			csvOutput += `${id},${info} kwh, ${timeStamp} \n`;
		});
	});
	return csvOutput;
}
/**
 * Function to download the formatted CSV file to the users computer.
 * @param inputCSV A String containing the formatted CSV data.
 */
function downloadCSV(inputCSV) {
	const csvContent = `data:text/csv;charset=utf-8,${inputCSV}`;
	const encodedUri = encodeURI(csvContent);
	const link = document.createElement('a');
	const fileName = 'exportedDataOED.csv';
	link.setAttribute('href', encodedUri);
	link.setAttribute('download', fileName);
	document.body.appendChild(link);

	link.click(); // This will download the data file
}
/**
 * Function to export compressed data from the graph currently displaying. May be used for routing if more export options are added
 * @param dataSets An Object. The compressed data from each meter currently selected in the graph.
 */
export default function graphExport(dataSets) {
	const dataToExport = convertToCSV(dataSets);
	downloadCSV(dataToExport);
}
<|endoftext|>


<commit_before>/**!
 *
 * Copyright (c) 2015-2016 Cisco Systems, Inc. See LICENSE file.
 */

'use strict';

var SparkBase = require('../../../lib/spark-base');
var AvatarUrlRequestBatcher = require('./avatar-url-request-batcher');
var defaults = require('lodash.defaults');
var patterns = require('../../../util/patterns');

/**
 * @class
 * @extends {SparkBase}
 * @memberof Avatar
 */
var AvatarService = SparkBase.extend(
  /** @lends Avatar.AvatarService.prototype */
  {
  children: {
    _batcher: AvatarUrlRequestBatcher
  },

  derived: {
    store: {
      deps: ['_batcher'],
      fn: function store() {
        return this._batcher.store;
      }
    }
  },

  namespace: 'Avatar',

  /**
   * Retrieves an Avatar URL from the api.
   * Avatars are square images with sides of 1600, 640, 192, 135, 110, 80, 50,
   * or 40 pixels. If no size is specified, 80px will be retrieved. If a
   * non-standard size is requested, the server will return the closest-but-
   * greater size (or 1600).
   * @param {UserObject|string} user The user for which to retrieve an avatar
   * url.
   * @param {Object} options [description]
   * @param {integer} options.size One of 1600, 640, 192, 135, 110, 80, 50, or
   * 40. Defaults to 80
   */
  retrieveAvatarUrl: function retrieveAvatarUrl(user, options) {
    /* eslint complexity: [0] */
    options = options || {};
    defaults(options, {
      size: this.config.defaultAvatarSize
    });

    if (!user) {
      return Promise.reject(new Error('`user` is a required parameter'));
    }

    var id = (user.id || user.email || user.emailAddress || user);

    if (!id) {
      return Promise.reject(new Error('`user` is a required parameter'));
    }

    id = id.toLowerCase();

    if (patterns.uuid.test(id)) {
      return this._batcher.fetch(id, options.size);
    }
    else {
      return this.spark.user.getUUID(id)
        .then(function fetchAvatarUrl(uuid) {
          if (!uuid) {
            throw new Error('User "' + id + '" does not appear to exist');
          }

          return this._batcher.fetch(uuid, options.size);
        }.bind(this))
        .catch(function processError(reason) {
          throw new Error('failed to retrieve avatar url: ' + (reason.body || reason));
        });
    }
  },

  /**
   * Upload a new avatar for the current user
   * @memberof AvatarService.prototype
   * @param {Blob|File|Buffer} file The new avatar
   * @returns {Promise} Resolves with the URL of the full-sized avatar
   */
  setAvatar: function setAvatar(file) {
    return this.upload({
      api: 'avatar',
      resource: 'profile',
      file: file,
      phases: {
        upload: {
          $uri: function $uri(session) {
            return session.url;
          }
        },
        finalize: {
          method: 'PUT',
          api: 'avatar',
          $resource: function $resource(session) {
            return 'profile/' + session.id;
          },
          $body: function $body(session) {
            return session;
          }
        }
      }
    })
      .then(function processResponse(res) {
        // invalidate user's cached avatar
        this.store.remove(this.spark.device.userId);
        return res.url;
      }.bind(this));
  }
});

module.exports = AvatarService;
<commit_msg>fix(avatar): use _values.id when no user id<commit_after>/**!
 *
 * Copyright (c) 2015-2016 Cisco Systems, Inc. See LICENSE file.
 */

'use strict';

var SparkBase = require('../../../lib/spark-base');
var AvatarUrlRequestBatcher = require('./avatar-url-request-batcher');
var defaults = require('lodash.defaults');
var patterns = require('../../../util/patterns');

/**
 * @class
 * @extends {SparkBase}
 * @memberof Avatar
 */
var AvatarService = SparkBase.extend(
  /** @lends Avatar.AvatarService.prototype */
  {
  children: {
    _batcher: AvatarUrlRequestBatcher
  },

  derived: {
    store: {
      deps: ['_batcher'],
      fn: function store() {
        return this._batcher.store;
      }
    }
  },

  namespace: 'Avatar',

  /**
   * Retrieves an Avatar URL from the api.
   * Avatars are square images with sides of 1600, 640, 192, 135, 110, 80, 50,
   * or 40 pixels. If no size is specified, 80px will be retrieved. If a
   * non-standard size is requested, the server will return the closest-but-
   * greater size (or 1600).
   * @param {UserObject|string} user The user for which to retrieve an avatar
   * url.
   * @param {Object} options [description]
   * @param {integer} options.size One of 1600, 640, 192, 135, 110, 80, 50, or
   * 40. Defaults to 80
   */
  retrieveAvatarUrl: function retrieveAvatarUrl(user, options) {
    /* eslint complexity: [0] */
    options = options || {};
    defaults(options, {
      size: this.config.defaultAvatarSize
    });

    if (!user) {
      return Promise.reject(new Error('`user` is a required parameter'));
    }

    var id = (user.id || (user._values ? user._values.id : user._values) || user.email || user.emailAddress || user);

    if (!id) {
      return Promise.reject(new Error('`user` is a required parameter'));
    }

    id = id.toLowerCase();

    if (patterns.uuid.test(id)) {
      return this._batcher.fetch(id, options.size);
    }
    else {
      return this.spark.user.getUUID(id)
        .then(function fetchAvatarUrl(uuid) {
          if (!uuid) {
            throw new Error('User "' + id + '" does not appear to exist');
          }

          return this._batcher.fetch(uuid, options.size);
        }.bind(this))
        .catch(function processError(reason) {
          throw new Error('failed to retrieve avatar url: ' + (reason.body || reason));
        });
    }
  },

  /**
   * Upload a new avatar for the current user
   * @memberof AvatarService.prototype
   * @param {Blob|File|Buffer} file The new avatar
   * @returns {Promise} Resolves with the URL of the full-sized avatar
   */
  setAvatar: function setAvatar(file) {
    return this.upload({
      api: 'avatar',
      resource: 'profile',
      file: file,
      phases: {
        upload: {
          $uri: function $uri(session) {
            return session.url;
          }
        },
        finalize: {
          method: 'PUT',
          api: 'avatar',
          $resource: function $resource(session) {
            return 'profile/' + session.id;
          },
          $body: function $body(session) {
            return session;
          }
        }
      }
    })
      .then(function processResponse(res) {
        // invalidate user's cached avatar
        this.store.remove(this.spark.device.userId);
        return res.url;
      }.bind(this));
  }
});

module.exports = AvatarService;
<|endoftext|>