<commit_before>(function () {
    'use strict';

    const { Money } = require('@waves/data-entities');
    const { SIGN_TYPE } = require('@waves/signature-adapter');
    const { filter, whereEq, uniqBy, prop, where, gt, pick, __ } = require('ramda');
    const ds = require('data-service');

    /**
     * @param Base
     * @param {Waves} waves
     * @param {User} user
     * @param {IPollCreate} createPoll
     * @param {INotification} notification
     * @param {app.utils} utils
     * @param {$rootScope.Scope} $scope
     * @param {DexDataService} dexDataService
     * @param {ModalManager} modalManager
     * @param {PermissionManager} permissionManager,
     * @param {Ease} ease
     * @param {JQuery} $element
     * @return {DexMyOrders}
     */
    const controller = function (
        Base,
        waves,
        user,
        createPoll,
        notification,
        utils,
        $scope,
        dexDataService,
        modalManager,
        permissionManager,
        ease,
        $element
    ) {

        class DexMyOrders extends Base {

            /**
             * @type {{amount: string, price: string}}
             * @private
             */
            _assetIdPair;
            /**
             * @type {Promise<string>}
             * @private
             */
            _matcherPublicKeyPromise = ds.fetch(user.getSetting('network.matcher'));
            /**
             * @type {Array<IDexOrders>}
             */
            orders = [];
            /**
             * @type {boolean}
             */
            isDemo = !user.address;
            /**
             * @type {boolean}
             */
            pending = !!user.address;
            /**
             * @type {Object.<string, boolean>}
             */
            shownOrderDetails = Object.create(null);
            /**
             * @type {boolean}
             */
            loadingError = false;
            /**
             * @type {boolean}
             */
            showAnims = false;

            /**
             * @type {Array}
             */
            userList = [];

            constructor() {
                super();

                this.syncSettings({
                    _assetIdPair: 'dex.assetIdPair',
                    _matcherUrl: 'network.matcher'
                });

                this.observe('_matcherUrl', () => {
                    this._matcherPublicKeyPromise = ds.fetch(user.getSetting('network.matcher'));
                });

                this.headers = [
                    {
                        id: 'pair',
                        valuePath: 'item.pair',
                        search: true,
                        placeholder: 'directives.filter'
                    },
                    {
                        id: 'type',
                        title: { literal: 'directives.myOrders.type' },
                        valuePath: 'item.type',
                        sort: true
                    },
                    {
                        id: 'time',
                        title: { literal: 'directives.myOrders.time' },
                        valuePath: 'item.timestamp',
                        sort: true,
                        sortActive: true,
                        isAsc: false
                    },
                    {
                        id: 'price',
                        title: { literal: 'directives.myOrders.price' },
                        valuePath: 'item.price',
                        sort: true
                    },
                    {
                        id: 'amount',
                        title: { literal: 'directives.myOrders.amount' },
                        valuePath: 'item.amount',
                        sort: true
                    },
                    {
                        id: 'total',
                        title: { literal: 'directives.myOrders.total' },
                        valuePath: 'item.total',
                        sort: true
                    },
                    {
                        id: 'fee',
                        title: { literal: 'directives.myOrders.tableTitle.fee' },
                        valuePath: 'item.userFee',
                        sort: true
                    },
                    {
                        id: 'status',
                        title: { literal: 'directives.myOrders.status' },
                        valuePath: 'item.progress',
                        sort: true
                    },
                    {
                        id: 'controls',
                        templatePath: 'modules/dex/directives/dexMyOrders/header-control-cell.html',
                        scopeData: {
                            cancelAllOrdersClick: () => {
                                this.cancelAllOrders();
                            },
                            $ctrl: this
                        }
                    }
                ];

                if (!this.isDemo) {
                    const poll = createPoll(this, DexMyOrders._getAllOrders, this._setOrders, 1000);
                    poll.ready.then(() => {
                        this.pending = false;
                    });
                    this.receive(dexDataService.createOrder, () => poll.restart());
                    this.poll = poll;
                }

                user.getFilteredUserList().then(list => {
                    this.userList = list;
                });
            }

            /**
             * @return {Promise<Array<IOrder> | never>}
             * @private
             */
            static _getAllOrders() {
                return waves.matcher.getOrders()
                    .then(filter(whereEq({ isActive: true })))
                    .catch(() => (this.loadingError = true));
            }

            static _animateNotification($element) {
                return utils.animate($element, { t: 100 }, {
                    duration: 1200,
                    step: function (tween) {
                        const progress = ease.bounceOut(tween / 100);
                        $element.css('transform', `translate(0, ${-100 + progress * 100}%)`);
                    }
                })
                    .then(() => utils.wait(700))
                    .then(() => {
                        return utils.animate($element, { t: 0 }, {
                            duration: 500,
                            step: function (tween) {
                                const progress = ease.linear(tween / 100);
                                $element.css('transform', `translate(0, ${(-((1 - progress) * 100))}%)`);
                            }
                        });
                    });
            }

            static _getTransactionsByOrderIdHash(txList) {
                const uniqueList = uniqBy(prop('id'), txList);
                const transactionsByOrderHash = Object.create(null);
                uniqueList.forEach((tx) => {
                    ['order1', 'order2'].forEach((orderFieldName) => {
                        if (!transactionsByOrderHash[tx[orderFieldName].id]) {
                            transactionsByOrderHash[tx[orderFieldName].id] = [];
                        }
                        transactionsByOrderHash[tx[orderFieldName].id].push(DexMyOrders._remapTx(tx));
                    });
                });
                return transactionsByOrderHash;
            }

            static _remapTx(tx) {
                const fee = (tx, order) => order.orderType === 'sell' ? tx.sellMatcherFee : tx.buyMatcherFee;
                const emptyFee = new Money(0, tx.fee.asset);
                const userFee = [tx.order1, tx.order2]
                    .filter((order) => order.sender === user.address)
                    .reduce((acc, order) => acc.add(fee(tx, order)), emptyFee);

                return { ...tx, userFee };
            }

            /**
             * @param {IOrder} order
             * @private
             */
            static _remapOrders(matcherPublicKey) {
                return order => {
                    const assetPair = order.assetPair;
                    const pair = `${assetPair.amountAsset.displayName} / ${assetPair.priceAsset.displayName}`;
                    const isNew = DexMyOrders._isNewOrder(order.timestamp.getTime());
                    const percent = new BigNumber(order.progress * 100).dp(2).toFixed();
                    return waves.matcher.getCreateOrderFee({ ...order, matcherPublicKey })
                        .then(fee => ({ ...order, isNew, percent, pair, fee }));
                };
            }

            /**
             * @param {number} timestamp
             * @return {boolean}
             * @private
             */
            static _isNewOrder(timestamp) {
                return ds.utils.normalizeTime(Date.now()) < timestamp + 1000 * 8;
            }

            /**
             * @param {IOrder} order
             */
            setPair(order) {
                user.setSetting('dex.assetIdPair', {
                    amount: order.assetPair.amountAsset.id,
                    price: order.assetPair.priceAsset.id
                });
            }

            showDetails(order) {
                this.shownOrderDetails[order.id] = true;
            }

            hideDetails(order) {
                this.shownOrderDetails[order.id] = false;
            }

            toggleDetails(order) {
                this.shownOrderDetails[order.id] = !this.shownOrderDetails[order.id];
            }

            cancelAllOrders() {
                if (!permissionManager.isPermitted('CAN_CANCEL_ORDER')) {
                    const $notify = $element.find('.js-order-notification');
                    DexMyOrders._animateNotification($notify);
                    return null;
                }

                this.orders.filter(whereEq({ isActive: true }))
                    .forEach((order) => this.dropOrder(order));
            }

            round(data) {
                return Math.round(Number(data));
            }

            /**
             * @param {IOrder} order
             * @return boolean
             */
            isSelected(order) {
                return this._assetIdPair.amount === order.amount.asset.id &&
                    this._assetIdPair.price === order.price.asset.id;
            }

            dropOrderGetSignData(order) {
                const { id } = order;
                const data = { id };
                const signable = ds.signature.getSignatureApi().makeSignable({
                    type: SIGN_TYPE.CANCEL_ORDER,
                    data
                });

                return utils.signMatcher(signable)
                    .then(signable => signable.getDataForApi());
            }

            /**
             * @param order
             */
            dropOrder(order) {
                if (!permissionManager.isPermitted('CAN_CANCEL_ORDER')) {
                    const $notify = $element.find('.js-order-notification');
                    DexMyOrders._animateNotification($notify);
                    return null;
                }

                const dataPromise = this.dropOrderGetSignData(order);

                const classNameToOrder = (className, isRemove = false) => {
                    const $row = $element.find(`.order_${order.id}`).closest('.order-row');

                    if (isRemove) {
                        $row.removeClass(className);
                    } else {
                        $row.addClass(className);
                    }
                };

                classNameToOrder('pre-leave');

                dataPromise
                    .then((signedTxData) => ds.cancelOrder(signedTxData, order.amount.asset.id, order.price.asset.id))
                    .then(() => {
                        classNameToOrder('force-leave');
                        const canceledOrder = this.orders.find(whereEq({ id: order.id }));
                        canceledOrder.state = 'Canceled';
                        notification.info({
                            ns: 'app.dex',
                            title: { literal: 'directives.myOrders.notifications.isCanceled' }
                        });

                        if (this.poll) {
                            this.poll.restart();
                        }
                    })
                    .catch(e => {
                        classNameToOrder('pre-leave', true);
                        const error = utils.parseError(e);
                        notification.error({
                            ns: 'app.dex',
                            title: { literal: 'directives.myOrders.notifications.somethingWentWrong' },
                            body: { literal: error && error.message || error }
                        });
                    });
            }

            /**
             * @param {Array<IOrder>} orders
             * @private
             */
            _setOrders(orders) {
                const isEqual = this.orders.length === orders.length && this.orders
                    .every((item, i) => whereEq(pick(['id', 'progress'], item), orders[i]));

                if (isEqual) {
                    let needApply = false;

                    this.orders.forEach(order => {
                        const isNew = DexMyOrders._isNewOrder(order.timestamp.getTime());
                        needApply = needApply || isNew !== order.isNew;
                        order.isNew = isNew;
                    });

                    if (needApply) {
                        $scope.$apply();
                    }
                    this.showAnims = true;
                    return null;
                }

                return this._matcherPublicKeyPromise
                    .then(matcherPublicKey => Promise.all(orders.map(DexMyOrders._remapOrders(matcherPublicKey))))
                    .then(result => {
                        const lastOrder = result.slice().reverse().find(where({ progress: gt(__, 0) }));

                        if (!lastOrder) {
                            return result;
                        }

                        return ds.api.transactions.getExchangeTxList({
                            sender: user.address,
                            timeStart: ds.utils.normalizeTime(lastOrder.timestamp.getTime())
                        }).then(txList => {
                            const transactionsByOrderHash = DexMyOrders._getTransactionsByOrderIdHash(txList);
                            this.loadingError = false;
                            return result.map(order => {
                                if (!transactionsByOrderHash[order.id]) {
                                    transactionsByOrderHash[order.id] = [];
                                }
                                order.exchange = transactionsByOrderHash[order.id];
                                return order;
                            });
                        }).catch(() => result);
                    })
                    .then(orders => (this.orders = orders))
                    .catch(() => (this.loadingError = true))
                    .then(() => {
                        $scope.$apply();
                    });
            }

        }

        return new DexMyOrders();
    };

    controller.$inject = [
        'Base',
        'waves',
        'user',
        'createPoll',
        'notification',
        'utils',
        '$scope',
        'dexDataService',
        'modalManager',
        'permissionManager',
        'ease',
        '$element'
    ];

    angular.module('app.dex').component('wDexMyOrders', {
        bindings: {},
        templateUrl: 'modules/dex/directives/dexMyOrders/myOrders.html',
        controller
    });
})();

