<commit_before>Ext.namespace('Vps.Menu');

Vps.Menu.Index = Ext.extend(Ext.Toolbar,
{
    controllerUrl: '/vps/user/menu',
    changeUserTpl: ['<tpl for=".">',
                        '<div class="x-combo-list-item changeuser-list-item<tpl if="locked != 0"> changeuser-locked</tpl>">',
                            '
{lastname} {firstname}
',
                            '{email} ({role})',
                        '
',
                      '</tpl>'],
    tplDataControllerUrl: '/vps/user/changeUser/json-data',

    initComponent : function()
    {
        this.addEvents(
            'menuevent'
        );
        Vps.Menu.Index.superclass.initComponent.call(this);

    },
    afterRender: function() {
        Vps.Menu.Index.superclass.afterRender.call(this);
        this.reload();
    },
    reload: function()
    {
        Ext.Ajax.request({
            url: this.controllerUrl+'/json-data',
            params: this.params,
            success: this.loadMenu,
            scope: this
        });
    },
    _processMenus: function(menus)
    {
        var menuItems = [];
        for (var i=0; i<menus.length; i++) {
            var m = menus[i];
            var subMenu = m.menuConfig;
            if (m.type == 'dropdown') {
                var childMenuItems = this._processMenus(m.children);
                var menu = new Ext.menu.Menu({
                    items: childMenuItems
                });
                subMenu.menu = menu;
            } else if (m.type == 'url') {
                subMenu.href = m.url;
                subMenu.handler = function(o, e) {
                    e.stopEvent();
                    var cb = function() {
                        if (top != window) {
                            top.location.href = o.href;
                        } else {
                            location.href = o.href;
                        }
                    };
                    if (!Vps.currentViewport || !Vps.currentViewport.mabySubmit) {
                        cb();
                    } else {
                        if (Vps.currentViewport.mabySubmit({
                            callback: cb,
                            scope: this
                        })) {
                            cb();
                        }
                    }
                };
                subMenu.scope = this;
            } else if (m.type == 'event') {
                subMenu.handler = function(o) {
                    if(o.eventConfig && !o.eventConfig.title) o.eventConfig.title = o.text;
                    this.fireEvent('menuevent', o.eventConfig);
                };
                subMenu.scope = this;
                subMenu.eventConfig = m.eventConfig;
            } else if (m.type == 'commandDialog') {
                subMenu.handler = function(o) {
                    var c = eval(o.commandClass);
                    var dlg = new c(o.commandConfig);
                    dlg.show();
                };
                subMenu.scope = this;
                subMenu.commandClass = m.commandClass;
                subMenu.commandConfig = m.commandConfig;
                if (m.command != undefined) {
                    eval(m.command + '();');
                }
            } else if (m.type == 'command') {
                subMenu.handler = function(o) {
                    Vps.currentViewport.remove(Vps.currentViewport.items.item('mainPanel'));
                    var c = eval(o.commandClass);
                    var panel = new c(o.commandConfig);
                    panel.region = 'center';
                    panel.id = 'mainPanel';
                    Vps.currentViewport.add(panel);
                    Vps.currentViewport.layout.rendered = false;
                    Vps.currentViewport.doLayout();
                };
                subMenu.scope = this;
                subMenu.commandClass = m.commandClass;
                subMenu.commandConfig = m.commandConfig;
            } else if (m.type == 'separator') {
                subMenu = '-';
            } else {
                throw "unknown menu-type: "+m.type;
            }

            menuItems.push(subMenu);
        }
        return menuItems;
    },
    loadMenu: function(response, options, result)
    {
        this.items.each(function(i) {
            i.destroy();
        });
        var menuItems = this._processMenus(result.menus);
        menuItems.each(function(menuItem) {
            if (menuItem.icon && menuItem.text) {
                menuItem.cls = 'x-btn-text-icon';
            } else if (menuItem.icon) {
                menuItem.cls = 'x-btn-icon';
            }
            this.add(menuItem);
        }, this);

        this.add(new Ext.Toolbar.Fill());

        if (result.changeUser) {
            var changeUser = new Vps.Form.ComboBox({
                store: {
                    url: this.tplDataControllerUrl
                },
                mode: 'remote',
                editable: true,
                forceSelection: true,
                pageSize: 10,
                triggerAction: 'all',
                width: 120,
                maxHeight: 350,
                listWidth: 280,
                tpl: new Ext.XTemplate(
                        this.changeUserTpl
                      )
            });
            changeUser.on('render', function(combo) {
                combo.setRawValue(result.fullname);
            }, this, {delay: 10});
            changeUser.on('select', function(combo, record, index) {
                Ext.Ajax.request({
                    url: '/vps/user/changeUser/json-change-user',
                    params: { userId: record.id },
                    success: function() {
                        location.href = '/vps/welcome';
                    },
                    scope: this
                });
            }, this);
            this.add(changeUser);
        }

        if (result.fullname && result.userSelfControllerUrl) {
            this.add({
                id: 'currentUser',
                text: result.fullname,
                cls: 'x-btn-text-icon',
                icon: '/assets/silkicons/user.png',
                handler: function() {
                    var dlg = new Vps.Auto.Form.Window({
                        width: 450,
                        height: 370,
                        formConfig: {
                            controllerUrl: result.userSelfControllerUrl
                        }
                    });
                    dlg.on('datachange', function() {
                        this.reload();
                    }, this);
                    dlg.showEdit(result.userId);
                },
                scope: this
            });
        }
        if (result.showLogout) {
            this.add({
                cls: 'x-btn-icon',
                tooltip: trlVps('Logout'),
                icon: '/assets/silkicons/door_out.png',
                handler: function() {
                    Ext.Ajax.request({
                        url : '/vps/user/login/json-logout-user',
                        success : function(form, action) {
                            //nicht reload, weil user nach erneutem login vielleicht
                            //die aktuelle seite gar nicht mehr sehen darf
                            location.href = '/vps/welcome';
                        },
                        scope: this
                    });
                },
                scope: this
            });
        }
        this.add({
            cls: 'x-btn-icon',
            icon: '/assets/vps/images/information.png',
            tooltip: trlVps('Information'),
            handler: function() {
                var about = new Vps.About();
                about.show();
            },
            scope: this
        });
        if (result.hasFrontend) {
            this.add({
                tooltip: trlVps('Open frontend in a new window'),
                cls: 'x-btn-icon',
                icon: '/assets/silkicons/world.png',
                handler: function() {
                    window.open('/');
                },
                scope: this
            });
        }

        if (Vps.Debug.showMenu) {
            this.add('-');
            this.add({
                cls: 'x-btn-icon',
                icon: '/assets/silkicons/bug.png',
                menu: new Vps.Debug.Menu()
            });
        } else if (Vps.Debug.showActivator) {
            this.add('-');
            this.add({
                tooltip: 'Activate Debugging',
                cls: 'x-btn-icon',
                icon: '/assets/silkicons/bug.png',
                handler: function() {
                    location.href = '/vps/debug/activate?url=' + location.href;
                }
            });
        }
    }
});
Ext.reg('vps.menu', Vps.Menu.Index);
<commit_msg>sehr komischen variablennamen entfernt, das muss ja gar keine var sein<commit_after>Ext.namespace('Vps.Menu');

