<commit_before>/*
 * ------------------------------------------
 * 音频播放控件实现文件
 * @version  1.0
 * @author   genify(caijf@corp.netease.com)
 * ------------------------------------------
 */
var f = function(){
    // variable declaration
    var _  = NEJ.P,
        _c = _('nej.c'),
        _e = _('nej.e'),
        _p = _('nej.ut'),
        _pro;
    if (!!_p._$$MediaFlash) return;
    /**
     * 音频播放控件

     * 脚本举例
     * [code]
     *   // 首先生成播放对象,只负责逻辑部分，要配合UI来使用
     *   // preload：是否预加载
     *   // url：音频地址
     *   var _mda = _p._$$MediaFlash._$allocate({
     *       preload:false,
     *       url:'http://127.0.0.1:8000/nej-baseline/res/test.mp3',
     *       onstatechange:function(_event){
     *           // 状态改变的回调
     *           // 0 | 当前停止状态
     *           // 1 | 当前缓冲状态
     *           // 2 | 当前播放状态
     *           // 3 | 当前暂停状态
     *           // 4 | 播放结束状态
     *       }
     *   });
     *   // 开始播放
     *   _mda._$play();
     *   // 暂停播放
     *   _mda._$pause();
     *   // 停止播放
     *   _mda._$stop();
     * [/code]
     * @class   {nej.ut._$$MediaFlash} 音频播放控件
     * @extends {nej.ut._$$Media}
     * @param   {Object} 可选配置参数，已处理参数列表如下所示
     * @config  {String} url 音频地址
     */
    _p._$$MediaFlash = NEJ.C();
    _pro = _p._$$MediaFlash._$extend(_p._$$Media);
    /**
     * 控件初始化
     * @return {Void}
     */
    _pro.__init = (function(){
        var _onReady = function(_flash){
            this.__audio = _flash;
            if (!!this.__action){
                this.__action.call(this);
                delete this.__action;
            }
        };
        return function(){
            this.__supInit();
            _e._$flash({
                hidden:!0,
                src:_c._$get('audio.swf'),
                onready:_onReady._$bind(this),
                onended:this.__onStop._$bind(this),
                onpause:this.__onPause._$bind(this),
                onseking:this.__onLoading._$bind(this),
                onprogress:this.__onLoading._$bind(this),
                ontimeupdate:this.__onPlaying._$bind(this),
                onvolumechange:this.__onVolumeChange._$bind(this),
                onerror:this.__onError._$bind(this)
            });
        };
    })();
    /**
     * 控件销毁
     * @return {Void}
     */
    _pro.__destroy = function(){
        this.__supDestroy();
        delete this.__action;
    };
    /**
     * 执行播放操作
     * @protected
     * @method {__doPlay}
     * @return {Void}
     */
    _pro.__doPlay = function(){
        if (!!this.__audio){
            this.__audio.nej_setSrc(this.__source);
            this.__audio.nej_play();
        }else{
            this.__action = this.__doPlay;
        }
    };
    /**
     * 执行暂停操作
     * @protected
     * @method {__doPause}
     * @return {Void}
     */
    _pro.__doPause = function(){
        if (!!this.__audio){
            this.__audio.nej_pause();
        }else{
            this.__action = this.__doPause;
        }
    };
    /**
     * 执行停止操作
     * @protected
     * @method {__doStop}
     * @return {Void}
     */
    _pro.__doStop = function(){
        if (!!this.__audio){
            this.__audio.nej_stop();
            this.__doStateChange(0);
        }else{
            this.__action = this.__doStop;
        }
    };
    /**
     * 文件载入触发事件
     * @protected
     * @method {__onLoading}
     * @return {Void}
     */
    _pro.__onLoading = function(){
        this.__doStateChange(1);
    };
    /**
     * 暂停触发事件
     * @protected
     * @method {__onPause}
     * @return {Void}
     */
    _pro.__onPause = function(){
        this.__doStateChange(3);
    };
    /**
     * 播放过程触发事件
     * @protected
     * @method {__onPlaying}
     * @return {Void}
     */
    _pro.__onPlaying = function(_event){
        this.__doStateChange(2);
        this._$dispatchEvent(
            'ontimeupdate',{
                duration:_event.duration,
                current:_event.currentTime
            }
        );
    };
    /**
     * 播放错误事件
     * @param  {Event} 事件信息
     * @return {Void}
     */
    _pro.__onError = function(_event){
        this.__doError();
        this._$dispatchEvent('onerror',{
            code:_event.code
        });
    };
    /**
     * 设置播放时间
     * @protected
     * @method {__setCurrentTime}
     * @return {Void}
     */
    _pro.__setCurrentTime = function(_time){
        if (this.__state==1) return;
        this.__audio.nej_seek(_time||0);
    };
    /**
     * 获取播放时间
     * @protected
     * @method {__getCurrentTime}
     * @return {Number} 当前时间
     */
    _pro.__getCurrentTime = function(){
        return this.__audio.nej_flash_get_currentTime();
    };
    /**
     * 设置音量
     * @protected
     * @method {__setVolume}
     * @return {Void}
     */
    _pro.__setVolume = function(_volume){
        if (!this.__audio) return;
        this.__audio.nej_flash_set_volume(_volume);
    };
    /**
     * 获取音量
     * @protected
     * @method {__getVolume}
     * @return {Number} 音量值
     */
    _pro.__getVolume = function(){
        if (!this.__audio) return;
        return this.__audio.nej_flash_get_volume();
    };
};
NEJ.define(
    '{lib}util/media/flash.js',[
    '{patch}config.js',
    '{lib}base/event.js',
    '{lib}util/media/media.js',
    '{lib}util/flash/flash.js'
],f);<commit_msg>check source setting for flash media<commit_after>/*
 * ------------------------------------------
 * 音频播放控件实现文件
 * @version  1.0
 * @author   genify(caijf@corp.netease.com)
 * ------------------------------------------
 */
var f = function(){
    // variable declaration
    var _  = NEJ.P,
        _c = _('nej.c'),
        _e = _('nej.e'),
        _p = _('nej.ut'),
        _pro;
    if (!!_p._$$MediaFlash) return;
    /**
     * 音频播放控件

     * 脚本举例
     * [code]
     *   // 首先生成播放对象,只负责逻辑部分，要配合UI来使用
     *   // preload：是否预加载
     *   // url：音频地址
     *   var _mda = _p._$$MediaFlash._$allocate({
     *       preload:false,
     *       url:'http://127.0.0.1:8000/nej-baseline/res/test.mp3',
     *       onstatechange:function(_event){
     *           // 状态改变的回调
     *           // 0 | 当前停止状态
     *           // 1 | 当前缓冲状态
     *           // 2 | 当前播放状态
     *           // 3 | 当前暂停状态
     *           // 4 | 播放结束状态
     *       }
     *   });
     *   // 开始播放
     *   _mda._$play();
     *   // 暂停播放
     *   _mda._$pause();
     *   // 停止播放
     *   _mda._$stop();
     * [/code]
     * @class   {nej.ut._$$MediaFlash} 音频播放控件
     * @extends {nej.ut._$$Media}
     * @param   {Object} 可选配置参数，已处理参数列表如下所示
     * @config  {String} url 音频地址
     */
    _p._$$MediaFlash = NEJ.C();
    _pro = _p._$$MediaFlash._$extend(_p._$$Media);
    /**
     * 控件初始化
     * @return {Void}
     */
    _pro.__init = (function(){
        var _onReady = function(_flash){
            this.__audio = _flash;
            if (!!this.__action){
                this.__action.call(this);
                delete this.__action;
            }
        };
        return function(){
            this.__supInit();
            _e._$flash({
                hidden:!0,
                src:_c._$get('audio.swf'),
                onready:_onReady._$bind(this),
                onended:this.__onStop._$bind(this),
                onpause:this.__onPause._$bind(this),
                onseking:this.__onLoading._$bind(this),
                onprogress:this.__onLoading._$bind(this),
                ontimeupdate:this.__onPlaying._$bind(this),
                onvolumechange:this.__onVolumeChange._$bind(this),
                onerror:this.__onError._$bind(this)
            });
        };
    })();
    /**
     * 控件销毁
     * @return {Void}
     */
    _pro.__destroy = function(){
        this.__supDestroy();
        delete this.__action;
    };
    /**
     * 执行播放操作
     * @protected
     * @method {__doPlay}
     * @return {Void}
     */
    _pro.__doPlay = function(){
        if (!!this.__audio){
            if (!!this.__source){
                this.__audio.nej_setSrc(this.__source);
                delete this.__source;
            }
            this.__audio.nej_play();
        }else{
            this.__action = this.__doPlay;
        }
    };
    /**
     * 执行暂停操作
     * @protected
     * @method {__doPause}
     * @return {Void}
     */
    _pro.__doPause = function(){
        if (!!this.__audio){
            this.__audio.nej_pause();
        }else{
            this.__action = this.__doPause;
        }
    };
    /**
     * 执行停止操作
     * @protected
     * @method {__doStop}
     * @return {Void}
     */
    _pro.__doStop = function(){
        if (!!this.__audio){
            this.__audio.nej_stop();
            this.__doStateChange(0);
        }else{
            this.__action = this.__doStop;
        }
    };
    /**
     * 文件载入触发事件
     * @protected
     * @method {__onLoading}
     * @return {Void}
     */
    _pro.__onLoading = function(){
        this.__doStateChange(1);
    };
    /**
     * 暂停触发事件
     * @protected
     * @method {__onPause}
     * @return {Void}
     */
    _pro.__onPause = function(){
        this.__doStateChange(3);
    };
    /**
     * 播放过程触发事件
     * @protected
     * @method {__onPlaying}
     * @return {Void}
     */
    _pro.__onPlaying = function(_event){
        this.__doStateChange(2);
        this._$dispatchEvent(
            'ontimeupdate',{
                duration:_event.duration,
                current:_event.currentTime
            }
        );
    };
    /**
     * 播放错误事件
     * @param  {Event} 事件信息
     * @return {Void}
     */
    _pro.__onError = function(_event){
        this.__doError();
        this._$dispatchEvent('onerror',{
            code:_event.code
        });
    };
    /**
     * 设置播放时间
     * @protected
     * @method {__setCurrentTime}
     * @return {Void}
     */
    _pro.__setCurrentTime = function(_time){
        if (this.__state==1) return;
        this.__audio.nej_seek(_time||0);
    };
    /**
     * 获取播放时间
     * @protected
     * @method {__getCurrentTime}
     * @return {Number} 当前时间
     */
    _pro.__getCurrentTime = function(){
        return this.__audio.nej_flash_get_currentTime();
    };
    /**
     * 设置音量
     * @protected
     * @method {__setVolume}
     * @return {Void}
     */
    _pro.__setVolume = function(_volume){
        if (!this.__audio) return;
        this.__audio.nej_flash_set_volume(_volume);
    };
    /**
     * 获取音量
     * @protected
     * @method {__getVolume}
     * @return {Number} 音量值
     */
    _pro.__getVolume = function(){
        if (!this.__audio) return;
        return this.__audio.nej_flash_get_volume();
    };
};
NEJ.define(
    '{lib}util/media/flash.js',[
    '{patch}config.js',
    '{lib}base/event.js',
    '{lib}util/media/media.js',
    '{lib}util/flash/flash.js'
],f);<|endoftext|>


