<commit_before>const moment               = require('moment');
const SetCurrency          = require('./set_currency');
const BinaryPjax           = require('../../base/binary_pjax');
const Client               = require('../../base/client');
const BinarySocket         = require('../../base/socket');
const AccountOpening       = require('../../common/account_opening');
const showPopup            = require('../../common/attach_dom/popup');
const Currency             = require('../../common/currency');
const localize             = require('../../../_common/localize').localize;
const State                = require('../../../_common/storage').State;
const urlFor               = require('../../../_common/url').urlFor;

const Accounts = (() => {
    let landing_company;
    const form_id = '#new_accounts';

    const TableHeaders = (() => {
        let table_headers;

        const initTableHeaders = () => ({
            account          : localize('Account'),
            available_markets: localize('Available Markets'),
            type             : localize('Type'),
            currency         : localize('Currency'),
        });

        return {
            get: () => {
                if (!table_headers) {
                    table_headers = initTableHeaders();
                }
                return table_headers;
            },
        };
    })();

    const onLoad = () => {
        if (!Client.get('residence')) {
            // ask client to set residence first since cannot wait landing_company otherwise
            BinaryPjax.load(urlFor('user/settings/detailsws'));
        }
        clearPopup();
        BinarySocket.send({ statement: 1, limit: 1 });
        BinarySocket.wait('landing_company', 'get_settings', 'statement', 'mt5_login_list').then(() => {
            landing_company           = State.getResponse('landing_company');
            const can_change_currency = Client.canChangeCurrency(State.getResponse('statement'), State.getResponse('mt5_login_list'));
            const is_virtual          = Client.get('is_virtual');
            const has_real_account    = Client.hasAccountType('real');
            populateExistingAccounts();

            let element_to_show = '#no_new_accounts_wrapper';
            const upgrade_info  = Client.getUpgradeInfo();
            if (upgrade_info.can_upgrade) {
                // VRTC SVG has can_upgrade, but they are only allowed to open crypto related
                // accounts. This is a check to ignore the account creation form for them
                if (upgrade_info.can_open_multi || !upgrade_info.can_upgrade_to.includes('svg') || !has_real_account) {
                    populateNewAccounts(upgrade_info);
                    element_to_show = '#new_accounts_wrapper';
                }
            }

            if (upgrade_info.can_open_multi || (upgrade_info.can_upgrade_to.includes('svg') && is_virtual && has_real_account)) {
                populateMultiAccount();
            } else if (!can_change_currency) {
                doneLoading(element_to_show);
            }

            if (can_change_currency) {
                addChangeCurrencyOption();
                element_to_show = '#new_accounts_wrapper';
                if (!upgrade_info.can_open_multi) {
                    doneLoading(element_to_show);
                }
            }
        });
    };

    const clearPopup = () => {
        SetCurrency.cleanupPopup();
    };

    const doneLoading = (element_to_show) => {
        $(element_to_show).setVisibility(1);
        $('#accounts_loading').remove();
        $('#accounts_wrapper').setVisibility(1);
    };

    const getCompanyName = account => Client.getLandingCompanyValue(account, landing_company, 'name');

    const getCompanyCountry = account => Client.getLandingCompanyValue(account, landing_company, 'country');

    const populateNewAccounts = (upgrade_info) => {
        const table_headers = TableHeaders.get();
        upgrade_info.type.forEach((new_account_type, index) => {
            const getAccountTitle = () => {
                if (new_account_type === 'financial') {
                    return localize('Financial Account');
                }
                if (upgrade_info.can_upgrade_to[index] === 'malta') {
                    return localize('Gaming Account');
                }

                return localize('Real Account');
            };

            const account           = {
                real     : new_account_type === 'real',
                financial: new_account_type === 'financial',
            };
            const new_account_title = getAccountTitle();
            $(form_id).find('tbody')
                .append($('<tr/>')
                    .append($('<td/>', { datath: table_headers.account }).html($('<span/>', {
                        text          : new_account_title,
                        'data-balloon': `${localize('Counterparty')}: ${getCompanyName(account)}, ${localize(
                            'Jurisdiction')}: ${getCompanyCountry(account)}`,
                        'data-balloon-length': 'large',
                    })))
                    .append($('<td/>', { text: getAvailableMarkets(account), datath: table_headers.available_markets }))
                    .append($('<td/>')
                        .html($(
                            '<a/>',
                            {
                                class: 'button',
                                href : AccountOpening.getSinupPageLink(
                                    upgrade_info,
                                    upgrade_info.can_upgrade_to[index]
                                ),
                            },
                        )
                            .html($('<span/>', { text: localize('Create account') })))));
        });
    };

    const addChangeCurrencyOption = () => {
        if ($(form_id).find('#change_account_currency').length) {
            return;
        }
        const table_headers = TableHeaders.get();
        const loginid       = Client.get('loginid');

        // Set the table row
        $(form_id).find('tbody')
            .append($('<tr/>', { id: 'change_account_currency' })
                .append($('<td/>', { datath: table_headers.account }).html($('<span/>', {
                    text: loginid,
                })))
                .append($('<td/>', { text: getAvailableMarkets(loginid), datath: table_headers.available_markets }))
                .append($('<td/>', { id: 'change_currency_action' })
                    .html($('<button/>', {
                        id   : 'change_currency_btn',
                        class: 'button no-margin',
                        type : 'button',
                        text : localize('Change currency'),
                    }).on('click', () => showCurrencyPopUp('change')))));

        // Replace note to reflect ability to change currency
        $('#note > .hint').text(`${localize('Note: You are limited to one fiat currency account. The currency of your fiat account can be changed before you deposit into your fiat account for the first time or create an MT5 account. You may also open one account for each supported cryptocurrency.')}`);
    };

    const onConfirmSetCurrency = () => {
        const can_change_currency = Client.canChangeCurrency(State.getResponse('statement'), State.getResponse('mt5_login_list'));
        if (can_change_currency) {
            addChangeCurrencyOption();
        }
    };

    const action_map = {
        create: 'multi_account',
        set   : 'set_currency',
        change: 'change_currency',
    };

    const showCurrencyPopUp = (action) => {
        showPopup({
            url               : urlFor('user/set-currency'),
            content_id        : '#set_currency',
            form_id           : 'frm_set_currency',
            additionalFunction: async () => {
                localStorage.setItem('popup_action', action_map[action]);
                await SetCurrency.onLoad(onConfirmSetCurrency);
            },
        });
    };

    const populateExistingAccounts = () => {
        const all_login_ids = Client.getAllLoginids();
        // Populate active loginids first.
        all_login_ids
            .filter(loginid => !Client.get('is_disabled', loginid) && !Client.get('excluded_until', loginid))
            .sort((a, b) => a > b)
            .forEach((loginid) => {
                appendExistingAccounts(loginid);
            });

        // Populate disabled or self excluded loginids.
        all_login_ids
            .filter(loginid => Client.get('is_disabled', loginid) || Client.get('excluded_until', loginid))
            .sort((a, b) => a > b)
            .forEach((loginid) => {
                appendExistingAccounts(loginid);
            });
    };

    const appendExistingAccounts = (loginid) => {
        const table_headers     = TableHeaders.get();
        const account_currency  = Client.get('currency', loginid);
        const account_type_prop = { text: Client.getAccountTitle(loginid) };

        if (!Client.isAccountOfType('virtual', loginid)) {
            const company_name                       = getCompanyName(loginid);
            const company_country                    = getCompanyCountry(loginid);
            account_type_prop['data-balloon']        = `${localize('Counterparty')}: ${company_name}, ${localize('Jurisdiction')}: ${company_country}`;
            account_type_prop['data-balloon-length'] = 'large';
        }

        const is_disabled    = Client.get('is_disabled', loginid);
        const excluded_until = Client.get('excluded_until', loginid);
        let txt_markets;
        if (is_disabled) {
            txt_markets = localize('This account is disabled');
        } else if (excluded_until) {
            txt_markets = localize('This account is excluded until [_1]', moment(+excluded_until * 1000).format('YYYY-MM-DD HH:mm:ss Z'));
        } else {
            txt_markets = getAvailableMarkets(loginid);
        }

        const showSetCurrency = () => showCurrencyPopUp('set');
        $('#existing_accounts').find('tbody')
            .append($('<tr/>', { id: loginid, class: ((is_disabled || excluded_until) ? 'color-dark-white' : '') })
                .append($('<td/>', { text: loginid, datath: table_headers.account }))
                .append($('<td/>', { datath: table_headers.type }).html($('<span/>', account_type_prop)))
                .append($('<td/>', { text: txt_markets, datath: table_headers.available_markets }))
                .append($('<td/>', { datath: table_headers.currency })
                    .html(!account_currency && loginid === Client.get('loginid') ? $('<button/>', {
                        text: localize('Set currency'),
                        type: 'button',
                    }).on('click', showSetCurrency) : (Currency.getCurrencyFullName(account_currency) || '-'))));

        if (is_disabled || excluded_until) {
            $('#note_support').setVisibility(1);
        }
    };

    const getAvailableMarkets = (loginid) => {
        let legal_allowed_markets = Client.getLandingCompanyValue(loginid, landing_company, 'legal_allowed_markets') || '';
        if (Array.isArray(legal_allowed_markets) && legal_allowed_markets.length) {
            legal_allowed_markets =
                legal_allowed_markets
                    .map(market => getMarketName(market))
                    .filter((value, index, self) => value && self.indexOf(value) === index)
                    .join(', ');
        }
        return legal_allowed_markets;
    };

    const MarketsConfig = (() => {
        let markets_config;

        const initMarketsConfig = () => ({
            commodities    : localize('Commodities'),
            forex          : localize('Forex'),
            indices        : localize('Stock Indices'),
            stocks         : localize('Stocks'),
            synthetic_index: localize('Synthetic Indices'),
        });

        return {
            get: () => {
                if (!markets_config) {
                    markets_config = initMarketsConfig();
                }
                return markets_config;
            },
        };
    })();

    const getMarketName = market => MarketsConfig.get()[market] || '';

    const populateMultiAccount = () => {
        const table_headers = TableHeaders.get();
        const account     = { real: 1 };
        const handleClick = () => showCurrencyPopUp('create');
        $(form_id).find('tbody')
            .append($('<tr/>', { id: 'new_account_opening' })
                .append($('<td/>', { datath: table_headers.account }).html($('<span/>', {
                    text                 : localize('Real Account'),
                    'data-balloon'       : `${localize('Counterparty')}: ${getCompanyName(account)}, ${localize('Jurisdiction')}: ${getCompanyCountry(account)}`,
                    'data-balloon-length': 'large',
                })))
                .append($('<td/>', { text: getAvailableMarkets({ real: 1 }), datath: table_headers.available_markets }))
                .append($('<td/>').html($('<button/>', {
                    text: localize('Create account'),
                    type: 'button',
                }).on('click' , handleClick))));

        $('#note').setVisibility(1);

        doneLoading('#new_accounts_wrapper');
    };

    const onUnload = () => {
        clearPopup();
    };

    return {
        onLoad,
        onUnload,
    };
})();

