<commit_before>/*
 * phantomjs.js
 * ~~~~~~~~~~~~
 *
 * This is the script that runs under PhantomJS.
 * It communicates with Wextracto over stdin/stdout.
 */

var system = require('system');
var wexRequest = JSON.parse(system.stdin.read());
var webpage = require('webpage');
var page = webpage.create();
var navigation = Array();
var requiredModules = Array();
var moduleWaitCallbacks = Array();
var logLevel = wexRequest.loglevel ;
var globals = {};
var waitMS = 100 ;
var requestWait = wexRequest.requestWait || 500 ;
var exitTimeoutId = null ;

navigation.push({"requests": Array(), "responses": {}, "started": false});

if (logLevel === null || logLevel === undefined) {
    logLevel = 30;
}

//
// update webpage settings

for (var setting in (wexRequest.settings || {})) {
    page.settings[setting] = wexRequest.settings[setting];
}

//
// load the modules specified by the wexRequest

for (var i=0; i < (wexRequest.requires || []).length; i++) {
    requiredModules.push(require(wexRequest.requires[i]));
}

// logging

function log(level, msg, prefix) {
    prefix = prefix || ' [phantomjs] ';
    system.stderr.writeLine(level + prefix + msg);
}

function logDebug(msg, prefix) {
    if (logLevel <= 10) {
        log('DEBUG', msg, prefix);
    }
}

function logInfo(msg, prefix) {
    if (logLevel <= 20) {
        log('INFO ', msg, prefix);
    }
}

function logWarning(msg, prefix) {
    if (logLevel <= 30) {
        log('WARNI', msg, prefix);
    }
}

function logError(msg, prefix) {
    if (logLevel <= 40) {
        log('ERROR', msg, prefix);
    }
}

// set proxy if specified
if (wexRequest.proxy) {
    phantom.setProxy(wexRequest.proxy.hostname,
                     wexRequest.proxy.port,
                     wexRequest.proxy.type,
                     wexRequest.proxy.username,
                     wexRequest.proxy.password);
}

// webpage callbacks

page.onConsoleMessage = function(msg, prefix) {
    logDebug(msg, " [phantomjs.onConsoleMessage] ");
};

page.onError = function(msg, trace) {
    logInfo(msg, " [phantomjs.onError] ");
};

page.onNavigationRequested = function(url, type, willNavigate, main) {
    if (main) {
        logDebug("onNavigationRequested to '" + url + "' (" + type + ")");
        navigation.push({"url": url, "requests": Array(), "responses": {}});
        clearTimeout(exitTimeoutId);
    }
};

page.onResourceRequested = function(requestData, networkRequest) {
    navigation[navigation.length-1].requests.push(requestData);
};

page.onResourceReceived = function(response) {
    navigation[navigation.length-1].responses[response.id] = response;
};

page.onResourceError = function(resourceError) {
    logDebug("onResourceError: " + JSON.stringify(resourceError));
    navigation[navigation.length-1].responses[resourceError.id] = resourceError;
};

//
// Return primary response.
// The primary response is the response to the first request
// for most recent navigation.
function getPrimaryResponse() {

    var i;
    var nav = null;
    var pageUrl = page.url && stripFragment(page.url);

    // Work backwards until we find navigation where onLoadStarted happened
    for (i = navigation.length-1; i >= 0; i--) {
        if (navigation[i].started) {
            nav = navigation[i];
            break;
        }
    }

    if (!nav) {
        return null;
    }

    var request = null;
    var response = null;

    for (i = 0 ; i < nav.requests.length; i++) {
        if (nav.requests[i].url == pageUrl) {
            request = nav.requests[i];
            break;
        }
    }

    if (request === null && nav.requests.length > 0) {
        request = nav.requests[0];
    }

    if (request !== null && request.id in nav.responses) {
        response = nav.responses[request.id];
    }

    return response;
}

var numWaits = 0;

function exitIfReady() {

    var keepWaiting = false;

    logDebug('exitIfReady()');
    numWaits += 1;

    var nav = navigation[navigation.length-1];
    for (var i = 0 ; i < nav.requests.length; i++) {
        var since = Date.now() - nav.requests[i].time.getTime();
        if (!(nav.requests[i].id in nav.responses)) {
            if (since <= requestWait) {
                logDebug("keep waiting for request: " + nav.requests[i].url);
                keepWaiting = true;
                break;
            }
        }
    }

    if (!keepWaiting) {
        // Ask the loaded modules if they need us to keep waiting
        keepWaiting = moduleWaitCallbacks.some(function(keepWaitingCallback) {
            try {
                return keepWaitingCallback(numWaits * waitMS);
            }
            catch (err) {
                logError("error in " + wait + ": " + err);
            }
        });
    }

    if (keepWaiting) {
        logDebug("not ready to exit - try again in " + waitMS + "ms");
        exitTimeoutId = setTimeout(exitIfReadyAtDepth(navigation.length), waitMS);
        return;
    }

    //
    // Now it's time to go

    response = getPrimaryResponse();
    writeWexIn(response);
    logDebug("phantom.exit(0) with: " + JSON.stringify(response));
    phantom.exit(0);

}

function exitIfReadyAtDepth(depth) {
    return function () {
        if (navigation.length <= depth) {
            exitIfReady();
        } else {
            logDebug('navigation since timeout started');
        }
    };
}

page.onLoadStarted = function() {
     var currentUrl = page.evaluate(function() {
             return window.location.href;
     });
     var readyState = page.evaluate(function() {
             return document.readyState;
     });
    logDebug('onLoadStarted: ' + currentUrl + ' ' + page.url + ' ' + readyState);
    navigation[navigation.length-1].started = true;
};

page.onUrlChanged = function(targetUrl) {
      logDebug('onUrlChanged: ' + targetUrl);
};

page.onLoadFinished = function(status) {

    var response = null ;

    //if (status != "success") {
    if (!page.url) {
        logError("exiting because onLoadFinished(" + status + ") " + page.url) ;
        phantom.exit(1);
        return;
    }

    requiredModules.map(function(module) {
        try {
            if (module.onLoadFinished) {
                wait = module.onLoadFinished();
                // logDebug("wait? " + wait + " " + module);
                if (wait) {
                    moduleWaitCallbacks.push(wait);
                }
            }
        }
        catch (err) {
            logError("error in " + module + ": " + err);
        }
    });

    clearTimeout(exitTimeoutId);
    exitTimeoutId = setTimeout(exitIfReadyAtDepth(navigation.length), 0);

    logDebug("onLoadFinished: " + status);
};

function writeWexIn(response) {

    var wexin = [];
    var status = 502 ;
    var statusText = "PhantomJS error";

    if (response !== null) {
        status = response.status;
        statusText = response.statusText;

        var pageUrl = page.url && stripFragment(page.url);

        if (response.url != pageUrl) {
            logWarning("response.url " + JSON.stringify(response.url) +
                       " is not same as page.url " + JSON.stringify(pageUrl)) ;
        }
    }

    wexin.push("HTTP/1.1 " + status + " " + statusText);
    if (response !== null) {

        for (var i=0; i<response.headers.length; i++) {
            var header = response.headers[i];
            wexin.push(header.name + ": " + header.value.replace(/\n/g, " "));
        }
    }

    var context = wexRequest.context || {};
    for (var key in context) {
        if (context.hasOwnProperty(key)) {
            wexin.push("X-wex-context-" + key + ": " + context[key]);
        }
    }

    wexin.push("X-wex-request-url: " + wexRequest.url);
    if (page.url) {
        wexin.push("X-wex-url: " + page.url);
    }
    wexin.push("");
    wexin.push(page.content);
    // previously I found PhantomJS will hang if I call write to stdout
    // multiple times (but only for large responses) so we join it all
    // in memory and then send it in one call.
    wexin = wexin.join("\r\n");

    system.stdout.write(wexin);
}

function stripFragment(url) {
    if (url.indexOf('#') >= 0) {
        return url.substring(0, url.indexOf('#'));
    }
    return url ;
}

page.open(stripFragment(wexRequest.url));
<commit_msg>Add support for onInitialized in JS exports<commit_after>/*
 * phantomjs.js
 * ~~~~~~~~~~~~
 *
 * This is the script that runs under PhantomJS.
 * It communicates with Wextracto over stdin/stdout.
 */

var system = require('system');
var wexRequest = JSON.parse(system.stdin.read());
var webpage = require('webpage');
var page = webpage.create();
var navigation = Array();
var requiredModules = Array();
var moduleWaitCallbacks = Array();
var logLevel = wexRequest.loglevel ;
var globals = {};
var waitMS = 100 ;
var requestWait = wexRequest.requestWait || 500 ;
var exitTimeoutId = null ;

navigation.push({"requests": Array(), "responses": {}, "started": false});

if (logLevel === null || logLevel === undefined) {
    logLevel = 30;
}

//
// update webpage settings

for (var setting in (wexRequest.settings || {})) {
    page.settings[setting] = wexRequest.settings[setting];
}

//
// load the modules specified by the wexRequest

for (var i=0; i < (wexRequest.requires || []).length; i++) {
    requiredModules.push(require(wexRequest.requires[i]));
}

// logging

function log(level, msg, prefix) {
    prefix = prefix || ' [phantomjs] ';
    system.stderr.writeLine(level + prefix + msg);
}

function logDebug(msg, prefix) {
    if (logLevel <= 10) {
        log('DEBUG', msg, prefix);
    }
}

function logInfo(msg, prefix) {
    if (logLevel <= 20) {
        log('INFO ', msg, prefix);
    }
}

function logWarning(msg, prefix) {
    if (logLevel <= 30) {
        log('WARNI', msg, prefix);
    }
}

function logError(msg, prefix) {
    if (logLevel <= 40) {
        log('ERROR', msg, prefix);
    }
}

// set proxy if specified
if (wexRequest.proxy) {
    phantom.setProxy(wexRequest.proxy.hostname,
                     wexRequest.proxy.port,
                     wexRequest.proxy.type,
                     wexRequest.proxy.username,
                     wexRequest.proxy.password);
}

// webpage callbacks

page.onConsoleMessage = function(msg, prefix) {
    logDebug(msg, " [phantomjs.onConsoleMessage] ");
};

