<commit_before>let React = require('react-native')

let {
    NativeModules,
    NativeAppEventEmitter
} = React

let {
    TwilioIPMessagingClient,
    TwilioIPMessagingChannels,
    TwilioIPMessagingMessages
} = NativeModules

let Message = require('./Message')

class Channel {
    constructor(props) {
        this.sid = props.sid
        this.friendlyName = props.friendlyName
        this.uniqueName = props.uniqueName
        this.synchronizationStatus = props.synchronizationStatus
        this.status = props.status
        this.type = props.type

        this.onSynchronizationStatusChanged = null
        this.onChanged = null
        this.onDeleted = null
        this.onMemberJoined = null
        this.onMemberChanged = null
        this.onMemberLeft = null
        this.onMessageAdded = null
        this.onMessageChanged = null
        this.onMessageDeleted = null
        this.onTypingStarted = null
        this.onTypingEnded = null
        this.onToastReceived = null

        // event handlers
        this._channelSynchronizationStatusChangedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:synchronizationStatusChanged',
            ({channelSid, status}) => {
                if (channelSid == this.sid && this.onSynchronizationStatusChanged) this.onSynchronizationStatusChanged(status)
            }
        )

        this._channelChangedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channelChanged',
            (channel) => {
                if (channelSid == this.sid && this.onChannelChanged) this.onChanged(channel)
            }
        )

        this._channelDeletedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channelDeleted',
            (channel) => {
                if (channelSid == this.sid && this.onDeleted) this.onDeleted()
            }
        )

        this._channelMemberJoinedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:memberJoined',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onMemberJoined) this.onMemberJoined({member})
            }
        )

        this._channelMemberChangedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:memberChanged',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onMemberChanged) this.onMemberChanged({member})
            }
        )

        this._channelMemberLeftSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:memberLeft',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onMemberLeft) this.onMemberLeft({member})
            }
        )

        this._channelMessageAddedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:messageAdded',
            ({channelSid, message}) => {
                if (channelSid == this.sid && this.onMessageAdded) this.onMessageAdded({message: new Message(message, channelSid)})
            }
        )

        this._channelMessageChangedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:messageChanged',
            ({channelSid, message}) => {
                if (channelSid == this.sid && this.onMessageChanged) this.onMessageChanged({message: new Message(message, channelSid)})
            }
        )

        this._channelMessageDeletedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:messageDeleted',
            ({channelSid, message}) => {
                if (channelSid == this.sid && this.onMessageDeleted) this.onMessageDeleted({message: new Message(message, channelSid)})
            }
        )

        this._typingChannelStartedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:typingStartedOnChannel',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onTypingStarted) this.onTypingStarted({member})
            }
        )

        this._typingChannelEndedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:typingEndedOnChannel',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onTypingEnded) this.onTypingEnded({member})
            }
        )

        this._toastReceivedChannelSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:toastReceivedOnChannel',
            ({channelSid, message}) => {
                if (channelSid == this.sid && this.onToastReceived) this.onToastReceived({message})
            }
        )
    }

    initialize() {
        return TwilioIPMessagingChannels.synchronizeWithCompletion(this.sid)
    }

    setAttributes(attributes) {
        return TwilioIPMessagingChannels.setAttributes(this.sid, attributes)
    }

    setFriendlyName(friendlyName) {
        return TwilioIPMessagingChannels.setFriendlyName(this.sid, friendlyName)
    }

    setUniqueName(uniqueName) {
        return TwilioIPMessagingChannels.setUniqueName(this.sid, uniqueName)
    }

    join() {
        return TwilioIPMessagingChannels.joinWithCompletion(this.sid)
    }

    declineInvitation() {
        return TwilioIPMessagingChannels.declineInvitationWithCompletion(this.sid)
    }

    leave() {
        return TwilioIPMessagingChannels.leaveWithCompletion(this.sid)
    }

    destroy() {
        return TwilioIPMessagingChannels.destroyWithCompletion(this.sid)
    }

    typing() {
        TwilioIPMessagingChannels.typing(this.sid)
    }

    getMember(identity) {
        return TwilioIPMessagingChannels.memberWithIdentity(this.sid, identity)
    }

    getMembers() {
        return TwilioIPMessagingMembers.allObjects()
    }

    add(identity) {
        return TwilioIPMessagingMembers.addByIdentity(this.sid, identity)
    }

    invite(identity) {
        return TwilioIPMessagingMembers.inviteByIdentity(this.sid, identity)
    }

    remove(identity) {
        return TwilioIPMessagingMembers.removeByIdentity(this.sid, identity)
    }

    lastConsumedMessageIndex() {
        return TwilioIPMessagingMessages.lastConsumedMessageIndex(this.sid)
    }

    sendMessage(body) {
        return TwilioIPMessagingMessages.sendMessageWithBody(this.sid, body)
    }

    removeMessage(index) {
        return TwilioIPMessagingMessages.removeMessage(this.sid, index)
    }

    getMessages(count = 10) {
        return TwilioIPMessagingMessages.getLastMessagesWithCount(this.sid, count)
        .then((messages) => messages.map((message) => new Message(message, this.sid)))
    }

    getMessagesBefore(index, count) {
        return TwilioIPMessagingMessages.getMessagesBefore(this.sid, index, count)
        .then((messages) => messages.map((message) => new Message(message, this.sid)))

    }

    getMessagesAfter(index, count) {
        return TwilioIPMessagingMessages.getMessagesAfter(this.sid, index, count)
        .then((messages) => messages.map((message) => new Message(message, this.sid)))
    }

    getMessage(index) {
        return TwilioIPMessagingMessages.messageWithIndex(this.sid, index)
        .then((message) => new Message(message, this.sid))
    }

    getMessageForConsumption(index) {
        return TwilioIPMessagingMessages.messageForConsumptionIndex(this.sid, index)
        .then((message) => new Message(message, this.sid))
    }

    setLastConsumedMessageIndex(index) {
        TwilioIPMessagingMessages.setLastConsumedMessageIndex(this.sid, index)
    }

    advanceLastConsumedMessageIndex(index) {
        TwilioIPMessagingMessages.advanceLastConsumedMessageIndex(this.sid, index)
    }

    setAllMessagesConsumed() {
        TwilioIPMessagingMessages.setAllMessagesConsumed(this.sid)
    }

    close() {
        this._channelChangedSubscription.remove()
        this._channelDeletedSubscription.remove()
        this._channelSynchronizationStatusChangedSubscription.remove()
        this._channelMemberJoinedSubscription.remove()
        this._channelMemberChangedSubscription.remove()
        this._channelMemberLeftSubscription.remove()
        this._channelMessageAddedSubscription.remove()
        this._channelMessageChangedSubscription.remove()
        this._channelMessageDeletedSubscription.remove()
        this._typingChannelStartedSubscription.remove()
        this._typingChannelEndedSubscription.remove()
        this._toastReceivedChannelSubscription.remove()
    }
}

module.exports = Channel<commit_msg>Modified API for response of events (return result instead of object)<commit_after>let React = require('react-native')

let {
    NativeModules,
    NativeAppEventEmitter
} = React

let {
    TwilioIPMessagingClient,
    TwilioIPMessagingChannels,
    TwilioIPMessagingMessages
} = NativeModules

let Message = require('./Message')

class Channel {
    constructor(props) {
        this.sid = props.sid
        this.friendlyName = props.friendlyName
        this.uniqueName = props.uniqueName
        this.synchronizationStatus = props.synchronizationStatus
        this.status = props.status
        this.type = props.type

        this.onSynchronizationStatusChanged = null
        this.onChanged = null
        this.onDeleted = null
        this.onMemberJoined = null
        this.onMemberChanged = null
        this.onMemberLeft = null
        this.onMessageAdded = null
        this.onMessageChanged = null
        this.onMessageDeleted = null
        this.onTypingStarted = null
        this.onTypingEnded = null
        this.onToastReceived = null

        // event handlers
        this._channelSynchronizationStatusChangedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:synchronizationStatusChanged',
            ({channelSid, status}) => {
                if (channelSid == this.sid && this.onSynchronizationStatusChanged) this.onSynchronizationStatusChanged(status)
            }
        )

        this._channelChangedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channelChanged',
            (channel) => {
                if (channelSid == this.sid && this.onChannelChanged) this.onChanged(new Channel(channel))
            }
        )

        this._channelDeletedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channelDeleted',
            (channel) => {
                if (channelSid == this.sid && this.onDeleted) this.onDeleted()
            }
        )

        this._channelMemberJoinedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:memberJoined',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onMemberJoined) this.onMemberJoined(member)
            }
        )

        this._channelMemberChangedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:memberChanged',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onMemberChanged) this.onMemberChanged(member)
            }
        )

        this._channelMemberLeftSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:memberLeft',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onMemberLeft) this.onMemberLeft(member)
            }
        )

        this._channelMessageAddedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:messageAdded',
            ({channelSid, message}) => {
                if (channelSid == this.sid && this.onMessageAdded) this.onMessageAdded(new Message(message, channelSid))
            }
        )

        this._channelMessageChangedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:messageChanged',
            ({channelSid, message}) => {
                if (channelSid == this.sid && this.onMessageChanged) this.onMessageChanged(message: new Message(message, channelSid))
            }
        )

        this._channelMessageDeletedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:channel:messageDeleted',
            ({channelSid, message}) => {
                if (channelSid == this.sid && this.onMessageDeleted) this.onMessageDeleted(message: new Message(message, channelSid))
            }
        )

        this._typingChannelStartedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:typingStartedOnChannel',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onTypingStarted) this.onTypingStarted(member)
            }
        )

        this._typingChannelEndedSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:typingEndedOnChannel',
            ({channelSid, member}) => {
                if (channelSid == this.sid && this.onTypingEnded) this.onTypingEnded(member)
            }
        )

        this._toastReceivedChannelSubscription = NativeAppEventEmitter.addListener(
            'ipMessagingClient:toastReceivedOnChannel',
            ({channelSid, message}) => {
                if (channelSid == this.sid && this.onToastReceived) this.onToastReceived(message)
            }
        )
    }

    initialize() {
        return TwilioIPMessagingChannels.synchronizeWithCompletion(this.sid)
    }

    setAttributes(attributes) {
        return TwilioIPMessagingChannels.setAttributes(this.sid, attributes)
    }

    setFriendlyName(friendlyName) {
        return TwilioIPMessagingChannels.setFriendlyName(this.sid, friendlyName)
    }

    setUniqueName(uniqueName) {
        return TwilioIPMessagingChannels.setUniqueName(this.sid, uniqueName)
    }

    join() {
        return TwilioIPMessagingChannels.joinWithCompletion(this.sid)
    }

    declineInvitation() {
        return TwilioIPMessagingChannels.declineInvitationWithCompletion(this.sid)
    }

    leave() {
        return TwilioIPMessagingChannels.leaveWithCompletion(this.sid)
    }

    destroy() {
        return TwilioIPMessagingChannels.destroyWithCompletion(this.sid)
    }

    typing() {
        TwilioIPMessagingChannels.typing(this.sid)
    }

    getMember(identity) {
        return TwilioIPMessagingChannels.memberWithIdentity(this.sid, identity)
    }

    getMembers() {
        return TwilioIPMessagingMembers.allObjects()
    }

    add(identity) {
        return TwilioIPMessagingMembers.addByIdentity(this.sid, identity)
    }

    invite(identity) {
        return TwilioIPMessagingMembers.inviteByIdentity(this.sid, identity)
    }

    remove(identity) {
        return TwilioIPMessagingMembers.removeByIdentity(this.sid, identity)
    }

    lastConsumedMessageIndex() {
        return TwilioIPMessagingMessages.lastConsumedMessageIndex(this.sid)
    }

    sendMessage(body) {
        return TwilioIPMessagingMessages.sendMessageWithBody(this.sid, body)
    }

    removeMessage(index) {
        return TwilioIPMessagingMessages.removeMessage(this.sid, index)
    }

    getMessages(count = 10) {
        return TwilioIPMessagingMessages.getLastMessagesWithCount(this.sid, count)
        .then((messages) => messages.map((message) => new Message(message, this.sid)))
    }

    getMessagesBefore(index, count) {
        return TwilioIPMessagingMessages.getMessagesBefore(this.sid, index, count)
        .then((messages) => messages.map((message) => new Message(message, this.sid)))

    }

    getMessagesAfter(index, count) {
        return TwilioIPMessagingMessages.getMessagesAfter(this.sid, index, count)
        .then((messages) => messages.map((message) => new Message(message, this.sid)))
    }

    getMessage(index) {
        return TwilioIPMessagingMessages.messageWithIndex(this.sid, index)
        .then((message) => new Message(message, this.sid))
    }

    getMessageForConsumption(index) {
        return TwilioIPMessagingMessages.messageForConsumptionIndex(this.sid, index)
        .then((message) => new Message(message, this.sid))
    }

    setLastConsumedMessageIndex(index) {
        TwilioIPMessagingMessages.setLastConsumedMessageIndex(this.sid, index)
    }

    advanceLastConsumedMessageIndex(index) {
        TwilioIPMessagingMessages.advanceLastConsumedMessageIndex(this.sid, index)
    }

    setAllMessagesConsumed() {
        TwilioIPMessagingMessages.setAllMessagesConsumed(this.sid)
    }

    close() {
        this._channelChangedSubscription.remove()
        this._channelDeletedSubscription.remove()
        this._channelSynchronizationStatusChangedSubscription.remove()
        this._channelMemberJoinedSubscription.remove()
        this._channelMemberChangedSubscription.remove()
        this._channelMemberLeftSubscription.remove()
        this._channelMessageAddedSubscription.remove()
        this._channelMessageChangedSubscription.remove()
        this._channelMessageDeletedSubscription.remove()
        this._typingChannelStartedSubscription.remove()
        this._typingChannelEndedSubscription.remove()
        this._toastReceivedChannelSubscription.remove()
    }
}

