<commit_before>/*jslint white: true, nomen: true, plusplus: true */
/*global mx, mxui, mendix, dojo, require, console, define, module, document*/

require([
	"dojo/_base/declare",
	"mxui/widget/_WidgetBase",

	"mxui/dom",
	"dojo/dom-style",
	"dojo/dom-attr",
	"dojo/dom-construct",
	"dojo/_base/lang",
	"dijit/layout/LinkPane"
], function(declare, _WidgetBase, dom, domStyle, domAttr, domConstruct, lang, LinkPane) {
	"use strict";

	return declare("HTMLSnippet.widget.HTMLSnippet", [_WidgetBase], {

		_objectChangeHandler : null,

		postCreate: function() {
			this._setupEvents();

			if (!this.refreshOnContextChange) {
				this.executeCode();
			}
		},

		executeCode: function() {
			var external = this.contentsPath !== "" ? true : false;
			switch (this.contenttype) {
				case "html":
					if (external) {
						new LinkPane({
							preload: true,
							loadingMessage: "",
							href: this.contentsPath,
							onDownloadError: function() {
								console.log("Error loading html path");
							}
						}).placeAt(this.domNode.id).startup();
					} else {
						domStyle.set(this.domNode, {
							"height": "auto",
							"width": "100%",
							"outline": 0
						});

						domAttr.set(this.domNode, "style", this.style); // might override height and width
						var domNode = domConstruct.create("div", { innerHTML: this.contents });
						domConstruct.place(domNode, this.domNode, "only");
					}
					break;

				case "js":
				case "jsjQuery":
					if (external) {
						var scriptNode = document.createElement("script"),
							intDate = +new Date();

						scriptNode.type = "text/javascript";
						scriptNode.src = this.contentsPath + "?v=" + intDate.toString();

						domConstruct.place(scriptNode, this.domNode, "only");
					} else {
						if (this.contenttype === "jsjQuery") {
							require(["HTMLSnippet/lib/jquery-1.11.3"], lang.hitch(this, this.evalJs));
						} else {
							this.evalJs();
						}
					}
					break;
			}
		},

		update: function(obj, callback) {
			if (this.refreshOnContextChange) {
				this.executeCode();

				if(this.refreshOnContextUpdate){

					if (this._objectChangeHandler !== null){
						this.unsubscribe(this._objectChangeHandler);
					}

					if (obj){

						this.subscribe({
							guid: obj.getGuid(),
							callback: lang.hitch(this, function(){
								this.executeCode();
							})
						});
					}
				}
			}

			callback();
		},

		_setupEvents: function() {
			if (this.onclickmf) {
				this.connect(this.domNode, "click", this._executeMicroflow);
			}
		},

		_executeMicroflow: function() {
			if (this.onclickmf) {
				mx.data.action({
					store: {
						caller: this.mxform
					},
					params: {
						actionname: this.onclickmf
					},
					callback: function() {
						// ok
					},
					error: function() {
						// error
					}
				});
			}
		},

		evalJs: function() {
			try {
				eval(this.contents + "\r\n//# sourceURL=" + this.id + ".js");
			} catch (e) {
				domConstruct.place("
Error while evaluating javascript input: " + e + "
", this.domNode, "only");
			}
		}

	});
});
<commit_msg>Cleanup code<commit_after>/*jslint white: true, nomen: true, plusplus: true */
/*global mx, mxui, mendix, dojo, require, console, define, module, document*/

require([
    "dojo/_base/declare",
    "mxui/widget/_WidgetBase",

    "mxui/dom",
    "dojo/dom-style",
    "dojo/dom-attr",
    "dojo/dom-construct",
    "dojo/_base/lang",
    "dijit/layout/LinkPane"
], function(declare, _WidgetBase, dom, domStyle, domAttr, domConstruct, lang, LinkPane) {
    "use strict";

    return declare("HTMLSnippet.widget.HTMLSnippet", [_WidgetBase], {

        _objectChangeHandler: null,

        postCreate: function() {
            this._setupEvents();

            if (!this.refreshOnContextChange) {
                this.executeCode();
            }
        },

        executeCode: function() {
            var external = this.contentsPath !== "" ? true : false;
            switch (this.contenttype) {
                case "html":
                    if (external) {
                        new LinkPane({
                            preload: true,
                            loadingMessage: "",
                            href: this.contentsPath,
                            onDownloadError: function() {
                                console.log("Error loading html path");
                            }
                        }).placeAt(this.domNode.id).startup();
                    } else {
                        domStyle.set(this.domNode, {
                            "height": "auto",
                            "width": "100%",
                            "outline": 0
                        });

                        domAttr.set(this.domNode, "style", this.style); // might override height and width
                        var domNode = domConstruct.create("div", {
                            innerHTML: this.contents
                        });
                        domConstruct.place(domNode, this.domNode, "only");
                    }
                    break;

                case "js":
                case "jsjQuery":
                    if (external) {
                        var scriptNode = document.createElement("script"),
                            intDate = +new Date();

                        scriptNode.type = "text/javascript";
                        scriptNode.src = this.contentsPath + "?v=" + intDate.toString();

                        domConstruct.place(scriptNode, this.domNode, "only");
                    } else {
                        if (this.contenttype === "jsjQuery") {
                            require(["HTMLSnippet/lib/jquery-1.11.3"], lang.hitch(this, this.evalJs));
                        } else {
                            this.evalJs();
                        }
                    }
                    break;
            }
        },

        update: function(obj, callback) {
            if (this.refreshOnContextChange) {
                this.executeCode();

                if (this.refreshOnContextUpdate) {
                    if (this._objectChangeHandler !== null) {
                        this.unsubscribe(this._objectChangeHandler);
                    }

                    if (obj) {
                        this.subscribe({
                            guid: obj.getGuid(),
                            callback: lang.hitch(this, function() {
                                this.executeCode();
                            })
                        });
                    }
                }
            }

            callback();
        },

        _setupEvents: function() {
            if (this.onclickmf) {
                this.connect(this.domNode, "click", this._executeMicroflow);
            }
        },

        _executeMicroflow: function() {
            if (this.onclickmf) {
                mx.data.action({
                    store: {
                        caller: this.mxform
                    },
                    params: {
                        actionname: this.onclickmf
                    },
                    callback: function() {
                        // ok
                    },
                    error: function() {
                        // error
                    }
                });
            }
        },

        evalJs: function() {
            try {
                eval(this.contents + "\r\n//# sourceURL=" + this.id + ".js");
            } catch (e) {
                domConstruct.place("
Error while evaluating javascript input: " + e + "
", this.domNode, "only");
            }
        }

    });
});
<|endoftext|>


<commit_before>'use strict';

var marked = require('marked'),
    swig = require('swig'),
    Node = function(path) {
      this.path = path;
      this.children = [];
    };

module.exports = function(basePath, grunt)
{
  swig.init({
    root: basePath + '/templates'
  });

  Node.prototype.initialize = function(filename, properties)
  {
    this.filename = filename;

    // Copy over properties from the json data onto the base of this object
    for (var prop in properties) {
      this[prop] = properties[prop];
    }

    // A node must have template data to render with if it wasn't already specified in the .json
    this.templateData = this.templateData || {};
  };

  Node.prototype.render = function()
  {
    var path = this.path;

    // Recursively finds fields in the templateData object that specify markdown files
    // and parses them to html.
    function findAndParseMarkdown(data) {
      for (var fieldName in data) {
        var fieldValue = data[fieldName];
        if (typeof fieldValue === 'string') {
          // If it's a string then check if the extension is .md and parse it
          if (fieldValue.match(/\.md$/)) {
            var mdPath = basePath + '/content/' + path + fieldValue;
            data[fieldName] = marked(grunt.file.read(mdPath));
          }
        } else if (typeof fieldValue === 'object') {
          // Recursively search nested objects
          findAndParseMarkdown(fieldValue);
        }
      }
    }

    findAndParseMarkdown(this.templateData);

    var rendered = swig.compileFile(this.template).render(this.templateData);
    return rendered;
  };

  return Node;
};

<commit_msg>Made intermediate data provider when rendering templates<commit_after>'use strict';

var marked = require('marked'),
    swig = require('swig'),
    Node = function(path) {
      this.path = path;
      this.children = [];
    };

module.exports = function(basePath, grunt)
{
  swig.init({
    root: basePath + '/templates'
  });

  Node.prototype.initialize = function(filename, properties)
  {
    this.filename = filename;

    // Copy over properties from the json data onto the base of this object
    for (var prop in properties) {
      this[prop] = properties[prop];
    }

    // A node must have template data to render with if it wasn't already specified in the .json
    this.templateData = this.templateData || {};
  };

  Node.prototype.render = function()
  {
    var path = this.path;

    // Recursively finds fields in the templateData object that specify markdown files
    // and parses them to html.
    function findAndParseMarkdown(data) {
      for (var fieldName in data) {
        var fieldValue = data[fieldName];
        if (typeof fieldValue === 'string') {
          // If it's a string then check if the extension is .md and parse it
          if (fieldValue.match(/\.md$/)) {
            var mdPath = basePath + '/content/' + path + fieldValue;
            data[fieldName] = marked(grunt.file.read(mdPath));
          }
        } else if (typeof fieldValue === 'object') {
          // Recursively search nested objects
          findAndParseMarkdown(fieldValue);
        }
      }
    }

    findAndParseMarkdown(this.templateData);

    // Create an intermediate data provider that will combine the properties of templateData
    // with this node object.
    var templateDataProvider = {};
    for (var prop in this.templateData) {
      templateDataProvider[prop] = this.templateData[prop];
    }
    templateDataProvider.node = this;

    var rendered = swig.compileFile(this.template).render(templateDataProvider);
    return rendered;
  };

  return Node;
};

<|endoftext|>


<commit_before>$('#datasend1').click( function() {
			var message = $('#data1').val();
			$('#data1').val('');
			$('#data1').focus(); // manda el enfoque al input
			// tell server to execute 'sendchat' and send along one parameter
			socket.emit('sendchatagent', message, socket.localusername + '01', '1');
		});

		// when the client hits ENTER on their keyboard
		$('#data1').keypress(function(e) {
			if(e.which == 13) {
				$(this).blur();
				$('#datasend1').focus().click();
			}
		});<commit_msg>Se elimina porque este codigo se añade en linea en forma dinamica<commit_after><|endoftext|>


<commit_before>var imageDataController = require('../app/controllers/ImageData.js');
var helpers = require('./helperfunctions');
var fs = require('fs');
var request = require('request');
var knox = require('knox');
var uuid = require('node-uuid');

var client = helpers.helper.awsClient();

module.exports = {
  //stream requested image to fs and store in s3 bucket
  upload: function(req, res, next) {
    var key = uuid.v4().split('-').pop();
    var outStream = fs.createWriteStream(process.env.LOCAL_FILE_PATH + '/' + key + '.jpg');

    request(req.query.imgUrl).pipe(outStream);

    outStream.on('close', function() {
      fs.readFile(process.env.LOCAL_FILE_PATH + '/' + key + '.jpg', function(err, buff){
        var req = client.put(key, {
            'Content-Length': buff.length,
            'Content-Type': 'image/jpeg',
            'x-amz-acl': 'public-read'
          });

        req.on('response', function(res){
          if (200 == res.statusCode) {
            console.log('saved to %s', req.url);
          }
        });

        req.end(buff);
        insertDB(req, res, key);
      });
    });
  }
};

//store metadata to db
var insertDB = function(req, res, key) {
  var metaData = imageDataController.storeImageMetaData(key);

  response(req, res, metaData.key);
};

var response = function(req, res, key) {
  var response = {};

  response.createdAt = new Date();
  response.imgId = key;

  helpers.helper.write(req, res, 201, JSON.stringify(response));
};<commit_msg>modify model name<commit_after>var imageData = require('../app/controllers/ImageData.js');
var helpers = require('./helperfunctions');
var fs = require('fs');
var request = require('request');
var knox = require('knox');
var uuid = require('node-uuid');

var client = helpers.helper.awsClient();

module.exports = {
  //stream requested image to fs and store in s3 bucket
  upload: function(req, res, next) {
    var key = uuid.v4().split('-').pop();
    var outStream = fs.createWriteStream(process.env.LOCAL_FILE_PATH + '/' + key + '.jpg');

    request(req.query.imgUrl).pipe(outStream);

    outStream.on('close', function() {
      fs.readFile(process.env.LOCAL_FILE_PATH + '/' + key + '.jpg', function(err, buff){
        var req = client.put(key, {
            'Content-Length': buff.length,
            'Content-Type': 'image/jpeg',
            'x-amz-acl': 'public-read'
          });

        req.on('response', function(res){
          if (200 == res.statusCode) {
            console.log('saved to %s', req.url);
          }
        });

        req.end(buff);
        insertDB(req, res, key);
      });
    });
  }
};

//store metadata to db
var insertDB = function(req, res, key) {
  var metaData = imageData.imageData(key);

  response(req, res, metaData.key);
};

var response = function(req, res, key) {
  var response = {};

  response.createdAt = new Date();
  response.imgId = key;

  helpers.helper.write(req, res, 201, JSON.stringify(response));
};<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------

/// <reference path="../testFramework.js" />

function definePushTestsNamespace() {
    var tests = [],
        channelUri,
        registrationWaitInterval = 10000;

    var testTemplate = {
            body: '<toast><visual><binding template="ToastText01"><text id="1">$(message)</text></binding></visual></toast>',
            name: 'templateForToastWinJS',
            headers: {
                'X-WNS-Type': 'wns/toast',
                'X-WNS-TTL': '1000'
            },
            lowerHeaders: {
                'x-wns-type': 'wns/toast',
                'x-wns-ttl': '1000'
            },
            tags: [ 'World' ]
    };

    var pushNotifications = Windows.Networking.PushNotifications;
    var pushNotificationQueue = [];

    var onPushNotificationReceived = function (e) {
        var notificationPayload;
        switch (e.notificationType) {
            case pushNotifications.PushNotificationType.toast:
                notificationPayload = e.toastNotification.content.getXml();
                break;

            case pushNotifications.PushNotificationType.tile:
                notificationPayload = e.tileNotification.content.getXml();
                break;

            case pushNotifications.PushNotificationType.badge:
                notificationPayload = e.badgeNotification.content.getXml();
                break;

            case pushNotifications.PushNotificationType.raw:
                notificationPayload = e.rawNotification.content;
                break;
        }
        pushNotificationQueue.push({ type: e.notificationType, content: notificationPayload });
    };

    function waitForNotification(timeout, timeAfterPush, continuation) {
        /// <param name="timeout" type="Number">Time to wait for push notification in milliseconds</param>
        /// <param name="timeAfterPush" type="Number">Time to sleep after a push is received. Used to prevent
        ///            blasting the push notification service.</param>
        /// <param name="continuation" type="function(Object)">Function called when the timeout expires.
        ///            If there was a push notification, it will be passed; otherwise null will be passed
        ///            to the function.</param>
        if (typeof timeAfterPush === 'function') {
            continuation = timeAfterPush;
            timeAfterPush = 3000; // default to 3 seconds
        }
        var start = Date.now();
        var waitForPush = function () {
            var now = Date.now();
            if (pushNotificationQueue.length) {
                var notification = pushNotificationQueue.pop();
                setTimeout(function () {
                    continuation(notification);
                }, timeAfterPush);
            } else {
                if ((now - start) > timeout) {
                    continuation(null); // Timed out
                } else {
                    setTimeout(waitForPush, 500); // try it again in 500ms
                }
            }
        }

        waitForPush();
    };

    tests.push(new zumo.Test('InitialDeleteRegistrations', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                return zumo.getClient().push.unregisterAll(channel.uri);
            })
            .then(getRegistrations(channelUri, 'wns'))
            .then(function (registrations) {
                zumo.assert.isTrue(Array.isArray(registrations));
                zumo.assert.areEqual(0, registrations.length);
                zumo.assert.areEqual('{}', JSON.stringify(zumo.getClient().push._registrationManager._storageManager._registrations));
                return true;
            })
            .done(done, fail(test, done));
    }));

    tests.push(new zumo.Test('RegisterNative', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                zumo.getClient().push.registerNative(channelUri, [ 'tag1' ]);
                channel.onpushnotificationreceived = onPushNotificationReceived;
            })
            .then(wait(registrationWaitInterval))
            .then(getRegistrations(channelUri, 'wns'))
            .then(function (registrations) {
                zumo.assert.isTrue(Array.isArray(registrations));
                zumo.assert.areEqual(1, registrations.length);
                zumo.assert.areEqual('{"$Default":"' + registrations[0].registrationId + '"}', JSON.stringify(zumo.getClient().push._registrationManager._storageManager._registrations));
                return true;
            })
            .done(done, fail(test, done));
    }));

    tests.push(createPushTest('wns',
        'toast',
        'tag1',
        '<?xml version="1.0"?><toast><visual><binding template="ToastText01"><text id="1">hello world</text></binding></visual></toast>'));

    tests.push(new zumo.Test('UnregisterNative', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                return zumo.getClient().push.unregisterNative();
            })
            .then(getRegistrations(channelUri, 'wns'))
            .then(function (registrations) {
                zumo.assert.isTrue(Array.isArray(registrations));
                zumo.assert.areEqual(0, registrations.length);
                zumo.assert.areEqual('{}', JSON.stringify(zumo.getClient().push._registrationManager._storageManager._registrations));
                return true;
            })
            .done(done, fail(test, done));
    }));

    tests.push(new zumo.Test('RegisterWithTemplate', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                zumo.getClient().push.registerTemplate(channelUri, testTemplate.body, testTemplate.name, testTemplate.headers, testTemplate.tags);
                channel.onpushnotificationreceived = onPushNotificationReceived;
            })
            .then(wait(registrationWaitInterval))
            .then(getRegistrations(channelUri, 'wns'))
            .then(function (registrations) {
                zumo.assert.isTrue(Array.isArray(registrations));
                zumo.assert.areEqual(1, registrations.length);
                zumo.assert.areEqual('{"templateForToastWinJS":"' + registrations[0].registrationId + '"}', JSON.stringify(zumo.getClient().push._registrationManager._storageManager._registrations));
                zumo.assert.areEqual(zumo.getClient().push._registrationManager._storageManager.pushHandle, registrations[0].deviceId, 'Local storage should have channelUri from returned registrations');
                zumo.assert.areEqual(registrations[0].deviceId, channelUri, 'Returned registrations should use channelUri sent from registered template');
                Object.getOwnPropertyNames(registrations[0].headers).forEach(function (header) {
                    zumo.assert.areEqual(registrations[0].headers[header], testTemplate.lowerHeaders[header.toLowerCase()], 'Each header returned by registration should match what was registered');
                });
                zumo.assert.areEqual(Object.getOwnPropertyNames(registrations[0].headers).length, Object.getOwnPropertyNames(testTemplate.headers).length, 'Returned registration should contain same number of headers sent from registered template');

                var features = zumo.util.globalTestParams[zumo.constants.RUNTIME_FEATURES_KEY];
                if (features === undefined) {
                    throw 'Runtime features undefined, run "tests setup" test group first';
                }
                else if (features[zumo.runtimeFeatureNames.DotNetRuntime_Only]) {
                    zumo.assert.areEqual(registrations[0].tags.length, testTemplate.tags.length, 'Returned registration should contain tags sent from registered template');
                } else {
                    zumo.assert.areEqual(registrations[0].tags.length, testTemplate.tags.length + 1, 'Returned registration should contain tags sent from registered template and 1 extra for installationId');
                    zumo.assert.isTrue(registrations[0].tags.indexOf(WindowsAzure.MobileServiceClient._applicationInstallationId) > -1, 'Expected the installationID in the tags');
                }
                zumo.assert.areEqual(registrations[0].templateName, testTemplate.name, 'Expected returned registration to use templateName it was fed');
                zumo.assert.areEqual(registrations[0].templateBody, testTemplate.body, 'Expected returned registration to use templateBody it was fed');
                zumo.assert.areEqual(zumo.getClient().push._registrationManager._storageManager.getRegistrationIdWithName(testTemplate.name), registrations[0].registrationId, 'Expected the stored registrationId to equal the one returned from service');
                return true;
            })
            .done(done, fail(test, done));
    }));

    tests.push(createPushTest('template',
        'toast',
        'World',
        '{ message: "hello world template" }',
        '<toast><visual><binding template="ToastText01"><text id="1">hello world template</text></binding></visual></toast>'));

    tests.push(new zumo.Test('UnregisterTemplate', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                return zumo.getClient().push.unregisterTemplate(testTemplate.name);
            })
            .then(getRegistrations(channelUri, 'wns'))
            .then(function (registrations) {
                zumo.assert.isTrue(Array.isArray(registrations));
                zumo.assert.areEqual(0, registrations.length);
                zumo.assert.areEqual('{}', JSON.stringify(zumo.getClient().push._registrationManager._storageManager._registrations));
                return true;
            })
            .done(done, fail(test, done));
    }));

    tests.push(new zumo.Test('RegisterMultiple', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                return zumo.getClient().push.registerNative(channelUri);
            })
            .then(function () {
                return zumo.getClient().push.registerTemplate(channelUri, testTemplate.body, testTemplate.name, testTemplate.headers, testTemplate.tags);
            })
            .then(function () {
                return zumo.getClient().push.registerNative(channelUri);
            })
            .then(wait(registrationWaitInterval))
            .then(getRegistrations(channelUri, 'wns'))
            .then(function (registrations) {
                zumo.assert.isTrue(Array.isArray(registrations));
                zumo.assert.areEqual(2, registrations.length);
                return true;
            })
            .then(function () {
                return zumo.getClient().push.unregisterAll(channelUri);
            })
            .then(getRegistrations(channelUri, 'wns'))
            .then(function (registrations) {
                zumo.assert.isTrue(Array.isArray(registrations));
                zumo.assert.areEqual(0, registrations.length);
                zumo.assert.areEqual('{}', JSON.stringify(zumo.getClient().push._registrationManager._storageManager._registrations));
                return true;
            })
            .done(done, fail(test, done));
    }));

    function createPushTest(provider, method, tag, payload, expectedPayload) {

        var testName = 'Test for ' + provider + '/' + method;

        if (!expectedPayload) {
            expectedPayload = payload;
        }

        return new zumo.Test(testName, function (test, done) {
            test.addLog('Test for provider ', provider, ', method ', method, ', tag ', tag, ', payload ', payload);
            var client = zumo.getClient();

            client.invokeApi('push', {
                method: 'POST',
                body: {
                    method: 'send',
                    type: provider,
                    payload: payload,
                    token: 'dummy',
                    pushType: method,
                    tag: tag
                }
            }).done(function (response) {
                waitForNotification(15000, function (notification) {
                    if (notification) {
                        test.addLog('Notification received: ', notification);
                        if (notification.type !== pushNotifications.PushNotificationType.toast) {
                            test.addLog('Error, notification type (', notification.type, ') is not the expected (', pushNotifications.PushNotificationType.toast, ')');
                            done(false);
                        } else {
                            if (notification.content !== expectedPayload) {
                                test.addLog('Error, notification payload (', notification.content, ') is not the expected (', expectedPayload, ')');
                                done(false);
                            } else {
                                test.addLog('Push notification received successfully');
                                done(true);
                            }
                        }
                    } else {
                        test.addLog('Error, push not received on the allowed timeout');
                        done(false);
                    }
                });
            }, function (error) {
                test.addLog('Error calling push api, ' + error.toString);
            });
        });
    }

    return {
        name: 'Push',
        tests: tests
    };
}

