<commit_before>/* Python 'str' type */

var str = __inherit(object);

str.__name__ = 'str';
str.prototype.__class__ = str;
str.prototype.MARK = "str";

str.prototype.__init__ = function(s) {
    if (!defined(s)) {
        this._obj = '';
    } else {
        if (typeof(s) === "string") {
            this._obj = s;
        } else if (defined(s.toString)) {
            this._obj = s.toString();
        } else if (defined(s.__str__)) {
            this._obj = js(s.__str__());
        } else
            this._obj = js(s);
    }
};

str.prototype.__str__ = function () {
    return this;
};

str.prototype.__eq__ = function (other) {
    if (other.__class__ == this.__class__) {
        if (len(this) != len(other))
            return false;
        for (var i = 0; i < len(this); i++) {
            if (this._obj[i] != other._obj[i])
                return false;
        }
        return true;
    } else
        return false;
};

str.prototype.toString = function () {
    return js(this.__str__());
};

str.prototype._js_ = function () {
    return this._obj;
};

str.prototype.__hash__ = function () {
    var value = 0x345678;
    var length = this.__len__();

    for (var index in this._obj) {
        value = ((1000003*value) & 0xFFFFFFFF) ^ hash(this._obj[index]);
        value = value ^ length;
    }

    if (value == -1) {
        value = -2;
    }

    return value;
};

str.prototype.__len__ = function() {
    return this._obj.length;
};

str.prototype.__iter__ = function() {
    return iter.__call__(this._obj);
};

str.prototype.__bool__ = function() {
    return py_builtins.bool(this._obj);
};

str.prototype.__eq__ = function(s) {
    if (typeof(s) === "string")
        return this._obj == s;
    else if (isinstance(s, str))
        return this._obj == s._obj;
    else
        return false;
};

str.prototype.__contains__ = function(item) {
    for (var index in this._obj) {
        if (item == this._obj[index]) {
            return true;
        }
    }

    return false;
};

str.prototype.__getitem__ = function(index) {

    var seq;
    if (isinstance(index, slice)) {
        var s = index;
        var inds = s.indices(len(this));
        var start = inds.__getitem__(0);
        var stop = inds.__getitem__(1);
        var step = inds.__getitem__(2);
        seq = "";
        for (var i = start; i < stop; i += step) {
            seq = seq + js(this.__getitem__(i));
        }
        return this.__class__.__call__(seq);
    } else if ((index >= 0) && (index < len(this)))
        return this._obj[index];
    else if ((index < 0) && (index >= -len(this)))
        return this._obj[index+len(this)];
    else
        throw new py_builtins.IndexError("string index out of range");
};

str.prototype.__setitem__ = function(index, value) {
    throw new py_builtins.TypeError("'str' object doesn't support item assignment");
};

str.prototype.__delitem__ = function(index) {
    throw new py_builtins.TypeError("'str' object doesn't support item deletion");
};

str.prototype.count = function(str, start, end) {
    if (!defined(start))
        start = 0;
    if (!defined(end))
        end = null;
    var count = 0;
    s = this.__getitem__(slice.__call__(start, end));
    idx = s.find(str);
    while (idx != -1) {
        count += 1;
        s = s.__getitem__(slice.__call__(idx+1, null));
        idx = s.find(str);
    }
    return count;
};

str.prototype.index = function(value, start, end) {
    if (!defined(start)) {
        start = 0;
    }

    for (var i = start; !defined(end) || (start < end); i++) {
        var _value = this._obj[i];

        if (!defined(_value)) {
            break;
        }

        if (_value == value) {
            return i;
        }
    }

    throw new py_builtins.ValueError("substring not found");
};

str.prototype.find = function(s) {
    return this._obj.search(s);
};

str.prototype.rfind = function(s) {
    rev = function(s) {
        var a = list.__call__(str.__call__(s));
        a.reverse();
        a = str.__call__("").join(a);
        return a;
    }
    var a = rev(this);
    var b = rev(s);
    var r = a.find(b);
    if (r == -1)
        return r;
    return len(this)-len(b)-r
};

str.prototype.join = function(s) {
    return str.__call__(js(s).join(js(this)));
};

str.prototype.replace = function(old, _new, count) {
    old = js(old);
    _new = js(_new);
    var old_s;
    var new_s;

    if (defined(count))
        count = js(count);
    else
        count = -1;
    old_s = "";
    new_s = this._obj;
    while ((count != 0) && (new_s != old_s)) {
        old_s = new_s;
        new_s = new_s.replace(old, _new);
        count -= 1;
    }
    return str.__call__(new_s);
};

str.prototype.lstrip = function(chars) {
    if (len(this) == 0)
        return this;
    if (defined(chars))
        chars = tuple.__call__(chars);
    else
        chars = tuple.__call__(["\n", "\t", " "]);
    var i = 0;
    while ((i < len(this)) && (chars.__contains__(this.__getitem__(i)))) {
        i += 1;
    }
    return this.__getitem__(slice.__call__(i, null));
};

str.prototype.rstrip = function(chars) {
    if (len(this) == 0)
        return this
    if (defined(chars))
        chars = tuple.__call__(chars);
    else
        chars = tuple.__call__(["\n", "\t", " "]);
    var i = len(this)-1;
    while ((i >= 0) && (chars.__contains__(this.__getitem__(i)))) {
        i -= 1;
    }
    return this.__getitem__(slice.__call__(i+1));
};

str.prototype.strip = function(chars) {
    return this.lstrip(chars).rstrip(chars);
};

str.prototype.split = function(sep) {
    if (defined(sep)) {
        var r = list.__call__(this._obj.split(sep));
        var r_new = list.__call__([]);
        iterate(iter.__call__(r), function(item) {
                r_new.append(str.__call__(item));
        });
        return r_new;
    }
    else {
        var r_new = list.__call__([]);
        iterate(iter.__call__(this.split(" ")), function(item) {
                if (len(item) > 0)
                    r_new.append(item);
        });
        return r_new;
    }
};

str.prototype.splitlines = function() {
    return this.split("\n");
};

str.prototype.lower = function() {
    return str.__call__(this._obj.toLowerCase());
};

str.prototype.upper = function() {
    return str.__call__(this._obj.toUpperCase());
};

<commit_msg> * Changed all methods of str to Function-style<commit_after>/* Python 'str' type */

var str = __inherit(object);

str.__name__ = 'str';
str.prototype.__class__ = str;
str.prototype.MARK = "str";

str.prototype.__init__ = function(s) {
    if (!defined(s)) {
        this._obj = '';
    } else {
        if (typeof(s) === "string") {
            this._obj = s;
        } else if (defined(s.toString)) {
            this._obj = s.toString();
        } else if (defined(s.__str__)) {
            this._obj = js(s.__str__());
        } else
            this._obj = js(s);
    }
};

str.prototype.__str__ = function () {
    return this;
};

str.prototype.__eq__ = function (other) {
    if (other.__class__ == this.__class__) {
        if (len(this) != len(other))
            return false;
        for (var i = 0; i < len(this); i++) {
            if (this._obj[i] != other._obj[i])
                return false;
        }
        return true;
    } else
        return false;
};

str.prototype.toString = function () {
    return js(this.__str__());
};

str.prototype._js_ = function () {
    return this._obj;
};

str.prototype.__hash__ = function () {
    var value = 0x345678;
    var length = this.__len__();

    for (var index in this._obj) {
        value = ((1000003*value) & 0xFFFFFFFF) ^ hash(this._obj[index]);
        value = value ^ length;
    }

    if (value == -1) {
        value = -2;
    }

    return value;
};

str.prototype.__len__ = function() {
    return this._obj.length;
};

str.prototype.__iter__ = function() {
    return iter.__call__(this._obj);
};

str.prototype.__bool__ = function() {
    return py_builtins.bool(this._obj);
};

str.prototype.__eq__ = function(s) {
    if (typeof(s) === "string")
        return this._obj == s;
    else if (isinstance.__call__(s, str))
        return this._obj == s._obj;
    else
        return false;
};

str.prototype.__contains__ = function(item) {
    for (var index in this._obj) {
        if (item == this._obj[index]) {
            return true;
        }
    }

    return false;
};

str.prototype.__getitem__ = function(index) {

    var seq;
    if (isinstance.__call__(index, slice)) {
        var s = index;
        var inds = s.indices(len(this));
        var start = inds.__getitem__(0);
        var stop = inds.__getitem__(1);
        var step = inds.__getitem__(2);
        seq = "";
        for (var i = start; i < stop; i += step) {
            seq = seq + js(this.__getitem__(i));
        }
        return this.__class__.__call__(seq);
    } else if ((index >= 0) && (index < len(this)))
        return this._obj[index];
    else if ((index < 0) && (index >= -len(this)))
        return this._obj[index+len(this)];
    else
        throw new py_builtins.IndexError("string index out of range");
};

str.prototype.__setitem__ = function(index, value) {
    throw new py_builtins.TypeError("'str' object doesn't support item assignment");
};

str.prototype.__delitem__ = function(index) {
    throw new py_builtins.TypeError("'str' object doesn't support item deletion");
};

str.prototype.count = Function(function(str, start, end) {
    if (!defined(start))
        start = 0;
    if (!defined(end))
        end = null;
    var count = 0;
    s = this.__getitem__(slice.__call__(start, end));
    idx = s.find(str);
    while (idx != -1) {
        count += 1;
        s = s.__getitem__(slice.__call__(idx+1, null));
        idx = s.find(str);
    }
    return count;
});

str.prototype.index = Function(function(value, start, end) {
    if (!defined(start)) {
        start = 0;
    }

    for (var i = start; !defined(end) || (start < end); i++) {
        var _value = this._obj[i];

        if (!defined(_value)) {
            break;
        }

        if (_value == value) {
            return i;
        }
    }

    throw new py_builtins.ValueError("substring not found");
});

str.prototype.find = Function(function(s) {
    return this._obj.search(s);
});

str.prototype.rfind = Function(function(s) {
    rev = function(s) {
        var a = list.__call__(str.__call__(s));
        a.reverse();
        a = str.__call__("").join(a);
        return a;
    }
    var a = rev(this);
    var b = rev(s);
    var r = a.find(b);
    if (r == -1)
        return r;
    return len(this)-len(b)-r
});

str.prototype.join = Function(function(s) {
    return str.__call__(js(s).join(js(this)));
});

str.prototype.replace = Function(function(old, _new, count) {
    old = js(old);
    _new = js(_new);
    var old_s;
    var new_s;

    if (defined(count))
        count = js(count);
    else
        count = -1;
    old_s = "";
    new_s = this._obj;
    while ((count != 0) && (new_s != old_s)) {
        old_s = new_s;
        new_s = new_s.replace(old, _new);
        count -= 1;
    }
    return str.__call__(new_s);
});

str.prototype.lstrip = Function(function(chars) {
    if (len(this) == 0)
        return this;
    if (defined(chars))
        chars = tuple.__call__(chars);
    else
        chars = tuple.__call__(["\n", "\t", " "]);
    var i = 0;
    while ((i < len(this)) && (chars.__contains__(this.__getitem__(i)))) {
        i += 1;
    }
    return this.__getitem__(slice.__call__(i, null));
});