page.onError = function(msg, trace) {
    logInfo(msg, " [phantomjs.onError] ");
};

page.onInitialized = function() {
    requiredModules.map(function(module) {
        try {
            if (module.onInitialized) {
                module.onInitialized();
            }
        }
        catch (err) {
            logError("error in " + module + ": " + err);
        }
    });
};

page.onNavigationRequested = function(url, type, willNavigate, main) {
    if (main) {
        logDebug("onNavigationRequested to '" + url + "' (" + type + ")");
        navigation.push({"url": url, "requests": Array(), "responses": {}});
        clearTimeout(exitTimeoutId);
    }
};

page.onResourceRequested = function(requestData, networkRequest) {
    navigation[navigation.length-1].requests.push(requestData);
};

page.onResourceReceived = function(response) {
    navigation[navigation.length-1].responses[response.id] = response;
};

page.onResourceError = function(resourceError) {
    logDebug("onResourceError: " + JSON.stringify(resourceError));
    navigation[navigation.length-1].responses[resourceError.id] = resourceError;
};

//
// Return primary response.
// The primary response is the response to the first request
// for most recent navigation.
function getPrimaryResponse() {

    var i;
    var nav = null;
    var pageUrl = page.url && stripFragment(page.url);

    // Work backwards until we find navigation where onLoadStarted happened
    for (i = navigation.length-1; i >= 0; i--) {
        if (navigation[i].started) {
            nav = navigation[i];
            break;
        }
    }

    if (!nav) {
        return null;
    }

    var request = null;
    var response = null;

    for (i = 0 ; i < nav.requests.length; i++) {
        if (nav.requests[i].url == pageUrl) {
            request = nav.requests[i];
            break;
        }
    }

    if (request === null && nav.requests.length > 0) {
        request = nav.requests[0];
    }

    if (request !== null && request.id in nav.responses) {
        response = nav.responses[request.id];
    }

    return response;
}

var numWaits = 0;

function exitIfReady() {

    var keepWaiting = false;

    logDebug('exitIfReady()');
    numWaits += 1;

    var nav = navigation[navigation.length-1];
    for (var i = 0 ; i < nav.requests.length; i++) {
        var since = Date.now() - nav.requests[i].time.getTime();
        if (!(nav.requests[i].id in nav.responses)) {
            if (since <= requestWait) {
                logDebug("keep waiting for request: " + nav.requests[i].url);
                keepWaiting = true;
                break;
            }
        }
    }

    if (!keepWaiting) {
        // Ask the loaded modules if they need us to keep waiting
        keepWaiting = moduleWaitCallbacks.some(function(keepWaitingCallback) {
            try {
                return keepWaitingCallback(numWaits * waitMS);
            }
            catch (err) {
                logError("error in " + wait + ": " + err);
            }
        });
    }

    if (keepWaiting) {
        logDebug("not ready to exit - try again in " + waitMS + "ms");
        exitTimeoutId = setTimeout(exitIfReadyAtDepth(navigation.length), waitMS);
        return;
    }

    //
    // Now it's time to go

    response = getPrimaryResponse();
    writeWexIn(response);
    logDebug("phantom.exit(0) with: " + JSON.stringify(response));
    phantom.exit(0);

}

function exitIfReadyAtDepth(depth) {
    return function () {
        if (navigation.length <= depth) {
            exitIfReady();
        } else {
            logDebug('navigation since timeout started');
        }
    };
}

page.onLoadStarted = function() {
     var currentUrl = page.evaluate(function() {
             return window.location.href;
     });
     var readyState = page.evaluate(function() {
             return document.readyState;
     });
    logDebug('onLoadStarted: ' + currentUrl + ' ' + page.url + ' ' + readyState);
    navigation[navigation.length-1].started = true;
};

page.onUrlChanged = function(targetUrl) {
      logDebug('onUrlChanged: ' + targetUrl);
};

page.onLoadFinished = function(status) {

    var response = null ;

    //if (status != "success") {
    if (!page.url) {
        logError("exiting because onLoadFinished(" + status + ") " + page.url) ;
        phantom.exit(1);
        return;
    }

    requiredModules.map(function(module) {
        try {
            if (module.onLoadFinished) {
                wait = module.onLoadFinished();
                // logDebug("wait? " + wait + " " + module);
                if (wait) {
                    moduleWaitCallbacks.push(wait);
                }
            }
        }
        catch (err) {
            logError("error in " + module + ": " + err);
        }
    });

    clearTimeout(exitTimeoutId);
    exitTimeoutId = setTimeout(exitIfReadyAtDepth(navigation.length), 0);

    logDebug("onLoadFinished: " + status);
};

function writeWexIn(response) {

    var wexin = [];
    var status = 502 ;
    var statusText = "PhantomJS error";

    if (response !== null) {
        status = response.status;
        statusText = response.statusText;

        var pageUrl = page.url && stripFragment(page.url);

        if (response.url != pageUrl) {
            logWarning("response.url " + JSON.stringify(response.url) +
                       " is not same as page.url " + JSON.stringify(pageUrl)) ;
        }
    }

    wexin.push("HTTP/1.1 " + status + " " + statusText);
    if (response !== null) {

        for (var i=0; i<response.headers.length; i++) {
            var header = response.headers[i];
            wexin.push(header.name + ": " + header.value.replace(/\n/g, " "));
        }
    }

    var context = wexRequest.context || {};
    for (var key in context) {
        if (context.hasOwnProperty(key)) {
            wexin.push("X-wex-context-" + key + ": " + context[key]);
        }
    }

    wexin.push("X-wex-request-url: " + wexRequest.url);
    if (page.url) {
        wexin.push("X-wex-url: " + page.url);
    }
    wexin.push("");
    wexin.push(page.content);
    // previously I found PhantomJS will hang if I call write to stdout
    // multiple times (but only for large responses) so we join it all
    // in memory and then send it in one call.
    wexin = wexin.join("\r\n");

    system.stdout.write(wexin);
}

function stripFragment(url) {
    if (url.indexOf('#') >= 0) {
        return url.substring(0, url.indexOf('#'));
    }
    return url ;
}

page.open(stripFragment(wexRequest.url));
<|endoftext|>


<commit_before>dojo.provide("dojox.widget.Toaster");