function getRegistrations(channelUri, platform) {
    return function () {
        return new WinJS.Promise(function (complete) {
            zumo.getClient().push._registrationManager._pushHttpClient.listRegistrations(channelUri, platform, function (error, registrations) {
                complete(registrations);
            });
        });
    }
}

function wait(interval) {
    return function () {
        return WinJS.Promise.timeout(interval);
    }
}

function fail(test, done) {
    return function (error) {
        test.addLog('Error occurred: ', error);
        done(false);
    }
}

zumo.tests.push = definePushTestsNamespace();
<commit_msg>Clearer Registration Verification<commit_after>// ----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------

/// <reference path="../testFramework.js" />

function definePushTestsNamespace() {
    var tests = [],
        channelUri,
        registrationWaitInterval = 10000;

    var testTemplate = {
            body: '<toast><visual><binding template="ToastText01"><text id="1">$(message)</text></binding></visual></toast>',
            name: 'templateForToastWinJS',
            headers: {
                'X-WNS-Type': 'wns/toast',
                'X-WNS-TTL': '1000'
            },
            lowerHeaders: {
                'x-wns-type': 'wns/toast',
                'x-wns-ttl': '1000'
            },
            tags: [ 'World' ]
    };

    var pushNotifications = Windows.Networking.PushNotifications;
    var pushNotificationQueue = [];

    var onPushNotificationReceived = function (e) {
        var notificationPayload;
        switch (e.notificationType) {
            case pushNotifications.PushNotificationType.toast:
                notificationPayload = e.toastNotification.content.getXml();
                break;

            case pushNotifications.PushNotificationType.tile:
                notificationPayload = e.tileNotification.content.getXml();
                break;

            case pushNotifications.PushNotificationType.badge:
                notificationPayload = e.badgeNotification.content.getXml();
                break;

            case pushNotifications.PushNotificationType.raw:
                notificationPayload = e.rawNotification.content;
                break;
        }
        pushNotificationQueue.push({ type: e.notificationType, content: notificationPayload });
    };

    function waitForNotification(timeout, timeAfterPush, continuation) {
        /// <param name="timeout" type="Number">Time to wait for push notification in milliseconds</param>
        /// <param name="timeAfterPush" type="Number">Time to sleep after a push is received. Used to prevent
        ///            blasting the push notification service.</param>
        /// <param name="continuation" type="function(Object)">Function called when the timeout expires.
        ///            If there was a push notification, it will be passed; otherwise null will be passed
        ///            to the function.</param>
        if (typeof timeAfterPush === 'function') {
            continuation = timeAfterPush;
            timeAfterPush = 3000; // default to 3 seconds
        }
        var start = Date.now();
        var waitForPush = function () {
            var now = Date.now();
            if (pushNotificationQueue.length) {
                var notification = pushNotificationQueue.pop();
                setTimeout(function () {
                    continuation(notification);
                }, timeAfterPush);
            } else {
                if ((now - start) > timeout) {
                    continuation(null); // Timed out
                } else {
                    setTimeout(waitForPush, 500); // try it again in 500ms
                }
            }
        }

        waitForPush();
    };

    tests.push(new zumo.Test('InitialDeleteRegistrations', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                return zumo.getClient().push.unregisterAll(channel.uri);
            })
            .then(getRegistrations(channelUri, 'wns'))
            .then(testRegistrations(0))
            .done(done, fail(test, done));
    }));

    tests.push(new zumo.Test('RegisterNative', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                zumo.getClient().push.registerNative(channelUri, [ 'tag1' ]);
                channel.onpushnotificationreceived = onPushNotificationReceived;
            })
            .then(wait(registrationWaitInterval))
            .then(getRegistrations(channelUri, 'wns'))
            .then(testRegistrations(1))
            .done(done, fail(test, done));
    }));

    tests.push(createPushTest('wns',
        'toast',
        'tag1',
        '<?xml version="1.0"?><toast><visual><binding template="ToastText01"><text id="1">hello world</text></binding></visual></toast>'));

    tests.push(new zumo.Test('UnregisterNative', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                return zumo.getClient().push.unregisterNative();
            })
            .then(getRegistrations(channelUri, 'wns'))
            .then(testRegistrations(0))
            .done(done, fail(test, done));
    }));

    tests.push(new zumo.Test('RegisterWithTemplate', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                zumo.getClient().push.registerTemplate(channelUri, testTemplate.body, testTemplate.name, testTemplate.headers, testTemplate.tags);
                channel.onpushnotificationreceived = onPushNotificationReceived;
            })
            .then(wait(registrationWaitInterval))
            .then(getRegistrations(channelUri, 'wns'))
            .then(testRegistrations(1, function (registrations) {
                zumo.assert.areEqual(registrations[0].deviceId, channelUri, 'Returned registrations should use channelUri sent from registered template');
                Object.getOwnPropertyNames(registrations[0].headers).forEach(function (header) {
                    zumo.assert.areEqual(registrations[0].headers[header], testTemplate.lowerHeaders[header.toLowerCase()], 'Each header returned by registration should match what was registered');
                });
                zumo.assert.areEqual(Object.getOwnPropertyNames(registrations[0].headers).length, Object.getOwnPropertyNames(testTemplate.headers).length, 'Returned registration should contain same number of headers sent from registered template');

                var features = zumo.util.globalTestParams[zumo.constants.RUNTIME_FEATURES_KEY];
                if (features === undefined) {
                    throw 'Runtime features undefined, run "tests setup" test group first';
                }
                else if (features[zumo.runtimeFeatureNames.DotNetRuntime_Only]) {
                    zumo.assert.areEqual(registrations[0].tags.length, testTemplate.tags.length, 'Returned registration should contain tags sent from registered template');
                } else {
                    zumo.assert.areEqual(registrations[0].tags.length, testTemplate.tags.length + 1, 'Returned registration should contain tags sent from registered template and 1 extra for installationId');
                    zumo.assert.isTrue(registrations[0].tags.indexOf(WindowsAzure.MobileServiceClient._applicationInstallationId) > -1, 'Expected the installationID in the tags');
                }
                zumo.assert.areEqual(registrations[0].templateName, testTemplate.name, 'Expected returned registration to use templateName it was fed');
                zumo.assert.areEqual(registrations[0].templateBody, testTemplate.body, 'Expected returned registration to use templateBody it was fed');
            }))
            .done(done, fail(test, done));
    }));

    tests.push(createPushTest('template',
        'toast',
        'World',
        '{ message: "hello world template" }',
        '<toast><visual><binding template="ToastText01"><text id="1">hello world template</text></binding></visual></toast>'));

    tests.push(new zumo.Test('UnregisterTemplate', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                return zumo.getClient().push.unregisterTemplate(testTemplate.name);
            })
            .then(getRegistrations(channelUri, 'wns'))
            .then(testRegistrations(0))
            .done(done, fail(test, done));
    }));

    tests.push(new zumo.Test('RegisterMultiple', function (test, done) {
        testPlatform.getPushChannel()
            .then(function (channel) {
                channelUri = channel.uri;
                return zumo.getClient().push.registerNative(channelUri);
            })
            .then(function () {
                return zumo.getClient().push.registerTemplate(channelUri, testTemplate.body, testTemplate.name, testTemplate.headers, testTemplate.tags);
            })
            .then(function () {
                return zumo.getClient().push.registerNative(channelUri);
            })
            .then(wait(registrationWaitInterval))
            .then(getRegistrations(channelUri, 'wns'))
            .then(testRegistrations(2))
            .then(function () {
                return zumo.getClient().push.unregisterAll(channelUri);
            })
            .then(getRegistrations(channelUri, 'wns'))
            .then(testRegistrations(0))
            .done(done, fail(test, done));
    }));

    function createPushTest(provider, method, tag, payload, expectedPayload) {
        var testName = 'Test for ' + provider + '/' + method;

        if (!expectedPayload) {
            expectedPayload = payload;
        }

        return new zumo.Test(testName, function (test, done) {
            test.addLog('Test for provider ', provider, ', method ', method, ', tag ', tag, ', payload ', payload);
            var client = zumo.getClient();

            client.invokeApi('push', {
                method: 'POST',
                body: {
                    method: 'send',
                    type: provider,
                    payload: payload,
                    token: 'dummy',
                    pushType: method,
                    tag: tag
                }
            }).done(function (response) {
                waitForNotification(15000, function (notification) {
                    if (notification) {
                        test.addLog('Notification received: ', notification);
                        if (notification.type !== pushNotifications.PushNotificationType.toast) {
                            test.addLog('Error, notification type (', notification.type, ') is not the expected (', pushNotifications.PushNotificationType.toast, ')');
                            done(false);
                        } else {
                            if (notification.content !== expectedPayload) {
                                test.addLog('Error, notification payload (', notification.content, ') is not the expected (', expectedPayload, ')');
                                done(false);
                            } else {
                                test.addLog('Push notification received successfully');
                                done(true);
                            }
                        }
                    } else {
                        test.addLog('Error, push not received on the allowed timeout');
                        done(false);
                    }
                });
            }, function (error) {
                test.addLog('Error calling push api, ' + error.toString);
            });
        });
    }

    return {
        name: 'Push',
        tests: tests
    };
}