str.prototype.rstrip = Function(function(chars) {
    if (len(this) == 0)
        return this
    if (defined(chars))
        chars = tuple.__call__(chars);
    else
        chars = tuple.__call__(["\n", "\t", " "]);
    var i = len(this)-1;
    while ((i >= 0) && (chars.__contains__(this.__getitem__(i)))) {
        i -= 1;
    }
    return this.__getitem__(slice.__call__(i+1));
});

str.prototype.strip = Function(function(chars) {
    return this.lstrip(chars).rstrip(chars);
});

str.prototype.split = Function(function(sep) {
    if (defined(sep)) {
        var r = list.__call__(this._obj.split(sep));
        var r_new = list.__call__([]);
        iterate(iter.__call__(r), function(item) {
                r_new.append(str.__call__(item));
        });
        return r_new;
    }
    else {
        var r_new = list.__call__([]);
        iterate(iter.__call__(this.split(" ")), function(item) {
                if (len(item) > 0)
                    r_new.append(item);
        });
        return r_new;
    }
});

str.prototype.splitlines = Function(function() {
    return this.split("\n");
});

str.prototype.lower = Function(function() {
    return str.__call__(this._obj.toLowerCase());
});

str.prototype.upper = Function(function() {
    return str.__call__(this._obj.toUpperCase());
});

<|endoftext|>


<commit_before>
const dependencyPlatforms = {
    "@cdm-logger/server": 'server',
    "@sample-stack/utils": 'server',
    "@sample-stack/core": "*",
    "@sample-stack/client-core": "*",
    "@sample-stack/client-react": "*",
    "@sample-stack/client-redux": "*",
    "@sample-stack/graphql-gql": "*",
    "@sample-stack/utils": "*",
    "@sample-stack/counter": "*",
    "bunyan": 'server',
    "export-dir": 'server',
    "express": 'server',
    'body-parser': 'server',
    express: 'server',
    'apollo-server-express': 'server',
    'graphql-subscriptions': 'server',
    'graphql-tools': 'server',
    "graphql-tag": ['server', 'web'],
    'immutability-helper': ['ios', 'android', 'web'],
    'isomorphic-fetch': 'server',
    knex: 'server',
    mysql2: 'server',
    persistgraphql: ['server', 'web'],
    "graphql-nats-subscriptions": 'server',
    "graphql-server-core": 'server',
    "apollo-server-express": 'server',
    "graphql-tools": 'server',
    "helmet": 'server',
    "hemera-joi": 'server',
    "hemera-plugin": 'server',
    "inversify": 'server',
    "morgan": 'server',
    "nats": 'server',
    "nats-hemera":'server',
    "nconf": 'server',
    "node-pre-gyp": 'server',
    "prop-types": 'web',
    "ramda": ['web', 'server'],
    "reflect-metadata": 'server',
    "sequelize": 'server',
    'react-native': ['ios', 'android'],
    'react-navigation': ['ios', 'android'],
    'serialize-javascript': 'server',
    'source-map-support': 'server',
    sqlite3: 'server',
    'styled-components': ['server', 'web'],
    'subscriptions-transport-ws': ['ios', 'android', 'web'],
    'ws': ['server']
};

module.exports = { dependencyPlatforms };<commit_msg>update no ddl<commit_after>
const dependencyPlatforms = {
    "@cdm-logger/server": 'server',
    "@sample-stack/utils": 'server',
    "@sample-stack/core": "noddl",
    "@sample-stack/client-core": "noddl",
    "@sample-stack/client-react": "noddl",
    "@sample-stack/client-redux": "noddl",
    "@sample-stack/graphql-gql": "noddl",
    "@sample-stack/utils": "noddl",
    "@sample-stack/counter": "noddl",
    "bunyan": 'server',
    "export-dir": 'server',
    "express": 'server',
    'body-parser': 'server',
    express: 'server',
    'apollo-server-express': 'server',
    'graphql-subscriptions': 'server',
    'graphql-tools': 'server',
    "graphql-tag": ['server', 'web'],
    'immutability-helper': ['ios', 'android', 'web'],
    'isomorphic-fetch': 'server',
    knex: 'server',
    mysql2: 'server',
    persistgraphql: ['server', 'web'],
    "graphql-nats-subscriptions": 'server',
    "graphql-server-core": 'server',
    "apollo-server-express": 'server',
    "graphql-tools": 'server',
    "helmet": 'server',
    "hemera-joi": 'server',
    "hemera-plugin": 'server',
    "inversify": 'server',
    "morgan": 'server',
    "nats": 'server',
    "nats-hemera":'server',
    "nconf": 'server',
    "node-pre-gyp": 'server',
    "prop-types": 'web',
    "ramda": ['web', 'server'],
    "reflect-metadata": 'server',
    "sequelize": 'server',
    'react-native': ['ios', 'android'],
    'react-navigation': ['ios', 'android'],
    'serialize-javascript': 'server',
    'source-map-support': 'server',
    sqlite3: 'server',
    'styled-components': ['server', 'web'],
    'subscriptions-transport-ws': ['ios', 'android', 'web'],
    'ws': ['server']
};

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


<commit_before>console.log('Starting SGActions: rich ActionMenuItems')

var original = window.SG.Menu.prototype.render_menu_items;