dojo.require("dojo.fx");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare("dojox.widget.Toaster", [dijit._Widget, dijit._Templated], {
		// summary:
		//		Message that slides in from the corner of the screen, used for notifications
		//		like "new email".

		templateString: '

',

		// messageTopic: String
		//		Name of topic; anything published to this topic will be displayed as a message.
		//		Message format is either String or an object like
		//		{message: "hello word", type: "error", duration: 500}
		messageTopic: "",

		_uniqueId: 0,

		// messageTypes: Enumeration
		//		Possible message types.
		messageTypes: {
			MESSAGE: "message",
			WARNING: "warning",
			ERROR: "error",
			FATAL: "fatal"
		},

		// defaultType: String
		//		If message type isn't specified (see "messageTopic" parameter),
		//		then display message as this type.
		//		Possible values in messageTypes enumeration ("message", "warning", "error", "fatal")
		defaultType: "message",

		// positionDirection: String
		//		Position from which message slides into screen, one of
		//		["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"]
		positionDirection: "br-up",

		// positionDirectionTypes: Array
		//		Possible values for positionDirection parameter
		positionDirectionTypes: ["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"],

		// duration: Integer
		//		Number of milliseconds to show message
		duration: "2000",

		//separator: String
		//		String used to separate messages if consecutive calls are made to setContent before previous messages go away
		separator: "

",

		postCreate: function(){
			this.inherited(arguments);
			this.hide();

			dojo.body().appendChild(this.clipNode);

			this.clipNode.className = "dijitToasterClip";
			this.containerNode.className += " dijitToasterContainer";
			this.contentNode.className = "dijitToasterContent";
			if(this.messageTopic){
				dojo.subscribe(this.messageTopic, this, "_handleMessage");
			}
		},

		_handleMessage: function(/*String|Object*/message){
			if(dojo.isString(message)){
				this.setContent(message);
			}else{
				this.setContent(message.message, message.type, message.duration);
			}
		},

		_capitalize: function(/* String */w){
				return w.substring(0,1).toUpperCase() + w.substring(1);
		},

		setContent: function(/*String|Function*/message, /*String*/messageType, /*int?*/duration){
			// summary:
			//		sets and displays the given message and show duration
			// message:
			//		the message. If this is a function, it will be called with this toaster widget as the only argument.
			// messageType:
			//		type of message; possible values in messageTypes enumeration ("message", "warning", "error", "fatal")
			// duration:
			//		duration in milliseconds to display message before removing it. Widget has default value.
			duration = duration||this.duration;
			// sync animations so there are no ghosted fades and such
			if(this.slideAnim){
				if(this.slideAnim.status() != "playing"){
					this.slideAnim.stop();
				}
				if(this.slideAnim.status() == "playing" || (this.fadeAnim && this.fadeAnim.status() == "playing")){
					setTimeout(dojo.hitch(this, function(){
						this.setContent(message, messageType, duration);
					}), 50);
					return;
				}
			}

			// determine type of content and apply appropriately
			for(var type in this.messageTypes){
				dojo.removeClass(this.containerNode, "dijitToaster" + this._capitalize(this.messageTypes[type]));
			}

			dojo.style(this.containerNode, "opacity", 1);

			this._setContent(message);

			dojo.addClass(this.containerNode, "dijitToaster" + this._capitalize(messageType || this.defaultType));

			// now do funky animation of widget appearing from
			// bottom right of page and up
			this.show();
			var nodeSize = dojo.marginBox(this.containerNode);
			this._cancelHideTimer();
			if(this.isVisible){
				this._placeClip();
				//update hide timer if no sticky message in stack
				if (!this._stickyMessage)
					this._setHideTimer(duration);

			}else{
				var style = this.containerNode.style;
				var pd = this.positionDirection;
				// sets up initial position of container node and slide-out direction
				if(pd.indexOf("-up") >= 0){
					style.left=0+"px";
					style.top=nodeSize.h + 10 + "px";
				}else if(pd.indexOf("-left") >= 0){
					style.left=nodeSize.w + 10 +"px";
					style.top=0+"px";
				}else if(pd.indexOf("-right") >= 0){
					style.left = 0 - nodeSize.w - 10 + "px";
					style.top = 0+"px";
				}else if(pd.indexOf("-down") >= 0){
					style.left = 0+"px";
					style.top = 0 - nodeSize.h - 10 + "px";
				}else{
					throw new Error(this.id + ".positionDirection is invalid: " + pd);
				}
				this.slideAnim = dojo.fx.slideTo({
					node: this.containerNode,
					top: 0, left: 0,
					duration: 450});
				this.connect(this.slideAnim, "onEnd", function(nodes, anim){
						//we build the fadeAnim here so we dont have to duplicate it later
						// can't do a fadeHide because we're fading the
						// inner node rather than the clipping node
						this.fadeAnim = dojo.fadeOut({
							node: this.containerNode,
							duration: 1000});
						this.connect(this.fadeAnim, "onEnd", function(evt){
							this.isVisible = false;
							this.hide();
						});
						this._setHideTimer(duration);
						this.connect(this, 'onSelect', function(evt){
							this._cancelHideTimer();
							//force clear sticky message
							this._stickyMessage=false;
							this.fadeAnim.play();
						});

						this.isVisible = true;
					});
				this.slideAnim.play();
			}
		},

		_setContent: function(message){
			if(dojo.isFunction(message)){
				message(this);
				return;
			}
			if(message && this.isVisible){
				message = this.contentNode.innerHTML + this.separator + message;
			}
			this.contentNode.innerHTML = message;
		},
		_cancelHideTimer:function(){
			if (this._hideTimer){
				clearTimeout(this._hideTimer);
				this._hideTimer=null;
			}
		},

		_setHideTimer:function(duration){
			this._cancelHideTimer();
			//if duration == 0 we keep the message displayed until clicked
			if(duration>0){
				this._cancelHideTimer();
				this._hideTimer=setTimeout(dojo.hitch(this, function(evt){
					// we must hide the iframe in order to fade
					// TODO: figure out how to fade with a BackgroundIframe
					if(this.bgIframe && this.bgIframe.iframe){
						this.bgIframe.iframe.style.display="none";
					}
					this._hideTimer=null;
					//force clear sticky message
					this._stickyMessage=false;
					this.fadeAnim.play();
				}), duration);
			}
			else
				this._stickyMessage=true;
		},

		_placeClip: function(){
			var view = dijit.getViewport();

			var nodeSize = dojo.marginBox(this.containerNode);

			var style = this.clipNode.style;
			// sets up the size of the clipping node
			style.height = nodeSize.h+"px";
			style.width = nodeSize.w+"px";

			// sets up the position of the clipping node
			var pd = this.positionDirection;
			if(pd.match(/^t/)){
				style.top = view.t+"px";
			}else if(pd.match(/^b/)){
				style.top = (view.h - nodeSize.h - 2 + view.t)+"px";
			}
			if(pd.match(/^[tb]r-/)){
				style.left = (view.w - nodeSize.w - 1 - view.l)+"px";
			}else if(pd.match(/^[tb]l-/)){
				style.left = 0 + "px";
			}

			style.clip = "rect(0px, " + nodeSize.w + "px, " + nodeSize.h + "px, 0px)";
			if(dojo.isIE){
				if(!this.bgIframe){
					this.clipNode.id = "__dojoXToaster_"+this._uniqueId++;
					this.bgIframe = new dijit.BackgroundIframe(this.clipNode);
				}
				var iframe = this.bgIframe.iframe;
				if(iframe){ iframe.style.display="block"; }
			}
		},

		onSelect: function(/*Event*/e){
			// summary: callback for when user clicks the message
		},

		show: function(){
			// summary: show the Toaster
			dojo.style(this.domNode, 'display', 'block');

			this._placeClip();

			if(!this._scrollConnected){
				this._scrollConnected = dojo.connect(window, "onscroll", this, this._placeClip);
			}
		},

		hide: function(){
			// summary: hide the Toaster

			dojo.style(this.domNode, 'display', 'none');

			if(this._scrollConnected){
				dojo.disconnect(this._scrollConnected);
				this._scrollConnected = false;
			}

			dojo.style(this.containerNode, "opacity", 1);
		}
	}
);
<commit_msg>wrong node by accident, refs #7342<commit_after>dojo.provide("dojox.widget.Toaster");

dojo.require("dojo.fx");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare("dojox.widget.Toaster", [dijit._Widget, dijit._Templated], {
		// summary:
		//		Message that slides in from the corner of the screen, used for notifications
		//		like "new email".

		templateString: '

',

		// messageTopic: String
		//		Name of topic; anything published to this topic will be displayed as a message.
		//		Message format is either String or an object like
		//		{message: "hello word", type: "error", duration: 500}
		messageTopic: "",

		_uniqueId: 0,

		// messageTypes: Enumeration
		//		Possible message types.
		messageTypes: {
			MESSAGE: "message",
			WARNING: "warning",
			ERROR: "error",
			FATAL: "fatal"
		},

		// defaultType: String
		//		If message type isn't specified (see "messageTopic" parameter),
		//		then display message as this type.
		//		Possible values in messageTypes enumeration ("message", "warning", "error", "fatal")
		defaultType: "message",

		// positionDirection: String
		//		Position from which message slides into screen, one of
		//		["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"]
		positionDirection: "br-up",

		// positionDirectionTypes: Array
		//		Possible values for positionDirection parameter
		positionDirectionTypes: ["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"],

		// duration: Integer
		//		Number of milliseconds to show message
		duration: "2000",

		//separator: String
		//		String used to separate messages if consecutive calls are made to setContent before previous messages go away
		separator: "

",

		postCreate: function(){
			this.inherited(arguments);
			this.hide();

			// place node as a child of body for positioning
			dojo.body().appendChild(this.domNode);

			this.clipNode.className = "dijitToasterClip";
			this.containerNode.className += " dijitToasterContainer";
			this.contentNode.className = "dijitToasterContent";
			if(this.messageTopic){
				dojo.subscribe(this.messageTopic, this, "_handleMessage");
			}
		},

		_handleMessage: function(/*String|Object*/message){
			if(dojo.isString(message)){
				this.setContent(message);
			}else{
				this.setContent(message.message, message.type, message.duration);
			}
		},

		_capitalize: function(/* String */w){
				return w.substring(0,1).toUpperCase() + w.substring(1);
		},

		setContent: function(/*String|Function*/message, /*String*/messageType, /*int?*/duration){
			// summary:
			//		sets and displays the given message and show duration
			// message:
			//		the message. If this is a function, it will be called with this toaster widget as the only argument.
			// messageType:
			//		type of message; possible values in messageTypes enumeration ("message", "warning", "error", "fatal")
			// duration:
			//		duration in milliseconds to display message before removing it. Widget has default value.
			duration = duration||this.duration;
			// sync animations so there are no ghosted fades and such
			if(this.slideAnim){
				if(this.slideAnim.status() != "playing"){
					this.slideAnim.stop();
				}
				if(this.slideAnim.status() == "playing" || (this.fadeAnim && this.fadeAnim.status() == "playing")){
					setTimeout(dojo.hitch(this, function(){
						this.setContent(message, messageType, duration);
					}), 50);
					return;
				}
			}

			// determine type of content and apply appropriately
			for(var type in this.messageTypes){
				dojo.removeClass(this.containerNode, "dijitToaster" + this._capitalize(this.messageTypes[type]));
			}

			dojo.style(this.containerNode, "opacity", 1);

			this._setContent(message);

			dojo.addClass(this.containerNode, "dijitToaster" + this._capitalize(messageType || this.defaultType));

			// now do funky animation of widget appearing from
			// bottom right of page and up
			this.show();
			var nodeSize = dojo.marginBox(this.containerNode);
			this._cancelHideTimer();
			if(this.isVisible){
				this._placeClip();
				//update hide timer if no sticky message in stack
				if (!this._stickyMessage)
					this._setHideTimer(duration);

			}else{
				var style = this.containerNode.style;
				var pd = this.positionDirection;
				// sets up initial position of container node and slide-out direction
				if(pd.indexOf("-up") >= 0){
					style.left=0+"px";
					style.top=nodeSize.h + 10 + "px";
				}else if(pd.indexOf("-left") >= 0){
					style.left=nodeSize.w + 10 +"px";
					style.top=0+"px";
				}else if(pd.indexOf("-right") >= 0){
					style.left = 0 - nodeSize.w - 10 + "px";
					style.top = 0+"px";
				}else if(pd.indexOf("-down") >= 0){
					style.left = 0+"px";
					style.top = 0 - nodeSize.h - 10 + "px";
				}else{
					throw new Error(this.id + ".positionDirection is invalid: " + pd);
				}
				this.slideAnim = dojo.fx.slideTo({
					node: this.containerNode,
					top: 0, left: 0,
					duration: 450});
				this.connect(this.slideAnim, "onEnd", function(nodes, anim){
						//we build the fadeAnim here so we dont have to duplicate it later
						// can't do a fadeHide because we're fading the
						// inner node rather than the clipping node
						this.fadeAnim = dojo.fadeOut({
							node: this.containerNode,
							duration: 1000});
						this.connect(this.fadeAnim, "onEnd", function(evt){
							this.isVisible = false;
							this.hide();
						});
						this._setHideTimer(duration);
						this.connect(this, 'onSelect', function(evt){
							this._cancelHideTimer();
							//force clear sticky message
							this._stickyMessage=false;
							this.fadeAnim.play();
						});

						this.isVisible = true;
					});
				this.slideAnim.play();
			}
		},

		_setContent: function(message){
			if(dojo.isFunction(message)){
				message(this);
				return;
			}
			if(message && this.isVisible){
				message = this.contentNode.innerHTML + this.separator + message;
			}
			this.contentNode.innerHTML = message;
		},
		_cancelHideTimer:function(){
			if (this._hideTimer){
				clearTimeout(this._hideTimer);
				this._hideTimer=null;
			}
		},

		_setHideTimer:function(duration){
			this._cancelHideTimer();
			//if duration == 0 we keep the message displayed until clicked
			if(duration>0){
				this._cancelHideTimer();
				this._hideTimer=setTimeout(dojo.hitch(this, function(evt){
					// we must hide the iframe in order to fade
					// TODO: figure out how to fade with a BackgroundIframe
					if(this.bgIframe && this.bgIframe.iframe){
						this.bgIframe.iframe.style.display="none";
					}
					this._hideTimer=null;
					//force clear sticky message
					this._stickyMessage=false;
					this.fadeAnim.play();
				}), duration);
			}
			else
				this._stickyMessage=true;
		},

		_placeClip: function(){
			var view = dijit.getViewport();

			var nodeSize = dojo.marginBox(this.containerNode);

			var style = this.clipNode.style;
			// sets up the size of the clipping node
			style.height = nodeSize.h+"px";
			style.width = nodeSize.w+"px";

			// sets up the position of the clipping node
			var pd = this.positionDirection;
			if(pd.match(/^t/)){
				style.top = view.t+"px";
			}else if(pd.match(/^b/)){
				style.top = (view.h - nodeSize.h - 2 + view.t)+"px";
			}
			if(pd.match(/^[tb]r-/)){
				style.left = (view.w - nodeSize.w - 1 - view.l)+"px";
			}else if(pd.match(/^[tb]l-/)){
				style.left = 0 + "px";
			}

			style.clip = "rect(0px, " + nodeSize.w + "px, " + nodeSize.h + "px, 0px)";
			if(dojo.isIE){
				if(!this.bgIframe){
					this.clipNode.id = "__dojoXToaster_"+this._uniqueId++;
					this.bgIframe = new dijit.BackgroundIframe(this.clipNode);
				}
				var iframe = this.bgIframe.iframe;
				if(iframe){ iframe.style.display="block"; }
			}
		},

		onSelect: function(/*Event*/e){
			// summary: callback for when user clicks the message
		},

		show: function(){
			// summary: show the Toaster
			dojo.style(this.domNode, 'display', 'block');

			this._placeClip();

			if(!this._scrollConnected){
				this._scrollConnected = dojo.connect(window, "onscroll", this, this._placeClip);
			}
		},

		hide: function(){
			// summary: hide the Toaster

			dojo.style(this.domNode, 'display', 'none');

			if(this._scrollConnected){
				dojo.disconnect(this._scrollConnected);
				this._scrollConnected = false;
			}

			dojo.style(this.containerNode, "opacity", 1);
		}
	}
);
<|endoftext|>