Vps.Menu.Index = Ext.extend(Ext.Toolbar,
{
    controllerUrl: '/vps/user/menu',
    changeUserTpl: ['<tpl for=".">',
                        '<div class="x-combo-list-item changeuser-list-item<tpl if="locked != 0"> changeuser-locked</tpl>">',
                            '
{lastname} {firstname}
',
                            '{email} ({role})',
                        '
',
                      '</tpl>'],

    initComponent : function()
    {
        this.addEvents(
            'menuevent'
        );
        Vps.Menu.Index.superclass.initComponent.call(this);

    },
    afterRender: function() {
        Vps.Menu.Index.superclass.afterRender.call(this);
        this.reload();
    },
    reload: function()
    {
        Ext.Ajax.request({
            url: this.controllerUrl+'/json-data',
            params: this.params,
            success: this.loadMenu,
            scope: this
        });
    },
    _processMenus: function(menus)
    {
        var menuItems = [];
        for (var i=0; i<menus.length; i++) {
            var m = menus[i];
            var subMenu = m.menuConfig;
            if (m.type == 'dropdown') {
                var childMenuItems = this._processMenus(m.children);
                var menu = new Ext.menu.Menu({
                    items: childMenuItems
                });
                subMenu.menu = menu;
            } else if (m.type == 'url') {
                subMenu.href = m.url;
                subMenu.handler = function(o, e) {
                    e.stopEvent();
                    var cb = function() {
                        if (top != window) {
                            top.location.href = o.href;
                        } else {
                            location.href = o.href;
                        }
                    };
                    if (!Vps.currentViewport || !Vps.currentViewport.mabySubmit) {
                        cb();
                    } else {
                        if (Vps.currentViewport.mabySubmit({
                            callback: cb,
                            scope: this
                        })) {
                            cb();
                        }
                    }
                };
                subMenu.scope = this;
            } else if (m.type == 'event') {
                subMenu.handler = function(o) {
                    if(o.eventConfig && !o.eventConfig.title) o.eventConfig.title = o.text;
                    this.fireEvent('menuevent', o.eventConfig);
                };
                subMenu.scope = this;
                subMenu.eventConfig = m.eventConfig;
            } else if (m.type == 'commandDialog') {
                subMenu.handler = function(o) {
                    var c = eval(o.commandClass);
                    var dlg = new c(o.commandConfig);
                    dlg.show();
                };
                subMenu.scope = this;
                subMenu.commandClass = m.commandClass;
                subMenu.commandConfig = m.commandConfig;
                if (m.command != undefined) {
                    eval(m.command + '();');
                }
            } else if (m.type == 'command') {
                subMenu.handler = function(o) {
                    Vps.currentViewport.remove(Vps.currentViewport.items.item('mainPanel'));
                    var c = eval(o.commandClass);
                    var panel = new c(o.commandConfig);
                    panel.region = 'center';
                    panel.id = 'mainPanel';
                    Vps.currentViewport.add(panel);
                    Vps.currentViewport.layout.rendered = false;
                    Vps.currentViewport.doLayout();
                };
                subMenu.scope = this;
                subMenu.commandClass = m.commandClass;
                subMenu.commandConfig = m.commandConfig;
            } else if (m.type == 'separator') {
                subMenu = '-';
            } else {
                throw "unknown menu-type: "+m.type;
            }

            menuItems.push(subMenu);
        }
        return menuItems;
    },
    loadMenu: function(response, options, result)
    {
        this.items.each(function(i) {
            i.destroy();
        });
        var menuItems = this._processMenus(result.menus);
        menuItems.each(function(menuItem) {
            if (menuItem.icon && menuItem.text) {
                menuItem.cls = 'x-btn-text-icon';
            } else if (menuItem.icon) {
                menuItem.cls = 'x-btn-icon';
            }
            this.add(menuItem);
        }, this);

        this.add(new Ext.Toolbar.Fill());

        if (result.changeUser) {
            var changeUser = new Vps.Form.ComboBox({
                store: {
                    url: '/vps/user/changeUser/json-data'
                },
                mode: 'remote',
                editable: true,
                forceSelection: true,
                pageSize: 10,
                triggerAction: 'all',
                width: 120,
                maxHeight: 350,
                listWidth: 280,
                tpl: new Ext.XTemplate(
                        this.changeUserTpl
                      )
            });
            changeUser.on('render', function(combo) {
                combo.setRawValue(result.fullname);
            }, this, {delay: 10});
            changeUser.on('select', function(combo, record, index) {
                Ext.Ajax.request({
                    url: '/vps/user/changeUser/json-change-user',
                    params: { userId: record.id },
                    success: function() {
                        location.href = '/vps/welcome';
                    },
                    scope: this
                });
            }, this);
            this.add(changeUser);
        }

        if (result.fullname && result.userSelfControllerUrl) {
            this.add({
                id: 'currentUser',
                text: result.fullname,
                cls: 'x-btn-text-icon',
                icon: '/assets/silkicons/user.png',
                handler: function() {
                    var dlg = new Vps.Auto.Form.Window({
                        width: 450,
                        height: 370,
                        formConfig: {
                            controllerUrl: result.userSelfControllerUrl
                        }
                    });
                    dlg.on('datachange', function() {
                        this.reload();
                    }, this);
                    dlg.showEdit(result.userId);
                },
                scope: this
            });
        }
        if (result.showLogout) {
            this.add({
                cls: 'x-btn-icon',
                tooltip: trlVps('Logout'),
                icon: '/assets/silkicons/door_out.png',
                handler: function() {
                    Ext.Ajax.request({
                        url : '/vps/user/login/json-logout-user',
                        success : function(form, action) {
                            //nicht reload, weil user nach erneutem login vielleicht
                            //die aktuelle seite gar nicht mehr sehen darf
                            location.href = '/vps/welcome';
                        },
                        scope: this
                    });
                },
                scope: this
            });
        }
        this.add({
            cls: 'x-btn-icon',
            icon: '/assets/vps/images/information.png',
            tooltip: trlVps('Information'),
            handler: function() {
                var about = new Vps.About();
                about.show();
            },
            scope: this
        });
        if (result.hasFrontend) {
            this.add({
                tooltip: trlVps('Open frontend in a new window'),
                cls: 'x-btn-icon',
                icon: '/assets/silkicons/world.png',
                handler: function() {
                    window.open('/');
                },
                scope: this
            });
        }

        if (Vps.Debug.showMenu) {
            this.add('-');
            this.add({
                cls: 'x-btn-icon',
                icon: '/assets/silkicons/bug.png',
                menu: new Vps.Debug.Menu()
            });
        } else if (Vps.Debug.showActivator) {
            this.add('-');
            this.add({
                tooltip: 'Activate Debugging',
                cls: 'x-btn-icon',
                icon: '/assets/silkicons/bug.png',
                handler: function() {
                    location.href = '/vps/debug/activate?url=' + location.href;
                }
            });
        }
    }
});
Ext.reg('vps.menu', Vps.Menu.Index);
<|endoftext|>


<commit_before>'use strict';

var volumeChangeCallback = '';

module.exports = {
	setMute: function (success, fail, args) {
		try {
			var result = webapis.audiocontrol.setMute(args[0]);

			if (result) {
				setTimeout(function () {
					success();
				}, 0);
			}
		}
		catch (e) {
			fail(e);
		}
	},
	isMute: function (success, fail, args) {
		try {
			var result = webapis.audiocontrol.getMute();

			if (typeof result == 'boolean') {
				setTimeout(function () {
					success(result);
				}, 0);
			}
		}
		catch (e) {
			fail(e);
		}
	},
	setVolume: function (success, fail, args) {
		try {
			var isMute = webapis.audiocontrol.getMute();
			if(isMute){
				webapis.audiocontrol.setMute(false);
			}

			webapis.audiocontrol.setVolume(args[0]);

			if((volumeChangeCallback) && (typeof args[0] == 'number')){
				volumeChangeCallback(args[0]);
			}
			success();
		}
		catch (e) {
			fail(e);
		}
	},
	setVolumeUp: function (success, fail, args) {
		try {
			var isMute = webapis.audiocontrol.getMute();
			if(isMute){
				webapis.audiocontrol.setMute(false);
			}

			webapis.audiocontrol.setVolumeUp();

			if(volumeChangeCallback){
				var volume = webapis.audiocontrol.getVolume();
				if((typeof volume == 'number') && (volume != -1)){
					volumeChangeCallback(volume);
				}
			}
			success();
		}
		catch (e) {
			fail(e);
		}
	},
	setVolumeDown: function (success, fail, args) {
		try {
			var isMute = webapis.audiocontrol.getMute();
			if(isMute){
				webapis.audiocontrol.setMute(false);
			}

			webapis.audiocontrol.setVolumeDown();

			if(volumeChangeCallback){
				var volume = webapis.audiocontrol.getVolume();
				if((typeof volume == 'number') && (volume != -1)){
					volumeChangeCallback(volume);
				}
			}
			success();
		}
		catch (e) {
			fail(e);
		}
	},
	getVolume: function (success, fail, args) {
		var result = webapis.audiocontrol.getVolume();

		if (result != -1) {
			setTimeout(function () {
				success(result);
			}, 0);
		}
		else {
			setTimeout(function () {
				var e = new Error('failed to getVolume');
				fail(e);
			}, 0);
		}
	},
	setVolumeChangeListener: function (success, fail, args) {
		volumeChangeCallback = args[0];
		if(volumeChangeCallback){
			success();
		}
		else{
			var e = new Error('failed to setVolumeChangeListener');
			fail(e);
		}
	},
	unsetVolumeChangeListener: function (success, fail, args) {
		volumeChangeCallback = '';

		if(!volumeChangeCallback){
			success();
		}
		else{
			var e = new Error('failed to unsetVolumeChangeListener');
			fail(e);
		}
	}
};

require('cordova/exec/proxy').add('toast.tvaudiocontrol', module.exports);
<commit_msg>bug fix jscs<commit_after>'use strict';

var volumeChangeCallback = '';

module.exports = {
	setMute: function (success, fail, args) {
		try {
			var result = webapis.audiocontrol.setMute(args[0]);

			if (result) {
				setTimeout(function () {
					success();
				}, 0);
			}
		}
		catch (e) {
			fail(e);
		}
	},
	isMute: function (success, fail, args) {
		try {
			var result = webapis.audiocontrol.getMute();

			if (typeof result == 'boolean') {
				setTimeout(function () {
					success(result);
				}, 0);
			}
		}
		catch (e) {
			fail(e);
		}
	},
	setVolume: function (success, fail, args) {
		try {
			var isMute = webapis.audiocontrol.getMute();
			if(isMute){
				webapis.audiocontrol.setMute(false);
			}

			webapis.audiocontrol.setVolume(args[0]);

			if((volumeChangeCallback) && (typeof args[0] == 'number')){
				volumeChangeCallback(args[0]);
			}
			success();
		}
		catch (e) {
			fail(e);
		}
	},
	setVolumeUp: function (success, fail, args) {
		try {
			var isMute = webapis.audiocontrol.getMute();
			if(isMute){
				webapis.audiocontrol.setMute(false);
			}

			webapis.audiocontrol.setVolumeUp();

			if(volumeChangeCallback){
				var volume = webapis.audiocontrol.getVolume();
				if((typeof volume == 'number') && (volume != -1)){
					volumeChangeCallback(volume);
				}
			}
			success();
		}
		catch (e) {
			fail(e);
		}
	},
	setVolumeDown: function (success, fail, args) {
		try {
			var isMute = webapis.audiocontrol.getMute();
			if(isMute){
				webapis.audiocontrol.setMute(false);
			}

			webapis.audiocontrol.setVolumeDown();

			if(volumeChangeCallback){
				var volume = webapis.audiocontrol.getVolume();
				if((typeof volume == 'number') && (volume != -1)){
					volumeChangeCallback(volume);
				}
			}
			success();
		}
		catch (e) {
			fail(e);
		}
	},
	getVolume: function (success, fail, args) {
		var result = webapis.audiocontrol.getVolume();

		if (result != -1) {
			setTimeout(function () {
				success(result);
			}, 0);
		}
		else {
			setTimeout(function () {
				var e = new Error('failed to getVolume');
				fail(e);
			}, 0);
		}
	},
	setVolumeChangeListener: function (success, fail, args) {
		volumeChangeCallback = args[0];
		if(volumeChangeCallback){
			success();
		}
		else{
			var e = new Error('failed to setVolumeChangeListener');
			fail(e);
		}
	},
	unsetVolumeChangeListener: function (success, fail, args) {
		volumeChangeCallback = '';

		if(!volumeChangeCallback){
			success();
		}
		else{
			var e = new Error('failed to unsetVolumeChangeListener');
			fail(e);
		}
	}
};

require('cordova/exec/proxy').add('toast.tvaudiocontrol', module.exports);
<|endoftext|>


<commit_before>import { Component, createElement } from "react";
import PropTypes from "prop-types";

let SCRIPT_MAP = {};

// A counter used to generate a unique id for each component that uses the function
let idCount = 0;