function getRegistrations(channelUri, platform) {
    return function () {
        return new WinJS.Promise(function (complete) {
            zumo.getClient().push._registrationManager._pushHttpClient.listRegistrations(channelUri, platform, function (error, registrations) {
                complete(registrations);
            });
        });
    }
}

function testRegistrations(count, verify) {
    return function testRegistrations(registrations) {
        zumo.assert.isTrue(Array.isArray(registrations));
        zumo.assert.areEqual(count, registrations.length);

        if (typeof verify !== 'undefined') {
            verify(registrations);
        }

        return true;
    }
}

function wait(interval) {
    return function () {
        return WinJS.Promise.timeout(interval);
    }
}

function fail(test, done) {
    return function (error) {
        test.addLog('Error occurred: ', error);
        done(false);
    }
}

zumo.tests.push = definePushTestsNamespace();
<|endoftext|>


<commit_before>moj.Helpers.SideBar = {
  Base: function(options) {
    var _options = {
      type: '_Base',
      vatfactor: 0.2,
      autoVAT: false
    };
    this.config = $.extend({}, _options, options);
    this.$el = this.config.$el;
    this.el = this.config.el;

    this.getConfig = function(key) {
      return this.config[key] || undefined;
    };

    this.updateTotals = function() {
      return 'This method needs an override';
    };

    this.isVisible = function() {
      return this.$el.find('.rate').is(':visible') || this.$el.find('.amount').is(':visible') || this.$el.find('.total').is(':visible');
    };

    this.applyVat = function() {
      if (this.config.autoVAT) {
        this.totals.vat = this.totals.total * this.config.vatfactor;
      }
    };

    this.getVal = function(selector) {
      return parseFloat(this.$el.find(selector + ':visible').val()) || 0;
    };

    this.getDataVal = function(selector) {
      return parseFloat(this.$el.find('.' + selector).data('total')) || false;
    };

    this.getMultipliedVal = function(val1, val2) {
      return parseFloat((this.getVal(val1) * this.getVal(val2)).toFixed(2));
    }
  },
  FeeBlock: function() {
    var self = this;
    // copy methods over
    moj.Helpers.SideBar.Base.apply(this, arguments);
    this.totals = {
      quantity: 0,
      rate: 0,
      amount: 0,
      total: 0,
      vat: 0
    };

    this.init = function() {
      this.config.fn = 'FeeBlock';
      this.bindRecalculate();
      return this;
    };

    this.bindRecalculate = function() {
      this.$el.on('change', '.quantity, .rate, .amount, .vat, .total', function(e) {
        self.$el.trigger('recalculate');
      });
    };

    this.reload = function() {
      this.updateTotals();
      this.applyVat();
      return this;
    };

    this.setTotals = function() {
      this.totals = {
        quantity: this.getVal('.quantity'),
        rate: this.getVal('.rate'),
        amount: this.getVal('.amount'),
        total: this.getDataVal('total') || this.getVal('.total'),
        vat: this.getVal('.vat')
      };

      this.totals.typeTotal = this.totals.total;
      return this.totals;
    };

    this.updateTotals = function(a) {
      if (!this.isVisible()) {
        return this.totals;
      }
      return this.setTotals();
    };

    this.render = function() {
      // TODO: Can this be removed? Investigate across block types.
      this.$el.find('.total').html('£' + moj.Helpers.SideBar.addCommas(this.totals.total.toFixed(2)));
      this.$el.find('.total').data('total', this.totals.total);
    };
  },
  FeeBlockCalculator: function() {
    var self = this;
    moj.Helpers.SideBar.FeeBlock.apply(this, arguments);

    this.init = function() {
      this.config.fn = 'FeeBlockCalculator';
      this.bindRecalculate();
      this.bindRender();
      return this;
    };

    this.setTotals = function() {
      this.totals = {
        quantity: this.getVal('.quantity'),
        rate: this.getVal('.rate'),
        amount: this.getVal('.amount'),
        total: this.getMultipliedVal('.quantity', '.rate'),
        vat: this.getVal('.vat')
      };

      this.totals.typeTotal = this.totals.total;
      return this.totals;
    };

    this.bindRender = function() {
      this.$el.on('change', '.quantity, .rate', function() {
        self.updateTotals();
        self.render();
      });
    };
  },
  FeeBlockManualAmounts: function() {
    var self = this;
    moj.Helpers.SideBar.FeeBlock.apply(this, arguments);

    this.init = function() {
      this.config.fn = 'FeeBlockManualAmounts';

      this.bindRecalculate();
      this.bindRender();
      this.setTotals();
      return this;
    };

    this.setTotals = function() {
      this.totals = {
        quantity: this.getVal('.quantity'),
        rate: this.getVal('.rate'),
        amount: this.getVal('.amount'),
        total: parseFloat((this.getVal('.amount') + this.getVal('.vat')).toFixed(2)),
        vat: this.getVal('.vat')
      };
      this.totals.typeTotal = this.totals.amount;
      return this.totals;
    };

    this.bindRender = function() {
      this.$el.on('change', '.amount, .vat', function() {
        self.updateTotals();
        self.render();
      });
    };
  },
  PhantomBlock: function() {
    var self = this;
    moj.Helpers.SideBar.Base.apply(this, arguments);
    this.totals = {
      quantity: 0,
      rate: 0,
      amount: 0,
      total: 0,
      vat: 0
    };

    this.isVisible = function() {
      return true;
    };

    this.reload = function() {
      this.totals.total = (parseFloat(this.$el.data('seed')) || 0);
      this.totals.typeTotal = this.totals.total;

      if (this.config.autoVAT) {
        this.totals.vat = this.totals.total * 0.2;
      } else {
        this.totals.vat = (parseFloat(this.$el.data('seed-vat')) || 0)
      }
      return this;
    };

    this.init = function() {
      return this;
    }
  },
  ExpenseBlock: function() {
    var self = this;
    var staticdata = moj.Helpers.SideBar.staticdata.expenseBlock;
    moj.Helpers.SideBar.FeeBlock.apply(this, arguments);

    this.stateLookup = staticdata.stateLookup;
    this.defaultstate = staticdata.defaultstate;
    this.expenseReasons = staticdata.expenseReasons;

    this.init = function() {
      this.config.fn = 'ExpenseBlock';

      // Overides for LGFS reason set C;
      // NOT REQUIRED IN THE DESIGN UPGRADE
      // this.config.featureDistance = $('#expenses').data('featureDistance');
      //
      // Bind events
      this.bindEvents();
      // Load the state based on the selected option
      this.loadCurrentState();
      return this;
    };
    this.bindEvents = function() {
      // Bind the core change listner
      this.bindRecalculate();

      // Bind events on the this.$el element
      this.bindListners();
    };
    // Bind delegated events onto this.$el
    this.bindListners = function() {
      var self = this;
      /**
       * Listen for the `expense type` change event and
       * pass the event object to the statemanager
       */
      this.$el.on('change', '.fx-travel-expense-type select', function(e) {
        self.statemanager(e);
      });
      /**
       * Travel reason change event
       * - extract the `other reason` input state var and call toggle on it
       * - set the hidden `location_type` to the selected val
       *   this is used to reset to the correct line in the select box
       *   when the user returns to the page
       */
      this.$el.on('change', '.fx-travel-reason select', function(e) {
        var $option, state, location_type;

        $option = $(e.target).find('option:selected');
        state = $option.data('reasonText');
        location_type = $option.data('locationType') || '';
        self.$el.find('.fx-location-type').val(location_type)
        self.$el.find('.fx-travel-reason-other').css('display', state ? 'block' : 'none');
      });
      return this;
    };
    this.loadCurrentState = function() {
      var $select = this.$el.find('.fx-travel-expense-type select');
      if ($select.val()) {
        $select.trigger('change');
      }
    };
    this.setTotals = function() {
      this.totals = {
        quantity: this.getVal('.quantity'),
        rate: this.getVal('.rate'),
        amount: this.getVal('.amount'),
        total: this.getVal('.rate'),
        vat: this.getVal('.vat')
      };
      this.totals.typeTotal = this.totals.total;
      return this.totals;
    };

    /**
     * statemanager: Controlling the visiblilty of form elements
     * @param  {object} e jQuery event object
     * @return this
     */
    this.statemanager = function(e) {
      var self = this;
      var reasons = [];
      var $el = $(e.target);
      var state = {
        config: $.extend({}, this.defaultstate, $el.find('option:selected').data()),
        value: $el.val()
      };
      var $parent = $el.closest('.js-block');
      var $detached = $parent.find('.form-section-compound').detach();
      var locationType = $detached.find('.fx-location-type').val();
      var travelReasonValue = $detached.find('.fx-travel-reason option:selected').val();
      // regular fields
      ['date',
        'distance',
        'hours',
        'mileage',
        'reason',
        'vatAmount'
      ].forEach(function(value, idx) {
        $detached.find(self.stateLookup[value]).css('display', (state.config[value] ? 'block' : 'none'));
      });
      // net amount & lable
      $detached.find(this.stateLookup['netAmount']).css('display', (state.config['date'] ? 'block' : 'none'));
      $detached.find(this.stateLookup['netAmount'] + ' label').text(state.config['netAmountLabel']);
      // location & lable
      $detached.find(this.stateLookup['location']).css('display', (state.config['date'] ? 'block' : 'none'));
      $detached.find(this.stateLookup['location'] + ' label').text(state.config['locationLabel']);

      // Overides for LGFS reason set C;
      // NOT REQUIRED IN THE DESIGN UPGRADE
      // state.config.reasonSet = (this.config.featureDistance ? 'C' : (state.config.reasonSet || 'A'));

      // travel reasons
      reasons.push(new Option('Please select'));
      this.expenseReasons[state.config.reasonSet].forEach(function(obj) {
        $option = $(new Option(obj.reason, obj.id));
        $option.attr('data-reason-text', obj.reason_text)
        $option.attr('data-location-type', obj.location_type)
        if (locationType) {
          if (obj.location_type == locationType && obj.id == travelReasonValue) {
            $option.prop('selected', true);
          }
        } else {
          if (obj.id == travelReasonValue) {
            $option.prop('selected', true);
          }
        }
        reasons.push($option)
      });
      // Attach the travel reasons
      $detached.find('.fx-travel-reason select').children().remove().end().append(reasons);
      // Mileage radios: BIKE
      if (state.config.mileageType === 'bike') {
        // Display the correct block
        $detached.find('.fx-travel-mileage-car').css('display', 'none');
        $detached.find('.fx-travel-mileage-bike').css('display', 'block');
        // Activate the radios for this block and reset checked status
        $detached.find('.fx-travel-mileage-bike input[type=radio]').is(function() {
          $(this).prop('checked', true).prop('disabled', false);
        });
        // Deactivate the others and reset checked status
        $detached.find('.fx-travel-mileage-car input[type=radio]').is(function() {
          $(this).prop('checked', false).prop('disabled', true);
        });
      }
      // Mileage radios: BIKE
      if (state.config.mileageType === 'car') {
        // Display the correct block
        $detached.find('.fx-travel-mileage-car').css('display', 'block');
        $detached.find('.fx-travel-mileage-bike').css('display', 'none');
        // Activate the radios for this block and reset checked status
        $detached.find('.fx-travel-mileage-car input[type=radio]').is(function() {
          $(this).prop('disabled', false);
        });
        // Deactivate the others and reset checked status
        $detached.find('.fx-travel-mileage-bike input[type=radio]').is(function() {
          $(this).prop('checked', false).prop('disabled', true);
        });
      }
      return $parent.append($detached);
    };
  },
  staticdata: {
    expenseBlock: {
      stateLookup: {
        "vatAmount": ".fx-travel-vat-amount",
        "reason": ".fx-travel-reason",
        "netAmount": ".fx-travel-net-amount",
        "location": ".fx-travel-location",
        "hours": ".fx-travel-hours",
        "distance": ".fx-travel-distance",
        "destination": ".fx-travel-destination",
        "date": ".fx-travel-date",
        "mileage": ".fx-travel-mileage",
        "grossAmount": ".fx-travel-gross-amount"
      },
      defaultstate: {
        "mileage": false,
        "date": false,
        "distance": false,
        "grossAmount": false,
        "hours": false,
        "location": false,
        "netAmount": false,
        "reason": false,
        "vatAmount": false,
      },
      expenseReasons: {
        "A": [{
          "id": 1,
          "reason": "Court hearing",
          "reason_text": false
        }, {
          "id": 2,
          "reason": "Pre-trial conference expert witnesses",
          "reason_text": false
        }, {
          "id": 3,
          "reason": "Pre-trial conference defendant",
          "reason_text": false
        }, {
          "id": 4,
          "reason": "View of crime scene",
          "reason_text": false
        }, {
          "id": 5,
          "reason": "Other",
          "reason_text": true
        }],
        "B": [{
          "id": 2,
          "reason": "Pre-trial conference expert witnesses",
          "reason_text": false
        }, {
          "id": 3,
          "reason": "Pre-trial conference defendant",
          "reason_text": false
        }, {
          "id": 4,
          "reason": "View of crime scene",
          "reason_text": false
        }]
      }
    }
  },
  addCommas: function(nStr) {
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
      x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
  }
};
<commit_msg>Mileage radios state management<commit_after>moj.Helpers.SideBar = {
  Base: function(options) {
    var _options = {
      type: '_Base',
      vatfactor: 0.2,
      autoVAT: false
    };
    this.config = $.extend({}, _options, options);
    this.$el = this.config.$el;
    this.el = this.config.el;

    this.getConfig = function(key) {
      return this.config[key] || undefined;
    };

    this.updateTotals = function() {
      return 'This method needs an override';
    };

    this.isVisible = function() {
      return this.$el.find('.rate').is(':visible') || this.$el.find('.amount').is(':visible') || this.$el.find('.total').is(':visible');
    };

    this.applyVat = function() {
      if (this.config.autoVAT) {
        this.totals.vat = this.totals.total * this.config.vatfactor;
      }
    };

    this.getVal = function(selector) {
      return parseFloat(this.$el.find(selector + ':visible').val()) || 0;
    };

    this.getDataVal = function(selector) {
      return parseFloat(this.$el.find('.' + selector).data('total')) || false;
    };

    this.getMultipliedVal = function(val1, val2) {
      return parseFloat((this.getVal(val1) * this.getVal(val2)).toFixed(2));
    }
  },
  FeeBlock: function() {
    var self = this;
    // copy methods over
    moj.Helpers.SideBar.Base.apply(this, arguments);
    this.totals = {
      quantity: 0,
      rate: 0,
      amount: 0,
      total: 0,
      vat: 0
    };

    this.init = function() {
      this.config.fn = 'FeeBlock';
      this.bindRecalculate();
      return this;
    };

    this.bindRecalculate = function() {
      this.$el.on('change', '.quantity, .rate, .amount, .vat, .total', function(e) {
        self.$el.trigger('recalculate');
      });
    };

    this.reload = function() {
      this.updateTotals();
      this.applyVat();
      return this;
    };

    this.setTotals = function() {
      this.totals = {
        quantity: this.getVal('.quantity'),
        rate: this.getVal('.rate'),
        amount: this.getVal('.amount'),
        total: this.getDataVal('total') || this.getVal('.total'),
        vat: this.getVal('.vat')
      };

      this.totals.typeTotal = this.totals.total;
      return this.totals;
    };

    this.updateTotals = function(a) {
      if (!this.isVisible()) {
        return this.totals;
      }
      return this.setTotals();
    };

    this.render = function() {
      // TODO: Can this be removed? Investigate across block types.
      this.$el.find('.total').html('£' + moj.Helpers.SideBar.addCommas(this.totals.total.toFixed(2)));
      this.$el.find('.total').data('total', this.totals.total);
    };
  },
  FeeBlockCalculator: function() {
    var self = this;
    moj.Helpers.SideBar.FeeBlock.apply(this, arguments);

    this.init = function() {
      this.config.fn = 'FeeBlockCalculator';
      this.bindRecalculate();
      this.bindRender();
      return this;
    };

    this.setTotals = function() {
      this.totals = {
        quantity: this.getVal('.quantity'),
        rate: this.getVal('.rate'),
        amount: this.getVal('.amount'),
        total: this.getMultipliedVal('.quantity', '.rate'),
        vat: this.getVal('.vat')
      };

      this.totals.typeTotal = this.totals.total;
      return this.totals;
    };

    this.bindRender = function() {
      this.$el.on('change', '.quantity, .rate', function() {
        self.updateTotals();
        self.render();
      });
    };
  },
  FeeBlockManualAmounts: function() {
    var self = this;
    moj.Helpers.SideBar.FeeBlock.apply(this, arguments);

    this.init = function() {
      this.config.fn = 'FeeBlockManualAmounts';

      this.bindRecalculate();
      this.bindRender();
      this.setTotals();
      return this;
    };

    this.setTotals = function() {
      this.totals = {
        quantity: this.getVal('.quantity'),
        rate: this.getVal('.rate'),
        amount: this.getVal('.amount'),
        total: parseFloat((this.getVal('.amount') + this.getVal('.vat')).toFixed(2)),
        vat: this.getVal('.vat')
      };
      this.totals.typeTotal = this.totals.amount;
      return this.totals;
    };

    this.bindRender = function() {
      this.$el.on('change', '.amount, .vat', function() {
        self.updateTotals();
        self.render();
      });
    };
  },
  PhantomBlock: function() {
    var self = this;
    moj.Helpers.SideBar.Base.apply(this, arguments);
    this.totals = {
      quantity: 0,
      rate: 0,
      amount: 0,
      total: 0,
      vat: 0
    };

    this.isVisible = function() {
      return true;
    };

    this.reload = function() {
      this.totals.total = (parseFloat(this.$el.data('seed')) || 0);
      this.totals.typeTotal = this.totals.total;

      if (this.config.autoVAT) {
        this.totals.vat = this.totals.total * 0.2;
      } else {
        this.totals.vat = (parseFloat(this.$el.data('seed-vat')) || 0)
      }
      return this;
    };

    this.init = function() {
      return this;
    }
  },
  ExpenseBlock: function() {
    var self = this;
    var staticdata = moj.Helpers.SideBar.staticdata.expenseBlock;
    moj.Helpers.SideBar.FeeBlock.apply(this, arguments);

    this.stateLookup = staticdata.stateLookup;
    this.defaultstate = staticdata.defaultstate;
    this.expenseReasons = staticdata.expenseReasons;

    this.init = function() {
      this.config.fn = 'ExpenseBlock';

      // Overides for LGFS reason set C;
      // NOT REQUIRED IN THE DESIGN UPGRADE
      // this.config.featureDistance = $('#expenses').data('featureDistance');
      //
      // Bind events
      this.bindEvents();
      // Load the state based on the selected option
      this.loadCurrentState();
      return this;
    };
    this.bindEvents = function() {
      // Bind the core change listner
      this.bindRecalculate();

      // Bind events on the this.$el element
      this.bindListners();
    };
    // Bind delegated events onto this.$el
    this.bindListners = function() {
      var self = this;
      /**
       * Listen for the `expense type` change event and
       * pass the event object to the statemanager
       */
      this.$el.on('change', '.fx-travel-expense-type select', function(e) {
        self.statemanager(e);
      });
      /**
       * Travel reason change event
       * - extract the `other reason` input state var and call toggle on it
       * - set the hidden `location_type` to the selected val
       *   this is used to reset to the correct line in the select box
       *   when the user returns to the page
       */
      this.$el.on('change', '.fx-travel-reason select', function(e) {
        var $option, state, location_type;

        $option = $(e.target).find('option:selected');
        state = $option.data('reasonText');
        location_type = $option.data('locationType') || '';
        self.$el.find('.fx-location-type').val(location_type)
        self.$el.find('.fx-travel-reason-other').css('display', state ? 'block' : 'none');
      });
      return this;
    };
    this.loadCurrentState = function() {
      var $select = this.$el.find('.fx-travel-expense-type select');
      if ($select.val()) {
        $select.trigger('change');
      }
    };
    this.setTotals = function() {
      this.totals = {
        quantity: this.getVal('.quantity'),
        rate: this.getVal('.rate'),
        amount: this.getVal('.amount'),
        total: this.getVal('.rate'),
        vat: this.getVal('.vat')
      };
      this.totals.typeTotal = this.totals.total;
      return this.totals;
    };

    /**
     * statemanager: Controlling the visiblilty of form elements
     * @param  {object} e jQuery event object
     * @return this
     */
    this.statemanager = function(e) {
      var self = this;
      var reasons = [];
      var $el = $(e.target);
      var state = {
        config: $.extend({}, this.defaultstate, $el.find('option:selected').data()),
        value: $el.val()
      };
      var $parent = $el.closest('.js-block');
      var $detached = $parent.find('.form-section-compound').detach();
      var locationType = $detached.find('.fx-location-type').val();
      var travelReasonValue = $detached.find('.fx-travel-reason option:selected').val();
      // regular fields
      ['date',
        'distance',
        'hours',
        'mileage',
        'reason',
        'vatAmount'
      ].forEach(function(value, idx) {
        $detached.find(self.stateLookup[value]).css('display', (state.config[value] ? 'block' : 'none'));
      });
      // net amount & lable
      $detached.find(this.stateLookup['netAmount']).css('display', (state.config['date'] ? 'block' : 'none'));
      $detached.find(this.stateLookup['netAmount'] + ' label').text(state.config['netAmountLabel']);
      // location & lable
      $detached.find(this.stateLookup['location']).css('display', (state.config['date'] ? 'block' : 'none'));
      $detached.find(this.stateLookup['location'] + ' label').text(state.config['locationLabel']);

      // Overides for LGFS reason set C;
      // NOT REQUIRED IN THE DESIGN UPGRADE
      // state.config.reasonSet = (this.config.featureDistance ? 'C' : (state.config.reasonSet || 'A'));

      // travel reasons
      reasons.push(new Option('Please select'));
      this.expenseReasons[state.config.reasonSet].forEach(function(obj) {
        $option = $(new Option(obj.reason, obj.id));
        $option.attr('data-reason-text', obj.reason_text)
        $option.attr('data-location-type', obj.location_type)
        if (locationType) {
          if (obj.location_type == locationType && obj.id == travelReasonValue) {
            $option.prop('selected', true);
          }
        } else {
          if (obj.id == travelReasonValue) {
            $option.prop('selected', true);
          }
        }
        reasons.push($option)
      });
      // Attach the travel reasons
      $detached.find('.fx-travel-reason select').children().remove().end().append(reasons);
      // Mileage radios: BIKE
      if (state.config.mileageType === 'bike') {
        // Display the correct block
        $detached.find('.fx-travel-mileage-car').css('display', 'none');
        $detached.find('.fx-travel-mileage-bike').css('display', 'block');
        // Activate the radios for this block and reset checked status
        $detached.find('.fx-travel-mileage-bike input[type=radio]').is(function() {
          $(this).prop('checked', true).prop('disabled', false);
        });
        // Deactivate the others and reset checked status
        $detached.find('.fx-travel-mileage-car input').is(function() {
          $(this).prop('checked', false).prop('disabled', true);
        });
      }
      // Mileage radios: BIKE
      if (state.config.mileageType === 'car') {
        // Display the correct block
        $detached.find('.fx-travel-mileage-car').css('display', 'block');
        $detached.find('.fx-travel-mileage-bike').css('display', 'none');
        // Activate the radios for this block and reset checked status
        $detached.find('.fx-travel-mileage-car input').is(function() {
          $(this).prop('disabled', false);
        });
        // Deactivate the others and reset checked status
        $detached.find('.fx-travel-mileage-bike input').is(function() {
          $(this).prop('checked', false).prop('disabled', true);
        });
      }
      return $parent.append($detached);
    };
  },
  staticdata: {
    expenseBlock: {
      stateLookup: {
        "vatAmount": ".fx-travel-vat-amount",
        "reason": ".fx-travel-reason",
        "netAmount": ".fx-travel-net-amount",
        "location": ".fx-travel-location",
        "hours": ".fx-travel-hours",
        "distance": ".fx-travel-distance",
        "destination": ".fx-travel-destination",
        "date": ".fx-travel-date",
        "mileage": ".fx-travel-mileage",
        "grossAmount": ".fx-travel-gross-amount"
      },
      defaultstate: {
        "mileage": false,
        "date": false,
        "distance": false,
        "grossAmount": false,
        "hours": false,
        "location": false,
        "netAmount": false,
        "reason": false,
        "vatAmount": false,
      },
      expenseReasons: {
        "A": [{
          "id": 1,
          "reason": "Court hearing",
          "reason_text": false
        }, {
          "id": 2,
          "reason": "Pre-trial conference expert witnesses",
          "reason_text": false
        }, {
          "id": 3,
          "reason": "Pre-trial conference defendant",
          "reason_text": false
        }, {
          "id": 4,
          "reason": "View of crime scene",
          "reason_text": false
        }, {
          "id": 5,
          "reason": "Other",
          "reason_text": true
        }],
        "B": [{
          "id": 2,
          "reason": "Pre-trial conference expert witnesses",
          "reason_text": false
        }, {
          "id": 3,
          "reason": "Pre-trial conference defendant",
          "reason_text": false
        }, {
          "id": 4,
          "reason": "View of crime scene",
          "reason_text": false
        }]
      }
    }
  },
  addCommas: function(nStr) {
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
      x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
  }
};
<|endoftext|>