<commit_before>(function (angular, buildfire, location, jQuery) {
  "use strict";

  angular.module('mediaCenterRSSPluginWidget')

  /***************
   *   Filters   *
   ***************/

  /**
   * A filter for retrieving cropped image using buildfire.imageLib.cropImage component.
   * @param url
   * @param width
   * @param height
   */
    .filter('resizeImage', [function () {
      return function (url, width, height) {
        if (!url) {
          return '';
        } else {
          return buildfire.imageLib.resizeImage(url, {
            width: width,
            height: height
          });
        }
      };
    }])

  /**
   * A filter for retrieving re-sized image using buildfire.imageLib.resizeImage component.
   * @param url
   * @param width
   * @param height
   */
    .filter('cropImage', [function () {
      return function (url, width, height) {
        if (!url) {
          return '';
        } else {
          return buildfire.imageLib.cropImage(url, {
            width: width,
            height: height
          });
        }
      };
    }])

  /**
   * A filter for retrieving trusty Html using angular $sce service.
   * @param html
   */
    .filter('safeHtml', ['$sce', function ($sce) {
      return function (html) {
        if (html) {
          return $sce.trustAsHtml(html);
        }
        else {
          return "";
        }
      };
    }])

  /**
   * A filter for retrieving truncate Html of given length using jQuery.truncate method.
   * @param html
   * @param length
   */
    .filter('truncate', [function () {
      return function (html, length) {
        if (typeof html === 'string') {
          html = html.replace(/<[^>]+>/gm, '');
          return jQuery.truncate(html, {
            length: length
          });
        } else {
          return 'a';
        }
      };
    }])

  /**
   * A filter will remove styles from Html and add attribute 'target=_blank' to all anchor tags available in html.
   * @param html
   */
    .filter('removeHtmlStyle', [function () {
      return function (html) {
        if (html) {
          html = html.replace(/(<[^>]+) style=".*?"/i, '$1', "");
          html = html.replace(/<iframe.+?<\/iframe>/g, '');
          html = html.replace(/(<a\b[^><]*)>/ig, '$1 target="_blank">');
        }
        return html;
      };
    }])

  /**
   * A filter will return src url of first found image tag in html..
   * @param html
   */
    .filter('extractImgSrc', [function () {
      return function (html) {
        var imgArr = html.match(/<img[^>]+>/i);
        if (!imgArr || imgArr.length === 0) {
          return '';
        }
        var img = imgArr[0]
          , rex = /^<img[^>].*src=['"]([\/:a-zA-Z0-9\._-]+)['"].*$/i
          , result = img.match(rex);
        return (result && result[1]) ? result[1] : '';
      };
    }])

  /**
   * A filter to correct time.
   * @param html
   */
    .filter("timeCorrect", function () {
      return function (x) {
        x = '0' + x.substring(1);
        return x;
      };
    })
    .filter('secondsToDateTime', [function() {
      return function(seconds) {
        return new Date(1970, 0, 1).setSeconds(seconds);
      };
    }]);
})(window.angular, window.buildfire, window.location, jQuery);<commit_msg>List 1 fix on iphone trial<commit_after>(function (angular, buildfire, location, jQuery) {
  "use strict";

  angular.module('mediaCenterRSSPluginWidget')

  /***************
   *   Filters   *
   ***************/

  /**
   * A filter for retrieving cropped image using buildfire.imageLib.cropImage component.
   * @param url
   * @param width
   * @param height
   */
    .filter('resizeImage', [function () {
      return function (url, width, height) {
        if (!url) {
          return '';
        } else {
          return buildfire.imageLib.resizeImage(url, {
            width: width,
            height: height
          });
        }
      };
    }])

  /**
   * A filter for retrieving re-sized image using buildfire.imageLib.resizeImage component.
   * @param url
   * @param width
   * @param height
   */
    .filter('cropImage', [function () {
      return function (url, width, height) {
        if (!url) {
          return '';
        } else {
          return buildfire.imageLib.cropImage(url, {
            width: width,
            height: height
          });
        }
      };
    }])

  /**
   * A filter for retrieving trusty Html using angular $sce service.
   * @param html
   */
    .filter('safeHtml', ['$sce', function ($sce) {
      return function (html) {
        if (html) {
          return $sce.trustAsHtml(html);
        }
        else {
          return "";
        }
      };
    }])

  /**
   * A filter for retrieving truncate Html of given length using jQuery.truncate method.
   * @param html
   * @param length
   */
    .filter('truncate', [function () {
      return function (html, length) {
        if (typeof html === 'string') {
          html = html.replace(/<[^>]+>/gm, '');
          return jQuery.truncate(html, {
            length: length
          });
        } else {
          return 'aa';
        }
      };
    }])

  /**
   * A filter will remove styles from Html and add attribute 'target=_blank' to all anchor tags available in html.
   * @param html
   */
    .filter('removeHtmlStyle', [function () {
      return function (html) {
        if (html) {
          html = html.replace(/(<[^>]+) style=".*?"/i, '$1', "");
          html = html.replace(/<iframe.+?<\/iframe>/g, '');
          html = html.replace(/(<a\b[^><]*)>/ig, '$1 target="_blank">');
        }
        return html;
      };
    }])

  /**
   * A filter will return src url of first found image tag in html..
   * @param html
   */
    .filter('extractImgSrc', [function () {
      return function (html) {
        var imgArr = html.match(/<img[^>]+>/i);
        if (!imgArr || imgArr.length === 0) {
          return '';
        }
        var img = imgArr[0]
          , rex = /^<img[^>].*src=['"]([\/:a-zA-Z0-9\._-]+)['"].*$/i
          , result = img.match(rex);
        return (result && result[1]) ? result[1] : '';
      };
    }])

  /**
   * A filter to correct time.
   * @param html
   */
    .filter("timeCorrect", function () {
      return function (x) {
        x = '0' + x.substring(1);
        return x;
      };
    })
    .filter('secondsToDateTime', [function() {
      return function(seconds) {
        return new Date(1970, 0, 1).setSeconds(seconds);
      };
    }]);
})(window.angular, window.buildfire, window.location, jQuery);<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2020
 */

/**
 * Returns the boolean string as a boolean (false if none passed)
 * @param  {string} numberString The string to convert to a boolean
 * @return {boolean}               The boolean representation of the string
 */
export const parseBoolean = booleanString => {
  const trueStrings = ['true', 'True', 'TRUE'];
  return trueStrings.includes(booleanString);
};

/**
 * Return a Date object representing the given date, time.
 *
 * @param   {string}  ISODate  The date in ISO 8601 format.
 * @param   {string}  ISOTime  The time in ISO 8601 format. Optional.
 * @return  {Date}             The Date representing |ISODate| (and |ISOTime|).
 */
export const parseDate = (ISODate, ISOTime) => {
  if (
    !ISODate ||
    ISODate.length < 1 ||
    ISODate === '0000-00-00T00:00:00' ||
    ISODate === '0000-00-00T00:00:00Z'
  ) {
    return null;
  }
  const date = new Date(ISODate);
  if (ISOTime && ISOTime.length >= 6) {
    const hours = ISOTime.substring(0, 2);
    const minutes = ISOTime.substring(3, 5);
    const seconds = ISOTime.substring(6, 8);
    date.setHours(hours, minutes, seconds);
  }
  return date;
};

/**
 * Returns the number string as a float, or null if none passed.
 *
 * @param   {string}  numberString  The string to convert to a number.
 * @return  {float}                 The numeric representation of the string.
 */
export const parseNumber = numberString => {
  if (!numberString) return null;
  const result = parseFloat(numberString);
  return Number.isNaN(result) ? null : result;
};

/**
 * Returns jsonString prepared correctly for mobile realm database
 * @param  {string} jsonString The string to parse
 * @return {string}            The parsed string or |null|
 */
export const parseJsonString = jsonString => {
  // 4D adds extra backslashes, remove them so JSON.parse doesn't break
  let validatedString = jsonString && jsonString.replace(/\\/g, '');
  const nullValues = ['null', 'undefined'];
  // 'undefined' is stored as string on 4D, but as an optional field
  // in our realm schemas we can prefer |null|
  if (!validatedString || nullValues.includes(validatedString.toLowerCase())) {
    validatedString = null;
  }
  return validatedString;
};
<commit_msg>Update helper boolean parse logic<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2020
 */

/**
 * Returns the boolean string as a boolean (false if none passed)
 *
 * @param  {string}  numberString  The string to convert to a boolean
 * @return {boolean}               The boolean representation of the string
 */
export const parseBoolean = booleanString => booleanString.toString().toLowerCase() === 'true';

/**
 * Return a Date object representing the given date, time.
 *
 * @param   {string}  ISODate  The date in ISO 8601 format.
 * @param   {string}  ISOTime  The time in ISO 8601 format. Optional.
 * @return  {Date}             The Date representing |ISODate| (and |ISOTime|).
 */
export const parseDate = (ISODate, ISOTime) => {
  if (
    !ISODate ||
    ISODate.length < 1 ||
    ISODate === '0000-00-00T00:00:00' ||
    ISODate === '0000-00-00T00:00:00Z'
  ) {
    return null;
  }
  const date = new Date(ISODate);
  if (ISOTime && ISOTime.length >= 6) {
    const hours = ISOTime.substring(0, 2);
    const minutes = ISOTime.substring(3, 5);
    const seconds = ISOTime.substring(6, 8);
    date.setHours(hours, minutes, seconds);
  }
  return date;
};

/**
 * Returns the number string as a float, or null if none passed.
 *
 * @param   {string}  numberString  The string to convert to a number.
 * @return  {float}                 The numeric representation of the string.
 */
export const parseNumber = numberString => {
  if (!numberString) return null;
  const result = parseFloat(numberString);
  return Number.isNaN(result) ? null : result;
};

/**
 * Returns jsonString prepared correctly for mobile realm database
 * @param  {string} jsonString The string to parse
 * @return {string}            The parsed string or |null|
 */
export const parseJsonString = jsonString => {
  // 4D adds extra backslashes, remove them so JSON.parse doesn't break
  let validatedString = jsonString && jsonString.replace(/\\/g, '');
  const nullValues = ['null', 'undefined'];
  // 'undefined' is stored as string on 4D, but as an optional field
  // in our realm schemas we can prefer |null|
  if (!validatedString || nullValues.includes(validatedString.toLowerCase())) {
    validatedString = null;
  }
  return validatedString;
};
<|endoftext|>


<commit_before>const debug = require('debug');
const log = debug('swf');

const { createTaskPoller } = require('../util/poller');

const { resolveDeciderFunction } = require('./resolve');
const { runDecider } = require('./run');
const { createDecisionTaskCompletedResponder } = require('./respond');
const { summarizeDecisions } = require('../util/logging');

function getMostRecentNonDecisionEvent(events) {
    const rx = /^Decision/;
    for (let i = events.length - 1; i >= 0; i--) {
        if (!rx.test(events[i].eventType)) {
            return events[i];
        }
    }
    return undefined;
}

/**
 * Starts a long-poller that processes decision tasks.
 */
function pollForAndRunDecisionTasks(options) {
    const {
        domain,
        emitter,
        identity,
        swfClient,
        taskList,
        workflowDefinitions,
    } = options;

    const poller = createTaskPoller({
        swfClient,
        method: 'pollForDecisionTask',
        params: {
            domain,
            taskList: {
                name: taskList,
            },
            identity,
        },
    });

    // Forward polling errors to the main emitter.
    poller.on('error', (err) => emitter.emit('error', err));

    poller.on('started', () => log('Polling for decision tasks...'));

    poller.on('timedOut', () => log('Decision task long polling timed out.'));

    poller.on('task', (task, continuePolling) => {
        const {
            events,
            workflowExecution: { workflowId },
        } = task;

        const workflowLog = debug(`swf:${workflowId}:decider`);

        const mostRecentEvent = getMostRecentNonDecisionEvent(events) || {};

        workflowLog(
            'Received decision task with %d event(s). Most recent non-decision event: %s (%s)',
            events.length,
            mostRecentEvent.eventType,
            mostRecentEvent.eventId
        );

        const handleCompletedDecisionTask = createDecisionTaskCompletedResponder(swfClient, task);

        resolveDeciderFunction(task, workflowDefinitions)
            .then(deciderFunc => runDecider(task, deciderFunc, workflowLog, options))
            .then(handleCompletedDecisionTask)
            .then((decisions) => {
                workflowLog('Decision task completed: %s', summarizeDecisions(decisions));
                continuePolling();
            })
            .catch(err => {
                workflowLog('Decision task failed: %s.', err.message);
                emitter.emit('error', err);
                continuePolling();
            });
    });

    poller.start();
}

module.exports = { pollForAndRunDecisionTasks };
<commit_msg>Improve logging when decider returns nothing<commit_after>const debug = require('debug');
const log = debug('swf');

const { createTaskPoller } = require('../util/poller');

const { resolveDeciderFunction } = require('./resolve');
const { runDecider } = require('./run');
const { createDecisionTaskCompletedResponder } = require('./respond');
const { summarizeDecisions } = require('../util/logging');

function getMostRecentNonDecisionEvent(events) {
    const rx = /^Decision/;
    for (let i = events.length - 1; i >= 0; i--) {
        if (!rx.test(events[i].eventType)) {
            return events[i];
        }
    }
    return undefined;
}

/**
 * Starts a long-poller that processes decision tasks.
 */
function pollForAndRunDecisionTasks(options) {
    const {
        domain,
        emitter,
        identity,
        swfClient,
        taskList,
        workflowDefinitions,
    } = options;

    const poller = createTaskPoller({
        swfClient,
        method: 'pollForDecisionTask',
        params: {
            domain,
            taskList: {
                name: taskList,
            },
            identity,
        },
    });

    // Forward polling errors to the main emitter.
    poller.on('error', (err) => emitter.emit('error', err));

    poller.on('started', () => log('Polling for decision tasks...'));

    poller.on('timedOut', () => log('Decision task long polling timed out.'));

    poller.on('task', (task, continuePolling) => {
        const {
            events,
            workflowExecution: { workflowId },
        } = task;

        const workflowLog = debug(`swf:${workflowId}:decider`);

        const mostRecentEvent = getMostRecentNonDecisionEvent(events) || {};

        workflowLog(
            'Received decision task with %d event(s). Most recent non-decision event: %s (%s)',
            events.length,
            mostRecentEvent.eventType,
            mostRecentEvent.eventId
        );

        const handleCompletedDecisionTask = createDecisionTaskCompletedResponder(swfClient, task);

        resolveDeciderFunction(task, workflowDefinitions)
            .then(deciderFunc => runDecider(task, deciderFunc, workflowLog, options))
            .then(handleCompletedDecisionTask)
            .then((decisions) => {
                workflowLog(
                    'Decision task completed: %s',
                    decisions.length ? summarizeDecisions(decisions) : '(no decisions)'
                );
                continuePolling();
            })
            .catch(err => {
                workflowLog('Decision task failed: %s.', err.message);
                emitter.emit('error', err);
                continuePolling();
            });
    });

    poller.start();
}

module.exports = { pollForAndRunDecisionTasks };
<|endoftext|>


<commit_before>pref("toolkit.defaultChromeURI", "chrome://specter/content/main.xul");

/* debugging prefs, disable these before you deploy your application! */
pref("browser.dom.window.dump.enabled", true);
pref("javascript.options.showInConsole", true);
pref("javascript.options.strict", true);
pref("nglayout.debug.disable_xul_cache", true);
pref("nglayout.debug.disable_xul_fastload", true);
<commit_msg>turn off strict preference<commit_after>pref("toolkit.defaultChromeURI", "chrome://specter/content/main.xul");

/* debugging prefs, disable these before you deploy your application! */
pref("browser.dom.window.dump.enabled", true);
pref("javascript.options.showInConsole", true);
//pref("javascript.options.strict", true);
pref("nglayout.debug.disable_xul_cache", true);
pref("nglayout.debug.disable_xul_fastload", true);
<|endoftext|>


<commit_before>(function($) {
    $.fn.extend({
        dustParticles: function(particlesNumber, opacity) {
            return this.each(function() {
                var width = $(this).width();
                var height = $(this).height();
                var canvas = document.createElement('canvas');
                canvas.id = 'canvas';
                document.body.appendChild(canvas);
                var ctx = canvas.getContext('2d');
                canvas.width = width;
                canvas.height = height;
                var particles = [];
                var particleLimit = particlesNumber;
                for (var i = 0; i < particleLimit; i++) {
                    particles.push(new particle());
                }

                function particle() {
                    this.speed = {
                        x: Math.random() * 3 - 0.5,
                        y: Math.random() * 3 - 0.5
                    };
                    this.radius = Math.random() * (10 - 1) + 1;
                    console.log(this.radius)
                    this.opacity = opacity / this.radius;
                    this.r = 255;
                    this.g = 255;
                    this.b = 255;
                    this.x = Math.random() * (canvas.width - 0) + 0;
                    this.y = Math.random() * (canvas.height - 0) + 0;
                    this.color = this.color = "rgba(" + this.r + ", " + this.g + ", " + this.b + ", " + this.opacity + ")";
                }

                function live() {
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    particles.forEach(function(element, index) {
                        ctx.beginPath();
                        var gradient = ctx.createRadialGradient(element.x, element.y, 0, element.x, element.y, element.radius);
                        gradient.addColorStop(1, "rgba(" + element.r + ", " + element.g + ", " + element.b + ", 0)");
                        gradient.addColorStop(0.5, "rgba(" + element.r + ", " + element.g + ", " + element.b + ", " + (element.opacity / 2) + ")");
                        gradient.addColorStop(0, "rgba(" + element.r + ", " + element.g + ", " + element.b + ", " + element.opacity + ")");
                        ctx.fillStyle = gradient;
                        ctx.arc(element.x, element.y, element.radius, 0, Math.PI * 2, true);
                        ctx.fill();
                        element.x += element.speed.x;
                        element.y += element.speed.y;
                        if (element.x < -50) element.x = canvas.width + 50;
                        if (element.y < -50) element.y = canvas.height + 50;
                        if (element.x > canvas.width + 50) element.x = -50;
                        if (element.y > canvas.height + 50) element.y = -50;
                    });
                }
                setInterval(live, 33);
            });
        }
    });
})(jQuery)
<commit_msg>Re-version.<commit_after>(function($) {
    $.fn.extend({
        dustParticles: function(particlesNumber, opacity) {
            return this.each(function() {
                //Generate a 'canvas' with size of element selected from the DOM .
                var width = $(this).width();
                var height = $(this).height();
                var canvas = document.createElement('canvas');
                canvas.id = 'canvas';
                document.body.appendChild(canvas);
                //Generate the context of canvas
                var ctx = canvas.getContext('2d');
                canvas.width = width;
                canvas.height = height;
                var particles = [];
                var particleLimit = particlesNumber;
                //We create our funny particles !
                for (var i = 0; i < particleLimit; i++) {
                    particles.push(new particle());
                }
                //Function generating the object particles , having size , radio, opacity, initial position and color.
                function particle() {
                    this.speed = {
                        x: Math.random() * 3 - 0.5,
                        y: Math.random() * 3 - 0.5
                    };
                    this.radius = Math.random() * (10 - 1) + 1;
                    console.log(this.radius)
                    this.opacity = opacity / this.radius;
                    this.r = 255;
                    this.g = 255;
                    this.b = 255;
                    this.x = Math.random() * (canvas.width - 0) + 0;
                    this.y = Math.random() * (canvas.height - 0) + 0;
                    this.color = this.color = 'rgba(' + this.r + ', ' + this.g + ', ' + this.b + ', ' + this.opacity + ')';
                }

                function live() {
                    //We repainted the canvas to create the sensation of movement.
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    particles.forEach(function(element, index) {
                        ctx.beginPath();
                        var gradient = ctx.createRadialGradient(element.x, element.y, 0, element.x, element.y, element.radius);
                        gradient.addColorStop(1, 'rgba(' + element.r + ', ' + element.g + ', ' + element.b + ', 0)');
                        gradient.addColorStop(0.5, 'rgba(' + element.r + ', ' + element.g + ', ' + element.b + ', ' + (element.opacity / 2) + ')');
                        gradient.addColorStop(0, 'rgba(' + element.r + ', ' + element.g + ', ' + element.b + ', ' + element.opacity + ')');
                        ctx.fillStyle = gradient;
                        ctx.arc(element.x, element.y, element.radius, 0, Math.PI * 2, true);
                        ctx.fill();
                        //New position of particles
                        element.x += element.speed.x;
                        element.y += element.speed.y;
                        //We avoid the particles are beyond our territory!
                        if (element.x < -50) element.x = canvas.width + 50;
                        if (element.y < -50) element.y = canvas.height + 50;
                        if (element.x > canvas.width + 50) element.x = -50;
                        if (element.y > canvas.height + 50) element.y = -50;
                    });
                }
                setInterval(live, 33);
            });
        }
    });
})(jQuery)

<|endoftext|>


<commit_before>/**
 * This is inception. Using Handsontable as Handsontable editor
 */

function HandsontableHandsontableEditorClass(instance) {
  this.instance = instance;
  this.createElements();
  this.bindEvents();
}

Handsontable.helper.inherit(HandsontableHandsontableEditorClass, HandsontableTextEditorClass);

HandsontableHandsontableEditorClass.prototype.createElements = function () {
  HandsontableTextEditorClass.prototype.createElements.call(this);

  var DIV = document.createElement('DIV');
  DIV.className = 'handsontableEditor';
  this.TEXTAREA_PARENT.appendChild(DIV);

  this.$htContainer = $(DIV);
};

HandsontableTextEditorClass.prototype.moveSelectedOption = function (rowDelta, colDelta) {
  var HOT = this.$htContainer.handsontable('getInstance');
  var sel = HOT.getSelected();
  HOT.selectCell(sel[0] + rowDelta, sel[1] + colDelta);
  this.wtDom.setCaretPosition(this.$textarea[0], 0, this.$textarea[0].value.length);
};

HandsontableTextEditorClass.prototype.bindEvents = function () {
  var that = this;

  this.$textarea.off('.editor').on('keydown.editor', function (event) {
    if (that.state === that.STATE_WAITING) {
      event.stopImmediatePropagation();
    }
    else {
      that.waitingEvent = null;
    }

    if (that.state !== that.STATE_EDITING) {
      return;
    }

    var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)

    if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
      //when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
      event.stopImmediatePropagation();
      return;
    }

    switch (event.keyCode) {
      case 38: /* arrow up */
        that.moveSelectedOption(-1, 0);
        break;

      case 40: /* arrow down */
        that.moveSelectedOption(1, 0);
        break;

      case 9: /* tab */
        that.finishEditing(false);
        event.preventDefault();
        break;

      case 39: /* arrow right */
        that.moveSelectedOption(0, 1);
        break;

      case 37: /* arrow left */
        that.moveSelectedOption(0, -1);
        break;

      case 27: /* ESC */
        that.instance.destroyEditor(true);
        event.stopImmediatePropagation();
        break;

      case 13: /* return/enter */
        that.TEXTAREA.value = that.$htContainer.handsontable('getInstance').getValue();
        that.instance.destroyEditor();
        break;

      default:
        event.stopImmediatePropagation(); //backspace, delete, home, end, CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
        break;
    }

    if (that.state !== that.STATE_FINISHED && !event.isImmediatePropagationStopped()) {
      that.waitingEvent = event;
      event.stopImmediatePropagation();
      event.preventDefault();
    }
  });

  var parent = this;

  var options = {
    className: 'listbox',
    cells: function () {
      return {
        readOnly: true
      }
    },
    fillHandle: false,
    width: 2000,
    //width: 'auto',
    afterOnCellMouseDown: function () {
      parent.TEXTAREA.value = this.getValue();
      parent.instance.destroyEditor();
    }
  };

  this.$htContainer.handsontable(options);
};