module.exports = Accounts;
<commit_msg>Prince/ Ukgc changes with UK clients gaming account (#6822)<commit_after>const moment               = require('moment');
const SetCurrency          = require('./set_currency');
const BinaryPjax           = require('../../base/binary_pjax');
const Client               = require('../../base/client');
const BinarySocket         = require('../../base/socket');
const AccountOpening       = require('../../common/account_opening');
const showPopup            = require('../../common/attach_dom/popup');
const Currency             = require('../../common/currency');
const localize             = require('../../../_common/localize').localize;
const State                = require('../../../_common/storage').State;
const urlFor               = require('../../../_common/url').urlFor;

const Accounts = (() => {
    let landing_company;
    const form_id = '#new_accounts';

    const TableHeaders = (() => {
        let table_headers;

        const initTableHeaders = () => ({
            account          : localize('Account'),
            available_markets: localize('Available Markets'),
            type             : localize('Type'),
            currency         : localize('Currency'),
        });

        return {
            get: () => {
                if (!table_headers) {
                    table_headers = initTableHeaders();
                }
                return table_headers;
            },
        };
    })();

    const onLoad = () => {
        if (!Client.get('residence')) {
            // ask client to set residence first since cannot wait landing_company otherwise
            BinaryPjax.load(urlFor('user/settings/detailsws'));
        }
        clearPopup();
        BinarySocket.send({ statement: 1, limit: 1 });
        BinarySocket.wait('landing_company', 'get_settings', 'statement', 'mt5_login_list').then(() => {
            landing_company           = State.getResponse('landing_company');
            const can_change_currency = Client.canChangeCurrency(State.getResponse('statement'), State.getResponse('mt5_login_list'));
            const is_virtual          = Client.get('is_virtual');
            const has_real_account    = Client.hasAccountType('real');
            populateExistingAccounts();

            let element_to_show = '#no_new_accounts_wrapper';
            const upgrade_info  = Client.getUpgradeInfo();
            if (upgrade_info.can_upgrade) {
                // VRTC SVG has can_upgrade, but they are only allowed to open crypto related
                // accounts. This is a check to ignore the account creation form for them
                if (upgrade_info.can_open_multi || !upgrade_info.can_upgrade_to.includes('svg') || !has_real_account) {
                    populateNewAccounts(upgrade_info);
                    element_to_show = '#new_accounts_wrapper';
                }
            }

            if (upgrade_info.can_open_multi || (upgrade_info.can_upgrade_to.includes('svg') && is_virtual && has_real_account)) {
                populateMultiAccount();
            } else if (!can_change_currency) {
                doneLoading(element_to_show);
            }

            if (can_change_currency) {
                addChangeCurrencyOption();
                element_to_show = '#new_accounts_wrapper';
                if (!upgrade_info.can_open_multi) {
                    doneLoading(element_to_show);
                }
            }
        });
    };

    const clearPopup = () => {
        SetCurrency.cleanupPopup();
    };

    const doneLoading = (element_to_show) => {
        $(element_to_show).setVisibility(1);
        $('#accounts_loading').remove();
        $('#accounts_wrapper').setVisibility(1);
    };

    const getCompanyName = account => Client.getLandingCompanyValue(account, landing_company, 'name');

    const getCompanyCountry = account => Client.getLandingCompanyValue(account, landing_company, 'country');

    const populateNewAccounts = (upgrade_info) => {
        const table_headers = TableHeaders.get();
        const residence = Client.get('residence');

        upgrade_info.type.forEach((new_account_type, index) => {
            const getAccountTitle = () => {
                if (new_account_type === 'financial') {
                    return localize('Financial Account');
                }
                if (upgrade_info.can_upgrade_to[index] === 'malta') {
                    return localize('Gaming Account');
                }
                if (residence === 'gb' && upgrade_info.can_upgrade_to[index] === 'iom'){
                    return localize('Gaming Account');
                }

                return localize('Real Account');
            };

            const account           = {
                real     : new_account_type === 'real',
                financial: new_account_type === 'financial',
            };
            const new_account_title = getAccountTitle();
            $(form_id).find('tbody')
                .append($('<tr/>')
                    .append($('<td/>', { datath: table_headers.account }).html($('<span/>', {
                        text          : new_account_title,
                        'data-balloon': `${localize('Counterparty')}: ${getCompanyName(account)}, ${localize(
                            'Jurisdiction')}: ${getCompanyCountry(account)}`,
                        'data-balloon-length': 'large',
                    })))
                    .append($('<td/>', { text: getAvailableMarkets(account), datath: table_headers.available_markets }))
                    .append($('<td/>')
                        .html($(
                            '<a/>',
                            {
                                class: 'button',
                                href : AccountOpening.getSinupPageLink(
                                    upgrade_info,
                                    upgrade_info.can_upgrade_to[index]
                                ),
                            },
                        )
                            .html($('<span/>', { text: localize('Create account') })))));
        });
    };

    const addChangeCurrencyOption = () => {
        if ($(form_id).find('#change_account_currency').length) {
            return;
        }
        const table_headers = TableHeaders.get();
        const loginid       = Client.get('loginid');

        // Set the table row
        $(form_id).find('tbody')
            .append($('<tr/>', { id: 'change_account_currency' })
                .append($('<td/>', { datath: table_headers.account }).html($('<span/>', {
                    text: loginid,
                })))
                .append($('<td/>', { text: getAvailableMarkets(loginid), datath: table_headers.available_markets }))
                .append($('<td/>', { id: 'change_currency_action' })
                    .html($('<button/>', {
                        id   : 'change_currency_btn',
                        class: 'button no-margin',
                        type : 'button',
                        text : localize('Change currency'),
                    }).on('click', () => showCurrencyPopUp('change')))));

        // Replace note to reflect ability to change currency
        $('#note > .hint').text(`${localize('Note: You are limited to one fiat currency account. The currency of your fiat account can be changed before you deposit into your fiat account for the first time or create an MT5 account. You may also open one account for each supported cryptocurrency.')}`);
    };

    const onConfirmSetCurrency = () => {
        const can_change_currency = Client.canChangeCurrency(State.getResponse('statement'), State.getResponse('mt5_login_list'));
        if (can_change_currency) {
            addChangeCurrencyOption();
        }
    };

    const action_map = {
        create: 'multi_account',
        set   : 'set_currency',
        change: 'change_currency',
    };

    const showCurrencyPopUp = (action) => {
        showPopup({
            url               : urlFor('user/set-currency'),
            content_id        : '#set_currency',
            form_id           : 'frm_set_currency',
            additionalFunction: async () => {
                localStorage.setItem('popup_action', action_map[action]);
                await SetCurrency.onLoad(onConfirmSetCurrency);
            },
        });
    };

    const populateExistingAccounts = () => {
        const all_login_ids = Client.getAllLoginids();
        // Populate active loginids first.
        all_login_ids
            .filter(loginid => !Client.get('is_disabled', loginid) && !Client.get('excluded_until', loginid))
            .sort((a, b) => a > b)
            .forEach((loginid) => {
                appendExistingAccounts(loginid);
            });

        // Populate disabled or self excluded loginids.
        all_login_ids
            .filter(loginid => Client.get('is_disabled', loginid) || Client.get('excluded_until', loginid))
            .sort((a, b) => a > b)
            .forEach((loginid) => {
                appendExistingAccounts(loginid);
            });
    };

    const appendExistingAccounts = (loginid) => {
        const table_headers     = TableHeaders.get();
        const account_currency  = Client.get('currency', loginid);
        const account_type_prop = { text: Client.getAccountTitle(loginid) };

        if (!Client.isAccountOfType('virtual', loginid)) {
            const company_name                       = getCompanyName(loginid);
            const company_country                    = getCompanyCountry(loginid);
            account_type_prop['data-balloon']        = `${localize('Counterparty')}: ${company_name}, ${localize('Jurisdiction')}: ${company_country}`;
            account_type_prop['data-balloon-length'] = 'large';
        }

        const is_disabled    = Client.get('is_disabled', loginid);
        const excluded_until = Client.get('excluded_until', loginid);
        let txt_markets;
        if (is_disabled) {
            txt_markets = localize('This account is disabled');
        } else if (excluded_until) {
            txt_markets = localize('This account is excluded until [_1]', moment(+excluded_until * 1000).format('YYYY-MM-DD HH:mm:ss Z'));
        } else {
            txt_markets = getAvailableMarkets(loginid);
        }

        const showSetCurrency = () => showCurrencyPopUp('set');
        $('#existing_accounts').find('tbody')
            .append($('<tr/>', { id: loginid, class: ((is_disabled || excluded_until) ? 'color-dark-white' : '') })
                .append($('<td/>', { text: loginid, datath: table_headers.account }))
                .append($('<td/>', { datath: table_headers.type }).html($('<span/>', account_type_prop)))
                .append($('<td/>', { text: txt_markets, datath: table_headers.available_markets }))
                .append($('<td/>', { datath: table_headers.currency })
                    .html(!account_currency && loginid === Client.get('loginid') ? $('<button/>', {
                        text: localize('Set currency'),
                        type: 'button',
                    }).on('click', showSetCurrency) : (Currency.getCurrencyFullName(account_currency) || '-'))));

        if (is_disabled || excluded_until) {
            $('#note_support').setVisibility(1);
        }
    };

    const getAvailableMarkets = (loginid) => {
        let legal_allowed_markets = Client.getLandingCompanyValue(loginid, landing_company, 'legal_allowed_markets') || '';
        if (Array.isArray(legal_allowed_markets) && legal_allowed_markets.length) {
            legal_allowed_markets =
                legal_allowed_markets
                    .map(market => getMarketName(market))
                    .filter((value, index, self) => value && self.indexOf(value) === index)
                    .join(', ');
        }
        return legal_allowed_markets;
    };

    const MarketsConfig = (() => {
        let markets_config;

        const initMarketsConfig = () => ({
            commodities    : localize('Commodities'),
            forex          : localize('Forex'),
            indices        : localize('Stock Indices'),
            stocks         : localize('Stocks'),
            synthetic_index: localize('Synthetic Indices'),
        });

        return {
            get: () => {
                if (!markets_config) {
                    markets_config = initMarketsConfig();
                }
                return markets_config;
            },
        };
    })();

    const getMarketName = market => MarketsConfig.get()[market] || '';

    const populateMultiAccount = () => {
        const table_headers = TableHeaders.get();
        const account     = { real: 1 };
        const handleClick = () => showCurrencyPopUp('create');
        $(form_id).find('tbody')
            .append($('<tr/>', { id: 'new_account_opening' })
                .append($('<td/>', { datath: table_headers.account }).html($('<span/>', {
                    text                 : localize('Real Account'),
                    'data-balloon'       : `${localize('Counterparty')}: ${getCompanyName(account)}, ${localize('Jurisdiction')}: ${getCompanyCountry(account)}`,
                    'data-balloon-length': 'large',
                })))
                .append($('<td/>', { text: getAvailableMarkets({ real: 1 }), datath: table_headers.available_markets }))
                .append($('<td/>').html($('<button/>', {
                    text: localize('Create account'),
                    type: 'button',
                }).on('click' , handleClick))));

        $('#note').setVisibility(1);

        doneLoading('#new_accounts_wrapper');
    };

    const onUnload = () => {
        clearPopup();
    };

    return {
        onLoad,
        onUnload,
    };
})();

module.exports = Accounts;
<|endoftext|>


<commit_before>'use strict';

(function () {

angular
  .module('copayApp.controllers')
  .controller('tabScanController', tabScanController);

  function tabScanController(
    gettextCatalog
    , popupService
    , qrReaderService
    , qrScannerService
    , $scope
    , $log
    , $timeout
    , incomingDataService
    , $state
    , $ionicHistory
    , $rootScope
    , $ionicNavBarDelegate
    , platformInfo
    ) {

      var qrPermissionResult = {
        denied: 'PERMISSION_DENIED',
        granted: 'PERMISSION_GRANTED',

        // iOS
        restricted: 'PERMISSION_RESTRICTED',
        notDetermined: 'PERMISSION_NOT_DETERMINED'
      };

    var scannerStates = {
      denied: 'denied',
      unavailable: 'unavailable',
      visible: 'visible'
    };

    var isCheckingPermissions = false;
    var isReading = false;
    var isDesktop = !platformInfo.isCordova;
    var qrService = isDesktop ? qrScannerService : qrReaderService;

    $scope.onOpenSettings = onOpenSettings;
    $scope.onRetry = onRetry;
    $scope.scannerStates = scannerStates;
    $scope.currentState = scannerStates.visible;
    $scope.canOpenSettings = isDesktop ? false : true;

    $scope.$on("$ionicView.enter", function(event, data) {
      $ionicNavBarDelegate.showBar(true);
    });

    $scope.$on("$ionicView.afterEnter", function() {
      _checkPermissionThenStartReading();
      document.addEventListener("resume", _onResume, true);
    });

    $scope.$on("$ionicView.beforeLeave", function() {
      document.removeEventListener("resume", _onResume, true);
      qrService.stopReading();
    });

    function _onResume() {
      console.log('onResume()');

      // Give everything time to settle since onResume gets call after the app resumes,
      // and some things are already happening, such as:
      // - Permission check has returned and reading was started.o

      $timeout(function onResumeTimeout() {

        if (isCheckingPermissions) {
          console.log('onResume(), was checking permissions, so don\'t do anything.');
          // Resume is called after using the permissions dialog
          // Let's hope they are not switching back to this app from another app
          return;
        }

        if (isReading && platformInfo.isAndroid) { // Don't need to do this on iOS, in fact it breaks if you do
          console.log('onResume(), was reading, so restart reading.');
          qrService.stopReading().then(
            function onStoppedReadingSuccess() {
              console.log('onResume(), Starting reading after stopping.');
              _startReading();
            },
            function onStoppedReadingFailed(err) {
              $log.error('Failed to restart reading', err);
              $scope.currentState = scannerStates.unavailable;
            }
          );
        }

      }, 200);

    }

    function _handleSuccessfulScan(contents){

      $log.debug('Scan returned: "' + contents + '"');
      //scannerService.pausePreview();
      // Sometimes (testing in Chrome, when reading QR Code) data is an object
      // that has a string data.result.
      contents = contents.result || contents;
      incomingDataService.redir(contents, function onError(err) {
        if (err) {
          var title = gettextCatalog.getString('Scan Failed');
          popupService.showAlert(title, err.message, function onAlertShown() {
            // Enable another scan since we won't receive incomingDataMenu.menuHidden
            _startReading();
          });
        } else {
          _startReading();
        }
      });

    }

    $rootScope.$on('incomingDataMenu.menuHidden', function() {
      _startReading();
    });

    function onRetry() {
      _checkPermissionThenStartReading();
    }

    function onOpenSettings(){
      //scannerService.openSettings();
      qrService.openSettings().then(
        function onOpenSettingsResolved(result) {
          console.log('Open settings resolved with:', result);
          //_checkPermissionThenStartReading();
          // Allow to manually retry the camera
          $scope.canOpenSettings = false;

        },
        function onOpenSettingsRejected(reason) {
          $log.error('Failed to open settings. ' + reason);

          $scope.canOpenSettings = false;

          // TODO: Handle all the different types of errors
          $scope.currentState = scannerStates.unavailable;
        }
      );
    }

    function _checkPermissionThenStartReading() {
      isCheckingPermissions = true;
      qrService.checkPermission().then(
        function onCheckPermissionSuccess(result) {
          console.log('onPermissionSuccess() ', result);
          isCheckingPermissions = false;
          if (result === qrPermissionResult.granted || result === qrPermissionResult.notDetermined) {
            _startReading();
          } else {
            $scope.currentState = scannerStates.denied;
          }
        },
        function onCheckPermissionFailed(err) {
          isCheckingPermissions = false;
          $log.error('Failed to check permission.', err);
        }
      );
    }

    function _startReading() {
      $scope.currentState = scannerStates.visible;
      isReading = true;
      console.log('Starting QR Service.');
      qrService.startReading().then(
        function onStartReadingResolved(contents) {
          isReading = false;
          _handleSuccessfulScan(contents);
        },
        function onStartReadingRejected(reason) {
          isReading = false;
          $log.error('Failed to start reading QR code. ' + reason);

          if (reason === qrService.errors.permissionDenied) {
            $scope.currentState = scannerStates.denied;
          } else {
            // TODO: Handle all the different types of errors
            $scope.currentState = scannerStates.unavailable;
          }
        });
    }

    $scope.toggleLight = function(){
      /*
      scannerService.toggleLight(function(lightEnabled){
        $scope.lightActive = lightEnabled;
        $scope.$apply();
      });
      */
    };

    $scope.toggleCamera = function(){
      /*
      $scope.cameraToggleActive = true;
      scannerService.toggleCamera(function(status){
      // (a short delay for the user to see the visual feedback)
        $timeout(function(){
          $scope.cameraToggleActive = false;
          $scope.lightActive = false; // The light is off when we switch camera succesfully
          $log.debug('Camera toggle control deactivated.');
        }, 200);
      });
      */
    };

    $scope.canGoBack = function(){
      return $state.params.passthroughMode;
    };

    function goBack(){
      $ionicHistory.nextViewOptions({
        disableAnimate: true
      });
      $ionicHistory.backView().go();
    }
    $scope.goBack = goBack;
  }
})();
<commit_msg>Remved handling of resume on the tab-scan controller because it was interfering with resume being handled in the plugins.<commit_after>'use strict';

(function () {

angular
  .module('copayApp.controllers')
  .controller('tabScanController', tabScanController);

  function tabScanController(
    gettextCatalog
    , popupService
    , qrReaderService
    , qrScannerService
    , $scope
    , $log
    , $timeout
    , incomingDataService
    , $state
    , $ionicHistory
    , $rootScope
    , $ionicNavBarDelegate
    , platformInfo
    ) {

      var qrPermissionResult = {
        denied: 'PERMISSION_DENIED',
        granted: 'PERMISSION_GRANTED',

        // iOS
        restricted: 'PERMISSION_RESTRICTED',
        notDetermined: 'PERMISSION_NOT_DETERMINED'
      };

    var scannerStates = {
      denied: 'denied',
      unavailable: 'unavailable',
      visible: 'visible'
    };

    var isCheckingPermissions = false;
    var isReading = false;
    var isDesktop = !platformInfo.isCordova;
    var qrService = isDesktop ? qrScannerService : qrReaderService;

    $scope.onOpenSettings = onOpenSettings;
    $scope.onRetry = onRetry;
    $scope.scannerStates = scannerStates;
    $scope.currentState = scannerStates.visible;
    $scope.canOpenSettings = isDesktop ? false : true;

    $scope.$on("$ionicView.enter", function(event, data) {
      $ionicNavBarDelegate.showBar(true);
    });

    $scope.$on("$ionicView.afterEnter", function() {
      _checkPermissionThenStartReading();
    });

    $scope.$on("$ionicView.beforeLeave", function() {
      qrService.stopReading();
    });

    function _handleSuccessfulScan(contents){

      $log.debug('Scan returned: "' + contents + '"');
      //scannerService.pausePreview();
      // Sometimes (testing in Chrome, when reading QR Code) data is an object
      // that has a string data.result.
      contents = contents.result || contents;
      incomingDataService.redir(contents, function onError(err) {
        if (err) {
          var title = gettextCatalog.getString('Scan Failed');
          popupService.showAlert(title, err.message, function onAlertShown() {
            // Enable another scan since we won't receive incomingDataMenu.menuHidden
            _startReading();
          });
        } else {
          _startReading();
        }
      });

    }

    $rootScope.$on('incomingDataMenu.menuHidden', function() {
      _startReading();
    });

    function onRetry() {
      _checkPermissionThenStartReading();
    }

    function onOpenSettings(){
      //scannerService.openSettings();
      qrService.openSettings().then(
        function onOpenSettingsResolved(result) {
          console.log('Open settings resolved with:', result);
          //_checkPermissionThenStartReading();
          // Allow to manually retry the camera
          $scope.canOpenSettings = false;

        },
        function onOpenSettingsRejected(reason) {
          $log.error('Failed to open settings. ' + reason);

          $scope.canOpenSettings = false;

          // TODO: Handle all the different types of errors
          $scope.currentState = scannerStates.unavailable;
        }
      );
    }

    function _checkPermissionThenStartReading() {
      isCheckingPermissions = true;
      qrService.checkPermission().then(
        function onCheckPermissionSuccess(result) {
          console.log('onPermissionSuccess() ', result);
          isCheckingPermissions = false;
          if (result === qrPermissionResult.granted || result === qrPermissionResult.notDetermined) {
            _startReading();
          } else {
            $scope.currentState = scannerStates.denied;
          }
        },
        function onCheckPermissionFailed(err) {
          isCheckingPermissions = false;
          $log.error('Failed to check permission.', err);
        }
      );
    }

    function _startReading() {
      $scope.currentState = scannerStates.visible;
      isReading = true;
      console.log('Starting QR Service.');
      qrService.startReading().then(
        function onStartReadingResolved(contents) {
          isReading = false;
          _handleSuccessfulScan(contents);
        },
        function onStartReadingRejected(reason) {
          isReading = false;
          $log.error('Failed to start reading QR code. ' + reason);

          if (reason === qrService.errors.permissionDenied) {
            $scope.currentState = scannerStates.denied;
          } else {
            // TODO: Handle all the different types of errors
            $scope.currentState = scannerStates.unavailable;
          }
        });
    }

    $scope.toggleLight = function(){
      /*
      scannerService.toggleLight(function(lightEnabled){
        $scope.lightActive = lightEnabled;
        $scope.$apply();
      });
      */
    };

    $scope.toggleCamera = function(){
      /*
      $scope.cameraToggleActive = true;
      scannerService.toggleCamera(function(status){
      // (a short delay for the user to see the visual feedback)
        $timeout(function(){
          $scope.cameraToggleActive = false;
          $scope.lightActive = false; // The light is off when we switch camera succesfully
          $log.debug('Camera toggle control deactivated.');
        }, 200);
      });
      */
    };

    $scope.canGoBack = function(){
      return $state.params.passthroughMode;
    };

    function goBack(){
      $ionicHistory.nextViewOptions({
        disableAnimate: true
      });
      $ionicHistory.backView().go();
    }
    $scope.goBack = goBack;
  }
})();
<|endoftext|>


<commit_before>app.factory('dashboardRestService', ['$http', 'HOST',

function($http, HOST) {

	'use strict';

	function getMyExpenses() {
		return $http.get(HOST + '/api/user/expenses');
	}

	function getReviewExpensesAsFinanceAdmin() {
		$http.get(HOST + '/api/finance-admin/review-expenses');
	}

	function getReviewExpensesAsProf() {
		$http.get(HOST + '/api/prof/review-expenses');
	}

	return {
		getMyExpenses: getMyExpenses,
		getReviewExpensesAsFinanceAdmin: getReviewExpensesAsFinanceAdmin,
		getReviewExpensesAsProf: getReviewExpensesAsProf
	};

}]);
<commit_msg>fix dashboard<commit_after>app.factory('dashboardRestService', ['$http', 'HOST',

function($http, HOST) {

	'use strict';

	function getMyExpenses() {
		return $http.get(HOST + '/api/user/expenses');
	}

	function getReviewExpensesAsFinanceAdmin() {
		return $http.get(HOST + '/api/finance-admin/review-expenses');
	}

	function getReviewExpensesAsProf() {
		return $http.get(HOST + '/api/prof/review-expenses');
	}

	return {
		getMyExpenses: getMyExpenses,
		getReviewExpensesAsFinanceAdmin: getReviewExpensesAsFinanceAdmin,
		getReviewExpensesAsProf: getReviewExpensesAsProf
	};

}]);
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow
 * @providesModule WKWebView
 */

const React = require('react');

const requireNativeComponent = require('requireNativeComponent');

const RCTWKWebView = requireNativeComponent('RCTWKWebView');

type RCTWKWebViewProps = {
  allowsInlineMediaPlayback?: boolean,
  mediaPlaybackRequiresUserAction?: boolean,
  dataDetectorTypes?: boolean,
};

class WKWebView extends React.Component<RCTWKWebViewProps> {
  componentWillReceiveProps(nextProps: RCTWKWebViewProps) {
    this.showRedboxOnPropChanges(nextProps, 'allowsInlineMediaPlayback');
    this.showRedboxOnPropChanges(nextProps, 'mediaPlaybackRequiresUserAction');
    this.showRedboxOnPropChanges(nextProps, 'dataDetectorTypes');
  }

  showRedboxOnPropChanges(nextProps: RCTWKWebViewProps, propName: string) {
    if (this.props[propName] !== nextProps[propName]) {
      console.error(`Changes to property ${propName} do nothing after the initial render.`);
    }
  }

  render() {
    return <RCTWKWebView {...this.props}/>;
  }
}

module.exports = WKWebView;
<commit_msg>Remove extra WKWebView file not used (#21182)<commit_after><|endoftext|>


<commit_before>;(function ($, window, document, undefined) {
  'use strict';

  Foundation.libs.dropdown = {
    name : 'dropdown',

    version : '5.2.2',

    settings : {
      active_class: 'open',
      align: 'bottom',
      bounds: 'window', // 'off', 'window', 'document'
      is_hover: false,
      opened: function(){},
      closed: function(){}
    },

    init : function (scope, method, options) {
      Foundation.inherit(this, 'throttle');

      this.bindings(method, options);
    },

    events : function (scope) {
      var self = this,
          S = self.S;

      S(this.scope)
        .off('.dropdown')
        .on('click.fndtn.dropdown', '[' + this.attr_name() + ']', function (e) {
          var settings = S(this).data(self.attr_name(true) + '-init') || self.settings;
          if (!settings.is_hover || Modernizr.touch) {
            e.preventDefault();
            self.toggle($(this));
          }
        })
        .on('mouseenter.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) {
          var $this = S(this);
          clearTimeout(self.timeout);

          if ($this.data(self.data_attr())) {
            var dropdown = S('#' + $this.data(self.data_attr())),
                target = $this;
          } else {
            var dropdown = $this;
                target = S("[" + self.attr_name() + "='" + dropdown.attr('id') + "']");
          }

          var settings = target.data(self.attr_name(true) + '-init') || self.settings;

          if(S(e.target).data(self.data_attr()) && settings.is_hover) {
            self.closeall.call(self);
          }

          if (settings.is_hover) self.open.apply(self, [dropdown, target]);
        })
        .on('mouseleave.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) {
          var $this = S(this);
          self.timeout = setTimeout(function () {
            if ($this.data(self.data_attr())) {
              var settings = $this.data(self.data_attr(true) + '-init') || self.settings;
              if (settings.is_hover) self.close.call(self, S('#' + $this.data(self.data_attr())));
            } else {
              var target = S('[' + self.attr_name() + '="' + S(this).attr('id') + '"]'),
                  settings = target.data(self.attr_name(true) + '-init') || self.settings;
              if (settings.is_hover) self.close.call(self, $this);
            }
          }.bind(this), 150);
        })
        .on('click.fndtn.dropdown', function (e) {
          var parent = S(e.target).closest('[' + self.attr_name() + '-content]');

          if (S(e.target).data(self.data_attr()) || S(e.target).parent().data(self.data_attr())) {
            return;
          }
          if (!(S(e.target).data('revealId')) &&
            (parent.length > 0 && (S(e.target).is('[' + self.attr_name() + '-content]') ||
              $.contains(parent.first()[0], e.target)))) {
            e.stopPropagation();
            return;
          }

          self.close.call(self, S('[' + self.attr_name() + '-content]'));
        })
        .on('opened.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () {
            self.settings.opened.call(this);
        })
        .on('closed.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () {
            self.settings.closed.call(this);
        });

      S(window)
        .off('.dropdown')
        .on('resize.fndtn.dropdown', self.throttle(function () {
          self.resize.call(self);
        }, 50));

      this.resize();
    },

    close: function (dropdown) {
      var self = this;
      dropdown.each(function () {
        if (self.S(this).hasClass(self.settings.active_class)) {
          self.S(this)
            .css(Foundation.rtl ? 'right':'left', '-99999px')
            .removeClass(self.settings.active_class)
            .prev('[' + self.attr_name() + ']')
            .removeClass(self.settings.active_class)
            .removeData('target');

          self.S(this).trigger('closed', [dropdown]);
        }
      });
    },

    closeall: function() {
      var self = this;
      $.each(self.S('[' + this.attr_name() + '-content]'), function() {
        self.close.call(self, self.S(this))
      });
    },

    open: function (dropdown, target) {
        this
          .css(dropdown
            .addClass(this.settings.active_class), target);
        dropdown.prev('[' + this.attr_name() + ']').addClass(this.settings.active_class);
        dropdown.data('target', target.get(0)).trigger('opened', [dropdown, target]);
    },

    data_attr: function () {
      if (this.namespace.length > 0) {
        return this.namespace + '-' + this.name;
      }

      return this.name;
    },

    toggle : function (target) {
      var dropdown = this.S('#' + target.data(this.data_attr()));
      if (dropdown.length === 0) {
        // No dropdown found, not continuing
        return;
      }

      this.close.call(this, this.S('[' + this.attr_name() + '-content]').not(dropdown));

      if (dropdown.hasClass(this.settings.active_class)) {
        this.close.call(this, dropdown);
        if (dropdown.data('target') !== target.get(0))
          this.open.call(this, dropdown, target);
      } else {
        this.open.call(this, dropdown, target);
      }
    },

    resize : function () {
      var dropdown = this.S('[' + this.attr_name() + '-content].open'),
          target = this.S("[" + this.attr_name() + "='" + dropdown.attr('id') + "']");

      if (dropdown.length && target.length) {
        this.css(dropdown, target);
      }
    },

    css : function (dropdown, target) {
      this.clear_idx();

      if (this.small()) {
        var p = this.dirs.bottom.call(dropdown, target);

        dropdown.attr('style', '').removeClass('drop-left drop-right drop-top').css({
          position : 'absolute',
          width: '95%',
          'max-width': 'none',
          top: p.top
        });

        dropdown.css(Foundation.rtl ? 'right':'left', '2.5%');
      } else {
        var settings = target.data(this.attr_name(true) + '-init') || this.settings;

        this.style(dropdown, target, settings);
      }

      return dropdown;
    },

    style : function (dropdown, target, settings) {
      var p = this.dirs[settings.align].call(dropdown, target, settings),
        css = $.extend({position: 'absolute'},
        this.fit_bounds.call(dropdown, p, target, settings));

      dropdown.attr('style', '').css(css);
    },

    // return CSS property object
    // `this` is the dropdown
    dirs : {
      // Calculate target offset
      _base : function (t) {
        var o_p = this.offsetParent(),
            o = o_p.offset(),
            p = t.offset();

        p.top -= o.top;
        p.left -= o.left;

        return p;
      },
      top: function (t, s) {
        var self = Foundation.libs.dropdown,
            p = self.dirs._base.call(this, t),
            pip_offset_base = (t.outerWidth() / 2) - 8;

        this.addClass('drop-top');

        if (t.outerWidth() < this.outerWidth() || self.small()) {
          self.adjust_pip(pip_offset_base, p);
        }

        if (Foundation.rtl) {
          return {left: p.left - this.outerWidth() + t.outerWidth(),
            top: p.top - this.outerHeight()};
        }

        return {left: p.left, top: p.top - this.outerHeight()};
      },
      bottom: function (t, s) {
        var self = Foundation.libs.dropdown,
            p = self.dirs._base.call(this, t),
            pip_offset_base = (t.outerWidth() / 2) - 8;

        if (t.outerWidth() < this.outerWidth() || self.small()) {
          self.adjust_pip(pip_offset_base, p);
        }

        if (self.rtl) {
          return {left: p.left - this.outerWidth() + t.outerWidth(), top: p.top + t.outerHeight()};
        }

        return {left: p.left, top: p.top + t.outerHeight()};
      },
      left: function (t, s) {
        var p = Foundation.libs.dropdown.dirs._base.call(this, t);

        this.addClass('drop-left');

        return {left: p.left - this.outerWidth(), top: p.top};
      },
      right: function (t, s) {
        var p = Foundation.libs.dropdown.dirs._base.call(this, t);

        this.addClass('drop-right');

        return {left: p.left + t.outerWidth(), top: p.top};
      }
    },

    // Make sure the dropdown is entirely visible within chosen bounds
    fit_bounds : function(p, t, s) {
      var self = Foundation.libs.dropdown,
        min_x = 0,
        min_y = 0,
        max_x,
        max_y;

      if (s.bounds === 'window') {
        var w = self.S(window);
        min_x = w.scrollLeft();
        min_y = w.scrollTop();
        max_x = w.width() + min_x;
        max_y = w.height() + min_y;
      }
      else if (s.bounds === 'document') {
        var d = self.dropdown.S(document);
        max_x = d.width();
        max_y = d.height();
      }
      else {
        return p;
      }

      var zone = 3, // clear zone around document bounds
        dd_w = this.outerWidth(),
        dd_h = this.outerHeight(),
        t_h = t.outerHeight(),
        t_w = t.outerWidth(),
        o_p = this.offsetParent(),
        o = o_p.offset(),
        res = p;

      if (s.align === 'bottom' && res.top + o.top + dd_h + zone > max_y) {
        return self.fit_bounds.call(this, self.dirs.top.call(this, t, s), t, s);
      }

      if (s.align === 'right' && res.left + o.left + dd_w + zone > max_x) {
        return self.fit_bounds.call(this, self.dirs.left.call(this, t, s), t, s);
      }

      if (s.align === 'top' && res.top - o.top - zone < min_y) {
        return self.fit_bounds.call(this, self.dirs.bottom.call(this, t, s), t, s);
      }

      if (s.align === 'left' && res.left - o.left - zone < min_x) {
        return self.fit_bounds.call(this, self.dirs.right.call(this, t, s), t, s);
      }

      if ((s.align === 'bottom' || s.align === 'top') && res.left + o.left + dd_w + zone > max_x) {
        res.left = Math.max(zone, res.left + t_w - dd_w);
      }

      return res;
    },

    // Insert rule to style psuedo elements
    adjust_pip : function (pip_offset_base, p) {
      var sheet = Foundation.stylesheet;

      if (this.small()) {
        pip_offset_base += p.left - 8;
      }

      this.rule_idx = sheet.cssRules.length;

      var sel_before = '.f-dropdown.open:before',
          sel_after  = '.f-dropdown.open:after',
          css_before = 'left: ' + pip_offset_base + 'px;',
          css_after  = 'left: ' + (pip_offset_base - 1) + 'px;';

      if (sheet.insertRule) {
        sheet.insertRule([sel_before, '{', css_before, '}'].join(' '), this.rule_idx);
        sheet.insertRule([sel_after, '{', css_after, '}'].join(' '), this.rule_idx + 1);
      } else {
        sheet.addRule(sel_before, css_before, this.rule_idx);
        sheet.addRule(sel_after, css_after, this.rule_idx + 1);
      }
    },

    // Remove old dropdown rule index
    clear_idx : function () {
      var sheet = Foundation.stylesheet;

      if (this.rule_idx) {
        sheet.deleteRule(this.rule_idx);
        sheet.deleteRule(this.rule_idx);
        delete this.rule_idx;
      }
    },

    small : function () {
      return matchMedia(Foundation.media_queries.small).matches &&
        !matchMedia(Foundation.media_queries.medium).matches;
    },

    off: function () {
      this.S(this.scope).off('.fndtn.dropdown');
      this.S('html, body').off('.fndtn.dropdown');
      this.S(window).off('.fndtn.dropdown');
      this.S('[data-dropdown-content]').off('.fndtn.dropdown');
    },

    reflow : function () {}
  };
}(jQuery, window, window.document));
<commit_msg>Typo fix<commit_after>;(function ($, window, document, undefined) {
  'use strict';

  Foundation.libs.dropdown = {
    name : 'dropdown',

    version : '5.2.2',

    settings : {
      active_class: 'open',
      align: 'bottom',
      bounds: 'window',
      is_hover: false,
      opened: function(){},
      closed: function(){}
    },

    init : function (scope, method, options) {
      Foundation.inherit(this, 'throttle');

      this.bindings(method, options);
    },

    events : function (scope) {
      var self = this,
          S = self.S;

      S(this.scope)
        .off('.dropdown')
        .on('click.fndtn.dropdown', '[' + this.attr_name() + ']', function (e) {
          var settings = S(this).data(self.attr_name(true) + '-init') || self.settings;
          if (!settings.is_hover || Modernizr.touch) {
            e.preventDefault();
            self.toggle($(this));
          }
        })
        .on('mouseenter.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) {
          var $this = S(this);
          clearTimeout(self.timeout);

          if ($this.data(self.data_attr())) {
            var dropdown = S('#' + $this.data(self.data_attr())),
                target = $this;
          } else {
            var dropdown = $this;
                target = S("[" + self.attr_name() + "='" + dropdown.attr('id') + "']");
          }

          var settings = target.data(self.attr_name(true) + '-init') || self.settings;

          if(S(e.target).data(self.data_attr()) && settings.is_hover) {
            self.closeall.call(self);
          }

          if (settings.is_hover) self.open.apply(self, [dropdown, target]);
        })
        .on('mouseleave.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) {
          var $this = S(this);
          self.timeout = setTimeout(function () {
            if ($this.data(self.data_attr())) {
              var settings = $this.data(self.data_attr(true) + '-init') || self.settings;
              if (settings.is_hover) self.close.call(self, S('#' + $this.data(self.data_attr())));
            } else {
              var target = S('[' + self.attr_name() + '="' + S(this).attr('id') + '"]'),
                  settings = target.data(self.attr_name(true) + '-init') || self.settings;
              if (settings.is_hover) self.close.call(self, $this);
            }
          }.bind(this), 150);
        })
        .on('click.fndtn.dropdown', function (e) {
          var parent = S(e.target).closest('[' + self.attr_name() + '-content]');

          if (S(e.target).data(self.data_attr()) || S(e.target).parent().data(self.data_attr())) {
            return;
          }
          if (!(S(e.target).data('revealId')) &&
            (parent.length > 0 && (S(e.target).is('[' + self.attr_name() + '-content]') ||
              $.contains(parent.first()[0], e.target)))) {
            e.stopPropagation();
            return;
          }

          self.close.call(self, S('[' + self.attr_name() + '-content]'));
        })
        .on('opened.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () {
            self.settings.opened.call(this);
        })
        .on('closed.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () {
            self.settings.closed.call(this);
        });

      S(window)
        .off('.dropdown')
        .on('resize.fndtn.dropdown', self.throttle(function () {
          self.resize.call(self);
        }, 50));

      this.resize();
    },

    close: function (dropdown) {
      var self = this;
      dropdown.each(function () {
        if (self.S(this).hasClass(self.settings.active_class)) {
          self.S(this)
            .css(Foundation.rtl ? 'right':'left', '-99999px')
            .removeClass(self.settings.active_class)
            .prev('[' + self.attr_name() + ']')
            .removeClass(self.settings.active_class)
            .removeData('target');

          self.S(this).trigger('closed', [dropdown]);
        }
      });
    },

    closeall: function() {
      var self = this;
      $.each(self.S('[' + this.attr_name() + '-content]'), function() {
        self.close.call(self, self.S(this))
      });
    },

    open: function (dropdown, target) {
        this
          .css(dropdown
            .addClass(this.settings.active_class), target);
        dropdown.prev('[' + this.attr_name() + ']').addClass(this.settings.active_class);
        dropdown.data('target', target.get(0)).trigger('opened', [dropdown, target]);
    },

    data_attr: function () {
      if (this.namespace.length > 0) {
        return this.namespace + '-' + this.name;
      }

      return this.name;
    },

    toggle : function (target) {
      var dropdown = this.S('#' + target.data(this.data_attr()));
      if (dropdown.length === 0) {
        // No dropdown found, not continuing
        return;
      }

      this.close.call(this, this.S('[' + this.attr_name() + '-content]').not(dropdown));

      if (dropdown.hasClass(this.settings.active_class)) {
        this.close.call(this, dropdown);
        if (dropdown.data('target') !== target.get(0))
          this.open.call(this, dropdown, target);
      } else {
        this.open.call(this, dropdown, target);
      }
    },

    resize : function () {
      var dropdown = this.S('[' + this.attr_name() + '-content].open'),
          target = this.S("[" + this.attr_name() + "='" + dropdown.attr('id') + "']");

      if (dropdown.length && target.length) {
        this.css(dropdown, target);
      }
    },

    css : function (dropdown, target) {
      this.clear_idx();

      if (this.small()) {
        var p = this.dirs.bottom.call(dropdown, target);

        dropdown.attr('style', '').removeClass('drop-left drop-right drop-top').css({
          position : 'absolute',
          width: '95%',
          'max-width': 'none',
          top: p.top
        });

        dropdown.css(Foundation.rtl ? 'right':'left', '2.5%');
      } else {
        var settings = target.data(this.attr_name(true) + '-init') || this.settings;

        this.style(dropdown, target, settings);
      }

      return dropdown;
    },

    style : function (dropdown, target, settings) {
      var p = this.dirs[settings.align].call(dropdown, target, settings),
        css = $.extend({position: 'absolute'},
        this.fit_bounds.call(dropdown, p, target, settings));

      dropdown.attr('style', '').css(css);
    },

    // return CSS property object
    // `this` is the dropdown
    dirs : {
      // Calculate target offset
      _base : function (t) {
        var o_p = this.offsetParent(),
            o = o_p.offset(),
            p = t.offset();

        p.top -= o.top;
        p.left -= o.left;

        return p;
      },
      top: function (t, s) {
        var self = Foundation.libs.dropdown,
            p = self.dirs._base.call(this, t),
            pip_offset_base = (t.outerWidth() / 2) - 8;

        this.addClass('drop-top');

        if (t.outerWidth() < this.outerWidth() || self.small()) {
          self.adjust_pip(pip_offset_base, p);
        }

        if (Foundation.rtl) {
          return {left: p.left - this.outerWidth() + t.outerWidth(),
            top: p.top - this.outerHeight()};
        }

        return {left: p.left, top: p.top - this.outerHeight()};
      },
      bottom: function (t, s) {
        var self = Foundation.libs.dropdown,
            p = self.dirs._base.call(this, t),
            pip_offset_base = (t.outerWidth() / 2) - 8;

        if (t.outerWidth() < this.outerWidth() || self.small()) {
          self.adjust_pip(pip_offset_base, p);
        }

        if (self.rtl) {
          return {left: p.left - this.outerWidth() + t.outerWidth(), top: p.top + t.outerHeight()};
        }

        return {left: p.left, top: p.top + t.outerHeight()};
      },
      left: function (t, s) {
        var p = Foundation.libs.dropdown.dirs._base.call(this, t);

        this.addClass('drop-left');

        return {left: p.left - this.outerWidth(), top: p.top};
      },
      right: function (t, s) {
        var p = Foundation.libs.dropdown.dirs._base.call(this, t);

        this.addClass('drop-right');

        return {left: p.left + t.outerWidth(), top: p.top};
      }
    },

    // Make sure the dropdown is entirely visible within chosen bounds
    fit_bounds : function(p, t, s) {
      var self = Foundation.libs.dropdown,
        min_x = 0,
        min_y = 0,
        max_x,
        max_y;

      if (s.bounds === 'window') {
        var w = self.S(window);
        min_x = w.scrollLeft();
        min_y = w.scrollTop();
        max_x = w.width() + min_x;
        max_y = w.height() + min_y;
      }
      else if (s.bounds === 'document') {
        var d = self.S(document);
        max_x = d.width();
        max_y = d.height();
      }
      else {
        return p;
      }

      var zone = 3, // clear zone around document bounds
        dd_w = this.outerWidth(),
        dd_h = this.outerHeight(),
        t_h = t.outerHeight(),
        t_w = t.outerWidth(),
        o_p = this.offsetParent(),
        o = o_p.offset(),
        res = p;

      if (s.align === 'bottom' && res.top + o.top + dd_h + zone > max_y) {
        return self.fit_bounds.call(this, self.dirs.top.call(this, t, s), t, s);
      }

      if (s.align === 'right' && res.left + o.left + dd_w + zone > max_x) {
        return self.fit_bounds.call(this, self.dirs.left.call(this, t, s), t, s);
      }

      if (s.align === 'top' && res.top - o.top - zone < min_y) {
        return self.fit_bounds.call(this, self.dirs.bottom.call(this, t, s), t, s);
      }

      if (s.align === 'left' && res.left - o.left - zone < min_x) {
        return self.fit_bounds.call(this, self.dirs.right.call(this, t, s), t, s);
      }

      if ((s.align === 'bottom' || s.align === 'top') && res.left + o.left + dd_w + zone > max_x) {
        res.left = Math.max(zone, res.left + t_w - dd_w);
      }

      return res;
    },

    // Insert rule to style psuedo elements
    adjust_pip : function (pip_offset_base, p) {
      var sheet = Foundation.stylesheet;

      if (this.small()) {
        pip_offset_base += p.left - 8;
      }

      this.rule_idx = sheet.cssRules.length;

      var sel_before = '.f-dropdown.open:before',
          sel_after  = '.f-dropdown.open:after',
          css_before = 'left: ' + pip_offset_base + 'px;',
          css_after  = 'left: ' + (pip_offset_base - 1) + 'px;';

      if (sheet.insertRule) {
        sheet.insertRule([sel_before, '{', css_before, '}'].join(' '), this.rule_idx);
        sheet.insertRule([sel_after, '{', css_after, '}'].join(' '), this.rule_idx + 1);
      } else {
        sheet.addRule(sel_before, css_before, this.rule_idx);
        sheet.addRule(sel_after, css_after, this.rule_idx + 1);
      }
    },

    // Remove old dropdown rule index
    clear_idx : function () {
      var sheet = Foundation.stylesheet;

      if (this.rule_idx) {
        sheet.deleteRule(this.rule_idx);
        sheet.deleteRule(this.rule_idx);
        delete this.rule_idx;
      }
    },

    small : function () {
      return matchMedia(Foundation.media_queries.small).matches &&
        !matchMedia(Foundation.media_queries.medium).matches;
    },

    off: function () {
      this.S(this.scope).off('.fndtn.dropdown');
      this.S('html, body').off('.fndtn.dropdown');
      this.S(window).off('.fndtn.dropdown');
      this.S('[data-dropdown-content]').off('.fndtn.dropdown');
    },

    reflow : function () {}
  };
}(jQuery, window, window.document));
<|endoftext|>