window.Ext.override(window.SG.Menu, {
    render_menu_items: function() {

        try {

            // Parse and set the data.
            for (var i = 0; i < this.items.length; i++) {

                var item = this.items[i];

                // The undefined check is our tenuous hold on folders
                // that are created for ActionMenuItems.
                if (item.url || (item.order !== undefined && item.disabled === undefined)) {

                    if (/^sgaction/.test(item.url || '')) {

                        // Parse the rich data.
                        var rich = {};
                        var m = /^(.+?)\/(.+?)$/.exec(item.url);
                        if (m) {
                            item.url = m[1]
                            var pairs = m[2].split('&');
                            for (var j = 0; j < pairs.length; j++) {
                                var pair = pairs[j].split('=');
                                rich[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
                            }
                        }

                        item.html = rich.t || item.html;
                        item.icon_name = 'silk-icon silk-icon-' + (rich.i || 'brick');
                        item.heading = rich.h;

                    }

                    // New method: Rich data in the title itself, e.g.:
                    // "Heading / Title [icon]"
                    var m = /^\s*(.+?)\s+\/\s+(.+?)\s*$/.exec(item.html || '');
                    if (m) {
                        item.heading = m[1];
                        item.html = m[2];
                    }

                    // Icon in square-brackets at end.
                    m = /^(.+?)\s*\[(.+?)\]$/.exec(item.html || '');
                    if (m) {
                        item.html = m[1];
                        item.icon_name = 'silk-icon silk-icon-' + m[2];
                    }
                }

            }

            // Collapse headings and lines.
            var last_heading = null;
            for (var i = 0; i < this.items.length; i++) {

                // Headings.
                if (this.items[i].heading == last_heading) {
                    this.items[i].heading = null
                } else {
                    last_heading = this.items[i].heading;
                }

                // Double lines before headline changes.
                if (i && this.items[i].heading && this.items[i-1].line && !this.items[i-1].html) {
                    this.items[i-1].line = false;
                }
            }

        } catch (err) {
            console.log(err);
        }

        // this.items.push({html: "Submenu test", submenu:{items:[{html: 'Child'}]}});

        return original.apply(this, arguments);
    }
});

<commit_msg>Gracefully handle if there are multiple Chrome extensions added<commit_after>if (window._sgactions_loaded != undefined) {
    console.log('SGActions already loaded; are there more than one?')

} else if (window.SG == undefined) {
    console.log('SGActions loaded before Shotgun; this is OK on the login page.');

} else {

    window._sgactions_loaded = true;
    console.log('Starting SGActions: rich ActionMenuItems')

    var original = window.SG.Menu.prototype.render_menu_items;

    window.Ext.override(window.SG.Menu, {
        render_menu_items: function() {

            try {

                // Parse and set the data.
                for (var i = 0; i < this.items.length; i++) {

                    var item = this.items[i];

                    // The undefined check is our tenuous hold on folders
                    // that are created for ActionMenuItems.
                    if (item.url || (item.order !== undefined && item.disabled === undefined)) {

                        if (/^sgaction/.test(item.url || '')) {

                            // Parse the rich data.
                            var rich = {};
                            var m = /^(.+?)\/(.+?)$/.exec(item.url);
                            if (m) {
                                item.url = m[1]
                                var pairs = m[2].split('&');
                                for (var j = 0; j < pairs.length; j++) {
                                    var pair = pairs[j].split('=');
                                    rich[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
                                }
                            }

                            item.html = rich.t || item.html;
                            item.icon_name = 'silk-icon silk-icon-' + (rich.i || 'brick');
                            item.heading = rich.h;

                        }

                        // New method: Rich data in the title itself, e.g.:
                        // "Heading / Title [icon]"
                        var m = /^\s*(.+?)\s+\/\s+(.+?)\s*$/.exec(item.html || '');
                        if (m) {
                            item.heading = m[1];
                            item.html = m[2];
                        }

                        // Icon in square-brackets at end.
                        m = /^(.+?)\s*\[(.+?)\]$/.exec(item.html || '');
                        if (m) {
                            item.html = m[1];
                            item.icon_name = 'silk-icon silk-icon-' + m[2];
                        }
                    }

                }

                // Collapse headings and lines.
                var last_heading = null;
                for (var i = 0; i < this.items.length; i++) {

                    // Headings.
                    if (this.items[i].heading == last_heading) {
                        this.items[i].heading = null
                    } else {
                        last_heading = this.items[i].heading;
                    }

                    // Double lines before headline changes.
                    if (i && this.items[i].heading && this.items[i-1].line && !this.items[i-1].html) {
                        this.items[i-1].line = false;
                    }
                }

            } catch (err) {
                console.log(err);
            }

            // this.items.push({html: "Submenu test", submenu:{items:[{html: 'Child'}]}});

            return original.apply(this, arguments);
        }
    });

} // load check

<|endoftext|>


<commit_before>/*global define, window*/
define(['jquery'], function ($) {
    "use strict";
    var Tracking, ga;

    Tracking = function ($context) {
        this.$context = $context;
        this.trackCollapse();
        this.trackControls();
        this.trackSideNavigation();
        this.trackCenterNavigation();
    };

    Tracking.prototype.trackCollapse = function () {
        return $('[data-toggle="collapse"]', this.$context).on('click', function () {
            ga('send', 'event', 'button', 'click', 'Collapsed an item');
        });
    };

    Tracking.prototype.trackControls = function () {
        return $('[data-toggle="edit-controls"]', this.$context).on('click', function () {
            ga('send', 'event', 'button', 'click', 'Clicked on edit controls');
        });
    };

    Tracking.prototype.trackSideNavigation = function () {
        return $('#main-nav a', this.$context).on('click', function () {
            ga('send', 'event', 'button', 'click', 'Clicked left drop down');
        });
    };

    Tracking.prototype.trackCenterNavigation = function () {
        return $('.subject-dropdown-toggle', this.$context).on('click', function () {
            ga('send', 'event', 'button', 'click', 'Clicked center drop down');
        });
    };

    return function ($context) {
        ga = window[window['GoogleAnalyticsObject'] || 'ga'];
        if (ga) {
            ga('provide', 'advancedTracking', Tracking);
        }
        return new Tracking($context);
    };
});<commit_msg>Fixed tracking.js<commit_after>/*global define, window*/
define(['jquery'], function ($) {
    "use strict";
    var Tracking, ga;

    Tracking = function ($context) {
        this.$context = $context;
        if (ga === undefined) {
            return;
        }

        this.trackCollapse();
        this.trackControls();
        this.trackSideNavigation();
        this.trackCenterNavigation();
    };

    Tracking.prototype.trackCollapse = function () {
        return $('[data-toggle="collapse"]', this.$context).on('click', function () {
            ga('send', 'event', 'button', 'click', 'Collapsed an item');
        });
    };

    Tracking.prototype.trackControls = function () {
        return $('[data-toggle="edit-controls"]', this.$context).on('click', function () {
            ga('send', 'event', 'button', 'click', 'Clicked on edit controls');
        });
    };

    Tracking.prototype.trackSideNavigation = function () {
        return $('#main-nav a', this.$context).on('click', function () {
            ga('send', 'event', 'button', 'click', 'Clicked left drop down');
        });
    };

    Tracking.prototype.trackCenterNavigation = function () {
        return $('.subject-dropdown-toggle', this.$context).on('click', function () {
            ga('send', 'event', 'button', 'click', 'Clicked center drop down');
        });
    };

    return function ($context) {
        ga = window[window['GoogleAnalyticsObject'] || 'ga'];
        if (ga !== undefined) {
            ga('provide', 'advancedTracking', Tracking);
        }
        return new Tracking($context);
    };
});<|endoftext|>


<commit_before>$(function() {
    if (!$('.playbackrate').length) {
        // if the dom node isn't there don't bother with any of this
        return;
    }
    function highlightCurrentPlaybackrate() {
        var current = document.querySelector('video').playbackRate;
        $('.playbackrate .options a').each(function() {
            if ($(this).data('rate') === current) {
                $(this).addClass('current');

            } else {
                $(this).removeClass('current');
            }
        });
        $('.playbackrate a.open')
        .attr('title', 'Current playback rate: ' + current + '×');
        if (current === 1) {
            $('.playbackrate a.open').addClass('inactive');
        } else {
            $('.playbackrate a.open').removeClass('inactive');
        }
    }

    // expand the options into the page
    var options = $('.playbackrate .options');
    $.each(options.data('options'), function() {
        $('<a>')
            .data('rate', this[0])
            .attr('title', this[1])
            .html(this[0] + '&times')
            .appendTo(options);
    });

    $('.playbackrate').on('click', 'a.open', function(event) {
        event.preventDefault();
        $('.playbackrate .options').toggle();
        highlightCurrentPlaybackrate();
    });

    $('.playbackrate .options').on('click', 'a', function(event) {
        event.preventDefault();
        document.querySelector('video').playbackRate = $(this).data('rate');
        highlightCurrentPlaybackrate();
    });

    // It doesn't really matter which of tearout.js or this file that does
    // this as long as one of them do.
    setTimeout(function() {
        $('.play-options:hidden').fadeIn(400);
    }, 1000);
});
<commit_msg>bug 1246292 - update playbackrate by event<commit_after>$(function() {
    if (!$('.playbackrate').length) {
        // if the dom node isn't there don't bother with any of this
        return;
    }
    function highlightCurrentPlaybackrate(current) {
        // var current = document.querySelector('video').playbackRate;
        $('.playbackrate .options a').each(function() {
            if ($(this).data('rate') === current) {
                $(this).addClass('current');

            } else {
                $(this).removeClass('current');
            }
        });
        $('.playbackrate a.open')
        .attr('title', 'Current playback rate: ' + current + '×');
        if (current === 1) {
            $('.playbackrate a.open').addClass('inactive');
        } else {
            $('.playbackrate a.open').removeClass('inactive');
        }
    }

    var _setup = false;
    var setupRatechangeEvent = function() {
        if (_setup) return;
        var videoElement = document.querySelector('video');
        if (videoElement) {
            videoElement.addEventListener('ratechange', function(event) {
                console.log('Rate changed', event.target.playbackRate);
                highlightCurrentPlaybackrate(event.target.playbackRate);
            });
            _setup = true;
        }
    };

    // expand the options into the page
    var options = $('.playbackrate .options');
    $.each(options.data('options'), function() {
        $('<a>')
            .data('rate', this[0])
            .attr('title', this[1])
            .html(this[0] + '&times')
            .appendTo(options);
    });

    $('.playbackrate').on('click', 'a.open', function(event) {
        event.preventDefault();
        setupRatechangeEvent();  // can be called repeatedly
        $('.playbackrate .options').toggle();
    });

    $('.playbackrate .options').on('click', 'a', function(event) {
        event.preventDefault();
        document.querySelector('video').playbackRate = $(this).data('rate');
    });

    // It doesn't really matter which of tearout.js or this file that does
    // this as long as one of them do.
    setTimeout(function() {
        $('.play-options:hidden').fadeIn(400);
    }, 1000);
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import joint from 'npm:jointjs';
import { UseCase } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-use-case';
import { UsecaseActor } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-usecase-actor';
import { Association } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-association';
import { DirectedAssociation } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-usecase-directed-association';
import { UseCaseGeneralization } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-usecase-generalization';
import { Partition } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-partition';

export default Ember.Controller.extend({
  actions: {
    printDiagram: function() {
      let _this = this;
      _this.graph = new joint.dia.Graph();

      let paper = document.getElementById('paper');
      let minX = 16384;
      let minY = 16384;
      let maxX = 0;
      let maxY = 0;
      let sidebar = Ember.$('.ui.sidebar.main.menu');
      let sidebarWidth = sidebar.hasClass('visible') ? sidebar.width() : 0;

      if (minX > maxX) {
        maxX = paper && ('offsetWidth' in paper) ? paper.offsetWidth : 1024;
        maxX += sidebarWidth;
        maxY = 840;
      } else {
        maxX = minX + maxX + sidebarWidth;
        maxY = minY + maxY;
      }

      _this.paper = new joint.dia.Paper({
        el: paper,
        width: maxX,
        height: maxY,
        gridSize: 1,
        model: _this.graph,
      });

      let jUseCase = new UseCase({
        position: { x: 50, y: 10 },
        size: { width: 100, height: 40 },
        name: 'UseCase \n primitive \n 1',
        ports: {
          groups: {
            'in': {
              position: 'absolute'
            },
            'out': {
              position: 'absolute'
            }
          }
        }
      });
      _this.graph.addCell(jUseCase);

      let jUseCaseBoundary = new Partition({
        position: { x: 50, y: 150 },
        size: { width: 70, height: 50 },
        name: 'Boundary \n Very long string uuuuuuuuuuuuuuuuuuuuu \n the end',
        ports: {
          groups: {
            'in': {
              position: 'absolute'
            },
            'out': {
              position: 'absolute'
            }
          }
        }
      });
      _this.graph.addCell(jUseCaseBoundary);

      let jUseCaseActor = new UsecaseActor({
        position: { x: 250, y: 50 },
        name: 'Actor',
        ports: {
          groups: {
            'in': {
              position: 'absolute'
            },
            'out': {
              position: 'absolute'
            }
          }
        }
      });
      _this.graph.addCell(jUseCaseActor);

      let jUseCaseUndirAssociation = new Association({
        source: { x:500, y:80 },
        target: { x:700, y:80 },
        labels: [{ attrs: { text: { text:  'Undir association' } } }]
      });
      _this.graph.addCell(jUseCaseUndirAssociation);

      let jUseCaseDirAssociation = new DirectedAssociation({
        source: { x:500, y:150 },
        target: { x:700, y:150 },
        labels: [{ attrs: { text: { text:  'Directed association' } } }]
      });
      _this.graph.addCell(jUseCaseDirAssociation);

      let jUseCaseGeneralization = new UseCaseGeneralization({
        source: { x:500, y:200 },
        target: { x:700, y:200 },
        labels: [{ attrs: { text: { text:  'Generalization' } } }]
      });
      _this.graph.addCell(jUseCaseGeneralization);
    }
  }
});
<commit_msg>Fix jscs<commit_after>import Ember from 'ember';
import joint from 'npm:jointjs';
import { UseCase } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-use-case';
import { UsecaseActor } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-usecase-actor';
import { Association } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-association';
import { DirectedAssociation } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-usecase-directed-association';
import { UseCaseGeneralization } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-usecase-generalization';
import { Partition } from 'ember-flexberry-designer/objects/uml-primitives/fd-uml-partition';

export default Ember.Controller.extend({
  actions: {
    printDiagram: function() {
      let _this = this;
      _this.graph = new joint.dia.Graph();

      let paper = document.getElementById('paper');
      let minX = 16384;
      let minY = 16384;
      let maxX = 0;
      let maxY = 0;
      let sidebar = Ember.$('.ui.sidebar.main.menu');
      let sidebarWidth = sidebar.hasClass('visible') ? sidebar.width() : 0;

      if (minX > maxX) {
        maxX = paper && ('offsetWidth' in paper) ? paper.offsetWidth : 1024;
        maxX += sidebarWidth;
        maxY = 840;
      } else {
        maxX = minX + maxX + sidebarWidth;
        maxY = minY + maxY;
      }

      _this.paper = new joint.dia.Paper({
        el: paper,
        width: maxX,
        height: maxY,
        gridSize: 1,
        model: _this.graph,
      });

      let jUseCase = new UseCase({
        position: { x: 50, y: 10 },
        size: { width: 100, height: 40 },
        name: 'UseCase \n primitive \n 1',
        ports: {
          groups: {
            'in': {
              position: 'absolute'
            },
            'out': {
              position: 'absolute'
            }
          }
        }
      });
      _this.graph.addCell(jUseCase);

      let jUseCaseBoundary = new Partition({
        position: { x: 50, y: 150 },
        size: { width: 70, height: 50 },
        name: 'Boundary \n Very long string uuuuuuuuuuuuuuuuuuuuu \n the end',
        ports: {
          groups: {
            'in': {
              position: 'absolute'
            },
            'out': {
              position: 'absolute'
            }
          }
        }
      });
      _this.graph.addCell(jUseCaseBoundary);

      let jUseCaseActor = new UsecaseActor({
        position: { x: 250, y: 50 },
        name: 'Actor',
        ports: {
          groups: {
            'in': {
              position: 'absolute'
            },
            'out': {
              position: 'absolute'
            }
          }
        }
      });
      _this.graph.addCell(jUseCaseActor);

      let jUseCaseUndirAssociation = new Association({
        source: { x:500, y:80 },
        target: { x:700, y:80 },
        labels: [{ attrs: { text: { text:  'Undir association' } } }]
      });
      _this.graph.addCell(jUseCaseUndirAssociation);

      let jUseCaseDirAssociation = new DirectedAssociation({
        source: { x:500, y:150 },
        target: { x:700, y:150 },
        labels: [{ attrs: { text: { text:  'Directed association' } } }]
      });
      _this.graph.addCell(jUseCaseDirAssociation);

      let jUseCaseGeneralization = new UseCaseGeneralization({
        source: { x:500, y:200 },
        target: { x:700, y:200 },
        labels: [{ attrs: { text: { text:  'Generalization' } } }]
      });
      _this.graph.addCell(jUseCaseGeneralization);
    }
  }
});
<|endoftext|>


<commit_before>/**
 * Analytics write scope requests tests.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import {
	activatePlugin,
	createURL,
	visitAdminPage,
} from '@wordpress/e2e-test-utils';

/**
 * Internal dependencies
 */
import {
	deactivateUtilityPlugins,
	resetSiteKit,
	useRequestInterception,
	setupSiteKit,
} from '../../../utils';

describe( 'Analytics write scope requests', () => {
	let scope;
	// These variables are used to determine whether or not we need to intercept requests to the server. By default the first request
	// won't be intercepted to reach the server and to trigger the insufficient scopes error on the server. The following requests will
	// be intercepted and mocked to immediately return fake data to emulate property/profile creation.
	let interceptCreatePropertyRequest;
	let interceptCreateProfileRequest;

	// Custom helper to click the "Configure Analytics" button.
	// For some reason, using normal methods of clicking are less reliable in this test.
	// See https://github.com/puppeteer/puppeteer/issues/1805
	const submitForm = () =>
		page.$eval( '.googlesitekit-setup-module__action button', ( el ) =>
			el.click()
		);

	beforeAll( async () => {
		await page.setRequestInterception( true );
		useRequestInterception( ( request ) => {
			if (
				request
					.url()
					.startsWith(
						'https://sitekit.withgoogle.com/o/oauth2/auth'
					)
			) {
				request.respond( {
					status: 302,
					headers: {
						location: createURL(
							'/wp-admin/index.php',
							`oauth2callback=1&code=valid-test-code&scope=${ scope }`
						),
					},
				} );
			} else if (
				request.url().match( 'analytics/data/create-account-ticket' )
			) {
				request.respond( {
					status: 200,
					body: JSON.stringify( {
						id: `${ Math.ceil( 1000 * Math.random() ) }`,
					} ),
				} );
			} else if (
				request.url().match( 'analytics/data/create-property' )
			) {
				if ( interceptCreatePropertyRequest ) {
					request.respond( {
						status: 200,
						body: JSON.stringify( {
							accountId: '100', // eslint-disable-line sitekit/acronym-case
							id: 'UA-100-1',
							internalWebPropertyId: '200', // eslint-disable-line sitekit/acronym-case
							kind: 'analytics#webproperty',
							level: 'STANDARD',
							name: 'Test Property X',
							websiteUrl: '/wp-admin/', // eslint-disable-line sitekit/acronym-case
							permissions: {
								effective: [ 'READ_AND_ANALYZE' ],
							},
						} ),
					} );
				} else {
					request.continue();
					interceptCreatePropertyRequest = true;
				}
			} else if (
				request.url().match( 'analytics/data/create-profile' )
			) {
				if ( interceptCreateProfileRequest ) {
					request.respond( {
						status: 200,
						body: JSON.stringify( {
							id: '300',
							accountId: '100', // eslint-disable-line sitekit/acronym-case
							webPropertyId: 'UA-100-1', // eslint-disable-line sitekit/acronym-case
							internalWebPropertyId: '200', // eslint-disable-line sitekit/acronym-case
							kind: 'analytics#profile',
							level: 'STANDARD',
							name: 'Test Profile X',
							type: 'WEB',
							websiteUrl: '/wp-admin/', // eslint-disable-line sitekit/acronym-case
							permissions: {
								effective: [ 'READ_AND_ANALYZE' ],
							},
						} ),
					} );
				} else {
					request.continue();
					interceptCreateProfileRequest = true;
				}
			} else if (
				request.url().match( 'analytics-4/data/account-summaries' )
			) {
				request.respond( {
					status: 200,
					body: JSON.stringify( {} ),
				} );
			} else if (
				request.url().match( '/wp-json/google-site-kit/v1/data/' )
			) {
				request.respond( { status: 200 } );
			} else if (
				request.url().match( `//analytics.google.com/analytics/web/` )
			) {
				request.respond( { status: 200 } );
			} else {
				request.continue();
			}
		} );
	} );

	beforeEach( async () => {
		scope = 'https://www.googleapis.com/auth/analytics.provision';
		interceptCreatePropertyRequest = false;
		interceptCreateProfileRequest = false;

		await activatePlugin( 'e2e-tests-oauth-callback-plugin' );
		await setupSiteKit();
	} );

	afterEach( async () => {
		await deactivateUtilityPlugins();
		await resetSiteKit();
	} );

	it( 'prompts for additional permissions during a new Analytics account creation if the user has not granted the Analytics provisioning scope', async () => {
		await activatePlugin(
			'e2e-tests-module-setup-analytics-api-mock-no-account'
		);

		// Go to the analytics setup page.
		await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
		await page.waitForSelector( '.mdc-tab-bar' );
		await expect( page ).toClick( '.mdc-tab', {
			text: /connect more services/i,
		} );
		await page.waitForSelector(
			'.googlesitekit-settings-connect-module--analytics'
		);
		await expect( page ).toClick( '.googlesitekit-cta-link', {
			text: /set up analytics/i,
		} );
		await page.waitForSelector( '.googlesitekit-setup-module--analytics' );
		await page.waitForSelector( '.googlesitekit-setup-module__inputs' );

		// The user sees a notice above the button that explains they will need to grant additional permissions.
		await expect( page ).toMatchElement( 'p', {
			text: /You will need to give Site Kit permission to create an Analytics account/i,
		} );

		// Upon clicking the button, they're redirected to OAuth (should be mocked).
		await Promise.all( [
			page.waitForNavigation(), // User is sent directly to OAuth.
			expect( page ).toClick( '.mdc-button', {
				text: /create account/i,
			} ),
		] );

		// When returning, their original action is automatically invoked, without requiring them to click the button again.
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics/data/create-account-ticket' )
		);

		// They should be redirected to the Analytics TOS.
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics.google.com/analytics/web' )
		);
	} );

	it( 'prompts for additional permissions during a new Analytics property creation if the user has not granted the Analytics edit scope', async () => {
		scope = 'https://www.googleapis.com/auth/analytics.edit';
		interceptCreateProfileRequest = true;

		await activatePlugin( 'e2e-tests-module-setup-analytics-api-mock' );

		// Go to the analytics setup page.
		await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
		await page.waitForSelector( '.mdc-tab-bar' );
		await expect( page ).toClick( '.mdc-tab', {
			text: /connect more services/i,
		} );
		await page.waitForSelector(
			'.googlesitekit-settings-connect-module--analytics'
		);
		await expect( page ).toClick( '.googlesitekit-cta-link', {
			text: /set up analytics/i,
		} );
		await page.waitForSelector( '.googlesitekit-setup-module--analytics' );
		await page.waitForSelector( '.googlesitekit-setup-module__inputs' );

		// Select "Test Account A" account.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-account'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /test account a/i,
		} );

		// Select "Set up a new property" option.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-property'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /set up a new property/i,
		} );

		// Click on confirm changes button and wait for permissions modal dialog.
		await submitForm();
		await page.waitForSelector( '.mdc-dialog--open', { timeout: 3000 } );

		// Click on proceed button and wait for oauth request.
		await Promise.all( [
			expect( page ).toClick( '.mdc-dialog--open .mdc-button', {
				text: /proceed/i,
			} ),
			page.waitForRequest( ( req ) =>
				req.url().match( 'sitekit.withgoogle.com/o/oauth2/auth' )
			),
		] );

		// When returning, their original action is automatically invoked, without requiring them to click the button again.
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics/data/create-property' )
		);
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics/data/create-profile' )
		);

		// They should end up on the dashboard.
		await Promise.all( [
			page.waitForNavigation(),
			page.waitForSelector( '.googlesitekit-publisher-win__title' ),
		] );
		await expect( page ).toMatchElement(
			'.googlesitekit-publisher-win__title',
			{
				text: /Congrats on completing the setup for Analytics!/i,
			}
		);
		expect( console ).toHaveErrored(); // Permission scope error.
	} );

	it( 'prompts for additional permissions during a new Analytics profile creation if the user has not granted the Analytics edit scope', async () => {
		scope = 'https://www.googleapis.com/auth/analytics.edit';

		await activatePlugin( 'e2e-tests-module-setup-analytics-api-mock' );

		// Go to the analytics setup page.
		await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
		await page.waitForSelector( '.mdc-tab-bar' );
		await expect( page ).toClick( '.mdc-tab', {
			text: /connect more services/i,
		} );
		await page.waitForSelector(
			'.googlesitekit-settings-connect-module--analytics'
		);
		await expect( page ).toClick( '.googlesitekit-cta-link', {
			text: /set up analytics/i,
		} );
		await page.waitForSelector( '.googlesitekit-setup-module--analytics' );
		await page.waitForSelector( '.googlesitekit-setup-module__inputs' );

		// Select "Test Account A" account.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-account'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /test account a/i,
		} );

		// Select "Test Property X" property.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-property'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /test property x/i,
		} );

		// Select "Set up a new view" option.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-profile'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /set up a new view/i,
		} );

		// Click on confirm changes button and wait for permissions modal dialog.
		await submitForm();
		await page.waitForSelector( '.mdc-dialog--open', { timeout: 3000 } );

		// Click on proceed button and wait for oauth request.
		await Promise.all( [
			expect( page ).toClick( '.mdc-dialog--open .mdc-button', {
				text: /proceed/i,
			} ),
			page.waitForRequest( ( req ) =>
				req.url().match( 'sitekit.withgoogle.com/o/oauth2/auth' )
			),
		] );

		// When returning, their original action is automatically invoked, without requiring them to click the button again.
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics/data/create-profile' )
		);

		// They should end up on the dashboard.
		await Promise.all( [
			page.waitForNavigation(),
			page.waitForSelector( '.googlesitekit-publisher-win__title' ),
		] );
		await expect( page ).toMatchElement(
			'.googlesitekit-publisher-win__title',
			{
				text: /Congrats on completing the setup for Analytics!/i,
			}
		);
		expect( console ).toHaveErrored(); // Permission scope error.
	} );
} );
<commit_msg>Use correct fixture (still fails).<commit_after>/**
 * Analytics write scope requests tests.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import {
	activatePlugin,
	createURL,
	visitAdminPage,
} from '@wordpress/e2e-test-utils';

/**
 * Internal dependencies
 */
