<commit_before>// lib/finishers.js
//
// Functions for adding extra flags and stream data to API output
//
// Copyright 2012, StatusNet Inc.
//
// 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.

var _ = require("underscore"),
    Step = require("step"),
    ActivityObject = require("../lib/model/activityobject").ActivityObject,
    Edge = require("../lib/model/edge").Edge,
    Proxy = require("../lib/model/proxy").Proxy,
    Favorite = require("../lib/model/favorite").Favorite,
    Share = require("../lib/model/share").Share,
    FilteredStream = require("../lib/filteredstream").FilteredStream,
    filters = require("../lib/filters"),
    URLMaker = require("../lib/urlmaker").URLMaker,
    urlparse = require("url").parse,
    recipientsOnly = filters.recipientsOnly,
    objectRecipientsOnly = filters.objectRecipientsOnly,
    objectPublicOnly = filters.objectPublicOnly,
    publicOnly = filters.publicOnly;

// finisher that adds followed flag to stuff

var addFollowedFinisher = function(req, collection, callback) {

    // Ignore for non-users

    if (!req.principal) {
        callback(null);
        return;
    }

    addFollowed(req.principal, _.pluck(collection.items, "object"), callback);
};

var addFollowed = function(profile, objects, callback) {

    var edgeIDs;

    // Ignore for non-users

    if (!profile) {
        callback(null);
        return;
    }

    edgeIDs = objects.map(function(object) {
        return Edge.id(profile.id, object.id);
    });

    Step(
        function() {
            Edge.readAll(edgeIDs, this);
        },
        function(err, edges) {
            if (err) {
                callback(err);
            } else {
                _.each(objects, function(object, i) {
                    var edgeID = edgeIDs[i];
                    if (!_.has(object, "pump_io")) {
                        object.pump_io = {};
                    }
                    if (_.has(edges, edgeID) && _.isObject(edges[edgeID])) {
                        object.pump_io.followed = true;
                    } else {
                        object.pump_io.followed = false;
                    }
                });
                callback(null);
            }
        }
    );
};

// finisher that adds shared flag to stuff

var addSharedFinisher = function(req, collection, callback) {

    // Ignore for non-users

    if (!req.principal) {
        callback(null);
        return;
    }

    addShared(req.principal, _.pluck(collection.items, "object"), callback);
};

var addShared = function(profile, objects, callback) {

    var shareIDs;

    // Ignore for non-users

    if (!profile) {
        callback(null);
        return;
    }

    shareIDs = objects.map(function(object) {
        return Share.id(profile, object);
    });

    Step(
        function() {
            Share.readAll(shareIDs, this);
        },
        function(err, shares) {
            if (err) {
                callback(err);
            } else {
                _.each(objects, function(object, i) {
                    var shareID = shareIDs[i];
                    if (!_.has(object, "pump_io")) {
                        object.pump_io = {};
                    }
                    if (_.has(shares, shareID) && _.isObject(shares[shareID])) {
                        object.pump_io.shared = true;
                    } else {
                        object.pump_io.shared = false;
                    }
                });
                callback(null);
            }
        }
    );
};

// finisher that adds liked flag to stuff

var addLikedFinisher = function(req, collection, callback) {

    // Ignore for non-users

    if (!req.principal) {
        callback(null);
        return;
    }

    addLiked(req.principal, _.pluck(collection.items, "object"), callback);
};

var addLiked = function(profile, objects, callback) {

    var faveIDs;

    // Ignore for non-users

    if (!profile) {
        callback(null);
        return;
    }

    faveIDs = objects.map(function(object) {
        return Favorite.id(profile.id, object.id);
    });

    Step(
        function() {
            Favorite.readAll(faveIDs, this);
        },
        function(err, faves) {
            if (err) {
                callback(err);
            } else {
                _.each(objects, function(object, i) {
                    var faveID = faveIDs[i];
                    if (_.has(faves, faveID) && _.isObject(faves[faveID])) {
                        object.liked = true;
                    } else {
                        object.liked = false;
                    }
                });
                callback(null);
            }
        }
    );
};

var firstFewRepliesFinisher = function(req, collection, callback) {

    var profile = req.principal,
        objects = _.pluck(collection.items, "object");

    firstFewReplies(profile, objects, callback);
};

var firstFewReplies = function(profile, objs, callback) {

    var getReplies = function(obj, callback) {

        if (!_.has(obj, "replies") ||
            !_.isObject(obj.replies) ||
            (_.has(obj.replies, "totalItems") && obj.replies.totalItems === 0)) {
            callback(null);
            return;
        }

        Step(
            function() {
                obj.getRepliesStream(this);
            },
            function(err, str) {
                var filtered;
                if (err) throw err;
                if (!profile) {
                    filtered = new FilteredStream(str, objectPublicOnly);
                } else {
                    filtered = new FilteredStream(str, objectRecipientsOnly(profile));
                }
                filtered.getObjects(0, 4, this);
            },
            function(err, refs) {
                var group = this.group();
                if (err) throw err;
                _.each(refs, function(ref) {
                    ActivityObject.getObject(ref.objectType, ref.id, group());
                });
            },
            function(err, objs) {
                if (err) {
                    callback(err);
                } else {
                    obj.replies.items = objs;
                    _.each(obj.replies.items, function(item) {
                        item.sanitize();
                    });
                    callback(null);
                }
            }
        );
    };

    Step(
        function() {
            var group = this.group();
            _.each(objs, function(obj) {
                getReplies(obj, group());
            });
        },
        callback
    );
};

var firstFewSharesFinisher = function(req, collection, callback) {

    var profile = req.principal,
        objects = _.pluck(collection.items, "object");

    firstFewShares(profile, objects, callback);
};

var firstFewShares = function(profile, objs, callback) {

    var getShares = function(obj, callback) {

        if (!_.has(obj, "shares") ||
            !_.isObject(obj.shares) ||
            (_.has(obj.shares, "totalItems") && obj.shares.totalItems === 0)) {
            callback(null);
            return;
        }

        Step(
            function() {
                obj.getSharesStream(this);
            },
            function(err, str) {
                if (err) throw err;
                str.getObjects(0, 4, this);
            },
            function(err, refs) {
                var group = this.group();
                if (err) throw err;
                _.each(refs, function(ref) {
                    ActivityObject.getObject(ref.objectType, ref.id, group());
                });
            },
            function(err, objs) {
                if (err) {
                    callback(err);
                } else {
                    obj.shares.items = objs;
                    _.each(obj.shares.items, function(item) {
                        item.sanitize();
                    });
                    callback(null);
                }
            }
        );
    };

    Step(
        function() {
            var group = this.group();
            _.each(objs, function(obj) {
                getShares(obj, group());
            });
        },
        callback
    );
};

// finisher that adds followed flag to stuff

var addLikersFinisher = function(req, collection, callback) {

    // Ignore for non-users

    addLikers(req.principal,
              _.pluck(collection.items, "object"),
              callback);
};

var addLikers = function(profile, objects, callback) {

    var liked = _.filter(objects, function(object) {
        return _.has(object, "likes") &&
            _.isObject(object.likes) &&
            _.has(object.likes, "totalItems") &&
            _.isNumber(object.likes.totalItems) &&
            object.likes.totalItems > 0;
    });

    Step(
        function() {
            var group = this.group();

            _.each(liked, function(object) {
                object.getFavoriters(0, 4, group());
            });
        },
        function(err, likers) {
            if (err) {
                callback(err);
            } else {
                _.each(liked, function(object, i) {
                    object.likes.items = likers[i];
                });
                callback(null);
            }
        }
    );
};

// finisher that adds proxy URLs for remote URLs

var addProxyFinisher = function(req, collection, callback) {

    // Ignore for non-users

    if (!req.principalUser) {
        callback(null);
        return;
    }

    addProxy(collection.items,
             callback);
};

var addProxy = function(activities, callback) {

    var op = ['actor',
              'object',
              'target',
              'generator',
              'provider',
              'context',
              'source'],
        cp = ['members',
              'followers',
              'following',
              'lists',
              'likes',
              'replies',
              'shares'],
        ap = ['to',
              'cc',
              'bto',
              'bcc'],
        objects = [],
        props = [],
        selves = [],
        urls;

    // Get all the objects that are parts of these activities

    _.each(op, function(prop) {
        objects = objects.concat(_.pluck(activities, prop));
    });

    _.each(ap, function(prop) {
        var values = _.pluck(activities, prop);
        _.each(values, function(value) {
            objects = objects.concat(value);
        });
    });

    objects = _.compact(objects);

    // Get all the object properties that we know have urls and are parts of these objects

    props = props.concat(_.pluck(objects, "image"));

    _.each(cp, function(prop) {
        props = props.concat(_.pluck(objects, prop));
    });

    props = _.compact(props);

    urls = _.compact(_.pluck(props, "url"));

    // Get all the self-links

    _.each(objects, function(obj) {
        if (obj.links && obj.links.self && obj.links.self.href) {
            urls.push(obj.links.self.href);
        }
    });

    // Uniquify the whole set of URLs

    urls = _.uniq(urls);

    // Only need proxies for remote URLs

    urls = _.filter(urls, function(url) {
        var parts = urlparse(url);
        return (parts.hostname != URLMaker.hostname);
    });

    console.dir({propsLength: props.length,
                 objectsLength: objects.length,
                 urlsLength: urls.length});

    Step(
        function() {
            var group = this.group();
            _.each(urls, function(url) {
                Proxy.ensureURL(url, group());
            });
        },
        function(err, proxies) {
            var utp = {};
            if (err) {
                callback(err);
                return;
            }
            _.each(proxies, function(proxy) {
                utp[proxy.url] = proxy;
            });
            _.each(props, function(prop) {
                if (_.has(utp, prop.url)) {
                    if (!prop.pump_io) {
                        prop.pump_io = {};
                    }
                    prop.pump_io.proxyURL = URLMaker.makeURL("/api/proxy/"+utp[prop.url].id);
                }
            });
            _.each(objects, function(obj) {
                if (obj.links && obj.links.self && obj.links.self.href) {
                    if (_.has(utp, obj.links.self.href)) {
                        if (!obj.pump_io) {
                            obj.pump_io = {};
                        }
                        obj.pump_io.proxyURL = URLMaker.makeURL("/api/proxy/"+utp[obj.links.self.href].id);
                    }
                }
            });
            callback(null);
        }
    );
};

var doFinishers = function(finishers) {
    return function(req, collection, callback) {
        Step(
            function() {
                var group = this.group();
                _.each(finishers, function(finisher) {
                    finisher(req, collection, group());
                });
            },
            callback
        );
    };
};

exports.addFollowedFinisher = addFollowedFinisher;
exports.addFollowed = addFollowed;
exports.addLikedFinisher = addLikedFinisher;
exports.addLiked = addLiked;
exports.firstFewRepliesFinisher = firstFewRepliesFinisher;
exports.firstFewReplies = firstFewReplies;
exports.firstFewSharesFinisher = firstFewSharesFinisher;
exports.firstFewShares = firstFewShares;
exports.doFinishers = doFinishers;
exports.addLikersFinisher = addLikersFinisher;
exports.addLikers = addLikers;
exports.addSharedFinisher = addSharedFinisher;
exports.addShared = addShared;
exports.addProxyFinisher = addProxyFinisher;
exports.addProxy = addProxy;
<commit_msg>Remove errant debug logging<commit_after>// lib/finishers.js
//
// Functions for adding extra flags and stream data to API output
//
// Copyright 2012, StatusNet Inc.
//
// 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.

