<commit_before>'use strict';

angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, ongoingProcess, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService, platformInfo, bwcError, gettextCatalog, scannerService, configService, bitcoinCashJsService, $ionicPopup, $ionicNavBarDelegate, clipboardService) {
  var clipboardHasAddress = false;
  var clipboardHasContent = false;
  var originalList;
  $scope.displayBalanceAsFiat = true;
  $scope.walletSelectorTitleForce = true;

  $scope.addContact = function() {
      $state.go('tabs.send.addressbook');
  };

  $scope.pasteClipboard = function() {
    if ($scope.clipboardHasAddress || $scope.clipboardHasContent) {
      clipboardService.readFromClipboard(function(text) {
        $scope.$apply(function() {
          $scope.formData.search = text;
          $scope.findContact($scope.formData.search);
        });
      });
    } else {
      $ionicPopup.alert({
        title: gettextCatalog.getString('Clipboard'),
        template: gettextCatalog.getString('Your Clipboard is empty')
      });
    }
  };

  $scope.$on("$ionicView.enter", function(event, data) {
    clipboardService.readFromClipboard(function(text) {
      if (text.length > 200) {
        text = text.substring(0, 200);
      }

      $scope.clipboardHasAddress = false;
      $scope.clipboardHasContent = false;
      if ((text.indexOf('bitcoincash:') === 0 || text[0] === 'C' || text[0] === 'H' || text[0] === 'p' || text[0] === 'q') && text.replace('bitcoincash:', '').length === 42) { // CashAddr
        $scope.clipboardHasAddress = true;
      } else if ((text[0] === "1" || text[0] === "3" || text.substring(0, 3) === "bc1") && text.length >= 26 && text.length <= 35) { // Legacy Addresses
        $scope.clipboardHasAddress = true;
      } else if (text.length > 1) {
        $scope.clipboardHasContent = true;
      }
    });

    $ionicNavBarDelegate.showBar(true);
    if (!$scope.hasWallets) {
      $scope.checkingBalance = false;
      return;
    }
    updateHasFunds();
    updateContactsList(function() {
      updateList();
    });
  });

  var wallets;
  var walletsBch;
  var walletsBtc;
  var walletToWalletFrom = false;

  $scope.onWalletSelect = function(wallet) {
    if (!$scope.walletToWalletFrom) {
      $scope.walletToWalletFrom = wallet;
      if (wallet.coin === 'bch') {
        $scope.showWalletsBch = true;
      } else if (wallet.coin === 'btc') {
        $scope.showWalletsBtc = true;
      }
      $scope.walletSelectorTitleTo = gettextCatalog.getString('Send to');
    } else {
      ongoingProcess.set(null, true);
      walletService.getAddress(wallet, true, function(err, addr) {
        ongoingProcess.set(null, false);
        return $state.transitionTo('tabs.send.amount', {
          displayAddress: $scope.walletToWalletFrom.coin === 'bch' ? bitcoinCashJsService.translateAddresses(addr).cashaddr : addr,
          recipientType: 'wallet',
          fromWalletId: $scope.walletToWalletFrom.walletId,
          toAddress: addr,
          coin: $scope.walletToWalletFrom.coin
        });
      });

    }
  };

  $scope.showWalletSelector = function() {
    $scope.walletToWalletFrom = false;
    $scope.walletSelectorTitleFrom = gettextCatalog.getString('Send from');
    $scope.showWallets = true;
  };

  $scope.findContact = function(search) {

    if (incomingData.redir(search)) {
      return;
    }

    if (!search || search.length < 1) {
      $scope.list = originalList;
      $timeout(function() {
        $scope.$apply();
      });
      return;
    }

    var result = lodash.filter(originalList, function(item) {
      var val = item.name;
      return lodash.startsWith(val.toLowerCase(), search.toLowerCase());
    });

    $scope.list = result;
  };

  var hasWallets = function() {
    $scope.walletsWithFunds = profileService.getWallets({
      onlyComplete: true,
      hasFunds: true
    });
    $scope.wallets = profileService.getWallets({
      onlyComplete: true,
    });
    $scope.walletsBch = profileService.getWallets({
      onlyComplete: true,
      coin: 'bch'
    });
    $scope.walletsBtc = profileService.getWallets({
      onlyComplete: true,
      coin: 'btc'
    });
    $scope.hasWallets = lodash.isEmpty($scope.wallets) ? false : true;
  };

  var updateHasFunds = function() {

    $scope.hasFunds = false;
    var index = 0;
    lodash.each($scope.wallets, function(w) {
      walletService.getStatus(w, {}, function(err, status) {

        ++index;
        if (err && !status) {
          $log.error(err);
          // error updating the wallet. Probably a network error, do not show
          // the 'buy bitcoins' message.

          $scope.hasFunds = true;
        } else if (status.availableBalanceSat > 0) {
          $scope.hasFunds = true;
        }

        if (index === $scope.wallets.length) {
          $scope.checkingBalance = false;
          $timeout(function() {
            $scope.$apply();
          });
        }
      });
    });
  };

  var updateContactsList = function(cb) {
    var config = configService.getSync();
    var defaults = configService.getDefaults();
    addressbookService.list(function(err, ab) {
      if (err) $log.error(err);

      $scope.hasContacts = lodash.isEmpty(ab) ? false : true;
      if (!$scope.hasContacts) return cb();

      var completeContacts = [];
      lodash.each(ab, function(v, k) {
        completeContacts.push({
          name: lodash.isObject(v) ? v.name : v,
          address: k,
          email: lodash.isObject(v) ? v.email : null,
          recipientType: 'contact',
          coin: v.coin,
          displayCoin:  (v.coin == 'bch'
              ? (config.bitcoinCashAlias || defaults.bitcoinCashAlias)
              : (config.bitcoinAlias || defaults.bitcoinAlias)).toUpperCase(),
          getAddress: function(cb) {
            return cb(null, k);
          },
        });
      });
      originalList = completeContacts;
      return cb();
    });
  };

  var updateList = function() {
    $scope.list = lodash.clone(originalList);
    $timeout(function() {
      $ionicScrollDelegate.resize();
      $scope.$apply();
    }, 10);
  };

  $scope.searchInFocus = function() {
    $scope.searchFocus = true;
  };

  $scope.searchBlurred = function() {
    if ($scope.formData.search == null || $scope.formData.search.length == 0) {
      $scope.searchFocus = false;
    }
  };

  $scope.goToAmount = function(item) {
    $timeout(function() {
      item.getAddress(function(err, addr) {
        if (err || !addr) {
          //Error is already formated
          return popupService.showAlert(err);
        }

        if (item.recipientType && item.recipientType == 'contact') {
          if (addr.indexOf('bch') == 0 || addr.indexOf('btc') == 0) {
            addr = addr.substring(3);
          }
        }

        $log.debug('Got toAddress:' + addr + ' | ' + item.name);
        return $state.transitionTo('tabs.send.amount', {
          recipientType: item.recipientType,
          displayAddress: item.coin == 'bch' ? bitcoinCashJsService.translateAddresses(addr).cashaddr : addr,
          toAddress: addr,
          toName: item.name,
          toEmail: item.email,
          toColor: item.color,
          coin: item.coin
        });
      });
    });
  };

  // This could probably be enhanced refactoring the routes abstract states
  $scope.createWallet = function() {
    $state.go('tabs.home').then(function() {
      $state.go('tabs.add.create-personal');
    });
  };

  $scope.buyBitcoin = function() {
    $state.go('tabs.home').then(function() {
      $state.go('tabs.buyandsell');
    });
  };

  $scope.$on("$ionicView.beforeEnter", function(event, data) {
    $scope.isIOS = platformInfo.isIOS && platformInfo.isCordova;
    $scope.showWalletsBch = $scope.showWalletsBtc = $scope.showWallets = false;

    $scope.checkingBalance = true;
    $scope.formData = {
      search: null
    };
    originalList = [];
    hasWallets();

    configService.whenAvailable(function(_config) {
      $scope.displayBalanceAsFiat = _config.wallet.settings.priceDisplay === 'fiat';
    });

  });
});
<commit_msg>416 - ionicLoading<commit_after>'use strict';

angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, $ionicLoading, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService, platformInfo, bwcError, gettextCatalog, scannerService, configService, bitcoinCashJsService, $ionicPopup, $ionicNavBarDelegate, clipboardService) {
  var clipboardHasAddress = false;
  var clipboardHasContent = false;
  var originalList;
  $scope.displayBalanceAsFiat = true;
  $scope.walletSelectorTitleForce = true;

  $scope.addContact = function() {
      $state.go('tabs.send.addressbook');
  };

  $scope.pasteClipboard = function() {
    if ($scope.clipboardHasAddress || $scope.clipboardHasContent) {
      clipboardService.readFromClipboard(function(text) {
        $scope.$apply(function() {
          $scope.formData.search = text;
          $scope.findContact($scope.formData.search);
        });
      });
    } else {
      $ionicPopup.alert({
        title: gettextCatalog.getString('Clipboard'),
        template: gettextCatalog.getString('Your Clipboard is empty')
      });
    }
  };

  $scope.$on("$ionicView.enter", function(event, data) {
    clipboardService.readFromClipboard(function(text) {
      if (text.length > 200) {
        text = text.substring(0, 200);
      }

      $scope.clipboardHasAddress = false;
      $scope.clipboardHasContent = false;
      if ((text.indexOf('bitcoincash:') === 0 || text[0] === 'C' || text[0] === 'H' || text[0] === 'p' || text[0] === 'q') && text.replace('bitcoincash:', '').length === 42) { // CashAddr
        $scope.clipboardHasAddress = true;
      } else if ((text[0] === "1" || text[0] === "3" || text.substring(0, 3) === "bc1") && text.length >= 26 && text.length <= 35) { // Legacy Addresses
        $scope.clipboardHasAddress = true;
      } else if (text.length > 1) {
        $scope.clipboardHasContent = true;
      }
    });

    $ionicNavBarDelegate.showBar(true);
    if (!$scope.hasWallets) {
      $scope.checkingBalance = false;
      return;
    }
    updateHasFunds();
    updateContactsList(function() {
      updateList();
    });
  });

  var wallets;
  var walletsBch;
  var walletsBtc;
  var walletToWalletFrom = false;

  $scope.onWalletSelect = function(wallet) {
    if (!$scope.walletToWalletFrom) {
      $scope.walletToWalletFrom = wallet;
      if (wallet.coin === 'bch') {
        $scope.showWalletsBch = true;
      } else if (wallet.coin === 'btc') {
        $scope.showWalletsBtc = true;
      }
      $scope.walletSelectorTitleTo = gettextCatalog.getString('Send to');
    } else {
      $ionicLoading.show();
      walletService.getAddress(wallet, true, function(err, addr) {
        $ionicLoading.hide();
        return $state.transitionTo('tabs.send.amount', {
          displayAddress: $scope.walletToWalletFrom.coin === 'bch' ? bitcoinCashJsService.translateAddresses(addr).cashaddr : addr,
          recipientType: 'wallet',
          fromWalletId: $scope.walletToWalletFrom.walletId,
          toAddress: addr,
          coin: $scope.walletToWalletFrom.coin
        });
      });

    }
  };

  $scope.showWalletSelector = function() {
    $scope.walletToWalletFrom = false;
    $scope.walletSelectorTitleFrom = gettextCatalog.getString('Send from');
    $scope.showWallets = true;
  };

  $scope.findContact = function(search) {

    if (incomingData.redir(search)) {
      return;
    }

    if (!search || search.length < 1) {
      $scope.list = originalList;
      $timeout(function() {
        $scope.$apply();
      });
      return;
    }

    var result = lodash.filter(originalList, function(item) {
      var val = item.name;
      return lodash.startsWith(val.toLowerCase(), search.toLowerCase());
    });

    $scope.list = result;
  };

  var hasWallets = function() {
    $scope.walletsWithFunds = profileService.getWallets({
      onlyComplete: true,
      hasFunds: true
    });
    $scope.wallets = profileService.getWallets({
      onlyComplete: true,
    });
    $scope.walletsBch = profileService.getWallets({
      onlyComplete: true,
      coin: 'bch'
    });
    $scope.walletsBtc = profileService.getWallets({
      onlyComplete: true,
      coin: 'btc'
    });
    $scope.hasWallets = lodash.isEmpty($scope.wallets) ? false : true;
  };

  var updateHasFunds = function() {

    $scope.hasFunds = false;
    var index = 0;
    lodash.each($scope.wallets, function(w) {
      walletService.getStatus(w, {}, function(err, status) {

        ++index;
        if (err && !status) {
          $log.error(err);
          // error updating the wallet. Probably a network error, do not show
          // the 'buy bitcoins' message.

          $scope.hasFunds = true;
        } else if (status.availableBalanceSat > 0) {
          $scope.hasFunds = true;
        }

        if (index === $scope.wallets.length) {
          $scope.checkingBalance = false;
          $timeout(function() {
            $scope.$apply();
          });
        }
      });
    });
  };

  var updateContactsList = function(cb) {
    var config = configService.getSync();
    var defaults = configService.getDefaults();
    addressbookService.list(function(err, ab) {
      if (err) $log.error(err);

      $scope.hasContacts = lodash.isEmpty(ab) ? false : true;
      if (!$scope.hasContacts) return cb();

      var completeContacts = [];
      lodash.each(ab, function(v, k) {
        completeContacts.push({
          name: lodash.isObject(v) ? v.name : v,
          address: k,
          email: lodash.isObject(v) ? v.email : null,
          recipientType: 'contact',
          coin: v.coin,
          displayCoin:  (v.coin == 'bch'
              ? (config.bitcoinCashAlias || defaults.bitcoinCashAlias)
              : (config.bitcoinAlias || defaults.bitcoinAlias)).toUpperCase(),
          getAddress: function(cb) {
            return cb(null, k);
          },
        });
      });
      originalList = completeContacts;
      return cb();
    });
  };

  var updateList = function() {
    $scope.list = lodash.clone(originalList);
    $timeout(function() {
      $ionicScrollDelegate.resize();
      $scope.$apply();
    }, 10);
  };

  $scope.searchInFocus = function() {
    $scope.searchFocus = true;
  };

  $scope.searchBlurred = function() {
    if ($scope.formData.search == null || $scope.formData.search.length == 0) {
      $scope.searchFocus = false;
    }
  };

  $scope.goToAmount = function(item) {
    $timeout(function() {
      item.getAddress(function(err, addr) {
        if (err || !addr) {
          //Error is already formated
          return popupService.showAlert(err);
        }

        if (item.recipientType && item.recipientType == 'contact') {
          if (addr.indexOf('bch') == 0 || addr.indexOf('btc') == 0) {
            addr = addr.substring(3);
          }
        }

        $log.debug('Got toAddress:' + addr + ' | ' + item.name);
        return $state.transitionTo('tabs.send.amount', {
          recipientType: item.recipientType,
          displayAddress: item.coin == 'bch' ? bitcoinCashJsService.translateAddresses(addr).cashaddr : addr,
          toAddress: addr,
          toName: item.name,
          toEmail: item.email,
          toColor: item.color,
          coin: item.coin
        });
      });
    });
  };

  // This could probably be enhanced refactoring the routes abstract states
  $scope.createWallet = function() {
    $state.go('tabs.home').then(function() {
      $state.go('tabs.add.create-personal');
    });
  };

  $scope.buyBitcoin = function() {
    $state.go('tabs.home').then(function() {
      $state.go('tabs.buyandsell');
    });
  };

  $scope.$on("$ionicView.beforeEnter", function(event, data) {
    $scope.isIOS = platformInfo.isIOS && platformInfo.isCordova;
    $scope.showWalletsBch = $scope.showWalletsBtc = $scope.showWallets = false;

    $scope.checkingBalance = true;
    $scope.formData = {
      search: null
    };
    originalList = [];
    hasWallets();

    configService.whenAvailable(function(_config) {
      $scope.displayBalanceAsFiat = _config.wallet.settings.priceDisplay === 'fiat';
    });

  });
});
<|endoftext|>