import {
	deactivateUtilityPlugins,
	resetSiteKit,
	useRequestInterception,
	setupSiteKit,
} from '../../../utils';
import * as fixtures from '../../../../../assets/js/modules/analytics/datastore/__fixtures__';

describe( 'Analytics write scope requests', () => {
	let scope;
	// These variables are used to determine whether or not we need to intercept requests to the server. By default the first request
	// won't be intercepted to reach the server and to trigger the insufficient scopes error on the server. The following requests will
	// be intercepted and mocked to immediately return fake data to emulate property/profile creation.
	let interceptCreatePropertyRequest;
	let interceptCreateProfileRequest;

	// Custom helper to click the "Configure Analytics" button.
	// For some reason, using normal methods of clicking are less reliable in this test.
	// See https://github.com/puppeteer/puppeteer/issues/1805
	const submitForm = () =>
		page.$eval( '.googlesitekit-setup-module__action button', ( el ) =>
			el.click()
		);

	beforeAll( async () => {
		await page.setRequestInterception( true );
		useRequestInterception( ( request ) => {
			if (
				request
					.url()
					.startsWith(
						'https://sitekit.withgoogle.com/o/oauth2/auth'
					)
			) {
				request.respond( {
					status: 302,
					headers: {
						location: createURL(
							'/wp-admin/index.php',
							`oauth2callback=1&code=valid-test-code&scope=${ scope }`
						),
					},
				} );
			} else if (
				request.url().match( 'analytics/data/create-account-ticket' )
			) {
				request.respond( {
					status: 200,
					body: JSON.stringify( {
						id: `${ Math.ceil( 1000 * Math.random() ) }`,
					} ),
				} );
			} else if (
				request.url().match( 'analytics/data/create-property' )
			) {
				if ( interceptCreatePropertyRequest ) {
					request.respond( {
						status: 200,
						body: JSON.stringify( {
							accountId: '100', // eslint-disable-line sitekit/acronym-case
							id: 'UA-100-1',
							internalWebPropertyId: '200', // eslint-disable-line sitekit/acronym-case
							kind: 'analytics#webproperty',
							level: 'STANDARD',
							name: 'Test Property X',
							websiteUrl: '/wp-admin/', // eslint-disable-line sitekit/acronym-case
							permissions: {
								effective: [ 'READ_AND_ANALYZE' ],
							},
						} ),
					} );
				} else {
					request.continue();
					interceptCreatePropertyRequest = true;
				}
			} else if (
				request.url().match( 'analytics/data/create-profile' )
			) {
				if ( interceptCreateProfileRequest ) {
					request.respond( {
						status: 200,
						body: JSON.stringify( {
							id: '300',
							accountId: '100', // eslint-disable-line sitekit/acronym-case
							webPropertyId: 'UA-100-1', // eslint-disable-line sitekit/acronym-case
							internalWebPropertyId: '200', // eslint-disable-line sitekit/acronym-case
							kind: 'analytics#profile',
							level: 'STANDARD',
							name: 'Test Profile X',
							type: 'WEB',
							websiteUrl: '/wp-admin/', // eslint-disable-line sitekit/acronym-case
							permissions: {
								effective: [ 'READ_AND_ANALYZE' ],
							},
						} ),
					} );
				} else {
					request.continue();
					interceptCreateProfileRequest = true;
				}
			} else if (
				request.url().match( 'analytics-4/data/account-summaries' )
			) {
				request.respond( {
					status: 200,
					body: JSON.stringify( {} ),
				} );
			} else if (
				request.url().match( '/wp-json/google-site-kit/v1/data/' )
			) {
				request.respond( { status: 200 } );
			} else if (
				request.url().match( 'analytics-4/data/create-property' )
			) {
				request.respond( {
					body: fixtures.createProperty,
					status: 200,
				} );
			} else if (
				request.url().match( `//analytics.google.com/analytics/web/` )
			) {
				request.respond( { status: 200 } );
			} else {
				request.continue();
			}
		} );
	} );

	beforeEach( async () => {
		scope = 'https://www.googleapis.com/auth/analytics.provision';
		interceptCreatePropertyRequest = false;
		interceptCreateProfileRequest = false;

		await activatePlugin( 'e2e-tests-oauth-callback-plugin' );
		await setupSiteKit();
	} );

	afterEach( async () => {
		await deactivateUtilityPlugins();
		await resetSiteKit();
	} );

	it( 'prompts for additional permissions during a new Analytics account creation if the user has not granted the Analytics provisioning scope', async () => {
		await activatePlugin(
			'e2e-tests-module-setup-analytics-api-mock-no-account'
		);

		// Go to the analytics setup page.
		await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
		await page.waitForSelector( '.mdc-tab-bar' );
		await expect( page ).toClick( '.mdc-tab', {
			text: /connect more services/i,
		} );
		await page.waitForSelector(
			'.googlesitekit-settings-connect-module--analytics'
		);
		await expect( page ).toClick( '.googlesitekit-cta-link', {
			text: /set up analytics/i,
		} );
		await page.waitForSelector( '.googlesitekit-setup-module--analytics' );
		await page.waitForSelector( '.googlesitekit-setup-module__inputs' );

		// The user sees a notice above the button that explains they will need to grant additional permissions.
		await expect( page ).toMatchElement( 'p', {
			text: /You will need to give Site Kit permission to create an Analytics account/i,
		} );

		// Upon clicking the button, they're redirected to OAuth (should be mocked).
		await Promise.all( [
			page.waitForNavigation(), // User is sent directly to OAuth.
			expect( page ).toClick( '.mdc-button', {
				text: /create account/i,
			} ),
		] );

		// When returning, their original action is automatically invoked, without requiring them to click the button again.
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics/data/create-account-ticket' )
		);

		// They should be redirected to the Analytics TOS.
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics.google.com/analytics/web' )
		);
	} );

	it( 'prompts for additional permissions during a new Analytics property creation if the user has not granted the Analytics edit scope', async () => {
		scope = 'https://www.googleapis.com/auth/analytics.edit';
		interceptCreateProfileRequest = true;

		await activatePlugin( 'e2e-tests-module-setup-analytics-api-mock' );

		// Go to the analytics setup page.
		await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
		await page.waitForSelector( '.mdc-tab-bar' );
		await expect( page ).toClick( '.mdc-tab', {
			text: /connect more services/i,
		} );
		await page.waitForSelector(
			'.googlesitekit-settings-connect-module--analytics'
		);
		await expect( page ).toClick( '.googlesitekit-cta-link', {
			text: /set up analytics/i,
		} );
		await page.waitForSelector( '.googlesitekit-setup-module--analytics' );
		await page.waitForSelector( '.googlesitekit-setup-module__inputs' );

		// Select "Test Account A" account.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-account'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /test account a/i,
		} );

		// Select "Set up a new property" option.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-property'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /set up a new property/i,
		} );

		// Click on confirm changes button and wait for permissions modal dialog.
		await submitForm();
		await page.waitForSelector( '.mdc-dialog--open', { timeout: 3000 } );

		// Click on proceed button and wait for oauth request.
		await Promise.all( [
			expect( page ).toClick( '.mdc-dialog--open .mdc-button', {
				text: /proceed/i,
			} ),
			page.waitForRequest( ( req ) =>
				req.url().match( 'sitekit.withgoogle.com/o/oauth2/auth' )
			),
		] );

		// When returning, their original action is automatically invoked, without requiring them to click the button again.
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics/data/create-property' )
		);
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics/data/create-profile' )
		);

		// They should end up on the dashboard.
		await Promise.all( [
			page.waitForNavigation(),
			page.waitForSelector( '.googlesitekit-publisher-win__title' ),
		] );
		await expect( page ).toMatchElement(
			'.googlesitekit-publisher-win__title',
			{
				text: /Congrats on completing the setup for Analytics!/i,
			}
		);
		expect( console ).toHaveErrored(); // Permission scope error.
	} );

	it( 'prompts for additional permissions during a new Analytics profile creation if the user has not granted the Analytics edit scope', async () => {
		scope = 'https://www.googleapis.com/auth/analytics.edit';

		await activatePlugin( 'e2e-tests-module-setup-analytics-api-mock' );

		// Go to the analytics setup page.
		await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
		await page.waitForSelector( '.mdc-tab-bar' );
		await expect( page ).toClick( '.mdc-tab', {
			text: /connect more services/i,
		} );
		await page.waitForSelector(
			'.googlesitekit-settings-connect-module--analytics'
		);
		await expect( page ).toClick( '.googlesitekit-cta-link', {
			text: /set up analytics/i,
		} );
		await page.waitForSelector( '.googlesitekit-setup-module--analytics' );
		await page.waitForSelector( '.googlesitekit-setup-module__inputs' );

		// Select "Test Account A" account.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-account'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /test account a/i,
		} );

		// Select "Test Property X" property.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-property'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /test property x/i,
		} );

		// Select "Set up a new view" option.
		await expect( page ).toClick(
			'.googlesitekit-analytics__select-profile'
		);
		await expect( page ).toClick( '.mdc-menu-surface--open li', {
			text: /set up a new view/i,
		} );

		// Click on confirm changes button and wait for permissions modal dialog.
		await submitForm();
		await page.waitForSelector( '.mdc-dialog--open', { timeout: 3000 } );

		// Click on proceed button and wait for oauth request.
		await Promise.all( [
			expect( page ).toClick( '.mdc-dialog--open .mdc-button', {
				text: /proceed/i,
			} ),
			page.waitForRequest( ( req ) =>
				req.url().match( 'sitekit.withgoogle.com/o/oauth2/auth' )
			),
		] );

		// When returning, their original action is automatically invoked, without requiring them to click the button again.
		await page.waitForRequest( ( req ) =>
			req.url().match( 'analytics/data/create-profile' )
		);

		// They should end up on the dashboard.
		await Promise.all( [
			page.waitForNavigation(),
			page.waitForSelector( '.googlesitekit-publisher-win__title' ),
		] );
		await expect( page ).toMatchElement(
			'.googlesitekit-publisher-win__title',
			{
				text: /Congrats on completing the setup for Analytics!/i,
			}
		);
		expect( console ).toHaveErrored(); // Permission scope error.
	} );
} );
<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'