module.exports = Channel<|endoftext|>


<commit_before>const axios = require('axios');

const config = require('./Config.js')

module.exports = {

	get: async  function(options){
		let optionsFinal = config.optionsFinalize("get",options);
		return _makeRequest(optionsFinal,options);
	},

	post: async function(options){
		let optionsFinal = config.optionsFinalize("post",options);
		return _makeRequest(optionsFinal,options);
	},

	patch: async function(options){
		let optionsFinal = config.optionsFinalize("post",options, true);
		return _makeRequest(optionsFinal,options);
	},

	delete: async function(options){
		let optionsFinal = config.optionsFinalize("delete",options, true);
		return _makeRequest(optionsFinal,options);
	},

}

const _setOptions = function(printingOptions){

	let returnJson = (printingOptions.debug != undefined && printingOptions.debug == true) ? false : true;

	let prettyPrint = (printingOptions.prettyPrint != undefined && printingOptions.prettyPrint == true) ? true : false;

	return [returnJson,prettyPrint];
}

const _makeRequest = async function(optionsFinal, printingOptions){

	let printingOptionsFinal = _setOptions(printingOptions)

	let response = await axios(optionsFinal);

	if(printingOptionsFinal[0] == true){
		if (printingOptionsFinal[1] == true){
			return JSON.stringify(response.data, null , 4)
		}else{
			return response.data;
		}
	}else{
		return response;
	}
}<commit_msg>trying again, there seems to be an issue with inlining async within exporting modules...<commit_after>const axios = require('axios');

const config = require('./Config.js')

module.exports = {

	get: function(options){
		let optionsFinal = config.optionsFinalize("get",options);
		return _makeRequest(optionsFinal,options);
	},

	post: function(options){
		let optionsFinal = config.optionsFinalize("post",options);
		return _makeRequest(optionsFinal,options);
	},

	patch: function(options){
		let optionsFinal = config.optionsFinalize("post",options, true);
		return _makeRequest(optionsFinal,options);
	},

	delete: function(options){
		let optionsFinal = config.optionsFinalize("delete",options, true);
		return _makeRequest(optionsFinal,options);
	},

}

const _setOptions = function(printingOptions){

	let returnJson = (printingOptions.debug != undefined && printingOptions.debug == true) ? false : true;

	let prettyPrint = (printingOptions.prettyPrint != undefined && printingOptions.prettyPrint == true) ? true : false;

	return [returnJson,prettyPrint];
}

const _makeRequest = async function(optionsFinal, printingOptions){

	let printingOptionsFinal = _setOptions(printingOptions)

	let response = await axios(optionsFinal);

	if(printingOptionsFinal[0] == true){
		if (printingOptionsFinal[1] == true){
			return JSON.stringify(response.data, null , 4)
		}else{
			return response.data;
		}
	}else{
		return response;
	}
}<|endoftext|>


<commit_before>var __apply = function(f,as) {
    var arr = [];
    for(; as[0] === 1; as = as[2]) {
        arr.push(as[1]);
    }
    arr.reverse();
    return f.apply(null, arr);
}
var __app0 = function(f) {return f();}
var __app1 = function(f,a) {return f(a);}
var __app2 = function(f,a,b) {return f(a,b);}
var __app3 = function(f,a,b,c) {return f(a,b,c);}
var __app4 = function(f,a,b,c,d) {return f(a,b,c,d);}
var __app5 = function(f,a,b,c,d,e) {return f(a,b,c,d,e);}
var __jsNull = function() {return null;}
var __jsTrue = function() {return true;}
var __jsFalse = function() {return false;}
var __eq = function(a,b) {return a===b;}
var __createJSFunc = function(arity, f){
    if(f instanceof Function && arity === f.length) {
        return (function() {
            var x = f.apply(null,arguments);
            if(x instanceof T) {
                if(x.f !== __blackhole) {
                    var ff = x.f;
                    x.f = __blackhole;
                    return x.x = ff();
                }
                return x.x;
            } else {
                while(x instanceof F) {
                    x = fun();
                }
                return E(x);
            }
        });
    } else {
        return (function(){
            var as = Array.prototype.slice.call(arguments);
            as.push(0);
            return E(B(A(f,as)));
        });
    }
}

function __arr2lst(elem,arr) {
    if(elem >= arr.length) {
        return [0];
    }
    return [1, arr[elem],new T(function(){return __arr2lst(elem+1,arr);})]
}

function __lst2arr(xs) {
    var arr = [];
    xs = E(xs);
    for(;xs[0] === 1; xs = E(xs[2])) {
        arr.push(E(xs[1]));
    }
    return arr;
}

var __new = function() {return ({});}
var __set = function(o,k,v) {o[k]=v;}
var __get = function(o,k) {return o[k];}
var __has = function(o,k) {return o[k]!==undefined;}
<commit_msg>Add scaffolding for foreign import ccall "wrapper".<commit_after>/* For foreign import ccall "wrapper" */
function createAdjustor(args, f, a, b) {
    return function(){
        var x = f.apply(null, arguments);
        while(x instanceof F) {x = x.f();}
        return x;
    };
}

var __apply = function(f,as) {
    var arr = [];
    for(; as[0] === 1; as = as[2]) {
        arr.push(as[1]);
    }
    arr.reverse();
    return f.apply(null, arr);
}
var __app0 = function(f) {return f();}
var __app1 = function(f,a) {return f(a);}
var __app2 = function(f,a,b) {return f(a,b);}
var __app3 = function(f,a,b,c) {return f(a,b,c);}
var __app4 = function(f,a,b,c,d) {return f(a,b,c,d);}
var __app5 = function(f,a,b,c,d,e) {return f(a,b,c,d,e);}
var __jsNull = function() {return null;}
var __jsTrue = function() {return true;}
var __jsFalse = function() {return false;}
var __eq = function(a,b) {return a===b;}
var __createJSFunc = function(arity, f){
    if(f instanceof Function && arity === f.length) {
        return (function() {
            var x = f.apply(null,arguments);
            if(x instanceof T) {
                if(x.f !== __blackhole) {
                    var ff = x.f;
                    x.f = __blackhole;
                    return x.x = ff();
                }
                return x.x;
            } else {
                while(x instanceof F) {
                    x = fun();
                }
                return E(x);
            }
        });
    } else {
        return (function(){
            var as = Array.prototype.slice.call(arguments);
            as.push(0);
            return E(B(A(f,as)));
        });
    }
}

function __arr2lst(elem,arr) {
    if(elem >= arr.length) {
        return [0];
    }
    return [1, arr[elem],new T(function(){return __arr2lst(elem+1,arr);})]
}

function __lst2arr(xs) {
    var arr = [];
    xs = E(xs);
    for(;xs[0] === 1; xs = E(xs[2])) {
        arr.push(E(xs[1]));
    }
    return arr;
}

var __new = function() {return ({});}
var __set = function(o,k,v) {o[k]=v;}
var __get = function(o,k) {return o[k];}
var __has = function(o,k) {return o[k]!==undefined;}
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import FocusTrap from './FocusTrap';
import HotKeyMapMixin from './HotKeyMapMixin';
import isBool from 'lodash/isBoolean';
import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';
import forEach from 'lodash/forEach';
import isEqual from 'lodash/isEqual';

function getSequencesFromMap(hotKeyMap, hotKeyName) {
  const sequences = hotKeyMap[hotKeyName];

  // If no sequence is found with this name we assume
  // the user is passing a hard-coded sequence as a key
  if (!sequences) {
    return [hotKeyName];
  }

  if (isArray(sequences)) {
    return sequences;
  }

  return [sequences];
}

const HotKeys = React.createClass({

  mixins: [HotKeyMapMixin()],

  propTypes: {
    children: React.PropTypes.node,
    onFocus: React.PropTypes.func,
    onBlur: React.PropTypes.func,
    keyMap: React.PropTypes.object,
    handlers: React.PropTypes.object,
    focused: React.PropTypes.bool, // externally controlled focus
    attach: React.PropTypes.any // dom element to listen for key events
  },

  contextTypes: {
    hotKeyParent: React.PropTypes.any
  },

  childContextTypes: {
    hotKeyParent: React.PropTypes.any
  },

  getChildContext() {
    return {
      hotKeyParent: this
    };
  },

  componentDidMount() {
    // import is here to support React's server rendering as Mousetrap immediately
    // calls itself with window and it fails in Node environment
    const Mousetrap = require('mousetrap');
    // Not optimal - imagine hundreds of this component. We need a top level
    // delegation point for mousetrap
    this.__mousetrap__ = new Mousetrap(
      this.props.attach || ReactDOM.findDOMNode(this)
    );

    this.updateHotKeys(true);
  },

  componentDidUpdate(prevProps) {
    this.updateHotKeys(false, prevProps);
  },

  componentWillUnmount() {
    if (this.context.hotKeyParent) {
      this.context.hotKeyParent.childHandledSequence(null);
    }

    if (this.__mousetrap__) {
      this.__mousetrap__.reset();
    }
  },

  updateHotKeys(force = false, prevProps = {}) {
    const {handlers = {}} = this.props;
    const {handlers: prevHandlers = handlers} = prevProps;

    // Ensure map is up-to-date to begin with
    // We will only bother continuing if the map was actually updated
    if (!force && isEqual(handlers, prevHandlers) && !this.updateMap()) {
      return;
    }

    const hotKeyMap = this.getMap();
    const sequenceHandlers = [];
    const mousetrap = this.__mousetrap__;

    // Group all our handlers by sequence
    forEach(handlers, (handler, hotKey) => {
      const handlerSequences = getSequencesFromMap(hotKeyMap, hotKey);

      // Could be optimized as every handler will get called across every bound
      // component - imagine making a node a focus point and then having hundreds!
      forEach(handlerSequences, (sequence) => {
        let action;

        const callback = (event, sequence) => {
          // Check we are actually in focus and that a child hasn't already handled this sequence
          const isFocused = isBool(this.props.focused)
            ? this.props.focused
            : this.__isFocused__;

          if (isFocused && sequence !== this.__lastChildSequence__) {
            if (this.context.hotKeyParent) {
              this.context.hotKeyParent.childHandledSequence(sequence);
            }

            return handler(event, sequence);
          }
        };

        if (isObject(sequence)) {
          action = sequence.action;
          sequence = sequence.sequence;
        }

        sequenceHandlers.push({callback, action, sequence});
      });
    });

    // Hard reset our handlers (probably could be more efficient)
    mousetrap.reset();
    forEach(sequenceHandlers, (handler) =>
      mousetrap.bind(handler.sequence, handler.callback, handler.action));
  },

  childHandledSequence(sequence = null) {
    this.__lastChildSequence__ = sequence;

    // Traverse up any hot key parents so everyone is aware a child has handled a certain sequence
    if (this.context.hotKeyParent) {
      this.context.hotKeyParent.childHandledSequence(sequence);
    }
  },

  onFocus() {
    this.__isFocused__ = true;

    if (this.props.onFocus) {
      this.props.onFocus(...arguments);
    }
  },

  onBlur() {
    this.__isFocused__ = false;

    if (this.props.onBlur) {
      this.props.onBlur(...arguments);
    }
    if (this.context.hotKeyParent) {
      this.context.hotKeyParent.childHandledSequence(null);
    }
  },

  render() {
    const {children, keyMap, handlers, focused, attach, ...props} = this.props;

    return (
      <FocusTrap {...props} onFocus={this.onFocus} onBlur={this.onBlur}>
        {children}
      </FocusTrap>
    );
  }

});