<commit_before>'use babel';
'use strict';

import { client } from '../rpbot';
import config from '../config';
import ModRolesDatabase from '../database/mod-roles';

export function isModerator(server, user) {
	[server, user] = resolve(server, user);
	if(user.id === config.owner) return true;
	const userRoles = server.rolesOfUser(user);
	if(userRoles.some(role => role.hasPermission('administrator'))) return true;
	if(!ModRolesDatabase.serverHasRoles(server)) return userRoles.some(role => role.hasPermission('manageMessages'));
	return ModRolesDatabase.findRolesInServer(server).some(element => userRoles.some(element2 => element.id === element2.id));
}

export function isAdministrator(server, user) {
	[server, user] = resolve(server, user);
	if(user.id === config.owner) return true;
	return server.rolesOfUser(user).some(role => role.hasPermission('administrator'));
}

function resolve(server, user) {
	if(!server || !user) throw new Error('A server and a user must be specified.');
	if(typeof server === 'string') server = client.servers.get('id', server);
	if(!server || !server.id) throw new Error('Unable to identify server.');
	if(typeof user === 'string') user = server.users.get('id', user);
	if(!user || !user.id) throw new Error('Unable to identify user.');
	return [server, user];
}
<commit_msg>Fixed an oopsie<commit_after>'use babel';
'use strict';

import { client } from '../rpbot';
import config from '../config';
import ModRolesDatabase from '../database/mod-roles';

export function isModerator(server, user) {
	[server, user] = resolve(server, user);
	if(user.id === config.owner) return true;
	const userRoles = server.rolesOfUser(user);
	if(userRoles.some(role => role.hasPermission('administrator'))) return true;
	if(!ModRolesDatabase.serverHasRoles(server)) return userRoles.some(role => role.hasPermission('manageMessages'));
	return ModRolesDatabase.findRolesInServer(server).some(element => userRoles.some(element2 => element.id === element2.id));
}

export function isAdministrator(server, user) {
	[server, user] = resolve(server, user);
	if(user.id === config.owner) return true;
	return server.rolesOfUser(user).some(role => role.hasPermission('administrator'));
}

function resolve(server, user) {
	if(!server || !user) throw new Error('A server and a user must be specified.');
	if(typeof server === 'string') server = client.servers.get('id', server);
	if(!server || !server.id) throw new Error('Unable to identify server.');
	if(typeof user === 'string') user = server.members.get('id', user);
	if(!user || !user.id) throw new Error('Unable to identify user.');
	return [server, user];
}
<|endoftext|>


<commit_before>import { nucleotide_gene } from "./globals";

export const setGenotype = (nodes, prot, positions) => {
  // console.time("setGenotype")
  const nPositions = positions.length;
  const ancState = positions.map(() => undefined);
  const ancNodes = positions.map(() => []);
  const recurse = (node, state) => {
    const newState = state; /* reference. cheap */
    let data; // any potential mutations that would result in a state change
    if (prot === nucleotide_gene && node.mutations && node.mutations.nuc && node.mutations.nuc.length) {
      data = node.mutations;
    } else if (node.mutations && node.mutations[prot]) {
      data = node.mutations[prot];
    }
    if (data && data.length) {
      for (let i = 0; i < data.length; i++) {
        const m = data[i];
        const mPos = parseInt(m.slice(1, m.length - 1), 10);
        for (let j = 0; j < nPositions; j++) {
          if (positions[j] === mPos) {
            /* check if ancState is known / set */
            if (!ancState[j]) ancState[j] = m.slice(0, 1); // only set once. Unknowable until the 1st mutation is seen.
            newState[j] = m.slice(m.length - 1, m.length);
          }
        }
      }
    }
    /* set for all nodes. will be undefined if ancestral */
    node.currentGt = [...newState];
    for (let j = 0; j < nPositions; j++) {
      if (!newState[j]) {
        ancNodes[j].push(node);
      }
    }
    if (node.hasChildren) {
      for (const child of node.children) {
        recurse(child, [...newState]);
      }
    }
  };
  recurse(nodes[0], positions.map(() => undefined), positions);
  for (let j = 0; j < nPositions; j++) {
    for (const node of ancNodes[j]) {
      node.currentGt[j] = ancState[j];
    }
  }
  nodes.forEach((n) => {n.currentGt = n.currentGt.join(' / ');});
  // console.timeEnd("setGenotype")
  // console.log(`set ${ancNodes.length} nodes to the ancestral state: ${ancState}`)
};

export const orderOfGenotypeAppearance = (nodes) => {
  const seen = {};
  nodes.forEach((n) => {
    if (!seen[n.currentGt] || n.num_date.value < seen[n.currentGt]) {
      seen[n.currentGt] = n.num_date.value;
    }
  });
  const ordered = Object.keys(seen);
  ordered.sort((a, b) => seen[a] < seen[b] ? -1 : 1);
  return ordered;
};
<commit_msg>Fix nucleotide colorby bug<commit_after>import { nucleotide_gene } from "./globals";

export const setGenotype = (nodes, prot, positions) => {
  // console.time("setGenotype")
  const nPositions = positions.length;
  const ancState = positions.map(() => undefined);
  const ancNodes = positions.map(() => []);
  const recurse = (node, state) => {
    const newState = state; /* reference. cheap */
    let data; // any potential mutations that would result in a state change
    if (node.mutations && node.mutations[prot]) {
      data = node.mutations[prot];
    }
    if (data && data.length) {
      for (let i = 0; i < data.length; i++) {
        const m = data[i];
        const mPos = parseInt(m.slice(1, m.length - 1), 10);
        for (let j = 0; j < nPositions; j++) {
          if (positions[j] === mPos) {
            /* check if ancState is known / set */
            if (!ancState[j]) ancState[j] = m.slice(0, 1); // only set once. Unknowable until the 1st mutation is seen.
            newState[j] = m.slice(m.length - 1, m.length);
          }
        }
      }
    }
    /* set for all nodes. will be undefined if ancestral */
    node.currentGt = [...newState];
    for (let j = 0; j < nPositions; j++) {
      if (!newState[j]) {
        ancNodes[j].push(node);
      }
    }
    if (node.hasChildren) {
      for (const child of node.children) {
        recurse(child, [...newState]);
      }
    }
  };
  recurse(nodes[0], positions.map(() => undefined), positions);
  for (let j = 0; j < nPositions; j++) {
    for (const node of ancNodes[j]) {
      node.currentGt[j] = ancState[j];
    }
  }
  nodes.forEach((n) => {n.currentGt = n.currentGt.join(' / ');});
  // console.timeEnd("setGenotype")
  // console.log(`set ${ancNodes.length} nodes to the ancestral state: ${ancState}`)
};

export const orderOfGenotypeAppearance = (nodes) => {
  const seen = {};
  nodes.forEach((n) => {
    if (!seen[n.currentGt] || n.num_date.value < seen[n.currentGt]) {
      seen[n.currentGt] = n.num_date.value;
    }
  });
  const ordered = Object.keys(seen);
  ordered.sort((a, b) => seen[a] < seen[b] ? -1 : 1);
  return ordered;
};
<|endoftext|>