import FloatingActionButton from 'material-ui/FloatingActionButton'
import FileFileDownload from 'material-ui/svg-icons/file/file-download'

const mapStateToProps = ({ }) => ({ })

const DownloadButton = ({fileName, list, style, disabled }) => (
  <FloatingActionButton
    style={style}
    disabled={disabled}
    onClick={() => {
      var content = list.map(line => line.join(',')).join("\n")

      var blob = new Blob([content], {type: 'text/csv'});
      var url = window.URL || window.webkitURL;
      var blobURL = url.createObjectURL(blob);

      if(window.navigator.msSaveBlob){
        window.navigator.msSaveBlob(blob, fileName)
      }
      else{
        var a = document.createElement('a');
         a.download = fileName;
         a.href = blobURL;
         a.click();
       }
     }
    }
    ><FileFileDownload /></FloatingActionButton>
)

export default connect(mapStateToProps)(DownloadButton) <commit_msg>add bom<commit_after>import React from 'react'
import { connect } from 'react-redux'

import FloatingActionButton from 'material-ui/FloatingActionButton'
import FileFileDownload from 'material-ui/svg-icons/file/file-download'

const mapStateToProps = ({ }) => ({ })

const DownloadButton = ({fileName, list, style, disabled }) => (
  <FloatingActionButton
    style={style}
    disabled={disabled}
    onClick={() => {
      var content = list.map(line => line.join(',')).join("\n")
      var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
      var blob = new Blob([bom,content], {type: 'text/csv'});
      var url = window.URL || window.webkitURL;
      var blobURL = url.createObjectURL(blob);

      if(window.navigator.msSaveBlob){
        window.navigator.msSaveBlob(blob, fileName)
      }
      else{
        var a = document.createElement('a');
         a.download = fileName;
         a.href = blobURL;
         a.click();
       }
     }
    }
    ><FileFileDownload /></FloatingActionButton>
)