/**
 * @typedef {IOrder} IDexOrders
 * @property {boolean} isNew
 * @property {string} pair
 * @property {Array} exchange
 */
<commit_msg>DEXW-1771: fix my orders<commit_after>(function () {
    'use strict';

    const { Money } = require('@waves/data-entities');
    const { SIGN_TYPE } = require('@waves/signature-adapter');
    const { filter, whereEq, uniqBy, prop, where, gt, pick, __, tap } = require('ramda');
    const ds = require('data-service');

    /**
     * @param Base
     * @param {Waves} waves
     * @param {User} user
     * @param {IPollCreate} createPoll
     * @param {INotification} notification
     * @param {app.utils} utils
     * @param {$rootScope.Scope} $scope
     * @param {DexDataService} dexDataService
     * @param {ModalManager} modalManager
     * @param {PermissionManager} permissionManager,
     * @param {Ease} ease
     * @param {JQuery} $element
     * @return {DexMyOrders}
     */
    const controller = function (
        Base,
        waves,
        user,
        createPoll,
        notification,
        utils,
        $scope,
        dexDataService,
        modalManager,
        permissionManager,
        ease,
        $element
    ) {

        class DexMyOrders extends Base {

            /**
             * @type {{amount: string, price: string}}
             * @private
             */
            _assetIdPair;
            /**
             * @type {Promise<string>}
             * @private
             */
            _matcherPublicKeyPromise = ds.fetch(user.getSetting('network.matcher'));
            /**
             * @type {Array<IDexOrders>}
             */
            orders = [];
            /**
             * @type {boolean}
             */
            isDemo = !user.address;
            /**
             * @type {boolean}
             */
            pending = !!user.address;
            /**
             * @type {Object.<string, boolean>}
             */
            shownOrderDetails = Object.create(null);
            /**
             * @type {boolean}
             */
            loadingError = false;
            /**
             * @type {boolean}
             */
            showAnims = false;

            /**
             * @type {Array}
             */
            userList = [];

            constructor() {
                super();

                this.syncSettings({
                    _assetIdPair: 'dex.assetIdPair',
                    _matcherUrl: 'network.matcher'
                });

                this.observe('_matcherUrl', () => {
                    this._matcherPublicKeyPromise = ds.fetch(user.getSetting('network.matcher'));
                });

                this.headers = [
                    {
                        id: 'pair',
                        valuePath: 'item.pair',
                        search: true,
                        placeholder: 'directives.filter'
                    },
                    {
                        id: 'type',
                        title: { literal: 'directives.myOrders.type' },
                        valuePath: 'item.type',
                        sort: true
                    },
                    {
                        id: 'time',
                        title: { literal: 'directives.myOrders.time' },
                        valuePath: 'item.timestamp',
                        sort: true,
                        sortActive: true,
                        isAsc: false
                    },
                    {
                        id: 'price',
                        title: { literal: 'directives.myOrders.price' },
                        valuePath: 'item.price',
                        sort: true
                    },
                    {
                        id: 'amount',
                        title: { literal: 'directives.myOrders.amount' },
                        valuePath: 'item.amount',
                        sort: true
                    },
                    {
                        id: 'total',
                        title: { literal: 'directives.myOrders.total' },
                        valuePath: 'item.total',
                        sort: true
                    },
                    {
                        id: 'fee',
                        title: { literal: 'directives.myOrders.tableTitle.fee' },
                        valuePath: 'item.userFee',
                        sort: true
                    },
                    {
                        id: 'status',
                        title: { literal: 'directives.myOrders.status' },
                        valuePath: 'item.progress',
                        sort: true
                    },
                    {
                        id: 'controls',
                        templatePath: 'modules/dex/directives/dexMyOrders/header-control-cell.html',
                        scopeData: {
                            cancelAllOrdersClick: () => {
                                this.cancelAllOrders();
                            },
                            $ctrl: this
                        }
                    }
                ];

                if (!this.isDemo) {
                    const poll = createPoll(this, DexMyOrders._getAllOrders, this._setOrders, 1000);
                    poll.ready.then(() => {
                        this.pending = false;
                    });
                    this.receive(dexDataService.createOrder, () => poll.restart());
                    this.poll = poll;
                }

                user.getFilteredUserList().then(list => {
                    this.userList = list;
                });
            }

            /**
             * @return {Promise<Array<IOrder> | never>}
             * @private
             */
            static _getAllOrders() {
                return waves.matcher.getOrders()
                    .then(filter(whereEq({ isActive: true })))
                    .then(tap(() => {
                        this.loadingError = false;
                    }))
                    .catch(tap(() => {
                        this.loadingError = true;
                    }));
            }

            static _animateNotification($element) {
                return utils.animate($element, { t: 100 }, {
                    duration: 1200,
                    step: function (tween) {
                        const progress = ease.bounceOut(tween / 100);
                        $element.css('transform', `translate(0, ${-100 + progress * 100}%)`);
                    }
                })
                    .then(() => utils.wait(700))
                    .then(() => {
                        return utils.animate($element, { t: 0 }, {
                            duration: 500,
                            step: function (tween) {
                                const progress = ease.linear(tween / 100);
                                $element.css('transform', `translate(0, ${(-((1 - progress) * 100))}%)`);
                            }
                        });
                    });
            }

            static _getTransactionsByOrderIdHash(txList) {
                const uniqueList = uniqBy(prop('id'), txList);
                const transactionsByOrderHash = Object.create(null);
                uniqueList.forEach((tx) => {
                    ['order1', 'order2'].forEach((orderFieldName) => {
                        if (!transactionsByOrderHash[tx[orderFieldName].id]) {
                            transactionsByOrderHash[tx[orderFieldName].id] = [];
                        }
                        transactionsByOrderHash[tx[orderFieldName].id].push(DexMyOrders._remapTx(tx));
                    });
                });
                return transactionsByOrderHash;
            }

            static _remapTx(tx) {
                const fee = (tx, order) => order.orderType === 'sell' ? tx.sellMatcherFee : tx.buyMatcherFee;
                const emptyFee = new Money(0, tx.fee.asset);
                const userFee = [tx.order1, tx.order2]
                    .filter((order) => order.sender === user.address)
                    .reduce((acc, order) => acc.add(fee(tx, order)), emptyFee);

                return { ...tx, userFee };
            }

            /**
             * @param {IOrder} order
             * @private
             */
            static _remapOrders(matcherPublicKey) {
                return order => {
                    const assetPair = order.assetPair;
                    const pair = `${assetPair.amountAsset.displayName} / ${assetPair.priceAsset.displayName}`;
                    const isNew = DexMyOrders._isNewOrder(order.timestamp.getTime());
                    const percent = new BigNumber(order.progress * 100).dp(2).toFixed();
                    return waves.matcher.getCreateOrderFee({ ...order, matcherPublicKey })
                        .then(fee => ({ ...order, isNew, percent, pair, fee }));
                };
            }

            /**
             * @param {number} timestamp
             * @return {boolean}
             * @private
             */
            static _isNewOrder(timestamp) {
                return ds.utils.normalizeTime(Date.now()) < timestamp + 1000 * 8;
            }

            /**
             * @param {IOrder} order
             */
            setPair(order) {
                user.setSetting('dex.assetIdPair', {
                    amount: order.assetPair.amountAsset.id,
                    price: order.assetPair.priceAsset.id
                });
            }

            showDetails(order) {
                this.shownOrderDetails[order.id] = true;
            }

            hideDetails(order) {
                this.shownOrderDetails[order.id] = false;
            }

            toggleDetails(order) {
                this.shownOrderDetails[order.id] = !this.shownOrderDetails[order.id];
            }

            cancelAllOrders() {
                if (!permissionManager.isPermitted('CAN_CANCEL_ORDER')) {
                    const $notify = $element.find('.js-order-notification');
                    DexMyOrders._animateNotification($notify);
                    return null;
                }

                this.orders.filter(whereEq({ isActive: true }))
                    .forEach((order) => this.dropOrder(order));
            }

            round(data) {
                return Math.round(Number(data));
            }

            /**
             * @param {IOrder} order
             * @return boolean
             */
            isSelected(order) {
                return this._assetIdPair.amount === order.amount.asset.id &&
                    this._assetIdPair.price === order.price.asset.id;
            }

            dropOrderGetSignData(order) {
                const { id } = order;
                const data = { id };
                const signable = ds.signature.getSignatureApi().makeSignable({
                    type: SIGN_TYPE.CANCEL_ORDER,
                    data
                });

                return utils.signMatcher(signable)
                    .then(signable => signable.getDataForApi());
            }

            /**
             * @param order
             */
            dropOrder(order) {
                if (!permissionManager.isPermitted('CAN_CANCEL_ORDER')) {
                    const $notify = $element.find('.js-order-notification');
                    DexMyOrders._animateNotification($notify);
                    return null;
                }

                const dataPromise = this.dropOrderGetSignData(order);

                const classNameToOrder = (className, isRemove = false) => {
                    const $row = $element.find(`.order_${order.id}`).closest('.order-row');

                    if (isRemove) {
                        $row.removeClass(className);
                    } else {
                        $row.addClass(className);
                    }
                };

                classNameToOrder('pre-leave');

                dataPromise
                    .then((signedTxData) => ds.cancelOrder(signedTxData, order.amount.asset.id, order.price.asset.id))
                    .then(() => {
                        classNameToOrder('force-leave');
                        const canceledOrder = this.orders.find(whereEq({ id: order.id }));
                        canceledOrder.state = 'Canceled';
                        notification.info({
                            ns: 'app.dex',
                            title: { literal: 'directives.myOrders.notifications.isCanceled' }
                        });

                        if (this.poll) {
                            this.poll.restart();
                        }
                    })
                    .catch(e => {
                        classNameToOrder('pre-leave', true);
                        const error = utils.parseError(e);
                        notification.error({
                            ns: 'app.dex',
                            title: { literal: 'directives.myOrders.notifications.somethingWentWrong' },
                            body: { literal: error && error.message || error }
                        });
                    });
            }

            /**
             * @param {Array<IOrder>} orders
             * @private
             */
            _setOrders(orders) {
                const isEqual = this.orders.length === orders.length && this.orders
                    .every((item, i) => whereEq(pick(['id', 'progress'], item), orders[i]));

                if (isEqual) {
                    let needApply = false;

                    this.orders.forEach(order => {
                        const isNew = DexMyOrders._isNewOrder(order.timestamp.getTime());
                        needApply = needApply || isNew !== order.isNew;
                        order.isNew = isNew;
                    });

                    if (needApply) {
                        $scope.$apply();
                    }
                    this.showAnims = true;
                    return null;
                }

                return this._matcherPublicKeyPromise
                    .then(matcherPublicKey => Promise.all(orders.map(DexMyOrders._remapOrders(matcherPublicKey))))
                    .then(result => {
                        const lastOrder = result.slice().reverse().find(where({ progress: gt(__, 0) }));

                        if (!lastOrder) {
                            return result;
                        }

                        return ds.api.transactions.getExchangeTxList({
                            sender: user.address,
                            timeStart: ds.utils.normalizeTime(lastOrder.timestamp.getTime())
                        }).then(txList => {
                            const transactionsByOrderHash = DexMyOrders._getTransactionsByOrderIdHash(txList);
                            this.loadingError = false;
                            return result.map(order => {
                                if (!transactionsByOrderHash[order.id]) {
                                    transactionsByOrderHash[order.id] = [];
                                }
                                order.exchange = transactionsByOrderHash[order.id];
                                return order;
                            });
                        }).catch(() => result);
                    })
                    .then(orders => (this.orders = orders))
                    .catch(() => (this.loadingError = true))
                    .then(() => {
                        $scope.$apply();
                    });
            }

        }

        return new DexMyOrders();
    };

    controller.$inject = [
        'Base',
        'waves',
        'user',
        'createPoll',
        'notification',
        'utils',
        '$scope',
        'dexDataService',
        'modalManager',
        'permissionManager',
        'ease',
        '$element'
    ];

    angular.module('app.dex').component('wDexMyOrders', {
        bindings: {},
        templateUrl: 'modules/dex/directives/dexMyOrders/myOrders.html',
        controller
    });
})();