<commit_before>(function(){
	var pim = util.isObject("Widget.PIM") ? Widget.PIM : {};

	dohx.add({name:"AddressBook",
		tests:[
			//
			// Preconditions
			//
			{
				id:1,
				name:"Helper Widget",
				instructions:[
					"This widget will show some relevant information which you might need to configure your test widget(s) properly.",
				],
				test:function(t){
					t.success(true);
				}
			},
			{
				id:2,
				name:"config info",
				test:function(t){
					if (config._meta.isCustomConfiguration){
						t.success(config._meta);
					}else{
						t.failure("Unconfigured, userAgent: " + window.navigator.userAgent);
					}
				}
			},

			//
			//
			//
			{
				id:100,
				name:"config.validAddressBookItemId",
				test:function(t){
					var addr = new pim.AddressBookItem();
					addr.setAttributeValue("fullName", "*");
					Widget.PIM.onAddressBookItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].addressBookItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findAddressBookItems(addr, 0, 1);
				},
				tearDown:function(){
					delete pim.onAddressBookItemsFound;
				}
			},
			{
				id:200,
				name:"config.validCalendarItemId",
				test:function(t){
					var item = new pim.CalendarItem();
					item.eventName = "*";
					Widget.PIM.onCalendarItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].calendarItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findCalendarItems(item, 0, 1);
				},
				tearDown:function(){
					delete pim.onAddressBookItemsFound;
				}
			},
//*/
		]
	});

})();<commit_msg>Added more details, to be more helpful.<commit_after>(function(){
	var pim = util.isObject("Widget.PIM") ? Widget.PIM : {};

	dohx.add({name:"AddressBook",
		tests:[
			//
			// Preconditions
			//
			{
				id:1,
				name:"Helper Widget",
				instructions:[
					"This widget will show some relevant information which you might need to configure your test widget(s) properly.",
				],
				test:function(t){
					t.success(true);
				}
			},
			{
				id:2,
				name:"config info",
				test:function(t){
					if (config._meta.isCustomConfiguration){
						t.success(config._meta);
					}else{
						t.failure("Unconfigured, userAgent: " + window.navigator.userAgent);
					}
				}
			},

			//
			//
			//
			{
				id:100,
				name:"config.validAddressBookItemId - possible value",
				test:function(t){
					var addr = new pim.AddressBookItem();
					addr.setAttributeValue("fullName", null);
					Widget.PIM.onAddressBookItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].addressBookItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findAddressBookItems(addr, 0, 1);
				},
				tearDown:function(){
					pim.onAddressBookItemsFound = null;
				}
			},
			{
				id:110,
				name:"config.validAddressBookItemId - current value",
				test:function(t){
					var val = config.validAddressBookItemId;
					t[val ? "success" : "failure"](val);
				}
			},
			{
				id:200,
				name:"config.validCalendarItemId - possible value",
				test:function(t){
					var item = new pim.CalendarItem();
					item.eventName = null;
					Widget.PIM.onCalendarItemsFound = function(items){
						if (items.length==0){
							t.failure("No items found :(");
						} else {
							var ids = [];
							for (var i=0; i<items.length; i++){
								ids.push(items[i].calendarItemId);
								if (i>10) break; // 10 at most
							}
							t.success("Some valid IDs: "+ ids.join(", "));
						}
					}
					pim.findCalendarItems(item, 0, 1);
				},
				tearDown:function(){
					pim.onCalendarItemsFound = null;
				}
			},
			{
				id:210,
				name:"config.validCalendarItemId - current value",
				test:function(t){
					var val = config.validCalendarItemId;
					t[val ? "success" : "failure"](val);
				}
			},
//*/
		]
	});

})();<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(["peanut"]);
    expect(array.slice(0, 2)).toEqual(["peanut", "butter"]);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(["and", "jelly"]);
    expect(array.slice(3, 0)).toEqual([]);
    expect(array.slice(3, 100)).toEqual(["jelly"]);
    expect(array.slice(5, 1)).toEqual([]);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe("three");
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1, 2, 3]);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1, 2]);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>AboutArrays done<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(["peanut"]);
    expect(array.slice(0, 2)).toEqual(["peanut", "butter"]);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(["and", "jelly"]);
    expect(array.slice(3, 0)).toEqual([]);
    expect(array.slice(3, 100)).toEqual(["jelly"]);
    expect(array.slice(5, 1)).toEqual([]);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe("three");
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1, 2, 3]);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1, 2]);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual([3, 1, 2]);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(3);
    expect(array).toEqual([1, 2]);
  });
});
<|endoftext|>


<commit_before>/* Query string parameters. These change how the program runs from the outside.
 * For example:
 *   http://www.example.com/embed.html?facilitator=127.0.0.1:9002&debug=1
 *
 * facilitator=<HOST>:<PORT>
 * The address of the facilitator to use. By default it is
 * DEFAULT_FACILITATOR_ADDR. Both <HOST> and <PORT> must be present.
 */

var DEFAULT_FACILITATOR_ADDR = {
    host: "tor-facilitator.bamsoftware.com",
    port: 9002
};

/* Parse a URL query string or application/x-www-form-urlencoded body. The
   return type is an object mapping string keys to string values. By design,
   this function doesn't support multiple values for the same named parameter,
   for example "a=1&a=2&a=3"; the first definition always wins. Returns null on
   error.

   Always decodes from UTF-8, not any other encoding.

   http://dev.w3.org/html5/spec/Overview.html#url-encoded-form-data */
function parse_query_string(qs)
{
    var strings;
    var result;

    result = {};
    if (qs)
        strings = qs.split("&");
    else
        strings = {}
    for (var i = 0; i < strings.length; i++) {
        var string = strings[i];
        var j, name, value;

        j = string.indexOf("=");
        if (j == -1) {
            name = string;
            value = "";
        } else {
            name = string.substr(0, j);
            value = string.substr(j + 1);
        }
        name = decodeURIComponent(name.replace(/\+/, " "));
        value = decodeURIComponent(value.replace(/\+/, " "));
        if (!(name in result))
             result[name] = value;
    }

    return result;
}

/* Get a query string parameter and parse it as an address spec. Returns
   default_val if param is not defined in the query string. Returns null on a
   parsing error. */
function get_query_param_addr(query, param, default_val)
{
    var val;

    val = query[param];
    if (val === undefined)
        return default_val;
    else
        return parse_addr_spec(val);
}

/* Parse an address in the form "host:port". Returns an Object with
   keys "host" (String) and "port" (int). Returns null on error. */
function parse_addr_spec(spec)
{
    var groups;
    var host, port;

    groups = spec.match(/^([^:]+):(\d+)$/);
    if (!groups)
        return null;
    host = groups[1];
    port = parseInt(groups[2], 10);
    if (isNaN(port) || port < 0 || port > 65535)
        return null;

    return { host: host, port: port }
}

function format_addr(addr)
{
    return addr.host + ":" + addr.port;
}

function FlashProxy()
{
    this.debug_div = document.createElement("div");
    this.debug_div.className = "debug";

    this.badge_elem = this.debug_div;
    this.badge_elem.setAttribute("id", "flashproxy-badge");

    this.puts = function(s) {
        if (this.debug_div) {
            this.debug_div.appendChild(document.createTextNode(s));
            this.debug_div.appendChild(document.createElement("br"));
        }
    };

    this.start = function() {
        var query;
        var fac_addr;

        query = parse_query_string(window.location.search.substr(1));

        fac_addr = get_query_param_addr(query, "facilitator", DEFAULT_FACILITATOR_ADDR);
        if (!fac_addr) {
            this.puts("Error: Facilitator spec must be in the form \"host:port\".");
            return;
        }

        this.proxy_main(fac_addr);
    };

    this.proxy_main = function(fac_addr) {
        var fac_url;
        var xhr;

        this.puts("Using facilitator " + format_addr(fac_addr) + ".");

        fac_url = "http://" + encodeURIComponent(fac_addr.host)
            + ":" + encodeURIComponent(fac_addr.port) + "/";
        xhr = new XMLHttpRequest();
        xhr.open("GET", fac_url);
        xhr.responseType = "text";
        xhr.onreadystatechange = function() {
            /* Status 0 is UNSENT. 4 is DONE. */
            if (xhr.status == 0 && xhr.statusText == null) {
                this.puts("Facilitator: cross-domain error.");
            } else if (xhr.readyState == 4) {
                if (xhr.status == 200)
                    this.fac_complete(xhr.responseText);
                else if (xhr.readyState == 4)
                    this.puts("Facilitator: got status " + xhr.status + ".");
                else
                    this.puts("Facilitator: unknown error.");
            }
        }.bind(this);
        this.puts("Facilitator: connecting to " + fac_url + ".");
        xhr.send(null);
    };

    this.fac_complete = function(text) {
        this.puts("Facilitator: got response \"" + text + "\".");
    };
}

/* This is the non-functional badge that occupies space when
   flashproxy_should_disable decides that the proxy shouldn't run. */
function DummyFlashProxy()
{
    var img;

    img = document.createElement("img");
    img.setAttribute("src", "https://crypto.stanford.edu/flashproxy/badge.png");
    img.setAttribute("border", 0);
    img.setAttribute("id", "flashproxy-badge");

    this.badge_elem = img;

    this.start = function() {
    };
}