export default function makeAsyncScript(getScriptURL, options) {
  options = options || {};
  return function wrapWithAsyncScript(WrappedComponent) {
    const wrappedComponentName =
    WrappedComponent.displayName || WrappedComponent.name || "Component";

    class AsyncScriptLoader extends Component {
      constructor(props, context) {
        super(props, context)
        this.state = {};
        this.__scriptURL = "";
        this.assignChildComponent = this.assignChildComponent.bind(this);
      }

      asyncScriptLoaderGetScriptLoaderID() {
        if (!this.__scriptLoaderID) {
          this.__scriptLoaderID = "async-script-loader-" + idCount++;
        }
        return this.__scriptLoaderID;
      }

      setupScriptURL() {
        this.__scriptURL =
          typeof getScriptURL === "function" ? getScriptURL() : getScriptURL;
        return this.__scriptURL;
      }

      assignChildComponent(ref) {
        this.__childComponent = ref;
      }

      getComponent() {
        return this.__childComponent;
      }

      asyncScriptLoaderHandleLoad(state) {
        // use reacts setState callback to fire props.asyncScriptOnLoad with new state/entry
        this.setState(state,
          () => this.props.asyncScriptOnLoad && this.props.asyncScriptOnLoad(this.state)
        );
      }

      asyncScriptLoaderTriggerOnScriptLoaded() {
        let mapEntry = SCRIPT_MAP[this.__scriptURL];
        if (!mapEntry || !mapEntry.loaded) {
          throw new Error("Script is not loaded.");
        }
        for (let obsKey in mapEntry.observers) {
          mapEntry.observers[obsKey](mapEntry);
        }
        delete window[options.callbackName];
      }

      componentDidMount() {
        const scriptURL = this.setupScriptURL();
        const key = this.asyncScriptLoaderGetScriptLoaderID();
        const { globalName, callbackName } = options;

        // check if global object already attached to window
        if (globalName && typeof window[globalName] !== "undefined") {
          SCRIPT_MAP[scriptURL] = { loaded: true, observers: {} };
        }

        // check if script loading already
        if (SCRIPT_MAP[scriptURL]) {
          let entry = SCRIPT_MAP[scriptURL];
          // if loaded or errored then "finish"
          if (entry && (entry.loaded || entry.errored)) {
            this.asyncScriptLoaderHandleLoad(entry);
            return;
          }
          // if still loading then callback to observer queue
          entry.observers[key] = entry => this.asyncScriptLoaderHandleLoad(entry);
          return;
        }

        /*
         * hasn't started loading
         * start the "magic"
         * setup script to load and observers
         */
        let observers = {};
        observers[key] = entry => this.asyncScriptLoaderHandleLoad(entry);
        SCRIPT_MAP[scriptURL] = {
          loaded: false,
          observers,
        };

        let script = document.createElement("script");

        script.src = scriptURL;
        script.async = true;

        let callObserverFuncAndRemoveObserver = func => {
          if (SCRIPT_MAP[scriptURL]) {
            let mapEntry = SCRIPT_MAP[scriptURL];
            let observersMap = mapEntry.observers;

            for (let obsKey in observersMap) {
              if (func(observersMap[obsKey])) {
                delete observersMap[obsKey];
              }
            }
          }
        };

        if (callbackName && typeof window !== "undefined") {
          window[callbackName] = () =>
            this.asyncScriptLoaderTriggerOnScriptLoaded();
        }

        script.onload = () => {
          let mapEntry = SCRIPT_MAP[scriptURL];
          if (mapEntry) {
            mapEntry.loaded = true;
            callObserverFuncAndRemoveObserver(observer => {
              if (callbackName) {
                return false;
              }
              observer(mapEntry);
              return true;
            });
          }
        };
        script.onerror = event => {
          let mapEntry = SCRIPT_MAP[scriptURL];
          if (mapEntry) {
            mapEntry.errored = true;
            callObserverFuncAndRemoveObserver(observer => {
              observer(mapEntry);
              return true;
            });
          }
        };

        // (old) MSIE browsers may call "onreadystatechange" instead of "onload"
        script.onreadystatechange = () => {
          if (this.readyState === "loaded") {
            // wait for other events, then call onload if default onload hadn't been called
            window.setTimeout(() => {
              const mapEntry = SCRIPT_MAP[scriptURL];
              if (mapEntry && mapEntry.loaded !== true) {
                script.onload();
              }
            }, 0);
          }
        };

        document.body.appendChild(script);
      }

      componentWillUnmount() {
        // Remove tag script
        const scriptURL = this.__scriptURL;
        if (options.removeOnUnmount === true) {
          const allScripts = document.getElementsByTagName("script");
          for (let i = 0; i < allScripts.length; i += 1) {
            if (allScripts[i].src.indexOf(scriptURL) > -1) {
              if (allScripts[i].parentNode) {
                allScripts[i].parentNode.removeChild(allScripts[i]);
              }
            }
          }
        }
        // Clean the observer entry
        let mapEntry = SCRIPT_MAP[scriptURL];
        if (mapEntry) {
          delete mapEntry.observers[this.asyncScriptLoaderGetScriptLoaderID()];
          if (options.removeOnUnmount === true) {
            delete SCRIPT_MAP[scriptURL];
          }
        }
      }

      render() {
        const globalName = options.globalName;
        // remove asyncScriptOnLoad from childProps
        let { asyncScriptOnLoad, ...childProps } = this.props; // eslint-disable-line no-unused-vars
        if (globalName && typeof window !== "undefined") {
          childProps[globalName] =
            typeof window[globalName] !== "undefined"
              ? window[globalName]
              : undefined;
        }
        childProps.ref = this.assignChildComponent;
        return createElement(WrappedComponent, childProps);
      }
    }
    AsyncScriptLoader.displayName = `AsyncScriptLoader(${wrappedComponentName})`;
    AsyncScriptLoader.propTypes = {
      asyncScriptOnLoad: PropTypes.func,
    };

    if (options.exposeFuncs) {
      options.exposeFuncs.forEach(funcToExpose => {
        AsyncScriptLoader.prototype[funcToExpose] = function() {
          return this.getComponent()[funcToExpose](...arguments);
        };
      });
    }
    return AsyncScriptLoader;
  }
}
<commit_msg>remove old ie support<commit_after>import { Component, createElement } from "react";
import PropTypes from "prop-types";

let SCRIPT_MAP = {};

// A counter used to generate a unique id for each component that uses the function
let idCount = 0;

export default function makeAsyncScript(getScriptURL, options) {
  options = options || {};
  return function wrapWithAsyncScript(WrappedComponent) {
    const wrappedComponentName =
    WrappedComponent.displayName || WrappedComponent.name || "Component";

    class AsyncScriptLoader extends Component {
      constructor(props, context) {
        super(props, context)
        this.state = {};
        this.__scriptURL = "";
        this.assignChildComponent = this.assignChildComponent.bind(this);
      }

      asyncScriptLoaderGetScriptLoaderID() {
        if (!this.__scriptLoaderID) {
          this.__scriptLoaderID = "async-script-loader-" + idCount++;
        }
        return this.__scriptLoaderID;
      }

      setupScriptURL() {
        this.__scriptURL =
          typeof getScriptURL === "function" ? getScriptURL() : getScriptURL;
        return this.__scriptURL;
      }

      assignChildComponent(ref) {
        this.__childComponent = ref;
      }

      getComponent() {
        return this.__childComponent;
      }

      asyncScriptLoaderHandleLoad(state) {
        // use reacts setState callback to fire props.asyncScriptOnLoad with new state/entry
        this.setState(state,
          () => this.props.asyncScriptOnLoad && this.props.asyncScriptOnLoad(this.state)
        );
      }

      asyncScriptLoaderTriggerOnScriptLoaded() {
        let mapEntry = SCRIPT_MAP[this.__scriptURL];
        if (!mapEntry || !mapEntry.loaded) {
          throw new Error("Script is not loaded.");
        }
        for (let obsKey in mapEntry.observers) {
          mapEntry.observers[obsKey](mapEntry);
        }
        delete window[options.callbackName];
      }

      componentDidMount() {
        const scriptURL = this.setupScriptURL();
        const key = this.asyncScriptLoaderGetScriptLoaderID();
        const { globalName, callbackName } = options;

        // check if global object already attached to window
        if (globalName && typeof window[globalName] !== "undefined") {
          SCRIPT_MAP[scriptURL] = { loaded: true, observers: {} };
        }

        // check if script loading already
        if (SCRIPT_MAP[scriptURL]) {
          let entry = SCRIPT_MAP[scriptURL];
          // if loaded or errored then "finish"
          if (entry && (entry.loaded || entry.errored)) {
            this.asyncScriptLoaderHandleLoad(entry);
            return;
          }
          // if still loading then callback to observer queue
          entry.observers[key] = entry => this.asyncScriptLoaderHandleLoad(entry);
          return;
        }

        /*
         * hasn't started loading
         * start the "magic"
         * setup script to load and observers
         */
        let observers = {};
        observers[key] = entry => this.asyncScriptLoaderHandleLoad(entry);
        SCRIPT_MAP[scriptURL] = {
          loaded: false,
          observers,
        };

        let script = document.createElement("script");

        script.src = scriptURL;
        script.async = true;

        let callObserverFuncAndRemoveObserver = func => {
          if (SCRIPT_MAP[scriptURL]) {
            let mapEntry = SCRIPT_MAP[scriptURL];
            let observersMap = mapEntry.observers;

            for (let obsKey in observersMap) {
              if (func(observersMap[obsKey])) {
                delete observersMap[obsKey];
              }
            }
          }
        };

        if (callbackName && typeof window !== "undefined") {
          window[callbackName] = () =>
            this.asyncScriptLoaderTriggerOnScriptLoaded();
        }

        script.onload = () => {
          let mapEntry = SCRIPT_MAP[scriptURL];
          if (mapEntry) {
            mapEntry.loaded = true;
            callObserverFuncAndRemoveObserver(observer => {
              if (callbackName) {
                return false;
              }
              observer(mapEntry);
              return true;
            });
          }
        };
        script.onerror = event => {
          let mapEntry = SCRIPT_MAP[scriptURL];
          if (mapEntry) {
            mapEntry.errored = true;
            callObserverFuncAndRemoveObserver(observer => {
              observer(mapEntry);
              return true;
            });
          }
        };

        document.body.appendChild(script);
      }

      componentWillUnmount() {
        // Remove tag script
        const scriptURL = this.__scriptURL;
        if (options.removeOnUnmount === true) {
          const allScripts = document.getElementsByTagName("script");
          for (let i = 0; i < allScripts.length; i += 1) {
            if (allScripts[i].src.indexOf(scriptURL) > -1) {
              if (allScripts[i].parentNode) {
                allScripts[i].parentNode.removeChild(allScripts[i]);
              }
            }
          }
        }
        // Clean the observer entry
        let mapEntry = SCRIPT_MAP[scriptURL];
        if (mapEntry) {
          delete mapEntry.observers[this.asyncScriptLoaderGetScriptLoaderID()];
          if (options.removeOnUnmount === true) {
            delete SCRIPT_MAP[scriptURL];
          }
        }
      }

      render() {
        const globalName = options.globalName;
        // remove asyncScriptOnLoad from childProps
        let { asyncScriptOnLoad, ...childProps } = this.props; // eslint-disable-line no-unused-vars
        if (globalName && typeof window !== "undefined") {
          childProps[globalName] =
            typeof window[globalName] !== "undefined"
              ? window[globalName]
              : undefined;
        }
        childProps.ref = this.assignChildComponent;
        return createElement(WrappedComponent, childProps);
      }
    }
    AsyncScriptLoader.displayName = `AsyncScriptLoader(${wrappedComponentName})`;
    AsyncScriptLoader.propTypes = {
      asyncScriptOnLoad: PropTypes.func,
    };

    if (options.exposeFuncs) {
      options.exposeFuncs.forEach(funcToExpose => {
        AsyncScriptLoader.prototype[funcToExpose] = function() {
          return this.getComponent()[funcToExpose](...arguments);
        };
      });
    }
    return AsyncScriptLoader;
  }
}
<|endoftext|>