/**
 * @typedef {IOrder} IDexOrders
 * @property {boolean} isNew
 * @property {string} pair
 * @property {Array} exchange
 */
<|endoftext|>


<commit_before>(function(w,d,l,undefined) {
  // ページを読み込んだ時の初期化処理
  //   現在のページ数判定
  //   最終ページ判定
  // ハッシュ値が変わった時
  //   設定値を上書き更新する
  // ->  状態管理は $mds.data のハッシュに持たせる
  w.$mds = {};
  $mds.page = function() {
    return +l.hash.slice(1);
  };
  $mds.next = function() {
    l.hash = "#" + (this.page() + 1);
  };
  $mds.prev = function() {
    l.hash = "#" + (this.page() - 1);
  };
  $mds.render = function(p, e, i) {
    p = $mds.page();
    e = document.getElementsByClassName("slide");
    i = e.length;
    while (i--) {
      e[i].style.display = (e[i].dataset.page == p ? 'block' : 'none');
    }
  };

  w.onload = $mds.render;
  w.onhashchange = $mds.render;

})(window, document, location);
<commit_msg>リファクタリング #6<commit_after>(function(w,d,l,undefined,self) {
  self = w.$mds = {};

  $mds.init = function() {
    self._class = 'slide'
    self._slide = d.getElementsByClassName(self._class);
    self._size  = self._slide.length;
    self._page  = +l.hash.slice(1);
    if (self._page <= 0 || isNaN(self._page)) {
      self._page = 1;
    }
  };
  $mds.page = function(p) {
    l.hash = '#' + p;
  };
  $mds.next = function() {
    if (self._page < self._size) {
      self.page(self._page + 1);
      return true;
    } else {
      return false;
    }
  };
  $mds.prev = function() {
    if (self._page > 1) {
      self.page(self._page - 1);
      return true;
    } else {
      return false;
    }
  };
  $mds.render = function(e, i, p) {
    p = self._page; i = self._size;
    e = self._slide;
    while (i--) {
      e[i].style.display = (e[i].dataset.page == p ? 'block' : 'none');
    }
  };
  $mds.refresh = function() {
    self.init();
    self.render();
  };

  w.onload       = $mds.refresh;
  w.onhashchange = $mds.refresh;

})(window, document, location);
<|endoftext|>


<commit_before>
// ordered: bool.
// old_results and new_results: collections of documents.
//    if ordered, they are arrays.
//    if unordered, they are maps {_id: doc}.
// observer: object with 'added', 'changed', 'removed',
//           and (if ordered) 'moved' functions (each optional)
// deepcopy: if true, elements of new_results that are passed
//           to callbacks are deepcopied first.
LocalCollection._diffQueryChanges = function (ordered, oldResults, newResults,
                                       observer) {
  if (ordered)
    LocalCollection._diffQueryOrderedChanges(
      oldResults, newResults, observer);
  else
    LocalCollection._diffQueryUnorderedChanges(
      oldResults, newResults, observer);
};