var _ = require("underscore"),
    Step = require("step"),
    ActivityObject = require("../lib/model/activityobject").ActivityObject,
    Edge = require("../lib/model/edge").Edge,
    Proxy = require("../lib/model/proxy").Proxy,
    Favorite = require("../lib/model/favorite").Favorite,
    Share = require("../lib/model/share").Share,
    FilteredStream = require("../lib/filteredstream").FilteredStream,
    filters = require("../lib/filters"),
    URLMaker = require("../lib/urlmaker").URLMaker,
    urlparse = require("url").parse,
    recipientsOnly = filters.recipientsOnly,
    objectRecipientsOnly = filters.objectRecipientsOnly,
    objectPublicOnly = filters.objectPublicOnly,
    publicOnly = filters.publicOnly;

// finisher that adds followed flag to stuff

var addFollowedFinisher = function(req, collection, callback) {

    // Ignore for non-users

    if (!req.principal) {
        callback(null);
        return;
    }

    addFollowed(req.principal, _.pluck(collection.items, "object"), callback);
};

var addFollowed = function(profile, objects, callback) {

    var edgeIDs;

    // Ignore for non-users

    if (!profile) {
        callback(null);
        return;
    }

    edgeIDs = objects.map(function(object) {
        return Edge.id(profile.id, object.id);
    });

    Step(
        function() {
            Edge.readAll(edgeIDs, this);
        },
        function(err, edges) {
            if (err) {
                callback(err);
            } else {
                _.each(objects, function(object, i) {
                    var edgeID = edgeIDs[i];
                    if (!_.has(object, "pump_io")) {
                        object.pump_io = {};
                    }
                    if (_.has(edges, edgeID) && _.isObject(edges[edgeID])) {
                        object.pump_io.followed = true;
                    } else {
                        object.pump_io.followed = false;
                    }
                });
                callback(null);
            }
        }
    );
};

// finisher that adds shared flag to stuff

var addSharedFinisher = function(req, collection, callback) {

    // Ignore for non-users

    if (!req.principal) {
        callback(null);
        return;
    }

    addShared(req.principal, _.pluck(collection.items, "object"), callback);
};

var addShared = function(profile, objects, callback) {

    var shareIDs;

    // Ignore for non-users

    if (!profile) {
        callback(null);
        return;
    }

    shareIDs = objects.map(function(object) {
        return Share.id(profile, object);
    });

    Step(
        function() {
            Share.readAll(shareIDs, this);
        },
        function(err, shares) {
            if (err) {
                callback(err);
            } else {
                _.each(objects, function(object, i) {
                    var shareID = shareIDs[i];
                    if (!_.has(object, "pump_io")) {
                        object.pump_io = {};
                    }
                    if (_.has(shares, shareID) && _.isObject(shares[shareID])) {
                        object.pump_io.shared = true;
                    } else {
                        object.pump_io.shared = false;
                    }
                });
                callback(null);
            }
        }
    );
};

// finisher that adds liked flag to stuff

var addLikedFinisher = function(req, collection, callback) {

    // Ignore for non-users

    if (!req.principal) {
        callback(null);
        return;
    }

    addLiked(req.principal, _.pluck(collection.items, "object"), callback);
};

var addLiked = function(profile, objects, callback) {

    var faveIDs;

    // Ignore for non-users

    if (!profile) {
        callback(null);
        return;
    }

    faveIDs = objects.map(function(object) {
        return Favorite.id(profile.id, object.id);
    });

    Step(
        function() {
            Favorite.readAll(faveIDs, this);
        },
        function(err, faves) {
            if (err) {
                callback(err);
            } else {
                _.each(objects, function(object, i) {
                    var faveID = faveIDs[i];
                    if (_.has(faves, faveID) && _.isObject(faves[faveID])) {
                        object.liked = true;
                    } else {
                        object.liked = false;
                    }
                });
                callback(null);
            }
        }
    );
};

var firstFewRepliesFinisher = function(req, collection, callback) {

    var profile = req.principal,
        objects = _.pluck(collection.items, "object");

    firstFewReplies(profile, objects, callback);
};

var firstFewReplies = function(profile, objs, callback) {

    var getReplies = function(obj, callback) {

        if (!_.has(obj, "replies") ||
            !_.isObject(obj.replies) ||
            (_.has(obj.replies, "totalItems") && obj.replies.totalItems === 0)) {
            callback(null);
            return;
        }

        Step(
            function() {
                obj.getRepliesStream(this);
            },
            function(err, str) {
                var filtered;
                if (err) throw err;
                if (!profile) {
                    filtered = new FilteredStream(str, objectPublicOnly);
                } else {
                    filtered = new FilteredStream(str, objectRecipientsOnly(profile));
                }
                filtered.getObjects(0, 4, this);
            },
            function(err, refs) {
                var group = this.group();
                if (err) throw err;
                _.each(refs, function(ref) {
                    ActivityObject.getObject(ref.objectType, ref.id, group());
                });
            },
            function(err, objs) {
                if (err) {
                    callback(err);
                } else {
                    obj.replies.items = objs;
                    _.each(obj.replies.items, function(item) {
                        item.sanitize();
                    });
                    callback(null);
                }
            }
        );
    };

    Step(
        function() {
            var group = this.group();
            _.each(objs, function(obj) {
                getReplies(obj, group());
            });
        },
        callback
    );
};

var firstFewSharesFinisher = function(req, collection, callback) {

    var profile = req.principal,
        objects = _.pluck(collection.items, "object");

    firstFewShares(profile, objects, callback);
};

var firstFewShares = function(profile, objs, callback) {

    var getShares = function(obj, callback) {

        if (!_.has(obj, "shares") ||
            !_.isObject(obj.shares) ||
            (_.has(obj.shares, "totalItems") && obj.shares.totalItems === 0)) {
            callback(null);
            return;
        }

        Step(
            function() {
                obj.getSharesStream(this);
            },
            function(err, str) {
                if (err) throw err;
                str.getObjects(0, 4, this);
            },
            function(err, refs) {
                var group = this.group();
                if (err) throw err;
                _.each(refs, function(ref) {
                    ActivityObject.getObject(ref.objectType, ref.id, group());
                });
            },
            function(err, objs) {
                if (err) {
                    callback(err);
                } else {
                    obj.shares.items = objs;
                    _.each(obj.shares.items, function(item) {
                        item.sanitize();
                    });
                    callback(null);
                }
            }
        );
    };

    Step(
        function() {
            var group = this.group();
            _.each(objs, function(obj) {
                getShares(obj, group());
            });
        },
        callback
    );
};

// finisher that adds followed flag to stuff

var addLikersFinisher = function(req, collection, callback) {

    // Ignore for non-users

    addLikers(req.principal,
              _.pluck(collection.items, "object"),
              callback);
};

var addLikers = function(profile, objects, callback) {

    var liked = _.filter(objects, function(object) {
        return _.has(object, "likes") &&
            _.isObject(object.likes) &&
            _.has(object.likes, "totalItems") &&
            _.isNumber(object.likes.totalItems) &&
            object.likes.totalItems > 0;
    });

    Step(
        function() {
            var group = this.group();

            _.each(liked, function(object) {
                object.getFavoriters(0, 4, group());
            });
        },
        function(err, likers) {
            if (err) {
                callback(err);
            } else {
                _.each(liked, function(object, i) {
                    object.likes.items = likers[i];
                });
                callback(null);
            }
        }
    );
};

// finisher that adds proxy URLs for remote URLs

var addProxyFinisher = function(req, collection, callback) {

    // Ignore for non-users

    if (!req.principalUser) {
        callback(null);
        return;
    }

    addProxy(collection.items,
             callback);
};

var addProxy = function(activities, callback) {

    var op = ['actor',
              'object',
              'target',
              'generator',
              'provider',
              'context',
              'source'],
        cp = ['members',
              'followers',
              'following',
              'lists',
              'likes',
              'replies',
              'shares'],
        ap = ['to',
              'cc',
              'bto',
              'bcc'],
        objects = [],
        props = [],
        selves = [],
        urls;

    // Get all the objects that are parts of these activities

    _.each(op, function(prop) {
        objects = objects.concat(_.pluck(activities, prop));
    });

    _.each(ap, function(prop) {
        var values = _.pluck(activities, prop);
        _.each(values, function(value) {
            objects = objects.concat(value);
        });
    });

    objects = _.compact(objects);

    // Get all the object properties that we know have urls and are parts of these objects

    props = props.concat(_.pluck(objects, "image"));

    _.each(cp, function(prop) {
        props = props.concat(_.pluck(objects, prop));
    });

    props = _.compact(props);

    urls = _.compact(_.pluck(props, "url"));

    // Get all the self-links

    _.each(objects, function(obj) {
        if (obj.links && obj.links.self && obj.links.self.href) {
            urls.push(obj.links.self.href);
        }
    });

    // Uniquify the whole set of URLs

    urls = _.uniq(urls);

    // Only need proxies for remote URLs

    urls = _.filter(urls, function(url) {
        var parts = urlparse(url);
        return (parts.hostname != URLMaker.hostname);
    });

    Step(
        function() {
            var group = this.group();
            _.each(urls, function(url) {
                Proxy.ensureURL(url, group());
            });
        },
        function(err, proxies) {
            var utp = {};
            if (err) {
                callback(err);
                return;
            }
            _.each(proxies, function(proxy) {
                utp[proxy.url] = proxy;
            });
            _.each(props, function(prop) {
                if (_.has(utp, prop.url)) {
                    if (!prop.pump_io) {
                        prop.pump_io = {};
                    }
                    prop.pump_io.proxyURL = URLMaker.makeURL("/api/proxy/"+utp[prop.url].id);
                }
            });
            _.each(objects, function(obj) {
                if (obj.links && obj.links.self && obj.links.self.href) {
                    if (_.has(utp, obj.links.self.href)) {
                        if (!obj.pump_io) {
                            obj.pump_io = {};
                        }
                        obj.pump_io.proxyURL = URLMaker.makeURL("/api/proxy/"+utp[obj.links.self.href].id);
                    }
                }
            });
            callback(null);
        }
    );
};

var doFinishers = function(finishers) {
    return function(req, collection, callback) {
        Step(
            function() {
                var group = this.group();
                _.each(finishers, function(finisher) {
                    finisher(req, collection, group());
                });
            },
            callback
        );
    };
};

exports.addFollowedFinisher = addFollowedFinisher;
exports.addFollowed = addFollowed;
exports.addLikedFinisher = addLikedFinisher;
exports.addLiked = addLiked;
exports.firstFewRepliesFinisher = firstFewRepliesFinisher;
exports.firstFewReplies = firstFewReplies;
exports.firstFewSharesFinisher = firstFewSharesFinisher;
exports.firstFewShares = firstFewShares;
exports.doFinishers = doFinishers;
exports.addLikersFinisher = addLikersFinisher;
exports.addLikers = addLikers;
exports.addSharedFinisher = addSharedFinisher;
exports.addShared = addShared;
exports.addProxyFinisher = addProxyFinisher;
exports.addProxy = addProxy;
<|endoftext|>