<commit_before>/**
 * EventEmitter v4.0.4 - git.io/ee
 * Oliver Caldwell
 * MIT license
 * @preserve
 */
(function(exports){"use strict";function EventEmitter(){}var proto=EventEmitter.prototype,nativeIndexOf=Array.prototype.indexOf?true:false;function indexOfListener(listener,listeners){if(nativeIndexOf){return listeners.indexOf(listener)}var i=listeners.length;while(i--){if(listeners[i]===listener){return i}}return-1}proto._getEvents=function(){return this._events||(this._events={})};proto.getListeners=function(evt){var events=this._getEvents();return events[evt]||(events[evt]=[])};proto.addListener=function(evt,listener){var listeners=this.getListeners(evt);if(indexOfListener(listener,listeners)===-1){listeners.push(listener)}return this};proto.on=proto.addListener;proto.removeListener=function(evt,listener){var listeners=this.getListeners(evt),index=indexOfListener(listener,listeners);if(index!==-1){listeners.splice(index,1);if(listeners.length===0){this.removeEvent(evt)}}return this};proto.off=proto.removeListener;proto.addListeners=function(evt,listeners){return this.manipulateListeners(false,evt,listeners)};proto.removeListeners=function(evt,listeners){return this.manipulateListeners(true,evt,listeners)};proto.manipulateListeners=function(remove,evt,listeners){var i,value,single=remove?this.removeListener:this.addListener,multiple=remove?this.removeListeners:this.addListeners;if(typeof evt==="object"){for(i in evt){if(evt.hasOwnProperty(i)&&(value=evt[i])){if(typeof value==="function"){single.call(this,i,value)}else{multiple.call(this,i,value)}}}}else{i=listeners.length;while(i--){single.call(this,evt,listeners[i])}}return this};proto.removeEvent=function(evt){if(evt){delete this._getEvents()[evt]}else{delete this._events}return this};proto.emitEvent=function(evt,args){var listeners=this.getListeners(evt),i=listeners.length,response;while(i--){response=args?listeners[i].apply(null,args):listeners[i]();if(response===true){this.removeListener(evt,listeners[i])}}return this};proto.trigger=proto.emitEvent;if(typeof define==="function"&&define.amd){define(function(){return EventEmitter})}else{exports.EventEmitter=EventEmitter}})(this);<commit_msg>Recompiled v4.0.4 with correct minification. My bad.<commit_after>/**
 * EventEmitter v4.0.4 - git.io/ee
 * Oliver Caldwell
 * MIT license
 * @preserve
 */
(function(e){"use strict";function t(){}function n(e,t){if(r)return t.indexOf(e);for(var n=t.length;n--;)if(t[n]===e)return n;return-1}var i=t.prototype,r=Array.prototype.indexOf?!0:!1;i._getEvents=function(){return this._events||(this._events={})},i.getListeners=function(e){var t=this._getEvents();return t[e]||(t[e]=[])},i.addListener=function(e,t){var i=this.getListeners(e);return-1===n(t,i)&&i.push(t),this},i.on=i.addListener,i.removeListener=function(e,t){var i=this.getListeners(e),r=n(t,i);return-1!==r&&(i.splice(r,1),0===i.length&&this.removeEvent(e)),this},i.off=i.removeListener,i.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},i.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},i.manipulateListeners=function(e,t,n){var i,r,s=e?this.removeListener:this.addListener,o=e?this.removeListeners:this.addListeners;if("object"==typeof t)for(i in t)t.hasOwnProperty(i)&&(r=t[i])&&("function"==typeof r?s.call(this,i,r):o.call(this,i,r));else for(i=n.length;i--;)s.call(this,t,n[i]);return this},i.removeEvent=function(e){return e?delete this._getEvents()[e]:delete this._events,this},i.emitEvent=function(e,t){for(var n,i=this.getListeners(e),r=i.length;r--;)n=t?i[r].apply(null,t):i[r](),n===!0&&this.removeListener(e,i[r]);return this},i.trigger=i.emitEvent,"function"==typeof define&&define.amd?define(function(){return t}):e.EventEmitter=t})(this);<|endoftext|>


<commit_before>import React, {
  StyleSheet,
  Text,
  View,
  PropTypes,
  TouchableOpacity,
  Component,
  Animated,
  Dimensions,
} from 'react-native';
import Swiper from 'react-native-swiper';
const windowsWidth = Dimensions.get('window').width;
const windowsHeight = Dimensions.get('window').height;

const styles = StyleSheet.create({
  slide0: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#9DD6EB',
  },
  slide1: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#97CAE5',
  },
  slide3: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#92BBD9',
  },
  text: {
    color: '#fff',
    fontSize: 22,
    fontWeight: 'bold',
  },
  dotStyle: {
    backgroundColor: 'rgba(255,255,255,.3)',
    width: 13,
    height: 13,
    borderRadius: 7,
    marginLeft: 7,
    marginRight: 7,
    marginTop: 7,
    marginBottom: 7,
  },
  activeDotStyle: {
    backgroundColor: '#fff',
    width: 13,
    height: 13,
    borderRadius: 7,
    marginLeft: 7,
    marginRight: 7,
    marginTop: 7,
    marginBottom: 7,
  },
  paginationContainer: {
    position: 'absolute',
    bottom: 25,
    left: 0,
    right: 0,
    flexDirection: 'row',
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'transparent',
  },
  dotContainer: {
    flex: 0.6,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  btnContainer: {
    flex: 0.2,
    justifyContent: 'center',
    alignItems: 'center',
    height: 50,
  },
  nextButtonText: {
    fontSize: 25,
    fontWeight: 'bold',
    fontFamily: 'Arial',
  },
  full: {
    height: 80,
    width: 100,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default class AppIntro extends Component {
  constructor(props) {
    super(props);
    this.state = {
      skipFadeOpacity: new Animated.Value(1),
      doneFadeOpacity: new Animated.Value(0),
      nextOpacity: new Animated.Value(1),
      parallax: new Animated.Value(0),
    };
  }

  componentWillMount() {
    // this.state.parallax.setValue({x: 375, y: 0});
    // this.setState({
    //   parallax: {
    //     x: 375,
    //     y: 0,
    //   },
    // });
  }

  onNextBtnClick = (context) => {
    if (context.state.isScrolling || context.state.total < 2) return;
    const state = context.state;
    const diff = (context.props.loop ? 1 : 0) + 1 + context.state.index;
    let x = 0;
    let y = 0;
    if (state.dir === 'x') x = diff * state.width;
    if (state.dir === 'y') y = diff * state.height;
    context.refs.scrollView.scrollTo({ y, x });
    this.props.onNextBtnClick();
  }

  setDoneBtnOpacity = (value) => {
    Animated.timing(
      this.state.doneFadeOpacity,
      { toValue: value },
    ).start();
  }

  setSkipBtnOpacity = (value) => {
    Animated.timing(
      this.state.skipFadeOpacity,
      { toValue: value },
    ).start();
  }

  setNextOpacity = (value) => {
    Animated.timing(
      this.state.nextOpacity,
      { toValue: value },
    ).start();
  }

  renderPagination = (index, total, context) => {
    const { activeDotColor, dotColor, rightTextColor } = this.props;
    this.props.onSlideChange(index, total);
    const ActiveDot = (
      <View
        style={[styles.activeDotStyle, { backgroundColor: activeDotColor }]}
      />
    );
    const Dot = <View style={[styles.dotStyle, { backgroundColor: dotColor }]} />;
    let dots = [];
    for (let i = 0; i < total; i++) {
      dots.push(i === index ?
        React.cloneElement(ActiveDot, { key: i })
        :
        React.cloneElement(Dot, { key: i })
      );
    }
    let isDoneBtnShow;
    let isSkipBtnShow;
    if (index === total - 1) {
      this.setDoneBtnOpacity(1);
      this.setSkipBtnOpacity(0);
      this.setNextOpacity(0);
      isDoneBtnShow = true;
      isSkipBtnShow = false;
    } else {
      this.setDoneBtnOpacity(0);
      this.setSkipBtnOpacity(1);
      this.setNextOpacity(1);
      isDoneBtnShow = false;
      isSkipBtnShow = true;
    }
    return (
      <View style={styles.paginationContainer}>
        <Animated.View style={[styles.btnContainer, {
          opacity: this.state.skipFadeOpacity,
          transform: [{
            translateX: this.state.skipFadeOpacity.interpolate({
              inputRange: [0, 1],
              outputRange: [0, 15],
            }),
          }],
        }]}
        >
          <TouchableOpacity
            style={styles.full}
            onPress={isSkipBtnShow ? this.props.onSkipBtnClick : null}
          >
            <Text style={[styles.text, { color: rightTextColor }]}>Skip</Text>
          </TouchableOpacity>
        </Animated.View>
        <View style={styles.dotContainer}>
          {dots}
        </View>
        <View style={styles.btnContainer}>
          <Animated.View style={[styles.full, { height: 0 }, {
            opacity: this.state.doneFadeOpacity,
            transform: [{
              translateX: this.state.skipFadeOpacity.interpolate({
                inputRange: [0, 1],
                outputRange: [0, 20],
              }),
            }],
          }]}
          >
            <View style={styles.full}>
              <Text style={[styles.text, { color: rightTextColor, paddingRight: 30 }]}>Done</Text>
            </View>
          </Animated.View>
          <Animated.View style={[styles.full, { height: 0 }, { opacity: this.state.nextOpacity }]}>
            <TouchableOpacity style={styles.full}
              onPress={ isDoneBtnShow ?
                this.props.onDoneBtnClick : this.onNextBtnClick.bind(this, context)}
            >
             <Text style={[styles.nextButtonText, { color: rightTextColor }]}>›</Text>
            </TouchableOpacity>
          </Animated.View>
        </View>
      </View>
    );
  }

  renderSlidePage = (index, title) => {
    const isFirstPage = index === 0;
    const statRange = isFirstPage ? 0 : windowsWidth * (index - 1);
    const endRange = isFirstPage ? windowsWidth : windowsWidth * index;
    const startOpacity = isFirstPage ? 1 : 0;
    const endOpacity = isFirstPage ? 1 : 1;
    const leftPosition = isFirstPage ? 0 : windowsWidth / 3;
    const rightPosition = isFirstPage ? -windowsWidth / 3 : 0;
    let style = index % 2 === 0 ? styles.slide0 : styles.slide1;
    const pageView = ( <View style={[
        style,
      ]}
        showsPagination={false}
      >
      <Animated.View style={[{
        transform: [   // Array order matters
          {
            translateX: this.state.parallax.interpolate({
              inputRange: [statRange, endRange],
              outputRange: [leftPosition, rightPosition],
            }),
          }],
      },
      {
        opacity: this.state.parallax.interpolate({
          inputRange: [statRange, endRange], outputRange: [startOpacity, endOpacity],
        }),
      },
      ]}
      >
        <Text style={styles.text}>{title}</Text>
      </Animated.View>
    </View>);
    return pageView
  }

  render() {
    return (
      <Swiper style={styles.wrapper}
        loop={false}
        renderPagination={this.renderPagination}
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { x: this.state.parallax }}}]
        )}
      >
        {/*<View style={styles.slide0}>
          <Text style={styles.text}>Hello Swiper</Text>
        </View>*/}
        {this.renderSlidePage(0, '000000000000000000000')}
        {this.renderSlidePage(1, '111111111111111111111')}
        {this.renderSlidePage(2, '222222222222222222222')}
      </Swiper>
    );
  }
}