LocalCollection._diffQueryUnorderedChanges = function (oldResults, newResults,
                                                observer) {
  if (observer.moved) {
    throw new Error("_diffQueryUnordered called with a moved observer!");
  }

  // "maybe deepcopy"
  _.each(newResults, function (newDoc) {
    if (_.has(oldResults, newDoc._id)) {
      var oldDoc = oldResults[newDoc._id];
      if (observer.changed && !EJSON.equals(oldDoc, newDoc)) {
        observer.changed(newDoc._id, LocalCollection._makeChangedFields(newDoc, oldDoc));
      }
    } else {
      var fields = EJSON.clone(newDoc);
      delete fields._id;
      observer.added && observer.added(newDoc._id, fields);
    }
  });

  if (observer.removed) {
    _.each(oldResults, function (oldDoc) {
      if (!_.has(newResults, oldDoc._id))
        observer.removed(oldDoc._id);
    });
  }
};

LocalCollection._diffQueryOrderedChanges = function (old_results, new_results, observer) {

  var new_presence_of_id = {};
  _.each(new_results, function (doc) {
    if (new_presence_of_id[doc._id])
      Meteor._debug("Duplicate _id in new_results");
    new_presence_of_id[doc._id] = true;
  });

  var old_index_of_id = {};
  _.each(old_results, function (doc, i) {
    if (doc._id in old_index_of_id)
      Meteor._debug("Duplicate _id in old_results");
    old_index_of_id[doc._id] = i;
  });

  // ALGORITHM:
  //
  // We walk old_idx through the old_results array and
  // new_idx through the new_results array at the same time.
  // These pointers establish a sort of correspondence between
  // old docs and new docs (identified by their _ids).
  // If they point to the same doc (i.e. old and new docs
  // with the same _id), we can increment both pointers
  // and fire no 'moved' callbacks.  Otherwise, we must
  // increment one or the other and fire approprate 'added',
  // 'removed', and 'moved' callbacks.
  //
  // The process is driven by new_results, in that we try
  // make the observer's array look like new_results by
  // establishing each new doc in order.  The doc pointed
  // to by new_idx is the one we are trying to establish
  // at any given time.  If it doesn't exist in old_results,
  // we fire an 'added' callback.  If it does, we have a
  // choice of two ways to handle the situation.  We can
  // advance old_idx forward to the corresponding old doc,
  // treating all intervening old docs as moved or removed,
  // and the current doc as unmoved.  Or, we can simply
  // establish the new doc as next by moving it into place,
  // i.e. firing a single 'moved' callback to move the
  // doc from wherever it was before.  Generating a sequence
  // of 'moved' callbacks that is not just correct but small
  // (or minimal) is a matter of choosing which elements
  // to consider moved and which ones merely change position
  // by virtue of the movement of other docs.
  //
  // Calling callbacks with correct indices requires understanding
  // what the observer's array looks like at each iteration.
  // The observer's array is a concatenation of:
  // - new_results up to (but not including) new_idx, with the
  //   addition of some "bumped" docs that we are later going
  //   to move into place
  // - old_results starting at old_idx, minus any docs that we
  //   have already moved ("taken" docs)
  //
  // To keep track of "bumped" items -- docs in the observer's
  // array that we have skipped over, but will be moved forward
  // later when we get to their new position -- we keep a
  // "bump list" of indices into new_results where bumped items
  // occur.  [The idea is that by adding an item to the list (bumping
  // it), we can consider it dealt with, even though it is still there.]
  // The corresponding position of new_idx in the observer's array,
  // then, is new_idx + bump_list.length, and the position of
  // the nth bumped item in the observer's array is
  // bump_list[n] + n (to account for the previous bumped items
  // that are still there).
  //
  // A "taken" list is used in a sort of analogous way to track
  // the indices of the documents after old_idx in old_results
  // that we have moved, so that, conversely, even though we will
  // come across them in old_results, they are actually no longer
  // in the observer's array.
  //
  // To determine which docs should be considered "moved" (and which
  // merely change position because of other docs moving) we run
  // a "longest common subsequence" (LCS) algorithm.  The LCS of the
  // old doc IDs and the new doc IDs gives the docs that should NOT be
  // considered moved.
  //
  // Overall, this diff implementation is asymptotically good, but could
  // be optimized to streamline execution and use less memory (e.g. not
  // have to build data structures with an entry for every doc).

  // Asymptotically: O(N k) where k is number of ops, or potentially
  // O(N log N) if inner loop of LCS were made to be binary search.

  //////// LCS (longest common sequence, with respect to _id)
  // (see Wikipedia article on Longest Increasing Subsequence,
  // where the LIS is taken of the sequence of old indices of the
  // docs in new_results)
  //
  // unmoved: the output of the algorithm; members of the LCS,
  // in the form of indices into new_results
  var unmoved = [];
  // max_seq_len: length of LCS found so far
  var max_seq_len = 0;
  // seq_ends[i]: the index into new_results of the last doc in a
  // common subsequence of length of i+1 <= max_seq_len
  var N = new_results.length;
  var seq_ends = new Array(N);
  // ptrs:  the common subsequence ending with new_results[n] extends
  // a common subsequence ending with new_results[ptr[n]], unless
  // ptr[n] is -1.
  var ptrs = new Array(N);
  // virtual sequence of old indices of new results
  var old_idx_seq = function(i_new) {
    return old_index_of_id[new_results[i_new]._id];
  };
  // for each item in new_results, use it to extend a common subsequence
  // of length j <= max_seq_len
  for(var i=0; i<N; i++) {
    if (old_index_of_id[new_results[i]._id] !== undefined) {
      var j = max_seq_len;
      // this inner loop would traditionally be a binary search,
      // but scanning backwards we will likely find a subseq to extend
      // pretty soon, bounded for example by the total number of ops.
      // If this were to be changed to a binary search, we'd still want
      // to scan backwards a bit as an optimization.
      while (j > 0) {
        if (old_idx_seq(seq_ends[j-1]) < old_idx_seq(i))
          break;
        j--;
      }

      ptrs[i] = (j === 0 ? -1 : seq_ends[j-1]);
      seq_ends[j] = i;
      if (j+1 > max_seq_len)
        max_seq_len = j+1;
    }
  }

  // pull out the LCS/LIS into unmoved
  var idx = (max_seq_len === 0 ? -1 : seq_ends[max_seq_len-1]);
  while (idx >= 0) {
    unmoved.push(idx);
    idx = ptrs[idx];
  }
  // the unmoved item list is built backwards, so fix that
  unmoved.reverse();

  // the last group is always anchored by the end of the result list, which is
  // an id of "null"
  unmoved.push(new_results.length);

  _.each(old_results, function (doc) {
    if (!new_presence_of_id[doc._id])
      observer.removed(doc._id);
  });
  // for each group of things in the new_results that is anchored by an unmoved
  // element, iterate through the things before it.
  var startOfGroup = 0;
  _.each(unmoved, function (endOfGroup) {
    var groupId = new_results[endOfGroup] ? new_results[endOfGroup]._id : null;
    var oldDoc;
    var newDoc;
    var fields;
    for (var i = startOfGroup; i < endOfGroup; i++) {
      newDoc = new_results[i];
      if (!_.has(old_index_of_id, newDoc._id)) {
        fields = EJSON.clone(newDoc);
        delete fields._id;
        observer.addedBefore(newDoc._id, fields, groupId);
      } else {
        // moved
        oldDoc = old_results[old_index_of_id[newDoc._id]];
        fields = LocalCollection._makeChangedFields(newDoc, oldDoc);
        if (!_.isEmpty(fields)) {
          observer.changed(newDoc._id, fields);
        }
        observer.movedBefore(newDoc._id, groupId);
      }
    }
    if (groupId) {
      newDoc = new_results[endOfGroup];
      oldDoc = old_results[old_index_of_id[newDoc._id]];
      fields = LocalCollection._makeChangedFields(newDoc, oldDoc);
      if (!_.isEmpty(fields)) {
        observer.changed(newDoc._id, fields);
      }
    }
    startOfGroup = endOfGroup+1;
  });

};

// General helper for diff-ing two objects.
// callbacks is an object like so:
// { leftOnly: function (key, leftValue) {...},
//   rightOnly: function (key, rightValue) {...},
//   both: function (key, leftValue, rightValue) {...},
// }
LocalCollection._diffObjects = function (left, right, callbacks) {
  _.each(left, function (leftValue, key) {
    if (_.has(right, key))
      callbacks.both && callbacks.both(key, leftValue, right[key]);
    else
      callbacks.leftOnly && callbacks.leftOnly(key, leftValue);
  });
  if (callbacks.rightOnly) {
    _.each(right, function(rightValue, key) {
      if (!_.has(left, key))
        callbacks.rightOnly(key, rightValue);
    });
  }
};
<commit_msg>Fixing the giant comment in diff.js to be descriptive again<commit_after>
// ordered: bool.
// old_results and new_results: collections of documents.
//    if ordered, they are arrays.
//    if unordered, they are maps {_id: doc}.
// observer: object with 'added', 'changed', 'removed',
//           and (if ordered) 'moved' functions (each optional)
// deepcopy: if true, elements of new_results that are passed
//           to callbacks are deepcopied first.
LocalCollection._diffQueryChanges = function (ordered, oldResults, newResults,
                                       observer) {
  if (ordered)
    LocalCollection._diffQueryOrderedChanges(
      oldResults, newResults, observer);
  else
    LocalCollection._diffQueryUnorderedChanges(
      oldResults, newResults, observer);
};