<commit_before>(function( $ ) {
    "use strict";

    $.widget("metro.carousel", {

        version: "3.0.0",

        options: {
            auto: true,
            period: 5000,
            duration: 1000,
            effect: 'slide', // slide, fade, switch, slowdown
            effectFunc: 'linear',
            direction: 'left',
            controls: true,
            controlNext: false,
            controlPrev: false,
            markers: true,
            stop: true,
            width: '100%',
            height: false,

            _slides: {},
            _currentIndex: 0,
            _interval: 0,
            _outPosition: 0
        },

        _create: function(){
            var that = this, o = this.options,
                element = this.element;

            $.each(element.data(), function(key, value){
                if (key in o) {
                    try {
                        o[key] = $.parseJSON(value);
                    } catch (e) {
                        o[key] = value;
                    }
                }
            });

            o._slides = element.find('.slide');

            var max_height = 0; //element.find('.slide:nth-child(1)').outerHeight();

            $.each(o._slides, function(){
                var oh, slide = $(this);

                oh = slide.outerHeight();

                if (oh > max_height) {max_height = oh;}
            });

            element.find('.slide').hide();
            element.find('.slide:nth-child(1)').show();

            element.css({
                'width': o.width,
                'height': o.height ? o.height : max_height
            });

            if (o._slides.length <= 1) {return;}

            if (o.markers) {
                this._markers();
            }

            if (o.controls) {
                this._controls();
            }

            if (o.stop) {
                element
                    .on('mouseenter', function(){
                        clearInterval(o._interval);
                    })
                    .on('mouseleave', function(){
                        if (that.options.auto) {that._autoStart();}// that.options.period;
                    });
            }

            //this._slideToSlide(0);
            if (o.auto) {
                this._autoStart();
            }

            element.data('carousel', this);

        },

        _autoStart: function(){
            var that = this, o = this.options;
            o._interval = setInterval(function(){
                if (o.direction === 'left') {
                    that._slideTo('next');
                } else {
                    that._slideTo('prior');
                }
            }, o.period);
        },

        _slideTo: function(direction){
            var carousel = this.element, that = this, o = this.options;
            var currentSlide = o._slides[o._currentIndex], nextSlide;

            if (direction === undefined) {direction = 'next';}

            if (direction === 'prior') {
                o._currentIndex -= 1;
                if (o._currentIndex < 0) {o._currentIndex = o._slides.length - 1;}

                o._outPosition = this.element.width();

            } else if (direction === 'next') {
                o._currentIndex += 1;
                if (o._currentIndex >= o._slides.length) {o._currentIndex = 0;}

                o._outPosition = -this.element.width();

            }

            nextSlide = o._slides[o._currentIndex];

            switch (this.options.effect) {
                case 'switch': this._effectSwitch(currentSlide, nextSlide); break;
                case 'slowdown': this._effectSlowdown(currentSlide, nextSlide, this.options.duration); break;
                case 'fade': this._effectFade(currentSlide, nextSlide, this.options.duration); break;
                default: this._effectSlide(currentSlide, nextSlide, this.options.duration);
            }

            carousel.find('.carousel-bullets a').each(function(){
                var index = $(this).data('num');
                if (index === o._currentIndex) {
                    $(this).addClass('bullet-on');
                } else {
                    $(this).removeClass('bullet-on');
                }
            });
        },

        _slideToSlide: function(slideIndex){
            var o = this.options,
                currentSlide = o._slides[o._currentIndex],
                nextSlide = o._slides[slideIndex];

            if (slideIndex > o._currentIndex) {
                o._outPosition = -this.element.width();
            } else {
                o._outPosition = this.element.width();
            }

            switch (this.options.effect) {
                case 'switch' : this._effectSwitch(currentSlide, nextSlide); break;
                case 'slowdown': this._effectSlowdown(currentSlide, nextSlide); break;
                case 'fade': this._effectFade(currentSlide, nextSlide); break;
                default : this._effectSlide(currentSlide, nextSlide);
            }

            o._currentIndex = slideIndex;
        },

        _controls: function(){
            var next, prev, that = this, element = this.element, o = this.options;

            next = $('').addClass('carousel-switch-next').html(">");
            prev = $('').addClass('carousel-switch-prev').html("<");

            if (o.controlNext) {
                next.html(o.controlNext);
            }

            if (o.controlPrev) {
                prev.html(o.controlPrev);
            }

            next.appendTo(element);
            prev.appendTo(element);

            if (o._slides.length > 1) {
                prev.on('click', function(){
                    that._slideTo('prior');
                });
                next.on('click', function(){
                    that._slideTo('next');
                });
            } else {
                next.hide();
                prev.hide();
            }
        },

        _markers: function () {
            var div, a, i, that = this, o = this.options;

            div = $('
');

            for (i = 0; i < o._slides.length; i++) {
                a = $('');
                if (i === 0) {
                    a.addClass('bullet-on');
                }
                a.appendTo(div);
            }

            div.find('a').on('click', function (e) {
                var $this = $(this),
                    index = $this.data('num');

                div.find('a').removeClass('bullet-on');
                $this.addClass('bullet-on');

                if (index === o._currentIndex) {
                    return false;
                }

                that._slideToSlide(index);

                e.preventDefault();
                e.stopPropagation();
            });

            div.appendTo(this.element);

        },

        _effectSwitch: function(currentSlide, nextSlide){
            $(currentSlide)
                .hide();
            $(nextSlide)
                .css({left: 0})
                .show();
            this.element.css({
                height: $(nextSlide).outerHeight()
            });
        },

        _effectSlide: function(currentSlide, nextSlide){
            var o = this.options;
            $(currentSlide)
                .animate({left: o._outPosition}, o.duration, o.effectFunc);
            $(nextSlide)
                .css('left', o._outPosition * -1)
                .show();

            this.element.css({
                height: $(nextSlide).outerHeight()
            });

            $(nextSlide).animate({left: 0}, o.duration, o.effectFunc);
        },

        _effectSlowdown: function(currentSlide, nextSlide){
            var o = this.options;
            var options = {
                'duration': o.duration,
                'easing': 'doubleSqrt'
            };
            $.easing.doubleSqrt = function(t) {
                return Math.sqrt(Math.sqrt(t));
            };

            $(currentSlide)
                .animate({left: o._outPosition}, options);

            $(nextSlide)
                .css('left', o._outPosition * -1)
                .show();

            this.element.css({
                height: $(nextSlide).outerHeight()
            });

            $(nextSlide).animate({left: 0}, options);
        },

        _effectFade: function(currentSlide, nextSlide){
            var o = this.options;

            $(currentSlide)
                .fadeOut(o.duration);
            $(nextSlide)
                .css({left: 0})
                .fadeIn(o.duration);
            this.element.css({
                height: $(nextSlide).outerHeight()
            });
        },

        _destroy: function(){

        },

        _setOption: function(key, value){
            this._super('_setOption', key, value);
        }
    });
})( jQuery );<commit_msg>Added duration based timeout to next/prev event<commit_after>(function( $ ) {
    "use strict";

    $.widget("metro.carousel", {

        version: "3.0.0",

        options: {
            auto: true,
            period: 5000,
            duration: 1000,
            effect: 'slide', // slide, fade, switch, slowdown
            effectFunc: 'linear',
            direction: 'left',
            controls: true,
            controlNext: false,
            controlPrev: false,
            markers: true,
            stop: true,
            width: '100%',
            height: false,

            _slides: {},
            _currentIndex: 0,
            _interval: 0,
            _outPosition: 0,
            _animating: false
        },

        _create: function(){
            var that = this, o = this.options,
                element = this.element;

            $.each(element.data(), function(key, value){
                if (key in o) {
                    try {
                        o[key] = $.parseJSON(value);
                    } catch (e) {
                        o[key] = value;
                    }
                }
            });

            o._slides = element.find('.slide');

            var max_height = 0; //element.find('.slide:nth-child(1)').outerHeight();

            $.each(o._slides, function(){
                var oh, slide = $(this);

                oh = slide.outerHeight();

                if (oh > max_height) {max_height = oh;}
            });

            element.find('.slide').hide();
            element.find('.slide:nth-child(1)').show();

            element.css({
                'width': o.width,
                'height': o.height ? o.height : max_height
            });

            if (o._slides.length <= 1) {return;}

            if (o.markers) {
                this._markers();
            }

            if (o.controls) {
                this._controls();
            }

            if (o.stop) {
                element
                    .on('mouseenter', function(){
                        clearInterval(o._interval);
                    })
                    .on('mouseleave', function(){
                        if (that.options.auto) {that._autoStart();}// that.options.period;
                    });
            }

            //this._slideToSlide(0);
            if (o.auto) {
                this._autoStart();
            }

            element.data('carousel', this);

        },

        _autoStart: function(){
            var that = this, o = this.options;
            o._interval = setInterval(function(){
                if (o.direction === 'left') {
                    that._slideTo('next');
                } else {
                    that._slideTo('prior');
                }
            }, o.period);
        },

        _slideTo: function(direction){
            var carousel = this.element, that = this, o = this.options;
            var currentSlide = o._slides[o._currentIndex], nextSlide;

            if (direction === undefined) {direction = 'next';}

            if (direction === 'prior') {
                o._currentIndex -= 1;
                if (o._currentIndex < 0) {o._currentIndex = o._slides.length - 1;}

                o._outPosition = this.element.width();

            } else if (direction === 'next') {
                o._currentIndex += 1;
                if (o._currentIndex >= o._slides.length) {o._currentIndex = 0;}

                o._outPosition = -this.element.width();

            }

            nextSlide = o._slides[o._currentIndex];

            switch (this.options.effect) {
                case 'switch': this._effectSwitch(currentSlide, nextSlide); break;
                case 'slowdown': this._effectSlowdown(currentSlide, nextSlide, this.options.duration); break;
                case 'fade': this._effectFade(currentSlide, nextSlide, this.options.duration); break;
                default: this._effectSlide(currentSlide, nextSlide, this.options.duration);
            }

            carousel.find('.carousel-bullets a').each(function(){
                var index = $(this).data('num');
                if (index === o._currentIndex) {
                    $(this).addClass('bullet-on');
                } else {
                    $(this).removeClass('bullet-on');
                }
            });
        },

        _slideToSlide: function(slideIndex){
            var o = this.options,
                currentSlide = o._slides[o._currentIndex],
                nextSlide = o._slides[slideIndex];

            if (slideIndex > o._currentIndex) {
                o._outPosition = -this.element.width();
            } else {
                o._outPosition = this.element.width();
            }

            switch (this.options.effect) {
                case 'switch' : this._effectSwitch(currentSlide, nextSlide); break;
                case 'slowdown': this._effectSlowdown(currentSlide, nextSlide); break;
                case 'fade': this._effectFade(currentSlide, nextSlide); break;
                default : this._effectSlide(currentSlide, nextSlide);
            }

            o._currentIndex = slideIndex;
        },

        _controls: function(){
            var next, prev, that = this, element = this.element, o = this.options;

            next = $('').addClass('carousel-switch-next').html(">");
            prev = $('').addClass('carousel-switch-prev').html("<");

            if (o.controlNext) {
                next.html(o.controlNext);
            }

            if (o.controlPrev) {
                prev.html(o.controlPrev);
            }

            next.appendTo(element);
            prev.appendTo(element);

            if (o._slides.length > 1) {
                prev.on('click', function(){
                    if (o._animating === false) {
                        that._slideTo('prior');
                        o._animating = true;
                        setTimeout({o._animating = false;}, o.duration);
                    }
                });
                next.on('click', function(){
                    if (o._animating === false) {
                        that._slideTo('next');
                        o._animating = true;
                        setTimeout({o._animating = false;}, o.duration);
                    }
                });
            } else {
                next.hide();
                prev.hide();
            }
        },

        _markers: function () {
            var div, a, i, that = this, o = this.options;

            div = $('
');

            for (i = 0; i < o._slides.length; i++) {
                a = $('');
                if (i === 0) {
                    a.addClass('bullet-on');
                }
                a.appendTo(div);
            }

            div.find('a').on('click', function (e) {
                var $this = $(this),
                    index = $this.data('num');

                div.find('a').removeClass('bullet-on');
                $this.addClass('bullet-on');

                if (index === o._currentIndex) {
                    return false;
                }

                that._slideToSlide(index);

                e.preventDefault();
                e.stopPropagation();
            });

            div.appendTo(this.element);

        },

        _effectSwitch: function(currentSlide, nextSlide){
            $(currentSlide)
                .hide();
            $(nextSlide)
                .css({left: 0})
                .show();
            this.element.css({
                height: $(nextSlide).outerHeight()
            });
        },

        _effectSlide: function(currentSlide, nextSlide){
            var o = this.options;
            $(currentSlide)
                .animate({left: o._outPosition}, o.duration, o.effectFunc);
            $(nextSlide)
                .css('left', o._outPosition * -1)
                .show();

            this.element.css({
                height: $(nextSlide).outerHeight()
            });

            $(nextSlide).animate({left: 0}, o.duration, o.effectFunc);
        },

        _effectSlowdown: function(currentSlide, nextSlide){
            var o = this.options;
            var options = {
                'duration': o.duration,
                'easing': 'doubleSqrt'
            };
            $.easing.doubleSqrt = function(t) {
                return Math.sqrt(Math.sqrt(t));
            };

            $(currentSlide)
                .animate({left: o._outPosition}, options);

            $(nextSlide)
                .css('left', o._outPosition * -1)
                .show();

            this.element.css({
                height: $(nextSlide).outerHeight()
            });

            $(nextSlide).animate({left: 0}, options);
        },

        _effectFade: function(currentSlide, nextSlide){
            var o = this.options;

            $(currentSlide)
                .fadeOut(o.duration);
            $(nextSlide)
                .css({left: 0})
                .fadeIn(o.duration);
            this.element.css({
                height: $(nextSlide).outerHeight()
            });
        },

        _destroy: function(){

        },

        _setOption: function(key, value){
            this._super('_setOption', key, value);
        }
    });
})( jQuery );
<|endoftext|>


<commit_before>'use strict';

const {
  GraphQLString,
  GraphQLID,
  GraphQLNonNull,
  GraphQLList,
} = require('graphql');

/*
ATTR {any}: filtering
  - for *Many
	- including description
Default values (only if not required)
*/

/*
findOne
findMany
createOne
createMany
replaceOne
replaceMany
updateOne
updateMany
upsertOne
upsertMany
deleteOne
deleteMany
*/

const getArguments = function (opts) {
  return Object.assign(
    {},
    getIdArgument(opts),
		getDataArgument(opts),
    getOrderArgument(opts)
  );
};

// id argument, i.e. used for querying|manipulating a single entity
const getIdArgument = function ({ opType, multiple, def }) {
  // Only with *One methods, not *Many. Also, not if `data` argument is present, as `data.id` does the same thing
  if (multiple || dataOpTypes.includes(opType)) { return; }
	const description = def.properties && def.properties.id && def.properties.id.description;
  return {
    id: {
      type: new GraphQLNonNull(GraphQLID),
      description,
    },
  };
};

// order_by argument, i.e. used for sorting results
const getOrderArgument = function ({ opType, multiple }) {
  // Only with *Many methods, except DeleteMany (since it does not return anything)
  if (!multiple || opType === 'delete') { return; }
  return {
    order_by: {
      type: GraphQLString,
      description: `Sort results according to this attribute.
Specify ascending or descending order by appending + or - (default is ascending)`,
      defaultValue: 'id+',
    },
  };
};

// Data argument, i.e. payload used by mutation operations
const dataOpTypes = ['create', 'replace', 'update', 'upsert'];
const getDataArgument = function ({ inputObjectType, opType, multiple }) {
	// Only for mutation operations, but not delete
	if (!dataOpTypes.includes(opType)) { return; }
	// Retrieves description before wrapping in modifers
	const description = inputObjectType.description;
	// Add required and array modifiers
	inputObjectType = new GraphQLNonNull(inputObjectType);
	if (multiple) {
		inputObjectType = new GraphQLNonNull(new GraphQLList(inputObjectType));
	}
	return {
		data: {
			type: inputObjectType,
			description,
		},
	};
};

// Filters argument, i.e. only queries entities that match specified attributes
const getFilterArgument = function ({ multiple }) {
  // Only with *Many methods, not *One
	if (!multiple) { return; }
};

module.exports = {
  getArguments,
};<commit_msg>Add comment<commit_after>'use strict';

const {
  GraphQLString,
  GraphQLID,
  GraphQLNonNull,
  GraphQLList,
} = require('graphql');

/*
ATTR {any}: filtering
  - for *Many
	- including description
Default values (only if not required)
*/

/*
findOne
findMany
createOne
createMany
replaceOne
replaceMany
updateOne
updateMany
upsertOne
upsertMany
deleteOne
deleteMany
*/

// Retrieves all resolver arguments
const getArguments = function (opts) {
  return Object.assign(
    {},
    getIdArgument(opts),
		getDataArgument(opts),
    getOrderArgument(opts)
  );
};

// id argument, i.e. used for querying|manipulating a single entity
const getIdArgument = function ({ opType, multiple, def }) {
  // Only with *One methods, not *Many. Also, not if `data` argument is present, as `data.id` does the same thing
  if (multiple || dataOpTypes.includes(opType)) { return; }
	const description = def.properties && def.properties.id && def.properties.id.description;
  return {
    id: {
      type: new GraphQLNonNull(GraphQLID),
      description,
    },
  };
};

// order_by argument, i.e. used for sorting results
const getOrderArgument = function ({ opType, multiple }) {
  // Only with *Many methods, except DeleteMany (since it does not return anything)
  if (!multiple || opType === 'delete') { return; }
  return {
    order_by: {
      type: GraphQLString,
      description: `Sort results according to this attribute.
Specify ascending or descending order by appending + or - (default is ascending)`,
      defaultValue: 'id+',
    },
  };
};

// Data argument, i.e. payload used by mutation operations
const dataOpTypes = ['create', 'replace', 'update', 'upsert'];
const getDataArgument = function ({ inputObjectType, opType, multiple }) {
	// Only for mutation operations, but not delete
	if (!dataOpTypes.includes(opType)) { return; }
	// Retrieves description before wrapping in modifers
	const description = inputObjectType.description;
	// Add required and array modifiers
	inputObjectType = new GraphQLNonNull(inputObjectType);
	if (multiple) {
		inputObjectType = new GraphQLNonNull(new GraphQLList(inputObjectType));
	}
	return {
		data: {
			type: inputObjectType,
			description,
		},
	};
};

// Filters argument, i.e. only queries entities that match specified attributes
const getFilterArgument = function ({ multiple }) {
  // Only with *Many methods, not *One
	if (!multiple) { return; }
};

module.exports = {
  getArguments,
};<|endoftext|>


<commit_before>import PostCooked from 'discourse/widgets/post-cooked';
import { createWidget } from 'discourse/widgets/widget';
import { iconNode } from 'discourse/helpers/fa-icon';
import { transformBasicPost } from 'discourse/lib/transform-post';
import { h } from 'virtual-dom';
import DiscourseURL from 'discourse/lib/url';
import { dateNode } from 'discourse/helpers/node';

export function avatarImg(wanted, attrs) {
  const size = Discourse.Utilities.translateSize(wanted);
  const url = Discourse.Utilities.avatarUrl(attrs.template, size);

  // We won't render an invalid url
  if (!url || url.length === 0) { return; }
  const title = attrs.username;

  const properties = {
    attributes: { alt: '', width: size, height: size, src: Discourse.getURLWithCDN(url), title },
    className: 'avatar'
  };

  return h('img', properties);
}

export function avatarFor(wanted, attrs) {
  return h('a', {
    className: `trigger-user-card ${attrs.className || ''}`,
    attributes: { href: attrs.url, 'data-user-card': attrs.username }
  }, avatarImg(wanted, attrs));
}

createWidget('select-post', {
  tagName: 'div.select-posts',

  html(attrs) {
    const buttons = [];

    if (attrs.replyCount > 0 && !attrs.selected) {
      buttons.push(this.attach('button', { label: 'topic.multi_select.select_replies', action: 'selectReplies' }));
    }

    const selectPostKey = attrs.selected ? 'topic.multi_select.selected' : 'topic.multi_select.select';
    buttons.push(this.attach('button', { className: 'select-post',
                                         label: selectPostKey,
                                         labelOptions: { count: attrs.selectedPostsCount },
                                         action: 'selectPost' }));
    return buttons;
  }
});

createWidget('reply-to-tab', {
  tagName: 'a.reply-to-tab',

  defaultState() {
    return { loading: false };
  },

  html(attrs, state) {
    if (state.loading) { return I18n.t('loading'); }

    return [iconNode('mail-forward'),
            ' ',
            avatarFor.call(this, 'small', {
              template: attrs.replyToAvatarTemplate,
              username: attrs.replyToUsername
            }),
            ' ',
            h('span', attrs.replyToUsername)];
  },

  click() {
    this.state.loading = true;
    this.sendWidgetAction('toggleReplyAbove').then(() => this.state.loading = false);
  }
});

createWidget('post-avatar', {
  tagName: 'div.topic-avatar',

  html(attrs) {
    let body;
    if (!attrs.user_id) {
      body = h('i', { className: 'fa fa-trash-o deleted-user-avatar' });
    } else {
      body = avatarFor.call(this, 'large', {
        template: attrs.avatar_template,
        username: attrs.username,
        url: attrs.usernameUrl,
        className: 'main-avatar'
      });
    }

    return [body, h('div.poster-avatar-extra')];
  }
});

createWidget('wiki-edit-button', {
  tagName: 'div.post-info.wiki',
  title: 'post.wiki.about',

  html() {
    return iconNode('pencil-square-o');
  },

  click() {
    this.sendWidgetAction('editPost');
  }
});

createWidget('post-email-indicator', {
  tagName: 'div.post-info.via-email',
  title: 'post.via_email',

  buildClasses(attrs) {
    return attrs.canViewRawEmail ? 'raw-email' : null;
  },

  html() {
    return iconNode('envelope-o');
  },

  click() {
    if (this.attrs.canViewRawEmail) {
      this.sendWidgetAction('showRawEmail');
    }
  }
});

function showReplyTab(attrs, siteSettings) {
  return attrs.replyToUsername &&
         (!attrs.replyDirectlyAbove || !siteSettings.suppress_reply_directly_above);
}

createWidget('post-meta-data', {
  tagName: 'div.topic-meta-data',
  html(attrs) {
    const result = [this.attach('poster-name', attrs)];

    if (attrs.isWhisper) {
      result.push(h('div.post-info.whisper', {
        attributes: { title: I18n.t('post.whisper') },
      }, iconNode('eye-slash')));
    }

    const createdAt = new Date(attrs.created_at);
    if (createdAt) {
      result.push(h('div.post-info',
        h('a.post-date', {
          attributes: {
            href: attrs.shareUrl,
            'data-share-url': attrs.shareUrl,
            'data-post-number': attrs.post_number
          }
        }, dateNode(createdAt))
      ));
    }

    if (attrs.via_email) {
      result.push(this.attach('post-email-indicator', attrs));
    }

    if (attrs.version > 1) {
      result.push(this.attach('post-edits-indicator', attrs));
    }

    if (attrs.wiki) {
      result.push(this.attach('wiki-edit-button', attrs));
    }

    if (attrs.multiSelect) {
      result.push(this.attach('select-post', attrs));
    }

    if (showReplyTab(attrs, this.siteSettings)) {
      result.push(this.attach('reply-to-tab', attrs));
    }

    result.push(h('div.read-state', {
      className: attrs.read ? 'read' : null,
      attributes: {
        title: I18n.t('post.unread')
      }
    }, iconNode('circle')));

    return result;
  }
});

createWidget('expand-hidden', {
  tagName: 'a.expand-hidden',

  html() {
    return I18n.t('post.show_hidden');
  },

  click() {
    this.sendWidgetAction('expandHidden');
  }
});

createWidget('expand-post-button', {
  tagName: 'button.btn.expand-post',
  buildKey: attrs => `expand-post-button-${attrs.id}`,

  defaultState() {
    return { loadingExpanded: false };
  },

  html(attrs, state) {
    if (state.loadingExpanded) {
      return I18n.t('loading');
    } else {
      return [I18n.t('post.show_full'), "..."];
    }
  },

  click() {
    this.state.loadingExpanded = true;
    this.sendWidgetAction('expandFirstPost');
  }
});

createWidget('post-contents', {
  buildKey: attrs => `post-contents-${attrs.id}`,

  buildClasses(attrs) {
    const classes = [];
    if (!this.state.repliesShown) {
      classes.push('contents');
    }
    if (showReplyTab(attrs, this.siteSettings)) {
      classes.push('avoid-tab');
    }
    return classes;
  },

  html(attrs) {
    return new PostCooked(attrs);
  }
});

createWidget('post-body', {
  tagName: 'div.topic-body',
  buildKey: attrs => `topic-body-${attrs.id}`,

  defaultState() {
    return { expandedFirstPost: false, repliesBelow: [] };
  },

  html(attrs, state) {
    const extraState = { state: { repliesShown: !!state.repliesBelow.length } };
    const regular = [this.attach('post-contents', attrs, extraState)];

    if (attrs.cooked_hidden) {
      regular.push(this.attach('expand-hidden', attrs));
    }

    if (!state.expandedFirstPost && attrs.expandablePost) {
      regular.push(this.attach('expand-post-button', attrs));
    }

    regular.push(this.attach('post-menu', attrs, extraState));

    const repliesBelow = state.repliesBelow;
    if (repliesBelow.length) {
      regular.push(h('section.embedded-posts.bottom',
                   repliesBelow.map(p => this.attach('embedded-post', p))));
    }

    const result = [this.attach('post-meta-data', attrs), h('div.regular', regular)];
    result.push(this.attach('actions-summary', attrs));
    if (attrs.showTopicMap) {
      result.push(this.attach('topic-map', attrs));
    }

    return result;
  },

  toggleRepliesBelow() {
    if (this.state.repliesBelow.length) {
      this.state.repliesBelow = [];
      return;
    }

    return this.store.find('post-reply', { postId: this.attrs.id }).then(posts => {
      this.state.repliesBelow = posts.map(transformBasicPost);
    });
  },

  expandFirstPost() {
    const post = this.findAncestorModel();
    return post.expand().then(() => this.state.expandedFirstPost = true);
  }
});

createWidget('post-article', {
  tagName: 'article.boxed.onscreen-post',
  buildKey: attrs => `post-article-${attrs.id}`,

  defaultState() {
    return { repliesAbove: [] };
  },

  buildId(attrs) {
    return `post_${attrs.post_number}`;
  },

  buildClasses(attrs) {
    if (attrs.via_email) { return 'via-email'; }
  },

  buildAttributes(attrs) {
    return { 'data-post-id': attrs.id, 'data-user-id': attrs.user_id };
  },

  html(attrs, state) {
    const rows = [h('a.tabLoc')];
    if (state.repliesAbove.length) {
      const replies = state.repliesAbove.map(p => this.attach('embedded-post', p, { state: { above: true } }));
      rows.push(h('div.row', h('section.embedded-posts.top.topic-body.offset2', replies)));
    }

    rows.push(h('div.row', [this.attach('post-avatar', attrs),
                            this.attach('post-body', attrs),
                            this.attach('post-gutter', attrs)]));
    return rows;
  },

  toggleReplyAbove() {
    const replyPostNumber = this.attrs.reply_to_post_number;

    // jump directly on mobile
    if (Discourse.Mobile.mobileView) {
      DiscourseURL.jumpToPost(replyPostNumber);
      return Ember.RSVP.Promise.resolve();
    }

    if (this.state.repliesAbove.length) {
      this.state.repliesAbove = [];
      return Ember.RSVP.Promise.resolve();
    } else {
      return this.store.find('post-reply-history', { postId: this.attrs.id }).then(posts => {
        this.state.repliesAbove = posts.map(transformBasicPost);
      });
    }
  },

});

export default createWidget('post', {
  buildKey: attrs => `post-${attrs.id}`,
  shadowTree: true,

  buildClasses(attrs) {
    const classNames = ['topic-post', 'clearfix'];

    if (attrs.selected) { classNames.push('selected'); }
    if (attrs.topicOwner) { classNames.push('topic-owner'); }
    if (attrs.hidden) { classNames.push('post-hidden'); }
    if (attrs.deleted) { classNames.push('deleted'); }
    if (attrs.primary_group_name) { classNames.push(`group-${attrs.primary_group_name}`); }
    if (attrs.wiki) { classNames.push(`wiki`); }
    if (attrs.isWhisper) { classNames.push('whisper'); }
    if (attrs.isModeratorAction || (attrs.isWarning && attrs.firstPost)) {
      classNames.push('moderator');
    } else {
      classNames.push('regular');
    }
    return classNames;
  },

  html(attrs) {
    return this.attach('post-article', attrs);
  },

  toggleLike() {
    const post = this.model;
    const likeAction = post.get('likeAction');

    if (likeAction && likeAction.get('canToggle')) {
      return likeAction.togglePromise(post);
    }
  },

  undoPostAction(typeId) {
    const post = this.model;
    return post.get('actions_summary').findProperty('id', typeId).undo(post);
  },

  deferPostActionFlags(typeId) {
    const post = this.model;
    return post.get('actions_summary').findProperty('id', typeId).deferFlags(post);
  }
});
<commit_msg>FIX: The dom was slightly incorrect, messing up mobile rendering<commit_after>import PostCooked from 'discourse/widgets/post-cooked';
import { createWidget } from 'discourse/widgets/widget';
import { iconNode } from 'discourse/helpers/fa-icon';
import { transformBasicPost } from 'discourse/lib/transform-post';
import { h } from 'virtual-dom';
import DiscourseURL from 'discourse/lib/url';
import { dateNode } from 'discourse/helpers/node';

export function avatarImg(wanted, attrs) {
  const size = Discourse.Utilities.translateSize(wanted);
  const url = Discourse.Utilities.avatarUrl(attrs.template, size);

  // We won't render an invalid url
  if (!url || url.length === 0) { return; }
  const title = attrs.username;

  const properties = {
    attributes: { alt: '', width: size, height: size, src: Discourse.getURLWithCDN(url), title },
    className: 'avatar'
  };

  return h('img', properties);
}

export function avatarFor(wanted, attrs) {
  return h('a', {
    className: `trigger-user-card ${attrs.className || ''}`,
    attributes: { href: attrs.url, 'data-user-card': attrs.username }
  }, avatarImg(wanted, attrs));
}

createWidget('select-post', {
  tagName: 'div.select-posts',

  html(attrs) {
    const buttons = [];

    if (attrs.replyCount > 0 && !attrs.selected) {
      buttons.push(this.attach('button', { label: 'topic.multi_select.select_replies', action: 'selectReplies' }));
    }

    const selectPostKey = attrs.selected ? 'topic.multi_select.selected' : 'topic.multi_select.select';
    buttons.push(this.attach('button', { className: 'select-post',
                                         label: selectPostKey,
                                         labelOptions: { count: attrs.selectedPostsCount },
                                         action: 'selectPost' }));
    return buttons;
  }
});

createWidget('reply-to-tab', {
  tagName: 'a.reply-to-tab',

  defaultState() {
    return { loading: false };
  },

  html(attrs, state) {
    if (state.loading) { return I18n.t('loading'); }

    return [iconNode('mail-forward'),
            ' ',
            avatarFor.call(this, 'small', {
              template: attrs.replyToAvatarTemplate,
              username: attrs.replyToUsername
            }),
            ' ',
            h('span', attrs.replyToUsername)];
  },

  click() {
    this.state.loading = true;
    this.sendWidgetAction('toggleReplyAbove').then(() => this.state.loading = false);
  }
});

createWidget('post-avatar', {
  tagName: 'div.topic-avatar',

  html(attrs) {
    let body;
    if (!attrs.user_id) {
      body = h('i', { className: 'fa fa-trash-o deleted-user-avatar' });
    } else {
      body = avatarFor.call(this, 'large', {
        template: attrs.avatar_template,
        username: attrs.username,
        url: attrs.usernameUrl,
        className: 'main-avatar'
      });
    }

    return [body, h('div.poster-avatar-extra')];
  }
});

createWidget('wiki-edit-button', {
  tagName: 'div.post-info.wiki',
  title: 'post.wiki.about',

  html() {
    return iconNode('pencil-square-o');
  },

  click() {
    this.sendWidgetAction('editPost');
  }
});

createWidget('post-email-indicator', {
  tagName: 'div.post-info.via-email',
  title: 'post.via_email',

  buildClasses(attrs) {
    return attrs.canViewRawEmail ? 'raw-email' : null;
  },

  html() {
    return iconNode('envelope-o');
  },

  click() {
    if (this.attrs.canViewRawEmail) {
      this.sendWidgetAction('showRawEmail');
    }
  }
});

function showReplyTab(attrs, siteSettings) {
  return attrs.replyToUsername &&
         (!attrs.replyDirectlyAbove || !siteSettings.suppress_reply_directly_above);
}

createWidget('post-meta-data', {
  tagName: 'div.topic-meta-data',
  html(attrs) {
    const result = [this.attach('poster-name', attrs)];

    if (attrs.isWhisper) {
      result.push(h('div.post-info.whisper', {
        attributes: { title: I18n.t('post.whisper') },
      }, iconNode('eye-slash')));
    }

    const createdAt = new Date(attrs.created_at);
    if (createdAt) {
      result.push(h('div.post-info',
        h('a.post-date', {
          attributes: {
            href: attrs.shareUrl,
            'data-share-url': attrs.shareUrl,
            'data-post-number': attrs.post_number
          }
        }, dateNode(createdAt))
      ));
    }

    if (attrs.via_email) {
      result.push(this.attach('post-email-indicator', attrs));
    }

    if (attrs.version > 1) {
      result.push(this.attach('post-edits-indicator', attrs));
    }

    if (attrs.wiki) {
      result.push(this.attach('wiki-edit-button', attrs));
    }

    if (attrs.multiSelect) {
      result.push(this.attach('select-post', attrs));
    }

    if (showReplyTab(attrs, this.siteSettings)) {
      result.push(this.attach('reply-to-tab', attrs));
    }

    result.push(h('div.read-state', {
      className: attrs.read ? 'read' : null,
      attributes: {
        title: I18n.t('post.unread')
      }
    }, iconNode('circle')));

    return result;
  }
});

createWidget('expand-hidden', {
  tagName: 'a.expand-hidden',

  html() {
    return I18n.t('post.show_hidden');
  },

  click() {
    this.sendWidgetAction('expandHidden');
  }
});

createWidget('expand-post-button', {
  tagName: 'button.btn.expand-post',
  buildKey: attrs => `expand-post-button-${attrs.id}`,

  defaultState() {
    return { loadingExpanded: false };
  },

  html(attrs, state) {
    if (state.loadingExpanded) {
      return I18n.t('loading');
    } else {
      return [I18n.t('post.show_full'), "..."];
    }
  },

  click() {
    this.state.loadingExpanded = true;
    this.sendWidgetAction('expandFirstPost');
  }
});

createWidget('post-contents', {
  buildKey: attrs => `post-contents-${attrs.id}`,

  defaultState() {
    return { expandedFirstPost: false, repliesBelow: [] };
  },

  buildClasses(attrs) {
    const classes = ['regular'];
    if (!this.state.repliesShown) {
      classes.push('contents');
    }
    if (showReplyTab(attrs, this.siteSettings)) {
      classes.push('avoid-tab');
    }
    return classes;
  },

  html(attrs, state) {
    const result = [new PostCooked(attrs)];

    if (attrs.cooked_hidden) {
      result.push(this.attach('expand-hidden', attrs));
    }

    if (!state.expandedFirstPost && attrs.expandablePost) {
      result.push(this.attach('expand-post-button', attrs));
    }

    const extraState = { state: { repliesShown: !!state.repliesBelow.length } };
    result.push(this.attach('post-menu', attrs, extraState));

    const repliesBelow = state.repliesBelow;
    if (repliesBelow.length) {
      result.push(h('section.embedded-posts.bottom', repliesBelow.map(p => this.attach('embedded-post', p))));
    }

    return result;
  },

  toggleRepliesBelow() {
    if (this.state.repliesBelow.length) {
      this.state.repliesBelow = [];
      return;
    }

    return this.store.find('post-reply', { postId: this.attrs.id }).then(posts => {
      this.state.repliesBelow = posts.map(transformBasicPost);
    });
  },

  expandFirstPost() {
    const post = this.findAncestorModel();
    return post.expand().then(() => this.state.expandedFirstPost = true);
  }
});

createWidget('post-body', {
  tagName: 'div.topic-body',

  html(attrs) {
    const postContents = this.attach('post-contents', attrs);
    const result = [this.attach('post-meta-data', attrs), postContents];

    result.push(this.attach('actions-summary', attrs));
    if (attrs.showTopicMap) {
      result.push(this.attach('topic-map', attrs));
    }

    return result;
  }
});

createWidget('post-article', {
  tagName: 'article.boxed.onscreen-post',
  buildKey: attrs => `post-article-${attrs.id}`,

  defaultState() {
    return { repliesAbove: [] };
  },

  buildId(attrs) {
    return `post_${attrs.post_number}`;
  },

  buildClasses(attrs) {
    if (attrs.via_email) { return 'via-email'; }
  },

  buildAttributes(attrs) {
    return { 'data-post-id': attrs.id, 'data-user-id': attrs.user_id };
  },

  html(attrs, state) {
    const rows = [h('a.tabLoc')];
    if (state.repliesAbove.length) {
      const replies = state.repliesAbove.map(p => this.attach('embedded-post', p, { state: { above: true } }));
      rows.push(h('div.row', h('section.embedded-posts.top.topic-body.offset2', replies)));
    }

    rows.push(h('div.row', [this.attach('post-avatar', attrs),
                            this.attach('post-body', attrs),
                            this.attach('post-gutter', attrs)]));
    return rows;
  },

  toggleReplyAbove() {
    const replyPostNumber = this.attrs.reply_to_post_number;

    // jump directly on mobile
    if (Discourse.Mobile.mobileView) {
      DiscourseURL.jumpToPost(replyPostNumber);
      return Ember.RSVP.Promise.resolve();
    }

    if (this.state.repliesAbove.length) {
      this.state.repliesAbove = [];
      return Ember.RSVP.Promise.resolve();
    } else {
      return this.store.find('post-reply-history', { postId: this.attrs.id }).then(posts => {
        this.state.repliesAbove = posts.map(transformBasicPost);
      });
    }
  },

});

export default createWidget('post', {
  buildKey: attrs => `post-${attrs.id}`,
  shadowTree: true,

  buildClasses(attrs) {
    const classNames = ['topic-post', 'clearfix'];

    if (attrs.selected) { classNames.push('selected'); }
    if (attrs.topicOwner) { classNames.push('topic-owner'); }
    if (attrs.hidden) { classNames.push('post-hidden'); }
    if (attrs.deleted) { classNames.push('deleted'); }
    if (attrs.primary_group_name) { classNames.push(`group-${attrs.primary_group_name}`); }
    if (attrs.wiki) { classNames.push(`wiki`); }
    if (attrs.isWhisper) { classNames.push('whisper'); }
    if (attrs.isModeratorAction || (attrs.isWarning && attrs.firstPost)) {
      classNames.push('moderator');
    } else {
      classNames.push('regular');
    }
    return classNames;
  },

  html(attrs) {
    return this.attach('post-article', attrs);
  },

  toggleLike() {
    const post = this.model;
    const likeAction = post.get('likeAction');

    if (likeAction && likeAction.get('canToggle')) {
      return likeAction.togglePromise(post);
    }
  },

  undoPostAction(typeId) {
    const post = this.model;
    return post.get('actions_summary').findProperty('id', typeId).undo(post);
  },

  deferPostActionFlags(typeId) {
    const post = this.model;
    return post.get('actions_summary').findProperty('id', typeId).deferFlags(post);
  }
});
<|endoftext|>


<commit_before>import assert from 'assert-diff';
import { parse } from'./index';
import { it } from './simple-it';
import 'should';

let stylesFixture = `
@on('load') {
    .foo {
        color: violette;
    }
}

@on('load') {
    @import "load/my/styles1.css";
    .nut {
        color: magento;
    }
}
@on('load') {
    .a {
        color: red;
    }
    .b {
        color: blue;
    }
    @fetch load/my111/styles2.css!async;
    @fetch load/my111/styles3.css!defer;
    /*@fetch   <= when no path declared*/
    /*
    .serkan {
        @fetch load/my/styles3.css!defer;
    }
    */
}
@media print {
    .a {
        color: yellow
    }
}

@rel('preload') {
    .foo {
        color: blue;
    }
}
@rel('preload') {
	@fetch load/my/styles2.css!async;
	@fetch load/my/styles3.css!defer;
}

@on('myCustomEvent') {
    .baz {
        width: 23px;
    }
}
`;

it('should create "attachOn: immediately" objects', () => {

    /**
     * "\n" (newlines) will be created by postcss
     * and thats is correct!
     */
    let fooClass =
        '.foo {'+
            'color: gray;'+
        '} \n';
    let barClass =
        '#foo {'+
        'color: gray;'+
        '} \n' ;
    let bazClass =
        'foo {'+
        'color: gray;'+
        '} \n' ;

    let styles =
        fooClass+
        barClass+
        bazClass;

    let result = parse(styles);

    // should have correct length
    result.should.be.have.length(3);

    // should have correct properties
    assert.deepEqual(result[0], {
        attachOn: "immediately",
        imports: [],
        styles: fooClass,
        type: "default",
    });

    assert.deepEqual(result[1], {
        attachOn: "immediately",
        imports: [],
        styles: barClass,
        type: "default",
    });

    assert.deepEqual(result[2], {
        attachOn: "immediately",
        imports: [],
        styles: bazClass,
        type: "default",
    });

});

it.run();
<commit_msg>postcss-parse-atrule-events: dry<commit_after>import assert from 'assert-diff';
import { parse } from'./index';
import { it } from './simple-it';
import 'should';

let stylesFixture = `
@on('load') {
    .foo {
        color: violette;
    }
}

@on('load') {
    @import "load/my/styles1.css";
    .nut {
        color: magento;
    }
}
@on('load') {
    .a {
        color: red;
    }
    .b {
        color: blue;
    }
    @fetch load/my111/styles2.css!async;
    @fetch load/my111/styles3.css!defer;
    /*@fetch   <= when no path declared*/
    /*
    .serkan {
        @fetch load/my/styles3.css!defer;
    }
    */
}
@media print {
    .a {
        color: yellow
    }
}

@rel('preload') {
    .foo {
        color: blue;
    }
}
@rel('preload') {
	@fetch load/my/styles2.css!async;
	@fetch load/my/styles3.css!defer;
}

@on('myCustomEvent') {
    .baz {
        width: 23px;
    }
}
`;

it('should create "attachOn: immediately" objects', () => {

    /**
     * "\n" (newlines) will be created by postcss
     * and thats is correct!
     */
    let fooClass =
        '.foo {'+
            'color: gray;'+
        '} \n',
        barClass =
        '#foo {'+
            'color: gray;'+
        '} \n' ,
        bazClass =
        'foo {'+
            'color: gray;'+
        '} \n' ;

    let styles =
        fooClass+
        barClass+
        bazClass;

    let result = parse(styles);

    // should have correct length
    result.should.be.have.length(3);

    // should have correct properties
    assert.deepEqual(result[0], {
        attachOn: "immediately",
        imports: [],
        styles: fooClass,
        type: "default",
    });

    assert.deepEqual(result[1], {
        attachOn: "immediately",
        imports: [],
        styles: barClass,
        type: "default",
    });

    assert.deepEqual(result[2], {
        attachOn: "immediately",
        imports: [],
        styles: bazClass,
        type: "default",
    });

});

it.run();
<|endoftext|>


<commit_before>/* eslint-disable jsx-a11y/anchor-has-content */
/* eslint-disable jsx-a11y/control-has-associated-label */
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import { Button, Padded, Text } from '@buffetjs/core';
import { Modal } from 'strapi-helper-plugin';
import { useIntl } from 'react-intl';
import { Arrow, Download, Option, Wrapper } from './components';

const UpgradePlanModal = ({ isOpen, onToggle }) => {
  const ref = useRef();
  const { formatMessage } = useIntl();

  const handleClick = () => {
    ref.current.click();
  };

  return (
    <Modal isOpen={isOpen} onToggle={onToggle} closeButtonColor="#fff">
      <Wrapper>
        <Padded>
          <Option />
          <Padded top size="smd">
            <Padded top size="xs">
              <Text fontSize="xl" fontWeight="bold" lineHeight="24px">
                {formatMessage({ id: 'app.components.UpgradePlanModal.limit-reached' })}
              </Text>
            </Padded>
          </Padded>
          <Padded style={{ maxWidth: 405 }} top size="smd">
            <Text color="black" lineHeight="18px">
              <Text as="span" fontSize="md" fontWeight="semiBold">
                {formatMessage({ id: 'app.components.UpgradePlanModal.text-power' })}
              </Text>

              <Text as="span" fontSize="md">
                {formatMessage({ id: 'app.components.UpgradePlanModal.text-strapi' })}
              </Text>

              <Text as="span" fontSize="md" fontWeight="semiBold">
                {formatMessage({ id: 'app.components.UpgradePlanModal.text-ee' })}
              </Text>
            </Text>
          </Padded>
          <Padded top size="md">
            <Button color="primary" onClick={handleClick} style={{ paddingRight: 0 }}>
              {formatMessage({ id: 'app.components.UpgradePlanModal.button' })}
              <Download />
            </Button>
          </Padded>
        </Padded>
        <Arrow />
      </Wrapper>

    </Modal>
  );
};

UpgradePlanModal.defaultProps = {
  isOpen: false,
  onToggle: () => {},
};

UpgradePlanModal.propTypes = {
  isOpen: PropTypes.bool,
  onToggle: PropTypes.func,
};

export default UpgradePlanModal;
<commit_msg>Change pricing page url<commit_after>/* eslint-disable jsx-a11y/anchor-has-content */
/* eslint-disable jsx-a11y/control-has-associated-label */
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import { Button, Padded, Text } from '@buffetjs/core';
import { Modal } from 'strapi-helper-plugin';
import { useIntl } from 'react-intl';
import { Arrow, Download, Option, Wrapper } from './components';

const UpgradePlanModal = ({ isOpen, onToggle }) => {
  const ref = useRef();
  const { formatMessage } = useIntl();

  const handleClick = () => {
    ref.current.click();
  };

  return (
    <Modal isOpen={isOpen} onToggle={onToggle} closeButtonColor="#fff">
      <Wrapper>
        <Padded>
          <Option />
          <Padded top size="smd">
            <Padded top size="xs">
              <Text fontSize="xl" fontWeight="bold" lineHeight="24px">
                {formatMessage({ id: 'app.components.UpgradePlanModal.limit-reached' })}
              </Text>
            </Padded>
          </Padded>
          <Padded style={{ maxWidth: 405 }} top size="smd">
            <Text color="black" lineHeight="18px">
              <Text as="span" fontSize="md" fontWeight="semiBold">
                {formatMessage({ id: 'app.components.UpgradePlanModal.text-power' })}
              </Text>

              <Text as="span" fontSize="md">
                {formatMessage({ id: 'app.components.UpgradePlanModal.text-strapi' })}
              </Text>

              <Text as="span" fontSize="md" fontWeight="semiBold">
                {formatMessage({ id: 'app.components.UpgradePlanModal.text-ee' })}
              </Text>
            </Text>
          </Padded>
          <Padded top size="md">
            <Button color="primary" onClick={handleClick} style={{ paddingRight: 0 }}>
              {formatMessage({ id: 'app.components.UpgradePlanModal.button' })}
              <Download />
            </Button>
          </Padded>
        </Padded>
        <Arrow />
      </Wrapper>

    </Modal>
  );
};

UpgradePlanModal.defaultProps = {
  isOpen: false,
  onToggle: () => {},
};

UpgradePlanModal.propTypes = {
  isOpen: PropTypes.bool,
  onToggle: PropTypes.func,
};

export default UpgradePlanModal;
<|endoftext|>


<commit_before>/**
 * PGN
 *
 * Representation of the PGN format. Different meta information
 * about the actual game(s) plus the moves and result of the game.
 *
 * @constructor
 * @param {string} The PGN data
 *
 * @property {string}	props		    - PGN properties supplied
 * @property {string}	requiredProps   - The required PGN properties
 * @property {string}	requiredLength  - (Currently 7)
 * @property {array}	moves           - Array of moves
 * @property {integer}	currentMove
 * @property {integer}	skip            - White (0) or Black (1) to move
 * @property {string}	gameIntro       - Commentary before game begins
 * @property {string}	pgnOrig         - original PGN string
 * @property {string}	pgn             - PGN being processed
 * @property {string}	pgnRaw          - PGN after being normalized
 * @property {string}	pgnStripped     - PGN with commentary removed
 *
 * @version 0.7.1
 * @author Toomas Rmer
 * @author Arlen P Walker
 * @copyright 2008 Toomas Rmer
 * @copyright 2012 Arlen P Walker (some portions)
 * @license http://www.apache.org/licenses/LICENSE-2.0
 **/
function Pgn(pgn) {
    "use strict";
	var themoves,
	    sizeOfTheMoves,
	    i,
	    move,
	    ply = [null, null],
	    plyidx = 0;	//make this 1 if FEN and black to move

	// properties of the game eg players, ELOs etc
	this.props = {};
	this.requiredProps = ['Result', 'Black', 'White', 'Date',
								'Round', 'Site', 'Event'];
	this.requiredLength = this.requiredProps.length;
	this.moves = [];	// the moves, one move contains the black and white move
	this.currentMove = 0;	// the current move in the game
	this.skip = 0;	// which ply at start? 0=white's, 1=black's
	this.gameIntro = null;

	this.pgnOrig = pgn;
	pgn = this.normalize(pgn);

	this.pgn = pgn;
	this.pgnRaw = this.pgn;
	this.pgnStripped = this.stripComments(this.pgn);

	this.pgn = this.extractTags(this.pgn);
	this.extractGameIntro();
	this.extractPostGame();
	this.pgn = this.stripComments(this.pgn, true);

	themoves = this.pgn.split(" ");
	ply[1] = null;
	if (this.isBlackToMove(this.props.FEN)) {
		plyidx = 1;
		this.skip = 1;
	}

	sizeOfTheMoves = this.dropLastMove(themoves) ?
							themoves.length - 1 : themoves.length;
	for (i = 0; i < sizeOfTheMoves; i += 1) {
		if (themoves[i]) {
			themoves[i] = themoves[i].trim();
			themoves[i] = this.includeOrigination(themoves[i]);
			themoves[i] = this.removeMoveNumber(themoves[i]);
			if (themoves[i].length > 0) {
				ply[plyidx] = themoves[i];
				if (plyidx === 1) {	//black's move or last move
					move = new Move(ply[0], ply[1]);
					this.moves[this.moves.length] = move;
					plyidx = 0;
					ply = [null, null];
					ply[1] = null;
				} else {
					plyidx = 1;
				}
			}
		}
	}

	if (ply[0] || ply[1]) {
		move = new Move(ply[0], ply[1]);
		this.moves[this.moves.length] = move;
	}
}
/**
 *	Checks FEN to see if it is Black to start
 */
Pgn.prototype.isBlackToMove = function (FEN) {
    "use strict";
	return (FEN && / b | B /.test(FEN));
};
/**
 *	Tests to see if last move entry should be dropped. It should be dropped if
 *	it's not a move, but rather a result/partial game indicator.
 */
Pgn.prototype.dropLastMove = function (themoves) {
    "use strict";
	return !!themoves[themoves.length - 1].match(/1\/2-1\/2|0-1|1-0|\*|\.\.\./);
};
/**
 *	Pull any info the move contains about its origin into the move as well
 */
Pgn.prototype.includeOrigination = function (move) {
    "use strict";
    var fromTo,
        newMove,
        matches;

	if (this.moveHasOrigination(move)) {
		fromTo = move.split("-");
		if (fromTo[0].match(/[0-9]*?\.?([A-Z])/) !== null) {
			// we can just replace the - with nothing
			newMove = move.replace("-", "");
		} else {
			matches = fromTo[0].match(/[0-9]+\./);
			if (matches) {
				newMove = matches[0] + fromTo[1];
			} else {
				newMove = fromTo[1];
			}
		}
		return newMove;
	}
	return move;
};
/**
 *	If the move is prefaced by a move number, remove it. If the token contains
 *	only a move number, with no move, it will be emptied.
 */
Pgn.prototype.removeMoveNumber = function (move) {
    "use strict";
	return move.replace(/^[1-9][0-9]*\.?[ ]*/g, "");
};
/**
 *	will return the pgn string without comments or with comments replaced
 *  by underscores.
 */
Pgn.prototype.stripComments = function (pgn, replace) {
    "use strict";
    var substitute,
        interim,
        theMoves,
        theMovesBegin;

    if (replace) {
        substitute = "";
    } else {
        substitute = function (theString) {
            var a = [];
            a.length = parseInt(theString.length, 10) + 1;
            return a.join("_");
        };
    }
    interim = pgn.replace(/\{(.)*?\}/g, substitute);
    while (interim.match(/\([^()]*\)/)) {
        interim = interim.replace(/\([^()]*\)/g, substitute);
    }

    theMoves = interim.replace(/\[[^\]]*\]/g, '').trim();
    theMovesBegin = theMoves.replace(/[_ ]*/, "");
    if (!parseInt(theMovesBegin.charAt(0), 10)) {
        if (replace) {
            interim = interim.substring(0, interim.length - theMoves.length);
        } else {
            interim = interim.substring(0, interim.length - theMoves.length) +
                    substitute(theMoves);
        }
    }
    return interim;
};
/**
 *	Does the move have information on its origin as well as its destination
 */
Pgn.prototype.moveHasOrigination = function (move) {
    "use strict";
	return move.indexOf("-") !== -1 &&
			 !/[0|o]-[0|o]/i.test(move) &&
			 !/[0|o]-[0|o]-[0|o]/i.test(move);
};
/**
 *	This will "normalize" the pgn file by removing line breaks, collapsing
 *  strings of spaces, and replacing the symbols for moves with the characters
 *  (!, ?, etc.)
 */
Pgn.prototype.normalize = function (pgn) {
    "use strict";
	pgn = pgn.replace(/\n/g, " ");

	// replace dollar signs
	//"!", "?", "!!", "!?", "?!", and "??"
	pgn = pgn.replace(/\ \$1[0-9]*/g, "!");
	pgn = pgn.replace(/\ \$2[0-9]*/g, "?");
	pgn = pgn.replace(/\ \$3[0-9]*/g, "!!");
	pgn = pgn.replace(/\ \$4[0-9]*/g, "??");
	pgn = pgn.replace(/\ \$5[0-9]*/g, "!?");
	pgn = pgn.replace(/\ \$6[0-9]*/g, "?!");
	pgn = pgn.replace(/\ \$[0-9]+/g, "");

	// make double spaces to single spaces
	return pgn.replace(/\s+/g, ' ');
};
/**
 *	This function takes a pgn game string and extracts all the tags into the
 *  class variable props as key/value pairs. it returns the pgn string, minus
 *  the tags.
 */
Pgn.prototype.extractTags = function (pgn) {
    "use strict";
	var matches,
	    reprop = /\[([^\]]*)\]/gi,
	    tmpMatches,
	    key,
	    i,
	    length,
	    value;

    matches = pgn.match(reprop);
	if (matches) {
		// extract information from each matched property
		for (i = 0; i < matches.length; i += 1) {
			// lose the brackets
			tmpMatches = matches[i].substring(1, matches[i].length - 1);
			// split by the first space
			key = tmpMatches.substring(0, tmpMatches.indexOf(" "));
			value = tmpMatches.substring(tmpMatches.indexOf(" ") + 1);
			if (value.charAt(0) === '"') {
				value = value.substr(1);
			}
			if (value.charAt(value.length - 1) === '"') {
				value = value.substr(0, value.length - 1);
			}

			this.props[key] = value;
			pgn = pgn.replace(matches[i], "");
		}
	}
	length = this.requiredLength - 1;
	while (length) {
		if (!this.props[this.requiredProps[length]]) {
			this.props[this.requiredProps[length]] = "?";
		}
        length -= 1;
    }

	return pgn.replace(/\[[^\]]*\]/g, '').trim();
};