export default HotKeys;
<commit_msg>fix key map update<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import FocusTrap from './FocusTrap';
import HotKeyMapMixin from './HotKeyMapMixin';
import isBool from 'lodash/isBoolean';
import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';
import forEach from 'lodash/forEach';
import isEqual from 'lodash/isEqual';

function getSequencesFromMap(hotKeyMap, hotKeyName) {
  const sequences = hotKeyMap[hotKeyName];

  // If no sequence is found with this name we assume
  // the user is passing a hard-coded sequence as a key
  if (!sequences) {
    return [hotKeyName];
  }

  if (isArray(sequences)) {
    return sequences;
  }

  return [sequences];
}

const HotKeys = React.createClass({

  mixins: [HotKeyMapMixin()],

  propTypes: {
    children: React.PropTypes.node,
    onFocus: React.PropTypes.func,
    onBlur: React.PropTypes.func,
    keyMap: React.PropTypes.object,
    handlers: React.PropTypes.object,
    focused: React.PropTypes.bool, // externally controlled focus
    attach: React.PropTypes.any // dom element to listen for key events
  },

  contextTypes: {
    hotKeyParent: React.PropTypes.any
  },

  childContextTypes: {
    hotKeyParent: React.PropTypes.any
  },

  getChildContext() {
    return {
      hotKeyParent: this
    };
  },

  componentDidMount() {
    // import is here to support React's server rendering as Mousetrap immediately
    // calls itself with window and it fails in Node environment
    const Mousetrap = require('mousetrap');
    // Not optimal - imagine hundreds of this component. We need a top level
    // delegation point for mousetrap
    this.__mousetrap__ = new Mousetrap(
      this.props.attach || ReactDOM.findDOMNode(this)
    );

    this.updateHotKeys(true);
  },

  componentDidUpdate(prevProps) {
    this.updateHotKeys(false, prevProps);
  },

  componentWillUnmount() {
    if (this.context.hotKeyParent) {
      this.context.hotKeyParent.childHandledSequence(null);
    }

    if (this.__mousetrap__) {
      this.__mousetrap__.reset();
    }
  },

  updateHotKeys(force = false, prevProps = {}) {
    const {handlers = {}} = this.props;
    const {handlers: prevHandlers = handlers} = prevProps;

    // Ensure map is up-to-date to begin with
    // We will only bother continuing if the map was actually updated
    if (!force && !this.updateMap() && isEqual(handlers, prevHandlers)) {
      return;
    }

    const hotKeyMap = this.getMap();
    const sequenceHandlers = [];
    const mousetrap = this.__mousetrap__;

    // Group all our handlers by sequence
    forEach(handlers, (handler, hotKey) => {
      const handlerSequences = getSequencesFromMap(hotKeyMap, hotKey);

      // Could be optimized as every handler will get called across every bound
      // component - imagine making a node a focus point and then having hundreds!
      forEach(handlerSequences, (sequence) => {
        let action;

        const callback = (event, sequence) => {
          // Check we are actually in focus and that a child hasn't already handled this sequence
          const isFocused = isBool(this.props.focused)
            ? this.props.focused
            : this.__isFocused__;

          if (isFocused && sequence !== this.__lastChildSequence__) {
            if (this.context.hotKeyParent) {
              this.context.hotKeyParent.childHandledSequence(sequence);
            }

            return handler(event, sequence);
          }
        };

        if (isObject(sequence)) {
          action = sequence.action;
          sequence = sequence.sequence;
        }

        sequenceHandlers.push({callback, action, sequence});
      });
    });

    // Hard reset our handlers (probably could be more efficient)
    mousetrap.reset();
    forEach(sequenceHandlers, (handler) =>
      mousetrap.bind(handler.sequence, handler.callback, handler.action));
  },

  childHandledSequence(sequence = null) {
    this.__lastChildSequence__ = sequence;

    // Traverse up any hot key parents so everyone is aware a child has handled a certain sequence
    if (this.context.hotKeyParent) {
      this.context.hotKeyParent.childHandledSequence(sequence);
    }
  },

  onFocus() {
    this.__isFocused__ = true;

    if (this.props.onFocus) {
      this.props.onFocus(...arguments);
    }
  },

  onBlur() {
    this.__isFocused__ = false;

    if (this.props.onBlur) {
      this.props.onBlur(...arguments);
    }
    if (this.context.hotKeyParent) {
      this.context.hotKeyParent.childHandledSequence(null);
    }
  },

  render() {
    const {children, keyMap, handlers, focused, attach, ...props} = this.props;

    return (
      <FocusTrap {...props} onFocus={this.onFocus} onBlur={this.onBlur}>
        {children}
      </FocusTrap>
    );
  }

});

export default HotKeys;
<|endoftext|>


<commit_before>/*
pa.js
Author: Willie Lawrence
Email: cptx032 arroba gmail dot com
*/
var PA_TOAST_BG = null;
var PA_TOAST_TEXT = null;
/*
returns a div with the toast
*/
function pa_get_toast_element(message) {
	var fill = document.createElement('div');
	fill.id = 'pa_toast_bg';
	var s_b = fill.style;
	s_b.backgroundColor = '#ffffff';
	var bg_pa = {
		id: 'pa_toast_bg',
		width: 1.0, height: 1.0, left: 0.0, right: 0.0
	};
	s_b.transition = 'opacity 1s';
	document.body.appendChild( fill );
	pa_add( bg_pa );

	var bg = document.createElement('div');
	bg.id = 'pa_toast';
	var s = bg.style;
	s.color = '#000000';
	s.opacity = 0;
	s.textAlign = 'center';
	s.transition = 'opacity 1s'
	bg.innerHTML = message;
	document.body.appendChild( bg );
	var pa_dict = {
		id: 'pa_toast',
		width: 1.0,
		center_vertical: true,
		fontSize: 0.05
	};
	pa_add( pa_dict );
}

function pa_show_toast() {
	PA_TOAST_BG.style.zIndex = 9999;
	PA_TOAST_TEXT.style.zIndex = 10000;

	PA_TOAST_TEXT.style.opacity = 1.0;
	PA_TOAST_BG.style.opacity = 1.0;
}

function pa_hide_toast() {
	PA_TOAST_TEXT.style.opacity = 0.0;
	PA_TOAST_BG.style.opacity = 0.0;
	setTimeout(function() {
		PA_TOAST_TEXT.style.zIndex = -1;
		PA_TOAST_BG.style.zIndex = -1;
	}, 1000);
}

/*
change the colors of toast
*/
function pa_toast_set_style(bg, fg) {
	PA_TOAST_TEXT.style.backgroundColor = bg;
	PA_TOAST_TEXT.style.color = fg;

	PA_TOAST_BG.style.backgroundColor = bg;
	PA_TOAST_BG.style.color = fg;
}

/*
Show a toast
*/
function pa_toast(message, msecs, bg, fg) {
	if (_('pa_toast') == null) {
		pa_get_toast_element(message);
		PA_TOAST_BG = _('pa_toast_bg');
		PA_TOAST_TEXT = _('pa_toast');
	}
	PA_TOAST_TEXT.innerHTML = message;
	pa_toast_set_style(bg, fg);
	pa_show_toast();
	if (msecs > 0) {
		setTimeout(function() {
			pa_hide_toast();
		}, msecs);
	}
}<commit_msg>add end function<commit_after>/*
pa.js
Author: Willie Lawrence
Email: cptx032 arroba gmail dot com
*/
var PA_TOAST_BG = null;
var PA_TOAST_TEXT = null;
/*
returns a div with the toast
*/
function pa_get_toast_element(message) {
	var fill = document.createElement('div');
	fill.id = 'pa_toast_bg';
	var s_b = fill.style;
	s_b.backgroundColor = '#ffffff';
	var bg_pa = {
		id: 'pa_toast_bg',
		width: 1.0, height: 1.0, left: 0.0, right: 0.0
	};
	s_b.transition = 'opacity 1s';
	document.body.appendChild( fill );
	pa_add( bg_pa );

	var bg = document.createElement('div');
	bg.id = 'pa_toast';
	var s = bg.style;
	s.color = '#000000';
	s.opacity = 0;
	s.textAlign = 'center';
	s.transition = 'opacity 1s'
	bg.innerHTML = message;
	document.body.appendChild( bg );
	var pa_dict = {
		id: 'pa_toast',
		width: 1.0,
		center_vertical: true,
		fontSize: 0.07
	};
	pa_add( pa_dict );
}

function pa_show_toast() {
	PA_TOAST_BG.style.zIndex = 9999;
	PA_TOAST_TEXT.style.zIndex = 10000;

	PA_TOAST_TEXT.style.opacity = 1.0;
	PA_TOAST_BG.style.opacity = 1.0;
}

function pa_hide_toast( end_function ) {
	PA_TOAST_TEXT.style.opacity = 0.0;
	PA_TOAST_BG.style.opacity = 0.0;
	setTimeout(function() {
		PA_TOAST_TEXT.style.zIndex = -1;
		PA_TOAST_BG.style.zIndex = -1;
		if (end_function) {
			end_function();
		}
	}, 1000);
}

/*
change the colors of toast
*/
function pa_toast_set_style(bg, fg) {
	PA_TOAST_TEXT.style.color = fg;

	PA_TOAST_BG.style.backgroundColor = bg;
	PA_TOAST_BG.style.color = fg;
}

/*
Show a toast
*/
function pa_toast(message, msecs, bg, fg, end_function) {
	if (_('pa_toast') == null) {
		pa_get_toast_element(message);
		PA_TOAST_BG = _('pa_toast_bg');
		PA_TOAST_TEXT = _('pa_toast');
	}
	PA_TOAST_TEXT.innerHTML = message;
	pa_toast_set_style(bg, fg);
	pa_show_toast();
	if (msecs > 0) {
		setTimeout(function() {
			pa_hide_toast( end_function );
		}, msecs);
	}
}<|endoftext|>


<commit_before>'use babel';

import { observable, autorun, computed, action } from 'mobx';
import untildify from 'untildify';
import projectUtil from 'atom-project-util';
import FileStore from './stores/FileStore';
import GitStore from './stores/GitStore';
import Settings from './Settings';
import Project from './models/Project';