LocalCollection._diffQueryUnorderedChanges = function (oldResults, newResults,
                                                observer) {
  if (observer.moved) {
    throw new Error("_diffQueryUnordered called with a moved observer!");
  }

  // "maybe deepcopy"
  _.each(newResults, function (newDoc) {
    if (_.has(oldResults, newDoc._id)) {
      var oldDoc = oldResults[newDoc._id];
      if (observer.changed && !EJSON.equals(oldDoc, newDoc)) {
        observer.changed(newDoc._id, LocalCollection._makeChangedFields(newDoc, oldDoc));
      }
    } else {
      var fields = EJSON.clone(newDoc);
      delete fields._id;
      observer.added && observer.added(newDoc._id, fields);
    }
  });

  if (observer.removed) {
    _.each(oldResults, function (oldDoc) {
      if (!_.has(newResults, oldDoc._id))
        observer.removed(oldDoc._id);
    });
  }
};

LocalCollection._diffQueryOrderedChanges = function (old_results, new_results, observer) {

  var new_presence_of_id = {};
  _.each(new_results, function (doc) {
    if (new_presence_of_id[doc._id])
      Meteor._debug("Duplicate _id in new_results");
    new_presence_of_id[doc._id] = true;
  });

  var old_index_of_id = {};
  _.each(old_results, function (doc, i) {
    if (doc._id in old_index_of_id)
      Meteor._debug("Duplicate _id in old_results");
    old_index_of_id[doc._id] = i;
  });

  // ALGORITHM:
  //
  // To determine which docs should be considered "moved" (and which
  // merely change position because of other docs moving) we run
  // a "longest common subsequence" (LCS) algorithm.  The LCS of the
  // old doc IDs and the new doc IDs gives the docs that should NOT be
  // considered moved.
  //

  // Once we have the items that should not move, we walk through the new
  // results array group-by-group, where a "group" is a set of items that have
  // moved, anchored on the end by an item that should not move.  One by one, we
  // move each of those elements into place "before" the anchoring end-of-group
  // item, and fire changed events on them if necessary.  Then we fire a changed
  // event on the anchor, and move on to the next group.  There is always at
  // least one group; the last group is anchored by a virtual "null" id at the
  // end.

  // Asymptotically: O(N k) where k is number of ops, or potentially
  // O(N log N) if inner loop of LCS were made to be binary search.

  //////// LCS (longest common sequence, with respect to _id)
  // (see Wikipedia article on Longest Increasing Subsequence,
  // where the LIS is taken of the sequence of old indices of the
  // docs in new_results)
  //
  // unmoved: the output of the algorithm; members of the LCS,
  // in the form of indices into new_results
  var unmoved = [];
  // max_seq_len: length of LCS found so far
  var max_seq_len = 0;
  // seq_ends[i]: the index into new_results of the last doc in a
  // common subsequence of length of i+1 <= max_seq_len
  var N = new_results.length;
  var seq_ends = new Array(N);
  // ptrs:  the common subsequence ending with new_results[n] extends
  // a common subsequence ending with new_results[ptr[n]], unless
  // ptr[n] is -1.
  var ptrs = new Array(N);
  // virtual sequence of old indices of new results
  var old_idx_seq = function(i_new) {
    return old_index_of_id[new_results[i_new]._id];
  };
  // for each item in new_results, use it to extend a common subsequence
  // of length j <= max_seq_len
  for(var i=0; i<N; i++) {
    if (old_index_of_id[new_results[i]._id] !== undefined) {
      var j = max_seq_len;
      // this inner loop would traditionally be a binary search,
      // but scanning backwards we will likely find a subseq to extend
      // pretty soon, bounded for example by the total number of ops.
      // If this were to be changed to a binary search, we'd still want
      // to scan backwards a bit as an optimization.
      while (j > 0) {
        if (old_idx_seq(seq_ends[j-1]) < old_idx_seq(i))
          break;
        j--;
      }

      ptrs[i] = (j === 0 ? -1 : seq_ends[j-1]);
      seq_ends[j] = i;
      if (j+1 > max_seq_len)
        max_seq_len = j+1;
    }
  }

  // pull out the LCS/LIS into unmoved
  var idx = (max_seq_len === 0 ? -1 : seq_ends[max_seq_len-1]);
  while (idx >= 0) {
    unmoved.push(idx);
    idx = ptrs[idx];
  }
  // the unmoved item list is built backwards, so fix that
  unmoved.reverse();

  // the last group is always anchored by the end of the result list, which is
  // an id of "null"
  unmoved.push(new_results.length);

  _.each(old_results, function (doc) {
    if (!new_presence_of_id[doc._id])
      observer.removed(doc._id);
  });
  // for each group of things in the new_results that is anchored by an unmoved
  // element, iterate through the things before it.
  var startOfGroup = 0;
  _.each(unmoved, function (endOfGroup) {
    var groupId = new_results[endOfGroup] ? new_results[endOfGroup]._id : null;
    var oldDoc;
    var newDoc;
    var fields;
    for (var i = startOfGroup; i < endOfGroup; i++) {
      newDoc = new_results[i];
      if (!_.has(old_index_of_id, newDoc._id)) {
        fields = EJSON.clone(newDoc);
        delete fields._id;
        observer.addedBefore(newDoc._id, fields, groupId);
      } else {
        // moved
        oldDoc = old_results[old_index_of_id[newDoc._id]];
        fields = LocalCollection._makeChangedFields(newDoc, oldDoc);
        if (!_.isEmpty(fields)) {
          observer.changed(newDoc._id, fields);
        }
        observer.movedBefore(newDoc._id, groupId);
      }
    }
    if (groupId) {
      newDoc = new_results[endOfGroup];
      oldDoc = old_results[old_index_of_id[newDoc._id]];
      fields = LocalCollection._makeChangedFields(newDoc, oldDoc);
      if (!_.isEmpty(fields)) {
        observer.changed(newDoc._id, fields);
      }
    }
    startOfGroup = endOfGroup+1;
  });

};

// General helper for diff-ing two objects.
// callbacks is an object like so:
// { leftOnly: function (key, leftValue) {...},
//   rightOnly: function (key, rightValue) {...},
//   both: function (key, leftValue, rightValue) {...},
// }
LocalCollection._diffObjects = function (left, right, callbacks) {
  _.each(left, function (leftValue, key) {
    if (_.has(right, key))
      callbacks.both && callbacks.both(key, leftValue, right[key]);
    else
      callbacks.leftOnly && callbacks.leftOnly(key, leftValue);
  });
  if (callbacks.rightOnly) {
    _.each(right, function(rightValue, key) {
      if (!_.has(left, key))
        callbacks.rightOnly(key, rightValue);
    });
  }
};
<|endoftext|>


<commit_before>
//Byggnads väljare
function byggnad(urlfranlankarbyggnad){
console.log("Går in i byggnad funktionen");
	skapabyggnadtable();
	$.ajax({
			url: urlfranlankarbyggnad,
			success: function(data) {
				var byggnadtable = document.getElementById('byggnad');
				var indifiera;
				var byggnadlank;
				var delabyggnadlank;
				indifiera = $(data).find("#lblShowFirstAvailable");
				if(indifiera.length != 0){
historia("byggnad()", urlfranlankarbyggnad);
console.log("Byggnad finns!")
					byggnadlank = $(data).find("td .headerColor");
					var d = 0;

					for(var i = 0; i < byggnadlank.length; i++){
console.log('Bygger upp table för byggnad');
						var byggnadrow = byggnadtable.insertRow(-1);
						var byggnadcell = byggnadrow.insertCell(-1);

						if(byggnadlank[d].onmousedown != null){
console.log('Kollar byggnad if-sats');
							byggnadcell.setAttribute("class", "byggnadnav");
							delabyggnadlank = String(byggnadlank[d].onmousedown).split("'",2);
							delabyggnadlank = "'http://tvatta.sgsstudentbostader.se/" + delabyggnadlank[1] + "'";
							byggnadcell.innerHTML = ''+
							byggnadlank[d].innerText + "";
						}
						d++;
					}
console.log('Slut av for-loop');
				}
				else{
console.log("Verkar inte ha funnits någon byggnad???")
					loadtvatta('http://www.sgsstudentbostader.se/ext_gw.aspx?module=wwwash&lang=se#lblPanelName');
				}

								}
	})

}