Pgn.prototype.nextMove = function () {
    "use strict";
    var rtrn = null;
    try {
        if (this.skip) {
            this.skip = 0;
            rtrn = [this.moves[this.currentMove].black, 'black'];
            this.currentMove += 1;
        } else {
            this.skip = 1;
            rtrn = [this.moves[this.currentMove].white, 'white'];
        }

        if (rtrn[0] === null || rtrn[0].length === 0) { rtrn = null; }
        return rtrn;
    } catch (e) {
        return null;
    }
};

Pgn.prototype.getComment = function (move, idx) {
    "use strict";
    var i = this.pgnStripped.indexOf(move, idx),
        j,
        c,
        k,
        c2;

    if (i === -1) {
        //throw("getComment error, could not find move '"
        //				+move+"'"+", with index '"+idx+"'");
        return [null, idx];
    }

    for (j = i + move.length; j < this.pgnStripped.length; j += 1) {
        c = this.pgnStripped.charAt(j);
        switch (c) {
        case ' ':
            break;
        case '_':	//found comment
            for (k = j; k < this.pgnStripped.length; k += 1) {
                c2 = this.pgnStripped.charAt(k);
                switch (c2) {
                case '_':	//found comment
                    break;
                default:	//no comment
                    // we might have many comments separated with spaces
                    // as we strip all double spaces to single ones we
                    // can just check for the next char being '_'
                    if (this.pgnStripped.length > k + 1 &&
                            this.pgnStripped.charAt(k + 1) === '_') {
                        continue;
                    }
                    return [this.pgnRaw.substring(j, k), k];
                }
            }
            break;
        default:	//no comment
            return [null, idx];
        }
    }
    return [null, idx];
};
/**
 *	Extract a comment starting from the beginning of the the pgn string.
 */