class Manager {
  @observable projects = [];
  @observable activePaths = [];

  @computed get activeProject() {
    if (this.activePaths.length === 0) {
      return null;
    }

    return this.projects.find(project => project.rootPath === this.activePaths[0]);
  }

  constructor() {
    this.gitStore = new GitStore();
    this.fileStore = new FileStore();
    this.settings = new Settings();

    this.fetchProjects();

    atom.config.observe('project-manager.includeGitRepositories', (include) => {
      if (include) {
        this.gitStore.fetch();
      } else {
        this.gitStore.empty();
      }
    });

    autorun(() => {
      for (const fileProp of this.fileStore.data) {
        this.addProject(fileProp);
      }
    });

    autorun(() => {
      for (const gitProp of this.gitStore.data) {
        this.addProject(gitProp);
      }
    });

    autorun(() => {
      if (this.activeProject) {
        this.settings.load(this.activeProject.settings);
      }
    });

    this.activePaths = atom.project.getPaths();
    atom.project.onDidChangePaths(() => {
      this.activePaths = atom.project.getPaths();
      const activePaths = atom.project.getPaths();

      if (this.activeProject && this.activeProject.rootPath === activePaths[0]) {
        if (this.activeProject.paths.length !== activePaths.length) {
          this.activeProject.updateProps({ paths: activePaths });
          this.saveProjects();
        }
      }
    });
  }

  /**
   * Create or Update a project.
   *
   * Props coming from file goes before any other source.
   */
  @action addProject(props) {
    const foundProject = this.projects.find(project => {
      const projectRootPath = project.rootPath.toLowerCase();
      const propsRootPath = untildify(props.paths[0].toLowerCase());
      return projectRootPath === propsRootPath;
    });

    if (!foundProject) {
      const newProject = new Project(props);
      this.projects.push(newProject);
    } else {
      if (foundProject.source === 'file' && props.source === 'file') {
        foundProject.updateProps(props);
      }

      if (props.source === 'file' || typeof props.source === 'undefined') {
        foundProject.updateProps(props);
      }
    }
  }

  fetchProjects() {
    this.fileStore.fetch();

    if (atom.config.get('project-manager.includeGitRepositories')) {
      this.gitStore.fetch();
    }
  }

  open(project, openInSameWindow = false) {
    if (this.isProject(project)) {
      const { devMode } = project.getProps();

      if (openInSameWindow) {
        projectUtil.switch(project.paths);
      } else {
        atom.open({
          devMode,
          pathsToOpen: project.paths,
        });
      }
    }
  }

  saveProject(props) {
    let propsToSave = props;
    if (this.isProject(props)) {
      propsToSave = props.getProps();
    }
    this.addProject({ ...propsToSave, source: 'file' });
    this.saveProjects();
  }

  saveProjects() {
    const projects = this.projects.filter(project => project.props.source === 'file');
    const arr = [];

    for (const project of projects) {
      const props = project.getChangedProps();
      delete props.source;
      arr.push(props);
    }

    this.fileStore.store(arr);
  }

  isProject(project) {
    if (project instanceof Project) {
      return true;
    }

    return false;
  }
}

const manager = new Manager();
export default manager;
<commit_msg>Fix case where home path isn't lowercased<commit_after>'use babel';

import { observable, autorun, computed, action } from 'mobx';
import untildify from 'untildify';
import projectUtil from 'atom-project-util';
import FileStore from './stores/FileStore';
import GitStore from './stores/GitStore';
import Settings from './Settings';
import Project from './models/Project';

class Manager {
  @observable projects = [];
  @observable activePaths = [];

  @computed get activeProject() {
    if (this.activePaths.length === 0) {
      return null;
    }

    return this.projects.find(project => project.rootPath === this.activePaths[0]);
  }

  constructor() {
    this.gitStore = new GitStore();
    this.fileStore = new FileStore();
    this.settings = new Settings();

    this.fetchProjects();

    atom.config.observe('project-manager.includeGitRepositories', (include) => {
      if (include) {
        this.gitStore.fetch();
      } else {
        this.gitStore.empty();
      }
    });

    autorun(() => {
      for (const fileProp of this.fileStore.data) {
        this.addProject(fileProp);
      }
    });

    autorun(() => {
      for (const gitProp of this.gitStore.data) {
        this.addProject(gitProp);
      }
    });

    autorun(() => {
      if (this.activeProject) {
        this.settings.load(this.activeProject.settings);
      }
    });

    this.activePaths = atom.project.getPaths();
    atom.project.onDidChangePaths(() => {
      this.activePaths = atom.project.getPaths();
      const activePaths = atom.project.getPaths();

      if (this.activeProject && this.activeProject.rootPath === activePaths[0]) {
        if (this.activeProject.paths.length !== activePaths.length) {
          this.activeProject.updateProps({ paths: activePaths });
          this.saveProjects();
        }
      }
    });
  }

  /**
   * Create or Update a project.
   *
   * Props coming from file goes before any other source.
   */
  @action addProject(props) {
    const foundProject = this.projects.find(project => {
      const projectRootPath = project.rootPath.toLowerCase();
      const propsRootPath = untildify(props.paths[0]).toLowerCase();
      return projectRootPath === propsRootPath;
    });

    if (!foundProject) {
      const newProject = new Project(props);
      this.projects.push(newProject);
    } else {
      if (foundProject.source === 'file' && props.source === 'file') {
        foundProject.updateProps(props);
      }

      if (props.source === 'file' || typeof props.source === 'undefined') {
        foundProject.updateProps(props);
      }
    }
  }

  fetchProjects() {
    this.fileStore.fetch();

    if (atom.config.get('project-manager.includeGitRepositories')) {
      this.gitStore.fetch();
    }
  }

  open(project, openInSameWindow = false) {
    if (this.isProject(project)) {
      const { devMode } = project.getProps();

      if (openInSameWindow) {
        projectUtil.switch(project.paths);
      } else {
        atom.open({
          devMode,
          pathsToOpen: project.paths,
        });
      }
    }
  }

  saveProject(props) {
    let propsToSave = props;
    if (this.isProject(props)) {
      propsToSave = props.getProps();
    }
    this.addProject({ ...propsToSave, source: 'file' });
    this.saveProjects();
  }

  saveProjects() {
    const projects = this.projects.filter(project => project.props.source === 'file');
    const arr = [];

    for (const project of projects) {
      const props = project.getChangedProps();
      delete props.source;
      arr.push(props);
    }

    this.fileStore.store(arr);
  }

  isProject(project) {
    if (project instanceof Project) {
      return true;
    }

    return false;
  }
}

const manager = new Manager();
export default manager;
<|endoftext|>


<commit_before>import Node from '../Node/Node.js';
import Stack from '../Stack/Stack.js';
import Queue from '../Queue/Queue.js';
import Tree from '../Tree/Tree.js';

export default function() {

  let tree = new Tree([
        new Node('a'),
        new Node('b'),
        new Node('c'),
        new Node('d'),
        new Node('e'),
        new Node('f'),
        new Node('g'),
        new Node('h'),
        new Node('i'),
        new Node('j'),
        new Node('k'),
        new Node('l')
      ]);

  console.log('%c*** Tree ***', 'color: blue;');
  tree.print();

  console.log('%c\n*** Search "k" ***', 'color: blue;');

  let stepNeeded = 1;
  depthFirstSearch('k', tree.data().root);
  console.log(' ');

  depthFirstSearchIterative('k', tree.data().root);
  console.log(' ');
}
<commit_msg>Remove example_bfs because is included in example_dfs_bfs<commit_after><|endoftext|>


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

var Emitter = require('events').EventEmitter
  , path = require('path')
  , dirname = path.dirname
  , basename = path.basename
  , extname = path.extname
  , join = path.join
  , mkdir = require('mkdirp').mkdirp
  , request = require('superagent')
  , debug = require('debug')('component:installer')
  , Batch = require('batch')
  , fs = require('fs');

/**
 * Expose installer.
 */

module.exports = Package;

/**
 * Initialize a new `Package` with
 * the given `pkg` name and `version`.
 *
 * Options:
 *
 *  - `dest` destination directory
 *  - `force` installation when previously installed
 *
 * @param {String} pkg
 * @param {String} version
 * @param {Object} options
 * @api private
 */

function Package(pkg, version, options) {
  options = options || {};
  if ('*' == version) version = 'master';
  debug('installing %s@%s %j', pkg, version, options);
  if (!pkg) throw new Error('pkg required');
  if (!version) throw new Error('version required');
  this.name = pkg;
  this.dest = options.dest || 'components';
  this.force = !! options.force;
  this.version = version;
}

/**
 * Inherit from `Emitter.prototype`.
 */

Package.prototype.__proto__ = Emitter.prototype;

/**
 * Return dirname for this package.
 * For example "component/dialog"
 * becomes "component-dialog".
 *
 * @return {String}
 * @api private
 */

Package.prototype.dirname = function(){
  return join(this.dest, this.name.split('/').join('-'));
};

/**
 * Join `path` to this package's dirname.
 *
 * @param {String} path
 * @return {String}
 * @api private
 */

Package.prototype.join = function(path){
  return join(this.dirname(), path);
};

/**
 * Return URL to `file`.
 *
 * @param {String} file
 * @return {String}
 * @api private
 */

Package.prototype.url = function(file){
  return 'https://raw.github.com/' + this.name + '/' + this.version + '/' + file;
};

/**
 * Get local json if the component is installed
 * and callback `fn(err, obj)`.
 *
 * @param {Function} fn
 * @api private
 */

Package.prototype.getLocalJSON = function(fn){
  fs.readFile(this.join('component.json'), 'utf8', function(err, json){
    if (err) return fn(err);
    try {
      json = JSON.parse(json);
    } catch (err) {
      return fn(err);
    }
    fn(null, json);
  });
};

/**
 * Get component.json and callback `fn(err, obj)`.
 *
 * @param {Function} fn
 * @api private
 */

Package.prototype.getJSON = function(fn){
  var self = this;
  var url = this.url('component.json');
  debug('fetching %s', url);
  request.get(url, function(res){
    if (res.ok) {
      debug('got %s', url);
      try {
        var json = JSON.parse(res.text);
      } catch (err) {
        return fn(err);
      }
      fn(null, json);
    } else {
      fn(new Error('failed to fetch ' + url));
    }
  });
};

/**
 * Fetch `files` and write them to disk and callback `fn(err)`.
 *
 * @param {Array} files
 * @param {Function} fn
 * @api private
 */

Package.prototype.getFiles = function(files, fn){
  var self = this;
  var batch = new Batch;

  files.forEach(function(file){
    batch.push(function(done){
      var url = self.url(file);
      debug('fetching %s', url);
      self.emit('file', file, url);
      var out = fs.createWriteStream(self.join(file));
      request
      .get(url)
      .buffer(false)
      .end(function(res){
        res.pipe(out);
        res.on('error', done);
        res.on('end', done);
      });
    });
  });

  batch.end(fn);
};

/**
 * Write `file` with `str` contents to disk and callback `fn(err)`.
 *
 * @param {String} file
 * @param {String} str
 * @param {Function} fn
 * @api private
 */

Package.prototype.writeFile = function(file, str, fn){
  file = this.join(file);
  debug('write %s', file);
  fs.writeFile(file, str, fn);
};

/**
 * Install `deps` and callback `fn()`.
 *
 * @param {Array} deps
 * @param {Function} fn
 * @api private
 */

Package.prototype.getDependencies = function(deps, fn){
  var self = this;
  var batch = new Batch;

  Object.keys(deps).forEach(function(name){
    var version = deps[name];
    debug('dep %s@%s', name, version);
    batch.push(function(done){
      var pkg = new Package(name, version, {
        dest: self.dest,
        force: self.force
      });
      self.emit('dep', pkg);
      pkg.on('end', done);
      pkg.install();
    });
  });

  batch.end(fn);
};