<commit_before>/**
 * This file contains JS functionality required by mforms and is included automatically
 * when required.
 */

// Namespace for the form bits and bobs
M.form = M.form || {};

/**
 * Initialises the show advanced functionality and events.
 * This should only ever happen ONCE per page.
 *
 * @param {YUI} Y
 * @param {object} config
 */
M.form.initShowAdvanced = function(Y, config) {
    if (M.form.showAdvanced) {
        return M.form.showAdvanced;
    }
    var showAdvanced = function(config) {
        showAdvanced.superclass.constructor.apply(this, arguments);
    }
    showAdvanced.prototype = {
        _advButtons : [],
        _advAreas : [],
        _stateInput : null,
        initializer : function() {
            this._advAreas = Y.all('form .advanced');
            this._advButtons = Y.all('.showadvancedbtn');
            if (this._advButtons.size() > 0) {
                this._advButtons.item(0).get('form').all('input').each(function(n){
                    if (this._stateInput == null && n.getAttribute('name') == 'mform_showadvanced_last') {
                        this._stateInput = n;
                    }
                }, this);
                this._advButtons.on('click', this.switchState, this);
            }
        },
        /**
         * Toggles between showing advanced items and hiding them.
         * Should be fired by an event.
         */
        switchState : function(e) {
            e.preventDefault();
            if (this._stateInput.get('value')=='1') {
                this._stateInput.set('value', '0');
                this._advButtons.setAttribute('value', M.str.form.showadvanced);
                this._advAreas.addClass('hide');
            } else {
                this._stateInput.set('value', '1');
                this._advButtons.setAttribute('value', M.str.form.hideadvanced);
                this._advAreas.removeClass('hide');
            }
        }
    }
    // Extend it with the YUI widget fw.
    Y.extend(showAdvanced, Y.Base, showAdvanced.prototype, {
        NAME : 'mform-showAdvanced'
    })
    M.form.showAdvanced = new showAdvanced(config);
    return M.form.showAdvanced;
}

/**
 * Initialises a manager for a forms dependencies.
 * This should happen once per form.
 */
M.form.initFormDependencies = function(Y, formid, dependencies) {

    // If the dependencies isn't an array or object we don't want to
    // know about it
    if (!Y.Lang.isArray(dependencies) && !Y.Lang.isObject(dependencies)) {
        return false;
    }

    /**
     * Fixes an issue with YUI's processing method of form.elements property
     * in Internet Explorer.
     *     http://yuilibrary.com/projects/yui3/ticket/2528030
     */
    Y.Node.ATTRS.elements = {
        getter: function() {
            return Y.all(new Y.Array(this._node.elements, 0, true));
        }
    };

    // Define the dependency manager if it hasn't already been defined.
    M.form.dependencyManager = M.form.dependencyManager || (function(){
        var dependencyManager = function(config) {
            dependencyManager.superclass.constructor.apply(this, arguments);
        }
        dependencyManager.prototype = {
            _form : null,
            _depElements : [],
            _nameCollections : [],
            initializer : function(config) {
                var i = 0, nodeName;
                this._form = Y.one('#'+formid);
                for (i in dependencies) {
                    this._depElements[i] = this.elementsByName(i);
                    if (this._depElements[i].size() == 0) {
                        continue;
                    }
                    this._depElements[i].each(function(node){
                        nodeName = node.get('nodeName').toUpperCase();
                        if (nodeName == 'INPUT') {
                            if (node.getAttribute('type').match(/^(button|submit|radio|checkbox)$/)) {
                                node.on('click', this.checkDependencies, this);
                            } else {
                                node.on('blur', this.checkDependencies, this);
                            }
                            node.on('change', this.checkDependencies, this);
                        } else if (nodeName == 'SELECT') {
                            node.on('change', this.checkDependencies, this);
                        } else {
                            node.on('click', this.checkDependencies, this);
                            node.on('blur', this.checkDependencies, this);
                            node.on('change', this.checkDependencies, this);
                        }
                    }, this);
                }
                this._form.get('elements').each(function(input){
                    if (input.getAttribute('type')=='reset') {
                        input.on('click', function(){
                            this._form.reset();
                            this.checkDependencies();
                        }, this);
                    }
                }, this);

                return this.checkDependencies(null);
            },
            /**
             * Gets all elements in the form by thier name and returns
             * a YUI NodeList
             * @return Y.NodeList
             */
            elementsByName : function(name) {
                if (!this._nameCollections[name]) {
                    var elements = [];
                    this._form.get('elements').each(function(){
                        if (this.getAttribute('name') == name) {
                            elements.push(this);
                        }
                    })
                    this._nameCollections[name] = new Y.NodeList(elements);
                }
                return this._nameCollections[name];
            },
            /**
             * Checks the dependencies the form has an makes any changes to the
             * form that are required.
             *
             * Changes are made by functions title _dependency_{dependencytype}
             * and more can easily be introduced by defining further functions.
             */
            checkDependencies : function(e) {
                var tolock = [],
                    tohide = [],
                    dependon, condition, value,
                    lock, hide, checkfunction, result;
                for (dependon in dependencies) {
                    if (this._depElements[dependon].size() == 0) {
                        continue;
                    }
                    for (condition in dependencies[dependon]) {
                        for (value in dependencies[dependon][condition]) {
                            lock = false;
                            hide = false;
                            checkfunction = '_dependency_'+condition;
                            if (Y.Lang.isFunction(this[checkfunction])) {
                                result = this[checkfunction].apply(this, [this._depElements[dependon], value]);
                            } else {
                                result = this._dependency_default(this._depElements[dependon], value);
                            }
                            lock = result.lock || false;
                            hide = result.hide || false;
                            for (var ei in dependencies[dependon][condition][value]) {
                                var eltolock = dependencies[dependon][condition][value][ei];
                                if (hide) {
                                    tohide[eltolock] = true;
                                }
                                if (tolock[eltolock] != null) {
                                    tolock[eltolock] = lock || tolock[eltolock];
                                } else {
                                    tolock[eltolock] = lock;
                                }
                            }
                        }
                    }
                }
                for (var el in tolock) {
                    this._disableElement(el, tolock[el]);
                    if (tohide.propertyIsEnumerable(el)) {
                        this._hideElement(el, tohide[el]);
                    }
                }
                return true;
            },
            /**
             * Disabled all form elements with the given name
             */
            _disableElement : function(name, disabled) {
                var els = this.elementsByName(name);
                els.each(function(){
                    if (disabled) {
                        this.setAttribute('disabled', 'disabled');
                    } else {
                        this.removeAttribute('disabled');
                    }
                })
            },
            /**
             * Hides all elements with the given name.
             */
            _hideElement : function(name, hidden) {
                var els = this.elementsByName(name);
                els.each(function(){
                    var e = els.ancestor('.fitem');
                    if (e) {
                        e.setStyles({
                            display : (hidden)?'none':''
                        })
                    }
                });
            },
            _dependency_notchecked : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || !this.get('checked');
                });
                return {
                    lock : lock,
                    hide : false
                }
            },
            _dependency_checked : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || this.get('checked');
                });
                return {
                    lock : lock,
                    hide : false
                }
            },
            _dependency_noitemselected : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || this.get('selectedIndex') == -1;
                });
                return {
                    lock : lock,
                    hide : false
                }
            },
            _dependency_eq : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || this.get('value') == value;
                });
                return {
                    lock : lock,
                    hide : false
                }
            },
            _dependency_hide : function(elements, value) {
                return {
                    lock : false,
                    hide : true
                }
            },
            _dependency_default : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || this.get('value') != value;
                });
                return {
                    lock : lock,
                    hide : false
                }
            }
        }
        Y.extend(dependencyManager, Y.Base, dependencyManager.prototype, {
            NAME : 'mform-dependency-manager'
        });

        return dependencyManager;
    })();

    return new M.form.dependencyManager();
}<commit_msg>forms MDL-24051 Fixed regression in IE + YUI<commit_after>/**
 * This file contains JS functionality required by mforms and is included automatically
 * when required.
 */

// Namespace for the form bits and bobs
M.form = M.form || {};

/**
 * Initialises the show advanced functionality and events.
 * This should only ever happen ONCE per page.
 *
 * @param {YUI} Y
 * @param {object} config
 */
M.form.initShowAdvanced = function(Y, config) {
    if (M.form.showAdvanced) {
        return M.form.showAdvanced;
    }
    var showAdvanced = function(config) {
        showAdvanced.superclass.constructor.apply(this, arguments);
    }
    showAdvanced.prototype = {
        _advButtons : [],
        _advAreas : [],
        _stateInput : null,
        initializer : function() {
            this._advAreas = Y.all('form .advanced');
            this._advButtons = Y.all('.showadvancedbtn');
            if (this._advButtons.size() > 0) {
                this._stateInput = new Y.NodeList(document.getElementsByName('mform_showadvanced_last'));
                this._advButtons.on('click', this.switchState, this);
            }
        },
        /**
         * Toggles between showing advanced items and hiding them.
         * Should be fired by an event.
         */
        switchState : function(e) {
            e.preventDefault();
            if (this._stateInput.get('value')=='1') {
                this._stateInput.set('value', '0');
                this._advButtons.setAttribute('value', M.str.form.showadvanced);
                this._advAreas.addClass('hide');
            } else {
                this._stateInput.set('value', '1');
                this._advButtons.setAttribute('value', M.str.form.hideadvanced);
                this._advAreas.removeClass('hide');
            }
        }
    }
    // Extend it with the YUI widget fw.
    Y.extend(showAdvanced, Y.Base, showAdvanced.prototype, {
        NAME : 'mform-showAdvanced'
    })
    M.form.showAdvanced = new showAdvanced(config);
    return M.form.showAdvanced;
}

/**
 * Initialises a manager for a forms dependencies.
 * This should happen once per form.
 */