HandsontableHandsontableEditorClass.prototype.bindTemporaryEvents = function (td, row, col, prop, value, cellProperties) {
  if (cellProperties.handsontable) {
    this.$htContainer.handsontable('updateSettings', cellProperties.handsontable);
  }

  HandsontableTextEditorClass.prototype.bindTemporaryEvents.call(this, td, row, col, prop, value, cellProperties);
};

HandsontableHandsontableEditorClass.prototype.beginEditing = function (row, col, prop, useOriginalValue, suffix) {
  var onBeginEditing = this.instance.getSettings().onBeginEditing;
  if (onBeginEditing && onBeginEditing() === false) {
    return;
  }

  HandsontableTextEditorClass.prototype.beginEditing.call(this, row, col, prop, useOriginalValue, suffix);

  this.$htContainer.handsontable('render');
  this.$htContainer.handsontable('selectCell', 0, 0);

  this.wtDom.setCaretPosition(this.$textarea[0], 0, this.$textarea[0].value.length);
};

HandsontableHandsontableEditorClass.prototype.finishEditing = function (isCancelled, ctrlDown) {
  if (this.$htContainer.handsontable('isListening')) { //if focus is still in the HOT editor
    this.instance.listen(); //return the focus to the parent HOT instance
  }
  HandsontableTextEditorClass.prototype.finishEditing.call(this, isCancelled, ctrlDown);
};