AppIntro.propTypes = {
  dotColor: PropTypes.string,
  activeDotColor: PropTypes.string,
  rightTextColor: PropTypes.string,
  leftTextColor: PropTypes.string,
  onSlideChange: PropTypes.func,
  onSkipBtnClick: PropTypes.func,
  onDoneBtnClick: PropTypes.func,
  onNextBtnClick: PropTypes.func,
};

AppIntro.defaultProps = {
  dotColor: 'rgba(255,255,255,.3)',
  activeDotColor: '#fff',
  rightTextColor: '#fff',
  leftTextColor: '#fff',
  onSlideChange: () => {},
  onSkipBtnClick: () => {},
  onDoneBtnClick: () => {},
  onNextBtnClick: () => {},
};
<commit_msg>fix code style<commit_after>import React, {
  StyleSheet,
  Text,
  View,
  PropTypes,
  TouchableOpacity,
  Component,
  Animated,
  Dimensions,
} from 'react-native';
import Swiper from 'react-native-swiper';
const windowsWidth = Dimensions.get('window').width;

const styles = StyleSheet.create({
  slide0: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#9DD6EB',
  },
  slide1: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#97CAE5',
  },
  slide3: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#92BBD9',
  },
  text: {
    color: '#fff',
    fontSize: 22,
    fontWeight: 'bold',
  },
  dotStyle: {
    backgroundColor: 'rgba(255,255,255,.3)',
    width: 13,
    height: 13,
    borderRadius: 7,
    marginLeft: 7,
    marginRight: 7,
    marginTop: 7,
    marginBottom: 7,
  },
  activeDotStyle: {
    backgroundColor: '#fff',
    width: 13,
    height: 13,
    borderRadius: 7,
    marginLeft: 7,
    marginRight: 7,
    marginTop: 7,
    marginBottom: 7,
  },
  paginationContainer: {
    position: 'absolute',
    bottom: 25,
    left: 0,
    right: 0,
    flexDirection: 'row',
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'transparent',
  },
  dotContainer: {
    flex: 0.6,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  btnContainer: {
    flex: 0.2,
    justifyContent: 'center',
    alignItems: 'center',
    height: 50,
  },
  nextButtonText: {
    fontSize: 25,
    fontWeight: 'bold',
    fontFamily: 'Arial',
  },
  full: {
    height: 80,
    width: 100,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default class AppIntro extends Component {
  constructor(props) {
    super(props);
    this.state = {
      skipFadeOpacity: new Animated.Value(1),
      doneFadeOpacity: new Animated.Value(0),
      nextOpacity: new Animated.Value(1),
      parallax: new Animated.Value(0),
    };
  }

  onNextBtnClick = (context) => {
    if (context.state.isScrolling || context.state.total < 2) return;
    const state = context.state;
    const diff = (context.props.loop ? 1 : 0) + 1 + context.state.index;
    let x = 0;
    let y = 0;
    if (state.dir === 'x') x = diff * state.width;
    if (state.dir === 'y') y = diff * state.height;
    context.refs.scrollView.scrollTo({ y, x });
    this.props.onNextBtnClick();
  }

  setDoneBtnOpacity = (value) => {
    Animated.timing(
      this.state.doneFadeOpacity,
      { toValue: value },
    ).start();
  }

  setSkipBtnOpacity = (value) => {
    Animated.timing(
      this.state.skipFadeOpacity,
      { toValue: value },
    ).start();
  }

  setNextOpacity = (value) => {
    Animated.timing(
      this.state.nextOpacity,
      { toValue: value },
    ).start();
  }

  renderPagination = (index, total, context) => {
    const { activeDotColor, dotColor, rightTextColor } = this.props;
    this.props.onSlideChange(index, total);
    const ActiveDot = (
      <View
        style={[styles.activeDotStyle, { backgroundColor: activeDotColor }]}
      />
    );
    const Dot = <View style={[styles.dotStyle, { backgroundColor: dotColor }]} />;
    let dots = [];
    for (let i = 0; i < total; i++) {
      dots.push(i === index ?
        React.cloneElement(ActiveDot, { key: i })
        :
        React.cloneElement(Dot, { key: i })
      );
    }
    let isDoneBtnShow;
    let isSkipBtnShow;
    if (index === total - 1) {
      this.setDoneBtnOpacity(1);
      this.setSkipBtnOpacity(0);
      this.setNextOpacity(0);
      isDoneBtnShow = true;
      isSkipBtnShow = false;
    } else {
      this.setDoneBtnOpacity(0);
      this.setSkipBtnOpacity(1);
      this.setNextOpacity(1);
      isDoneBtnShow = false;
      isSkipBtnShow = true;
    }
    return (
      <View style={styles.paginationContainer}>
        <Animated.View style={[styles.btnContainer, {
          opacity: this.state.skipFadeOpacity,
          transform: [{
            translateX: this.state.skipFadeOpacity.interpolate({
              inputRange: [0, 1],
              outputRange: [0, 15],
            }),
          }],
        }]}
        >
          <TouchableOpacity
            style={styles.full}
            onPress={isSkipBtnShow ? this.props.onSkipBtnClick : null}
          >
            <Text style={[styles.text, { color: rightTextColor }]}>Skip</Text>
          </TouchableOpacity>
        </Animated.View>
        <View style={styles.dotContainer}>
          {dots}
        </View>
        <View style={styles.btnContainer}>
          <Animated.View style={[styles.full, { height: 0 }, {
            opacity: this.state.doneFadeOpacity,
            transform: [{
              translateX: this.state.skipFadeOpacity.interpolate({
                inputRange: [0, 1],
                outputRange: [0, 20],
              }),
            }],
          }]}
          >
            <View style={styles.full}>
              <Text style={[styles.text, { color: rightTextColor, paddingRight: 30 }]}>Done</Text>
            </View>
          </Animated.View>
          <Animated.View style={[styles.full, { height: 0 }, { opacity: this.state.nextOpacity }]}>
            <TouchableOpacity style={styles.full}
              onPress={ isDoneBtnShow ?
                this.props.onDoneBtnClick : this.onNextBtnClick.bind(this, context)}
            >
             <Text style={[styles.nextButtonText, { color: rightTextColor }]}>›</Text>
            </TouchableOpacity>
          </Animated.View>
        </View>
      </View>
    );
  }

  renderSlidePage = (index, title) => {
    const isFirstPage = index === 0;
    const statRange = isFirstPage ? 0 : windowsWidth * (index - 1);
    const endRange = isFirstPage ? windowsWidth : windowsWidth * index;
    const startOpacity = isFirstPage ? 1 : 0;
    const endOpacity = isFirstPage ? 1 : 1;
    const leftPosition = isFirstPage ? 0 : windowsWidth / 3;
    const rightPosition = isFirstPage ? -windowsWidth / 3 : 0;
    const style = index % 2 === 0 ? styles.slide0 : styles.slide1;
    const pageView = (
      <View style={[style]} showsPagination={false}>
        <Animated.View style={[{
          transform: [   // Array order matters
            {
              translateX: this.state.parallax.interpolate({
                inputRange: [statRange, endRange],
                outputRange: [leftPosition, rightPosition],
              }),
            }],
        }, {
          opacity: this.state.parallax.interpolate({
            inputRange: [statRange, endRange], outputRange: [startOpacity, endOpacity],
          }),
        }]}
        >
          <Text style={styles.text}>{title}</Text>
        </Animated.View>
      </View>
    );
    return pageView
  }

  render() {
    return (
      <Swiper style={styles.wrapper}
        loop={false}
        renderPagination={this.renderPagination}
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { x: this.state.parallax } } }]
        )}
      >
        {this.renderSlidePage(0, '000000000000000000000')}
        {this.renderSlidePage(1, '111111111111111111111')}
        {this.renderSlidePage(2, '222222222222222222222')}
      </Swiper>
    );
  }
}

AppIntro.propTypes = {
  dotColor: PropTypes.string,
  activeDotColor: PropTypes.string,
  rightTextColor: PropTypes.string,
  leftTextColor: PropTypes.string,
  onSlideChange: PropTypes.func,
  onSkipBtnClick: PropTypes.func,
  onDoneBtnClick: PropTypes.func,
  onNextBtnClick: PropTypes.func,
};