var nastaveckafram;
var nastaveckabak;
var lokalenriktig;
var typlokalriktig;
var lankartvattariktig;
//Vi laddar in hela tvatta.sgsstudentbostader.se
function loadtvatta(urlfranlankar){
historia('loadtvatta()');
//console.log("Går in i tvätta funktionen");
	skapatvattatable();
	var tvattaimg;
	var antaltider;
	var nummer;
	var dagar;
	var tiderdygnet;
	var lankartvatta;
	var valjabokning;
	var typlokal;
	var c = 0;
	var lank;
	var recordposition;
	var table = document.getElementById('tvatta');
	var navtable = document.getElementById('navtvatta');
	var navtablebottom = document.getElementById('navtablebottom');
	$.ajax({
			url: urlfranlankar,
			success: function(data) {
//console.log('Går in i ajax');
				var root2 = document.getElementById('mydiv2');
				var tab2=document.createElement('table');
				tvattaimg = $(data).find("#tbl1 [src]");
				nummer = $(data).find("#tbl1 a");
				antaltider = $(data).find( "#tbl1 tr:contains('-')");
				dagar = $(data).find("#tbl1 th");
				lank = $(data).find("#tbl1 [onmousedown]");
				tiderdygnet = $(data).find("#tbl1 td:contains(':')");
				lankartvatta = $(data).find("#tblNav td.periodLinkColor");
				valjabokning = $(data).find("table td[width=12%][align].headerColor");
				typlokal = $(data).find("td[background]");
				var antal = antaltider.length;

				//Välja typ av lokal att boka
				if(valjabokning.length != 0){
				var valjabokningtext;
				var rakna = 0;
					var lokalrow = navtable.insertRow(-1);
					lokalrow.setAttribute("id", "navlokal");
					for(var l=0; l < valjabokning.length; l++){
						var lokalcell = lokalrow.insertCell(-1);
						if(valjabokning[rakna].onmousedown == null){
//console.log("Den går in i if satsen för olika lokaler");
							lokalcell.setAttribute("class", "lokalnav");
							valjabokningtext = String(valjabokning[rakna].innerHTML).split(' ');
							var navnummer = String("navnummer");
							lokalcell.innerHTML = ''+ valjabokningtext[0] +'';
							recordposition = l;
							rakna++;
						}
						else{
						lokalenriktig = String(valjabokning[rakna].onmousedown).split("'", 2);
						lokalenriktig = "'http://tvatta.sgsstudentbostader.se/"+ lokalenriktig[1] +"'";
						lokalcell.setAttribute("class", "lokalnavlank");
						lokalcell.setAttribute("onmousedown", "loadtvatta("+ lokalenriktig +")" )
						valjabokningtext = String(valjabokning[rakna].innerHTML).split(' ');
						lokalcell.innerHTML = ''+ valjabokningtext[0] +'';
						rakna++;
							}
					}
				}

				//Välja vilken lokal att boka i
				if(typlokal.length != 0){
				var typlokaltext;
				var typrakna = 0;
				//console.log(recordposition);
					var u = 0;
					for(var t = 0; t < typlokal.length; t++){
						var typrow = navtable.insertRow(-1);
						for(var u = 0; u < recordposition; u++){
						typrow.insertCell(-1);
						//console.log('Går in i recordposition');
						}

						typrow.setAttribute("id", "navnummer")
						var typcell = typrow.insertCell(-1);
						if(typlokal[typrakna].onmousedown == null){
						typcell.setAttribute("class", "typlokal");
						typlokaltext = String(typlokal[typrakna].innerHTML).split(' ');
						typcell.innerHTML = '' + typlokaltext[0] +'';
						typrakna++;
						}
						else{
						typlokalriktig = String(typlokal[typrakna].onmousedown).split("'", 2);
						typlokalriktig = "'http://tvatta.sgsstudentbostader.se/"+ typlokalriktig[1] +"'";
						typcell.setAttribute("class", "typlokallank");
						typcell.setAttribute("onmousedown", "loadtvatta("+typlokalriktig +")")
						typlokaltext = String(typlokal[typrakna].innerHTML).split(' ');
						typcell.innerHTML = ''+ typlokaltext[0] +'';
						typrakna++;
						}
					}

				}

				//Navigerings framåt och bakåt
				if(lankartvatta.length != 0){
				var navrakna = 0;
				var lankartvattatext;
					var navrow = navtablebottom.insertRow(-1);
					for(var lt = 0; lt < lankartvatta.length; lt++){
						var navcell = navrow.insertCell(-1);
						lankartvattariktig = String(lankartvatta[navrakna].onmousedown).split("'", 2);
						lankartvattariktig = "'http://tvatta.sgsstudentbostader.se/"+ lankartvattariktig[1] +"'";
						lankartvattatext = String(lankartvatta[navrakna].innerText).split(' ');
						navcell.setAttribute("onmousedown", "loadtvatta("+lankartvattariktig +")")
						navcell.setAttribute("class", "navknapparlank");
						navcell.innerHTML = '' + lankartvattatext[0] +'';
						navrakna++;
					}
				}

				//header med tider
				var f = 0;
				var tiderdygnetriktig;
				var headrow = table.insertRow(-1);
				headrow.insertCell(-1);
				for (var h = 0; h < antal; h++){
						var headcell = headrow.insertCell(-1);
						headcell.setAttribute("class", "bokningstider");
						tiderdygnetriktig = String(tiderdygnet[f].innerHTML).split(' ');
//console.log(tiderdygnetriktig[2]);
						headcell.innerHTML = "
" + tiderdygnetriktig[2] + "
";

						f++
						}

				//Här byggs tvatta tabeln upp
				var smart = 0;
				var extra = 6;
				var q = 1;
				var nollstall = ((antal * 7)-1);
				//Datum och dagar
				for (var b = 0; b < 7; b++){
					var dagarriktiga;
					var row = table.insertRow(-1)
					var cell2 = row.insertCell(-1);
					cell2.setAttribute("class", "bokningsdatum");
					dagarriktiga = String(dagar[q].innerHTML).split('dag');
//console.log(dagarriktiga[1]);
					cell2.innerHTML = "
" + dagarriktiga[0] + dagarriktiga[1] + "
"
					q++;
						if(b >= 1){
						smart = (smart - nollstall)
									}

				for (var i = 0; i < antal; i++){
					var tvattaimgriktig;
					var cell = row.insertCell(-1)
					tvattaimgriktig = String(tvattaimg[smart].outerHTML).split('.');
//console.log(tvattaimgriktig[0]);
					tvattaimgriktig = tvattaimgriktig[0] +'.png">';
//console.log(tvattaimgriktig);
					cell.setAttribute("class", "bokningsikoner");
					cell.innerHTML = "" + tvattaimgriktig + "";
//console.log(tvattaimg[smart].outerHTML);
					//kollar så att inte onmousedown är null

						if(tvattaimg[smart].parentNode.onmousedown != null){
							//splittar upp och tar ut endast värdet ur funktionen
							tvattaimgriktig = String(tvattaimg[smart].outerHTML).split('.');
							tvattaimgriktig = tvattaimgriktig[0] +'.png">';
							var split = String(tvattaimg[smart].parentNode.onmousedown).split("'",2);
							split = "'http://tvatta.sgsstudentbostader.se/" + split[1] +"','"+ urlfranlankar + "'";
							cell.setAttribute("class", "bokningsikoner");
							cell.innerHTML = ''
							+ tvattaimgriktig + "";
//console.log(split);
							}

					smart = (smart + extra);
					smart++

								}
								}

			}
			})
loadtvattaklar();
			}

//alt med hidden InAppBrowser
function bokatid(tiden,nuvarandebokning){
	console.log("Går in i funktionen bokatid");
	 var ref = window.open(tiden, '_blank', 'hidden=yes');

		 ref.addEventListener('loadstart', function(event2){
			console.log('Loadstart v.1.2');
			var spinnerevent = document.getElementById('loading');
			spinnerevent.style.display = 'inline';
		 })

		 ref.addEventListener('loadstop', function(event) {
		 	console.log('Loadstop v.1.3');
		 	//var loading2 = document.getElementById('loading');
			//loading2.style.display = 'none';
		 	console.log(event.url);
		 	console.log(event);
		 	})
		 ref.addEventListener('exit', function(event3){
			 console.log('Exit kanske fungerar bättre?');
		 })

loadtvatta(nuvarandebokning);
}

function show(){
	var spinnerevent = document.getElementById('loading');
	spinnerevent.style.display = 'inline';
}

//hemma.sgsstudentbostader.se

function hamtahemma(){
	$.ajax({
			url: 'http://hemma.sgsstudentbostader.se/DoorControl/Fullscreen',
			success: function(varde) {
			var buttonvalue;
			var buttonname;
							buttonvalue = $(varde).find('button').attr('value');
							buttonname = $(varde).find('button');
							document.getElementById('hemmadorren').value = buttonvalue;
							document.getElementById('hemmadorren').innerHTML = buttonname[0].innerHTML
							setTimeout(oppnadorr,500);
			},
			error: function(varde2){

					hemmafel();
			}
			});

			}

function oppnadorr(){
console.log("1");
	var sendform = document.getElementById('hemmadorren');
console.log("1");
	$.ajax({
		type: "POST",
		url: "http://hemma.sgsstudentbostader.se/DoorControl/PerformUnlock",
		data: "epName=" + encodeURI(sendform.value),
		charset: 'UTF-8',
		success: function(data){
			var vilkenhemma = $(data).find('.doorControlEntryPath');
			vilkenhemma = vilkenhemma[0].innerHTML;
			console.log(vilkenhemma);

			var meddelandehemma = $(data).find('.doorControlMessage');
			meddelandehemma = meddelandehemma[0].innerHTML;

			hemmavilken(vilkenhemma,meddelandehemma);
			console.log(meddelandehemma[0].innerHTML);

			console.log(data);

		}

	})

console.log("1");

}
function show_navnummer(){

    var menu = document.getElementById("navnummer");
    console.log(menu);
    if(menu.style.display == 'table-row'){
        menu.style.display = 'none';
    }else {
        menu.style.display = 'table-row';
    }
}