HandsontableHandsontableEditorClass.prototype.refreshDimensions = function () {
  if (this.state !== this.STATE_EDITING) {
    return;
  }

  ///start prepare textarea position
  this.TD = this.instance.getCell(this.row, this.col);
  var $td = $(this.TD); //because old td may have been scrolled out with scrollViewport
  var currentOffset = this.wtDom.offset(this.TD);
  var containerOffset = this.wtDom.offset(this.instance.rootElement[0]);
  var scrollTop = this.instance.rootElement.scrollTop();
  var scrollLeft = this.instance.rootElement.scrollLeft();
  var editTop = currentOffset.top - containerOffset.top + scrollTop - 1;
  var editLeft = currentOffset.left - containerOffset.left + scrollLeft - 1;

  var settings = this.instance.getSettings();
  var rowHeadersCount = settings.rowHeaders === false ? 0 : 1;
  var colHeadersCount = settings.colHeaders === false ? 0 : 1;

  if (editTop < 0) {
    editTop = 0;
  }
  if (editLeft < 0) {
    editLeft = 0;
  }

  if (rowHeadersCount > 0 && parseInt($td.css('border-top-width'), 10) > 0) {
    //editTop += 1;
  }
  if (colHeadersCount > 0 && parseInt($td.css('border-left-width'), 10) > 0) {
    //editLeft += 1;
  }

  if ($.browser.msie && parseInt($.browser.version, 10) <= 7) {
    editTop -= 1;
  }

  this.textareaParentStyle.top = editTop + 'px';
  this.textareaParentStyle.left = editLeft + 'px';
  ///end prepare textarea position

  var width = $td.width()
    , height = $td.outerHeight() - 4;

  if (parseInt($td.css('border-top-width'), 10) > 0) {
    //height -= 1;
  }
  if (parseInt($td.css('border-left-width'), 10) > 0) {
    if (rowHeadersCount > 0) {
      //width -= 1;
    }
  }

  this.$textarea[0].style.width = width + 'px';
  this.$textarea[0].style.height = height + 'px';

  this.textareaParentStyle.display = 'block';
};

/**
 * Handsontable editor
 * @param {Object} instance Handsontable instance
 * @param {Element} td Table cell where to render
 * @param {Number} row
 * @param {Number} col
 * @param {String|Number} prop Row object property name
 * @param value Original value (remember to escape unsafe HTML before inserting to DOM!)
 * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)
 */
Handsontable.HandsontableEditor = function (instance, td, row, col, prop, value, cellProperties) {
  if (!instance.handsontableEditor) {
    instance.handsontableEditor = new HandsontableHandsontableEditorClass(instance);
  }
  instance.handsontableEditor.bindTemporaryEvents(td, row, col, prop, value, cellProperties);

  instance.registerEditor = instance.handsontableEditor;

  return function (isCancelled) {
    instance.handsontableEditor.finishEditing(isCancelled);
  }
};
<commit_msg>fix extending wrong class<commit_after>/**
 * This is inception. Using Handsontable as Handsontable editor
 */