AppIntro.defaultProps = {
  dotColor: 'rgba(255,255,255,.3)',
  activeDotColor: '#fff',
  rightTextColor: '#fff',
  leftTextColor: '#fff',
  onSlideChange: () => {},
  onSkipBtnClick: () => {},
  onDoneBtnClick: () => {},
  onNextBtnClick: () => {},
};
<|endoftext|>


<commit_before>import * as Sounds from '../Sounds';
import { Service } from '../Service';
import { SingletonPage, PageHost } from './SingletonPage';

class SettingsService extends Service
{
  constructor(settingsManager) {
    super();
    this.settingsManager = settingsManager;
  }

  async getSettings() {
    return await this.settingsManager.get();
  }

  async setSettings(settings) {
    if (!this._isValid(settings)) {
      return;
    }

    await this.settingsManager.set(settings);
  }

  _isValid(settings) {
    let phasesValid = [settings.focus, settings.shortBreak, settings.longBreak].every(p => this._isPhaseValid(p));
    if (!phasesValid) {
      return false;
    }

    let autostart = settings.autostart && settings.autostart.time;
    if (autostart && !autostart.match(/^\d+:\d+$/)) {
      return false;
    }

    return true;
  }

  _isPhaseValid(phase) {
    let { duration, timerSound, countdown } = phase;
    if (isNaN(duration) || duration <= 0 || duration > 999) {
      return false;
    }

    if (timerSound && timerSound.metronome) {
      let { bpm } = timerSound.metronome;
      if (isNaN(bpm) || bpm <= 0 || bpm > 1000) {
        return false;
      }
    }

    if (countdown.host === 'window') {
      let { resolution } = countdown;

      // Resolution must either be 'fullscreen' or a [width, height] array.
      let isValid = (resolution === 'fullscreen') || (Array.isArray(resolution) && resolution.length === 2 && resolution.every(d => Number.isInteger(d)));
      if (!isValid) {
        return false;
      }
    }

    return true;
  }
}

class HistoryService extends Service
{
  constructor(history) {
    super();
    this.history = history;
  }

  async getStats(since) {
    return await this.history.stats(since);
  }

  async getCSV() {
    return await this.history.toCSV();
  }

  async getAll() {
    return await this.history.all();
  }

  async merge(history) {
    return await this.history.merge(history);
  }

  async clearHistory() {
    return await this.history.clear();
  }
}

class PomodoroService extends Service
{
  constructor(timer) {
    super();
    this.timer = timer;
    this.timer.observe(this);
  }

  async startSession() {
    this.timer.start();
  }

  async getStatus() {
    return this.timer.status;
  }

  onStart(...args) {
    this.emit('start', ...args);
  }

  onStop(...args) {
    this.emit('stop', ...args);
  }

  onPause(...args) {
    this.emit('pause', ...args);
  }

  onResume(...args) {
    this.emit('resume', ...args);
  }

  onTick(...args) {
    this.emit('tick', ...args);
  }

  onExpire(...args) {
    this.emit('expire', ...args);
  }
}

class SoundsService extends Service
{
  async getNotificationSounds() {
    return Sounds.notification;
  }

  async getTimerSounds() {
    return Sounds.timer;
  }
}

class OptionsService extends Service
{
  async showPage(optionPage) {
    let manifest = chrome.runtime.getManifest();
    let url = chrome.extension.getURL(manifest.options_page + '#/' + optionPage);
    let page = await SingletonPage.show(url, PageHost.Tab);
    page.focus();
  }

  async showSettingsPage() {
    return await this.showPage('settings');
  }

  async showHistoryPage() {
    return await this.showPage('history');
  }

  async showFeedbackPage() {
    return await this.showPage('feedback');
  }
}

const SettingsClient = SettingsService.proxy;
const HistoryClient = HistoryService.proxy;
const PomodoroClient = PomodoroService.proxy;
const SoundsClient = SoundsService.proxy;
const OptionsClient = OptionsService.proxy;

export {
  SettingsService,
  SettingsClient,
  HistoryService,
  HistoryClient,
  PomodoroService,
  PomodoroClient,
  SoundsService,
  SoundsClient,
  OptionsService,
  OptionsClient
};<commit_msg>Simplify expressions.<commit_after>import * as Sounds from '../Sounds';
import { Service } from '../Service';
import { SingletonPage, PageHost } from './SingletonPage';

class SettingsService extends Service
{
  constructor(settingsManager) {
    super();
    this.settingsManager = settingsManager;
  }

  async getSettings() {
    return await this.settingsManager.get();
  }

  async setSettings(settings) {
    if (!this._isValid(settings)) {
      return;
    }

    await this.settingsManager.set(settings);
  }

  _isValid(settings) {
    let phasesValid = [settings.focus, settings.shortBreak, settings.longBreak].every(this._isPhaseValid);
    if (!phasesValid) {
      return false;
    }

    let autostart = settings.autostart && settings.autostart.time;
    if (autostart && !autostart.match(/^\d+:\d+$/)) {
      return false;
    }

    return true;
  }

  _isPhaseValid(phase) {
    let { duration, timerSound, countdown } = phase;
    if (isNaN(duration) || duration <= 0 || duration > 999) {
      return false;
    }

    if (timerSound && timerSound.metronome) {
      let { bpm } = timerSound.metronome;
      if (isNaN(bpm) || bpm <= 0 || bpm > 1000) {
        return false;
      }
    }

    if (countdown.host === 'window') {
      let { resolution } = countdown;

      // Resolution must either be 'fullscreen' or a [width, height] array.
      let isValid = (resolution === 'fullscreen') || (Array.isArray(resolution) && resolution.length === 2 && resolution.every(Number.isInteger));
      if (!isValid) {
        return false;
      }
    }

    return true;
  }
}

class HistoryService extends Service
{
  constructor(history) {
    super();
    this.history = history;
  }

  async getStats(since) {
    return await this.history.stats(since);
  }

  async getCSV() {
    return await this.history.toCSV();
  }

  async getAll() {
    return await this.history.all();
  }

  async merge(history) {
    return await this.history.merge(history);
  }

  async clearHistory() {
    return await this.history.clear();
  }
}

class PomodoroService extends Service
{
  constructor(timer) {
    super();
    this.timer = timer;
    this.timer.observe(this);
  }

  async startSession() {
    this.timer.start();
  }

  async getStatus() {
    return this.timer.status;
  }

  onStart(...args) {
    this.emit('start', ...args);
  }

  onStop(...args) {
    this.emit('stop', ...args);
  }

  onPause(...args) {
    this.emit('pause', ...args);
  }

  onResume(...args) {
    this.emit('resume', ...args);
  }

  onTick(...args) {
    this.emit('tick', ...args);
  }

  onExpire(...args) {
    this.emit('expire', ...args);
  }
}

class SoundsService extends Service
{
  async getNotificationSounds() {
    return Sounds.notification;
  }

  async getTimerSounds() {
    return Sounds.timer;
  }
}

class OptionsService extends Service
{
  async showPage(optionPage) {
    let manifest = chrome.runtime.getManifest();
    let url = chrome.extension.getURL(manifest.options_page + '#/' + optionPage);
    let page = await SingletonPage.show(url, PageHost.Tab);
    page.focus();
  }

  async showSettingsPage() {
    return await this.showPage('settings');
  }

  async showHistoryPage() {
    return await this.showPage('history');
  }

  async showFeedbackPage() {
    return await this.showPage('feedback');
  }
}

const SettingsClient = SettingsService.proxy;
const HistoryClient = HistoryService.proxy;
const PomodoroClient = PomodoroService.proxy;
const SoundsClient = SoundsService.proxy;
const OptionsClient = OptionsService.proxy;

export {
  SettingsService,
  SettingsClient,
  HistoryService,
  HistoryClient,
  PomodoroService,
  PomodoroClient,
  SoundsService,
  SoundsClient,
  OptionsService,
  OptionsClient
};<|endoftext|>


<commit_before>'use strict'

module.exports = Sailbot

/*
 * Module dependencies
 */
let Webdriver = require('selenium-webdriver')
let By = Webdriver.By
let Until = Webdriver.until
let Init = require('./lib/launch')

/**
 * Namespace Object composed
 * @param  {object} [ options = {timeout: '30', port: 7055} ]
 *         Pass a property 'dev' to launch and keep session/browser opened
 *         Pass a property 'id': {string} session id, to attach to session
 * @returns {object} sailbot
 */
function Sailbot (options) {

    let proto = {
        to,
        switchTo,
        waitFor,
        isFound,
        isVisible,
        get: get,
        getAll,
        click,
        clear,
        write,
        innerHtml,
        text,
        attribute,
        alert,
        sleep,
        quit }

    let obj = Object.create(proto)

    let webdriver = init(options)
    obj.driver = webdriver.driver
    obj.flow = webdriver.flow

    return obj
}

function init (opt) {
    let driver
    let flow = 'Running in Dev Mode (one browser supported)'
    if ( opt && opt.hasOwnProperty('dev') ) {
        Init.dev_launch(opt)
    }
    else if ( opt && opt.hasOwnProperty('id') ) {
        driver = Init.dev_attach(opt)
    }
    else {
        let newBrowser = Init.launch(opt)
        driver = newBrowser.driver
        flow = newBrowser.flow
    }
    let webdriver = { driver, flow }
    return webdriver
}

/**
 * Methods
 */

/**
 * @param {string} url
 * @returns {sailbot}
 */
function to (url) {
    this.driver.get(url)
    return this
}

/**
 * Switches to all of the frames in order passed in the array
 * @param {array} [frame] - iframe's DOM node path -name or id.
 * Pass any string to switch to defaultContent()
 * @returns {sailbot}
 */
function switchTo (frame) {
    let switchTo = this.driver.switchTo()
    switchTo.defaultContent()
    let switchFrame = (frame) => switchTo.frame(frame)
    if (typeof frame !== 'string') frame.map(switchFrame)
    return this
}

/**
* @param {string} cssSelector
* @returns {sailbot} chain with with isFound() or isVisible()
*/
function waitFor (cssSelector) {
    this._locator = By.css(cssSelector)
    this._webElem = this.driver.findElement(this._locator)
    return this
}

/**
* @returns {sailbot}
*/
function isFound () {
    this.driver.wait(Until.elementsLocated(this._locator))
    return this
}

/**
* @returns {sailbot}
*/
function isVisible () {
    this.driver.wait(Until.elementIsVisible(this._webElem))
    return this
}