<commit_before>define(["jquery", "io", "../event.manager.js"], function($, io, eventManager) {
    var promptHtml = "
\r\n    @<\/span>\r\n    <input type=\"text\" id=\"prompt-userId\" class=\"form-control\" placeholder=\"Username\">\r\n<\/div>
Feel free to select a geographical scope, relative to you, in order to join the conversation:<\/p>";
    var notificationTemplateHtml = "<div class=\"alert alert-<%= type %>\">\r\n    <%= message %><\/a>\r\n<\/div>"
    var messageTemplateHtml = "<div class=\"panel panel-default <%= orientation %>\">\r\n
<%= timestamp %><\/div>\r\n
<%= from %><\/div>\r\n
<%= message %><\/div>\r\n<\/div>";
    // Constants
    var WS_URL = /*"courier.nodejitsu.com";*/ "sandile.me";
    var WS_PORT = 16558;
    // Instance variables
    var userId = null;
    var locale = null;
    var currentSession = null;
    var currLat = null;
    var currLong = null;

    // Geoloc subroutines
    function distance(lat1, lon1, lat2, lon2) {
        var radlat1 = Math.PI * lat1 / 180
        var radlat2 = Math.PI * lat2 / 180
        var radlon1 = Math.PI * lon1 / 180
        var radlon2 = Math.PI * lon2 / 180
        var theta = lon1 - lon2
        var radtheta = Math.PI * theta/180
        var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        dist = Math.acos(dist)
        dist = dist * 180/Math.PI
        dist = dist * 60 * 1.1515
        return dist
    }
    var updatePosition = function (callback) {
        navigator.geolocation.getCurrentPosition(function(position) {
            console.log(position);
            currLat = position.coords.latitude;
            currLong = position.coords.longitude;
            callback(currLat, currLong);
        }, function(positionError) {
            addNotification("danger", "We were blocked from getting Location.");
        });
    };
    // Bootstrapping subroutines
    var addNotification = function(type, message) {
        var html = notificationTemplateHtml
        .replace("<%= type %>", type)
        .replace("<%= message %>", message);

        $("#log-inner").append(html);
        console.log($("#log")[0].scrollHeight);
        $("#log").scrollTop($("#log")[0].scrollHeight);
    };
    var addMessage = function(msg, from, loc, ts) {
        var html = messageTemplateHtml
        .replace("<%= timestamp %>", ts)
        .replace("<%= orientation %>", (from === "Me") ? "right" : "left")
        .replace("<%= from %>", (from === "Me") ? from : ("@" + from))
        .replace("<%= message %>", msg);

        $("#log-inner").append(html);
        console.log($("#log")[0].scrollHeight);
        $("#log").scrollTop($("#log")[0].scrollHeight);
    };
    var joinSession = function(localeId) {
        userId = escape($("#prompt-userId").val());
        console.log(userId);
        switch (localeId) {
            case 0:
                // Building
                locale = "Building";
                break;
            case 1:
                // Block
                locale = "Block";
                break;
            case 2:
                // Neighborhood
                locale = "Neighborhood";
                break;
            case 3:
                // City
                locale = "City";
                break;
        };
        addNotification("success", "Now listening at the '" + locale + "' scope.");
        var ws = io.connect("ws://" + WS_URL + ":" + WS_PORT);
        ws.on("connect", function(sock) {
            addNotification("info", "Joined session successfully.");
            currentSession = ws;

            if (sock) {
                sock.on('disconnect', function () {
                    addNotification("danger", "Session was brutally murdered by Wifi.");
                    currentSession = null;
                });
            }
        });
        ws.on("message", function(data) {
            addMessage(data['message'], data['pseudo'], data['location'], new Date().toISOString(), false);
        });
        ws.on('nbUsers', function(msg) {
            addNotification("info", "Number of concurrent users now " + msg.nb + ".");
            console.log("Number of users = " + msg.nb);
        });
        ws.on('disconnect', function () {
            addNotification("danger", "Session was brutally murdered by Wifi.");
            currentSession = null;
        });
        ws.emit("setPseudo", userId);
        ws.on("pseudoStatus", function(data) {
            if (data == "ok") {
                bootbox.hideAll();
                $("#chat-box").focus();
            } else {
                addNotification("danger", "The internet jacked us.");
                console.log("OHHhhh NOOOOOooooooo....");
                console.log(data);
            }
        });

        $("#chat-box").bind('keypress', function(e) {
            var code = (e.keyCode ? e.keyCode : e.which);
            if (code == 13) {
                sendMessage();
            }
        });
        $("#chat-button").click(function() {
            sendMessage();
        });
        updatePosition(function () {
            addNotification("success", "Location locked to (" + currLat + ", " + currLong + ")");
        });
    };

    var sendMessage = function() {
        if (currentSession && $("#chat-box").val() && (currLat !== null && currLat !== null)) {
            var jsonObj = {
                msg: $("#chat-box").val(),
                loc: {
                    latitude: currLat,
                    longitude: currLong
                }
            };
            currentSession.emit("message", jsonObj);
            addMessage($("#chat-box").val(), "Me", null, new Date().toISOString(), true);
            $("#chat-box").val("");
            $("#chat-box").focus();
        }
    };

    // Handle header ui events
    eventManager.on("prompt:present", function() {
        bootbox.dialog({
            message: promptHtml,
            title: "Welcome to Courier",
            buttons: {
                building: {
                    label: "Building",
                    className: "btn-primary",
                    callback: function() {
                        joinSession(0);
                    }
                },
                block: {
                    label: "Block",
                    className: "btn-info",
                    callback: function() {
                        joinSession(1);
                    }
                },
                area: {
                    label: "Neighborhood",
                    className: "btn-success",
                    callback: function() {
                        joinSession(2);
                    }
                },
                city: {
                    label: "City",
                    className: "btn-warning",
                    callback: function() {
                        joinSession(3);
                    }
                }
            }
        });
    });

    // Exports
    return {
        /**
         * Initializes the header module.
         */
        init: function() {
            // All done!
            console.log("Prompt Presenter initialized");
        }
    }
});<commit_msg>Scope check now in effect<commit_after>define(["jquery", "io", "../event.manager.js"], function($, io, eventManager) {
    var promptHtml = "
\r\n    @<\/span>\r\n    <input type=\"text\" id=\"prompt-userId\" class=\"form-control\" placeholder=\"Username\">\r\n<\/div>
Feel free to select a geographical scope, relative to you, in order to join the conversation:<\/p>";
    var notificationTemplateHtml = "<div class=\"alert alert-<%= type %>\">\r\n    <%= message %><\/a>\r\n<\/div>"
    var messageTemplateHtml = "<div class=\"panel panel-default <%= orientation %>\">\r\n
<%= timestamp %><\/div>\r\n
<%= from %><\/div>\r\n
<%= message %><\/div>\r\n<\/div>";
    // Constants
    var WS_URL = /*"courier.nodejitsu.com";*/ "sandile.me";
    var WS_PORT = 16558;
    // Instance variables
    var userId = null;
    var locale = null;
    var currentSession = null;
    var currLat = null;
    var currLong = null;

    // Geoloc subroutines
    var scopeCheck = function(foreignLoc) {
        var dist = distance(currLat, curLong, foreignLoc.latitude, foreignLoc.longitude);
        if (locale === "Building") {
            return (dist < 2);
        } else if (locale === "Block") {
            return (dist < 5);
        } else if (locale === "Neighborhood") {
            return (dist < 8);
        } else if (locale === "City") {
            return (dist < 15);
        } else {
            return false;
        }
    };

    function distance(lat1, lon1, lat2, lon2) {
        var radlat1 = Math.PI * lat1 / 180
        var radlat2 = Math.PI * lat2 / 180
        var radlon1 = Math.PI * lon1 / 180
        var radlon2 = Math.PI * lon2 / 180
        var theta = lon1 - lon2
        var radtheta = Math.PI * theta / 180
        var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        dist = Math.acos(dist)
        dist = dist * 180 / Math.PI
        dist = dist * 60 * 1.1515
        return dist
    };
    var updatePosition = function(callback) {
        navigator.geolocation.getCurrentPosition(function(position) {
            console.log(position);
            currLat = position.coords.latitude;
            currLong = position.coords.longitude;
            callback(currLat, currLong);
        }, function(positionError) {
            addNotification("danger", "We were blocked from getting Location.");
        });
    };
    // Bootstrapping subroutines
    var addNotification = function(type, message) {
        var html = notificationTemplateHtml
            .replace("<%= type %>", type)
            .replace("<%= message %>", message);

        $("#log-inner").append(html);
        console.log($("#log")[0].scrollHeight);
        $("#log").scrollTop($("#log")[0].scrollHeight);
    };
    var addMessage = function(msg, from, loc, ts) {
        // Do location check
        if (scopeCheck(loc)) {
            var html = messageTemplateHtml
                .replace("<%= timestamp %>", ts)
                .replace("<%= orientation %>", (from === "Me") ? "right" : "left")
                .replace("<%= from %>", (from === "Me") ? from : ("@" + from))
                .replace("<%= message %>", msg);

            $("#log-inner").append(html);
            console.log($("#log")[0].scrollHeight);
            $("#log").scrollTop($("#log")[0].scrollHeight);
        } else {
            console.log("Message was blocked because it was out of location radius.");
        }
    };
    var joinSession = function(localeId) {
        userId = escape($("#prompt-userId").val());
        console.log(userId);
        switch (localeId) {
            case 0:
                // Building
                locale = "Building";
                break;
            case 1:
                // Block
                locale = "Block";
                break;
            case 2:
                // Neighborhood
                locale = "Neighborhood";
                break;
            case 3:
                // City
                locale = "City";
                break;
        };
        addNotification("success", "Now listening at the '" + locale + "' scope.");
        var ws = io.connect("ws://" + WS_URL + ":" + WS_PORT);
        ws.on("connect", function(sock) {
            addNotification("info", "Joined session successfully.");
            currentSession = ws;

            if (sock) {
                sock.on('disconnect', function() {
                    addNotification("danger", "Session was brutally murdered by Wifi.");
                    currentSession = null;
                });
            }
        });
        ws.on("message", function(data) {
            addMessage(data['message'], data['pseudo'], data['location'], new Date().toISOString(), false);
        });
        ws.on('nbUsers', function(msg) {
            addNotification("info", "Number of concurrent users now " + msg.nb + ".");
            console.log("Number of users = " + msg.nb);
        });
        ws.on('disconnect', function() {
            addNotification("danger", "Session was brutally murdered by Wifi.");
            currentSession = null;
        });
        ws.emit("setPseudo", userId);
        ws.on("pseudoStatus", function(data) {
            if (data == "ok") {
                bootbox.hideAll();
                $("#chat-box").focus();
            } else {
                addNotification("danger", "The internet jacked us.");
                console.log("OHHhhh NOOOOOooooooo....");
                console.log(data);
            }
        });

        $("#chat-box").bind('keypress', function(e) {
            var code = (e.keyCode ? e.keyCode : e.which);
            if (code == 13) {
                sendMessage();
            }
        });
        $("#chat-button").click(function() {
            sendMessage();
        });
        updatePosition(function() {
            addNotification("success", "Location locked to (" + currLat + ", " + currLong + ")");
        });
    };

    var sendMessage = function() {
        if (currentSession && $("#chat-box").val() && (currLat !== null && currLat !== null)) {
            var jsonObj = {
                msg: $("#chat-box").val(),
                loc: {
                    latitude: currLat,
                    longitude: currLong
                }
            };
            currentSession.emit("message", jsonObj);
            addMessage($("#chat-box").val(), "Me", null, new Date().toISOString(), true);
            $("#chat-box").val("");
            $("#chat-box").focus();
        }
    };

    // Handle header ui events
    eventManager.on("prompt:present", function() {
        bootbox.dialog({
            message: promptHtml,
            title: "Welcome to Courier",
            buttons: {
                building: {
                    label: "Building",
                    className: "btn-primary",
                    callback: function() {
                        joinSession(0);
                    }
                },
                block: {
                    label: "Block",
                    className: "btn-info",
                    callback: function() {
                        joinSession(1);
                    }
                },
                area: {
                    label: "Neighborhood",
                    className: "btn-success",
                    callback: function() {
                        joinSession(2);
                    }
                },
                city: {
                    label: "City",
                    className: "btn-warning",
                    callback: function() {
                        joinSession(3);
                    }
                }
            }
        });
    });

    // Exports
    return {
        /**
         * Initializes the header module.
         */
        init: function() {
            // All done!
            console.log("Prompt Presenter initialized");
        }
    }
});<|endoftext|>