export default connect(mapStateToProps)(DownloadButton)
<|endoftext|>


<commit_before>/*
 * Copyright 2005 Shinya Kasatani
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// shortcut
this.Preferences = SeleniumIDE.Preferences;

/*
 * A model that represents the state of the application.
 */
function Application() {
    this.baseURL = "";
    this.showDeveloperTools = false;
    this.options = Preferences.load();
    this.baseURLHistory = new StoredHistory("baseURLHistory", 20);
    this.testCase = null;
    this.testSuite = null;
    this.formats = null;
    this.currentFormat = null;
    this.clipboardFormat = null;
    this.recentTestSuites = new StoredHistory("recentTestSuites");
    this.recentTestCases = new StoredHistory("recentTestCases");
}

Application.prototype = {
    saveState: function() {
        if (this.options.rememberBaseURL == 'true'){
            this.options.baseURL = this.baseURL;
            Preferences.save(this.options, 'baseURL');
        }
    },

    getBaseURL: function() {
        return this.baseURL;
    },

    setBaseURL: function(baseURL) {
        this.baseURL = baseURL;
        this.baseURLHistory.add(baseURL);
        if (this.testCase) {
            this.testCase.setBaseURL(baseURL);
        }
        this.notify("baseURLChanged");
    },

    getBaseURLHistory: function() {
        return this.baseURLHistory.list();
    },

    //get the "showDeveloperTools" state
    getShowDeveloperTools: function(){
    	return this.showDeveloperTools;
    },

    //set the "showDeveloperTools" state by the given state "show"
    setShowDeveloperTools: function(show){
    	this.showDeveloperTools = show == 'true' ? true : false;
    	this.notify("showDevToolsChanged", this.showDeveloperTools);
    },

    initOptions: function() {
        if (this.options.rememberBaseURL == 'true' && this.options.baseURL != null){
            this.setBaseURL(this.options.baseURL);
        }
        //initializing the reload button
        this.setShowDeveloperTools(this.options.showDeveloperTools);
        this.setOptions(this.options); // to notify optionsChanged to views
    },

    getOptions: function(options) {
        return this.options;
    },

    setOptions: function(options) {
        this.options = options;
        this.setShowDeveloperTools(this.options.showDeveloperTools+"");
        this.formats = new FormatCollection(options);
        this.currentFormat = this.formats.selectFormat(options.selectedFormat || null);
        this.clipboardFormat = this.formats.selectFormat(options.clipboardFormat || null);
        this.notify("optionsChanged", options);
    },

    setCurrentFormat: function(format) {
        this.currentFormat = format;
        this.options.selectedFormat = format.id;
        Preferences.save(this.options, 'selectedFormat');
        //this.setClipboardFormat(format);
        this.notify("currentFormatChanged", format);
    },

    getCurrentFormat: function() {
        return this.currentFormat;
    },

    isPlayable: function() {
        return this.getCurrentFormat().getFormatter().playable;
    },

    setClipboardFormat: function(format) {
        this.clipboardFormat = format;
        this.options.clipboardFormat = format.id;
        Preferences.save(this.options, 'clipboardFormat');
        this.notify("clipboardFormatChanged", format);
    },

    getClipboardFormat: function() {
        return this.clipboardFormat;
    },

    getFormats: function() {
        return this.formats;
    },

    newTestSuite: function() {
        this.log.debug("newTestSuite");
        var testSuite = new TestSuite();
        var testCase = new TestCase();
        testSuite.addTestCaseFromContent(testCase);
        this.setTestSuite(testSuite);
        this.setTestCase(testCase);
    },

    setTestSuite: function(testSuite) {
        if (this.testSuite) {
            this.notify("testSuiteUnloaded", this.testSuite);
        }
        this.testSuite = testSuite;
        this.notify("testSuiteChanged", testSuite);
    },

    getTestSuite: function() {
        return this.testSuite;
    },

    addRecentTestSuite: function(testSuite) {
        this.recentTestSuites.add(testSuite.file.path);
    },

    setTestCase: function(testCase) {
        if (this.testCase) {
            if (testCase == this.testCase) return;
            this.notify("testCaseUnloaded", this.testCase);
        }
        this.testCase = testCase;
        if (testCase.baseURL) {
            this.setBaseURL(testCase.baseURL);
        } else {
            //testCase.setBaseURL(this.baseURL);
        }
        this.notify("testCaseChanged", this.testCase);
    },

    getTestCase: function() {
        return this.testCase;
    },

    newTestCase: function() {
        var testCase = new TestCase(this.testSuite.generateNewTestCaseTitle());
        this.testSuite.addTestCaseFromContent(testCase);
        this.setTestCase(testCase);
    },

    /**
     * Adds a testcase to the current suite
     */
    addTestCase: function(path) {
        var file = null;
        if (path) {
            file = FileUtils.getFile(path);
        }
        if (this._loadTestCase(file)) {
            this.testSuite.addTestCaseFromContent(this.getTestCase());
            this.setTestCase(this.getTestCase());
        }
    },

    loadTestCaseWithNewSuite: function(path) {
        var file = null;
        if (path) {
            file = FileUtils.getFile(path);
        }
        if (this._loadTestCase(file)) {
            this.setTestCaseWithNewSuite(this.getTestCase());
        }
    },

    setTestCaseWithNewSuite: function(testCase) {
        var testSuite = new TestSuite();
        testSuite.addTestCaseFromContent(testCase);
        this.setTestSuite(testSuite);
        this.setTestCase(testCase);
    },

    // show specified TestSuite.TestCase object.
    showTestCaseFromSuite: function(testCase) {
        if (testCase.content) {
            this.setTestCase(testCase.content);
        } else {
            this._loadTestCase(testCase.getFile(), function(test) {
                    test.title = testCase.getTitle(); // load title from suite
                    testCase.content = test;
                });
        }
    },

    _loadTestCase: function(file, testCaseHandler) {
        this.log.debug("loadTestCase");
        try {
            var testCase = null;
            if (file) {
                testCase = this.getCurrentFormat().loadFile(file, false);
            } else {
                testCase = this.getCurrentFormat().load();
            }
            if (testCase != null) {
                if (testCaseHandler) testCaseHandler(testCase);
                this.setTestCase(testCase);
                this.recentTestCases.add(testCase.file.path);
                return true;
            }
            return false;
        } catch (error) {
            alert("error loading test case: " + error);
            return false;
        }
    },

    loadTestSuite: function(path) {
        this.log.debug("loadTestSuite");
        try {
            var testSuite = null;
            if (path) {
                testSuite = TestSuite.loadFile(FileUtils.getFile(path));
            } else {
                testSuite = TestSuite.load();
            }
            if (testSuite) {
                this.setTestSuite(testSuite);
                this.addRecentTestSuite(testSuite);
            }
        } catch (error) {
            alert("error loading test suite: " + error);
        }
    },

    saveTestSuite: function() {
        this._saveTestSuiteAs(function(testSuite) {
                return testSuite.save(false);
            });
    },

    saveNewTestSuite: function() {
        this._saveTestSuiteAs(function(testSuite) {
                return testSuite.save(true);
            });
    },

    _saveTestSuiteAs: function(handler) {
        this.log.debug("saveTestSuite");
        var cancelled = false;
        this.getTestSuite().tests.forEach(function(test) {
                if (cancelled) return;
                if (test.content && test.content.modified) {
                    if (confirm("The test case is modified. Do you want to save this test case?")) {
                        if (!this.getCurrentFormat().save(test.content)) {
                            cancelled = true;
                        }
                    } else {
                        cancelled = true;
                    }
                }
            }, this);
        if (!cancelled) {
            if (handler(this.getTestSuite())) {
                this.addRecentTestSuite(this.getTestSuite());
            }
        }
    },

    saveTestCase: function() {
        var result = this.getCurrentFormat().save(this.getTestCase());
        if (result) {
            this.recentTestCases.add(this.getTestCase().file.path);
        }
        return result;
    },

    saveNewTestCase: function() {
        var result = this.getCurrentFormat().saveAsNew(this.getTestCase());
        if (result) {
            this.recentTestCases.add(this.getTestCase().file.path);
        }
    }
}

Application.prototype.log = Application.log = new Log("Application");
observable(Application);
<commit_msg>Dave Hunt: After discussion with Adam Goucher and Jérémy Hérault I have removed the line that previously linked changing the display source format with the clipboard format.<commit_after>/*
 * Copyright 2005 Shinya Kasatani
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// shortcut
this.Preferences = SeleniumIDE.Preferences;

/*
 * A model that represents the state of the application.
 */
function Application() {
    this.baseURL = "";
    this.showDeveloperTools = false;
    this.options = Preferences.load();
    this.baseURLHistory = new StoredHistory("baseURLHistory", 20);
    this.testCase = null;
    this.testSuite = null;
    this.formats = null;
    this.currentFormat = null;
    this.clipboardFormat = null;
    this.recentTestSuites = new StoredHistory("recentTestSuites");
    this.recentTestCases = new StoredHistory("recentTestCases");
}