/**
 * Check if the component exists already,
 * otherwise install it for realllll.
 *
 * @api public
 */

Package.prototype.install = function(){
  var self = this;
  var name = this.name;

  if (!~name.indexOf('/')) {
    return this.emit('error', new Error('invalid component name "' + name + '"'));
  }

  this.getLocalJSON(function(err, json){
    if (err && err.code == 'ENOENT') {
      self.reallyInstall();
    } else if (err) {
      self.emit('error', err);
    } else if (!self.force) {
      self.emit('exists', self);
    } else {
      self.reallyInstall();
    }
  });
};

/**
 * Really install the component.
 *
 * @api public
 */

Package.prototype.reallyInstall = function(){
  var self = this;
  var batch = new Batch;
  this.getJSON(function(err, json){
    if (err) return self.emit('error', err);

    var files = [];
    if (json.scripts) files = files.concat(json.scripts);
    if (json.styles) files = files.concat(json.styles);
    if (json.templates) files = files.concat(json.templates);
    json.repo = json.repo || 'https://github.com/' + self.name;

    if (json.dependencies) {
      batch.push(function(done){
        self.getDependencies(json.dependencies, done);
      });
    }

    batch.push(function(done){
      // TODO: dont duplicate mkdir twice here
      mkdir(self.dirname(), function(err){
        json = JSON.stringify(json, null, 2);
        self.writeFile('component.json', json, done);
      });
    });

    batch.push(function(done){
      mkdir(self.dirname(), function(err){
        self.getFiles(files, done);
      });
    });

    batch.end(function(err){
      if (err) return self.emit('error', err);
      self.emit('end');
    });
  });
};
<commit_msg>add friendlier dns lookup error message<commit_after>
/**
 * Module dependencies.
 */

var Emitter = require('events').EventEmitter
  , path = require('path')
  , dirname = path.dirname
  , basename = path.basename
  , extname = path.extname
  , join = path.join
  , mkdir = require('mkdirp').mkdirp
  , request = require('superagent')
  , debug = require('debug')('component:installer')
  , Batch = require('batch')
  , fs = require('fs');

/**
 * Expose installer.
 */

module.exports = Package;

/**
 * Initialize a new `Package` with
 * the given `pkg` name and `version`.
 *
 * Options:
 *
 *  - `dest` destination directory
 *  - `force` installation when previously installed
 *
 * @param {String} pkg
 * @param {String} version
 * @param {Object} options
 * @api private
 */

function Package(pkg, version, options) {
  options = options || {};
  if ('*' == version) version = 'master';
  debug('installing %s@%s %j', pkg, version, options);
  if (!pkg) throw new Error('pkg required');
  if (!version) throw new Error('version required');
  this.name = pkg;
  this.dest = options.dest || 'components';
  this.force = !! options.force;
  this.version = version;
}

/**
 * Inherit from `Emitter.prototype`.
 */

Package.prototype.__proto__ = Emitter.prototype;

/**
 * Return dirname for this package.
 * For example "component/dialog"
 * becomes "component-dialog".
 *
 * @return {String}
 * @api private
 */

Package.prototype.dirname = function(){
  return join(this.dest, this.name.split('/').join('-'));
};

/**
 * Join `path` to this package's dirname.
 *
 * @param {String} path
 * @return {String}
 * @api private
 */

Package.prototype.join = function(path){
  return join(this.dirname(), path);
};

/**
 * Return URL to `file`.
 *
 * @param {String} file
 * @return {String}
 * @api private
 */

Package.prototype.url = function(file){
  return 'https://raw.github.com/' + this.name + '/' + this.version + '/' + file;
};

/**
 * Get local json if the component is installed
 * and callback `fn(err, obj)`.
 *
 * @param {Function} fn
 * @api private
 */

Package.prototype.getLocalJSON = function(fn){
  fs.readFile(this.join('component.json'), 'utf8', function(err, json){
    if (err) return fn(err);
    try {
      json = JSON.parse(json);
    } catch (err) {
      return fn(err);
    }
    fn(null, json);
  });
};

/**
 * Get component.json and callback `fn(err, obj)`.
 *
 * @param {Function} fn
 * @api private
 */

Package.prototype.getJSON = function(fn){
  var self = this;
  var url = this.url('component.json');

  debug('fetching %s', url);
  var req = request.get(url, function(res){
    if (res.ok) {
      debug('got %s', url);
      try {
        var json = JSON.parse(res.text);
      } catch (err) {
        return fn(err);
      }
      fn(null, json);
    } else {
      fn(new Error('failed to fetch ' + url));
    }
  });

  req.on('error', function(err){
    if ('getaddrinfo' == err.syscall) err.message = 'dns lookup failed';
    fn(err);
  });
};

/**
 * Fetch `files` and write them to disk and callback `fn(err)`.
 *
 * @param {Array} files
 * @param {Function} fn
 * @api private
 */

Package.prototype.getFiles = function(files, fn){
  var self = this;
  var batch = new Batch;

  files.forEach(function(file){
    batch.push(function(done){
      var url = self.url(file);
      debug('fetching %s', url);
      self.emit('file', file, url);
      var out = fs.createWriteStream(self.join(file));
      request
      .get(url)
      .buffer(false)
      .end(function(res){
        res.pipe(out);
        res.on('error', done);
        res.on('end', done);
      });
    });
  });

  batch.end(fn);
};

/**
 * Write `file` with `str` contents to disk and callback `fn(err)`.
 *
 * @param {String} file
 * @param {String} str
 * @param {Function} fn
 * @api private
 */

Package.prototype.writeFile = function(file, str, fn){
  file = this.join(file);
  debug('write %s', file);
  fs.writeFile(file, str, fn);
};

/**
 * Install `deps` and callback `fn()`.
 *
 * @param {Array} deps
 * @param {Function} fn
 * @api private
 */

Package.prototype.getDependencies = function(deps, fn){
  var self = this;
  var batch = new Batch;

  Object.keys(deps).forEach(function(name){
    var version = deps[name];
    debug('dep %s@%s', name, version);
    batch.push(function(done){
      var pkg = new Package(name, version, {
        dest: self.dest,
        force: self.force
      });
      self.emit('dep', pkg);
      pkg.on('end', done);
      pkg.install();
    });
  });

  batch.end(fn);
};

/**
 * Check if the component exists already,
 * otherwise install it for realllll.
 *
 * @api public
 */

Package.prototype.install = function(){
  var self = this;
  var name = this.name;

  if (!~name.indexOf('/')) {
    return this.emit('error', new Error('invalid component name "' + name + '"'));
  }

  this.getLocalJSON(function(err, json){
    if (err && err.code == 'ENOENT') {
      self.reallyInstall();
    } else if (err) {
      self.emit('error', err);
    } else if (!self.force) {
      self.emit('exists', self);
    } else {
      self.reallyInstall();
    }
  });
};

/**
 * Really install the component.
 *
 * @api public
 */

Package.prototype.reallyInstall = function(){
  var self = this;
  var batch = new Batch;
  this.getJSON(function(err, json){
    if (err) return self.emit('error', err);

    var files = [];
    if (json.scripts) files = files.concat(json.scripts);
    if (json.styles) files = files.concat(json.styles);
    if (json.templates) files = files.concat(json.templates);
    json.repo = json.repo || 'https://github.com/' + self.name;

    if (json.dependencies) {
      batch.push(function(done){
        self.getDependencies(json.dependencies, done);
      });
    }

    batch.push(function(done){
      // TODO: dont duplicate mkdir twice here
      mkdir(self.dirname(), function(err){
        json = JSON.stringify(json, null, 2);
        self.writeFile('component.json', json, done);
      });
    });

    batch.push(function(done){
      mkdir(self.dirname(), function(err){
        self.getFiles(files, done);
      });
    });

    batch.end(function(err){
      if (err) return self.emit('error', err);
      self.emit('end');
    });
  });
};
<|endoftext|>


<commit_before>/**
 *  Point2D.js
 *  @module Point2D
 *  @copyright 2001-2019 Kevin Lindsey
 */

/**
 *  Point2D
 *
 *  @memberof module:kld-affine
 */
class Point2D {
    /**
     *  Point2D
     *
     *  @param {number} x
     *  @param {number} y
     *  @returns {module:kld-affine.Point2D}
     */
    constructor(x = 0, y = 0) {
        this.x = x;
        this.y = y;
    }

    /**
     *  clone
     *
     *  @returns {module:kld-affine.Point2D}
     */
    clone() {
        return new this.constructor(this.x, this.y);
    }

    /**
     *  add
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {module:kld-affine.Point2D}
     */
    add(that) {
        return new this.constructor(this.x + that.x, this.y + that.y);
    }

    /**
     *  subtract
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {module:kld-affine.Point2D}
     */
    subtract(that) {
        return new this.constructor(this.x - that.x, this.y - that.y);
    }

    /**
     *  multiply
     *
     *  @param {number} scalar
     *  @returns {module:kld-affine.Point2D}
     */
    multiply(scalar) {
        return new this.constructor(this.x * scalar, this.y * scalar);
    }

    /**
     *  divide
     *
     *  @param {number} scalar
     *  @returns {module:kld-affine.Point2D}
     */
    divide(scalar) {
        return new this.constructor(this.x / scalar, this.y / scalar);
    }

    /**
     *  equals
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {boolean}
     */
    equals(that) {
        return (this.x === that.x && this.y === that.y);
    }

    /**
     *  precisionEquals
     *
     *  @param {module:kld-affine.Point2D} that
     *  @param {number} precision
     *  @returns {boolean}
     */
    precisionEquals(that, precision) {
        return (
            Math.abs(this.x - that.x) < precision &&
            Math.abs(this.y - that.y) < precision
        );
    }

    // utility methods

    /**
     *  lerp
     *
     *  @param {module:kld-affine.Point2D} that
     *  @param {number} t
     *  @returns {module:kld-affine.Point2D}
     */
    lerp(that, t) {
        const omt = 1.0 - t;

        return new this.constructor(
            this.x * omt + that.x * t,
            this.y * omt + that.y * t
        );
    }

    /**
     *  distanceFrom
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {number}
     */
    distanceFrom(that) {
        const dx = this.x - that.x;
        const dy = this.y - that.y;

        return Math.sqrt(dx * dx + dy * dy);
    }

    /**
     *  min
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {number}
     */
    min(that) {
        return new this.constructor(
            Math.min(this.x, that.x),
            Math.min(this.y, that.y)
        );
    }

    /**
     *  max
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {number}
     */
    max(that) {
        return new this.constructor(
            Math.max(this.x, that.x),
            Math.max(this.y, that.y)
        );
    }

    /**
     *  transform
     *
     *  @param {module:kld-affine.Matrix2D} matrix
     *  @returns {module:kld-affine.Point2D}
     */
    transform(matrix) {
        return new this.constructor(
            matrix.a * this.x + matrix.c * this.y + matrix.e,
            matrix.b * this.x + matrix.d * this.y + matrix.f
        );
    }

    /**
     *  toString
     *
     *  @returns {string}
     */
    toString() {
        return `point(${this.x},${this.y})`;
    }
}

export default Point2D;
<commit_msg>fix return type of min and max<commit_after>/**
 *  Point2D.js
 *  @module Point2D
 *  @copyright 2001-2019 Kevin Lindsey
 */

/**
 *  Point2D
 *
 *  @memberof module:kld-affine
 */
class Point2D {
    /**
     *  Point2D
     *
     *  @param {number} x
     *  @param {number} y
     *  @returns {module:kld-affine.Point2D}
     */
    constructor(x = 0, y = 0) {
        this.x = x;
        this.y = y;
    }

    /**
     *  clone
     *
     *  @returns {module:kld-affine.Point2D}
     */
    clone() {
        return new this.constructor(this.x, this.y);
    }