M.form.initFormDependencies = function(Y, formid, dependencies) {

    // If the dependencies isn't an array or object we don't want to
    // know about it
    if (!Y.Lang.isArray(dependencies) && !Y.Lang.isObject(dependencies)) {
        return false;
    }

    /**
     * Fixes an issue with YUI's processing method of form.elements property
     * in Internet Explorer.
     *     http://yuilibrary.com/projects/yui3/ticket/2528030
     */
    Y.Node.ATTRS.elements = {
        getter: function() {
            return Y.all(new Y.Array(this._node.elements, 0, true));
        }
    };

    // Define the dependency manager if it hasn't already been defined.
    M.form.dependencyManager = M.form.dependencyManager || (function(){
        var dependencyManager = function(config) {
            dependencyManager.superclass.constructor.apply(this, arguments);
        }
        dependencyManager.prototype = {
            _form : null,
            _depElements : [],
            _nameCollections : [],
            initializer : function(config) {
                var i = 0, nodeName;
                this._form = Y.one('#'+formid);
                for (i in dependencies) {
                    this._depElements[i] = this.elementsByName(i);
                    if (this._depElements[i].size() == 0) {
                        continue;
                    }
                    this._depElements[i].each(function(node){
                        nodeName = node.get('nodeName').toUpperCase();
                        if (nodeName == 'INPUT') {
                            if (node.getAttribute('type').match(/^(button|submit|radio|checkbox)$/)) {
                                node.on('click', this.checkDependencies, this);
                            } else {
                                node.on('blur', this.checkDependencies, this);
                            }
                            node.on('change', this.checkDependencies, this);
                        } else if (nodeName == 'SELECT') {
                            node.on('change', this.checkDependencies, this);
                        } else {
                            node.on('click', this.checkDependencies, this);
                            node.on('blur', this.checkDependencies, this);
                            node.on('change', this.checkDependencies, this);
                        }
                    }, this);
                }
                this._form.get('elements').each(function(input){
                    if (input.getAttribute('type')=='reset') {
                        input.on('click', function(){
                            this._form.reset();
                            this.checkDependencies();
                        }, this);
                    }
                }, this);

                return this.checkDependencies(null);
            },
            /**
             * Gets all elements in the form by thier name and returns
             * a YUI NodeList
             * @return Y.NodeList
             */
            elementsByName : function(name) {
                if (!this._nameCollections[name]) {
                    var elements = [];
                    this._form.get('elements').each(function(){
                        if (this.getAttribute('name') == name) {
                            elements.push(this);
                        }
                    })
                    this._nameCollections[name] = new Y.NodeList(elements);
                }
                return this._nameCollections[name];
            },
            /**
             * Checks the dependencies the form has an makes any changes to the
             * form that are required.
             *
             * Changes are made by functions title _dependency_{dependencytype}
             * and more can easily be introduced by defining further functions.
             */
            checkDependencies : function(e) {
                var tolock = [],
                    tohide = [],
                    dependon, condition, value,
                    lock, hide, checkfunction, result;
                for (dependon in dependencies) {
                    if (this._depElements[dependon].size() == 0) {
                        continue;
                    }
                    for (condition in dependencies[dependon]) {
                        for (value in dependencies[dependon][condition]) {
                            lock = false;
                            hide = false;
                            checkfunction = '_dependency_'+condition;
                            if (Y.Lang.isFunction(this[checkfunction])) {
                                result = this[checkfunction].apply(this, [this._depElements[dependon], value]);
                            } else {
                                result = this._dependency_default(this._depElements[dependon], value);
                            }
                            lock = result.lock || false;
                            hide = result.hide || false;
                            for (var ei in dependencies[dependon][condition][value]) {
                                var eltolock = dependencies[dependon][condition][value][ei];
                                if (hide) {
                                    tohide[eltolock] = true;
                                }
                                if (tolock[eltolock] != null) {
                                    tolock[eltolock] = lock || tolock[eltolock];
                                } else {
                                    tolock[eltolock] = lock;
                                }
                            }
                        }
                    }
                }
                for (var el in tolock) {
                    this._disableElement(el, tolock[el]);
                    if (tohide.propertyIsEnumerable(el)) {
                        this._hideElement(el, tohide[el]);
                    }
                }
                return true;
            },
            /**
             * Disabled all form elements with the given name
             */
            _disableElement : function(name, disabled) {
                var els = this.elementsByName(name);
                els.each(function(){
                    if (disabled) {
                        this.setAttribute('disabled', 'disabled');
                    } else {
                        this.removeAttribute('disabled');
                    }
                })
            },
            /**
             * Hides all elements with the given name.
             */
            _hideElement : function(name, hidden) {
                var els = this.elementsByName(name);
                els.each(function(){
                    var e = els.ancestor('.fitem');
                    if (e) {
                        e.setStyles({
                            display : (hidden)?'none':''
                        })
                    }
                });
            },
            _dependency_notchecked : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || !this.get('checked');
                });
                return {
                    lock : lock,
                    hide : false
                }
            },
            _dependency_checked : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || this.get('checked');
                });
                return {
                    lock : lock,
                    hide : false
                }
            },
            _dependency_noitemselected : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || this.get('selectedIndex') == -1;
                });
                return {
                    lock : lock,
                    hide : false
                }
            },
            _dependency_eq : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || this.get('value') == value;
                });
                return {
                    lock : lock,
                    hide : false
                }
            },
            _dependency_hide : function(elements, value) {
                return {
                    lock : false,
                    hide : true
                }
            },
            _dependency_default : function(elements, value) {
                var lock = false;
                elements.each(function(){
                    lock = lock || this.get('value') != value;
                });
                return {
                    lock : lock,
                    hide : false
                }
            }
        }
        Y.extend(dependencyManager, Y.Base, dependencyManager.prototype, {
            NAME : 'mform-dependency-manager'
        });

        return dependencyManager;
    })();

    return new M.form.dependencyManager();
}<|endoftext|>


<commit_before>// Core modules
var fs = require('fs');
var path = require('path');

// Generate the root folder of snippets
var snippetsRoot = path.join(process.env.HOME, '.sheets');

// Logging
var helper = require('./helper');

// Function to create a snippet with the given name
module.exports.createSnippet = function (snippetName) {
    // Generate fileName
    var fileName = path.join(snippetsRoot, snippetName);

    // Open up vim for creating the snippet and then wait for close
    var editor = require('child_process').spawn(process.env.EDITOR, [fileName], {stdio: 'inherit'});
    editor.on('exit', process.exit);
};

// Function to list snippets from the snips directory
module.exports.listSnippets = function() {
    fs.readdir(snippetsRoot, function (err, items) {
        if (err) {
            helper.error('Filesystem error');
            process.exit(1);
        }

        // List all the snippets
        items.forEach(function(item) {
            console.log(item);
        });
    });
};

// Copy a snippet to the clipboard
module.exports.copySnippet = function (snippetName) {
    // Generate fileName
    var fileName = path.join(snippetsRoot, snippetName);

    // Check if there exists a snippet with the given name
    if (!fs.existsSync(fileName)) {
        process.exit(0);
    }

    // Get the text from the file
    var text = fs.readFileSync(fileName).toString();

    // Copy the text to clipboard
    require('copy-paste').copy(text, function() { process.exit(0); });
};

// Fuzzy search for snippet names
module.exports.searchSnippets = function(searchTerm) {
    // Get the names of snippets
    fs.readdir(snippetsRoot, function (err, items) {
        if (err) {
            helper.error('Filesystem error');
            process.exit(1);
        }

        // Search all the snippets for the search term
        var results = require('fuzzy').filter(searchTerm, items);
        results.map(function(match) { console.log(match.string); });
    });
};
<commit_msg>use snips folder for snippets<commit_after>// Core modules
var fs = require('fs');
var path = require('path');

// Generate the root folder of snippets
var snippetsRoot = path.join(process.env.HOME, '.snips');

// Logging
var helper = require('./helper');

// Function to create a snippet with the given name
module.exports.createSnippet = function (snippetName) {
    // Generate fileName
    var fileName = path.join(snippetsRoot, snippetName);

    // Open up vim for creating the snippet and then wait for close
    var editor = require('child_process').spawn(process.env.EDITOR, [fileName], {stdio: 'inherit'});
    editor.on('exit', process.exit);
};

// Function to list snippets from the snips directory
module.exports.listSnippets = function() {
    fs.readdir(snippetsRoot, function (err, items) {
        if (err) {
            helper.error('Filesystem error');
            process.exit(1);
        }

        // List all the snippets
        items.forEach(function(item) {
            console.log(item);
        });
    });
};

// Copy a snippet to the clipboard
module.exports.copySnippet = function (snippetName) {
    // Generate fileName
    var fileName = path.join(snippetsRoot, snippetName);

    // Check if there exists a snippet with the given name
    if (!fs.existsSync(fileName)) {
        process.exit(0);
    }

    // Get the text from the file
    var text = fs.readFileSync(fileName).toString();

    // Copy the text to clipboard
    require('copy-paste').copy(text, function() { process.exit(0); });
};

// Fuzzy search for snippet names
module.exports.searchSnippets = function(searchTerm) {
    // Get the names of snippets
    fs.readdir(snippetsRoot, function (err, items) {
        if (err) {
            helper.error('Filesystem error');
            process.exit(1);
        }

        // Search all the snippets for the search term
        var results = require('fuzzy').filter(searchTerm, items);
        results.map(function(match) { console.log(match.string); });
    });
};
<|endoftext|>