Application.prototype = {
    saveState: function() {
        if (this.options.rememberBaseURL == 'true'){
            this.options.baseURL = this.baseURL;
            Preferences.save(this.options, 'baseURL');
        }
    },

    getBaseURL: function() {
        return this.baseURL;
    },

    setBaseURL: function(baseURL) {
        this.baseURL = baseURL;
        this.baseURLHistory.add(baseURL);
        if (this.testCase) {
            this.testCase.setBaseURL(baseURL);
        }
        this.notify("baseURLChanged");
    },

    getBaseURLHistory: function() {
        return this.baseURLHistory.list();
    },

    //get the "showDeveloperTools" state
    getShowDeveloperTools: function(){
    	return this.showDeveloperTools;
    },

    //set the "showDeveloperTools" state by the given state "show"
    setShowDeveloperTools: function(show){
    	this.showDeveloperTools = show == 'true' ? true : false;
    	this.notify("showDevToolsChanged", this.showDeveloperTools);
    },

    initOptions: function() {
        if (this.options.rememberBaseURL == 'true' && this.options.baseURL != null){
            this.setBaseURL(this.options.baseURL);
        }
        //initializing the reload button
        this.setShowDeveloperTools(this.options.showDeveloperTools);
        this.setOptions(this.options); // to notify optionsChanged to views
    },

    getOptions: function(options) {
        return this.options;
    },

    setOptions: function(options) {
        this.options = options;
        this.setShowDeveloperTools(this.options.showDeveloperTools+"");
        this.formats = new FormatCollection(options);
        this.currentFormat = this.formats.selectFormat(options.selectedFormat || null);
        this.clipboardFormat = this.formats.selectFormat(options.clipboardFormat || null);
        this.notify("optionsChanged", options);
    },

    setCurrentFormat: function(format) {
        this.currentFormat = format;
        this.options.selectedFormat = format.id;
        Preferences.save(this.options, 'selectedFormat');
        this.notify("currentFormatChanged", format);
    },

    getCurrentFormat: function() {
        return this.currentFormat;
    },

    isPlayable: function() {
        return this.getCurrentFormat().getFormatter().playable;
    },

    setClipboardFormat: function(format) {
        this.clipboardFormat = format;
        this.options.clipboardFormat = format.id;
        Preferences.save(this.options, 'clipboardFormat');
        this.notify("clipboardFormatChanged", format);
    },

    getClipboardFormat: function() {
        return this.clipboardFormat;
    },

    getFormats: function() {
        return this.formats;
    },

    newTestSuite: function() {
        this.log.debug("newTestSuite");
        var testSuite = new TestSuite();
        var testCase = new TestCase();
        testSuite.addTestCaseFromContent(testCase);
        this.setTestSuite(testSuite);
        this.setTestCase(testCase);
    },

    setTestSuite: function(testSuite) {
        if (this.testSuite) {
            this.notify("testSuiteUnloaded", this.testSuite);
        }
        this.testSuite = testSuite;
        this.notify("testSuiteChanged", testSuite);
    },

    getTestSuite: function() {
        return this.testSuite;
    },

    addRecentTestSuite: function(testSuite) {
        this.recentTestSuites.add(testSuite.file.path);
    },

    setTestCase: function(testCase) {
        if (this.testCase) {
            if (testCase == this.testCase) return;
            this.notify("testCaseUnloaded", this.testCase);
        }
        this.testCase = testCase;
        if (testCase.baseURL) {
            this.setBaseURL(testCase.baseURL);
        } else {
            //testCase.setBaseURL(this.baseURL);
        }
        this.notify("testCaseChanged", this.testCase);
    },

    getTestCase: function() {
        return this.testCase;
    },

    newTestCase: function() {
        var testCase = new TestCase(this.testSuite.generateNewTestCaseTitle());
        this.testSuite.addTestCaseFromContent(testCase);
        this.setTestCase(testCase);
    },

    /**
     * Adds a testcase to the current suite
     */
    addTestCase: function(path) {
        var file = null;
        if (path) {
            file = FileUtils.getFile(path);
        }
        if (this._loadTestCase(file)) {
            this.testSuite.addTestCaseFromContent(this.getTestCase());
            this.setTestCase(this.getTestCase());
        }
    },

    loadTestCaseWithNewSuite: function(path) {
        var file = null;
        if (path) {
            file = FileUtils.getFile(path);
        }
        if (this._loadTestCase(file)) {
            this.setTestCaseWithNewSuite(this.getTestCase());
        }
    },

    setTestCaseWithNewSuite: function(testCase) {
        var testSuite = new TestSuite();
        testSuite.addTestCaseFromContent(testCase);
        this.setTestSuite(testSuite);
        this.setTestCase(testCase);
    },

    // show specified TestSuite.TestCase object.
    showTestCaseFromSuite: function(testCase) {
        if (testCase.content) {
            this.setTestCase(testCase.content);
        } else {
            this._loadTestCase(testCase.getFile(), function(test) {
                    test.title = testCase.getTitle(); // load title from suite
                    testCase.content = test;
                });
        }
    },

    _loadTestCase: function(file, testCaseHandler) {
        this.log.debug("loadTestCase");
        try {
            var testCase = null;
            if (file) {
                testCase = this.getCurrentFormat().loadFile(file, false);
            } else {
                testCase = this.getCurrentFormat().load();
            }
            if (testCase != null) {
                if (testCaseHandler) testCaseHandler(testCase);
                this.setTestCase(testCase);
                this.recentTestCases.add(testCase.file.path);
                return true;
            }
            return false;
        } catch (error) {
            alert("error loading test case: " + error);
            return false;
        }
    },

    loadTestSuite: function(path) {
        this.log.debug("loadTestSuite");
        try {
            var testSuite = null;
            if (path) {
                testSuite = TestSuite.loadFile(FileUtils.getFile(path));
            } else {
                testSuite = TestSuite.load();
            }
            if (testSuite) {
                this.setTestSuite(testSuite);
                this.addRecentTestSuite(testSuite);
            }
        } catch (error) {
            alert("error loading test suite: " + error);
        }
    },

    saveTestSuite: function() {
        this._saveTestSuiteAs(function(testSuite) {
                return testSuite.save(false);
            });
    },

    saveNewTestSuite: function() {
        this._saveTestSuiteAs(function(testSuite) {
                return testSuite.save(true);
            });
    },

    _saveTestSuiteAs: function(handler) {
        this.log.debug("saveTestSuite");
        var cancelled = false;
        this.getTestSuite().tests.forEach(function(test) {
                if (cancelled) return;
                if (test.content && test.content.modified) {
                    if (confirm("The test case is modified. Do you want to save this test case?")) {
                        if (!this.getCurrentFormat().save(test.content)) {
                            cancelled = true;
                        }
                    } else {
                        cancelled = true;
                    }
                }
            }, this);
        if (!cancelled) {
            if (handler(this.getTestSuite())) {
                this.addRecentTestSuite(this.getTestSuite());
            }
        }
    },

    saveTestCase: function() {
        var result = this.getCurrentFormat().save(this.getTestCase());
        if (result) {
            this.recentTestCases.add(this.getTestCase().file.path);
        }
        return result;
    },

    saveNewTestCase: function() {
        var result = this.getCurrentFormat().saveAsNew(this.getTestCase());
        if (result) {
            this.recentTestCases.add(this.getTestCase().file.path);
        }
    }
}

Application.prototype.log = Application.log = new Log("Application");
observable(Application);
<|endoftext|>


<commit_before>import container from './container'

let pid = 0

export default {
  props: {
    playerHeight: {
      type: [String, Number],
      default: '360'
    },
    playerWidth: {
      type: [String, Number],
      default: '640'
    },
    playerVars: {
      type: Object,
      default: () => ({ autoplay: 0, time: 0 })
    },
    videoId: {
      type: String
    },
    mute: {
      type: Boolean,
      default: false
    }
  },
  render (h) {
    return h('div', [
      h('div', { attrs: { id: this.elementId }})
    ])
  },
  template: '

',
  watch: {
    playerWidth: 'setSize',
    playerHeight: 'setSize',
    videoId: 'update',
    mute: 'setMute'
  },
  data () {
    pid += 1
    return {
      elementId: `youtube-player-${pid}`,
      player: {}
    }
  },
  methods: {
    setSize () {
      this.player.setSize(this.playerWidth, this.playerHeight)
    },
    setMute (value) {
      if (value) {
        this.player.mute()
      } else {
        this.player.unMute()
      }
    },
    update (videoId) {
      const name = `${this.playerVars.autoplay ? 'load' : 'cue'}VideoById`
      if (this.player.hasOwnProperty(name)) {
        this.player[name](videoId)
      } else {
        setTimeout(function () {
          this.update(videoId)
        }.bind(this), 100)
      }
    }
  },
  mounted () {
    container.register((YouTube) => {
      const { playerHeight, playerWidth, playerVars, videoId } = this

      this.player = new YouTube.Player(this.elementId, {
        height: playerHeight,
        width: playerWidth,
        playerVars,
        videoId,
        events: {
          onReady: (event) => {
            this.setMute(this.mute)
            this.$emit('ready', event)
          },
          onStateChange: (event) => {
            if (event.data !== -1) {
              this.$emit(container.events[event.data], event)
            }
          },
          onError: (event) => {
            this.$emit('error', event)
          }
        }
      })
    })
  },
  beforeDestroy () {
    if (this.player !== null && this.player.destroy) {
      this.player.destroy()
    }
    delete this.player
  }
}
<commit_msg>added support for host key in player options<commit_after>import container from './container'

let pid = 0

export default {
  props: {
    playerHeight: {
      type: [String, Number],
      default: '360'
    },
    playerWidth: {
      type: [String, Number],
      default: '640'
    },
    playerVars: {
      type: Object,
      default: () => ({ autoplay: 0, time: 0 })
    },
    videoId: {
      type: String
    },
    mute: {
      type: Boolean,
      default: false
    },
    host: {
      type: String,
      default: 'https://www.youtube.com'
    }
  },
  render (h) {
    return h('div', [
      h('div', { attrs: { id: this.elementId }})
    ])
  },
  template: '

',
  watch: {
    playerWidth: 'setSize',
    playerHeight: 'setSize',
    videoId: 'update',
    mute: 'setMute'
  },
  data () {
    pid += 1
    return {
      elementId: `youtube-player-${pid}`,
      player: {}
    }
  },
  methods: {
    setSize () {
      this.player.setSize(this.playerWidth, this.playerHeight)
    },
    setMute (value) {
      if (value) {
        this.player.mute()
      } else {
        this.player.unMute()
      }
    },
    update (videoId) {
      const name = `${this.playerVars.autoplay ? 'load' : 'cue'}VideoById`
      if (this.player.hasOwnProperty(name)) {
        this.player[name](videoId)
      } else {
        setTimeout(function () {
          this.update(videoId)
        }.bind(this), 100)
      }
    }
  },
  mounted () {
    container.register((YouTube) => {
      const { playerHeight, playerWidth, playerVars, videoId } = this

      this.player = new YouTube.Player(this.elementId, {
        height: playerHeight,
        width: playerWidth,
        playerVars,
        videoId,
        host,
        events: {
          onReady: (event) => {
            this.setMute(this.mute)
            this.$emit('ready', event)
          },
          onStateChange: (event) => {
            if (event.data !== -1) {
              this.$emit(container.events[event.data], event)
            }
          },
          onError: (event) => {
            this.$emit('error', event)
          }
        }
      })
    })
  },
  beforeDestroy () {
    if (this.player !== null && this.player.destroy) {
      this.player.destroy()
    }
    delete this.player
  }
}
<|endoftext|>