function quote(s)
{
    return "\"" + s.replace(/([\\\"])/, "\\$1") + "\"";
}

function maybe_quote(s)
{
    if (!/^[a-zA-Z_]\w*$/.test(s))
        return quote(s);
    else
        return s;
}

function repr(x)
{
    if (x === null) {
        return "null";
    } else if (typeof x == "undefined") {
        return "undefined";
    } else if (typeof x == "object") {
        var elems = [];
        for (var k in x)
            elems.push(maybe_quote(k) + ": " + repr(x[k]));
        return "{ " + elems.join(", ") + " }";
    } else if (typeof x == "string") {
        return quote(x);
    } else {
        return x.toString();
    }
}

/* Are circumstances such that we should self-disable and not be a
   proxy? We take a best-effort guess as to whether this device runs on
   a battery or the data transfer might be expensive.

   Matching mobile User-Agents is complex; but we only need to match
   those devices that can also run a recent version of Adobe Flash,
   which is a subset of this list:
   https://secure.wikimedia.org/wikipedia/en/wiki/Adobe_Flash_Player#Mobile_operating_systems

   Other resources:
   http://www.zytrax.com/tech/web/mobile_ids.html
   http://googlewebmastercentral.blogspot.com/2011/03/mo-better-to-also-detect-mobile-user.html
   http://search.cpan.org/~cmanley/Mobile-UserAgent-1.05/lib/Mobile/UserAgent.pm
*/
function flashproxy_should_disable()
{
    var ua;

    ua = window.navigator.userAgent;
    if (ua != null) {
        var UA_LIST = [
            /\bmobile\b/i,
            /\bandroid\b/i,
            /\bopera mobi\b/i,
        ];

        for (var i = 0; i < UA_LIST.length; i++) {
            var re = UA_LIST[i];

            if (ua.match(re)) {
                return true;
            }
        }
    }

    return false;
}

function flashproxy_badge_insert()
{
    var e;

    if (flashproxy_should_disable()) {
        fp = new DummyFlashProxy();
    } else {
        fp = new FlashProxy();
    }

    /* http://intertwingly.net/blog/2006/11/10/Thats-Not-Write for this trick to
       insert right after the <script> element in the DOM. */
    e = document;
    while (e.lastChild && e.lastChild.nodeType == 1) {
        e = e.lastChild;
    }
    e.parentNode.appendChild(fp.badge_elem);

    return fp;
}
<commit_msg>Better connection failure diagnostics.<commit_after>/* Query string parameters. These change how the program runs from the outside.
 * For example:
 *   http://www.example.com/embed.html?facilitator=127.0.0.1:9002&debug=1
 *
 * facilitator=<HOST>:<PORT>
 * The address of the facilitator to use. By default it is
 * DEFAULT_FACILITATOR_ADDR. Both <HOST> and <PORT> must be present.
 */

var DEFAULT_FACILITATOR_ADDR = {
    host: "tor-facilitator.bamsoftware.com",
    port: 9002
};

/* Parse a URL query string or application/x-www-form-urlencoded body. The
   return type is an object mapping string keys to string values. By design,
   this function doesn't support multiple values for the same named parameter,
   for example "a=1&a=2&a=3"; the first definition always wins. Returns null on
   error.

   Always decodes from UTF-8, not any other encoding.

   http://dev.w3.org/html5/spec/Overview.html#url-encoded-form-data */
function parse_query_string(qs)
{
    var strings;
    var result;

    result = {};
    if (qs)
        strings = qs.split("&");
    else
        strings = {}
    for (var i = 0; i < strings.length; i++) {
        var string = strings[i];
        var j, name, value;

        j = string.indexOf("=");
        if (j == -1) {
            name = string;
            value = "";
        } else {
            name = string.substr(0, j);
            value = string.substr(j + 1);
        }
        name = decodeURIComponent(name.replace(/\+/, " "));
        value = decodeURIComponent(value.replace(/\+/, " "));
        if (!(name in result))
             result[name] = value;
    }

    return result;
}

/* Get a query string parameter and parse it as an address spec. Returns
   default_val if param is not defined in the query string. Returns null on a
   parsing error. */
function get_query_param_addr(query, param, default_val)
{
    var val;

    val = query[param];
    if (val === undefined)
        return default_val;
    else
        return parse_addr_spec(val);
}

/* Parse an address in the form "host:port". Returns an Object with
   keys "host" (String) and "port" (int). Returns null on error. */
function parse_addr_spec(spec)
{
    var groups;
    var host, port;

    groups = spec.match(/^([^:]+):(\d+)$/);
    if (!groups)
        return null;
    host = groups[1];
    port = parseInt(groups[2], 10);
    if (isNaN(port) || port < 0 || port > 65535)
        return null;

    return { host: host, port: port }
}

function format_addr(addr)
{
    return addr.host + ":" + addr.port;
}

function FlashProxy()
{
    this.debug_div = document.createElement("div");
    this.debug_div.className = "debug";

    this.badge_elem = this.debug_div;
    this.badge_elem.setAttribute("id", "flashproxy-badge");

    this.puts = function(s) {
        if (this.debug_div) {
            this.debug_div.appendChild(document.createTextNode(s));
            this.debug_div.appendChild(document.createElement("br"));
        }
    };

    this.start = function() {
        var query;
        var fac_addr;

        query = parse_query_string(window.location.search.substr(1));

        fac_addr = get_query_param_addr(query, "facilitator", DEFAULT_FACILITATOR_ADDR);
        if (!fac_addr) {
            this.puts("Error: Facilitator spec must be in the form \"host:port\".");
            return;
        }

        this.proxy_main(fac_addr);
    };

    this.proxy_main = function(fac_addr) {
        var fac_url;
        var xhr;

        this.puts("Using facilitator " + format_addr(fac_addr) + ".");

        fac_url = "http://" + encodeURIComponent(fac_addr.host)
            + ":" + encodeURIComponent(fac_addr.port) + "/";
        xhr = new XMLHttpRequest();
        try {
            xhr.open("GET", fac_url);
        } catch (err) {
            /* An exception happens here when, for example, NoScript allows the
               domain on which the proxy badge runs, but not the domain to which
               it's trying to make the HTTP request. The exception message is
               like "Component returned failure code: 0x805e0006
               [nsIXMLHttpRequest.open]" on Firefox. */
            this.puts("Facilitator: exception while connecting: " + repr(err.message) + ".");
            return;
        }
        xhr.responseType = "text";
        xhr.onreadystatechange = function() {
            /* Status 0 is UNSENT. 4 is DONE. */
            if (xhr.status == 0 && xhr.statusText == null) {
                this.puts("Facilitator: cross-domain error.");
            } else if (xhr.readyState == 4) {
                if (xhr.status == 200)
                    this.fac_complete(xhr.responseText);
                else
                    this.puts("Facilitator: can't connect: got response code " + xhr.status + ".");
            }
        }.bind(this);
        this.puts("Facilitator: connecting to " + fac_url + ".");
        xhr.send(null);
    };

    this.fac_complete = function(text) {
        this.puts("Facilitator: got response \"" + text + "\".");
    };
}

/* This is the non-functional badge that occupies space when
   flashproxy_should_disable decides that the proxy shouldn't run. */
function DummyFlashProxy()
{
    var img;

    img = document.createElement("img");
    img.setAttribute("src", "https://crypto.stanford.edu/flashproxy/badge.png");
    img.setAttribute("border", 0);
    img.setAttribute("id", "flashproxy-badge");

    this.badge_elem = img;

    this.start = function() {
    };
}

function quote(s)
{
    return "\"" + s.replace(/([\\\"])/, "\\$1") + "\"";
}

function maybe_quote(s)
{
    if (!/^[a-zA-Z_]\w*$/.test(s))
        return quote(s);
    else
        return s;
}

function repr(x)
{
    if (x === null) {
        return "null";
    } else if (typeof x == "undefined") {
        return "undefined";
    } else if (typeof x == "object") {
        var elems = [];
        for (var k in x)
            elems.push(maybe_quote(k) + ": " + repr(x[k]));
        return "{ " + elems.join(", ") + " }";
    } else if (typeof x == "string") {
        return quote(x);
    } else {
        return x.toString();
    }
}

/* Are circumstances such that we should self-disable and not be a
   proxy? We take a best-effort guess as to whether this device runs on
   a battery or the data transfer might be expensive.

   Matching mobile User-Agents is complex; but we only need to match
   those devices that can also run a recent version of Adobe Flash,
   which is a subset of this list:
   https://secure.wikimedia.org/wikipedia/en/wiki/Adobe_Flash_Player#Mobile_operating_systems

   Other resources:
   http://www.zytrax.com/tech/web/mobile_ids.html
   http://googlewebmastercentral.blogspot.com/2011/03/mo-better-to-also-detect-mobile-user.html
   http://search.cpan.org/~cmanley/Mobile-UserAgent-1.05/lib/Mobile/UserAgent.pm
*/
function flashproxy_should_disable()
{
    var ua;

    ua = window.navigator.userAgent;
    if (ua != null) {
        var UA_LIST = [
            /\bmobile\b/i,
            /\bandroid\b/i,
            /\bopera mobi\b/i,
        ];

        for (var i = 0; i < UA_LIST.length; i++) {
            var re = UA_LIST[i];

            if (ua.match(re)) {
                return true;
            }
        }
    }

    return false;
}

function flashproxy_badge_insert()
{
    var e;

    if (flashproxy_should_disable()) {
        fp = new DummyFlashProxy();
    } else {
        fp = new FlashProxy();
    }

    /* http://intertwingly.net/blog/2006/11/10/Thats-Not-Write for this trick to
       insert right after the <script> element in the DOM. */
    e = document;
    while (e.lastChild && e.lastChild.nodeType == 1) {
        e = e.lastChild;
    }
    e.parentNode.appendChild(fp.badge_elem);

    return fp;
}
<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http://javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);
    //TODO: WHY IS THIS LIKE THIS?
    // console.log(tenEmptyElementArray.length);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(['peanut']);
    expect(array.slice(0, 2)).toEqual(['peanut', 'butter']);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(['and', 'jelly']);
    expect(array.slice(3, 0)).toEqual([]);
    //TODO:IS THIS AN EMPTY ARRAY BECAUSE IT STARTS AT THE LAST
    // ITEM IN THE ARRAY AND ENDS AT THE FIRST ITEM IN THE ARRAY?
    expect(array.slice(3, 100)).toEqual(['jelly']); //TODO: IS THIS ['JELLY'] BECAUSE IT STARTS AT 3 AND ENDS AT AN INDEX THAT DOES NOT OCCUR IN THIS ARRAY?
    expect(array.slice(5, 1)).toEqual([]); //TODO: SEE TODO ON LINE 56
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
        refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});<commit_msg>arrays section complete<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http://javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);
    //TODO: WHY IS THIS LIKE THIS?
    // console.log(tenEmptyElementArray.length);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(['peanut']);
    expect(array.slice(0, 2)).toEqual(['peanut', 'butter']);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(['and', 'jelly']);
    expect(array.slice(3, 0)).toEqual([]);
    //TODO:IS THIS AN EMPTY ARRAY BECAUSE IT STARTS AT THE LAST
    // ITEM IN THE ARRAY AND ENDS AT THE FIRST ITEM IN THE ARRAY?
    expect(array.slice(3, 100)).toEqual(['jelly']); //TODO: IS THIS ['JELLY'] BECAUSE IT STARTS AT 3 AND ENDS AT AN INDEX THAT DOES NOT OCCUR IN THIS ARRAY?
    expect(array.slice(5, 1)).toEqual([]); //TODO: SEE TODO ON LINE 56
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
        refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe("three");
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1, 2, 3]);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1, 2]);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual([3, 1, 2]);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(3);
    expect(array).toEqual([1, 2]);
  });
});<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe(FILL_ME_IN); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(FILL_ME_IN);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(FILL_ME_IN);
    expect(multiTypeArray[2]).toBe(FILL_ME_IN);
    expect(multiTypeArray[3]()).toBe(FILL_ME_IN);
    expect(multiTypeArray[4].value1).toBe(FILL_ME_IN);
    expect(multiTypeArray[4]["value2"]).toBe(FILL_ME_IN);
    expect(multiTypeArray[5][0]).toBe(FILL_ME_IN);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, FILL_ME_IN]);

    array.push(3);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>Passed all tests in AboutArrays<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1,2,3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(["peanut"]);
    expect(array.slice(0, 2)).toEqual(["peanut", "butter"]);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(["and","jelly"]);
    expect(array.slice(3, 0)).toEqual([]);
    expect(array.slice(3, 100)).toEqual(["jelly"]);
    expect(array.slice(5, 1)).toEqual([]);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe("three");
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1,2,3]);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1,2]);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual([3,1,2]);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(3);
    expect(array).toEqual([1,2]);
  });
});
<|endoftext|>


<commit_before><commit_msg>add tests for unescapeHTML utils function<commit_after><|endoftext|>


<commit_before>var os = require('os');
var ffi = require('ffi');
var ref = require('ref');

var osType = os.type();

var FLUID_FAILED = -1;