<commit_before>(function(c){function a(b,d){if({}.hasOwnProperty.call(a.cache,b))return a.cache[b];var e=a.resolve(b);if(!e)throw new Error('Failed to resolve module '+b);var c={id:b,require:a,filename:b,exports:{},loaded:!1,parent:d,children:[]};d&&d.children.push(c);var f=b.slice(0,b.lastIndexOf('/')+1);return a.cache[b]=c.exports,e.call(c.exports,c,c.exports,f,b),c.loaded=!0,a.cache[b]=c.exports}a.modules={},a.cache={},a.resolve=function(b){return{}.hasOwnProperty.call(a.modules,b)?a.modules[b]:void 0},a.define=function(b,c){a.modules[b]=c};var b=function(a){return a='/',{title:'browser',version:'v0.10.26',browser:!0,env:{},argv:[],nextTick:c.setImmediate||function(a){setTimeout(a,0)},cwd:function(){return a},chdir:function(b){a=b}}}();a.define('/gif.coffee',function(d,m,l,k){function g(a,b){return{}.hasOwnProperty.call(a,b)}function j(d,b){for(var a=0,c=b.length;a<c;++a)if(a in b&&b[a]===d)return!0;return!1}function i(a,b){function d(){this.constructor=a}for(var c in b)g(b,c)&&(a[c]=b[c]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a}var h,c,f,b,e;f=a('events',d).EventEmitter,h=a('/browser.coffee',d),e=function(d){function a(d){var a,b;this.running=!1,this.options={},this.frames=[],this.freeWorkers=[],this.activeWorkers=[],this.setOptions(d);for(a in c)b=c[a],null!=this.options[a]?this.options[a]:this.options[a]=b}return i(a,d),c={workerScript:'lib/gif_maker.worker.js',workers:2,repeat:0,background:'#fff',quality:10,width:null,height:null,transparent:null},b={delay:500,copy:!1},a.prototype.setOption=function(a,b){return this.options[a]=b,null!=this._canvas&&(a==='width'||a==='height')?this._canvas[a]=b:void 0},a.prototype.setOptions=function(b){var a,c;return function(d){for(a in b){if(!g(b,a))continue;c=b[a],d.push(this.setOption(a,c))}return d}.call(this,[])},a.prototype.addFrame=function(a,d){var c,e;null==d&&(d={}),c={},c.transparent=this.options.transparent;for(e in b)c[e]=d[e]||b[e];if(null!=this.options.width||this.setOption('width',a.width),null!=this.options.height||this.setOption('height',a.height),'undefined'!==typeof ImageData&&null!=ImageData&&a instanceof ImageData)c.data=a.data;else if('undefined'!==typeof CanvasRenderingContext2D&&null!=CanvasRenderingContext2D&&a instanceof CanvasRenderingContext2D||'undefined'!==typeof WebGLRenderingContext&&null!=WebGLRenderingContext&&a instanceof WebGLRenderingContext)d.copy?c.data=this.getContextData(a):c.context=a;else if(null!=a.childNodes)d.copy?c.data=this.getImageData(a):c.image=a;else throw new Error('Invalid image');return this.frames.push(c)},a.prototype.render=function(){var d,a;if(this.running)throw new Error('Already running');if(!(null!=this.options.width&&null!=this.options.height))throw new Error('Width and height must be set prior to rendering');this.running=!0,this.nextFrame=0,this.finishedFrames=0,this.imageParts=function(c){for(var b=function(){var b;b=[];for(var a=0;0<=this.frames.length?a<this.frames.length:a>this.frames.length;0<=this.frames.length?++a:--a)b.push(a);return b}.apply(this,arguments),a=0,e=b.length;a<e;++a)d=b[a],c.push(null);return c}.call(this,[]),a=this.spawnWorkers();for(var c=function(){var c;c=[];for(var b=0;0<=a?b<a:b>a;0<=a?++b:--b)c.push(b);return c}.apply(this,arguments),b=0,e=c.length;b<e;++b)d=c[b],this.renderNextFrame();return this.emit('start'),this.emit('progress',0)},a.prototype.abort=function(){var a;while(!0){if(a=this.activeWorkers.shift(),!(null!=a))break;console.log('killing active worker'),a.terminate()}return this.running=!1,this.emit('abort')},a.prototype.spawnWorkers=function(){var a;return a=Math.min(this.options.workers,this.frames.length),function(){var c;c=[];for(var b=this.freeWorkers.length;this.freeWorkers.length<=a?b<a:b>a;this.freeWorkers.length<=a?++b:--b)c.push(b);return c}.apply(this,arguments).forEach(function(a){return function(c){var b;return console.log('spawning worker '+c),b=new Worker(a.options.workerScript),b.onmessage=function(a){return function(c){return a.activeWorkers.splice(a.activeWorkers.indexOf(b),1),a.freeWorkers.push(b),a.frameFinished(c.data)}}(a),a.freeWorkers.push(b)}}(this)),a},a.prototype.frameFinished=function(a){return console.log('frame '+a.index+' finished - '+this.activeWorkers.length+' active'),this.finishedFrames++,this.emit('progress',this.finishedFrames/this.frames.length),this.imageParts[a.index]=a,j(null,this.imageParts)?this.renderNextFrame():this.finishRendering()},a.prototype.finishRendering=function(){var e,a,k,m,b,d,h;b=0;for(var f=0,j=this.imageParts.length;f<j;++f)a=this.imageParts[f],b+=(a.data.length-1)*a.pageSize+a.cursor;b+=a.pageSize-a.cursor,console.log('rendering finished - filesize '+Math.round(b/1e3)+'kb'),e=new Uint8Array(b),d=0;for(var g=0,l=this.imageParts.length;g<l;++g){a=this.imageParts[g];for(var c=0,i=a.data.length;c<i;++c)h=a.data[c],k=c,e.set(h,d),k===a.data.length-1?d+=a.cursor:d+=a.pageSize}return m=new Blob([e],{type:'image/gif'}),this.emit('finished',m,e)},a.prototype.renderNextFrame=function(){var c,a,b;if(this.freeWorkers.length===0)throw new Error('No free workers');return this.nextFrame>=this.frames.length?void 0:(c=this.frames[this.nextFrame++],b=this.freeWorkers.shift(),a=this.getTask(c),console.log('starting frame '+(a.index+1)+' of '+this.frames.length),this.activeWorkers.push(b),b.postMessage(a))},a.prototype.getContextData=function(a){return a.getImageData(0,0,this.options.width,this.options.height).data},a.prototype.getImageData=function(b){var a;return null!=this._canvas||(this._canvas=document.createElement('canvas'),this._canvas.width=this.options.width,this._canvas.height=this.options.height),a=this._canvas.getContext('2d'),a.setFill=this.options.background,a.fillRect(0,0,this.options.width,this.options.height),a.drawImage(b,0,0),this.getContextData(a)},a.prototype.getTask=function(a){var c,b;if(c=this.frames.indexOf(a),b={index:c,last:c===this.frames.length-1,delay:a.delay,transparent:a.transparent,width:this.options.width,height:this.options.height,quality:this.options.quality,repeat:this.options.repeat,canTransfer:h.name==='chrome'},null!=a.data)b.data=a.data;else if(null!=a.context)b.data=this.getContextData(a.context);else if(null!=a.image)b.data=this.getImageData(a.image);else throw new Error('Invalid frame');return b},a}(f),d.exports=e}),a.define('/browser.coffee',function(f,g,h,i){var a,d,e,c,b;c=navigator.userAgent.toLowerCase(),e=navigator.platform.toLowerCase(),b=c.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,'unknown',0],d=b[1]==='ie'&&document.documentMode,a={name:b[1]==='version'?b[3]:b[1],version:d||parseFloat(b[1]==='opera'&&b[4]?b[4]:b[2]),platform:{name:c.match(/ip(?:ad|od|hone)/)?'ios':(c.match(/(?:webos|android)/)||e.match(/mac|win|linux/)||['other'])[0]}},a[a.name]=!0,a[a.name+parseInt(a.version,10)]=!0,a.platform[a.platform.name]=!0,f.exports=a}),a.define('events',function(f,e,g,h){b.EventEmitter||(b.EventEmitter=function(){});var a=e.EventEmitter=b.EventEmitter,c=typeof Array.isArray==='function'?Array.isArray:function(a){return Object.prototype.toString.call(a)==='[object Array]'},d=10;a.prototype.setMaxListeners=function(a){this._events||(this._events={}),this._events.maxListeners=a},a.prototype.emit=function(f){if(f==='error'&&(!(this._events&&this._events.error)||c(this._events.error)&&!this._events.error.length))throw arguments[1]instanceof Error?arguments[1]:new Error("Uncaught, unspecified 'error' event.");if(!this._events)return!1;var a=this._events[f];if(!a)return!1;if(!(typeof a=='function'))if(c(a)){var b=Array.prototype.slice.call(arguments,1),e=a.slice();for(var d=0,g=e.length;d<g;d++)e[d].apply(this,b);return!0}else return!1;switch(arguments.length){case 1:a.call(this);break;case 2:a.call(this,arguments[1]);break;case 3:a.call(this,arguments[1],arguments[2]);break;default:var b=Array.prototype.slice.call(arguments,1);a.apply(this,b)}return!0},a.prototype.addListener=function(a,b){if('function'!==typeof b)throw new Error('addListener only takes instances of Function');if(this._events||(this._events={}),this.emit('newListener',a,b),!this._events[a])this._events[a]=b;else if(c(this._events[a])){if(!this._events[a].warned){var e;this._events.maxListeners!==undefined?e=this._events.maxListeners:e=d,e&&e>0&&this._events[a].length>e&&(this._events[a].warned=!0,console.error('(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.',this._events[a].length),console.trace())}this._events[a].push(b)}else this._events[a]=[this._events[a],b];return this},a.prototype.on=a.prototype.addListener,a.prototype.once=function(b,c){var a=this;return a.on(b,function d(){a.removeListener(b,d),c.apply(this,arguments)}),this},a.prototype.removeListener=function(a,d){if('function'!==typeof d)throw new Error('removeListener only takes instances of Function');if(!(this._events&&this._events[a]))return this;var b=this._events[a];if(c(b)){var e=b.indexOf(d);if(e<0)return this;b.splice(e,1),b.length==0&&delete this._events[a]}else this._events[a]===d&&delete this._events[a];return this},a.prototype.removeAllListeners=function(a){return a&&this._events&&this._events[a]&&(this._events[a]=null),this},a.prototype.listeners=function(a){return this._events||(this._events={}),this._events[a]||(this._events[a]=[]),c(this._events[a])||(this._events[a]=[this._events[a]]),this._events[a]}}),c.GIF=a('/gif.coffee')}.call(this,this))
// gif.js 0.1.6 - https://github.com/jnordberg/gif.js
<commit_msg>remove console.log<commit_after>(function(c){function a(b,d){if({}.hasOwnProperty.call(a.cache,b))return a.cache[b];var e=a.resolve(b);if(!e)throw new Error('Failed to resolve module '+b);var c={id:b,require:a,filename:b,exports:{},loaded:!1,parent:d,children:[]};d&&d.children.push(c);var f=b.slice(0,b.lastIndexOf('/')+1);return a.cache[b]=c.exports,e.call(c.exports,c,c.exports,f,b),c.loaded=!0,a.cache[b]=c.exports}a.modules={},a.cache={},a.resolve=function(b){return{}.hasOwnProperty.call(a.modules,b)?a.modules[b]:void 0},a.define=function(b,c){a.modules[b]=c};var b=function(a){return a='/',{title:'browser',version:'v0.10.26',browser:!0,env:{},argv:[],nextTick:c.setImmediate||function(a){setTimeout(a,0)},cwd:function(){return a},chdir:function(b){a=b}}}();a.define('/gif.coffee',function(d,m,l,k){function g(a,b){return{}.hasOwnProperty.call(a,b)}function j(d,b){for(var a=0,c=b.length;a<c;++a)if(a in b&&b[a]===d)return!0;return!1}function i(a,b){function d(){this.constructor=a}for(var c in b)g(b,c)&&(a[c]=b[c]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a}var h,c,f,b,e;f=a('events',d).EventEmitter,h=a('/browser.coffee',d),e=function(d){function a(d){var a,b;this.running=!1,this.options={},this.frames=[],this.freeWorkers=[],this.activeWorkers=[],this.setOptions(d);for(a in c)b=c[a],null!=this.options[a]?this.options[a]:this.options[a]=b}return i(a,d),c={workerScript:'lib/gif_maker.worker.js',workers:2,repeat:0,background:'#fff',quality:10,width:null,height:null,transparent:null},b={delay:500,copy:!1},a.prototype.setOption=function(a,b){return this.options[a]=b,null!=this._canvas&&(a==='width'||a==='height')?this._canvas[a]=b:void 0},a.prototype.setOptions=function(b){var a,c;return function(d){for(a in b){if(!g(b,a))continue;c=b[a],d.push(this.setOption(a,c))}return d}.call(this,[])},a.prototype.addFrame=function(a,d){var c,e;null==d&&(d={}),c={},c.transparent=this.options.transparent;for(e in b)c[e]=d[e]||b[e];if(null!=this.options.width||this.setOption('width',a.width),null!=this.options.height||this.setOption('height',a.height),'undefined'!==typeof ImageData&&null!=ImageData&&a instanceof ImageData)c.data=a.data;else if('undefined'!==typeof CanvasRenderingContext2D&&null!=CanvasRenderingContext2D&&a instanceof CanvasRenderingContext2D||'undefined'!==typeof WebGLRenderingContext&&null!=WebGLRenderingContext&&a instanceof WebGLRenderingContext)d.copy?c.data=this.getContextData(a):c.context=a;else if(null!=a.childNodes)d.copy?c.data=this.getImageData(a):c.image=a;else throw new Error('Invalid image');return this.frames.push(c)},a.prototype.render=function(){var d,a;if(this.running)throw new Error('Already running');if(!(null!=this.options.width&&null!=this.options.height))throw new Error('Width and height must be set prior to rendering');this.running=!0,this.nextFrame=0,this.finishedFrames=0,this.imageParts=function(c){for(var b=function(){var b;b=[];for(var a=0;0<=this.frames.length?a<this.frames.length:a>this.frames.length;0<=this.frames.length?++a:--a)b.push(a);return b}.apply(this,arguments),a=0,e=b.length;a<e;++a)d=b[a],c.push(null);return c}.call(this,[]),a=this.spawnWorkers();for(var c=function(){var c;c=[];for(var b=0;0<=a?b<a:b>a;0<=a?++b:--b)c.push(b);return c}.apply(this,arguments),b=0,e=c.length;b<e;++b)d=c[b],this.renderNextFrame();return this.emit('start'),this.emit('progress',0)},a.prototype.abort=function(){var a;while(!0){if(a=this.activeWorkers.shift(),!(null!=a))break;a.terminate()}return this.running=!1,this.emit('abort')},a.prototype.spawnWorkers=function(){var a;return a=Math.min(this.options.workers,this.frames.length),function(){var c;c=[];for(var b=this.freeWorkers.length;this.freeWorkers.length<=a?b<a:b>a;this.freeWorkers.length<=a?++b:--b)c.push(b);return c}.apply(this,arguments).forEach(function(a){return function(c){var b;return b=new Worker(a.options.workerScript),b.onmessage=function(a){return function(c){return a.activeWorkers.splice(a.activeWorkers.indexOf(b),1),a.freeWorkers.push(b),a.frameFinished(c.data)}}(a),a.freeWorkers.push(b)}}(this)),a},a.prototype.frameFinished=function(a){return this.finishedFrames++,this.emit('progress',this.finishedFrames/this.frames.length),this.imageParts[a.index]=a,j(null,this.imageParts)?this.renderNextFrame():this.finishRendering()},a.prototype.finishRendering=function(){var e,a,k,m,b,d,h;b=0;for(var f=0,j=this.imageParts.length;f<j;++f)a=this.imageParts[f],b+=(a.data.length-1)*a.pageSize+a.cursor;b+=a.pageSize-a.cursor,e=new Uint8Array(b),d=0;for(var g=0,l=this.imageParts.length;g<l;++g){a=this.imageParts[g];for(var c=0,i=a.data.length;c<i;++c)h=a.data[c],k=c,e.set(h,d),k===a.data.length-1?d+=a.cursor:d+=a.pageSize}return m=new Blob([e],{type:'image/gif'}),this.emit('finished',m,e)},a.prototype.renderNextFrame=function(){var c,a,b;if(this.freeWorkers.length===0)throw new Error('No free workers');return this.nextFrame>=this.frames.length?void 0:(c=this.frames[this.nextFrame++],b=this.freeWorkers.shift(),a=this.getTask(c),this.activeWorkers.push(b),b.postMessage(a))},a.prototype.getContextData=function(a){return a.getImageData(0,0,this.options.width,this.options.height).data},a.prototype.getImageData=function(b){var a;return null!=this._canvas||(this._canvas=document.createElement('canvas'),this._canvas.width=this.options.width,this._canvas.height=this.options.height),a=this._canvas.getContext('2d'),a.setFill=this.options.background,a.fillRect(0,0,this.options.width,this.options.height),a.drawImage(b,0,0),this.getContextData(a)},a.prototype.getTask=function(a){var c,b;if(c=this.frames.indexOf(a),b={index:c,last:c===this.frames.length-1,delay:a.delay,transparent:a.transparent,width:this.options.width,height:this.options.height,quality:this.options.quality,repeat:this.options.repeat,canTransfer:h.name==='chrome'},null!=a.data)b.data=a.data;else if(null!=a.context)b.data=this.getContextData(a.context);else if(null!=a.image)b.data=this.getImageData(a.image);else throw new Error('Invalid frame');return b},a}(f),d.exports=e}),a.define('/browser.coffee',function(f,g,h,i){var a,d,e,c,b;c=navigator.userAgent.toLowerCase(),e=navigator.platform.toLowerCase(),b=c.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,'unknown',0],d=b[1]==='ie'&&document.documentMode,a={name:b[1]==='version'?b[3]:b[1],version:d||parseFloat(b[1]==='opera'&&b[4]?b[4]:b[2]),platform:{name:c.match(/ip(?:ad|od|hone)/)?'ios':(c.match(/(?:webos|android)/)||e.match(/mac|win|linux/)||['other'])[0]}},a[a.name]=!0,a[a.name+parseInt(a.version,10)]=!0,a.platform[a.platform.name]=!0,f.exports=a}),a.define('events',function(f,e,g,h){b.EventEmitter||(b.EventEmitter=function(){});var a=e.EventEmitter=b.EventEmitter,c=typeof Array.isArray==='function'?Array.isArray:function(a){return Object.prototype.toString.call(a)==='[object Array]'},d=10;a.prototype.setMaxListeners=function(a){this._events||(this._events={}),this._events.maxListeners=a},a.prototype.emit=function(f){if(f==='error'&&(!(this._events&&this._events.error)||c(this._events.error)&&!this._events.error.length))throw arguments[1]instanceof Error?arguments[1]:new Error("Uncaught, unspecified 'error' event.");if(!this._events)return!1;var a=this._events[f];if(!a)return!1;if(!(typeof a=='function'))if(c(a)){var b=Array.prototype.slice.call(arguments,1),e=a.slice();for(var d=0,g=e.length;d<g;d++)e[d].apply(this,b);return!0}else return!1;switch(arguments.length){case 1:a.call(this);break;case 2:a.call(this,arguments[1]);break;case 3:a.call(this,arguments[1],arguments[2]);break;default:var b=Array.prototype.slice.call(arguments,1);a.apply(this,b)}return!0},a.prototype.addListener=function(a,b){if('function'!==typeof b)throw new Error('addListener only takes instances of Function');if(this._events||(this._events={}),this.emit('newListener',a,b),!this._events[a])this._events[a]=b;else if(c(this._events[a])){if(!this._events[a].warned){var e;this._events.maxListeners!==undefined?e=this._events.maxListeners:e=d,e&&e>0&&this._events[a].length>e&&(this._events[a].warned=!0,console.error('(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.',this._events[a].length),console.trace())}this._events[a].push(b)}else this._events[a]=[this._events[a],b];return this},a.prototype.on=a.prototype.addListener,a.prototype.once=function(b,c){var a=this;return a.on(b,function d(){a.removeListener(b,d),c.apply(this,arguments)}),this},a.prototype.removeListener=function(a,d){if('function'!==typeof d)throw new Error('removeListener only takes instances of Function');if(!(this._events&&this._events[a]))return this;var b=this._events[a];if(c(b)){var e=b.indexOf(d);if(e<0)return this;b.splice(e,1),b.length==0&&delete this._events[a]}else this._events[a]===d&&delete this._events[a];return this},a.prototype.removeAllListeners=function(a){return a&&this._events&&this._events[a]&&(this._events[a]=null),this},a.prototype.listeners=function(a){return this._events||(this._events={}),this._events[a]||(this._events[a]=[]),c(this._events[a])||(this._events[a]=[this._events[a]]),this._events[a]}}),c.GIF=a('/gif.coffee')}.call(this,this))
// gif.js 0.1.6 - https://github.com/jnordberg/gif.js
<|endoftext|>