<commit_before>/*jshint node:true jquery:true*/
"use strict";

var clayer = require('../clayer');

module.exports = function(editor) {
	editor.Stepbar = function() { return this.init.apply(this, arguments); };
	editor.Stepbar.prototype = {
		init: function($div, ed) {
			ed.bindEventHandler(this);

			this.$div = $div;
			this.editor = ed;

			this.$div.addClass('editor-stepbar');
			this.$div.on('mousemove', this.onMouseMove.bind(this));
			this.$div.on('mouseleave', this.onMouseLeave.bind(this));
			this.$div.on('click', this.onClick.bind(this));

			this.$numbers = $('

');
			this.$div.append(this.$numbers);

			this.editorMarginSize = 26; // corresponds to @editor-margin-size in global.less

			this.stepNumbersLength = 0;
			this.numberWidth = 16;
			this.numberMargin = 3;
			this.currentStep = null;
			this.mouseX = null;
			this.locked = false;
			this.lockedStep = null;
			this.leftOffset = 0;
		},

		remove: function() {
			this.$div.html('');
			this.$div.removeClass('editor-stepbar');
		},

		update: function(runner) {
			if (runner.isStatic() && runner.canStep()) {
				if (!this.enabled) {
					this.setLeftOffset(0);
				}
				this.enabled = true;
				this.runner = runner;
				this.$numbers.show();
				this.setStepTotal(runner.getStepTotal());
				this.setStepNum(runner.getStepNum());
			} else {
				this.disable();
			}
		},

		disable: function() {
			this.enabled = false;
			this.runner = null;
			this.$numbers.hide();
			this.mouseX = null;
			this.unsetlocked();
		},

		/// INTERNAL FUNCTIONS ///
		onMouseMove: function(e) {
			this.mouseX = e.pageX - this.$div.offset().left;
			this.updateMouse();
		},

		onMouseLeave: function() {
			this.mouseX = null;
			this.updateMouse();
		},

		onClick: function() {
			if (this.currentStep !== null) {
				if (this.locked && this.currentStep === this.lockedStep) {
					this.unsetlocked();
					this.updateMouse();
				} else {
					this.unsetlocked();
					this.setlocked();
				}
			}
		},

		setlocked: function() {
			this.$div.addClass('editor-stepbar-locked');
			this.locked = true;
			this.lockedStep = this.currentStep;

			if (this.lockedStep !== null) {
				this.$stepNumber(this.lockedStep).addClass('editor-stepbar-step-number-locked');
			}
		},

		unsetlocked: function() {
			this.$div.removeClass('editor-stepbar-locked');
			this.locked = false;
			this.lockedStep = null;
			this.$numbers.children('.editor-stepbar-step-number-locked').removeClass('editor-stepbar-step-number-locked');
		},

		updateLeftOffset: function() {
			if (!this.enabled || this.locked) return;

			var fraction = 0;
			if (this.mouseX !== null) {
				fraction = this.fractionFromX(this.mouseX);
			}
			this.setLeftOffset(this.leftOffsetFromFraction(fraction));
		},

		updateMouse: function() {
			if (!this.enabled) return;

			this.updateLeftOffset();
			if (this.mouseX !== null) {
				var step = this.stepFromXAndLeftOffset(this.mouseX, this.leftOffset);
				this.runner.setStepNum(step);
			} else if (this.currentStep !== this.lockedStep) {
				if (this.lockedStep !== null) {
					this.runner.setStepNum(this.lockedStep);
				} else {
					this.runner.restart();
				}
			}
		},

		setLeftOffset: function(leftOffset) {
			this.$numbers.css('left', leftOffset);
			this.leftOffset = leftOffset;
		},

		fractionFromX: function(x) {
			var sideMargin = this.numberWidth/2;
			var totalWidth = this.$div.outerWidth();
			var clippedX = Math.max(sideMargin, Math.min(totalWidth-sideMargin, x));
			return (clippedX-sideMargin)/(this.$div.outerWidth()-sideMargin*2);
		},

		leftOffsetFromFraction: function(fraction) {
			var numbersWidth = this.$numbers.outerWidth();
			var divWidth = this.$div.outerWidth();
			if (numbersWidth >= divWidth) {
				var scrollWidth = numbersWidth - divWidth;
				return -Math.round(fraction*scrollWidth);
			} else {
				var halfDivWidth = Math.floor(divWidth / 2);
				var leftOffsetAlignedRight = divWidth - numbersWidth;
				return Math.min(leftOffsetAlignedRight, halfDivWidth + this.editorMarginSize);
			}
		},

		stepFromXAndLeftOffset: function(x, leftOffset) {
			var width = this.numberWidth + this.numberMargin;
			var realX = x-leftOffset + this.numberMargin/2;

			var totalWidth = this.$numbers.outerWidth();
			var step = Math.floor(realX*this.stepTotal/totalWidth);

			return Math.min(this.stepTotal-1, Math.max(0, step));
		},

		setStepNum: function(stepNum) {
			if (stepNum === Infinity) stepNum = null;

			if (this.currentStep !== stepNum) {
				if (this.currentStep !== null) {
					this.$stepNumber(this.currentStep).removeClass('editor-stepbar-step-number-hover');
				}
				if (stepNum !== null) {
					this.$stepNumber(stepNum).addClass('editor-stepbar-step-number-hover');
				}
				this.currentStep = stepNum;
			}
		},

		setStepTotal: function(stepTotal) {
			if (stepTotal >= 998) stepTotal = 998;

			if (stepTotal !== this.stepTotal) {
				var stepsHTML = '';
				for (var step=this.stepNumbersLength; step<stepTotal; step++) {
					stepsHTML += this.getStepNumberHTML(step);
				}
				this.$numbers.append(stepsHTML);
				this.stepNumbersLength = step;

				this.removeNumbers(stepTotal);
				this.updateNumbersWidth(stepTotal);
				this.stepTotal = stepTotal;
				this.updateLeftOffset();
			}
		},

		removeNumbers: function(fromStep) {
			var $lastStepNumber = this.$stepNumber(fromStep-1);
			$lastStepNumber.nextAll().remove();

			if (this.currentStep >= fromStep) {
				this.currentStep = null;
			}
			if (this.lockedStep >= fromStep) {
				this.unsetlocked();
			}
		},

		getStepNumberHTML: function(step) {
			return '
' + (step+1) + '
';
		},

		$stepNumber: function(step) {
			return this.$numbers.children('.editor-stepbar-step-number-' + step);
		},

		updateNumbersWidth: function(stepTotal) {
			var width = this.numberWidth+this.numberMargin;
			this.$numbers.width(width*stepTotal);
		}
	};
};
<commit_msg>Stepbar fixes.<commit_after>/*jshint node:true jquery:true*/
"use strict";

var clayer = require('../clayer');

module.exports = function(editor) {
	editor.Stepbar = function() { return this.init.apply(this, arguments); };
	editor.Stepbar.prototype = {
		init: function($div, ed) {
			ed.bindEventHandler(this);

			this.$div = $div;
			this.editor = ed;

			this.$div.addClass('editor-stepbar');
			this.$div.on('mousemove', this.onMouseMove.bind(this));
			this.$div.on('mouseleave', this.onMouseLeave.bind(this));
			this.$div.on('click', this.onClick.bind(this));

			this.$numbers = $('

');
			this.$div.append(this.$numbers);

			this.editorMarginSize = 26; // corresponds to @editor-margin-size in global.less

			this.stepNumbersLength = 0;
			this.numberWidth = 16;
			this.numberMargin = 3;
			this.currentStep = null;
			this.mouseX = null;
			this.locked = false;
			this.lockedStep = null;
			this.leftOffset = 0;
		},

		remove: function() {
			this.$div.html('');
			this.$div.removeClass('editor-stepbar');
		},

		update: function(runner) {
			if (runner.isStatic() && runner.canStep()) {
				if (!this.enabled) {
					this.setLeftOffset(0);
				}
				this.enabled = true;
				this.runner = runner;
				this.$numbers.show();
				this.setStepTotal(runner.getStepTotal());
				this.setStepNum(runner.getStepNum());
			} else {
				this.disable();
			}
		},

		disable: function() {
			this.enabled = false;
			this.runner = null;
			this.$numbers.hide();
			this.mouseX = null;
			this.unsetlocked();
		},

		/// INTERNAL FUNCTIONS ///
		onMouseMove: function(e) {
			this.mouseX = e.pageX - this.$div.offset().left;
			this.updateMouse();
		},

		onMouseLeave: function() {
			this.mouseX = null;
			this.updateMouse();
		},

		onClick: function() {
			if (this.currentStep !== null) {
				if (this.locked && this.currentStep === this.lockedStep) {
					this.unsetlocked();
					this.updateMouse();
				} else {
					this.unsetlocked();
					this.setlocked();
				}
			}
		},

		setlocked: function() {
			this.$div.addClass('editor-stepbar-locked');
			this.locked = true;
			this.lockedStep = this.currentStep;

			if (this.lockedStep !== null) {
				this.$stepNumber(this.lockedStep).addClass('editor-stepbar-step-number-locked');
			}
		},

		unsetlocked: function() {
			this.$div.removeClass('editor-stepbar-locked');
			this.locked = false;
			this.lockedStep = null;
			this.$numbers.children('.editor-stepbar-step-number-locked').removeClass('editor-stepbar-step-number-locked');
		},

		updateLeftOffset: function() {
			if (!this.enabled || this.locked) return;

			var fraction = 0;
			if (this.mouseX !== null) {
				fraction = this.fractionFromX(this.mouseX);
			}
			this.setLeftOffset(this.leftOffsetFromFraction(fraction));
		},

		updateMouse: function() {
			if (!this.enabled) return;

			this.updateLeftOffset();
			if (this.mouseX !== null) {
				var step = this.stepFromXAndLeftOffset(this.mouseX, this.leftOffset);
				this.runner.setStepNum(step);
			} else if (this.currentStep !== this.lockedStep) {
				if (this.lockedStep !== null) {
					this.runner.setStepNum(this.lockedStep);
				} else {
					this.runner.restart();
				}
			}
		},

		setLeftOffset: function(leftOffset) {
			this.$numbers.css('left', leftOffset);
			this.leftOffset = leftOffset;
		},

		fractionFromX: function(x) {
			var sideMargin = this.numberWidth/2;
			var totalWidth = this.$div.outerWidth();
			var clippedX = Math.max(sideMargin, Math.min(totalWidth-sideMargin, x));
			return (clippedX-sideMargin)/(this.$div.outerWidth()-sideMargin*2);
		},

		leftOffsetFromFraction: function(fraction) {
			var numbersWidth = this.$numbers.outerWidth();
			var divWidth = this.$div.outerWidth();
			if (numbersWidth >= divWidth) {
				var scrollWidth = numbersWidth - divWidth;
				return -Math.round(fraction*scrollWidth);
			} else {
				var halfDivWidth = Math.floor(divWidth / 2);
				var leftOffsetAlignedRight = divWidth - numbersWidth;
				return Math.min(leftOffsetAlignedRight, halfDivWidth + this.editorMarginSize);
			}
		},

		stepFromXAndLeftOffset: function(x, leftOffset) {
			var width = this.numberWidth + this.numberMargin;
			var realX = x-leftOffset + this.numberMargin/2;

			var totalWidth = this.$numbers.outerWidth();
			var step = Math.floor(realX*this.stepTotal/totalWidth);

			return Math.min(this.stepTotal-1, Math.max(0, step));
		},

		setStepNum: function(stepNum) {
			if (stepNum >= 998) stepNum = null;

			if (this.currentStep !== stepNum) {
				if (this.currentStep !== null) {
					this.$stepNumber(this.currentStep).removeClass('editor-stepbar-step-number-hover');
				}
				if (stepNum !== null) {
					this.$stepNumber(stepNum).addClass('editor-stepbar-step-number-hover');
				}
				this.currentStep = stepNum;
			}
		},

		setStepTotal: function(stepTotal) {
			if (stepTotal >= 998) stepTotal = 998;

			if (stepTotal !== this.stepTotal) {
				var stepsHTML = '';
				for (var step=this.stepNumbersLength; step<stepTotal; step++) {
					stepsHTML += this.getStepNumberHTML(step);
				}
				this.$numbers.append(stepsHTML);
				this.stepNumbersLength = step;

				this.removeNumbers(stepTotal);
				this.updateNumbersWidth(stepTotal);
				this.stepTotal = stepTotal;
				this.updateLeftOffset();
			}
		},

		removeNumbers: function(fromStep) {
			var $lastStepNumber = this.$stepNumber(fromStep-1);
			$lastStepNumber.nextAll().remove();
			this.stepNumbersLength = fromStep;

			if (this.currentStep >= fromStep) {
				this.currentStep = null;
			}
			if (this.lockedStep >= fromStep) {
				this.unsetlocked();
			}
		},

		getStepNumberHTML: function(step) {
			return '
' + (step+1) + '
';
		},

		$stepNumber: function(step) {
			return this.$numbers.children('.editor-stepbar-step-number-' + step);
		},

		updateNumbersWidth: function(stepTotal) {
			var width = this.numberWidth+this.numberMargin;
			this.$numbers.width(width*stepTotal);
		}
	};
};
<|endoftext|>


<commit_before>describe('mocha + assert', function() {
  it('simple values equal?', function() {
    assert.equal('one', 'one');
  });
  it('simple values doesnt equal?', function() {
    assert.notEqual('one', 'two');
  });

  it('value is truthy', function() {
    assert.ok(true);
  });

  it('complex types equal?', function() {
    assert.deepEqual([1,2,3], [1,2,3]);
  });
  it('complex types dont equal?', function() {
    assert.notDeepEqual([1,2,3], ['one', 'two']);
  });

  it('value and type equal?', function() {
    assert.strictEqual('1', '1');
  });
  it('complex types dont equal?', function() {
    assert.notStrictEqual(1, '1');
  });

  it('throws?', function() {
    assert.throws(function(){ throw new Error(); });
  });
  it('does not throw?', function() {
    assert.doesNotThrow(function() {});
  });
});<commit_msg>Better test name.<commit_after>describe('mocha+assert API description', function() {

  it('simple values equal?', function() {
    assert.equal('one', 'one');
  });
  it('simple values doesnt equal?', function() {
    assert.notEqual('one', 'two');
  });

  it('value is truthy', function() {
    assert.ok(true);
  });

  it('complex types equal?', function() {
    assert.deepEqual([1,2,3], [1,2,3]);
  });
  it('complex types dont equal?', function() {
    assert.notDeepEqual([1,2,3], ['one', 'two']);
  });

  it('value and type equal?', function() {
    assert.strictEqual('1', '1');
  });
  it('complex types dont equal?', function() {
    assert.notStrictEqual(1, '1');
  });

  it('throws?', function() {
    assert.throws(function(){ throw new Error(); });
  });
  it('does not throw?', function() {
    assert.doesNotThrow(function() {});
  });
});<|endoftext|>


<commit_before>// 29: array -
// To do: make all tests pass, leave the assert lines unchanged!

describe('Array.from converts an array-like object or list into an Array', () => {

  it('from an object, requires the length property', function() {
    const arr = Array.from({0: 1, 1: 2, length: 2});

    assert.deepEqual(arr, [1, 2]);
  });

  it('a DOM node`s classList object can be converted', function() {
    document.body.classList.add('some');
    document.body.classList.add('other');
    const classList = Array.from(document.body.classList);

    assert.deepEqual(classList, ['some', 'other']);
  });

  it('convert a NodeList to an Array and filter works on it', function() {
    const nodeList = Array.from(document.querySelectorAll('body'));
    const bodies = nodeList.filter((node) => node === document.body);

    assert.deepEqual(bodies, [document.body]);
  });

  describe('custom conversion using a map function as second param', () => {
    it('we can modify the value before putting it in the array', function() {
      const arr = Array.from({0: 1, 1: 2, length: 2}, (value) => value - 1);
      assert.deepEqual(arr, [0, 1]);
    });

    it('and we also get the object`s key', function() {
      const arrLike = {0: 'one', 1: 'two', length: 2};
      const arr = Array.from(arrLike, (value, key) => `${key}=${value}`);
      assert.deepEqual(arr, ['0=one', '1=two']);
    });
  });

});
<commit_msg>Now it's a real kata.<commit_after>// 29: array - `Array.from` static method
// To do: make all tests pass, leave the assert lines unchanged!

describe('`Array.from` converts an array-like object or list into an Array', () => {

  const arrayLike = {0: 'one', 1: 'two', length: 2};

  it('call `Array.from` with an array-like object', function() {
    const arr = arrayLike;

    assert.deepEqual(arr, ['one', 'two']);
  });

  it('a DOM node`s classList object can be converted', function() {
    document.body.classList.add('some');
    document.body.classList.add('other');
    const classList = document.body.classList;

    assert.deepEqual(classList, ['some', 'other']);
  });

  it('convert a NodeList to an Array and `filter()` works on it', function() {
    const nodeList = document.querySelectorAll('body');
    const bodies = nodeList.filter((node) => node === document.body);

    assert.deepEqual(bodies, [document.body]);
  });

  describe('custom conversion using a map function as second param', () => {
    it('we can modify the value before putting it in the array', function() {
      const arr = Array.from(arrayLike, (value) => value);
      assert.deepEqual(arr, ['ONE', 'TWO']);
    });

    it('and we also get the object`s key as second parameter', function() {
      const arr = Array.from(arrayLike, (value) => `${key}=${value}`);
      assert.deepEqual(arr, ['0=one', '1=two']);
    });
  });

});<|endoftext|>


<commit_before>'use strict';

module.exports = {

  controller: function (args) {
    this.servico = args.servico;
  },

  view: function (ctrl) {
    return m('fieldset#nome', [
      m('h2', 'dados básicos'),
      m('h3', [
        'Nome do serviço',
        m.component(require('tooltips').nome)
      ]),

      m('input[type=text]', {
        onchange: m.withAttr('value', ctrl.servico().nome),
        value: ctrl.servico().nome()
      })
    ]);
  }

};
<commit_msg>Focando inicialmente no nome do serviço<commit_after>'use strict';

module.exports = {

  controller: function (args) {
    this.servico = args.servico;
  },

  view: function (ctrl) {
    return m('fieldset#nome', [
      m('h2', 'dados básicos'),
      m('h3', [
        'Nome do serviço',
        m.component(require('tooltips').nome)
      ]),

      m('input[type=text]', {
        onchange: m.withAttr('value', ctrl.servico().nome),
        value: ctrl.servico().nome(),
        autofocus: 'autofocus'
      })
    ]);
  }

};
<|endoftext|>