var char_ptr  = ffi.types.CString;
var void_ptr  = ref.refType(ffi.types.void);
var fluid_settings_t  = ref.refType(ffi.types.void);
var fluid_synth_t = ref.refType(ffi.types.void);
var fluid_audio_driver_t = ref.refType(ffi.types.void);
var fluid_settings_foreach_option_t = ref.refType(ffi.types.void);

//console.log(ffi.types);
console.log(ffi);
function Fluid4NodeError(message) {
    this.name = 'Fluid4NodeError';
    this.message = message;
    this.stack = (new Error()).stack;
}

var libSpec = {
    'new_fluid_settings': [ fluid_settings_t, [] ],
    'delete_fluid_settings': ['void', [fluid_settings_t]],
    'fluid_settings_setstr': ['int', [fluid_settings_t, char_ptr, char_ptr]],
    'new_fluid_synth': [fluid_synth_t, [fluid_settings_t]],
    'delete_fluid_synth': ['int', [fluid_synth_t]],
    'new_fluid_audio_driver': [fluid_audio_driver_t, [fluid_settings_t, fluid_synth_t]],
    'fluid_synth_sfload': ['int', [fluid_synth_t, char_ptr, 'int']],
    'fluid_synth_sfunload': ['int', [fluid_synth_t, 'int', 'int']],
    'fluid_synth_noteon': ['int', [fluid_synth_t, 'int', 'int', 'int']],
    'fluid_synth_noteoff': ['int', [fluid_synth_t, 'int', 'int']],
    'fluid_synth_program_change': ['int', [fluid_synth_t, 'int', 'int']],
    'fluid_synth_set_gain': [ 'void', [ fluid_synth_t, 'float'] ],
    'fluid_settings_foreach_option': ['void', [fluid_settings_t, char_ptr, void_ptr, fluid_settings_foreach_option_t]]
//    'fluid_settings_foreach_option': ['void', [fluid_settings_t, char_ptr, void_ptr, 'pointer']]
};

function initLib(libs) {
    var res = false;
    var i = 0;
    while (i < libs.length && !res) {
	try {
	    res = ffi.Library(libs[i++], libSpec);
	} catch (e) {
	    res = false;
	}
    }
    if (!res) {
	throw new Fluid4NodeError('Could not wrap any native library from list:' + libs.join(', '))
    };
    return res;
}

function initSynth(lib, settings, drivers) {

    var synth = lib.new_fluid_synth(settings);

    var driverMask = {};
    lib.fluid_settings_foreach_option(settings, "audio.driver", null,
				      ffi.Callback('void', [void_ptr, char_ptr, char_ptr],
						   function (data, name, option) {
						       driverMask[option] = true;
						   })
				     );

    var res;
    var i = 0;
    var drv;
    while (i < drivers.length) {
	drv = drivers[i++];
	if (!driverMask[drv]) {
	    console.log('Unknown driver: ' + drv);
	    continue;
	}
	try {
	    lib.fluid_settings_setstr(settings, "audio.driver", drv);
	    res = lib.new_fluid_audio_driver(settings, synth);
	    if (res.address()) {
		return synth;
	    }
	} catch (e) {
	}
    }
    throw new Fluid4NodeError('Could create sytnth with ant driver from:' + drivers.join(', '))
}

function initSoundFonts(lib, synth, soundFonts) {

    var res = {};
    soundFonts.forEach(function (sfPath) {
	var sf2Id = lib.fluid_synth_sfload(synth, sfPath, 0);

	if (res.hasOwnProperty(sfPath)) {
	    throw new Fluid4NodeError('Soundfont already loaded: ' + sfPath);
	}
	if (sf2Id === FLUID_FAILED) {
	    throw new Fluid4NodeError('Could load soundfont: ' + sfPath);
	}
	res[sfPath] = sf2Id;
    });
    return res;
}

var spec0 = {
    'drivers': ['dsound', 'winmidi', 'jack','alsa', 'pulseaudio', 'alsa_raw', 'alsa_seq'],
    'libs': [
	'libs/win/libfluidsynth.dll',
	'libs/linux/libfluidsynth.so.1'
    ],
    'soundFonts': ['./sf2/FluidR3_GM.sf2']
};

var  specByOSType= {
    'Linux': {
	'drivers': ['jack','alsa', 'pulseaudio', 'alsa_raw', 'alsa_seq'],
	'libs': [
	    'libs/linux/libfluidsynth.so.1'
	]
    },
    'Windows_NT': {
	'drivers': ['dsound', 'winmidi'],
    'libs': [
	'libs/win/libfluidsynth.dll'
    ],
    }

};

module.exports = function(spec) {

    var api = {
	FLUID_FAILED: FLUID_FAILED,
	getLib: function() {
	    return lib;
	}
    };

    if (spec) {
	spec.drivers = spec.drivers || specByOSType[osType].drivers || spec0.drivers;
	spec.libs = spec.libs || specByOSType[osType].libs || spec0.libs;
	spec.soundFonts = spec.soundFonts || specByOSType[osType].soundFonts || spec0.soundFonts;
	var lib = initLib(spec.libs);
	var settings = lib.new_fluid_settings();
	var synth = initSynth(lib, settings, spec.drivers);
	if (spec.soundFonts.length > 0) {
	    var soundFonts = initSoundFonts(lib, synth, spec.soundFonts);
	}
	api.setGain = function (gain) {
	    return lib.fluid_synth_set_gain(synth, gain);
	};
	api.programChange = function (chan, program) {
	    return lib.fluid_synth_program_change(synth, chan, program);
	};
	api.noteOn = function (chan, key, vel) {
	    lib.fluid_synth_noteon(synth, chan, key, vel);
	};
	api.noteOff = function (chan, key) {
	    lib.fluid_synth_noteoff(synth, chan, key);
	};
	api.destroy = function () {
	    for (var key in soundFonts) {
		lib.fluid_synth_sfunload(synth, soundFonts[key], 0);
	    }
	    lib.delete_fluid_settings(settings);
	    lib.delete_fluid_synth(synth);
	};
    }

    return api;
};
<commit_msg>Fixed paths and removed console.log.<commit_after>var os = require('os');
var path = require('path');
var ffi = require('ffi');
var ref = require('ref');

var osType = os.type();

var FLUID_FAILED = -1;

var char_ptr  = ffi.types.CString;
var void_ptr  = ref.refType(ffi.types.void);
var fluid_settings_t  = ref.refType(ffi.types.void);
var fluid_synth_t = ref.refType(ffi.types.void);
var fluid_audio_driver_t = ref.refType(ffi.types.void);
var fluid_settings_foreach_option_t = ref.refType(ffi.types.void);

function Fluid4NodeError(message) {
    this.name = 'Fluid4NodeError';
    this.message = message;
    this.stack = (new Error()).stack;
}

function relPath(locPath) {
    var res = path.normalize(__dirname + '/' + locPath);
    return res;
}

    var libSpec = {
    'new_fluid_settings': [ fluid_settings_t, [] ],
    'delete_fluid_settings': ['void', [fluid_settings_t]],
    'fluid_settings_setstr': ['int', [fluid_settings_t, char_ptr, char_ptr]],
    'new_fluid_synth': [fluid_synth_t, [fluid_settings_t]],
    'delete_fluid_synth': ['int', [fluid_synth_t]],
    'new_fluid_audio_driver': [fluid_audio_driver_t, [fluid_settings_t, fluid_synth_t]],
    'fluid_synth_sfload': ['int', [fluid_synth_t, char_ptr, 'int']],
    'fluid_synth_sfunload': ['int', [fluid_synth_t, 'int', 'int']],
    'fluid_synth_noteon': ['int', [fluid_synth_t, 'int', 'int', 'int']],
    'fluid_synth_noteoff': ['int', [fluid_synth_t, 'int', 'int']],
    'fluid_synth_program_change': ['int', [fluid_synth_t, 'int', 'int']],
    'fluid_synth_set_gain': [ 'void', [ fluid_synth_t, 'float'] ],
    'fluid_settings_foreach_option': ['void', [fluid_settings_t, char_ptr, void_ptr, fluid_settings_foreach_option_t]]
//    'fluid_settings_foreach_option': ['void', [fluid_settings_t, char_ptr, void_ptr, 'pointer']]
};

function initLib(libs) {
    var res = false;
    var i = 0;
    while (i < libs.length && !res) {
	try {
	    res = ffi.Library(relPath(libs[i++]), libSpec);
	} catch (e) {
	    res = false;
	}
    }
    if (!res) {
	throw new Fluid4NodeError('Could not wrap any native library from list:' + libs.join(', '))
    };
    return res;
}

function initSynth(lib, settings, drivers) {

    var synth = lib.new_fluid_synth(settings);

    var driverMask = {};
    lib.fluid_settings_foreach_option(settings, "audio.driver", null,
				      ffi.Callback('void', [void_ptr, char_ptr, char_ptr],
						   function (data, name, option) {
						       driverMask[option] = true;
						   })
				     );

    var res;
    var i = 0;
    var drv;
    while (i < drivers.length) {
	drv = drivers[i++];
	if (!driverMask[drv]) {
	    console.log('Unknown driver: ' + drv);
	    continue;
	}
	try {
	    lib.fluid_settings_setstr(settings, "audio.driver", drv);
	    res = lib.new_fluid_audio_driver(settings, synth);
	    if (res.address()) {
		return synth;
	    }
	} catch (e) {
	}
    }
    throw new Fluid4NodeError('Could create sytnth with ant driver from:' + drivers.join(', '))
}

function initSoundFonts(lib, synth, soundFonts) {

    var res = {};
    soundFonts.forEach(function (sfPath) {
	var sf2Id = lib.fluid_synth_sfload(synth, relPath(sfPath), 0);

	if (res.hasOwnProperty(sfPath)) {
	    throw new Fluid4NodeError('Soundfont already loaded: ' + sfPath);
	}
	if (sf2Id === FLUID_FAILED) {
	    throw new Fluid4NodeError('Could load soundfont: ' + sfPath);
	}
	res[sfPath] = sf2Id;
    });
    return res;
}