Pgn.prototype.extractGameIntro = function () {
    "use strict";
	this.gameIntro = null;

	this.pgn.trim();
	if (this.pgn.charAt(0) === '{') {
		this.gameIntro = this.pgn.substring(1, this.pgn.indexOf("}"));
		this.pgn = this.pgn.slice(this.pgn.indexOf("{"));
	}

	return;
};
/**
 *	Extract a comment starting from the beginning of the the pgn string.
 */
Pgn.prototype.extractPostGame = function () {
    "use strict";
	this.postGame = null;

	this.pgn.trim();
	if (this.pgn.charAt(this.pgn.length - 1) === '}') {
		this.postGame = this.pgn.substring(this.pgn.lastIndexOf("{") + 1,
				this.pgn.lastIndexOf("}"));
		this.pgn = this.pgn.slice(0, this.pgn.lastIndexOf("{"));
	}

	this.pgn = this.pgn.trim();
	return;
};
<commit_msg>Extraneous space<commit_after>/**
 * PGN
 *
 * Representation of the PGN format. Different meta information
 * about the actual game(s) plus the moves and result of the game.
 *
 * @constructor
 * @param {string} The PGN data
 *
 * @property {string}	props		    - PGN properties supplied
 * @property {string}	requiredProps   - The required PGN properties
 * @property {string}	requiredLength  - (Currently 7)
 * @property {array}	moves           - Array of moves
 * @property {integer}	currentMove
 * @property {integer}	skip            - White (0) or Black (1) to move
 * @property {string}	gameIntro       - Commentary before game begins
 * @property {string}	pgnOrig         - original PGN string
 * @property {string}	pgn             - PGN being processed
 * @property {string}	pgnRaw          - PGN after being normalized
 * @property {string}	pgnStripped     - PGN with commentary removed
 *
 * @version 0.7.1
 * @author Toomas Rmer
 * @author Arlen P Walker
 * @copyright 2008 Toomas Rmer
 * @copyright 2012 Arlen P Walker (some portions)
 * @license http://www.apache.org/licenses/LICENSE-2.0
 **/