function HandsontableHandsontableEditorClass(instance) {
  this.instance = instance;
  this.createElements();
  this.bindEvents();
}

Handsontable.helper.inherit(HandsontableHandsontableEditorClass, HandsontableTextEditorClass);

HandsontableHandsontableEditorClass.prototype.createElements = function () {
  HandsontableTextEditorClass.prototype.createElements.call(this);

  var DIV = document.createElement('DIV');
  DIV.className = 'handsontableEditor';
  this.TEXTAREA_PARENT.appendChild(DIV);

  this.$htContainer = $(DIV);
};

HandsontableHandsontableEditorClass.prototype.moveSelectedOption = function (rowDelta, colDelta) {
  var HOT = this.$htContainer.handsontable('getInstance');
  var sel = HOT.getSelected();
  HOT.selectCell(sel[0] + rowDelta, sel[1] + colDelta);
  this.wtDom.setCaretPosition(this.$textarea[0], 0, this.$textarea[0].value.length);
};

HandsontableHandsontableEditorClass.prototype.bindEvents = function () {
  var that = this;

  this.$textarea.off('.editor').on('keydown.editor', function (event) {
    if (that.state === that.STATE_WAITING) {
      event.stopImmediatePropagation();
    }
    else {
      that.waitingEvent = null;
    }

    if (that.state !== that.STATE_EDITING) {
      return;
    }

    var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)

    if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
      //when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
      event.stopImmediatePropagation();
      return;
    }

    switch (event.keyCode) {
      case 38: /* arrow up */
        that.moveSelectedOption(-1, 0);
        break;

      case 40: /* arrow down */
        that.moveSelectedOption(1, 0);
        break;

      case 9: /* tab */
        that.finishEditing(false);
        event.preventDefault();
        break;

      case 39: /* arrow right */
        that.moveSelectedOption(0, 1);
        break;

      case 37: /* arrow left */
        that.moveSelectedOption(0, -1);
        break;

      case 27: /* ESC */
        that.instance.destroyEditor(true);
        event.stopImmediatePropagation();
        break;

      case 13: /* return/enter */
        that.TEXTAREA.value = that.$htContainer.handsontable('getInstance').getValue();
        that.instance.destroyEditor();
        break;

      default:
        event.stopImmediatePropagation(); //backspace, delete, home, end, CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
        break;
    }

    if (that.state !== that.STATE_FINISHED && !event.isImmediatePropagationStopped()) {
      that.waitingEvent = event;
      event.stopImmediatePropagation();
      event.preventDefault();
    }
  });

  var parent = this;

  var options = {
    className: 'listbox',
    cells: function () {
      return {
        readOnly: true
      }
    },
    fillHandle: false,
    width: 2000,
    //width: 'auto',
    afterOnCellMouseDown: function () {
      parent.TEXTAREA.value = this.getValue();
      parent.instance.destroyEditor();
    }
  };

  this.$htContainer.handsontable(options);
};

HandsontableHandsontableEditorClass.prototype.bindTemporaryEvents = function (td, row, col, prop, value, cellProperties) {
  if (cellProperties.handsontable) {
    this.$htContainer.handsontable('updateSettings', cellProperties.handsontable);
  }

  HandsontableTextEditorClass.prototype.bindTemporaryEvents.call(this, td, row, col, prop, value, cellProperties);
};

HandsontableHandsontableEditorClass.prototype.beginEditing = function (row, col, prop, useOriginalValue, suffix) {
  var onBeginEditing = this.instance.getSettings().onBeginEditing;
  if (onBeginEditing && onBeginEditing() === false) {
    return;
  }

  HandsontableTextEditorClass.prototype.beginEditing.call(this, row, col, prop, useOriginalValue, suffix);

  this.$htContainer.handsontable('render');
  this.$htContainer.handsontable('selectCell', 0, 0);

  this.wtDom.setCaretPosition(this.$textarea[0], 0, this.$textarea[0].value.length);
};

HandsontableHandsontableEditorClass.prototype.finishEditing = function (isCancelled, ctrlDown) {
  if (this.$htContainer.handsontable('isListening')) { //if focus is still in the HOT editor
    this.instance.listen(); //return the focus to the parent HOT instance
  }
  HandsontableTextEditorClass.prototype.finishEditing.call(this, isCancelled, ctrlDown);
};

HandsontableHandsontableEditorClass.prototype.refreshDimensions = function () {
  if (this.state !== this.STATE_EDITING) {
    return;
  }

  ///start prepare textarea position
  this.TD = this.instance.getCell(this.row, this.col);
  var $td = $(this.TD); //because old td may have been scrolled out with scrollViewport
  var currentOffset = this.wtDom.offset(this.TD);
  var containerOffset = this.wtDom.offset(this.instance.rootElement[0]);
  var scrollTop = this.instance.rootElement.scrollTop();
  var scrollLeft = this.instance.rootElement.scrollLeft();
  var editTop = currentOffset.top - containerOffset.top + scrollTop - 1;
  var editLeft = currentOffset.left - containerOffset.left + scrollLeft - 1;

  var settings = this.instance.getSettings();
  var rowHeadersCount = settings.rowHeaders === false ? 0 : 1;
  var colHeadersCount = settings.colHeaders === false ? 0 : 1;

  if (editTop < 0) {
    editTop = 0;
  }
  if (editLeft < 0) {
    editLeft = 0;
  }

  if (rowHeadersCount > 0 && parseInt($td.css('border-top-width'), 10) > 0) {
    //editTop += 1;
  }
  if (colHeadersCount > 0 && parseInt($td.css('border-left-width'), 10) > 0) {
    //editLeft += 1;
  }

  if ($.browser.msie && parseInt($.browser.version, 10) <= 7) {
    editTop -= 1;
  }

  this.textareaParentStyle.top = editTop + 'px';
  this.textareaParentStyle.left = editLeft + 'px';
  ///end prepare textarea position

  var width = $td.width()
    , height = $td.outerHeight() - 4;

  if (parseInt($td.css('border-top-width'), 10) > 0) {
    //height -= 1;
  }
  if (parseInt($td.css('border-left-width'), 10) > 0) {
    if (rowHeadersCount > 0) {
      //width -= 1;
    }
  }

  this.$textarea[0].style.width = width + 'px';
  this.$textarea[0].style.height = height + 'px';

  this.textareaParentStyle.display = 'block';
};

/**
 * Handsontable editor
 * @param {Object} instance Handsontable instance
 * @param {Element} td Table cell where to render
 * @param {Number} row
 * @param {Number} col
 * @param {String|Number} prop Row object property name
 * @param value Original value (remember to escape unsafe HTML before inserting to DOM!)
 * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)
 */
Handsontable.HandsontableEditor = function (instance, td, row, col, prop, value, cellProperties) {
  if (!instance.handsontableEditor) {
    instance.handsontableEditor = new HandsontableHandsontableEditorClass(instance);
  }
  instance.handsontableEditor.bindTemporaryEvents(td, row, col, prop, value, cellProperties);

  instance.registerEditor = instance.handsontableEditor;

  return function (isCancelled) {
    instance.handsontableEditor.finishEditing(isCancelled);
  }
};
<|endoftext|>


<commit_before>/**
 * This is inception. Using Handsontable as Handsontable editor
 */

function HandsontableHandsontableEditorClass(instance) {
  this.isCellEdited = false;
  this.instance = instance;
  this.createElements();
  this.bindEvents();
}

Handsontable.helper.inherit(HandsontableHandsontableEditorClass, HandsontableTextEditorClass);

HandsontableHandsontableEditorClass.prototype.createElements = function () {
  HandsontableTextEditorClass.prototype.createElements.call(this);

  var DIV = document.createElement('DIV');
  DIV.className = 'handsontableEditor';
  this.TEXTAREA_PARENT.appendChild(DIV);

  this.$htContainer = $(DIV);
};

HandsontableHandsontableEditorClass.prototype.bindTemporaryEvents = function (td, row, col, prop, value, cellProperties) {
  var parent = this;

  var options = {
    colHeaders: true,
    cells: function () {
      return {
        readOnly: true
      }
    },
    fillHandle: false,
    width: 2000,
    //width: 'auto',
    afterOnCellMouseDown: function () {
      var sel = this.getSelected();
      parent.TEXTAREA.value = this.getDataAtCell(sel[0], sel[1]);
      parent.instance.destroyEditor();
    },
    beforeOnKeyDown: function (event) {
      switch (event.keyCode) {
        case 27: //esc
          parent.instance.destroyEditor(true);
          break;

        case 13: //enter
          var sel = this.getSelected();
          parent.TEXTAREA.value = this.getDataAtCell(sel[0], sel[1]);
          parent.instance.destroyEditor();
          break;
      }
    }
  };

  if (cellProperties.handsontable) {
    options = $.extend(options, cellProperties.handsontable);
  }

  this.$htContainer.handsontable(options);

  HandsontableTextEditorClass.prototype.bindTemporaryEvents.call(this, td, row, col, prop, value, cellProperties);
};

HandsontableHandsontableEditorClass.prototype.beginEditing = function (row, col, prop, useOriginalValue, suffix) {
  var onBeginEditing = this.instance.getSettings().onBeginEditing;
  if (onBeginEditing && onBeginEditing() === false) {
    return;
  }

  HandsontableTextEditorClass.prototype.beginEditing.call(this, row, col, prop, useOriginalValue, suffix);

  this.$htContainer.handsontable('selectCell', 0, 0);
};

HandsontableHandsontableEditorClass.prototype.finishEditing = function (isCancelled, ctrlDown) {
  if (Handsontable.helper.isDescendant(this.instance.rootElement[0], document.activeElement)) {
    var that = this;
    setTimeout(function () {
      that.instance.listen(); //return the focus to the cell must be done after destroyer to work in IE7-9
    }, 0);
    that.instance.listen(); //return the focus to the cell
  }
  this.$htContainer.handsontable('destroy');
  HandsontableTextEditorClass.prototype.finishEditing.call(this, isCancelled, ctrlDown);
};

HandsontableHandsontableEditorClass.prototype.isMenuExpanded = function () {
  if (this.typeahead.$menu.is(":visible")) {
    return this.typeahead;
  }
  else {
    return false;
  }
};