var spec0 = {
    'drivers': ['dsound', 'winmidi', 'jack','alsa', 'pulseaudio', 'alsa_raw', 'alsa_seq'],
    'libs': [
	'libs/win/libfluidsynth.dll',
	'libs/linux/libfluidsynth.so.1'
    ],
    'soundFonts': ['./sf2/FluidR3_GM.sf2']
};

var  specByOSType= {
    'Linux': {
	'drivers': ['jack','alsa', 'pulseaudio', 'alsa_raw', 'alsa_seq'],
	'libs': [
	    'libs/linux/libfluidsynth.so.1'
	]
    },
    'Windows_NT': {
	'drivers': ['dsound', 'winmidi'],
    'libs': [
	'libs/win/libfluidsynth.dll'
    ],
    }

};

module.exports = function(spec) {

    var api = {
	FLUID_FAILED: FLUID_FAILED,
	getLib: function() {
	    return lib;
	}
    };

    if (spec) {
	spec.drivers = spec.drivers || specByOSType[osType].drivers || spec0.drivers;
	spec.libs = spec.libs || specByOSType[osType].libs || spec0.libs;
	spec.soundFonts = spec.soundFonts || specByOSType[osType].soundFonts || spec0.soundFonts;
	var lib = initLib(spec.libs);
	var settings = lib.new_fluid_settings();
	var synth = initSynth(lib, settings, spec.drivers);
	if (spec.soundFonts.length > 0) {
	    var soundFonts = initSoundFonts(lib, synth, spec.soundFonts);
	}
	api.setGain = function (gain) {
	    return lib.fluid_synth_set_gain(synth, gain);
	};
	api.programChange = function (chan, program) {
	    return lib.fluid_synth_program_change(synth, chan, program);
	};
	api.noteOn = function (chan, key, vel) {
	    lib.fluid_synth_noteon(synth, chan, key, vel);
	};
	api.noteOff = function (chan, key) {
	    lib.fluid_synth_noteoff(synth, chan, key);
	};
	api.destroy = function () {
	    for (var key in soundFonts) {
		lib.fluid_synth_sfunload(synth, soundFonts[key], 0);
	    }
	    lib.delete_fluid_settings(settings);
	    lib.delete_fluid_synth(synth);
	};
    }

    return api;
};
<|endoftext|>


<commit_before>EditorUI.DragDrop = (function () {
    var Path = null;
    if ( Editor.isNative ) {
        Path = require('fire-path');
    }

    var _allowed = false;

    var DragDrop = {
        start: function ( dataTransfer, effect, type, items ) {
            var ids = items.map( function (item) {
                return item.id;
            } );
            dataTransfer.effectAllowed = effect;
            dataTransfer.dropEffect = 'none';
            // FIXME: https://github.com/atom/electron/issues/1276
            dataTransfer.setData('text', type);
            dataTransfer.setData('editor/type', type);
            dataTransfer.setData('editor/items', ids.join());
            var img = this.getDragIcon(items);
            dataTransfer.setDragImage(img, -10, 10);

            Editor.sendToWindows('editor:dragstart');
        },

        drop: function ( dataTransfer ) {
            var results = [];
            if ( _allowed ) {
                results = DragDrop.items(dataTransfer);
            }

            _allowed = false;

            return results;
        },

        end: function () {
            _allowed = false;
            Editor.sendToWindows('editor:dragend');
        },

        updateDropEffect: function ( dataTransfer, dropEffect ) {
            if ( _allowed ) {
                dataTransfer.dropEffect = dropEffect;
            }
            else {
                dataTransfer.dropEffect = 'none';
            }
        },

        allowDrop: function ( dataTransfer, allowed ) {
            _allowed = allowed;
            if ( !_allowed ) {
                dataTransfer.dropEffect = 'none';
            }
        },

        type: function ( dataTransfer ) {
            var type = dataTransfer.getData('editor/type');

            if ( type === '' && dataTransfer.files.length > 0 )
                return 'file';

            return type;
        },

        items: function ( dataTransfer ) {
            var type = DragDrop.type(dataTransfer);
            var items;

            if ( type === 'file' ) {
                var files = dataTransfer.files;
                items = [];

                for ( var i = 0; i < files.length; ++i ) {
                    var exists = false;

                    // filter out sub file paths if we have Path module
                    if ( Path ) {
                        for ( var j = 0; j < items.length; ++j ) {
                            if ( Path.contains( items[j], files[i].path ) ) {
                                exists = true;
                                break;
                            }
                        }
                    }

                    if ( !exists ) {
                        items.push( files[i].path );
                    }
                }
            }
            else {
                items = dataTransfer.getData('editor/items');
                if ( items !== '' ) {
                    items = items.split(',');
                }
                else {
                    items = [];
                }
            }

            return items;
        },

        // NOTE: The image will be blur in retina, still not find a solution.
        getDragIcon: function (items) {
            var icon = new Image();
            var canvas = document.createElement('canvas');
            var imgPanel = canvas.getContext('2d');
            imgPanel.font = 'normal 12px Arial';
            imgPanel.fillStyle = 'white';
            var top = 0;
            for ( var i = 0; i < items.length; ++i ) {
                var item = items[i];
                if ( i <= 4 ) {
                    // icon
                    // NOTE: the icon may be broken, use naturalWidth detect this
                    if ( item.icon &&
                         item.icon.naturalWidth !== undefined &&
                         item.icon.naturalWidth !== 0
                       )
                    {
                        imgPanel.drawImage(item.icon,0,top,16,16);
                    }
                    // text
                    imgPanel.fillText(item.name,20,top + 15);
                    top += 15;
                }
                else {
                    imgPanel.fillStyle = 'gray';
                    imgPanel.fillText('[more.....]',20,top + 15);
                    break;
                }

            }

            icon.src = canvas.toDataURL();
            return icon;
        },
    };

    Object.defineProperty( DragDrop, 'allowed', {
        get: function () { return _allowed; }
    });

    return DragDrop;
})();
<commit_msg>minor tweak<commit_after>EditorUI.DragDrop = (function () {
    var Path = null;
    if ( Editor.isNative ) {
        Path = require('fire-path');
    }

    var _allowed = false;

    var DragDrop = {
        start: function ( dataTransfer, effect, type, items ) {
            var ids = items.map( function (item) {
                return item.id;
            } );
            dataTransfer.effectAllowed = effect;
            dataTransfer.dropEffect = 'none';
            // FIXME: https://github.com/atom/electron/issues/1276
            dataTransfer.setData('text', type);
            dataTransfer.setData('editor/type', type);
            dataTransfer.setData('editor/items', ids.join());
            var img = this.getDragIcon(items);
            dataTransfer.setDragImage(img, -10, 10);

            Editor.sendToWindows('editor:dragstart');
        },

        drop: function ( dataTransfer ) {
            var results = [];
            if ( _allowed ) {
                results = DragDrop.items(dataTransfer);
            }

            _allowed = false;

            return results;
        },

        end: function () {
            _allowed = false;
            Editor.sendToWindows('editor:dragend');
        },

        updateDropEffect: function ( dataTransfer, dropEffect ) {
            if ( _allowed ) {
                dataTransfer.dropEffect = dropEffect;
            }
            else {
                dataTransfer.dropEffect = 'none';
            }
        },

        allowDrop: function ( dataTransfer, allowed ) {
            _allowed = allowed;
            if ( !_allowed ) {
                dataTransfer.dropEffect = 'none';
            }
        },

        type: function ( dataTransfer ) {
            var type = dataTransfer.getData('editor/type');

            if ( type === '' && dataTransfer.files.length > 0 )
                return 'file';

            return type;
        },

        items: function ( dataTransfer ) {
            var type = DragDrop.type(dataTransfer);
            var items;

            if ( type === 'file' ) {
                var files = dataTransfer.files;
                items = [];

                for ( var i = 0; i < files.length; ++i ) {
                    var exists = false;

                    // filter out sub file paths if we have Path module
                    if ( Path ) {
                        for ( var j = 0; j < items.length; ++j ) {
                            if ( Path.contains( items[j], files[i].path ) ) {
                                exists = true;
                                break;
                            }
                        }
                    }

                    if ( !exists ) {
                        items.push( files[i].path );
                    }
                }
            }
            else {
                items = dataTransfer.getData('editor/items');
                if ( items !== '' ) {
                    items = items.split(',');
                }
                else {
                    items = [];
                }
            }

            return items;
        },

        // NOTE: The image will be blur in retina, still not find a solution.
        getDragIcon: function (items) {
            var icon = new Image();
            var canvas = document.createElement('canvas');
            var imgPanel = canvas.getContext('2d');
            imgPanel.font = 'normal 12px Arial';
            imgPanel.fillStyle = 'white';
            var top = 0;
            for ( var i = 0; i < items.length; ++i ) {
                var item = items[i];
                if ( i <= 4 ) {
                    // icon
                    // NOTE: the icon may be broken, use naturalWidth detect this
                    if ( item.icon &&
                         item.icon.naturalWidth !== undefined &&
                         item.icon.naturalWidth !== 0
                       )
                    {
                        imgPanel.drawImage(item.icon,0,top,16,16);
                    }
                    // text
                    imgPanel.fillText(item.name,20,top + 15);
                    top += 15;
                }
                else {
                    imgPanel.fillStyle = 'gray';
                    imgPanel.fillText('[more...]',20,top + 15);
                    break;
                }

            }

            icon.src = canvas.toDataURL();
            return icon;
        },
    };

    Object.defineProperty( DragDrop, 'allowed', {
        get: function () { return _allowed; }
    });

    return DragDrop;
})();
<|endoftext|>


<commit_before>var _ = require('lodash');
var Joi = require('joi');

var common = {
  team: Joi.number().integer().min(0),
  userUuid: Joi.string().regex(/^[A-Za-z0-9_-]+$/).min(1, 'utf8').max(128, 'utf8'),
  primaryKeyId: Joi.number().integer().min(0)
};

const schemas = {
  common: common,

  action: {
    user: common.userUuid.required(),
    type: Joi.string().uppercase().required(),
    imageData: Joi.string().when('type', { is: 'IMAGE', then: Joi.required() }),
    text: Joi.string().when('type', { is: 'TEXT', then: Joi.required() }),
    location: Joi.object({
      latitude: Joi.number(),
      longitude: Joi.number()
    }).required()
  },

  user: {
    uuid: common.userUuid.required(),
    name: Joi.string().min(1, 'utf8').max(30, 'utf8').required(),
    team: common.team.required()
  },

  feedParams: {
    beforeId: Joi.number().integer().min(0).optional(),
    limit: Joi.number().integer().min(1).max(100).optional()
  }
};