/**
* @param {string} cssSelector
* @returns {sailbot}
*/
function get (cssSelector, visibility) {
    _load(this, cssSelector, visibility)
    this.whatGet = 'get'
    return this
}

/**
* @param {string} cssSelector
* @returns {sailbot}
*/
function getAll (cssSelector, visibility) {
    _load(this, cssSelector, visibility)
    this.whatGet = 'getAll'
    return this
}

/**
* @param {Any} [returnPromise] pass any value to return a promise
* @returns {sailbot | promise} promise if a param is passed
*/
function click (returnPromise) {
    let promise = this._webElem.click()
    if (returnPromise) return promise
    return this
}

/**
* @returns {sailbot}
*/
function clear () {
    this._webElem.clear()
    return this
}

/**
* @param {string} text
* @returns {sailbot}
*/
function write (text) {
    this._webElem.sendKeys(text)
    return this
}

/**
* @returns {promise} value (when get() used) or array of values (getAll())
*/
function text () {
    let fn = () => (elem) => elem.getText()
    return _execAction(this, fn)
}

/**
* @returns {promise} value (when get() used) or array of values (getAll())
*/
function innerHtml () {
    let fn = () => (elem) => elem.getInnerHtml()
    return _execAction(this, fn)
}

/**
* @param {string} attribute name
* @returns {promise} value (when get() used) or array of values (getAll())
*/
function attribute (attrName) {
    let fn = (attrName) => (elem) => elem.getAttribute(attrName)
    return _execAction(this, fn, attrName)
}

/**
* @returns {sailbot} chainable with webdriver native functions. EG:
* alert()( .accept() | .dismiss() | .getText() | .cancel(arg0)...)
*/
function alert () {
    this.driver.wait(Until.alertIsPresent(), 1000, 'WHAT')
    return this.driver.switchTo().alert()
}

/**
* @param {number} ms
* @returns {sailbot}
*/
function sleep (ms) {
    this.driver.sleep(ms)
    return this
}

/**
* @returns {sailbot}
*/
function quit () {
    this.driver.quit()
    return this
}

/*
 * Internal functions
 */

// run correspondent getAll or get
function _execAction (self, action, actionParam) {
    if (self.whatGet === 'getAll') {
        let actionFn = action(actionParam)
        return Webdriver.promise.map(self._webElemsArr, actionFn)
    }
    else return action(actionParam)(self._webElem)
}

function _load (self, cssSelector, visibility) {
    let locator = self._locator = By.css(cssSelector)
    self._webElem = self.driver.findElement(locator)
    self._webElemsArr = self.driver.findElements(locator)
    self.isFound() // checks first if element is in the page
    if (!visibility) self.isVisible() // then if it is visible
}
<commit_msg>quit() returns promise (resolved when browser closes)<commit_after>'use strict'

module.exports = Sailbot

/*
 * Module dependencies
 */
let Webdriver = require('selenium-webdriver')
let By = Webdriver.By
let Until = Webdriver.until
let Init = require('./lib/launch')

/**
 * Namespace Object composed
 * @param  {object} [ options = {timeout: '30', port: 7055} ]
 *         Pass a property 'dev' to launch and keep session/browser opened
 *         Pass a property 'id': {string} session id, to attach to session
 * @returns {object} sailbot
 */
function Sailbot (options) {

    let proto = {
        to,
        switchTo,
        waitFor,
        isFound,
        isVisible,
        get: get,
        getAll,
        click,
        clear,
        write,
        innerHtml,
        text,
        attribute,
        alert,
        sleep,
        quit }

    let obj = Object.create(proto)

    let webdriver = init(options)
    obj.driver = webdriver.driver
    obj.flow = webdriver.flow

    return obj
}

function init (opt) {
    let driver
    let flow = 'Running in Dev Mode (one browser supported)'
    if ( opt && opt.hasOwnProperty('dev') ) {
        Init.dev_launch(opt)
    }
    else if ( opt && opt.hasOwnProperty('id') ) {
        driver = Init.dev_attach(opt)
    }
    else {
        let newBrowser = Init.launch(opt)
        driver = newBrowser.driver
        flow = newBrowser.flow
    }
    let webdriver = { driver, flow }
    return webdriver
}

/**
 * Methods
 */

/**
 * @param {string} url
 * @returns {sailbot}
 */
function to (url) {
    this.driver.get(url)
    return this
}

/**
 * Switches to all of the frames in order passed in the array
 * @param {array} [frame] - iframe's DOM node path -name or id.
 * Pass any string to switch to defaultContent()
 * @returns {sailbot}
 */
function switchTo (frame) {
    let switchTo = this.driver.switchTo()
    switchTo.defaultContent()
    let switchFrame = (frame) => switchTo.frame(frame)
    if (typeof frame !== 'string') frame.map(switchFrame)
    return this
}

/**
* @param {string} cssSelector
* @returns {sailbot} chain with with isFound() or isVisible()
*/
function waitFor (cssSelector) {
    this._locator = By.css(cssSelector)
    this._webElem = this.driver.findElement(this._locator)
    return this
}

/**
* @returns {sailbot}
*/
function isFound () {
    this.driver.wait(Until.elementsLocated(this._locator))
    return this
}

/**
* @returns {sailbot}
*/
function isVisible () {
    this.driver.wait(Until.elementIsVisible(this._webElem))
    return this
}

/**
* @param {string} cssSelector
* @returns {sailbot}
*/
function get (cssSelector, visibility) {
    _load(this, cssSelector, visibility)
    this.whatGet = 'get'
    return this
}

/**
* @param {string} cssSelector
* @returns {sailbot}
*/
function getAll (cssSelector, visibility) {
    _load(this, cssSelector, visibility)
    this.whatGet = 'getAll'
    return this
}

/**
* @param {Any} [returnPromise] pass any value to return a promise
* @returns {sailbot | promise} promise if a param is passed
*/
function click (returnPromise) {
    let promise = this._webElem.click()
    if (returnPromise) return promise
    return this
}

/**
* @returns {sailbot}
*/
function clear () {
    this._webElem.clear()
    return this
}

/**
* @param {string} text
* @returns {sailbot}
*/
function write (text) {
    this._webElem.sendKeys(text)
    return this
}

/**
* @returns {promise} value (when get() used) or array of values (getAll())
*/
function text () {
    let fn = () => (elem) => elem.getText()
    return _execAction(this, fn)
}

/**
* @returns {promise} value (when get() used) or array of values (getAll())
*/
function innerHtml () {
    let fn = () => (elem) => elem.getInnerHtml()
    return _execAction(this, fn)
}

/**
* @param {string} attribute name
* @returns {promise} value (when get() used) or array of values (getAll())
*/
function attribute (attrName) {
    let fn = (attrName) => (elem) => elem.getAttribute(attrName)
    return _execAction(this, fn, attrName)
}

/**
* @returns {sailbot} chainable with webdriver native functions. EG:
* alert()( .accept() | .dismiss() | .getText() | .cancel(arg0)...)
*/
function alert () {
    this.driver.wait(Until.alertIsPresent(), 1000, 'WHAT')
    return this.driver.switchTo().alert()
}

/**
* @param {number} ms
* @returns {sailbot}
*/
function sleep (ms) {
    this.driver.sleep(ms)
    return this
}

/**
* @returns {sailbot}
*/
function quit () {
    return this.driver.quit()
}

/*
 * Internal functions
 */

// run correspondent getAll or get
function _execAction (self, action, actionParam) {
    if (self.whatGet === 'getAll') {
        let actionFn = action(actionParam)
        return Webdriver.promise.map(self._webElemsArr, actionFn)
    }
    else return action(actionParam)(self._webElem)
}

function _load (self, cssSelector, visibility) {
    let locator = self._locator = By.css(cssSelector)
    self._webElem = self.driver.findElement(locator)
    self._webElemsArr = self.driver.findElements(locator)
    self.isFound() // checks first if element is in the page
    if (!visibility) self.isVisible() // then if it is visible
}
<|endoftext|>


<commit_before>/*jshint multistr: true */

'use strict'

var $ = require('jquery'),
    history = require('../../../libs/history.js/scripts/bundled/html5/jquery.history'),
    tab = require('../../../js/libs/tab'),
    dropdown = require('../../../js/libs/dropdown'),
    PulsarUIComponent = require('../../../js/PulsarUIComponent');

    $.fx.off = !$.fx.off;