/**
 * Handsontable editor
 * @param {Object} instance Handsontable instance
 * @param {Element} td Table cell where to render
 * @param {Number} row
 * @param {Number} col
 * @param {String|Number} prop Row object property name
 * @param value Original value (remember to escape unsafe HTML before inserting to DOM!)
 * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)
 */
Handsontable.HandsontableEditor = function (instance, td, row, col, prop, value, cellProperties) {
  if (!instance.handsontableEditor) {
    instance.handsontableEditor = new HandsontableHandsontableEditorClass(instance);
  }
  instance.handsontableEditor.bindTemporaryEvents(td, row, col, prop, value, cellProperties);

  instance.registerEditor = instance.handsontableEditor;

  return function (isCancelled) {
    instance.handsontableEditor.finishEditing(isCancelled);
  }
};<commit_msg>Features: - Handsontable will not be rendered if the container is not attached to DOM or it's style is `display: none` - new configuration option `observeDOMVisibility` (default `true`) will attempt to rerender it once it is attached to DOM or style changed to `display: block`<commit_after>/**
 * This is inception. Using Handsontable as Handsontable editor
 */

function HandsontableHandsontableEditorClass(instance) {
  this.isCellEdited = false;
  this.instance = instance;
  this.createElements();
  this.bindEvents();
}

Handsontable.helper.inherit(HandsontableHandsontableEditorClass, HandsontableTextEditorClass);

HandsontableHandsontableEditorClass.prototype.createElements = function () {
  HandsontableTextEditorClass.prototype.createElements.call(this);

  var DIV = document.createElement('DIV');
  DIV.className = 'handsontableEditor';
  this.TEXTAREA_PARENT.appendChild(DIV);

  this.$htContainer = $(DIV);
};

HandsontableHandsontableEditorClass.prototype.bindTemporaryEvents = function (td, row, col, prop, value, cellProperties) {
  var parent = this;

  var options = {
    colHeaders: true,
    cells: function () {
      return {
        readOnly: true
      }
    },
    fillHandle: false,
    width: 2000,
    //width: 'auto',
    afterOnCellMouseDown: function () {
      var sel = this.getSelected();
      parent.TEXTAREA.value = this.getDataAtCell(sel[0], sel[1]);
      parent.instance.destroyEditor();
    },
    beforeOnKeyDown: function (event) {
      switch (event.keyCode) {
        case 27: //esc
          parent.instance.destroyEditor(true);
          break;

        case 13: //enter
          var sel = this.getSelected();
          parent.TEXTAREA.value = this.getDataAtCell(sel[0], sel[1]);
          parent.instance.destroyEditor();
          break;
      }
    }
  };

  if (cellProperties.handsontable) {
    options = $.extend(options, cellProperties.handsontable);
  }

  this.$htContainer.handsontable(options);

  HandsontableTextEditorClass.prototype.bindTemporaryEvents.call(this, td, row, col, prop, value, cellProperties);
};

HandsontableHandsontableEditorClass.prototype.beginEditing = function (row, col, prop, useOriginalValue, suffix) {
  var onBeginEditing = this.instance.getSettings().onBeginEditing;
  if (onBeginEditing && onBeginEditing() === false) {
    return;
  }

  HandsontableTextEditorClass.prototype.beginEditing.call(this, row, col, prop, useOriginalValue, suffix);

  this.$htContainer.handsontable('render');
  this.$htContainer.handsontable('selectCell', 0, 0);
};

HandsontableHandsontableEditorClass.prototype.finishEditing = function (isCancelled, ctrlDown) {
  if (Handsontable.helper.isDescendant(this.instance.rootElement[0], document.activeElement)) {
    var that = this;
    setTimeout(function () {
      that.instance.listen(); //return the focus to the cell must be done after destroyer to work in IE7-9
    }, 0);
    that.instance.listen(); //return the focus to the cell
  }
  this.$htContainer.handsontable('destroy');
  HandsontableTextEditorClass.prototype.finishEditing.call(this, isCancelled, ctrlDown);
};

HandsontableHandsontableEditorClass.prototype.isMenuExpanded = function () {
  if (this.typeahead.$menu.is(":visible")) {
    return this.typeahead;
  }
  else {
    return false;
  }
};

/**
 * Handsontable editor
 * @param {Object} instance Handsontable instance
 * @param {Element} td Table cell where to render
 * @param {Number} row
 * @param {Number} col
 * @param {String|Number} prop Row object property name
 * @param value Original value (remember to escape unsafe HTML before inserting to DOM!)
 * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)
 */
Handsontable.HandsontableEditor = function (instance, td, row, col, prop, value, cellProperties) {
  if (!instance.handsontableEditor) {
    instance.handsontableEditor = new HandsontableHandsontableEditorClass(instance);
  }
  instance.handsontableEditor.bindTemporaryEvents(td, row, col, prop, value, cellProperties);

  instance.registerEditor = instance.handsontableEditor;

  return function (isCancelled) {
    instance.handsontableEditor.finishEditing(isCancelled);
  }
};<|endoftext|>


<commit_before>'use strict';

angular.module('openshiftConsole')
.factory('ImageStreamResolver', function($q, DataService) {
  function ImageStreamResolver() {
  }

  // pods - the pods to check for referenced images
  // imagesByDockerReference - a map where any loaded images will be stored by their Docker image reference
  // imageStreamImageRefByDockerReference - a map of imageStreamImage names by their Docker image reference, should be generated by buildDockerRefMapForImageStreams
  // context - the context to be passed to any server requests, in general this is the $scope of the calling controller
  // returns a promise that will be resolved when all referenced images are loaded
  ImageStreamResolver.prototype.fetchReferencedImageStreamImages = function(pods, imagesByDockerReference, imageStreamImageRefByDockerReference, context) {
    var promises = [];
    angular.forEach(pods, function(pod){
      angular.forEach(pod.spec.containers, function(container){
        var dockerRef = container.image;
        if (!dockerRef) {
          return;
        }

        if (imagesByDockerReference[dockerRef]) {
          // Already have an image for this ref
          return;
        }

        var imageStreamImageRef = imageStreamImageRefByDockerReference[dockerRef];
        if (!imageStreamImageRef) {
          // This docker ref doesn't come from an image stream we know about
          return;
        }

        var parts = imageStreamImageRef.split("@");

        var imageStreamImagePromise = DataService.get("imagestreamimages", imageStreamImageRef, context);
        imageStreamImagePromise.then(function(imageStreamImage) {
          if (imageStreamImage && imageStreamImage.image) {
            var image = angular.copy(imageStreamImage.image);
            image.imageStreamName = parts[0];
            image.imageStreamNamespace = context.project.metadata.name;
            imagesByDockerReference[dockerRef] = image;
          }
        });
        promises.push(imageStreamImagePromise);
      });
    });
    return $q.all(promises);
  };

  // imageStreams - the image streams to process
  // imageStreamImageRefByDockerReference - a map that will be filled out with imageStreamImage names by their Docker image reference
  ImageStreamResolver.prototype.buildDockerRefMapForImageStreams = function(imageStreams, imageStreamImageRefByDockerReference) {
    angular.forEach(imageStreams, function(imageStream) {
      angular.forEach(imageStream.status.tags, function(tag){
        angular.forEach(tag.items, function(image){
          if (image.image) {
            // TODO if the API starts returning us the imageStreamImage name use that instead of building it ourselves
            imageStreamImageRefByDockerReference[image.dockerImageReference] = imageStream.metadata.name + "@" + image.image;
          }
        });
      });
    });
  };

  return new ImageStreamResolver();
});
<commit_msg>Don't fetch an is image if we are already in the process of fetching it<commit_after>'use strict';

angular.module('openshiftConsole')
.factory('ImageStreamResolver', function($q, DataService) {
  function ImageStreamResolver() {
  }

  // pods - the pods to check for referenced images
  // imagesByDockerReference - a map where any loaded images will be stored by their Docker image reference
  // imageStreamImageRefByDockerReference - a map of imageStreamImage names by their Docker image reference, should be generated by buildDockerRefMapForImageStreams
  // context - the context to be passed to any server requests, in general this is the $scope of the calling controller
  // returns a promise that will be resolved when all referenced images are loaded
  ImageStreamResolver.prototype.fetchReferencedImageStreamImages = function(pods, imagesByDockerReference, imageStreamImageRefByDockerReference, context) {
    var promises = {};
    angular.forEach(pods, function(pod){
      angular.forEach(pod.spec.containers, function(container){
        var dockerRef = container.image;
        if (!dockerRef) {
          return;
        }

        if (imagesByDockerReference[dockerRef] || promises[dockerRef]) {
          // Already have an image for this ref, or we already have a promise to go get it
          return;
        }

        var imageStreamImageRef = imageStreamImageRefByDockerReference[dockerRef];
        if (!imageStreamImageRef) {
          // This docker ref doesn't come from an image stream we know about
          return;
        }

        var parts = imageStreamImageRef.split("@");

        var imageStreamImagePromise = DataService.get("imagestreamimages", imageStreamImageRef, context);
        imageStreamImagePromise.then(function(imageStreamImage) {
          if (imageStreamImage && imageStreamImage.image) {
            var image = angular.copy(imageStreamImage.image);
            image.imageStreamName = parts[0];
            image.imageStreamNamespace = context.project.metadata.name;
            imagesByDockerReference[dockerRef] = image;
          }
        });
        promises[dockerRef] = imageStreamImagePromise;
      });
    });
    return $q.all(promises);
  };

  // imageStreams - the image streams to process
  // imageStreamImageRefByDockerReference - a map that will be filled out with imageStreamImage names by their Docker image reference
  ImageStreamResolver.prototype.buildDockerRefMapForImageStreams = function(imageStreams, imageStreamImageRefByDockerReference) {
    angular.forEach(imageStreams, function(imageStream) {
      angular.forEach(imageStream.status.tags, function(tag){
        angular.forEach(tag.items, function(image){
          if (image.image) {
            // TODO if the API starts returning us the imageStreamImage name use that instead of building it ourselves
            imageStreamImageRefByDockerReference[image.dockerImageReference] = imageStream.metadata.name + "@" + image.image;
          }
        });
      });
    });
  };

  return new ImageStreamResolver();
});
<|endoftext|>