const conversions = {};

function assert(obj, schemaName) {
  var joiObj = _getSchema(schemaName);

  // All this hassle to get joi to format nice error messages
  var content = {};
  content[schemaName] = obj;
  var expected = {};
  expected[schemaName] = joiObj;

  try {
    Joi.assert(content, expected);
  } catch (err) {
    if (!err.isJoi) {
      throw err;
    }

    _throwJoiError(err);
  };

  // Return for convenience
  return obj;
}

// Converts string `value` to a correct js object.
// `schemaName` refers to key in `conversion` object. It defines all
// conversion functions.
function convert(obj, schemaName) {
  return _.reduce(obj, (memo, val, key) => {
    var func = _getConversion(schemaName)
    if (_.isFunction(func)) {
      memo[key] = func(val);
    } else {
      memo[key] = val;
    }
    return memo;

  }, {});
}

function _getConversion(name) {
  var conversion = _.get(conversions, name);
  if (!conversion) {
    throw new Error('Conversion with name ' + name + ' was not found');
  }
  return conversion;
}

function _getSchema(name) {
  var joiObj = _.get(schemas, name);
  if (!joiObj) {
    throw new Error('Schema with name ' + name + ' was not found');
  }
  return joiObj;
}

function _throwJoiError(err) {
  // See https://github.com/hapijs/joi/blob/v7.2.3/API.md#errors
  var msg = _.get(err, 'details.0.message') || 'Validation error';
  var newErr = new Error(msg);
  newErr.status = 400;
  throw newErr;
}

export {
  assert,
  convert,
  common,
  schemas
};
<commit_msg>Allow action without location in validation<commit_after>var _ = require('lodash');
var Joi = require('joi');

var common = {
  team: Joi.number().integer().min(0),
  userUuid: Joi.string().regex(/^[A-Za-z0-9_-]+$/).min(1, 'utf8').max(128, 'utf8'),
  primaryKeyId: Joi.number().integer().min(0)
};

const schemas = {
  common: common,

  action: {
    user: common.userUuid.required(),
    type: Joi.string().uppercase().required(),
    imageData: Joi.string().when('type', { is: 'IMAGE', then: Joi.required() }),
    text: Joi.string().when('type', { is: 'TEXT', then: Joi.required() }),
    location: Joi.object({
      latitude: Joi.number(),
      longitude: Joi.number()
    })
  },

  user: {
    uuid: common.userUuid.required(),
    name: Joi.string().min(1, 'utf8').max(30, 'utf8').required(),
    team: common.team.required()
  },

  feedParams: {
    beforeId: Joi.number().integer().min(0).optional(),
    limit: Joi.number().integer().min(1).max(100).optional()
  }
};

const conversions = {};

function assert(obj, schemaName) {
  var joiObj = _getSchema(schemaName);

  // All this hassle to get joi to format nice error messages
  var content = {};
  content[schemaName] = obj;
  var expected = {};
  expected[schemaName] = joiObj;

  try {
    Joi.assert(content, expected);
  } catch (err) {
    if (!err.isJoi) {
      throw err;
    }

    _throwJoiError(err);
  };

  // Return for convenience
  return obj;
}

// Converts string `value` to a correct js object.
// `schemaName` refers to key in `conversion` object. It defines all
// conversion functions.
function convert(obj, schemaName) {
  return _.reduce(obj, (memo, val, key) => {
    var func = _getConversion(schemaName)
    if (_.isFunction(func)) {
      memo[key] = func(val);
    } else {
      memo[key] = val;
    }
    return memo;

  }, {});
}

function _getConversion(name) {
  var conversion = _.get(conversions, name);
  if (!conversion) {
    throw new Error('Conversion with name ' + name + ' was not found');
  }
  return conversion;
}

function _getSchema(name) {
  var joiObj = _.get(schemas, name);
  if (!joiObj) {
    throw new Error('Schema with name ' + name + ' was not found');
  }
  return joiObj;
}

function _throwJoiError(err) {
  // See https://github.com/hapijs/joi/blob/v7.2.3/API.md#errors
  var msg = _.get(err, 'details.0.message') || 'Validation error';
  var newErr = new Error(msg);
  newErr.status = 400;
  throw newErr;
}

export {
  assert,
  convert,
  common,
  schemas
};
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2017-present, Shopgate, Inc. All rights reserved.
 *
 * This source code is licensed under the Apache 2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 *
 */

import { FAVORITES_PATH } from '@shopgate/pwa-common-commerce/favorites/constants';
import {
  addFavorites,
} from '@shopgate/pwa-common-commerce/favorites/actions/toggleFavorites';
import {
  favoritesWillRemoveItem$,
} from '@shopgate/pwa-common-commerce/favorites/streams';
import {
  getHistoryPathname,
} from '@shopgate/pwa-common/selectors/history';
import createToast from '@shopgate/pwa-common/actions/toast/createToast';

/**
 * Favorites page subscriptions.
 * @param {Function} subscribe The subscribe function.
 */
export default function favorites(subscribe) {
  subscribe(favoritesWillRemoveItem$, ({ dispatch, action, getState }) => {
    if (getHistoryPathname(getState()) !== FAVORITES_PATH) {
      // No toast message when favorites is not active page.
      return;
    }
    // Animations are too fast. This should wait a little bit.
    setTimeout(() => {
      dispatch(createToast({
        action: 'common.undo',
        actionOnClick: addFavorites(action.productId, true),
        message: 'favorites.removed',
        duration: 600000,
      }));
    }, 300);
  });
}

<commit_msg>CON-2768 - correct createToast duration<commit_after>/**
 * Copyright (c) 2017-present, Shopgate, Inc. All rights reserved.
 *
 * This source code is licensed under the Apache 2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 *
 */

import { FAVORITES_PATH } from '@shopgate/pwa-common-commerce/favorites/constants';
import {
  addFavorites,
} from '@shopgate/pwa-common-commerce/favorites/actions/toggleFavorites';
import {
  favoritesWillRemoveItem$,
} from '@shopgate/pwa-common-commerce/favorites/streams';
import {
  getHistoryPathname,
} from '@shopgate/pwa-common/selectors/history';
import createToast from '@shopgate/pwa-common/actions/toast/createToast';

/**
 * Favorites page subscriptions.
 * @param {Function} subscribe The subscribe function.
 */
export default function favorites(subscribe) {
  subscribe(favoritesWillRemoveItem$, ({ dispatch, action, getState }) => {
    if (getHistoryPathname(getState()) !== FAVORITES_PATH) {
      // No toast message when favorites is not active page.
      return;
    }
    // Animations are too fast. This should wait a little bit.
    setTimeout(() => {
      dispatch(createToast({
        action: 'common.undo',
        actionOnClick: addFavorites(action.productId, true),
        message: 'favorites.removed',
        duration: 6000,
      }));
    }, 300);
  });
}

<|endoftext|>


<commit_before>/**
 * DialogView.js
 */