<commit_before>const q = require('q')
const _ = require('lodash')
const path = require('path')
const async = require('async')
const cheerio = require('cheerio')
const appDir = (path.resolve(__dirname) + '/').replace('lib/hash/', '')
const mainFile = require(appDir + 'index.js')
const utils = mainFile.utils
/**
 * Function to parse hash html data to JSON
 * @param  {String} hashPage HTML string of the page
 * @return {Promise}         Promise
 */
const getHashData = (hashPage) => {
  var dfd = q.defer()

  const errors = {
    noParam: 'No param was provided',
    parseError: 'Couldn\'t parse html. Check if it is valid'
  }

  const funcArray = [
    (callback) => { // verify params

      if (!hashPage) return callback(errors.noIp)

      callback(null, hashPage)
    },
    (html, callback) => {
      if (callback) {
        const $ = cheerio.load(html)
        const tr = $('div.data>table>tbody>tr')
        var array = []
        var hashData = {
          cores: []
        }
        try {
          hashData.title = $('title').html()
        } catch (e) {
          if (e) return callback(error.parseError)
        }

        tr.each((index, value) => {
          switch (index) {
            case 0:
              break

            case tr.length - 2: // total
              hashData.total = _.compact($(value).find('td').text().split(' '))
              break

            case tr.length - 1: // highest
              hashData.highest = $(value).find('td').text()
              break

            default:
              array[index] = _.compact($(value).find('td').text().split(' '))
              break
          }
        })

        hashData.cores = _.compact(array.map(core => {
          return {
            '2.5s': core[0],
            '60s': core[1],
            '15m': core[2]
          }
        }))

        hashData.total = {
          '2.5s': hashData.total[0],
          '60s': hashData.total[1],
          '15m': hashData.total[2]
        }

        callback(null, hashData)
      }
    }
  ]

  async.waterfall(
    funcArray,
    (err, result) => err ? dfd.reject(err) : dfd.resolve(result)
  )

  return dfd.promise
}

/**
 * Loops through the nods on the config files and get all the hash data
 * @param  {Array} nodes Array of objects with node description
 * @return {Promise}
 */
const getHashDataFromNodes = (nodes) => {
  var dfd = q.defer()

  const errors = {
    noNodes: 'No nodes were provided'
  }

  const funcArray = [
    (callback) => { // verify params
      var nds = _.clone(nodes)
      if (_.isEmpty(nodes)) return callback(errors.noNodes)

      callback(null, nds)
    },
    (nds, callback) => {
      if (callback) {
        var count = 0
        const mNodes = nds.map(node => {
          return new Promise((resolve, reject) => {
            return utils.getPage(node, 'h')
              .then(page => mainFile.hash.getHashData(page))
              .then(hashData => resolve(hashData))
              .catch(err => resolve(err)) // Resolves the error, so the other
                                          // nodes are returned regardledd
          })
        })

        Promise.all(mNodes)
          .then(pages => callback(null, pages))
          .catch(err => console.log(`err`))
      }
    }
  ]

  async.waterfall(
    funcArray,
    (err, result) => err ? dfd.reject(err) : dfd.resolve(result)
  )

  return dfd.promise
}

/**
 * Get total hash sum from nodes
 * @param  {Object} nodes Hash data of nodes
 * @return {Promise}
 */
const getHashSum = (nodes) => {
  var dfd = q.defer()

  const errors = {
    noNodes: 'No nodes were provided'
  }

  const funcArray = [
    (callback) => { // verify params
      var nds = _.clone(nodes)
      if (_.isEmpty(nodes)) return callback(errors.noNodes)

      callback(null, nds)
    },
    (nds, callback) => {
      nodes = _.reduce(nodes, (sum, node) => {
        // Eliminates the undefineds

        if (typeof node !== 'object' || _.isEmpty(node)) return sum

        sum.total = _.mapValues(sum.total, s => s ? s : 0)
        node.total = _.mapValues(node.total, n => n ? n : 0)

        sum.total['2.5s'] = (parseFloat(sum.total['2.5s']) + parseFloat(node.total['2.5s'])).toFixed(2)
        sum.total['60s'] = (parseFloat(sum.total['60s']) + parseFloat(node.total['60s'])).toFixed(2)
        sum.total['15m'] = (parseFloat(sum.total['15m']) + parseFloat(node.total['15m'])).toFixed(2)

        return sum
      }, {total: { '2.5s': 0, '60s': 0, '15m': 0 }})
      callback(null, nodes)
    }
  ]

  async.waterfall(
    funcArray,
    (err, result) => err ? dfd.reject(err) : dfd.resolve(result)
  )

  return dfd.promise
}