function Pgn(pgn) {
    "use strict";
	var themoves,
	    sizeOfTheMoves,
	    i,
	    move,
	    ply = [null, null],
	    plyidx = 0;	//make this 1 if FEN and black to move

	// properties of the game eg players, ELOs etc
	this.props = {};
	this.requiredProps = ['Result', 'Black', 'White', 'Date',
								'Round', 'Site', 'Event'];
	this.requiredLength = this.requiredProps.length;
	this.moves = [];	// the moves, one move contains the black and white move
	this.currentMove = 0;	// the current move in the game
	this.skip = 0;	// which ply at start? 0=white's, 1=black's
	this.gameIntro = null;

	this.pgnOrig = pgn;
	pgn = this.normalize(pgn);

	this.pgn = pgn;
	this.pgnRaw = this.pgn;
	this.pgnStripped = this.stripComments(this.pgn);

	this.pgn = this.extractTags(this.pgn);
	this.extractGameIntro();
	this.extractPostGame();
	this.pgn = this.stripComments(this.pgn, true);

	themoves = this.pgn.split(" ");
	ply[1] = null;
	if (this.isBlackToMove(this.props.FEN)) {
		plyidx = 1;
		this.skip = 1;
	}

	sizeOfTheMoves = this.dropLastMove(themoves) ?
							themoves.length - 1 : themoves.length;
	for (i = 0; i < sizeOfTheMoves; i += 1) {
		if (themoves[i]) {
			themoves[i] = themoves[i].trim();
			themoves[i] = this.includeOrigination(themoves[i]);
			themoves[i] = this.removeMoveNumber(themoves[i]);
			if (themoves[i].length > 0) {
				ply[plyidx] = themoves[i];
				if (plyidx === 1) {	//black's move or last move
					move = new Move(ply[0], ply[1]);
					this.moves[this.moves.length] = move;
					plyidx = 0;
					ply = [null, null];
					ply[1] = null;
				} else {
					plyidx = 1;
				}
			}
		}
	}

	if (ply[0] || ply[1]) {
		move = new Move(ply[0], ply[1]);
		this.moves[this.moves.length] = move;
	}
}
/**
 *	Checks FEN to see if it is Black to start
 */