(function (spiderOakApp, window, undefined) {
  "use strict";
  var console = window.console || {};
  console.log = console.log || function(){};
  var Backbone    = window.Backbone,
      _           = window._,
      $           = window.$,
      s           = window.s;

  spiderOakApp.DialogView = Backbone.View.extend({
    className: "modal",
    events: {
      "tap .cancel-btn a": "cancel_tapHandler"
    },
    initialize: function() {
      window.bindMine(this);
      var supportsOrientationChange = "onorientationchange" in window;
      this.orientationEvent = supportsOrientationChange ?
                                "orientationchange" :
                                "resize";
    },
    render: function() {
      $("body").append(this.el);
      return this;
    },
    showWait: function(options) {
      options = options || {};
      options.title = options.title || "Please wait";
      options.subtitle = options.subtitle || "";
      this.$el.html(window.tmpl["waitDialog"](options));
      if (options.showCancel && $.os.ios) $(".cancel-btn").show();
      this.$el.show();
    },
    showNotifyErrorResponse: function(response, options) {
      options = options ? _.clone(options) : {};
      options.title = options.title || " Error";
      options.duration = options.duration || 4000;
      options.subtitle = ((options.subtitle && (options.subtitle + ": ")) ||
                          "");
      options.subtitle += (response.statusText || "Network timeout " +
                           "
(status: " + response.status || 0 + ")");
      return this.showNotify(options);
    },
    showNotify: function(options) {
      options = options || {};
      options.title = options.title || "Done"; // terrible default ;)
      options.subtitle = options.subtitle || "";
      options.duration = options.duration || 2000; // in ms
      this.$el.html(window.tmpl["waitDialog"](options));
      this.$(".fadingBarsG").hide();
      this.$el.show();
      window.setTimeout(function(){
        this.hide();
      }.bind(this), options.duration);
    },
    cancel_tapHandler: function(event) {
      event.preventDefault();
      $(document).trigger("backbutton");
    },
    hide: function() {
      $(window).off(this.orientationEvent);
      this.$el.hide();
      this.$el.empty();
    },
    showProgress: function(options) {
      options = options || {};
      options.title = options.title || "Please wait";
      options.subtitle = options.subtitle || "";
      options.start = options.start || 0;
      this.$el.html(window.tmpl["progressDialog"](options));
      if (options.showCancel && $.os.ios) $(".cancel-btn").show();
      this.$el.show();
    },
    updateProgress: function(progressPercent) {
      this.$(".meter .progress").animate({"width":progressPercent+"%"});
    },
    showDialogView: function(view) {
      $(window).on(this.orientationEvent, function() {
        // alert("The rotation is " + window.orientation + " and the resolution is " + screen.width + " x " + screen.height);
        if (window.orientation === -90 || window.orientation === 90) {
          view.$el.css({"margin-top":"0", "max-height":"300px"});
          window.setTimeout(function(){
            view.scroller.refresh();
          },10);
        }
        else {
          view.$el.css({"margin-top":"10%", "max-height":"94%"});
          window.setTimeout(function(){
            view.scroller.refresh();
          },10);
        }
      }, false);
      this.$el.html(view.render().el);
      if (window.orientation === -90 || window.orientation === 90) {
        view.$el.css({"margin-top":"0", "max-height":"300px"});
      }
      window.setTimeout(function(){
        view.scroller.refresh();
      },10);
      if ($.os.ios) {
        // the stupid -50% is to keep it centered on iPad
        var _this = this;
        view.$el.css({"-webkit-transform":"translate3d(-50%,100%,0)"});
        this.$el.show();
        view.$el.animate(
          {"-webkit-transform":"translate3d(-50%,0,0)"}, 150, 'ease-in-out');
      } else {
        this.$el.show();
      }
    },
    close: function(){
      this.remove();
      this.unbind();
      // handle other unbinding needs, here
      _.each(this.subViews, function(subViews){
        if (subViews.close){
          subViews.close();
        }
      });
    }
  });
  spiderOakApp.dialogView = new spiderOakApp.DialogView().render();

  spiderOakApp.ContextPopup = Backbone.View.extend({
    className: "context-popup",
    events: {
      "tap a": "a_tapHandler"
    },
    initialize: function() {
      window.bindMine(this);
    },
    render: function() {
      this.$el.html(
        window.tmpl["contextPopup"]({
          items: this.options.items
        })
      );
      this.scroller = new window.iScroll(this.el, {
        bounce: !$.os.android,
        vScrollbar: false,
        hScrollbar: false
      });
      return this;
    },
    a_tapHandler: function(event) {
      this.trigger("item:tapped", event);
    },
    remove: function() {
      this.close();
      this.$el.remove();
      this.stopListening();
      return this;
    },
    close: function() {
      this.scroller.destroy();
    }
  });

})(window.spiderOakApp = window.spiderOakApp || {}, window);
<commit_msg>Progress dialogs were never getting past 50% or so… weird<commit_after>/**
 * DialogView.js
 */
(function (spiderOakApp, window, undefined) {
  "use strict";
  var console = window.console || {};
  console.log = console.log || function(){};
  var Backbone    = window.Backbone,
      _           = window._,
      $           = window.$,
      s           = window.s;

  spiderOakApp.DialogView = Backbone.View.extend({
    className: "modal",
    events: {
      "tap .cancel-btn a": "cancel_tapHandler"
    },
    initialize: function() {
      window.bindMine(this);
      var supportsOrientationChange = "onorientationchange" in window;
      this.orientationEvent = supportsOrientationChange ?
                                "orientationchange" :
                                "resize";
    },
    render: function() {
      $("body").append(this.el);
      return this;
    },
    showWait: function(options) {
      options = options || {};
      options.title = options.title || "Please wait";
      options.subtitle = options.subtitle || "";
      this.$el.html(window.tmpl["waitDialog"](options));
      if (options.showCancel && $.os.ios) $(".cancel-btn").show();
      this.$el.show();
    },
    showNotifyErrorResponse: function(response, options) {
      options = options ? _.clone(options) : {};
      options.title = options.title || " Error";
      options.duration = options.duration || 4000;
      options.subtitle = ((options.subtitle && (options.subtitle + ": ")) ||
                          "");
      options.subtitle += (response.statusText || "Network timeout " +
                           "
(status: " + response.status || 0 + ")");
      return this.showNotify(options);
    },
    showNotify: function(options) {
      options = options || {};
      options.title = options.title || "Done"; // terrible default ;)
      options.subtitle = options.subtitle || "";
      options.duration = options.duration || 2000; // in ms
      this.$el.html(window.tmpl["waitDialog"](options));
      this.$(".fadingBarsG").hide();
      this.$el.show();
      window.setTimeout(function(){
        this.hide();
      }.bind(this), options.duration);
    },
    cancel_tapHandler: function(event) {
      event.preventDefault();
      $(document).trigger("backbutton");
    },
    hide: function() {
      $(window).off(this.orientationEvent);
      this.$el.hide();
      this.$el.empty();
    },
    showProgress: function(options) {
      options = options || {};
      options.title = options.title || "Please wait";
      options.subtitle = options.subtitle || "";
      options.start = options.start || 0;
      this.$el.html(window.tmpl["progressDialog"](options));
      if (options.showCancel && $.os.ios) $(".cancel-btn").show();
      this.$el.show();
    },
    updateProgress: function(progressPercent) {
      console.log(progressPercent);
      progressPercent = progressPercent * (($.os.ios) ? 2 : 1.5); // WHY?!
      if (progressPercent > 100) {
        progressPercent = 100;
      }
      this.$(".meter .progress").animate({"width":progressPercent+"%"});
    },
    showDialogView: function(view) {
      $(window).on(this.orientationEvent, function() {
        // alert("The rotation is " + window.orientation + " and the resolution is " + screen.width + " x " + screen.height);
        if (window.orientation === -90 || window.orientation === 90) {
          view.$el.css({"margin-top":"0", "max-height":"300px"});
          window.setTimeout(function(){
            view.scroller.refresh();
          },10);
        }
        else {
          view.$el.css({"margin-top":"10%", "max-height":"94%"});
          window.setTimeout(function(){
            view.scroller.refresh();
          },10);
        }
      }, false);
      this.$el.html(view.render().el);
      if (window.orientation === -90 || window.orientation === 90) {
        view.$el.css({"margin-top":"0", "max-height":"300px"});
      }
      window.setTimeout(function(){
        view.scroller.refresh();
      },10);
      if ($.os.ios) {
        // the stupid -50% is to keep it centered on iPad
        var _this = this;
        view.$el.css({"-webkit-transform":"translate3d(-50%,100%,0)"});
        this.$el.show();
        view.$el.animate(
          {"-webkit-transform":"translate3d(-50%,0,0)"}, 150, 'ease-in-out');
      } else {
        this.$el.show();
      }
    },
    close: function(){
      this.remove();
      this.unbind();
      // handle other unbinding needs, here
      _.each(this.subViews, function(subViews){
        if (subViews.close){
          subViews.close();
        }
      });
    }
  });
  spiderOakApp.dialogView = new spiderOakApp.DialogView().render();

  spiderOakApp.ContextPopup = Backbone.View.extend({
    className: "context-popup",
    events: {
      "tap a": "a_tapHandler"
    },
    initialize: function() {
      window.bindMine(this);
    },
    render: function() {
      this.$el.html(
        window.tmpl["contextPopup"]({
          items: this.options.items
        })
      );
      this.scroller = new window.iScroll(this.el, {
        bounce: !$.os.android,
        vScrollbar: false,
        hScrollbar: false
      });
      return this;
    },
    a_tapHandler: function(event) {
      this.trigger("item:tapped", event);
    },
    remove: function() {
      this.close();
      this.$el.remove();
      this.stopListening();
      return this;
    },
    close: function() {
      this.scroller.destroy();
    }
  });

})(window.spiderOakApp = window.spiderOakApp || {}, window);
<|endoftext|>


<commit_before>alert("hello world");
<commit_msg>add a new action<commit_after>alert("hello world");

alert("");
<|endoftext|>


<commit_before>module.exports = {
  data: function() {
    return {
      id: '',
      schema: {}
    };
  },
  template: require('./template.html'),
  components: {
    'json-schema-property': {
      template: require('./property-template.html')
    }
  },
  filters: {
    input_type: function(value) {
      var types = {
          string: 'text',
          integer: 'number'
      }
      return types[value];
    }
  },
  watch: {
    id: function() {
      this.fetchSchema();
    }
  },
  methods: {
    fetchSchema: function() {
      if (!this.id) return false;
      var xhr = new XMLHttpRequest(),
          self = this;
      xhr.open('GET', self.id);
      xhr.onload = function () {
        self.schema = JSON.parse(xhr.responseText);
        if (self.schema.title) {
          self.$parent.name = self.schema.title;
          self.schema.title = '';
        } else {
          self.$parent.name = self.id;
        }
      };
      xhr.send();

    },
    output: function() {
      var jsonDOM = this.$el.querySelectorAll('[data-json]');
      var json = {};
      function accumulate(obj, dom) {
        for (var i = 0; i < dom.length; i++) {
          if (dom[i].dataset['json'] == 'kvp') {
            obj[dom[i].querySelector('label').textContent] = dom[i].querySelector('input').value;
          } else if (dom[i].dataset['json'] == 'object') {
            var legend = dom[i].querySelector('legend').textContent;
            var sub_dom = dom[i].querySelectorAll('[data-json]');
            obj[legend] = accumulate({}, sub_dom);
            i += sub_dom.length;
          }
        }
        return obj;
      }
      return accumulate(json, jsonDOM);
    }
  }
};
<commit_msg>Replace default <div> w/property template<commit_after>module.exports = {
  data: function() {
    return {
      id: '',
      schema: {}
    };
  },
  template: require('./template.html'),
  components: {
    'json-schema-property': {
      replace: true,
      template: require('./property-template.html')
    }
  },
  filters: {
    input_type: function(value) {
      var types = {
          string: 'text',
          integer: 'number'
      }
      return types[value];
    }
  },
  watch: {
    id: function() {
      this.fetchSchema();
    }
  },
  methods: {
    fetchSchema: function() {
      if (!this.id) return false;
      var xhr = new XMLHttpRequest(),
          self = this;
      xhr.open('GET', self.id);
      xhr.onload = function () {
        self.schema = JSON.parse(xhr.responseText);
        if (self.schema.title) {
          self.$parent.name = self.schema.title;
          self.schema.title = '';
        } else {
          self.$parent.name = self.id;
        }
      };
      xhr.send();

    },
    output: function() {
      var jsonDOM = this.$el.querySelectorAll('[data-json]');
      var json = {};
      function accumulate(obj, dom) {
        for (var i = 0; i < dom.length; i++) {
          if (dom[i].dataset['json'] == 'kvp') {
            obj[dom[i].querySelector('label').textContent] = dom[i].querySelector('input').value;
          } else if (dom[i].dataset['json'] == 'object') {
            var legend = dom[i].querySelector('legend').textContent;
            var sub_dom = dom[i].querySelectorAll('[data-json]');
            obj[legend] = accumulate({}, sub_dom);
            i += sub_dom.length;
          }
        }
        return obj;
      }
      return accumulate(json, jsonDOM);
    }
  }
};
<|endoftext|>