module.exports = {
  getHashData: getHashData,
  getHashDataFromNodes: getHashDataFromNodes,
  getHashSum: getHashSum
}
<commit_msg>Return hash sum correctly if a node is offlin<commit_after>const q = require('q')
const _ = require('lodash')
const path = require('path')
const async = require('async')
const cheerio = require('cheerio')
const appDir = (path.resolve(__dirname) + '/').replace('lib/hash/', '')
const mainFile = require(appDir + 'index.js')
const utils = mainFile.utils
/**
 * Function to parse hash html data to JSON
 * @param  {String} hashPage HTML string of the page
 * @return {Promise}         Promise
 */
const getHashData = (hashPage) => {
  var dfd = q.defer()

  const errors = {
    noParam: 'No param was provided',
    parseError: 'Couldn\'t parse html. Check if it is valid'
  }

  const funcArray = [
    (callback) => { // verify params

      if (!hashPage) return callback(errors.noIp)

      callback(null, hashPage)
    },
    (html, callback) => {
      if (callback) {
        const $ = cheerio.load(html)
        const tr = $('div.data>table>tbody>tr')
        var array = []
        var hashData = {
          cores: []
        }
        try {
          hashData.title = $('title').html()
        } catch (e) {
          if (e) return callback(error.parseError)
        }

        tr.each((index, value) => {
          switch (index) {
            case 0:
              break

            case tr.length - 2: // total
              hashData.total = _.compact($(value).find('td').text().split(' '))
              break

            case tr.length - 1: // highest
              hashData.highest = $(value).find('td').text()
              break

            default:
              array[index] = _.compact($(value).find('td').text().split(' '))
              break
          }
        })

        hashData.cores = _.compact(array.map(core => {
          return {
            '2.5s': core[0],
            '60s': core[1],
            '15m': core[2]
          }
        }))

        hashData.total = {
          '2.5s': hashData.total[0],
          '60s': hashData.total[1],
          '15m': hashData.total[2]
        }

        callback(null, hashData)
      }
    }
  ]

  async.waterfall(
    funcArray,
    (err, result) => err ? dfd.reject(err) : dfd.resolve(result)
  )

  return dfd.promise
}

/**
 * Loops through the nods on the config files and get all the hash data
 * @param  {Array} nodes Array of objects with node description
 * @return {Promise}
 */
const getHashDataFromNodes = (nodes) => {
  var dfd = q.defer()

  const errors = {
    noNodes: 'No nodes were provided'
  }

  const funcArray = [
    (callback) => { // verify params
      var nds = _.clone(nodes)
      if (_.isEmpty(nodes)) return callback(errors.noNodes)

      callback(null, nds)
    },
    (nds, callback) => {
      if (callback) {
        var count = 0
        const mNodes = nds.map(node => {
          return new Promise((resolve, reject) => {
            return utils.getPage(node, 'h')
              .then(page => mainFile.hash.getHashData(page))
              .then(hashData => resolve(hashData))
              .catch(err => resolve(err)) // Resolves the error, so the other
                                          // nodes are returned regardledd
          })
        })

        Promise.all(mNodes)
          .then(pages => callback(null, pages))
          .catch(err => console.log(`err`))
      }
    }
  ]

  async.waterfall(
    funcArray,
    (err, result) => err ? dfd.reject(err) : dfd.resolve(result)
  )

  return dfd.promise
}

/**
 * Get total hash sum from nodes
 * @param  {Object} nodes Hash data of nodes
 * @return {Promise}
 */
const getHashSum = (nodes) => {
  var dfd = q.defer()

  const errors = {
    noNodes: 'No nodes were provided'
  }

  const funcArray = [
    (callback) => { // verify params
      var nds = _.clone(nodes)
      if (_.isEmpty(nodes)) return callback(errors.noNodes)

      callback(null, nds)
    },
    (nds, callback) => {

      nds = _.reduce(nds, (sum, node) => {
        // Eliminates the undefineds

        if (typeof node !== 'object' || _.isEmpty(node) || _.isEmpty(node.cores)) return sum

        sum.total = _.mapValues(sum.total, s => s ? parseFloat(s) : 0)
        node.total = _.mapValues(node.total, (n, key) => {
          var parsedN = parseFloat(n)
          // console.log(key+' : '+n)
          if ( isNaN( parsedN) ) return 0
          return parsedN
        })

        sum.total['2.5s'] = (sum.total['2.5s']  + node.total['2.5s']).toFixed(2)
        sum.total['60s'] =  (sum.total['60s']   + node.total['60s']).toFixed(2)
        sum.total['15m'] =  (sum.total['15m']   + node.total['15m']).toFixed(2)

        return sum
      }, {total: { '2.5s': 0, '60s': 0, '15m': 0 }})
      callback(null, nds)
    }
  ]

  async.waterfall(
    funcArray,
    (err, result) => err ? dfd.reject(err) : dfd.resolve(result)
  )

  return dfd.promise
}

module.exports = {
  getHashData: getHashData,
  getHashDataFromNodes: getHashDataFromNodes,
  getHashSum: getHashSum
}
<|endoftext|>


<commit_before>import React from 'react';

import Cards from './Cards.js';
import * as etgutil from './etgutil.js';
import Game from './Game.js';
import * as store from './store.js';
import * as userutil from './userutil.js';
import RngMock from './RngMock.js';
import config from '../config.json';

const endpoint = `${location.protocol === 'http:' ? 'ws://' : 'wss://'}
	${location.hostname}:${
	location.protocol === 'http:' ? config.wsport : config.wssport
}`;
const buffer = [];
let socket = new WebSocket(endpoint),
	attempts = 0,
	attemptTimeout = 0,
	pvp = null;
export let trade = null;
const sockEvents = {
	clear: () => store.store.dispatch(store.clearChat('Main')),
	passchange: data => {
		store.store.dispatch(store.updateUser({ auth: data.auth }));
		store.store.dispatch(store.chatMsg('Password updated', 'System'));
	},
	mute: data => {
		store.store.dispatch(store.mute(data.m));
		store.store.dispatch(store.chatMsg(data.m + ' has been muted', 'System'));
	},
	roll: data => {
		store.store.dispatch(
			store.chat(

					{data.u && {data.u} }
					{data.A || 1}d{data.X}{' '}
					<a href={`speed/${data.sum}`} target="_blank">
						{data.sum}

,
				'Main',
			),
		);
	},
	chat: data => {
		const state = store.store.getState();
		if (state.opts.muteall) {
			if (!data.mode) return;
		} else if (
			typeof Notification !== 'undefined' &&
			Notification.permission !== 'denied' &&
			state.user &&
			~data.msg.indexOf(state.user.name) &&
			!document.hasFocus()
		) {
			Notification.requestPermission().then(result => {
				if (result == 'granted') new Notification(data.u, { body: data.msg });
			});
		}
		const now = new Date(),
			h = now.getHours(),
			m = now.getMinutes(),
			hs = h < 10 ? '0' + h : h.toString(),
			ms = m < 10 ? '0' + m : m.toString(),
			style = {},
			text = [];
		if (data.mode !== 1) style.color = data.mode == 2 ? '#69f' : '#ddd';
		if (data.guest) style.fontStyle = 'italic';
		let decklink = /\b(([01][0-9a-v]{4})+)\b/g,
			reres,
			lastindex = 0;
		while ((reres = decklink.exec(data.msg))) {
			if (reres.index !== lastindex)
				text.push(data.msg.slice(lastindex, reres.index));
			let notlink = false;
			for (let i = 2; i < reres[0].length; i += 5) {
				const code = parseInt(reres[0].substr(i, 3), 32);
				if (!(code in Cards.Codes) && etgutil.fromTrueMark(code) == -1) {
					notlink = true;
					break;
				}
			}
			if (notlink) {
				lastindex = reres.index;
				continue;
			}
			text.push(
				<a href={`deck/${reres[0]}`} target="_blank">
					{reres[0]}
				,
			);
			lastindex = reres.index + reres[0].length;
		}
		if (lastindex !== data.msg.length) text.push(data.msg.slice(lastindex));
		store.store.dispatch(
			store.chat(

					{`${hs}${ms} `}
					{data.u && {data.u} }
					{text}

,
				data.mode == 1 ? null : 'Main',
			),
		);
	},
	foearena: data => {
		const { user } = store.store.getState();
		const game = new Game({
			players: RngMock.shuffle([
				{
					idx: 1,
					name: user.name,
					user: user.name,
					deck: getDeck(),
				},
				{
					idx: 2,
					ai: 1,
					name: data.name,
					deck: data.deck,
					hp: data.hp,
					drawpower: data.draw,
					markpower: data.mark,
				},
			]),
			seed: data.seed,
			rank: data.rank,
			age: data.age,
			arena: data.name,
			level: 4 + data.lv,
			cost: userutil.arenaCost(data.lv),
			rematch: () => {
				const { user } = store.store.getState();
				if (!Cards.isDeckLegal(etgutil.decodedeck(getDeck()), user)) {
					store.store.dispatch(store.chatMsg(`Invalid deck`, 'System'));
					return;
				}
				const cost = userutil.arenaCost(data.lv);
				if (user.gold < cost) {
					store.store.dispatch(store.chatMsg(`Requires ${cost}$`, 'System'));
					return;
				}
				userEmit('foearena', { lv: data.lv });
			},
		});
		store.store.dispatch(store.doNav(import('./views/Match.js'), { game }));
	},
	tradegive: data => {
		if (trade) {
			trade = false;
			store.store.dispatch(store.doNav(import('./views/Trade.js')));
		}
	},
	pvpgive: data => {
		if (pvp) {
			pvp = null;
			store.store.dispatch(
				store.doNav(import('./views/Match.js'), {
					game: new Game(data.data),
				}),
			);
		}
	},
	matchinvite: data => {
		store.store.dispatch(
			store.chat(

 userEmit('matchjoin', { host: data.u })}>
					{`${data.u} invites you`}

,
			),
		);
	},
	matchgive: data => {
		store.store.dispatch(
			store.doNav(import('./views/Challenge.js'), {
				groups: data.groups,
				set: data.set,
			}),
		);
	},
	challenge: data => {
		store.store.dispatch(
			store.chat(

 {
						if (data.pvp) {
							sendChallenge(data.f);
						} else {
							userEmit('tradewant', { f: (trade = data.f) });
						}
					}}>
					{`${data.f} offers to ${data.pvp ? 'duel' : 'trade with'} you!`}

,
			),
		);
		emit({ x: 'challrecv', f: data.f, pvp: data.pvp });
	},
	bzgive: data => {
		store.store.dispatch(store.userCmd(data.g ? 'addgold' : 'addcards', data));
		store.store.dispatch(store.chatMsg(data.msg, 'System'));
	},
	addpools: data => {
		store.store.dispatch(store.userCmd('addcards', { c: data.c }));
		store.store.dispatch(store.userCmd('addbound', { c: data.b }));
		store.store.dispatch(store.chatMsg(data.msg, 'System'));
	},
};
socket.onmessage = function (msg) {
	const data = JSON.parse(msg.data);
	if (data.u && state.muted.has(data.u)) return;
	const state = store.store.getState(),
		func = sockEvents[data.x] || state.cmds[data.x];
	if (func) func.call(this, data);
};
socket.onopen = function () {
	attempts = 0;
	if (attemptTimeout) {
		clearTimeout(attemptTimeout);
		attemptTimeout = 0;
	}
	const { opts } = store.store.getState();
	if (opts.offline || opts.wantpvp || opts.afk)
		emit({
			x: 'chatus',
			hide: !!opts.offline,
			wantpvp: !!opts.wantpvp,
			afk: !!opts.afk,
		});
	buffer.forEach(this.send, this);
	buffer.length = 0;
	store.store.dispatch(store.chatMsg('Connected', 'System'));
};
socket.onclose = function () {
	if (attemptTimeout) return;
	if (attempts < 8) attempts++;
	const timeout = 99 + Math.floor(99 * Math.random()) * attempts;
	attemptTimeout = setTimeout(() => {
		attemptTimeout = 0;
		const oldsock = socket;
		socket = new WebSocket(endpoint);
		socket.onopen = oldsock.onopen;
		socket.onclose = oldsock.onclose;
		socket.onmessage = oldsock.onmessage;
	}, timeout);
	store.store.dispatch(store.chatMsg(`Reconnecting in ${timeout}ms`, 'System'));
};
export function emit(data) {
	const msg = JSON.stringify(data);
	if (socket && socket.readyState == 1) {
		socket.send(msg);
	} else {
		buffer.push(msg);
	}
}
export function userEmit(x, data = {}) {
	const { user } = store.store.getState();
	data.x = x;
	data.u = user.name;
	data.a = user.auth;
	emit(data);
}
export function userExec(x, data = {}) {
	userEmit(x, data);
	store.store.dispatch(store.userCmd(x, data));
}
export function getDeck() {
	const state = store.store.getState();
	return state.user
		? state.user.decks[state.user.selectedDeck] || ''
		: state.opts.deck;
}
export function sendChallenge(foe) {
	const deck = getDeck(),
		{ user } = store.store.getState();
	if (!Cards.isDeckLegal(etgutil.decodedeck(deck), user)) {
		store.store.dispatch(store.chatMsg(`Invalid deck`, 'System'));
		return;
	}
	const msg = { f: foe };
	userEmit('foewant', msg);
	pvp = foe;
}
export function offerTrade(f) {
	trade = f;
	userEmit('tradewant', { f });
}
export function cancelTrade() {
	if (trade) {
		trade = null;
		userEmit('canceltrade');
	}
}
<commit_msg>Fix chat<commit_after>import React from 'react';