function show_navlokal(){

	var menu = document.getElementById("navtvatta");
    if(menu.style.display == 'table'){
        menu.style.display = 'none';
    }else {
        menu.style.display = 'table';
    }
}

function loadtvattaklar(){
	console.log('laddat klart');
	var spinnerevent = document.getElementById('loading');
			spinnerevent.style.display = 'none';
}<commit_msg>event.url = nuvarandebokning???<commit_after>
//Byggnads väljare
function byggnad(urlfranlankarbyggnad){
console.log("Går in i byggnad funktionen");
	skapabyggnadtable();
	$.ajax({
			url: urlfranlankarbyggnad,
			success: function(data) {
				var byggnadtable = document.getElementById('byggnad');
				var indifiera;
				var byggnadlank;
				var delabyggnadlank;
				indifiera = $(data).find("#lblShowFirstAvailable");
				if(indifiera.length != 0){
historia("byggnad()", urlfranlankarbyggnad);
console.log("Byggnad finns!")
					byggnadlank = $(data).find("td .headerColor");
					var d = 0;

					for(var i = 0; i < byggnadlank.length; i++){
console.log('Bygger upp table för byggnad');
						var byggnadrow = byggnadtable.insertRow(-1);
						var byggnadcell = byggnadrow.insertCell(-1);

						if(byggnadlank[d].onmousedown != null){
console.log('Kollar byggnad if-sats');
							byggnadcell.setAttribute("class", "byggnadnav");
							delabyggnadlank = String(byggnadlank[d].onmousedown).split("'",2);
							delabyggnadlank = "'http://tvatta.sgsstudentbostader.se/" + delabyggnadlank[1] + "'";
							byggnadcell.innerHTML = ''+
							byggnadlank[d].innerText + "";
						}
						d++;
					}
console.log('Slut av for-loop');
				}
				else{
console.log("Verkar inte ha funnits någon byggnad???")
					loadtvatta('http://www.sgsstudentbostader.se/ext_gw.aspx?module=wwwash&lang=se#lblPanelName');
				}

								}
	})

}

var nastaveckafram;
var nastaveckabak;
var lokalenriktig;
var typlokalriktig;
var lankartvattariktig;
//Vi laddar in hela tvatta.sgsstudentbostader.se
function loadtvatta(urlfranlankar){
historia('loadtvatta()');
//console.log("Går in i tvätta funktionen");
	skapatvattatable();
	var tvattaimg;
	var antaltider;
	var nummer;
	var dagar;
	var tiderdygnet;
	var lankartvatta;
	var valjabokning;
	var typlokal;
	var c = 0;
	var lank;
	var recordposition;
	var table = document.getElementById('tvatta');
	var navtable = document.getElementById('navtvatta');
	var navtablebottom = document.getElementById('navtablebottom');
	$.ajax({
			url: urlfranlankar,
			success: function(data) {
//console.log('Går in i ajax');
				var root2 = document.getElementById('mydiv2');
				var tab2=document.createElement('table');
				tvattaimg = $(data).find("#tbl1 [src]");
				nummer = $(data).find("#tbl1 a");
				antaltider = $(data).find( "#tbl1 tr:contains('-')");
				dagar = $(data).find("#tbl1 th");
				lank = $(data).find("#tbl1 [onmousedown]");
				tiderdygnet = $(data).find("#tbl1 td:contains(':')");
				lankartvatta = $(data).find("#tblNav td.periodLinkColor");
				valjabokning = $(data).find("table td[width=12%][align].headerColor");
				typlokal = $(data).find("td[background]");
				var antal = antaltider.length;

				//Välja typ av lokal att boka
				if(valjabokning.length != 0){
				var valjabokningtext;
				var rakna = 0;
					var lokalrow = navtable.insertRow(-1);
					lokalrow.setAttribute("id", "navlokal");
					for(var l=0; l < valjabokning.length; l++){
						var lokalcell = lokalrow.insertCell(-1);
						if(valjabokning[rakna].onmousedown == null){
//console.log("Den går in i if satsen för olika lokaler");
							lokalcell.setAttribute("class", "lokalnav");
							valjabokningtext = String(valjabokning[rakna].innerHTML).split(' ');
							var navnummer = String("navnummer");
							lokalcell.innerHTML = ''+ valjabokningtext[0] +'';
							recordposition = l;
							rakna++;
						}
						else{
						lokalenriktig = String(valjabokning[rakna].onmousedown).split("'", 2);
						lokalenriktig = "'http://tvatta.sgsstudentbostader.se/"+ lokalenriktig[1] +"'";
						lokalcell.setAttribute("class", "lokalnavlank");
						lokalcell.setAttribute("onmousedown", "loadtvatta("+ lokalenriktig +")" )
						valjabokningtext = String(valjabokning[rakna].innerHTML).split(' ');
						lokalcell.innerHTML = ''+ valjabokningtext[0] +'';
						rakna++;
							}
					}
				}

				//Välja vilken lokal att boka i
				if(typlokal.length != 0){
				var typlokaltext;
				var typrakna = 0;
				//console.log(recordposition);
					var u = 0;
					for(var t = 0; t < typlokal.length; t++){
						var typrow = navtable.insertRow(-1);
						for(var u = 0; u < recordposition; u++){
						typrow.insertCell(-1);
						//console.log('Går in i recordposition');
						}

						typrow.setAttribute("id", "navnummer")
						var typcell = typrow.insertCell(-1);
						if(typlokal[typrakna].onmousedown == null){
						typcell.setAttribute("class", "typlokal");
						typlokaltext = String(typlokal[typrakna].innerHTML).split(' ');
						typcell.innerHTML = '' + typlokaltext[0] +'';
						typrakna++;
						}
						else{
						typlokalriktig = String(typlokal[typrakna].onmousedown).split("'", 2);
						typlokalriktig = "'http://tvatta.sgsstudentbostader.se/"+ typlokalriktig[1] +"'";
						typcell.setAttribute("class", "typlokallank");
						typcell.setAttribute("onmousedown", "loadtvatta("+typlokalriktig +")")
						typlokaltext = String(typlokal[typrakna].innerHTML).split(' ');
						typcell.innerHTML = ''+ typlokaltext[0] +'';
						typrakna++;
						}
					}

				}

				//Navigerings framåt och bakåt
				if(lankartvatta.length != 0){
				var navrakna = 0;
				var lankartvattatext;
					var navrow = navtablebottom.insertRow(-1);
					for(var lt = 0; lt < lankartvatta.length; lt++){
						var navcell = navrow.insertCell(-1);
						lankartvattariktig = String(lankartvatta[navrakna].onmousedown).split("'", 2);
						lankartvattariktig = "'http://tvatta.sgsstudentbostader.se/"+ lankartvattariktig[1] +"'";
						lankartvattatext = String(lankartvatta[navrakna].innerText).split(' ');
						navcell.setAttribute("onmousedown", "loadtvatta("+lankartvattariktig +")")
						navcell.setAttribute("class", "navknapparlank");
						navcell.innerHTML = '' + lankartvattatext[0] +'';
						navrakna++;
					}
				}

				//header med tider
				var f = 0;
				var tiderdygnetriktig;
				var headrow = table.insertRow(-1);
				headrow.insertCell(-1);
				for (var h = 0; h < antal; h++){
						var headcell = headrow.insertCell(-1);
						headcell.setAttribute("class", "bokningstider");
						tiderdygnetriktig = String(tiderdygnet[f].innerHTML).split(' ');
//console.log(tiderdygnetriktig[2]);
						headcell.innerHTML = "
" + tiderdygnetriktig[2] + "
";

						f++
						}

				//Här byggs tvatta tabeln upp
				var smart = 0;
				var extra = 6;
				var q = 1;
				var nollstall = ((antal * 7)-1);
				//Datum och dagar
				for (var b = 0; b < 7; b++){
					var dagarriktiga;
					var row = table.insertRow(-1)
					var cell2 = row.insertCell(-1);
					cell2.setAttribute("class", "bokningsdatum");
					dagarriktiga = String(dagar[q].innerHTML).split('dag');
//console.log(dagarriktiga[1]);
					cell2.innerHTML = "
" + dagarriktiga[0] + dagarriktiga[1] + "
"
					q++;
						if(b >= 1){
						smart = (smart - nollstall)
									}

				for (var i = 0; i < antal; i++){
					var tvattaimgriktig;
					var cell = row.insertCell(-1)
					tvattaimgriktig = String(tvattaimg[smart].outerHTML).split('.');
//console.log(tvattaimgriktig[0]);
					tvattaimgriktig = tvattaimgriktig[0] +'.png">';
//console.log(tvattaimgriktig);
					cell.setAttribute("class", "bokningsikoner");
					cell.innerHTML = "" + tvattaimgriktig + "";
//console.log(tvattaimg[smart].outerHTML);
					//kollar så att inte onmousedown är null

						if(tvattaimg[smart].parentNode.onmousedown != null){
							//splittar upp och tar ut endast värdet ur funktionen
							tvattaimgriktig = String(tvattaimg[smart].outerHTML).split('.');
							tvattaimgriktig = tvattaimgriktig[0] +'.png">';
							var split = String(tvattaimg[smart].parentNode.onmousedown).split("'",2);
							split = "'http://tvatta.sgsstudentbostader.se/" + split[1] +"','"+ urlfranlankar + "'";
							cell.setAttribute("class", "bokningsikoner");
							cell.innerHTML = ''
							+ tvattaimgriktig + "";
//console.log(split);
							}

					smart = (smart + extra);
					smart++

								}
								}

			}
			})
loadtvattaklar();
			}