    /**
     *  add
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {module:kld-affine.Point2D}
     */
    add(that) {
        return new this.constructor(this.x + that.x, this.y + that.y);
    }

    /**
     *  subtract
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {module:kld-affine.Point2D}
     */
    subtract(that) {
        return new this.constructor(this.x - that.x, this.y - that.y);
    }

    /**
     *  multiply
     *
     *  @param {number} scalar
     *  @returns {module:kld-affine.Point2D}
     */
    multiply(scalar) {
        return new this.constructor(this.x * scalar, this.y * scalar);
    }

    /**
     *  divide
     *
     *  @param {number} scalar
     *  @returns {module:kld-affine.Point2D}
     */
    divide(scalar) {
        return new this.constructor(this.x / scalar, this.y / scalar);
    }

    /**
     *  equals
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {boolean}
     */
    equals(that) {
        return (this.x === that.x && this.y === that.y);
    }

    /**
     *  precisionEquals
     *
     *  @param {module:kld-affine.Point2D} that
     *  @param {number} precision
     *  @returns {boolean}
     */
    precisionEquals(that, precision) {
        return (
            Math.abs(this.x - that.x) < precision &&
            Math.abs(this.y - that.y) < precision
        );
    }

    // utility methods

    /**
     *  lerp
     *
     *  @param {module:kld-affine.Point2D} that
     *  @param {number} t
     *  @returns {module:kld-affine.Point2D}
     */
    lerp(that, t) {
        const omt = 1.0 - t;

        return new this.constructor(
            this.x * omt + that.x * t,
            this.y * omt + that.y * t
        );
    }

    /**
     *  distanceFrom
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {number}
     */
    distanceFrom(that) {
        const dx = this.x - that.x;
        const dy = this.y - that.y;

        return Math.sqrt(dx * dx + dy * dy);
    }

    /**
     *  min
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {module:kld-affine.Point2D}
     */
    min(that) {
        return new this.constructor(
            Math.min(this.x, that.x),
            Math.min(this.y, that.y)
        );
    }

    /**
     *  max
     *
     *  @param {module:kld-affine.Point2D} that
     *  @returns {module:kld-affine.Point2D}
     */
    max(that) {
        return new this.constructor(
            Math.max(this.x, that.x),
            Math.max(this.y, that.y)
        );
    }

    /**
     *  transform
     *
     *  @param {module:kld-affine.Matrix2D} matrix
     *  @returns {module:kld-affine.Point2D}
     */
    transform(matrix) {
        return new this.constructor(
            matrix.a * this.x + matrix.c * this.y + matrix.e,
            matrix.b * this.x + matrix.d * this.y + matrix.f
        );
    }

    /**
     *  toString
     *
     *  @returns {string}
     */
    toString() {
        return `point(${this.x},${this.y})`;
    }
}

export default Point2D;
<|endoftext|>


<commit_before>var Image = require('./Image.js');

function ImagePreloader(parent) {
    "use strict";
    this.parent = parent;
    this.sources = [];
    this.images = [];
    this.loaded = 0;
    this.deepSearch = true;
}

ImagePreloader.prototype.getImageSrcs = function (element) {
    "use strict";
    this.sources = [];

    if (typeof element !== "undefined") {
        this.findImageInElement(element);

        if (this.deepSearch === true) {
            var elements = element.querySelectorAll("*");
            for (var i = 0; i < elements.length; i++) {
                if (elements[i].tagName !== "SCRIPT") {
                    this.findImageInElement(elements[i]);
                }
            }
        }
    }

    return this.sources;
};

ImagePreloader.prototype.findAndPreload = function (element) {
    "use strict";
    if (typeof element === "undefined") {
        return;
    }

    this.sources = this.getImageSrcs(element);

    for (var i = 0; i < this.sources.length; i++) {
        var image = new Image(this.sources[i]);
        image.preload(this.imageLoaded.bind(this));
        this.images.push(image);
    }
};

ImagePreloader.prototype.imageLoaded = function () {
    "use strict";
    this.loaded++;

    this.updateProgress();
};

ImagePreloader.prototype.updateProgress = function () {
    "use strict";
    this.parent.updateProgress(this.loaded, this.sources.length);
};

ImagePreloader.prototype.findImageInElement = function (element) {
    "use strict";
    var urlType = this.determineUrlAndType(element);

    //skip if gradient
    if (!this.hasGradient(urlType.url)) {
        //remove unwanted chars
        urlType.url = this.stripUrl(urlType.url);

        //split urls
        var urls = urlType.url.split(", ");

        for (var i = 0; i < urls.length; i++) {
            if (this.validUrl(urls[i]) && this.urlIsNew(urls[i])) {
                var extra = "";

                if (this.isIE() || this.isOpera()){
                    //filthy always no cache for IE, sorry peeps!
                    extra = "?rand=" + Math.random();
                }

                //add image to found list
                this.sources.push(urls[i] + extra);
            }
        }
    }
};

ImagePreloader.prototype.determineUrlAndType = function (element) {
    "use strict";
    var url = "";
    var type = "normal";

    if (element.style.backgroundImage !== "") {
        //if object has background image
        url = element.style.backgroundImage;
        type = "background";
    } else if (typeof(element.getAttribute("src")) !== "undefined" && element.nodeName.toLowerCase() === "img") {
        //if is img and has src
        url = element.getAttribute("src");
    }

    return {
        url: url,
        type: type
    };
};

ImagePreloader.prototype.hasGradient = function (url) {
    "use strict";
    return url.indexOf("gradient(") !== -1;
};