<commit_before>(function() {

  this.Player = function() {

    var defaults = {
        videoId: null,
        playerClass: 'custom-player',
        extraClass: null,
        width: 480,
        height: 270,
        autoPlay: null,
        controls: null,
        relatedVideos: 0,
        showInfo: null,
        wrap: null,
        wrapClass: 'custom-player-wrapper',
        playButton: null,
        playButtonText: 'Play',
        pauseButton: null,
        pauseButtonText: 'Pause',
        mute: null,
        placement: null
    };

    // Add our defaults above into a global array of options
    if (arguments[0] && typeof arguments[0] === 'object') {
      this.options = extendDefaults( defaults, arguments[0] );
    }

    // Global vars
    this.wrap = this.options.wrap;
    this.playButton = this.options.playButton;
    this.playButtonText = this.options.playButtonText;
    this.pauseButton = this.options.pauseButton;
    this.pauseButtonText = this.options.pauseButtonText;
    this.extraClass = this.options.extraClass;
    mute = this.options.mute;
    placement = this.options.placement;
    var usingDataAttr = false;

    // Run Player.init()
    this.init();

  };

  Player.prototype.init = function() {
    var this_ = this;

    if( !usingDataAttr ) {
      // If any extraClass names have been added add them
      var extraClass = this_.options.extraClass,
          classCheck = extraClass === null,
          addExtraClass = classCheck ? '' : ' ' + extraClass;

      generateEl( 'div', this_.options.videoId, this_.options.playerClass + addExtraClass );
    } else {
      playerData.id = this_.options.videoId;
    }

    // Generate the wrapper
    if ( this.wrap ) {
      this.wrapper = document.createElement( 'div' );
      this.wrapper.className = this_.options.wrapClass;
      this.customPlayer = document.getElementById( this_.options.videoId );
      this.wrapper.appendChild( this.customPlayer.cloneNode( true ) );
      this.customPlayer.parentNode.replaceChild( this.wrapper, this.customPlayer );
    }

    var callback = function() {
      this_.player = new YT.Player(this_.options.videoId, {
        videoId: this_.options.videoId,
        height: this_.options.height,
        width: this_.options.width,
        playButton: this_.options.playButton,
        pauseButton: this_.options.pauseButton,
        playerVars: {
          autoplay: this_.options.autoPlay,
          controls: this_.options.controls,
          rel: this_.options.relatedVideos,
          showinfo: this_.options.showInfo,
        },
        events: {
          onReady: this_._onPlayerReady,
          onStateChange: this_._onStateChange
        }
      });

      // Load custom controls
      if ( this_.playButton || this_.pauseButton ) {
        this_.customControls();
      }
    };

    // Test if the youtube api is loaded
    if ('YT' in window) {
      callback();
    } else {
      var tag = document.createElement( 'script' );

      tag.src = 'https://www.youtube.com/iframe_api';
      var firstScriptTag = document.getElementsByTagName( 'script' )[0];
      firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );

      tag.onload = function() {
        YT.ready( callback );
      };
    }

  };

  // Controls
  Player.prototype.customControls = function() {
    var this_ = this;
    var customControls = 'custom-controls';

    generateEl( 'div', customControls );

    // Find the first custom-controls element
    // TODO: Look for multiple elements on the page
    if ( this_.wrap ) {
      var controls = document.querySelector( '.' + customControls ),
          wrapper = document.querySelector( '.custom-player-wrapper' );

      wrapper.appendChild( controls );
    }

    // Play button
    if ( this_.playButton ) {
      var playButtonEl;
      playButtonEl = document.createElement( 'button' );
      playButtonEl.innerHTML = this.playButtonText;
      playButtonEl.className = this.playButton;
      document.querySelector( '.' + customControls ).appendChild( playButtonEl );

      document.querySelector( '.' + this.playButton ).addEventListener( 'click', function() {
        this_.player.playVideo();
      });
    }

    // Pause video
    if ( this_.pauseButton ) {
      var pauseButtonEl;
      pauseButtonEl = document.createElement( 'button' );
      pauseButtonEl.innerHTML = this.pauseButtonText;
      pauseButtonEl.className = this.pauseButton;
      document.querySelector( '.' + customControls ).appendChild( pauseButtonEl );

      document.querySelector( '.' + this.pauseButton ).addEventListener( 'click', function() {
        this_.player.pauseVideo();
      });
    }

  };

  // Events
  Player.prototype._onPlayerReady = function( event ) {
    if ( mute === '1') {
      event.target.mute();
    }
  };
  Player.prototype._onStateChange = function( event ) {};

  // Private Methods

  // Build the necessary markup
  // and inject it into the document if needed
  function generateEl( el, id, className ) {
    var docFrag, element;

    docFrag = document.createDocumentFragment();
    element = document.createElement( el );

    if ( id ) {
      element.id = id;
    }
    if ( className ) {
      element.className = className;
    }

    docFrag.appendChild( element );

    if ( placement !== null ) {
      var selector = document.querySelector( '.' + placement );
      selector.appendChild( docFrag );
    } else {
      document.body.appendChild( docFrag );
    }
  }

  // Utility method to extend defaults with user options
  function extendDefaults( source, properties ) {
    var property;
    for ( property in properties ) {
      if ( properties.hasOwnProperty( property ) ) {
        source[ property ] = properties[ property ];
      }
    }
    return source;
  }

  // Look for the first element that contains data-video-id
  // TODO: Look for multiple data-video-id's
  var playerData = document.querySelector( '[data-video-id]' );
  if ( playerData ) {
    var usingDataAttr = true;
    // If it exists create a new Player
    // and populate it with the rest of the data attributes
    var options = playerData.dataset,
        newPlayer = new Player(options);
  }

})();
<commit_msg>Added generateEl to the prototype<commit_after>(function() {

  this.Player = function() {

    var defaults = {
        videoId: null,
        playerClass: 'custom-player',
        extraClass: null,
        width: 480,
        height: 270,
        autoPlay: null,
        controls: null,
        relatedVideos: 0,
        showInfo: null,
        wrap: null,
        wrapClass: 'custom-player-wrapper',
        playButton: null,
        playButtonText: 'Play',
        pauseButton: null,
        pauseButtonText: 'Pause',
        mute: null,
        placement: null
    };

    // Add our defaults above into a global array of options
    if (arguments[0] && typeof arguments[0] === 'object') {
      this.options = extendDefaults( defaults, arguments[0] );
    }

    // Global vars
    this.wrap = this.options.wrap;
    this.playButton = this.options.playButton;
    this.playButtonText = this.options.playButtonText;
    this.pauseButton = this.options.pauseButton;
    this.pauseButtonText = this.options.pauseButtonText;
    this.extraClass = this.options.extraClass;
    mute = this.options.mute;
    this.placement = this.options.placement;

    var usingDataAttr = false;

    // Run Player.init()
    this.init();

  };

  Player.prototype.init = function() {
    var this_ = this;

    if( !usingDataAttr ) {
      // If any extraClass names have been added add them
      var extraClass = this_.options.extraClass,
          classCheck = extraClass === null,
          addExtraClass = classCheck ? '' : ' ' + extraClass;

      this.generateEl( 'div', this_.options.videoId, this_.options.playerClass + addExtraClass );
    } else {
      playerData.id = this_.options.videoId;
    }

    // Generate the wrapper
    if ( this.wrap ) {
      this.wrapper = document.createElement( 'div' );
      this.wrapper.className = this_.options.wrapClass;
      this.customPlayer = document.getElementById( this_.options.videoId );
      this.wrapper.appendChild( this.customPlayer.cloneNode( true ) );
      this.customPlayer.parentNode.replaceChild( this.wrapper, this.customPlayer );
    }

    var callback = function() {
      this_.player = new YT.Player(this_.options.videoId, {
        videoId: this_.options.videoId,
        height: this_.options.height,
        width: this_.options.width,
        playButton: this_.options.playButton,
        pauseButton: this_.options.pauseButton,
        playerVars: {
          autoplay: this_.options.autoPlay,
          controls: this_.options.controls,
          rel: this_.options.relatedVideos,
          showinfo: this_.options.showInfo,
        },
        events: {
          onReady: this_._onPlayerReady,
          onStateChange: this_._onStateChange
        }
      });

      // Load custom controls
      if ( this_.playButton || this_.pauseButton ) {
        this_.customControls();
      }
    };

    // Test if the youtube api is loaded
    if ('YT' in window) {
      callback();
    } else {
      var tag = document.createElement( 'script' );

      tag.src = 'https://www.youtube.com/iframe_api';
      var firstScriptTag = document.getElementsByTagName( 'script' )[0];
      firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );

      tag.onload = function() {
        YT.ready( callback );
      };
    }

  };

  // Controls
  Player.prototype.customControls = function() {
    var this_ = this;
    var customControls = 'custom-controls';

    this.generateEl( 'div', customControls );

    // Find the first custom-controls element
    // TODO: Look for multiple elements on the page
    if ( this_.wrap ) {
      var controls = document.querySelector( '.' + customControls ),
          wrapper = document.querySelector( '.custom-player-wrapper' );

      wrapper.appendChild( controls );
    }

    // Play button
    if ( this_.playButton ) {
      var playButtonEl;
      playButtonEl = document.createElement( 'button' );
      playButtonEl.innerHTML = this.playButtonText;
      playButtonEl.className = this.playButton;
      document.querySelector( '.' + customControls ).appendChild( playButtonEl );

      document.querySelector( '.' + this.playButton ).addEventListener( 'click', function() {
        this_.player.playVideo();
      });
    }

    // Pause video
    if ( this_.pauseButton ) {
      var pauseButtonEl;
      pauseButtonEl = document.createElement( 'button' );
      pauseButtonEl.innerHTML = this.pauseButtonText;
      pauseButtonEl.className = this.pauseButton;
      document.querySelector( '.' + customControls ).appendChild( pauseButtonEl );

      document.querySelector( '.' + this.pauseButton ).addEventListener( 'click', function() {
        this_.player.pauseVideo();
      });
    }

  };

  // Events
  Player.prototype._onPlayerReady = function( event ) {
    if ( mute === '1') {
      event.target.mute();
    }
  };
  Player.prototype._onStateChange = function( event ) {};

  // Private Methods

  // Build the necessary markup
  // and inject it into the document if needed
  Player.prototype.generateEl = function( el, id, className ) {
    var docFrag, element;

    docFrag = document.createDocumentFragment();
    element = document.createElement( el );

    if ( id ) {
      element.id = id;
    }
    if ( className ) {
      element.className = className;
    }

    docFrag.appendChild( element );

    if ( this.placement !== null ) {
      var selector = document.querySelector( this.placement );
      selector.appendChild( docFrag );
    } else {
      document.body.appendChild( docFrag );
    }
  }

  // Utility method to extend defaults with user options
  function extendDefaults( source, properties ) {
    var property;
    for ( property in properties ) {
      if ( properties.hasOwnProperty( property ) ) {
        source[ property ] = properties[ property ];
      }
    }
    return source;
  }

  // Look for the first element that contains data-video-id
  // TODO: Look for multiple data-video-id's
  var playerData = document.querySelector( '[data-video-id]' );
  if ( playerData ) {
    var usingDataAttr = true;
    // If it exists create a new Player
    // and populate it with the rest of the data attributes
    var options = playerData.dataset,
        newPlayer = new Player(options);
  }

})();
<|endoftext|>