Pgn.prototype.isBlackToMove = function (FEN) {
    "use strict";
	return (FEN && / b | B /.test(FEN));
};
/**
 *	Tests to see if last move entry should be dropped. It should be dropped if
 *	it's not a move, but rather a result/partial game indicator.
 */
Pgn.prototype.dropLastMove = function (themoves) {
    "use strict";
	return !!themoves[themoves.length - 1].match(/1\/2-1\/2|0-1|1-0|\*|\.\.\./);
};
/**
 *	Pull any info the move contains about its origin into the move as well
 */
Pgn.prototype.includeOrigination = function (move) {
    "use strict";
    var fromTo,
        newMove,
        matches;

	if (this.moveHasOrigination(move)) {
		fromTo = move.split("-");
		if (fromTo[0].match(/[0-9]*?\.?([A-Z])/) !== null) {
			// we can just replace the - with nothing
			newMove = move.replace("-", "");
		} else {
			matches = fromTo[0].match(/[0-9]+\./);
			if (matches) {
				newMove = matches[0] + fromTo[1];
			} else {
				newMove = fromTo[1];
			}
		}
		return newMove;
	}
	return move;
};
/**
 *	If the move is prefaced by a move number, remove it. If the token contains
 *	only a move number, with no move, it will be emptied.
 */
Pgn.prototype.removeMoveNumber = function (move) {
    "use strict";
	return move.replace(/^[1-9][0-9]*\.?[ ]*/g, "");
};
/**
 *	will return the pgn string without comments or with comments replaced
 *  by underscores.
 */