ImagePreloader.prototype.stripUrl = function (url) {
    "use strict";
    url = url.replace(/url\(\"/g, "");
    url = url.replace(/url\(/g, "");
    url = url.replace(/\"\)/g, "");
    url = url.replace(/\)/g, "");

    return url;
};

ImagePreloader.prototype.validUrl = function (url) {
    "use strict";
    if (url.length > 0 && !url.match(/^(data:)/i)) {
        return true;
    } else {
        return false;
    }
};

ImagePreloader.prototype.urlIsNew = function (url) {
    "use strict";
    return this.sources.indexOf(url) === -1;
};

ImagePreloader.prototype.isIE = function () {
    "use strict";
    return navigator.userAgent.match(/msie/i);
};

ImagePreloader.prototype.isOpera = function () {
    "use strict";
    return navigator.userAgent.match(/Opera/i);
};

module.exports = ImagePreloader;<commit_msg>True background image detection<commit_after>var Image = require('./Image.js');

function ImagePreloader(parent) {
    "use strict";
    this.parent = parent;
    this.sources = [];
    this.images = [];
    this.loaded = 0;
    this.deepSearch = true;
}

ImagePreloader.prototype.getImageSrcs = function (element) {
    "use strict";
    this.sources = [];

    if (typeof element !== "undefined") {
        this.findImageInElement(element);

        if (this.deepSearch === true) {
            var elements = element.querySelectorAll("*");
            for (var i = 0; i < elements.length; i++) {
                if (elements[i].tagName !== "SCRIPT") {
                    this.findImageInElement(elements[i]);
                }
            }
        }
    }

    return this.sources;
};

ImagePreloader.prototype.findAndPreload = function (element) {
    "use strict";
    if (typeof element === "undefined") {
        return;
    }

    this.sources = this.getImageSrcs(element);

    for (var i = 0; i < this.sources.length; i++) {
        var image = new Image(this.sources[i]);
        image.preload(this.imageLoaded.bind(this));
        this.images.push(image);
    }
};

ImagePreloader.prototype.imageLoaded = function () {
    "use strict";
    this.loaded++;

    this.updateProgress();
};

ImagePreloader.prototype.updateProgress = function () {
    "use strict";
    this.parent.updateProgress(this.loaded, this.sources.length);
};

ImagePreloader.prototype.findImageInElement = function (element) {
    "use strict";
    var urlType = this.determineUrlAndType(element);

    //skip if gradient
    if (!this.hasGradient(urlType.url)) {
        //remove unwanted chars
        urlType.url = this.stripUrl(urlType.url);

        //split urls
        var urls = urlType.url.split(", ");

        for (var i = 0; i < urls.length; i++) {
            if (this.validUrl(urls[i]) && this.urlIsNew(urls[i])) {
                var extra = "";

                if (this.isIE() || this.isOpera()){
                    //filthy always no cache for IE, sorry peeps!
                    extra = "?rand=" + Math.random();
                }

                //add image to found list
                this.sources.push(urls[i] + extra);
            }
        }
    }
};

ImagePreloader.prototype.determineUrlAndType = function (element) {
    "use strict";
    var url = "";
    var type = "normal";
    var style = element.currentStyle || window.getComputedStyle(element, null);

    if (style.backgroundImage !== "") {
        //if object has background image
        url = style.backgroundImage;
        type = "background";
    } else if (typeof(element.getAttribute("src")) !== "undefined" && element.nodeName.toLowerCase() === "img") {
        //if is img and has src
        url = element.getAttribute("src");
    }

    return {
        url: url,
        type: type
    };
};

ImagePreloader.prototype.hasGradient = function (url) {
    "use strict";
    return url.indexOf("gradient(") !== -1;
};

ImagePreloader.prototype.stripUrl = function (url) {
    "use strict";
    url = url.replace(/url\(\"/g, "");
    url = url.replace(/url\(/g, "");
    url = url.replace(/\"\)/g, "");
    url = url.replace(/\)/g, "");

    return url;
};

ImagePreloader.prototype.validUrl = function (url) {
    "use strict";
    if (url.length > 0 && !url.match(/^(data:)/i)) {
        return true;
    } else {
        return false;
    }
};

ImagePreloader.prototype.urlIsNew = function (url) {
    "use strict";
    return this.sources.indexOf(url) === -1;
};

ImagePreloader.prototype.isIE = function () {
    "use strict";
    return navigator.userAgent.match(/msie/i);
};

ImagePreloader.prototype.isOpera = function () {
    "use strict";
    return navigator.userAgent.match(/Opera/i);
};

module.exports = ImagePreloader;<|endoftext|>


<commit_before>/*jslint node: true */
"use strict";
var _ = require('lodash');
require('./enforce_singleton.js');

var arrQueuedJobs = [];
var arrLockedKeyArrays = [];

function getCountOfQueuedJobs(){
	return arrQueuedJobs.length;
}

function getCountOfLocks(){
	return arrLockedKeyArrays.length;
}

function isAnyOfKeysLocked(arrKeys){
	for (var i=0; i<arrLockedKeyArrays.length; i++){
		var arrLockedKeys = arrLockedKeyArrays[i];
		for (var j=0; j<arrLockedKeys.length; j++){
			if (arrKeys.indexOf(arrLockedKeys[j]) !== -1)
				return true;
		}
	}
	return false;
}

function release(arrKeys){
	for (var i=0; i<arrLockedKeyArrays.length; i++){
		if (_.isEqual(arrKeys, arrLockedKeyArrays[i])){
			arrLockedKeyArrays.splice(i, 1);
			return;
		}
	}
}

function exec(arrKeys, proc, next_proc){
	arrLockedKeyArrays.push(arrKeys);
	console.log("lock acquired", arrKeys);
	var bLocked = true;
	proc(function(){
		if (!bLocked)
			throw Error("double unlock?");
		bLocked = false;
		release(arrKeys);
		console.log("lock released", arrKeys);
		if (next_proc)
			next_proc.apply(next_proc, arguments);
		handleQueue();
	});
}

function handleQueue(){
	console.log("handleQueue "+arrQueuedJobs.length+" items");
	for (var i=0; i<arrQueuedJobs.length; i++){
		var job = arrQueuedJobs[i];
		if (isAnyOfKeysLocked(job.arrKeys))
			continue;
		arrQueuedJobs.splice(i, 1); // do it before exec as exec can trigger another job added, another lock unlocked, another handleQueue called
		console.log("starting job held by keys", job.arrKeys);
		exec(job.arrKeys, job.proc, job.next_proc);
		i--; // we've just removed one item
	}
	console.log("handleQueue done "+arrQueuedJobs.length+" items");
}

function lock(arrKeys, proc, next_proc){
	if (arguments.length === 1)
		return new Promise(resolve => lock(arrKeys, resolve));
	if (isAnyOfKeysLocked(arrKeys)){
		console.log("queuing job held by keys", arrKeys);
		arrQueuedJobs.push({arrKeys: arrKeys, proc: proc, next_proc: next_proc, ts:Date.now()});
	}
	else
		exec(arrKeys, proc, next_proc);
}

function lockOrSkip(arrKeys, proc, next_proc){
	if (arguments.length === 1)
		return new Promise(resolve => lockOrSkip(arrKeys, resolve));
	if (isAnyOfKeysLocked(arrKeys)){
		console.log("skipping job held by keys", arrKeys);
		if (next_proc)
			next_proc();
	}
	else
		exec(arrKeys, proc, next_proc);
}

function checkForDeadlocks(){
	for (var i=0; i<arrQueuedJobs.length; i++){
		var job = arrQueuedJobs[i];
		if (Date.now() - job.ts > 30*1000)
			throw Error("possible deadlock on job "+require('util').inspect(job)+",\nproc:"+job.proc.toString()+" \nall jobs: "+require('util').inspect(arrQueuedJobs, {depth: null}));
	}
}

// long running locks are normal in multisig scenarios
//setInterval(checkForDeadlocks, 1000);

setInterval(function(){
	console.log("queued jobs: "+JSON.stringify(arrQueuedJobs.map(function(job){ return job.arrKeys; }))+", locked keys: "+JSON.stringify(arrLockedKeyArrays));
}, 10000);

exports.lock = lock;
exports.lockOrSkip = lockOrSkip;
exports.isAnyOfKeysLocked = isAnyOfKeysLocked;
exports.getCountOfQueuedJobs = getCountOfQueuedJobs;
exports.getCountOfLocks = getCountOfLocks;

/*
function test(key){
	var loc = "localvar"+key;
	lock(
		[key],
		function(cb){
			console.log("doing "+key);
			setTimeout(function(){
				console.log("done "+key);
				cb("arg1", "arg2");
			}, 1000)
		},
		function(arg1, arg2){
			console.log("got "+arg1+", "+arg2+", loc="+loc);
		}
	);
}

test("key1");
test("key2");
*/
<commit_msg>single-key locks using string keys<commit_after>/*jslint node: true */
"use strict";
var _ = require('lodash');
require('./enforce_singleton.js');

var arrQueuedJobs = [];
var arrLockedKeyArrays = [];

function getCountOfQueuedJobs(){
	return arrQueuedJobs.length;
}

function getCountOfLocks(){
	return arrLockedKeyArrays.length;
}

function isAnyOfKeysLocked(arrKeys){
	for (var i=0; i<arrLockedKeyArrays.length; i++){
		var arrLockedKeys = arrLockedKeyArrays[i];
		for (var j=0; j<arrLockedKeys.length; j++){
			if (arrKeys.indexOf(arrLockedKeys[j]) !== -1)
				return true;
		}
	}
	return false;
}

function release(arrKeys){
	for (var i=0; i<arrLockedKeyArrays.length; i++){
		if (_.isEqual(arrKeys, arrLockedKeyArrays[i])){
			arrLockedKeyArrays.splice(i, 1);
			return;
		}
	}
}

function exec(arrKeys, proc, next_proc){
	arrLockedKeyArrays.push(arrKeys);
	console.log("lock acquired", arrKeys);
	var bLocked = true;
	proc(function(){
		if (!bLocked)
			throw Error("double unlock?");
		bLocked = false;
		release(arrKeys);
		console.log("lock released", arrKeys);
		if (next_proc)
			next_proc.apply(next_proc, arguments);
		handleQueue();
	});
}

function handleQueue(){
	console.log("handleQueue "+arrQueuedJobs.length+" items");
	for (var i=0; i<arrQueuedJobs.length; i++){
		var job = arrQueuedJobs[i];
		if (isAnyOfKeysLocked(job.arrKeys))
			continue;
		arrQueuedJobs.splice(i, 1); // do it before exec as exec can trigger another job added, another lock unlocked, another handleQueue called
		console.log("starting job held by keys", job.arrKeys);
		exec(job.arrKeys, job.proc, job.next_proc);
		i--; // we've just removed one item
	}
	console.log("handleQueue done "+arrQueuedJobs.length+" items");
}

function lock(arrKeys, proc, next_proc){
	if (arguments.length === 1)
		return new Promise(resolve => lock(arrKeys, resolve));
	if (typeof arrKeys === 'string')
		arrKeys = [arrKeys];
	if (isAnyOfKeysLocked(arrKeys)){
		console.log("queuing job held by keys", arrKeys);
		arrQueuedJobs.push({arrKeys: arrKeys, proc: proc, next_proc: next_proc, ts:Date.now()});
	}
	else
		exec(arrKeys, proc, next_proc);
}

function lockOrSkip(arrKeys, proc, next_proc){
	if (arguments.length === 1)
		return new Promise(resolve => lockOrSkip(arrKeys, resolve));
	if (typeof arrKeys === 'string')
		arrKeys = [arrKeys];
	if (isAnyOfKeysLocked(arrKeys)){
		console.log("skipping job held by keys", arrKeys);
		if (next_proc)
			next_proc();
	}
	else
		exec(arrKeys, proc, next_proc);
}

function checkForDeadlocks(){
	for (var i=0; i<arrQueuedJobs.length; i++){
		var job = arrQueuedJobs[i];
		if (Date.now() - job.ts > 30*1000)
			throw Error("possible deadlock on job "+require('util').inspect(job)+",\nproc:"+job.proc.toString()+" \nall jobs: "+require('util').inspect(arrQueuedJobs, {depth: null}));
	}
}

// long running locks are normal in multisig scenarios
//setInterval(checkForDeadlocks, 1000);

setInterval(function(){
	console.log("queued jobs: "+JSON.stringify(arrQueuedJobs.map(function(job){ return job.arrKeys; }))+", locked keys: "+JSON.stringify(arrLockedKeyArrays));
}, 10000);

exports.lock = lock;
exports.lockOrSkip = lockOrSkip;
exports.isAnyOfKeysLocked = isAnyOfKeysLocked;
exports.getCountOfQueuedJobs = getCountOfQueuedJobs;
exports.getCountOfLocks = getCountOfLocks;

/*
function test(key){
	var loc = "localvar"+key;
	lock(
		[key],
		function(cb){
			console.log("doing "+key);
			setTimeout(function(){
				console.log("done "+key);
				cb("arg1", "arg2");
			}, 1000)
		},
		function(arg1, arg2){
			console.log("got "+arg1+", "+arg2+", loc="+loc);
		}
	);
}

test("key1");
test("key2");
*/
<|endoftext|>


<commit_before>L.Control.Zoomslider = L.Control.extend({
	options: {
		position: 'topleft',
		sliderHeight: 162
	},

	onAdd: function (map) {
		var className = 'leaflet-control-zoomslider',
			container = L.DomUtil.create('div', className);

		this._createButton('Zoom in', className + '-in'
						   , container, map.zoomIn , map);
		this._createSlider(className + '-slider', container, map);
		this._createButton('Zoom out', className + '-out'
						   , container, map.zoomOut, map);

		this._map = map;

		this._map.on('zoomend', this._snapToZoomLevel, this);

		return container;
	},

	_createSlider: function (className, container, map) {
		var wrapper =  L.DomUtil.create('div', className + '-wrap', container);
		var slider = L.DomUtil.create('div', className, wrapper);
		var knob = L.DomUtil.create('div', className + '-knob', slider);

		this._zoomLevels = map.getMaxZoom() - map.getMinZoom();
		this._zoomStep = this.options.sliderHeight / this._zoomLevels;
		this._makeDraggable(knob);
		this._snapToZoomLevel();
		this._knob = knob;

		L.DomEvent
			.on(slider, 'click', L.DomEvent.stopPropagation)
			.on(slider, 'click', L.DomEvent.preventDefault)
			.on(slider, 'click', this._onSliderClick, this);

		return slider;
	},

	_createButton: function (title, className, container, fn, context) {
		var link = L.DomUtil.create('a', className, container);
		link.href = '#';
		link.title = title;

		L.DomEvent
			.on(link, 'click', L.DomEvent.stopPropagation)
			.on(link, 'click', L.DomEvent.preventDefault)
			.on(link, 'click', fn, context);

		return link;
	},

	_makeDraggable: function(knob, bbox) {
		if (!this._draggable) {
			L.DomUtil.setPosition(knob, new L.Point(0, 0));
			L.DomEvent
				.on(knob
					, L.Draggable.START
					, L.DomEvent.stopPropagation)
				.on(knob, 'click', L.DomEvent.stopPropagation);

			var bounds = new L.Bounds(
				new L.Point(0, 0),
				new L.Point(0, this.options.sliderHeight)
			);
			this._draggable = new L.BoundedDraggable(knob, knob, bounds)
				.on('drag', this._snap, this)
				.on('dragend', this._setZoom, this);
		}
		this._draggable.enable();
	},

	_snap : function(){
		var zoomLevel = this._posToZoomlevel();
		this._snapToZoomLevel(zoomLevel);
		return zoomLevel;
	},
	_setZoom: function() {
		this._map.setZoom(this._posToZoomlevel());
	},

	_onSliderClick: function(e){
		var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e);
	    var offset = first.offsetY
			? first.offsetY
			: L.DomEvent.getMousePosition(first).y
			- L.DomUtil.getViewportOffset(this._knob).y;
		var level = this._posToZoomlevel(offset  - this._knob.offsetHeight / 2);
		this._snapToZoomLevel(level);
		this._map.setZoom(level);
	},

	_posToZoomlevel: function(pos) {
		pos = !isNaN(pos)
			? pos
			: L.DomUtil.getPosition(this._knob).y;
		return Math.round( (this.options.sliderHeight - pos) / this._zoomStep);
	},

	_snapToZoomLevel: function(zoomLevel) {
		if(this._knob) {
			zoomLevel = !isNaN(zoomLevel)
				? zoomLevel
				: this._map.getZoom();
			var y = this.options.sliderHeight - (zoomLevel * this._zoomStep);
			L.DomUtil.setPosition(this._knob, new L.Point(0, y));
		}
	}
});

L.Map.mergeOptions({
    zoomControl: false,
    zoomsliderControl: true
});

L.Map.addInitHook(function () {
    if (this.options.zoomsliderControl) {
		this.zoomsliderControl = new L.Control.Zoomslider();
		this.addControl(this.zoomsliderControl);
	}
});

L.BoundedDraggable = L.Draggable.extend({
	initialize: function(element, dragStartTarget, bounds) {
		L.Draggable.prototype.initialize.call(this, element, dragStartTarget);
		this._bounds = bounds;
		this.on('predrag', function() {
			if(!this._bounds.contains(this._newPos)){
				this._newPos = this._fitPoint(this._newPos);
			}
		}, this);
	},
	_fitPoint: function(point){
		var closest = new L.Point(
			Math.min(point.x, this._bounds.max.x),
			Math.min(point.y, this._bounds.max.y)
		);
		closest.x = Math.max(closest.x, this._bounds.min.x);
		closest.y = Math.max(closest.y, this._bounds.min.y);
		return closest;
	}
});
<commit_msg>Add factory method in spirit with Leaflet 0.4<commit_after>L.Control.Zoomslider = L.Control.extend({
	options: {
		position: 'topleft',
		sliderHeight: 162
	},

	onAdd: function (map) {
		var className = 'leaflet-control-zoomslider',
			container = L.DomUtil.create('div', className);

		this._createButton('Zoom in', className + '-in'
						   , container, map.zoomIn , map);
		this._createSlider(className + '-slider', container, map);
		this._createButton('Zoom out', className + '-out'
						   , container, map.zoomOut, map);

		this._map = map;

		this._map.on('zoomend', this._snapToZoomLevel, this);

		return container;
	},

	_createSlider: function (className, container, map) {
		var wrapper =  L.DomUtil.create('div', className + '-wrap', container);
		var slider = L.DomUtil.create('div', className, wrapper);
		var knob = L.DomUtil.create('div', className + '-knob', slider);

		this._zoomLevels = map.getMaxZoom() - map.getMinZoom();
		this._zoomStep = this.options.sliderHeight / this._zoomLevels;
		this._makeDraggable(knob);
		this._snapToZoomLevel();
		this._knob = knob;

		L.DomEvent
			.on(slider, 'click', L.DomEvent.stopPropagation)
			.on(slider, 'click', L.DomEvent.preventDefault)
			.on(slider, 'click', this._onSliderClick, this);

		return slider;
	},

	_createButton: function (title, className, container, fn, context) {
		var link = L.DomUtil.create('a', className, container);
		link.href = '#';
		link.title = title;

		L.DomEvent
			.on(link, 'click', L.DomEvent.stopPropagation)
			.on(link, 'click', L.DomEvent.preventDefault)
			.on(link, 'click', fn, context);

		return link;
	},

	_makeDraggable: function(knob, bbox) {
		if (!this._draggable) {
			L.DomUtil.setPosition(knob, new L.Point(0, 0));
			L.DomEvent
				.on(knob
					, L.Draggable.START
					, L.DomEvent.stopPropagation)
				.on(knob, 'click', L.DomEvent.stopPropagation);

			var bounds = new L.Bounds(
				new L.Point(0, 0),
				new L.Point(0, this.options.sliderHeight)
			);
			this._draggable = new L.BoundedDraggable(knob, knob, bounds)
				.on('drag', this._snap, this)
				.on('dragend', this._setZoom, this);
		}
		this._draggable.enable();
	},

	_snap : function(){
		var zoomLevel = this._posToZoomlevel();
		this._snapToZoomLevel(zoomLevel);
		return zoomLevel;
	},
	_setZoom: function() {
		this._map.setZoom(this._posToZoomlevel());
	},

	_onSliderClick: function(e){
		var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e);
	    var offset = first.offsetY
			? first.offsetY
			: L.DomEvent.getMousePosition(first).y
			- L.DomUtil.getViewportOffset(this._knob).y;
		var level = this._posToZoomlevel(offset  - this._knob.offsetHeight / 2);
		this._snapToZoomLevel(level);
		this._map.setZoom(level);
	},

	_posToZoomlevel: function(pos) {
		pos = !isNaN(pos)
			? pos
			: L.DomUtil.getPosition(this._knob).y;
		return Math.round( (this.options.sliderHeight - pos) / this._zoomStep);
	},

	_snapToZoomLevel: function(zoomLevel) {
		if(this._knob) {
			zoomLevel = !isNaN(zoomLevel)
				? zoomLevel
				: this._map.getZoom();
			var y = this.options.sliderHeight - (zoomLevel * this._zoomStep);
			L.DomUtil.setPosition(this._knob, new L.Point(0, y));
		}
	}
});

L.Map.mergeOptions({
    zoomControl: false,
    zoomsliderControl: true
});

L.Map.addInitHook(function () {
    if (this.options.zoomsliderControl) {
		this.zoomsliderControl = new L.Control.Zoomslider();
		this.addControl(this.zoomsliderControl);
	}
});

L.control.zoomslider = function (options) {
    return new L.Control.Zoomslider(options);
};

L.BoundedDraggable = L.Draggable.extend({
	initialize: function(element, dragStartTarget, bounds) {
		L.Draggable.prototype.initialize.call(this, element, dragStartTarget);
		this._bounds = bounds;
		this.on('predrag', function() {
			if(!this._bounds.contains(this._newPos)){
				this._newPos = this._fitPoint(this._newPos);
			}
		}, this);
	},
	_fitPoint: function(point){
		var closest = new L.Point(
			Math.min(point.x, this._bounds.max.x),
			Math.min(point.y, this._bounds.max.y)
		);
		closest.x = Math.max(closest.x, this._bounds.min.x);
		closest.y = Math.max(closest.y, this._bounds.min.y);
		return closest;
	}
});
<|endoftext|>


<commit_before>"use strict";
/* -------------------------------------------------------------------
 * Require Statements << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

var EventEmitter = require('events').EventEmitter;
var sch = require('sch');
var Util = require('util');

/* =============================================================================
 *
 * Schtick Class
 *
 * ========================================================================== */

Util.inherits(Schtick, EventEmitter);
module.exports = Schtick;

/**
 * @param format {string|Schedule}
 * @param [options] {object}
 * @param [task] {function}
 * @returns {Schtick}
 * @constructor
 */
function Schtick (format, options, task)
{
	if (!(this instanceof Schtick))
		return new Schtick(format, options, task);

	/* -------------------------------------------------------------------
	 * Private Members Declaration << no methods >>
	 * ---------------------------------------------------------------- */

	Object.defineProperty(this, '__timeout', { value: null, writable: true });

	/* -------------------------------------------------------------------
	 * Public Members Declaration << no methods >>
	 * ---------------------------------------------------------------- */

	/** @member {Schedule} */
	this.schedule = null;

	/** @member {{window: number, ideal: boolean, autoStart: boolean, lastTick: ?Date}} */
	this.options = { window: 0, ideal: false, autoStart: true, lastTick: null };

	/** @member {Date} */
	this.lastTick = null;

	/** @member {boolean} */
	Object.defineProperty(this, 'isRunning', {
		get: function () { return this.__timeout !== null; }
	});

	/* -------------------------------------------------------------------
	 * Initialization
	 * ---------------------------------------------------------------- */

	EventEmitter.call(this);

	if (typeof format === 'string')
	{
		this.schedule = sch(format);
	}
	else if (isSchedule(format))
	{
		this.schedule = format;
	}
	else
	{
		throw new Error('format argument must be a string or a Schedule object from sch.');
	}

	if (typeof options === 'function')
	{
		task = options;
		options = null;
	}

	if (options && typeof options === 'object')
	{
		for (var i in this.options)
		{
			if (options.hasOwnProperty(i))
				this.options[i] = options[i];
		}
	}

	if (typeof task === 'function')
		this.on('tick', task);

	this.lastTick = this.options.lastTick;

	if (this.options.autoStart)
		this.start();
}

/* -------------------------------------------------------------------
 * Public Methods << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

/**
 * @param [lastKnownEvent] {Date}
 */
Schtick.prototype.start = function (lastKnownEvent)
{
	if (this.isRunning)
		return;

	if (lastKnownEvent instanceof Date)
		this.lastTick = lastKnownEvent;

	var now = new Date();
	var event = this.schedule.next(now);

	if (this.lastTick && this.options.window > 0)
	{
		var prev = this.schedule.previous(now);
		if (prev > (now - this.options.window) && prev > this.lastTick)
		{
			event = prev;
		}
	}

	if (!event)
		return event;

	// set timeout for next event
	this.__timeout = setTimeout(runTask.bind(this, event), Math.max(0, event - Date.now()));
};

Schtick.prototype.stop = function ()
{
	clearTimeout(this.__timeout);
	this.__timeout = null;
};

/* -------------------------------------------------------------------
 * Private Methods << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

function isSchedule (obj)
{
	if (!obj || typeof obj !== 'object')
		return false;

	return obj.constructor && obj.constructor.name === 'Schedule' &&
		typeof obj.next === 'function' && typeof obj.previous === 'function';
}

/**
 * @this {Schtick}
 */
function runTask (intendedTime)
{
	this.lastTick = this.options.ideal ? intendedTime : new Date();
	this.__timeout = null;
	this.start();

	this.emit('tick', intendedTime);
}
<commit_msg>add Schtick.prototype.ref and Schtick.prototype.unref<commit_after>"use strict";
/* -------------------------------------------------------------------
 * Require Statements << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

var EventEmitter = require('events').EventEmitter;
var sch = require('sch');
var Util = require('util');

/* =============================================================================
 *
 * Schtick Class
 *
 * ========================================================================== */

Util.inherits(Schtick, EventEmitter);
module.exports = Schtick;

/**
 * @param format {string|Schedule}
 * @param [options] {object}
 * @param [task] {function}
 * @returns {Schtick}
 * @constructor
 */
function Schtick (format, options, task)
{
	if (!(this instanceof Schtick))
		return new Schtick(format, options, task);

	/* -------------------------------------------------------------------
	 * Private Members Declaration << no methods >>
	 * ---------------------------------------------------------------- */

	Object.defineProperty(this, '__timeout', { value: null, writable: true });

	/* -------------------------------------------------------------------
	 * Public Members Declaration << no methods >>
	 * ---------------------------------------------------------------- */

	/** @member {Schedule} */
	this.schedule = null;

	/** @member {{window: number, ideal: boolean, autoStart: boolean, lastTick: ?Date}} */
	this.options = { window: 0, ideal: false, autoStart: true, lastTick: null };

	/** @member {Date} */
	this.lastTick = null;

	/** @member {boolean} */
	Object.defineProperty(this, 'isRunning', {
		get: function () { return this.__timeout !== null; }
	});

	/* -------------------------------------------------------------------
	 * Initialization
	 * ---------------------------------------------------------------- */

	EventEmitter.call(this);

	if (typeof format === 'string')
	{
		this.schedule = sch(format);
	}
	else if (isSchedule(format))
	{
		this.schedule = format;
	}
	else
	{
		throw new Error('format argument must be a string or a Schedule object from sch.');
	}

	if (typeof options === 'function')
	{
		task = options;
		options = null;
	}

	if (options && typeof options === 'object')
	{
		for (var i in this.options)
		{
			if (options.hasOwnProperty(i))
				this.options[i] = options[i];
		}
	}

	if (typeof task === 'function')
		this.on('tick', task);

	this.lastTick = this.options.lastTick;

	if (this.options.autoStart)
		this.start();
}

/* -------------------------------------------------------------------
 * Public Methods << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

/**
 * @param [lastKnownEvent] {Date}
 */
Schtick.prototype.start = function (lastKnownEvent)
{
	if (this.isRunning)
		return;

	if (lastKnownEvent instanceof Date)
		this.lastTick = lastKnownEvent;

	var now = new Date();
	var event = this.schedule.next(now);

	if (this.lastTick && this.options.window > 0)
	{
		var prev = this.schedule.previous(now);
		if (prev > (now - this.options.window) && prev > this.lastTick)
		{
			event = prev;
		}
	}

	if (!event)
		return event;

	// set timeout for next event
	this.__timeout = setTimeout(runTask.bind(this, event), Math.max(0, event - Date.now()));
};

Schtick.prototype.stop = function ()
{
	clearTimeout(this.__timeout);
	this.__timeout = null;
};

Schtick.prototype.ref = function ()
{
  if (this.__timeout)
    this.__timeout.ref();
};

Schtick.prototype.unref = function ()
{
  if (this.__timeout)
    this.__timeout.ref();
};

/* -------------------------------------------------------------------
 * Private Methods << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

function isSchedule (obj)
{
	if (!obj || typeof obj !== 'object')
		return false;

	return obj.constructor && obj.constructor.name === 'Schedule' &&
		typeof obj.next === 'function' && typeof obj.previous === 'function';
}

/**
 * @this {Schtick}
 */
function runTask (intendedTime)
{
	this.lastTick = this.options.ideal ? intendedTime : new Date();
	this.__timeout = null;
	this.start();

	this.emit('tick', intendedTime);
}
<|endoftext|>