import Cards from './Cards.js';
import * as etgutil from './etgutil.js';
import Game from './Game.js';
import * as store from './store.js';
import * as userutil from './userutil.js';
import RngMock from './RngMock.js';
import config from '../config.json';

const endpoint = `${location.protocol === 'http:' ? 'ws://' : 'wss://'}
	${location.hostname}:${
	location.protocol === 'http:' ? config.wsport : config.wssport
}`;
const buffer = [];
let socket = new WebSocket(endpoint),
	attempts = 0,
	attemptTimeout = 0,
	pvp = null;
export let trade = null;
const sockEvents = {
	clear: () => store.store.dispatch(store.clearChat('Main')),
	passchange: data => {
		store.store.dispatch(store.updateUser({ auth: data.auth }));
		store.store.dispatch(store.chatMsg('Password updated', 'System'));
	},
	mute: data => {
		store.store.dispatch(store.mute(data.m));
		store.store.dispatch(store.chatMsg(data.m + ' has been muted', 'System'));
	},
	roll: data => {
		store.store.dispatch(
			store.chat(

					{data.u && {data.u} }
					{data.A || 1}d{data.X}{' '}
					<a href={`speed/${data.sum}`} target="_blank">
						{data.sum}

,
				'Main',
			),
		);
	},
	chat: data => {
		const state = store.store.getState();
		if (state.opts.muteall) {
			if (!data.mode) return;
		} else if (
			typeof Notification !== 'undefined' &&
			Notification.permission !== 'denied' &&
			state.user &&
			~data.msg.indexOf(state.user.name) &&
			!document.hasFocus()
		) {
			Notification.requestPermission().then(result => {
				if (result == 'granted') new Notification(data.u, { body: data.msg });
			});
		}
		const now = new Date(),
			h = now.getHours(),
			m = now.getMinutes(),
			hs = h < 10 ? '0' + h : h.toString(),
			ms = m < 10 ? '0' + m : m.toString(),
			style = {},
			text = [];
		if (data.mode !== 1) style.color = data.mode == 2 ? '#69f' : '#ddd';
		if (data.guest) style.fontStyle = 'italic';
		let decklink = /\b(([01][0-9a-v]{4})+)\b/g,
			reres,
			lastindex = 0;
		while ((reres = decklink.exec(data.msg))) {
			if (reres.index !== lastindex)
				text.push(data.msg.slice(lastindex, reres.index));
			let notlink = false;
			for (let i = 2; i < reres[0].length; i += 5) {
				const code = parseInt(reres[0].substr(i, 3), 32);
				if (!(code in Cards.Codes) && etgutil.fromTrueMark(code) == -1) {
					notlink = true;
					break;
				}
			}
			if (notlink) {
				lastindex = reres.index;
				continue;
			}
			text.push(
				<a href={`deck/${reres[0]}`} target="_blank">
					{reres[0]}
				,
			);
			lastindex = reres.index + reres[0].length;
		}
		if (lastindex !== data.msg.length) text.push(data.msg.slice(lastindex));
		store.store.dispatch(
			store.chat(

					{`${hs}${ms} `}
					{data.u && {data.u} }
					{text}

,
				data.mode == 1 ? null : 'Main',
			),
		);
	},
	foearena: data => {
		const { user } = store.store.getState();
		const game = new Game({
			players: RngMock.shuffle([
				{
					idx: 1,
					name: user.name,
					user: user.name,
					deck: getDeck(),
				},
				{
					idx: 2,
					ai: 1,
					name: data.name,
					deck: data.deck,
					hp: data.hp,
					drawpower: data.draw,
					markpower: data.mark,
				},
			]),
			seed: data.seed,
			rank: data.rank,
			age: data.age,
			arena: data.name,
			level: 4 + data.lv,
			cost: userutil.arenaCost(data.lv),
			rematch: () => {
				const { user } = store.store.getState();
				if (!Cards.isDeckLegal(etgutil.decodedeck(getDeck()), user)) {
					store.store.dispatch(store.chatMsg(`Invalid deck`, 'System'));
					return;
				}
				const cost = userutil.arenaCost(data.lv);
				if (user.gold < cost) {
					store.store.dispatch(store.chatMsg(`Requires ${cost}$`, 'System'));
					return;
				}
				userEmit('foearena', { lv: data.lv });
			},
		});
		store.store.dispatch(store.doNav(import('./views/Match.js'), { game }));
	},
	tradegive: data => {
		if (trade) {
			trade = false;
			store.store.dispatch(store.doNav(import('./views/Trade.js')));
		}
	},
	pvpgive: data => {
		if (pvp) {
			pvp = null;
			store.store.dispatch(
				store.doNav(import('./views/Match.js'), {
					game: new Game(data.data),
				}),
			);
		}
	},
	matchinvite: data => {
		store.store.dispatch(
			store.chat(

 userEmit('matchjoin', { host: data.u })}>
					{`${data.u} invites you`}

,
			),
		);
	},
	matchgive: data => {
		store.store.dispatch(
			store.doNav(import('./views/Challenge.js'), {
				groups: data.groups,
				set: data.set,
			}),
		);
	},
	challenge: data => {
		store.store.dispatch(
			store.chat(

 {
						if (data.pvp) {
							sendChallenge(data.f);
						} else {
							userEmit('tradewant', { f: (trade = data.f) });
						}
					}}>
					{`${data.f} offers to ${data.pvp ? 'duel' : 'trade with'} you!`}

,
			),
		);
		emit({ x: 'challrecv', f: data.f, pvp: data.pvp });
	},
	bzgive: data => {
		store.store.dispatch(store.userCmd(data.g ? 'addgold' : 'addcards', data));
		store.store.dispatch(store.chatMsg(data.msg, 'System'));
	},
	addpools: data => {
		store.store.dispatch(store.userCmd('addcards', { c: data.c }));
		store.store.dispatch(store.userCmd('addbound', { c: data.b }));
		store.store.dispatch(store.chatMsg(data.msg, 'System'));
	},
};
socket.onmessage = function (msg) {
	const data = JSON.parse(msg.data),
		state = store.store.getState();
	if (data.u && state.muted.has(data.u)) return;
	const func = sockEvents[data.x] || state.cmds[data.x];
	if (func) func.call(this, data);
};
socket.onopen = function () {
	attempts = 0;
	if (attemptTimeout) {
		clearTimeout(attemptTimeout);
		attemptTimeout = 0;
	}
	const { opts } = store.store.getState();
	if (opts.offline || opts.wantpvp || opts.afk)
		emit({
			x: 'chatus',
			hide: !!opts.offline,
			wantpvp: !!opts.wantpvp,
			afk: !!opts.afk,
		});
	buffer.forEach(this.send, this);
	buffer.length = 0;
	store.store.dispatch(store.chatMsg('Connected', 'System'));
};
socket.onclose = function () {
	if (attemptTimeout) return;
	if (attempts < 8) attempts++;
	const timeout = 99 + Math.floor(99 * Math.random()) * attempts;
	attemptTimeout = setTimeout(() => {
		attemptTimeout = 0;
		const oldsock = socket;
		socket = new WebSocket(endpoint);
		socket.onopen = oldsock.onopen;
		socket.onclose = oldsock.onclose;
		socket.onmessage = oldsock.onmessage;
	}, timeout);
	store.store.dispatch(store.chatMsg(`Reconnecting in ${timeout}ms`, 'System'));
};
export function emit(data) {
	const msg = JSON.stringify(data);
	if (socket && socket.readyState == 1) {
		socket.send(msg);
	} else {
		buffer.push(msg);
	}
}
export function userEmit(x, data = {}) {
	const { user } = store.store.getState();
	data.x = x;
	data.u = user.name;
	data.a = user.auth;
	emit(data);
}
export function userExec(x, data = {}) {
	userEmit(x, data);
	store.store.dispatch(store.userCmd(x, data));
}
export function getDeck() {
	const state = store.store.getState();
	return state.user
		? state.user.decks[state.user.selectedDeck] || ''
		: state.opts.deck;
}
export function sendChallenge(foe) {
	const deck = getDeck(),
		{ user } = store.store.getState();
	if (!Cards.isDeckLegal(etgutil.decodedeck(deck), user)) {
		store.store.dispatch(store.chatMsg(`Invalid deck`, 'System'));
		return;
	}
	const msg = { f: foe };
	userEmit('foewant', msg);
	pvp = foe;
}
export function offerTrade(f) {
	trade = f;
	userEmit('tradewant', { f });
}
export function cancelTrade() {
	if (trade) {
		trade = null;
		userEmit('canceltrade');
	}
}
<|endoftext|>