Pgn.prototype.stripComments = function (pgn, replace) {
    "use strict";
    var substitute,
        interim,
        theMoves,
        theMovesBegin;

    if (replace) {
        substitute = "";
    } else {
        substitute = function (theString) {
            var a = [];
            a.length = parseInt(theString.length, 10) + 1;
            return a.join("_");
        };
    }
    interim = pgn.replace(/\{(.)*?\}/g, substitute);
    while (interim.match(/\([^()]*\)/)) {
        interim = interim.replace(/\([^()]*\)/g, substitute);
    }

    theMoves = interim.replace(/\[[^\]]*\]/g, '').trim();
    theMovesBegin = theMoves.replace(/[_ ]*/, "");
    if (!parseInt(theMovesBegin.charAt(0), 10)) {
        if (replace) {
            interim = interim.substring(0, interim.length - theMoves.length);
        } else {
            interim = interim.substring(0, interim.length - theMoves.length) +
                    substitute(theMoves);
        }
    }
    return interim;
};
/**
 *	Does the move have information on its origin as well as its destination
 */
Pgn.prototype.moveHasOrigination = function (move) {
    "use strict";
	return move.indexOf("-") !== -1 &&
			 !/[0|o]-[0|o]/i.test(move) &&
			 !/[0|o]-[0|o]-[0|o]/i.test(move);
};
/**
 *	This will "normalize" the pgn file by removing line breaks, collapsing
 *  strings of spaces, and replacing the symbols for moves with the characters
 *  (!, ?, etc.)
 */
Pgn.prototype.normalize = function (pgn) {
    "use strict";
	pgn = pgn.replace(/\n/g, " ");

	// replace dollar signs
	//"!", "?", "!!", "!?", "?!", and "??"
	pgn = pgn.replace(/\ \$1[0-9]*/g, "!");
	pgn = pgn.replace(/\ \$2[0-9]*/g, "?");
	pgn = pgn.replace(/\ \$3[0-9]*/g, "!!");
	pgn = pgn.replace(/\ \$4[0-9]*/g, "??");
	pgn = pgn.replace(/\ \$5[0-9]*/g, "!?");
	pgn = pgn.replace(/\ \$6[0-9]*/g, "?!");
	pgn = pgn.replace(/\ \$[0-9]+/g, "");

	// make double spaces to single spaces
	return pgn.replace(/\s+/g, ' ');
};
/**
 *	This function takes a pgn game string and extracts all the tags into the
 *  class variable props as key/value pairs. it returns the pgn string, minus
 *  the tags.
 */
Pgn.prototype.extractTags = function (pgn) {
    "use strict";
	var matches,
	    reprop = /\[([^\]]*)\]/gi,
	    tmpMatches,
	    key,
	    i,
	    length,
	    value;

    matches = pgn.match(reprop);
	if (matches) {
		// extract information from each matched property
		for (i = 0; i < matches.length; i += 1) {
			// lose the brackets
			tmpMatches = matches[i].substring(1, matches[i].length - 1);
			// split by the first space
			key = tmpMatches.substring(0, tmpMatches.indexOf(" "));
			value = tmpMatches.substring(tmpMatches.indexOf(" ") + 1);
			if (value.charAt(0) === '"') {
				value = value.substr(1);
			}
			if (value.charAt(value.length - 1) === '"') {
				value = value.substr(0, value.length - 1);
			}

			this.props[key] = value;
			pgn = pgn.replace(matches[i], "");
		}
	}
	length = this.requiredLength - 1;
	while (length) {
		if (!this.props[this.requiredProps[length]]) {
			this.props[this.requiredProps[length]] = "?";
		}
        length -= 1;
    }

	return pgn.replace(/\[[^\]]*\]/g, '').trim();
};

Pgn.prototype.nextMove = function () {
    "use strict";
    var rtrn = null;
    try {
        if (this.skip) {
            this.skip = 0;
            rtrn = [this.moves[this.currentMove].black, 'black'];
            this.currentMove += 1;
        } else {
            this.skip = 1;
            rtrn = [this.moves[this.currentMove].white, 'white'];
        }

        if (rtrn[0] === null || rtrn[0].length === 0) { rtrn = null; }
        return rtrn;
    } catch (e) {
        return null;
    }
};

Pgn.prototype.getComment = function (move, idx) {
    "use strict";
    var i = this.pgnStripped.indexOf(move, idx),
        j,
        c,
        k,
        c2;

    if (i === -1) {
        //throw("getComment error, could not find move '"
        //				+move+"'"+", with index '"+idx+"'");
        return [null, idx];
    }

    for (j = i + move.length; j < this.pgnStripped.length; j += 1) {
        c = this.pgnStripped.charAt(j);
        switch (c) {
        case ' ':
            break;
        case '_':	//found comment
            for (k = j; k < this.pgnStripped.length; k += 1) {
                c2 = this.pgnStripped.charAt(k);
                switch (c2) {
                case '_':	//found comment
                    break;
                default:	//no comment
                    // we might have many comments separated with spaces
                    // as we strip all double spaces to single ones we
                    // can just check for the next char being '_'
                    if (this.pgnStripped.length > k + 1 &&
                            this.pgnStripped.charAt(k + 1) === '_') {
                        continue;
                    }
                    return [this.pgnRaw.substring(j, k), k];
                }
            }
            break;
        default:	//no comment
            return [null, idx];
        }
    }
    return [null, idx];
};
/**
 *	Extract a comment starting from the beginning of the the pgn string.
 */
Pgn.prototype.extractGameIntro = function () {
    "use strict";
	this.gameIntro = null;

	this.pgn.trim();
	if (this.pgn.charAt(0) === '{') {
		this.gameIntro = this.pgn.substring(1, this.pgn.indexOf("}"));
		this.pgn = this.pgn.slice(this.pgn.indexOf("{"));
	}

	return;
};
/**
 *	Extract a comment starting from the beginning of the the pgn string.
 */
Pgn.prototype.extractPostGame = function () {
    "use strict";
	this.postGame = null;

	this.pgn.trim();
	if (this.pgn.charAt(this.pgn.length - 1) === '}') {
		this.postGame = this.pgn.substring(this.pgn.lastIndexOf("{") + 1,
				this.pgn.lastIndexOf("}"));
		this.pgn = this.pgn.slice(0, this.pgn.lastIndexOf("{"));
	}

	this.pgn = this.pgn.trim();
	return;
};
<|endoftext|>


<commit_before>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt

frappe.query_reports["Gross Profit"] = {
	"filters": [
		{
			"fieldname":"company",
			"label": __("Company"),
			"fieldtype": "Link",
			"options": "Company",
			"default": frappe.defaults.get_user_default("company")
		},
		{
			"fieldname":"from_date",
			"label": __("From Date"),
			"fieldtype": "Date",
			"default": frappe.defaults.get_user_default("year_start_date")
		},
		{
			"fieldname":"to_date",
			"label": __("To Date"),
			"fieldtype": "Date",
			"default": frappe.defaults.get_user_default("year_end_date")
		},
		{
			"fieldname":"group_by",
			"label": __("Group By"),
			"fieldtype": "Select",
			"options": "Invoice\nItem Code\nItem Group\nBrand\nWarehouse\nCustomer\nCustomer Group\nTerritory\nSales Person\nProject",
			"default": "Invoice"
		},
	]
}
<commit_msg>Gross Profit Report: Company filter should be reqd<commit_after>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt

frappe.query_reports["Gross Profit"] = {
	"filters": [
		{
			"fieldname":"company",
			"label": __("Company"),
			"fieldtype": "Link",
			"options": "Company",
			"reqd": 1,
			"default": frappe.defaults.get_user_default("company")
		},
		{
			"fieldname":"from_date",
			"label": __("From Date"),
			"fieldtype": "Date",
			"default": frappe.defaults.get_user_default("year_start_date")
		},
		{
			"fieldname":"to_date",
			"label": __("To Date"),
			"fieldtype": "Date",
			"default": frappe.defaults.get_user_default("year_end_date")
		},
		{
			"fieldname":"group_by",
			"label": __("Group By"),
			"fieldtype": "Select",
			"options": "Invoice\nItem Code\nItem Group\nBrand\nWarehouse\nCustomer\nCustomer Group\nTerritory\nSales Person\nProject",
			"default": "Invoice"
		},
	]
}
<|endoftext|>


<commit_before>var game_state = {"place": "the tavern",
                  "person": null,
                  "character": {"items": ["cat"]},
                 };

var message = "You are in a tavern. The local assassins hate you.";

function handle_take_action(resp) {
    if (resp.reload) {
        location.reload();
    }
    if (resp.moved) {
        resp.message += " You find yourself in " + game_state.place + ".";
    }
    game_state = resp.game_state;
    console.log(resp);
    document.getElementById("message").innerHTML = resp.message;
    document.getElementById("a").innerHTML = "a. " + resp.options["a"];
    var letters = "abcd";
    var letter;
    for (index in letters) {
        letter = letters[index];
        if (resp.options[letter]) {
            document.getElementById(letter).innerHTML =
                letter + ". " + resp.options[letter];
        } else {
            document.getElementById(letter).innerHTML = "";
        }
    }
}

function call_post(letter) {
    $.post("take_action.json",
           {"action": document.getElementById(letter).innerHTML,
            "game_state": game_state},
           handle_take_action);
}

function main() {
    document.onkeypress = function(event) {
        var ascii = event.which;
        if (ascii == 49 || ascii == 65 || ascii == 97) {
            call_post("a");
        } else if (ascii == 50 || ascii == 66 || ascii == 98) {
            call_post("b");
        } else if (ascii == 51 || ascii == 67 || ascii == 99) {
            call_post("c");
        } else if (ascii == 52 || ascii == 68 || ascii == 100) {
            call_post("d");
        } else if (ascii == 53 || ascii == 69 || ascii == 101) {
            call_post("e");
        }
    }
}

$(document).ready(main);
<commit_msg>added Easter egg<commit_after>var game_state = {"place": "the tavern",
                  "person": null,
                  "character": {"items": ["cat"]},
                 };

var message = "You are in a tavern. The local assassins hate you.";

function handle_action(resp) {
    if (resp.reload) {
        location.reload();
    }
    if (resp.moved) {
        resp.message += " You find yourself in " + game_state.place + ".";
    }
    game_state = resp.game_state;
    console.log(resp);
    document.getElementById("message").innerHTML = resp.message;
    document.getElementById("a").innerHTML = "a. " + resp.options["a"];
    var letters = "abcd";
    var letter;
    for (index in letters) {
        letter = letters[index];
        if (resp.options[letter]) {
            document.getElementById(letter).innerHTML =
                letter + ". " + resp.options[letter];
        } else {
            document.getElementById(letter).innerHTML = "";
        }
    }
}

function strip_action(string) {
    return string.trim().slice(3, string.trim().length);
}

function call_post(letter) {
    if (strip_action(document.getElementById(letter).innerHTML) ===
            "Don't play again.") {
        window.open("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
    } else {
        $.post("action.json",
               {"action": document.getElementById(letter).innerHTML,
                "game_state": game_state},
               handle_action);
    }
}

function main() {
    document.onkeypress = function(event) {
        var ascii = event.which;
        if (ascii == 49 || ascii == 65 || ascii == 97) {
            call_post("a");
        } else if (ascii == 50 || ascii == 66 || ascii == 98) {
            call_post("b");
        } else if (ascii == 51 || ascii == 67 || ascii == 99) {
            call_post("c");
        } else if (ascii == 52 || ascii == 68 || ascii == 100) {
            call_post("d");
        } else if (ascii == 53 || ascii == 69 || ascii == 101) {
            call_post("e");
        }
    }
}

$(document).ready(main);
<|endoftext|>