<commit_before>/*
 * This file is part of the AlphaLemon CMS Application and it is distributed
 * under the GPL LICENSE Version 2.0. To use this application you must leave
 * intact this copyright notice.
 *
 * Copyright (c) AlphaLemon <webmaster@alphalemon.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * For extra documentation and help please visit http://www.alphalemon.com
 *
 * @license    GPL LICENSE Version 2.0
 *
 */

InitDialog = function(id, options)
{
    try
    {
        var defaultOptions = {
        autoOpen: false,
        width: 800,
        buttons: {
            "Close": function() {
                $(this).dialog("close");
            }
        }};

        if(id == null) id = "al_dialog";
        if(options !== null) $.extend (defaultOptions, options);

        if($('body').find(id).length == 0)
        {
            $('

')
                    .css("display", "none")
                    .appendTo('body');
        }

        $('#' + id).dialog(defaultOptions);
    }
    catch(e)
    {
        alert(e);
    }
};

GetTopMost = function()
{
    // Credits for this snippet goes to Studio-42 http://elfinder.org
    var zindex = 100;
    $('body').find(':visible').each(function() {
            var $this = $(this), z;
            if ($this.css('position') == 'absolute' && (z = parseInt($this.zIndex())) > zindex) {
                    zindex = z + 1;
            }
    });

    return zindex + 10000;
};

(function($){
    $.fn.showAutoCloseDialog = function(html, width, delay)
    {
        if (width == null) width = 400;
        if (delay == null) delay = 2000;

        var zIndexDialog = GetTopMost();
        var options = {
            width: width,
            zIndex: zIndexDialog,
            buttons: {}
        };

        var message = '
' + html + '
';
        message += '
This window closes automatically in 2 seconds
';

        InitDialog('al_message_success', options);
        $('#al_message_success')
            .html(message)
            .dialog('open')
            .delay(delay)
            .fadeOut(function(){ $(this).dialog("close") });

        return false;
    };

    $.fn.showDialog = function(html, width)
    {
        if (width == null) width = 800;

        var zIndexDialog = GetTopMost();
        var options = {
            width: width,
            zIndex: zIndexDialog,
            hide: 'explode'
        };
        InitDialog('al_dialog', options);
        $('#al_dialog')
            .html(html)
            .dialog('open');

        return false;
    };
})($);<commit_msg>fixed a bug that doesn't show the ajax loader cursor when a panel was opened<commit_after>/*
 * This file is part of the AlphaLemon CMS Application and it is distributed
 * under the GPL LICENSE Version 2.0. To use this application you must leave
 * intact this copyright notice.
 *
 * Copyright (c) AlphaLemon <webmaster@alphalemon.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * For extra documentation and help please visit http://www.alphalemon.com
 *
 * @license    GPL LICENSE Version 2.0
 *
 */

InitDialog = function(id, options)
{
    try
    {
        var defaultOptions = {
        autoOpen: false,
        width: 800,
        buttons: {
            "Close": function() {
                $(this).dialog("close");
            }
        }};

        if(id == null) id = "al_dialog";
        if(options !== null) $.extend (defaultOptions, options);

        if($('body').find(id).length == 0)
        {
            $('

')
                    .css("display", "none")
                    .appendTo('body');
        }

        $('#' + id).dialog(defaultOptions);
    }
    catch(e)
    {
        alert(e);
    }
};

GetTopMost = function()
{
    // Credits for this snippet goes to Studio-42 http://elfinder.org
    var zindex = 100;
    $('body').find(':visible').each(function() {
            var $this = $(this), z;
            if ($this.css('position') != 'static' && (z = parseInt($this.zIndex())) > zindex) {
                    zindex = z + 1;
            }
    });

    return zindex + 10000;
};

(function($){
    $.fn.showAutoCloseDialog = function(html, width, delay)
    {
        if (width == null) width = 400;
        if (delay == null) delay = 2000;

        var zIndexDialog = GetTopMost();
        var options = {
            width: width,
            zIndex: zIndexDialog,
            buttons: {}
        };

        var message = '
' + html + '
';
        message += '
This window closes automatically in 2 seconds
';

        InitDialog('al_message_success', options);
        $('#al_message_success')
            .html(message)
            .dialog('open')
            .delay(delay)
            .fadeOut(function(){ $(this).dialog("close") });

        return false;
    };

    $.fn.showDialog = function(html, width)
    {
        if (width == null) width = 800;

        var zIndexDialog = GetTopMost();
        var options = {
            width: width,
            zIndex: zIndexDialog,
            hide: 'explode'
        };
        InitDialog('al_dialog', options);
        $('#al_dialog')
            .html(html)
            .dialog('open');

        return false;
    };
})($);<|endoftext|>


<commit_before>import React, {PropTypes, Component} from 'react'
import {connect} from 'react-redux'
import _ from 'lodash'

import * as kapacitorRuleActionCreators from 'src/kapacitor/actions/view'
import * as kapacitorQueryConfigActionCreators from 'src/kapacitor/actions/queryConfigs'

import {bindActionCreators} from 'redux'
import {getActiveKapacitor, getKapacitorConfig} from 'shared/apis/index'
import {RULE_ALERT_OPTIONS, DEFAULT_RULE_ID} from 'src/kapacitor/constants'
import KapacitorRule from 'src/kapacitor/components/KapacitorRule'

class KapacitorRulePage extends Component {
  constructor(props) {
    super(props)

    this.state = {
      enabledAlerts: [],
      kapacitor: {},
    }
  }

  async componentDidMount() {
    const {params, source, ruleActions, addFlashMessage} = this.props
    if (this.isEditing()) {
      ruleActions.fetchRule(source, params.ruleID)
    } else {
      ruleActions.loadDefaultRule()
    }

    const kapacitor = await getActiveKapacitor(this.props.source)
    if (!kapacitor) {
      return addFlashMessage({
        type: 'error',
        text: "We couldn't find a configured Kapacitor for this source", // eslint-disable-line quotes
      })
    }

    try {
      const {data: {sections}} = await getKapacitorConfig(kapacitor)
      const enabledAlerts = Object.keys(sections).filter(
        section =>
          _.get(
            sections,
            [section, 'elements', '0', 'options', 'enabled'],
            false
          ) && _.get(RULE_ALERT_OPTIONS, section, false)
      )

      this.setState({kapacitor, enabledAlerts})
    } catch (error) {
      addFlashMessage({
        type: 'error',
        text: 'There was a problem communicating with Kapacitor',
      })
      console.error(error)
      throw error
    }
  }

  render() {
    const {
      rules,
      queryConfigs,
      params,
      ruleActions,
      source,
      queryConfigActions,
      addFlashMessage,
      router,
    } = this.props
    const {enabledAlerts, kapacitor} = this.state
    const rule = this.isEditing()
      ? rules[params.ruleID]
      : rules[DEFAULT_RULE_ID]
    const query = rule && queryConfigs[rule.queryID]

    if (!query) {
      return

    }
    return (
      <KapacitorRule
        source={source}
        rule={rule}
        query={query}
        queryConfigs={queryConfigs}
        queryConfigActions={queryConfigActions}
        ruleActions={ruleActions}
        addFlashMessage={addFlashMessage}
        enabledAlerts={enabledAlerts}
        isEditing={this.isEditing()}
        router={router}
        kapacitor={kapacitor}
      />
    )
  }

  isEditing = () => {
    const {params} = this.props
    return params.ruleID && params.ruleID !== 'new'
  }
}

const {func, shape, string} = PropTypes

KapacitorRulePage.propTypes = {
  source: shape({
    links: shape({
      proxy: string.isRequired,
      self: string.isRequired,
    }),
  }),
  addFlashMessage: func,
  rules: shape({}).isRequired,
  queryConfigs: shape({}).isRequired,
  ruleActions: shape({
    loadDefaultRule: func.isRequired,
    fetchRule: func.isRequired,
    chooseTrigger: func.isRequired,
    addEvery: func.isRequired,
    removeEvery: func.isRequired,
    updateRuleValues: func.isRequired,
    updateMessage: func.isRequired,
    updateAlerts: func.isRequired,
    updateRuleName: func.isRequired,
  }).isRequired,
  queryConfigActions: shape({}).isRequired,
  params: shape({
    ruleID: string,
  }).isRequired,
  router: shape({
    push: func.isRequired,
  }).isRequired,
}

const mapStateToProps = ({rules, kapacitorQueryConfigs: queryConfigs}) => ({
  rules,
  queryConfigs,
})

const mapDispatchToProps = dispatch => ({
  ruleActions: bindActionCreators(kapacitorRuleActionCreators, dispatch),
  queryConfigActions: bindActionCreators(
    kapacitorQueryConfigActionCreators,
    dispatch
  ),
})

export default connect(mapStateToProps, mapDispatchToProps)(KapacitorRulePage)
<commit_msg>Christmas came early<commit_after>import React, {PropTypes, Component} from 'react'
import {connect} from 'react-redux'
import _ from 'lodash'

import * as kapacitorRuleActionCreators from 'src/kapacitor/actions/view'
import * as kapacitorQueryConfigActionCreators from 'src/kapacitor/actions/queryConfigs'

import {bindActionCreators} from 'redux'
import {getActiveKapacitor, getKapacitorConfig} from 'shared/apis/index'
import {RULE_ALERT_OPTIONS, DEFAULT_RULE_ID} from 'src/kapacitor/constants'
import KapacitorRule from 'src/kapacitor/components/KapacitorRule'

class KapacitorRulePage extends Component {
  constructor(props) {
    super(props)

    this.state = {
      enabledAlerts: [],
      kapacitor: {},
    }
  }

  async componentDidMount() {
    const {params, source, ruleActions, addFlashMessage} = this.props
    if (this.isEditing()) {
      ruleActions.fetchRule(source, params.ruleID)
    } else {
      ruleActions.loadDefaultRule()
    }

    const kapacitor = await getActiveKapacitor(this.props.source)
    if (!kapacitor) {
      return addFlashMessage({
        type: 'error',
        text: "We couldn't find a configured Kapacitor for this source", // eslint-disable-line quotes
      })
    }

    try {
      const {data: {sections}} = await getKapacitorConfig(kapacitor)
      const enabledAlerts = Object.keys(sections).filter(
        section =>
          _.get(
            sections,
            [section, 'elements', '0', 'options', 'enabled'],
            false
          ) && _.get(RULE_ALERT_OPTIONS, section, false)
      )

      this.setState({kapacitor, enabledAlerts})
    } catch (error) {
      addFlashMessage({
        type: 'error',
        text: 'There was a problem communicating with Kapacitor',
      })
      console.error(error)
      throw error
    }
  }

  render() {
    const {
      rules,
      queryConfigs,
      params,
      ruleActions,
      source,
      queryConfigActions,
      addFlashMessage,
      router,
    } = this.props
    const {enabledAlerts, kapacitor} = this.state
    const rule = this.isEditing()
      ? rules[params.ruleID]
      : rules[DEFAULT_RULE_ID]
    const query = rule && queryConfigs[rule.queryID]

    if (!query) {
      return

    }
    return (
      <KapacitorRule
        rule={rule}
        query={query}
        router={router}
        source={source}
        kapacitor={kapacitor}
        ruleActions={ruleActions}
        queryConfigs={queryConfigs}
        isEditing={this.isEditing()}
        enabledAlerts={enabledAlerts}
        addFlashMessage={addFlashMessage}
        queryConfigActions={queryConfigActions}
      />
    )
  }

  isEditing = () => {
    const {params} = this.props
    return params.ruleID && params.ruleID !== 'new'
  }
}

const {func, shape, string} = PropTypes

KapacitorRulePage.propTypes = {
  source: shape({
    links: shape({
      proxy: string.isRequired,
      self: string.isRequired,
    }),
  }),
  addFlashMessage: func,
  rules: shape({}).isRequired,
  queryConfigs: shape({}).isRequired,
  ruleActions: shape({
    loadDefaultRule: func.isRequired,
    fetchRule: func.isRequired,
    chooseTrigger: func.isRequired,
    addEvery: func.isRequired,
    removeEvery: func.isRequired,
    updateRuleValues: func.isRequired,
    updateMessage: func.isRequired,
    updateAlerts: func.isRequired,
    updateRuleName: func.isRequired,
  }).isRequired,
  queryConfigActions: shape({}).isRequired,
  params: shape({
    ruleID: string,
  }).isRequired,
  router: shape({
    push: func.isRequired,
  }).isRequired,
}

const mapStateToProps = ({rules, kapacitorQueryConfigs: queryConfigs}) => ({
  rules,
  queryConfigs,
})

const mapDispatchToProps = dispatch => ({
  ruleActions: bindActionCreators(kapacitorRuleActionCreators, dispatch),
  queryConfigActions: bindActionCreators(
    kapacitorQueryConfigActionCreators,
    dispatch
  ),
})

export default connect(mapStateToProps, mapDispatchToProps)(KapacitorRulePage)
<|endoftext|>


<commit_before>// Ultima Weapon Ultimate
[{
  zoneRegex: /^(The Weapon's Refrain \(Ultimate\)|Unknown Zone \(309\))$/,
  timelineFile: 'ultima_weapon_ultimate.txt',
  triggers: [
    {
      id: 'UWU Garuda Slipstream',
      regex: /14:2B53:Garuda starts using (?:Unknown_2B53|Slipstream)/,
      condition: function(data) { return data.role == 'tank'; },
      alertText: {
        en: 'Slipstream',
      },
      tts: {
        en: 'Slipstream',
      },
    },
    {
      id: 'UWU Garuda Mistral Song Marker',
      regex: / 1B:........:(\y{Name}):....:....:0010:0000:0000:0000:/,
      suppressSeconds: 5,
      alertText: {
        en: 'Mistral Song',
      },
      tts: {
        en: 'Mistral Song',
      },
    },
    {
      id: 'UWU Ifrit Fetters',
      regex: /1A:(\y{Name}) gains the effect of Infernal Fetters from/,
      condition: function(data, matches) { return data.me == matches[1]; },
      alertText: {
        en: 'Fetters on YOU',
      },
      tts: {
        en: 'Fetters',
      },
    },
    {
      id: 'UWU Searing Wind',
      regex: /1A:(\y{Name}) gains the effect of (?:Unknown_62A|Searing Wind) from/,
      condition: function(data, matches) { return data.me == matches[1]; },
      alarmText: {
        en: 'Searing Wind on YOU',
      },
      tts: {
        en: 'Searing Wind',
      },
    },
    // TODO: what's the 0075 marker
  ],
}]
<commit_msg>uwu: add spiny plume trigger<commit_after>// Ultima Weapon Ultimate
[{
  zoneRegex: /^(The Weapon's Refrain \(Ultimate\)|Unknown Zone \(309\))$/,
  timelineFile: 'ultima_weapon_ultimate.txt',
  triggers: [
    {
      id: 'UWU Garuda Slipstream',
      regex: /14:2B53:Garuda starts using (?:Unknown_2B53|Slipstream)/,
      condition: function(data) { return data.role == 'tank'; },
      alertText: {
        en: 'Slipstream',
      },
      tts: {
        en: 'Slipstream',
      },
    },
    {
      id: 'UWU Garuda Mistral Song Marker',
      regex: / 1B:........:(\y{Name}):....:....:0010:0000:0000:0000:/,
      suppressSeconds: 5,
      alertText: {
        en: 'Mistral Song',
      },
      tts: {
        en: 'Mistral Song',
      },
    },
    {
      id: 'UWU Garuda Spiny Plume',
      regex: / 03:Added new combatant Spiny Plume/,
      condition: function(data, matches) { return data.role == 'tank'; },
      infoText: {
        en: 'Spiny Plume Add',
      },
      tts: {
        en: 'Spiny Plume Add',
      },
    },
    {
      id: 'UWU Ifrit Fetters',
      regex: /1A:(\y{Name}) gains the effect of Infernal Fetters from/,
      condition: function(data, matches) { return data.me == matches[1]; },
      alertText: {
        en: 'Fetters on YOU',
      },
      tts: {
        en: 'Fetters',
      },
    },
    {
      id: 'UWU Searing Wind',
      regex: /1A:(\y{Name}) gains the effect of (?:Unknown_62A|Searing Wind) from/,
      condition: function(data, matches) { return data.me == matches[1]; },
      alarmText: {
        en: 'Searing Wind on YOU',
      },
      tts: {
        en: 'Searing Wind',
      },
    },
    // TODO: what's the 0075 marker
  ],
}]
<|endoftext|>


<commit_before>var stage = function() {
        // stage element
		this.$el = document.querySelector('#stage');

        // array of device instances
        this.devices = [];

        // currently displayed website
		this.href = null;

        // currently displayed website origin
        this.origin = null;

        // is stage stage focused (or device)
        this.isFocused = false;

	}, p = stage.prototype;

p.init = function() {
	this.events();
	return this;
}

p.events = function() {
    // get messages from subframe
    window.addEventListener("message", this.onMessage, false);

    // scale on scroll
    // document.addEventListener("scroll", this.onScroll, false);

    // mouseover stage
    document.addEventListener("mouseover", this.onFocus, false);
    document.addEventListener("focus", this.onFocus, false);
    document.addEventListener("blur", this)
}

p.onScroll = function(event) {
    // round (scrollTop / (page size / 100) / 10) / 10
    var percent = Math.round(
        (document.body.scrollTop / ((document.body.offsetHeight - window.innerHeight) / 100)) / 10
    ) / 10;

    // min 0.1
    percent = percent ? percent : 0.1;

    // update scale on mainbar
    _mainbar.$deviceScaleSelect.value = percent;

    // update devices
    _stage.updateDeviceScale(percent);
}

p.onFocus = function() {
    _stage.isFocused = true;
    console.log('stage focused');
}

// get messages from subframe
p.onMessage = function(event){
    switch (event.data.method) {
        // subframe handshake
        case 'handshake' :
            _stage.deviceHandshake(event);
            break;

        // subframe scrolls
        case 'scroll' :
            _stage.updateScroll(event.data.scrollTop, event.data.scrollLeft, event.data.idx);
            break;
    }
};

// register a subframe handshake as device
p.deviceHandshake = function(event) {
    var request = event.data;
    console.log('stage.registered handshake', request.l, request.r, this.href, this.origin);

    if(this.href == null // initial handshake
        || this.href == request.l // new frame handshake
        || this.href == request.r) // page change in subframe
        {

        for(var i = 0; i < this.devices.length; i++) {
            // sussess if device size match
            if(this.devices[i].deviceData.w == request.w && this.devices[i].deviceData.h == request.h) {
                console.log('handshake ok!', request.l);

                // send handshake back to subframe
                this.origin = event.origin;
                this.devices[i].$iframe.contentWindow.postMessage({method: 'handshake', deviceIdx : i}, event.origin);

                // update stage href if valid handshake from another location
                if(this.href != request.l) {
                    this.setHref(request.l);
                    this.updateStageHref(request.l)
                }
            }
        }
    }
}

// update current stage href
p.updateStageHref = function(href) {
    this.href = href;
    window.location.hash = href;
}

// setter for stage href
p.setHref = function(href) {
    this.href = null;

	if(this.devices.length == 0) {
		this.updateDeviceSet(_mainbar.getDeviceSet());
	}
    // update all subframes
	for(var i = 0; i < this.devices.length; i++) {
		this.devices[i].updateHref(href);
	}
    _mainbar.$navigationForm.href.value = href;
}

// update scroll for all subframes (except idx)
p.updateScroll = function(top, left, srcIdx) {
    for(var i = 0; i < this.devices.length; i++) {
        if(i != srcIdx) {
            this.devices[i].$iframe.contentWindow.postMessage({method: 'scroll',
                top : top, left: left}, this.origin);
        }
    }
}

// update device set in stage
p.updateDeviceSet = function(deviceSet) {
	var devices = deviceSet.devices,
		currentCount = this.devices.length,
		newCount = devices.length,
		iterations = newCount >= currentCount ? newCount : currentCount,
		newDevices = [];

	for(var i = 1; i <= iterations; i++) {
        // create device
		if(i <= newCount && i > currentCount) {
			var newDevice = new device().init(devices[i-1]);
			newDevices.push(newDevice);
			newDevice.updateHref(this.href);
		}
		else if(i <= currentCount && i > newCount) {
			// remove device
			this.devices[i-1].destroy();
		}
		else {
			newDevices.push(this.devices[i-1]);
			this.devices[i-1].update(devices[i-1]);
		}
	}

	this.devices = newDevices;
	this.updateDeviceScale(_mainbar.getDeviceScale());
}

p.updateDeviceScale = function(scale) {
	for(var i = 0; i < this.devices.length; i++) {
		this.devices[i].updateScale(scale);
	}
}

p.focusDevice = function($iframe) {
	this.unfocusAllDevices();
	for(var i = 0; i < this.devices.length; i++) {
		console.log(['focusDevice Loop', $iframe, this.devices[i].$iframe]);
		if(this.devices[i].$iframe == $iframe) {
			this.devices[i].$el.classList.add('focus');
		}
	}
}

p.unfocusAllDevices = function() {
	for(var i = 0; i < this.devices.length; i++) {
		this.devices[i].$el.classList.remove('focus');
	}
}<commit_msg>removed unused focus handler<commit_after>var stage = function() {
        // stage element
		this.$el = document.querySelector('#stage');

        // array of device instances
        this.devices = [];

        // currently displayed website
		this.href = null;

        // currently displayed website origin
        this.origin = null;

        // is stage stage focused (or device)
        this.isFocused = false;

	}, p = stage.prototype;

p.init = function() {
	this.events();
	return this;
}

p.events = function() {
    // get messages from subframe
    window.addEventListener("message", this.onMessage, false);

    // scale on scroll
    // document.addEventListener("scroll", this.onScroll, false);

    // mouseover stage
    //document.addEventListener("mouseover", this.onFocus, false);
    //document.addEventListener("focus", this.onFocus, false);
    //document.addEventListener("blur", this)
}

p.onScroll = function(event) {
    // round (scrollTop / (page size / 100) / 10) / 10
    var percent = Math.round(
        (document.body.scrollTop / ((document.body.offsetHeight - window.innerHeight) / 100)) / 10
    ) / 10;

    // min 0.1
    percent = percent ? percent : 0.1;

    // update scale on mainbar
    _mainbar.$deviceScaleSelect.value = percent;

    // update devices
    _stage.updateDeviceScale(percent);
}

p.onFocus = function() {
    _stage.isFocused = true;
    console.log('stage focused');
}

// get messages from subframe
p.onMessage = function(event){
    switch (event.data.method) {
        // subframe handshake
        case 'handshake' :
            _stage.deviceHandshake(event);
            break;

        // subframe scrolls
        case 'scroll' :
            _stage.updateScroll(event.data.scrollTop, event.data.scrollLeft, event.data.idx);
            break;
    }
};

// register a subframe handshake as device
p.deviceHandshake = function(event) {
    var request = event.data;
    console.log('stage.registered handshake', request.l, request.r, this.href, this.origin);

    if(this.href == null // initial handshake
        || this.href == request.l // new frame handshake
        || this.href == request.r) // page change in subframe
        {

        for(var i = 0; i < this.devices.length; i++) {
            // sussess if device size match
            if(this.devices[i].deviceData.w == request.w && this.devices[i].deviceData.h == request.h) {
                console.log('handshake ok!', request.l);

                // send handshake back to subframe
                this.origin = event.origin;
                this.devices[i].$iframe.contentWindow.postMessage({method: 'handshake', deviceIdx : i}, event.origin);

                // update stage href if valid handshake from another location
                if(this.href != request.l) {
                    this.setHref(request.l);
                    this.updateStageHref(request.l)
                }
            }
        }
    }
}

// update current stage href
p.updateStageHref = function(href) {
    this.href = href;
    window.location.hash = href;
}

// setter for stage href
p.setHref = function(href) {
    this.href = null;

	if(this.devices.length == 0) {
		this.updateDeviceSet(_mainbar.getDeviceSet());
	}
    // update all subframes
	for(var i = 0; i < this.devices.length; i++) {
		this.devices[i].updateHref(href);
	}
    _mainbar.$navigationForm.href.value = href;
}

// update scroll for all subframes (except idx)
p.updateScroll = function(top, left, srcIdx) {
    for(var i = 0; i < this.devices.length; i++) {
        if(i != srcIdx) {
            this.devices[i].$iframe.contentWindow.postMessage({method: 'scroll',
                top : top, left: left}, this.origin);
        }
    }
}

// update device set in stage
p.updateDeviceSet = function(deviceSet) {
	var devices = deviceSet.devices,
		currentCount = this.devices.length,
		newCount = devices.length,
		iterations = newCount >= currentCount ? newCount : currentCount,
		newDevices = [];

	for(var i = 1; i <= iterations; i++) {
        // create device
		if(i <= newCount && i > currentCount) {
			var newDevice = new device().init(devices[i-1]);
			newDevices.push(newDevice);
			newDevice.updateHref(this.href);
		}
		else if(i <= currentCount && i > newCount) {
			// remove device
			this.devices[i-1].destroy();
		}
		else {
			newDevices.push(this.devices[i-1]);
			this.devices[i-1].update(devices[i-1]);
		}
	}

	this.devices = newDevices;
	this.updateDeviceScale(_mainbar.getDeviceScale());
}

p.updateDeviceScale = function(scale) {
	for(var i = 0; i < this.devices.length; i++) {
		this.devices[i].updateScale(scale);
	}
}

p.focusDevice = function($iframe) {
	this.unfocusAllDevices();
	for(var i = 0; i < this.devices.length; i++) {
		console.log(['focusDevice Loop', $iframe, this.devices[i].$iframe]);
		if(this.devices[i].$iframe == $iframe) {
			this.devices[i].$el.classList.add('focus');
		}
	}
}

p.unfocusAllDevices = function() {
	for(var i = 0; i < this.devices.length; i++) {
		this.devices[i].$el.classList.remove('focus');
	}
}<|endoftext|>


<commit_before>import { translate } from '../../../common/i18n';

const steps = [
    {
        title: translate('Take a quick tour'),
        text : `

            ${translate('Ready to learn how to use Binary Bot?')}

              <input type="checkbox" id="do-not-ask-me-again"></input>
              ${translate('Do not ask me again.')}

                ${translate('No Thanks')}

                ${translate('Yes')}

          `,
        selector: '#tour',
        position: 'top',
        style   : {
            button: {
                display: 'none',
            },
            close: {
                display: 'none',
            },
        },
    },
    {
        title: translate('Workspace'),
        text : `

      ${translate('Drag and drop block files.')}

        ${translate('Download sample strategies')}

      ${translate('or')}

          ${translate('Make your own strategies')}

`,
        selector: '#center',
        position: 'bottom',
    },
    {
        title: translate('Blocks toolbox'),
        text : `

      ${translate('Add more blocks from here to your bot.')}

`,
        selector: '.blocklyToolboxDiv',
        position: 'right',
    },
    {
        title: translate('Accounts'),
        text : `

      ${translate('Login before starting your bot. Always test your strategies with the virtual account.')}

`,
        selector: '.right-header',
        position: 'left',
    },
    {
        title: translate('Bot controls'),
        text : `

      ${translate('Control your blocks. Hold the cursor on each button for more info.')}

`,
        selector: '#toolbox',
        position: 'left',
    },
    {
        title: translate('Enjoy!'),
        text : `

      ${translate('Want to report an issue or ask for help?')}

        ${translate('Click here')}

`,
        selector: '#center',
        position: 'bottom',
    },
];

export default steps;
<commit_msg>Fix tour css checkbox<commit_after>import { translate } from '../../../common/i18n';

const steps = [
    {
        title: translate('Take a quick tour'),
        text : `

            ${translate('Ready to learn how to use Binary Bot?')}
            <input type="checkbox" id="do-not-ask-me-again"></input>

              ${translate('Do not ask me again.')}

                ${translate('No Thanks')}

                ${translate('Yes')}

          `,
        selector: '#tour',
        position: 'top',
        style   : {
            button: {
                display: 'none',
            },
            close: {
                display: 'none',
            },
        },
    },
    {
        title: translate('Workspace'),
        text : `

      ${translate('Drag and drop block files.')}

        ${translate('Download sample strategies')}

      ${translate('or')}

          ${translate('Make your own strategies')}

`,
        selector: '#center',
        position: 'bottom',
    },
    {
        title: translate('Blocks toolbox'),
        text : `

      ${translate('Add more blocks from here to your bot.')}

`,
        selector: '.blocklyToolboxDiv',
        position: 'right',
    },
    {
        title: translate('Accounts'),
        text : `

      ${translate('Login before starting your bot. Always test your strategies with the virtual account.')}

`,
        selector: '.right-header',
        position: 'left',
    },
    {
        title: translate('Bot controls'),
        text : `

      ${translate('Control your blocks. Hold the cursor on each button for more info.')}

`,
        selector: '#toolbox',
        position: 'left',
    },
    {
        title: translate('Enjoy!'),
        text : `

      ${translate('Want to report an issue or ask for help?')}

        ${translate('Click here')}

`,
        selector: '#center',
        position: 'bottom',
    },
];

export default steps;
<|endoftext|>