describe('Pulsar UI Component', function() {

    beforeEach(function() {
        this.$html = $('');
        this.$body = $('').appendTo(this.$html);
        this.$code = $(`

                        foo
                        bar

                                <button data-toggle="dropdown" class="btn dropdown__toggle row-actions">
                                    Actions
                                </button>

action

            foo
            foo

            Expires in 6 hours\
`).appendTo(this.$html);

        this.$tabLink = this.$html.find('a[href="#tab"]');
        this.$pushStateTabLink = this.$html.find('a[href="#tab-foo"]');
        this.$isDisabled = this.$html.find('a[disabled]');
        this.$basicTable = this.$html.find('.qa-table');
        this.$datagridTable = this.$html.find('.qa-datagrid');
        this.$datatableTable = this.$html.find('.qa-datatable');
        this.$datatableWithCustomMessage = this.$html.find('.qa-datatable-empty-message');
        this.$datatableDisableSelection = this.$html.find('.qa-datatable-no-selection');
        this.$tableDupe = this.$html.find('.qa-table-dupe');
        this.$countdownOne = this.$html.find('.qa-countdown-one');
        this.$datatableActions = this.$html.find('.qa-datatable-actions');

        this.history = {
            pushState: sinon.stub()
        };

        this.pulsarUIComponent = new PulsarUIComponent(this.$html, this.history);

    });

    describe('A countdown element', function() {

        beforeEach(function() {
            sinon.spy($.fn, 'countdown');
            this.pulsarUIComponent.init();
        });

        it('should call the countdown plugin', function() {
            expect($.fn.countdown).to.have.been.called;
        });
    });

    describe('disabled links', function() {

        beforeEach(function() {
            this.pulsarUIComponent.init();
        });

        it('should preventDefault', function() {
            var clickEvent = $.Event('click');
            this.$isDisabled.trigger(clickEvent);
            expect(clickEvent.isDefaultPrevented()).to.be.true;
        });

    });

    describe('initialising tables', function() {

        beforeEach(function() {
            this.pulsarUIComponent.init();
        });

        it('should wrap basic tables with the container', function() {
            expect(this.$basicTable.parent().hasClass('table-container')).to.be.true;
        });

        it('should wrap datagrid tables with the container', function() {
            expect(this.$datagridTable.parent().hasClass('table-container')).to.be.true;
        });

        it('should NOT wrap datatable tables with the container', function() {
            expect(this.$datatableTable.parent().hasClass('table-container')).to.be.false;
        });

        it('should NOT wrap tables which already have the container', function() {
            expect(this.$tableDupe.parent().parent().hasClass('table-container')).to.be.false;
        });

        it('should show the default empty table message', function() {
            expect(this.$datatableTable.find('.dataTables_empty').text()).to.equal('There are currently no items to display');
        });

        it('should allow the empty table message to be overridden', function() {
            expect(this.$datatableWithCustomMessage.find('.dataTables_empty').text()).to.equal('foo');
        });

        it('should wrap the table with the disable class when the data-select attribute is false', function() {
            expect(this.$datatableDisableSelection.parent().hasClass('dt-disable-selection')).to.be.true;
        });
    });

    describe('Table row-actions', function() {

        beforeEach(function() {
            sinon.spy(this.pulsarUIComponent, 'closeRowActions');
            this.pulsarUIComponent.init();
        });

        it('should be opened when clicked', function() {
            this.$rowActions.click();
            setTimeout(function(done){
                expect(this.$rowActions.parent().hasClass('open')).to.be.true;
                done();
            }, 1000);
        });

        it('should be closed when clicked again', function() {
            this.$rowActions.click();
            this.$rowActions.click();
            setTimeout(function(done){
                expect(this.$rowActions.parent().hasClass('open')).to.be.false;
                done();
            }, 1000);
        });

        it('should call the closeRowActions method when window resized', function() {
            this.$rowActions.click();
            this.$html.trigger('resize');
            setTimeout(function(done){
                expect(this.closeRowActions).to.have.been.called;
                done();
            }, 1000);
        });

        it('should call the closeRowActions method when table scrolled', function() {
            this.$rowActions.click();
            this.$datatableActions.trigger('scroll');
            setTimeout(function(){
                expect(this.closeRowActions).to.have.been.called;
            }, 1000);
        });

        it('should be closed when the window resized', function() {
            this.$rowActions.click();
            this.$html.trigger('resize');
            expect(this.$rowActions.parent().hasClass('open')).to.be.false;
        });

        it('should be closed when the table is scrolled resized', function() {
            this.$rowActions.click();
            this.$datatableActions.trigger('scroll');
            expect(this.$rowActions.parent().hasClass('open')).to.be.false;
        });

    });

    describe('Clicking a tab toggle with the data-href attribute', function() {

        beforeEach(function() {
            this.pulsarUIComponent.init();
        });

        it('should call the history plugin', function() {
            this.$pushStateTabLink.click();
            expect(this.history.pushState).to.have.been.calledOnce;
        });

        it('should push the correct state object onto the history stack', function () {
            this.$pushStateTabLink.click();
            expect(this.history.pushState).to.have.been.calledWith({state: 1});
        });

        it('should push the correct href onto the history stack', function () {
            this.$pushStateTabLink.click();
            expect(this.history.pushState).to.have.been.calledWith(sinon.match.any, '?tab=foo', '?tab=foo');
        });
    });

    describe('clicking a tab toggle', function() {

        beforeEach(function() {

            this.recalc = sinon.stub();

            $.fn.dataTable = {
                tables: sinon.stub()
            };

            $.fn.DataTable = sinon.stub().returns({
                columns: {
                    adjust: sinon.stub().returns({
                        responsive: {
                            recalc: this.recalc
                        }
                    })
                }
            });

            this.pulsarUIComponent.init();
            this.$tabLink.click();
            this.$tabLink.trigger('shown.bs.tab');

        });

        afterEach(function () {
            delete $.fn.dataTable;
            delete $.fn.DataTable;
        });

        it('should recalculate the table', function() {
            expect(this.recalc).to.have.been.calledOnce;
        });

    });
});
<commit_msg>Fixes datatable row actions tests<commit_after>/*jshint multistr: true */

'use strict'

var $ = require('jquery'),
    history = require('../../../libs/history.js/scripts/bundled/html5/jquery.history'),
    tab = require('../../../js/libs/tab'),
    dropdown = require('../../../js/libs/dropdown'),
    PulsarUIComponent = require('../../../js/PulsarUIComponent');

    $.fx.off = !$.fx.off;

describe('Pulsar UI Component', function() {

    beforeEach(function() {
        this.$html = $('');
        this.$body = $('').appendTo(this.$html);
        this.$code = $(`

                        foo
                        bar

                                <button data-toggle="dropdown" class="btn dropdown__toggle row-actions">
                                    Actions
                                </button>

action

            foo
            foo

            Expires in 6 hours\
`).appendTo(this.$html);

        this.$tabLink = this.$html.find('a[href="#tab"]');
        this.$pushStateTabLink = this.$html.find('a[href="#tab-foo"]');
        this.$isDisabled = this.$html.find('a[disabled]');
        this.$basicTable = this.$html.find('.qa-table');
        this.$datagridTable = this.$html.find('.qa-datagrid');
        this.$datatableTable = this.$html.find('.qa-datatable');
        this.$datatableWithCustomMessage = this.$html.find('.qa-datatable-empty-message');
        this.$datatableDisableSelection = this.$html.find('.qa-datatable-no-selection');
        this.$tableDupe = this.$html.find('.qa-table-dupe');
        this.$countdownOne = this.$html.find('.qa-countdown-one');
        this.$datatableActions = this.$html.find('.qa-datatable-actions');
        this.$rowActions = this.$html.find('.row-actions');

        this.history = {
            pushState: sinon.stub()
        };

        this.pulsarUIComponent = new PulsarUIComponent(this.$html, this.history);

    });

    describe('A countdown element', function() {

        beforeEach(function() {
            sinon.spy($.fn, 'countdown');
            this.pulsarUIComponent.init();
        });

        it('should call the countdown plugin', function() {
            expect($.fn.countdown).to.have.been.called;
        });
    });

    describe('disabled links', function() {

        beforeEach(function() {
            this.pulsarUIComponent.init();
        });

        it('should preventDefault', function() {
            var clickEvent = $.Event('click');
            this.$isDisabled.trigger(clickEvent);
            expect(clickEvent.isDefaultPrevented()).to.be.true;
        });

    });

    describe('initialising tables', function() {

        beforeEach(function() {
            this.pulsarUIComponent.init();
        });

        it('should wrap basic tables with the container', function() {
            expect(this.$basicTable.parent().hasClass('table-container')).to.be.true;
        });

        it('should wrap datagrid tables with the container', function() {
            expect(this.$datagridTable.parent().hasClass('table-container')).to.be.true;
        });

        it('should NOT wrap datatable tables with the container', function() {
            expect(this.$datatableTable.parent().hasClass('table-container')).to.be.false;
        });

        it('should NOT wrap tables which already have the container', function() {
            expect(this.$tableDupe.parent().parent().hasClass('table-container')).to.be.false;
        });

        it('should show the default empty table message', function() {
            expect(this.$datatableTable.find('.dataTables_empty').text()).to.equal('There are currently no items to display');
        });

        it('should allow the empty table message to be overridden', function() {
            expect(this.$datatableWithCustomMessage.find('.dataTables_empty').text()).to.equal('foo');
        });

        it('should wrap the table with the disable class when the data-select attribute is false', function() {
            expect(this.$datatableDisableSelection.parent().hasClass('dt-disable-selection')).to.be.true;
        });
    });

    describe('Table row-actions', function() {

        beforeEach(function() {
            sinon.spy(this.pulsarUIComponent, 'closeRowActions');
            this.pulsarUIComponent.init();
        });

        it('should be opened when clicked', function() {
            this.$rowActions.click();
            setTimeout(function(done){
                expect(this.$rowActions.parent().hasClass('open')).to.be.true;
                done();
            }, 1000);
        });

        it('should be closed when clicked again', function() {
            this.$rowActions.click();
            this.$rowActions.click();
            setTimeout(function(done){
                expect(this.$rowActions.parent().hasClass('open')).to.be.false;
                done();
            }, 1000);
        });

        it('should call the closeRowActions method when window resized', function() {
            this.$rowActions.click();
            this.$html.trigger('resize');
            setTimeout(function(done){
                expect(this.closeRowActions).to.have.been.called;
                done();
            }, 1000);
        });

        it('should call the closeRowActions method when table scrolled', function() {
            this.$rowActions.click();
            this.$datatableActions.trigger('scroll');
            setTimeout(function(){
                expect(this.closeRowActions).to.have.been.called;
            }, 1000);
        });

        it('should be closed when the window resized', function() {
            this.$rowActions.click();
            this.$html.trigger('resize');
            expect(this.$rowActions.parent().hasClass('open')).to.be.false;
        });

        it('should be closed when the table is scrolled resized', function() {
            this.$rowActions.click();
            this.$datatableActions.trigger('scroll');
            expect(this.$rowActions.parent().hasClass('open')).to.be.false;
        });

    });

    describe('Clicking a tab toggle with the data-href attribute', function() {

        beforeEach(function() {
            this.pulsarUIComponent.init();
        });

        it('should call the history plugin', function() {
            this.$pushStateTabLink.click();
            expect(this.history.pushState).to.have.been.calledOnce;
        });

        it('should push the correct state object onto the history stack', function () {
            this.$pushStateTabLink.click();
            expect(this.history.pushState).to.have.been.calledWith({state: 1});
        });

        it('should push the correct href onto the history stack', function () {
            this.$pushStateTabLink.click();
            expect(this.history.pushState).to.have.been.calledWith(sinon.match.any, '?tab=foo', '?tab=foo');
        });
    });

    describe('clicking a tab toggle', function() {

        beforeEach(function() {

            this.recalc = sinon.stub();

            $.fn.dataTable = {
                tables: sinon.stub()
            };

            $.fn.DataTable = sinon.stub().returns({
                columns: {
                    adjust: sinon.stub().returns({
                        responsive: {
                            recalc: this.recalc
                        }
                    })
                }
            });

            this.pulsarUIComponent.init();
            this.$tabLink.click();
            this.$tabLink.trigger('shown.bs.tab');

        });

        afterEach(function () {
            delete $.fn.dataTable;
            delete $.fn.DataTable;
        });

        it('should recalculate the table', function() {
            expect(this.recalc).to.have.been.calledOnce;
        });

    });
});
<|endoftext|>