//alt med hidden InAppBrowser
function bokatid(tiden,nuvarandebokning){
	console.log("Går in i funktionen bokatid");
	 var ref = window.open(tiden, '_blank', 'hidden=yes');

		 ref.addEventListener('loadstart', function(event2){
			console.log('Loadstart v.1.2');
			var spinnerevent = document.getElementById('loading');
			spinnerevent.style.display = 'inline';
		 })

		 ref.addEventListener('loadstop', function(event) {
		 	console.log('Loadstop v.1.3');
		 	//var loading2 = document.getElementById('loading');
			//loading2.style.display = 'none';
		 	console.log(event.url);
		 	console.log(event);
		 	console.log(nuvarandebokning);
		 	})
		 ref.addEventListener('exit', function(event3){
			 console.log('Exit kanske fungerar bättre?');
		 })

loadtvatta(nuvarandebokning);
}

function show(){
	var spinnerevent = document.getElementById('loading');
	spinnerevent.style.display = 'inline';
}

//hemma.sgsstudentbostader.se

function hamtahemma(){
	$.ajax({
			url: 'http://hemma.sgsstudentbostader.se/DoorControl/Fullscreen',
			success: function(varde) {
			var buttonvalue;
			var buttonname;
							buttonvalue = $(varde).find('button').attr('value');
							buttonname = $(varde).find('button');
							document.getElementById('hemmadorren').value = buttonvalue;
							document.getElementById('hemmadorren').innerHTML = buttonname[0].innerHTML
							setTimeout(oppnadorr,500);
			},
			error: function(varde2){

					hemmafel();
			}
			});

			}

function oppnadorr(){
console.log("1");
	var sendform = document.getElementById('hemmadorren');
console.log("1");
	$.ajax({
		type: "POST",
		url: "http://hemma.sgsstudentbostader.se/DoorControl/PerformUnlock",
		data: "epName=" + encodeURI(sendform.value),
		charset: 'UTF-8',
		success: function(data){
			var vilkenhemma = $(data).find('.doorControlEntryPath');
			vilkenhemma = vilkenhemma[0].innerHTML;
			console.log(vilkenhemma);

			var meddelandehemma = $(data).find('.doorControlMessage');
			meddelandehemma = meddelandehemma[0].innerHTML;

			hemmavilken(vilkenhemma,meddelandehemma);
			console.log(meddelandehemma[0].innerHTML);

			console.log(data);

		}

	})

console.log("1");

}
function show_navnummer(){

    var menu = document.getElementById("navnummer");
    console.log(menu);
    if(menu.style.display == 'table-row'){
        menu.style.display = 'none';
    }else {
        menu.style.display = 'table-row';
    }
}

function show_navlokal(){

	var menu = document.getElementById("navtvatta");
    if(menu.style.display == 'table'){
        menu.style.display = 'none';
    }else {
        menu.style.display = 'table';
    }
}

function loadtvattaklar(){
	console.log('laddat klart');
	var spinnerevent = document.getElementById('loading');
			spinnerevent.style.display = 'none';
}<|endoftext|>


<commit_before>// Generated on 2015-10-23 using generator-angular-fullstack 2.1.1
'use strict';
module.exports = function (grunt) {

    require("load-grunt-tasks")(grunt);

    // Time how long tasks take. Can help when optimizing build times
    require('time-grunt')(grunt);

    // Add the grunt-mocha-test tasks.
    grunt.loadNpmTasks('grunt-mocha-test');

    grunt.initConfig({
        // Configure a mochaTest task
        mochaTest: {
            test: {
                options: {
                    reporter: 'spec'
                },
                src: ['test/**/*.js']
            }
        },

        clean: {
            lib: 'lib/*'
        },

        babel: {
            options: {
                sourceMap: true,
                experimental: true,
                modules: "amd"        //This is the line to be added.
            },
            lib: {
                files: [{
                    "expand": true,
                    "cwd": "src/",
                    "src": ["**/*.js"],
                    "dest": "lib/",
                    "ext": ".js"
                }]
            }
        }
    });

    grunt.registerTask('test', function () {
        return grunt.task.run([
            'mochaTest'
        ]);
    });

    grunt.registerTask("build", function () {
        return grunt.task.run([
            'clean:lib',
            'babel:lib'
        ]);
    });
};<commit_msg>Update<commit_after>// Generated on 2015-10-23 using generator-angular-fullstack 2.1.1
'use strict';
module.exports = function (grunt) {

    require("load-grunt-tasks")(grunt);

    // Time how long tasks take. Can help when optimizing build times
    require('time-grunt')(grunt);

    // Add the grunt-mocha-test tasks.
    grunt.loadNpmTasks('grunt-mocha-test');

    grunt.initConfig({
        // Configure a mochaTest task
        mochaTest: {
            test: {
                options: {
                    reporter: 'spec'
                },
                src: ['./test/**/*.js']
            }
        },

        clean: {
            lib: './lib/*'
        },

        babel: {
            options: {
                sourceMap: true,
                experimental: true,
                modules: "amd"        //This is the line to be added.
            },
            lib: {
                files: [{
                    "expand": true,
                    "cwd": "./src/",
                    "src": ["./**/*.js"],
                    "dest": "./lib/",
                    "ext": ".js"
                }]
            }
        }
    });

    grunt.registerTask('test', function () {
        return grunt.task.run([
            'mochaTest'
        ]);
    });

    grunt.registerTask("build", function () {
        return grunt.task.run([
            'clean:lib',
            'babel:lib'
        ]);
    });
};<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import React from 'react'
import {string, bool, shape} from 'prop-types'
import {stringify} from 'qs'
import permissionFilter from '../shared/helpers/permissionFilter'
import CoursesStore from './store/CoursesStore'
import TermsStore from './store/TermsStore'
import AccountsTreeStore from './store/AccountsTreeStore'
import UsersStore from './store/UsersStore'

const stores = [CoursesStore, TermsStore, AccountsTreeStore, UsersStore]

export default class AccountCourseUserSearch extends React.Component {
  static propTypes = {
    accountId: string.isRequired,
    rootAccountId: string.isRequired,
    permissions: shape({
      analytics: bool.isRequired
    }).isRequired
  }

  componentWillMount() {
    const {accountId, rootAccountId} = this.props
    stores.forEach(s => {
      s.reset({accountId, rootAccountId})
    })
  }

  updateQueryParams(params) {
    const query = stringify(params)
    window.history.replaceState(null, null, `?${query}`)
  }

  render() {
    const tabList = this.props.store.getState().tabList
    const tabs = permissionFilter(tabList.tabs, this.props.permissions)
    const ActivePane = tabs[tabList.selected].pane

    return (
      <ActivePane
        {...{
          ...this.props,
          onUpdateQueryParams: this.updateQueryParams,
          queryParams: tabList.queryParams
        }}
      />
    )
  }
}
<commit_msg>Make site admin deal with new user course search<commit_after>/*
 * Copyright (C) 2015 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import React from 'react'
import {string, bool, shape} from 'prop-types'
import {stringify} from 'qs'
import permissionFilter from '../shared/helpers/permissionFilter'
import CoursesStore from './store/CoursesStore'
import TermsStore from './store/TermsStore'
import AccountsTreeStore from './store/AccountsTreeStore'
import UsersStore from './store/UsersStore'

const stores = [CoursesStore, TermsStore, AccountsTreeStore, UsersStore]

export default class AccountCourseUserSearch extends React.Component {
  static propTypes = {
    accountId: string.isRequired,
    rootAccountId: string.isRequired,
    permissions: shape({
      analytics: bool.isRequired
    }).isRequired
  }

  componentWillMount() {
    const {accountId, rootAccountId} = this.props
    stores.forEach(s => {
      s.reset({accountId, rootAccountId})
    })
  }

  updateQueryParams(params) {
    const query = stringify(params)
    window.history.replaceState(null, null, `?${query}`)
  }

  render() {
    const tabList = this.props.store.getState().tabList
    const tabs = permissionFilter(tabList.tabs, this.props.permissions)
    const ActivePane = (tabs.length === 1) ? tabs[0].pane : tabs[tabList.selected].pane

    return (
      <ActivePane
        {...{
          ...this.props,
          onUpdateQueryParams: this.updateQueryParams,
          queryParams: tabList.queryParams
        }}
      />
    )
  }
}
<|endoftext|>