<commit_before>import $ from '../../utils/dom';
import Utils from '../../utils/utils';

const Pagination = {
  update() {
    // Render || Update Pagination bullets/items
    const swiper = this;
    const rtl = swiper.rtl;
    const params = swiper.params.pagination;
    if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
    const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
    const $el = swiper.pagination.$el;
    // Current/Total
    let current;
    const total = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
    if (swiper.params.loop) {
      current = Math.ceil((swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup);
      if (current > slidesLength - 1 - (swiper.loopedSlides * 2)) {
        current -= (slidesLength - (swiper.loopedSlides * 2));
      }
      if (current > total - 1) current -= total;
      if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;
    } else if (typeof swiper.snapIndex !== 'undefined') {
      current = swiper.snapIndex;
    } else {
      current = swiper.activeIndex || 0;
    }
    // Types
    if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {
      const bullets = swiper.pagination.bullets;
      let firstIndex;
      let lastIndex;
      let midIndex;
      if (params.dynamicBullets) {
        swiper.pagination.bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
        $el.css(swiper.isHorizontal() ? 'width' : 'height', `${swiper.pagination.bulletSize * (params.dynamicMainBullets + 4)}px`);
        if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
          swiper.pagination.dynamicBulletIndex += (current - swiper.previousIndex);
          if (swiper.pagination.dynamicBulletIndex > (params.dynamicMainBullets - 1)) {
            swiper.pagination.dynamicBulletIndex = params.dynamicMainBullets - 1;
          } else if (swiper.pagination.dynamicBulletIndex < 0) {
            swiper.pagination.dynamicBulletIndex = 0;
          }
        }
        firstIndex = current - swiper.pagination.dynamicBulletIndex;
        lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
        midIndex = (lastIndex + firstIndex) / 2;
      }
      bullets.removeClass(`${params.bulletActiveClass} ${params.bulletActiveClass}-next ${params.bulletActiveClass}-next-next ${params.bulletActiveClass}-prev ${params.bulletActiveClass}-prev-prev ${params.bulletActiveClass}-main`);
      if ($el.length > 1) {
        bullets.each((index, bullet) => {
          const $bullet = $(bullet);
          const bulletIndex = $bullet.index();
          if (bulletIndex === current) {
            $bullet.addClass(params.bulletActiveClass);
          }
          if (params.dynamicBullets) {
            if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
              $bullet.addClass(`${params.bulletActiveClass}-main`);
            }
            if (bulletIndex === firstIndex) {
              $bullet
                .prev()
                .addClass(`${params.bulletActiveClass}-prev`)
                .prev()
                .addClass(`${params.bulletActiveClass}-prev-prev`);
            }
            if (bulletIndex === lastIndex) {
              $bullet
                .next()
                .addClass(`${params.bulletActiveClass}-next`)
                .next()
                .addClass(`${params.bulletActiveClass}-next-next`);
            }
          }
        });
      } else {
        const $bullet = bullets.eq(current);
        const bulletIndex = $bullet.index();
        $bullet.addClass(params.bulletActiveClass);
        if (params.dynamicBullets) {
          const $firstDisplayedBullet = bullets.eq(firstIndex);
          const $lastDisplayedBullet = bullets.eq(lastIndex);
          for (let i = firstIndex; i <= lastIndex; i += 1) {
            bullets.eq(i).addClass(`${params.bulletActiveClass}-main`);
          }
          if (swiper.params.loop) {
            if (bulletIndex >= bullets.length - params.dynamicMainBullets) {
              for (let i = params.dynamicMainBullets; i >= 0; i -= 1) {
                bullets.eq(bullets.length - i).addClass(`${params.bulletActiveClass}-main`);
              }
              bullets.eq(bullets.length - params.dynamicMainBullets - 1).addClass(`${params.bulletActiveClass}-prev`);
            } else {
              $firstDisplayedBullet
                .prev()
                .addClass(`${params.bulletActiveClass}-prev`)
                .prev()
                .addClass(`${params.bulletActiveClass}-prev-prev`);
              $lastDisplayedBullet
                .next()
                .addClass(`${params.bulletActiveClass}-next`)
                .next()
                .addClass(`${params.bulletActiveClass}-next-next`);
            }
          } else {
            $firstDisplayedBullet
              .prev()
              .addClass(`${params.bulletActiveClass}-prev`)
              .prev()
              .addClass(`${params.bulletActiveClass}-prev-prev`);
            $lastDisplayedBullet
              .next()
              .addClass(`${params.bulletActiveClass}-next`)
              .next()
              .addClass(`${params.bulletActiveClass}-next-next`);
          }
        }
      }
      if (params.dynamicBullets) {
        const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
        const bulletsOffset = (((swiper.pagination.bulletSize * dynamicBulletsLength) - (swiper.pagination.bulletSize)) / 2) - (midIndex * swiper.pagination.bulletSize);
        const offsetProp = rtl ? 'right' : 'left';
        bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);
      }
    }
    if (params.type === 'fraction') {
      $el.find(`.${params.currentClass}`).text(params.formatFractionCurrent(current + 1));
      $el.find(`.${params.totalClass}`).text(params.formatFractionTotal(total));
    }
    if (params.type === 'progressbar') {
      let progressbarDirection;
      if (params.progressbarOpposite) {
        progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
      } else {
        progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
      }
      const scale = (current + 1) / total;
      let scaleX = 1;
      let scaleY = 1;
      if (progressbarDirection === 'horizontal') {
        scaleX = scale;
      } else {
        scaleY = scale;
      }
      $el.find(`.${params.progressbarFillClass}`).transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`).transition(swiper.params.speed);
    }
    if (params.type === 'custom' && params.renderCustom) {
      $el.html(params.renderCustom(swiper, current + 1, total));
      swiper.emit('paginationRender', swiper, $el[0]);
    } else {
      swiper.emit('paginationUpdate', swiper, $el[0]);
    }
    $el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
  },
  render() {
    // Render Container
    const swiper = this;
    const params = swiper.params.pagination;
    if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
    const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;

    const $el = swiper.pagination.$el;
    let paginationHTML = '';
    if (params.type === 'bullets') {
      const numberOfBullets = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
      for (let i = 0; i < numberOfBullets; i += 1) {
        if (params.renderBullet) {
          paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
        } else {
          paginationHTML += `<${params.bulletElement} class="${params.bulletClass}"></${params.bulletElement}>`;
        }
      }
      $el.html(paginationHTML);
      swiper.pagination.bullets = $el.find(`.${params.bulletClass}`);
    }
    if (params.type === 'fraction') {
      if (params.renderFraction) {
        paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
      } else {
        paginationHTML = `<span class="${params.currentClass}"></span>`
        + ' / '
        + `<span class="${params.totalClass}"></span>`;
      }
      $el.html(paginationHTML);
    }
    if (params.type === 'progressbar') {
      if (params.renderProgressbar) {
        paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
      } else {
        paginationHTML = `<span class="${params.progressbarFillClass}"></span>`;
      }
      $el.html(paginationHTML);
    }
    if (params.type !== 'custom') {
      swiper.emit('paginationRender', swiper.pagination.$el[0]);
    }
  },
  init() {
    const swiper = this;
    const params = swiper.params.pagination;
    if (!params.el) return;

    let $el = $(params.el);
    if ($el.length === 0) return;

    if (
      swiper.params.uniqueNavElements
      && typeof params.el === 'string'
      && $el.length > 1
      && swiper.$el.find(params.el).length === 1
    ) {
      $el = swiper.$el.find(params.el);
    }

    if (params.type === 'bullets' && params.clickable) {
      $el.addClass(params.clickableClass);
    }

    $el.addClass(params.modifierClass + params.type);

    if (params.type === 'bullets' && params.dynamicBullets) {
      $el.addClass(`${params.modifierClass}${params.type}-dynamic`);
      swiper.pagination.dynamicBulletIndex = 0;
      if (params.dynamicMainBullets < 1) {
        params.dynamicMainBullets = 1;
      }
    }
    if (params.type === 'progressbar' && params.progressbarOpposite) {
      $el.addClass(params.progressbarOppositeClass);
    }

    if (params.clickable) {
      $el.on('click', `.${params.bulletClass}`, function onClick(e) {
        e.preventDefault();
        let index = $(this).index() * swiper.params.slidesPerGroup;
        if (swiper.params.loop) index += swiper.loopedSlides;
        swiper.slideTo(index);
      });
    }

    Utils.extend(swiper.pagination, {
      $el,
      el: $el[0],
    });
  },
  destroy() {
    const swiper = this;
    const params = swiper.params.pagination;
    if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
    const $el = swiper.pagination.$el;

    $el.removeClass(params.hiddenClass);
    $el.removeClass(params.modifierClass + params.type);
    if (swiper.pagination.bullets) swiper.pagination.bullets.removeClass(params.bulletActiveClass);
    if (params.clickable) {
      $el.off('click', `.${params.bulletClass}`);
    }
  },
};

export default {
  name: 'pagination',
  params: {
    pagination: {
      el: null,
      bulletElement: 'span',
      clickable: false,
      hideOnClick: false,
      renderBullet: null,
      renderProgressbar: null,
      renderFraction: null,
      renderCustom: null,
      progressbarOpposite: false,
      type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom'
      dynamicBullets: false,
      dynamicMainBullets: 1,
      formatFractionCurrent: (number) => number,
      formatFractionTotal: (number) => number,
      bulletClass: 'swiper-pagination-bullet',
      bulletActiveClass: 'swiper-pagination-bullet-active',
      modifierClass: 'swiper-pagination-', // NEW
      currentClass: 'swiper-pagination-current',
      totalClass: 'swiper-pagination-total',
      hiddenClass: 'swiper-pagination-hidden',
      progressbarFillClass: 'swiper-pagination-progressbar-fill',
      progressbarOppositeClass: 'swiper-pagination-progressbar-opposite',
      clickableClass: 'swiper-pagination-clickable', // NEW
      lockClass: 'swiper-pagination-lock',
    },
  },
  create() {
    const swiper = this;
    Utils.extend(swiper, {
      pagination: {
        init: Pagination.init.bind(swiper),
        render: Pagination.render.bind(swiper),
        update: Pagination.update.bind(swiper),
        destroy: Pagination.destroy.bind(swiper),
        dynamicBulletIndex: 0,
      },
    });
  },
  on: {
    init() {
      const swiper = this;
      swiper.pagination.init();
      swiper.pagination.render();
      swiper.pagination.update();
    },
    activeIndexChange() {
      const swiper = this;
      if (swiper.params.loop) {
        swiper.pagination.update();
      } else if (typeof swiper.snapIndex === 'undefined') {
        swiper.pagination.update();
      }
    },
    snapIndexChange() {
      const swiper = this;
      if (!swiper.params.loop) {
        swiper.pagination.update();
      }
    },
    slidesLengthChange() {
      const swiper = this;
      if (swiper.params.loop) {
        swiper.pagination.render();
        swiper.pagination.update();
      }
    },
    snapGridLengthChange() {
      const swiper = this;
      if (!swiper.params.loop) {
        swiper.pagination.render();
        swiper.pagination.update();
      }
    },
    destroy() {
      const swiper = this;
      swiper.pagination.destroy();
    },
    click(e) {
      const swiper = this;
      if (
        swiper.params.pagination.el
        && swiper.params.pagination.hideOnClick
        && swiper.pagination.$el.length > 0
        && !$(e.target).hasClass(swiper.params.pagination.bulletClass)
      ) {
        const isHidden = swiper.pagination.$el.hasClass(swiper.params.pagination.hiddenClass);
        if (isHidden === true) {
          swiper.emit('paginationShow', swiper);
        } else {
          swiper.emit('paginationHide', swiper);
        }
        swiper.pagination.$el.toggleClass(swiper.params.pagination.hiddenClass);
      }
    },
  },
};
<commit_msg>Fix in pagination detect uniqueNaVElements<commit_after>import $ from '../../utils/dom';
import Utils from '../../utils/utils';

const Pagination = {
  update() {
    // Render || Update Pagination bullets/items
    const swiper = this;
    const rtl = swiper.rtl;
    const params = swiper.params.pagination;
    if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
    const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
    const $el = swiper.pagination.$el;
    // Current/Total
    let current;
    const total = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
    if (swiper.params.loop) {
      current = Math.ceil((swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup);
      if (current > slidesLength - 1 - (swiper.loopedSlides * 2)) {
        current -= (slidesLength - (swiper.loopedSlides * 2));
      }
      if (current > total - 1) current -= total;
      if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;
    } else if (typeof swiper.snapIndex !== 'undefined') {
      current = swiper.snapIndex;
    } else {
      current = swiper.activeIndex || 0;
    }
    // Types
    if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {
      const bullets = swiper.pagination.bullets;
      let firstIndex;
      let lastIndex;
      let midIndex;
      if (params.dynamicBullets) {
        swiper.pagination.bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
        $el.css(swiper.isHorizontal() ? 'width' : 'height', `${swiper.pagination.bulletSize * (params.dynamicMainBullets + 4)}px`);
        if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
          swiper.pagination.dynamicBulletIndex += (current - swiper.previousIndex);
          if (swiper.pagination.dynamicBulletIndex > (params.dynamicMainBullets - 1)) {
            swiper.pagination.dynamicBulletIndex = params.dynamicMainBullets - 1;
          } else if (swiper.pagination.dynamicBulletIndex < 0) {
            swiper.pagination.dynamicBulletIndex = 0;
          }
        }
        firstIndex = current - swiper.pagination.dynamicBulletIndex;
        lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
        midIndex = (lastIndex + firstIndex) / 2;
      }
      bullets.removeClass(`${params.bulletActiveClass} ${params.bulletActiveClass}-next ${params.bulletActiveClass}-next-next ${params.bulletActiveClass}-prev ${params.bulletActiveClass}-prev-prev ${params.bulletActiveClass}-main`);
      if ($el.length > 1) {
        bullets.each((index, bullet) => {
          const $bullet = $(bullet);
          const bulletIndex = $bullet.index();
          if (bulletIndex === current) {
            $bullet.addClass(params.bulletActiveClass);
          }
          if (params.dynamicBullets) {
            if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
              $bullet.addClass(`${params.bulletActiveClass}-main`);
            }
            if (bulletIndex === firstIndex) {
              $bullet
                .prev()
                .addClass(`${params.bulletActiveClass}-prev`)
                .prev()
                .addClass(`${params.bulletActiveClass}-prev-prev`);
            }
            if (bulletIndex === lastIndex) {
              $bullet
                .next()
                .addClass(`${params.bulletActiveClass}-next`)
                .next()
                .addClass(`${params.bulletActiveClass}-next-next`);
            }
          }
        });
      } else {
        const $bullet = bullets.eq(current);
        const bulletIndex = $bullet.index();
        $bullet.addClass(params.bulletActiveClass);
        if (params.dynamicBullets) {
          const $firstDisplayedBullet = bullets.eq(firstIndex);
          const $lastDisplayedBullet = bullets.eq(lastIndex);
          for (let i = firstIndex; i <= lastIndex; i += 1) {
            bullets.eq(i).addClass(`${params.bulletActiveClass}-main`);
          }
          if (swiper.params.loop) {
            if (bulletIndex >= bullets.length - params.dynamicMainBullets) {
              for (let i = params.dynamicMainBullets; i >= 0; i -= 1) {
                bullets.eq(bullets.length - i).addClass(`${params.bulletActiveClass}-main`);
              }
              bullets.eq(bullets.length - params.dynamicMainBullets - 1).addClass(`${params.bulletActiveClass}-prev`);
            } else {
              $firstDisplayedBullet
                .prev()
                .addClass(`${params.bulletActiveClass}-prev`)
                .prev()
                .addClass(`${params.bulletActiveClass}-prev-prev`);
              $lastDisplayedBullet
                .next()
                .addClass(`${params.bulletActiveClass}-next`)
                .next()
                .addClass(`${params.bulletActiveClass}-next-next`);
            }
          } else {
            $firstDisplayedBullet
              .prev()
              .addClass(`${params.bulletActiveClass}-prev`)
              .prev()
              .addClass(`${params.bulletActiveClass}-prev-prev`);
            $lastDisplayedBullet
              .next()
              .addClass(`${params.bulletActiveClass}-next`)
              .next()
              .addClass(`${params.bulletActiveClass}-next-next`);
          }
        }
      }
      if (params.dynamicBullets) {
        const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
        const bulletsOffset = (((swiper.pagination.bulletSize * dynamicBulletsLength) - (swiper.pagination.bulletSize)) / 2) - (midIndex * swiper.pagination.bulletSize);
        const offsetProp = rtl ? 'right' : 'left';
        bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);
      }
    }
    if (params.type === 'fraction') {
      $el.find(`.${params.currentClass}`).text(params.formatFractionCurrent(current + 1));
      $el.find(`.${params.totalClass}`).text(params.formatFractionTotal(total));
    }
    if (params.type === 'progressbar') {
      let progressbarDirection;
      if (params.progressbarOpposite) {
        progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
      } else {
        progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
      }
      const scale = (current + 1) / total;
      let scaleX = 1;
      let scaleY = 1;
      if (progressbarDirection === 'horizontal') {
        scaleX = scale;
      } else {
        scaleY = scale;
      }
      $el.find(`.${params.progressbarFillClass}`).transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`).transition(swiper.params.speed);
    }
    if (params.type === 'custom' && params.renderCustom) {
      $el.html(params.renderCustom(swiper, current + 1, total));
      swiper.emit('paginationRender', swiper, $el[0]);
    } else {
      swiper.emit('paginationUpdate', swiper, $el[0]);
    }
    $el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
  },
  render() {
    // Render Container
    const swiper = this;
    const params = swiper.params.pagination;
    if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
    const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;

    const $el = swiper.pagination.$el;
    let paginationHTML = '';
    if (params.type === 'bullets') {
      const numberOfBullets = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
      for (let i = 0; i < numberOfBullets; i += 1) {
        if (params.renderBullet) {
          paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
        } else {
          paginationHTML += `<${params.bulletElement} class="${params.bulletClass}"></${params.bulletElement}>`;
        }
      }
      $el.html(paginationHTML);
      swiper.pagination.bullets = $el.find(`.${params.bulletClass}`);
    }
    if (params.type === 'fraction') {
      if (params.renderFraction) {
        paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
      } else {
        paginationHTML = `<span class="${params.currentClass}"></span>`
        + ' / '
        + `<span class="${params.totalClass}"></span>`;
      }
      $el.html(paginationHTML);
    }
    if (params.type === 'progressbar') {
      if (params.renderProgressbar) {
        paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
      } else {
        paginationHTML = `<span class="${params.progressbarFillClass}"></span>`;
      }
      $el.html(paginationHTML);
    }
    if (params.type !== 'custom') {
      swiper.emit('paginationRender', swiper.pagination.$el[0]);
    }
  },
  init() {
    const swiper = this;
    const params = swiper.params.pagination;
    if (!params.el) return;

    let $el = $(params.el);
    if ($el.length === 0) return;

    if (
      swiper.params.uniqueNavElements
      && typeof params.el === 'string'
      && $el.length > 1
    ) {
      $el = swiper.$el.find(params.el);
    }

    if (params.type === 'bullets' && params.clickable) {
      $el.addClass(params.clickableClass);
    }

    $el.addClass(params.modifierClass + params.type);

    if (params.type === 'bullets' && params.dynamicBullets) {
      $el.addClass(`${params.modifierClass}${params.type}-dynamic`);
      swiper.pagination.dynamicBulletIndex = 0;
      if (params.dynamicMainBullets < 1) {
        params.dynamicMainBullets = 1;
      }
    }
    if (params.type === 'progressbar' && params.progressbarOpposite) {
      $el.addClass(params.progressbarOppositeClass);
    }

    if (params.clickable) {
      $el.on('click', `.${params.bulletClass}`, function onClick(e) {
        e.preventDefault();
        let index = $(this).index() * swiper.params.slidesPerGroup;
        if (swiper.params.loop) index += swiper.loopedSlides;
        swiper.slideTo(index);
      });
    }

    Utils.extend(swiper.pagination, {
      $el,
      el: $el[0],
    });
  },
  destroy() {
    const swiper = this;
    const params = swiper.params.pagination;
    if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) return;
    const $el = swiper.pagination.$el;

    $el.removeClass(params.hiddenClass);
    $el.removeClass(params.modifierClass + params.type);
    if (swiper.pagination.bullets) swiper.pagination.bullets.removeClass(params.bulletActiveClass);
    if (params.clickable) {
      $el.off('click', `.${params.bulletClass}`);
    }
  },
};

export default {
  name: 'pagination',
  params: {
    pagination: {
      el: null,
      bulletElement: 'span',
      clickable: false,
      hideOnClick: false,
      renderBullet: null,
      renderProgressbar: null,
      renderFraction: null,
      renderCustom: null,
      progressbarOpposite: false,
      type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom'
      dynamicBullets: false,
      dynamicMainBullets: 1,
      formatFractionCurrent: (number) => number,
      formatFractionTotal: (number) => number,
      bulletClass: 'swiper-pagination-bullet',
      bulletActiveClass: 'swiper-pagination-bullet-active',
      modifierClass: 'swiper-pagination-', // NEW
      currentClass: 'swiper-pagination-current',
      totalClass: 'swiper-pagination-total',
      hiddenClass: 'swiper-pagination-hidden',
      progressbarFillClass: 'swiper-pagination-progressbar-fill',
      progressbarOppositeClass: 'swiper-pagination-progressbar-opposite',
      clickableClass: 'swiper-pagination-clickable', // NEW
      lockClass: 'swiper-pagination-lock',
    },
  },
  create() {
    const swiper = this;
    Utils.extend(swiper, {
      pagination: {
        init: Pagination.init.bind(swiper),
        render: Pagination.render.bind(swiper),
        update: Pagination.update.bind(swiper),
        destroy: Pagination.destroy.bind(swiper),
        dynamicBulletIndex: 0,
      },
    });
  },
  on: {
    init() {
      const swiper = this;
      swiper.pagination.init();
      swiper.pagination.render();
      swiper.pagination.update();
    },
    activeIndexChange() {
      const swiper = this;
      if (swiper.params.loop) {
        swiper.pagination.update();
      } else if (typeof swiper.snapIndex === 'undefined') {
        swiper.pagination.update();
      }
    },
    snapIndexChange() {
      const swiper = this;
      if (!swiper.params.loop) {
        swiper.pagination.update();
      }
    },
    slidesLengthChange() {
      const swiper = this;
      if (swiper.params.loop) {
        swiper.pagination.render();
        swiper.pagination.update();
      }
    },
    snapGridLengthChange() {
      const swiper = this;
      if (!swiper.params.loop) {
        swiper.pagination.render();
        swiper.pagination.update();
      }
    },
    destroy() {
      const swiper = this;
      swiper.pagination.destroy();
    },
    click(e) {
      const swiper = this;
      if (
        swiper.params.pagination.el
        && swiper.params.pagination.hideOnClick
        && swiper.pagination.$el.length > 0
        && !$(e.target).hasClass(swiper.params.pagination.bulletClass)
      ) {
        const isHidden = swiper.pagination.$el.hasClass(swiper.params.pagination.hiddenClass);
        if (isHidden === true) {
          swiper.emit('paginationShow', swiper);
        } else {
          swiper.emit('paginationHide', swiper);
        }
        swiper.pagination.$el.toggleClass(swiper.params.pagination.hiddenClass);
      }
    },
  },
};
<|endoftext|>


<commit_before>/*
 * slipNslide Mobile Slider
 *
 * Brad Birdsall, Prime
 * Copyright 2011, Licensed GPL & MIT
 *
*/

window.slipNslide = function(element, options) {

  if (!element) return null;

  // retreive options
  this.options = options || {};
  this.index = this.options.startSlide || 0;
  this.speed = this.options.speed || 300;
  this.callback = this.options.callback || function() {};

  // reference dom elements
  this.container = element;
  this.element = this.container.getElementsByTagName('ul')[0]; // the slide pane
  this.slides = this.element.getElementsByTagName('li');
  this.length = this.slides.length;

  // static css
  this.container.style.overflow = 'hidden';
  this.element.style.listStyle = 'none';

  this.setup();

  this.element.addEventListener('touchstart', this, false);
  this.element.addEventListener('touchmove', this, false);
  this.element.addEventListener('touchend', this, false);
  this.element.addEventListener('webkitTransitionEnd', this, false);
  window.addEventListener('resize', this, false);

}

slipNslide.prototype = {

  setup: function() {

    this.container.style.visibility = 'hidden';

    this.width = this.container.getBoundingClientRect().width;

    this.slideWidth = this.slidesPer > 1 ? this.width/this.slidesPer : this.width;

    // dynamic css
    this.element.style.width = (this.slides.length * this.slideWidth) + 'px';
    var index = this.slides.length;
    while (index--) {
      var el = this.slides[index];
      el.style.width = this.slideWidth + 'px';
      el.style.display = 'inline-block';
    }

    this.slide(this.index, 0); // set start position and force translate to remove initial flickering

    this.container.style.visibility = 'visible';

  },

  slide: function(index,duration) {

    this.element.style.webkitTransitionDuration = duration + 'ms';
    this.element.style.webkitTransform = 'translate3d(' + -(index * this.width) + 'px,0,0)';

    this.index = index; // set new index to allow for expression arguments

  },

  prev: function() {

    if (this.index) this.slide(this.index-1, this.speed);

  },

  next: function() {

    if (this.index < this.length - 1) this.slide(this.index+1, this.speed);

  },

  handleEvent: function(e) {
    switch (e.type) {
      case 'touchstart': this.onTouchStart(e); break;
      case 'touchmove': this.onTouchMove(e); break;
      case 'touchend': this.onTouchEnd(e); break;
      case 'webkitTransitionEnd': this.callback(e, this.index, this.slides[this.index]); break;
      case 'resize': this.setup(); break;
    }
  },

  onTouchStart: function(e) {

    // get touch coordinates for delta calculations in onTouchMove
    this.startX = e.touches[0].pageX;
    this.startY = e.touches[0].pageY;

    this.time = Number(new Date()); // set start time of touch sequence
    this.isScrolling = undefined; // used for testing first onTouchMove event
    this.deltaX = 0; // reset deltaX
    this.element.style.webkitTransitionDuration = 0; // set transition time to 0 for 1-to-1 touch movement

  },

  onTouchMove: function(e) {

    this.deltaX = e.touches[0].pageX - this.startX;

    // determine if scrolling test has run - one time test
    if ( typeof this.isScrolling == 'undefined') {
      this.isScrolling = !!( this.isScrolling || Math.abs(this.deltaX) < Math.abs(e.touches[0].pageY - this.startY) );
    }

    // if user is not trying to scroll vertically
    if (!this.isScrolling) {
      e.preventDefault();
      this.deltaX = this.deltaX / ( (!this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0) ? ( Math.abs(this.deltaX) / this.width + 1 ) : 1 );
      this.element.style.webkitTransform = 'translate3d(' + (this.deltaX - this.index * this.width) + 'px,0,0)';
    }

  },

  onTouchEnd: function(e) {

    var isValidSlide = Number(new Date()) - this.time < 250 && Math.abs(this.deltaX) > 20 || Math.abs(this.deltaX) > this.width/2,
        isPastBounds = !this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0;

    if (!this.isScrolling) this.slide(this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ), this.speed);

  }

}<commit_msg>removed final traces of slidesPer and slidesWidth within setup function, depreciated is this commit: http://pr-i.me/A3gP<commit_after>/*
 * slipNslide Mobile Slider
 *
 * Brad Birdsall, Prime
 * Copyright 2011, Licensed GPL & MIT
 *
*/

window.slipNslide = function(element, options) {

  if (!element) return null;

  // retreive options
  this.options = options || {};
  this.index = this.options.startSlide || 0;
  this.speed = this.options.speed || 300;
  this.callback = this.options.callback || function() {};

  // reference dom elements
  this.container = element;
  this.element = this.container.getElementsByTagName('ul')[0]; // the slide pane
  this.slides = this.element.getElementsByTagName('li');
  this.length = this.slides.length;

  // static css
  this.container.style.overflow = 'hidden';
  this.element.style.listStyle = 'none';

  this.setup();

  this.element.addEventListener('touchstart', this, false);
  this.element.addEventListener('touchmove', this, false);
  this.element.addEventListener('touchend', this, false);
  this.element.addEventListener('webkitTransitionEnd', this, false);
  window.addEventListener('resize', this, false);

}

slipNslide.prototype = {

  setup: function() {

    this.container.style.visibility = 'hidden';

    this.width = this.container.getBoundingClientRect().width;

    // dynamic css
    this.element.style.width = (this.slides.length * this.width) + 'px';
    var index = this.slides.length;
    while (index--) {
      var el = this.slides[index];
      el.style.width = this.width + 'px';
      el.style.display = 'inline-block';
    }

    this.slide(this.index, 0); // set start position and force translate to remove initial flickering

    this.container.style.visibility = 'visible';

  },

  slide: function(index,duration) {

    this.element.style.webkitTransitionDuration = duration + 'ms';
    this.element.style.webkitTransform = 'translate3d(' + -(index * this.width) + 'px,0,0)';

    this.index = index; // set new index to allow for expression arguments

  },

  prev: function() {

    if (this.index) this.slide(this.index-1, this.speed);

  },

  next: function() {

    if (this.index < this.length - 1) this.slide(this.index+1, this.speed);

  },

  handleEvent: function(e) {
    switch (e.type) {
      case 'touchstart': this.onTouchStart(e); break;
      case 'touchmove': this.onTouchMove(e); break;
      case 'touchend': this.onTouchEnd(e); break;
      case 'webkitTransitionEnd': this.callback(e, this.index, this.slides[this.index]); break;
      case 'resize': this.setup(); break;
    }
  },

  onTouchStart: function(e) {

    // get touch coordinates for delta calculations in onTouchMove
    this.startX = e.touches[0].pageX;
    this.startY = e.touches[0].pageY;

    this.time = Number(new Date()); // set start time of touch sequence
    this.isScrolling = undefined; // used for testing first onTouchMove event
    this.deltaX = 0; // reset deltaX
    this.element.style.webkitTransitionDuration = 0; // set transition time to 0 for 1-to-1 touch movement

  },

  onTouchMove: function(e) {

    this.deltaX = e.touches[0].pageX - this.startX;

    // determine if scrolling test has run - one time test
    if ( typeof this.isScrolling == 'undefined') {
      this.isScrolling = !!( this.isScrolling || Math.abs(this.deltaX) < Math.abs(e.touches[0].pageY - this.startY) );
    }

    // if user is not trying to scroll vertically
    if (!this.isScrolling) {
      e.preventDefault();
      this.deltaX = this.deltaX / ( (!this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0) ? ( Math.abs(this.deltaX) / this.width + 1 ) : 1 );
      this.element.style.webkitTransform = 'translate3d(' + (this.deltaX - this.index * this.width) + 'px,0,0)';
    }

  },

  onTouchEnd: function(e) {

    var isValidSlide = Number(new Date()) - this.time < 250 && Math.abs(this.deltaX) > 20 || Math.abs(this.deltaX) > this.width/2,
        isPastBounds = !this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0;

    if (!this.isScrolling) this.slide(this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ), this.speed);

  }

}<|endoftext|>


<commit_before>// Design Basic Game Solo Challenge

// This is a solo challenge

// Your mission description:  Build a slot machine
// Overall mission: Allow the user to "pull the handle" of a slot machine and see if they won anything.
// Goals: The player wishes to get three of a kind.
// Characters: The player and the slot machine
// Objects:
// 1. The player:
//   a. Starts out with a default sum of money on refresh. ($100)
// 2. The slot machine:
//   a. Three reels
//   b. Buttons:
//      i. Bet button to enter bet multiplier (1 - 3) per coin ($1)
//      ii. Pull button to start game
//   c. LEDs:
//      i. Balance: player's current balance
//      ii. Last win: amount last paid out
//      iii. Previous turn won: amount paid in previous turn (Usually $0.00)
//   d. Payout rules
//   	i. any one cherry = 2 credits
//	    ii. any two cherry = 5
//      iii. any bars = 5
//      iv. 3 cherries = 10
//      v. 3 single bars = 10
//      vi. 3 double bars = 25
//      vii. 3 triple bars = 40
//      viii. 3 7s = 80
//      ix. 3 $s = 800
//      x. multiplier: multiply by multiplier up to 3x
// 3. A reel
//  a. Array of Symbols
// 4. Symbol
//  a. name
//  b. vector_image
//  c. x // x-coordinate
//  d. y // y-coordinate
//
// Functions:
// slot.changeMultiplier - toggles the multiplier (1 - 3) based on # coins inserted. Updates LED display
// player.updateBalance() - debits player's account if negative, credits if positive
// slot.spin() - calls spinReel 3x
// slot.playerSpin() - debits player x bet amount, calls slot.spin(), slot.outputResults(), slot.creditWins()
// slot.spinReel() - spins one reel, returns result
// slot.outputResults() - outputs results
// slot.creditWins() - calculates if any wins and updates player balances via player.updateBalance(),  slot.updateSlotDisplays()
// slot.updateSlotDisplays() - calls setRecentWinPayout(), setPreviousTurnPayout()
// slot.setRecentWinPayout() - amount last win paid out
// slot.setPreviousTurnPayout() - amount paid out in previous turn

// Pseudocode
// Slot machine is set up with random reel values displayed (no payout) with call to slot.spin
// Last win LED is set to 0.
// Previous turn won LED is set to 0.
// Current multiplier value is 1
// Slot machine has
//
// Player has:
// balance (starts with $100)
//
// On Page Load:
// On refresh, player starts with default balance.
//
// Start of Game:
// Player presses "Bet" button which calls "setMultiplier" and toggles multiplier from 1 - 3 and debits appropriate amount.
// If the player presses "Bet" button too many times, multiplier resets back to 1 and credits player accordingly.
// Player presses "Spin" button which calls "slot.playerSpin()"
// spinReels() calls spinReel() 3x and calls outputReels() with results which updates display.
// spinReels() next calls payoutWins() with results.
// payoutWins() runs (see description under "functions").
// Slot machine is done and returns to "Start of Game" for player to place next bet and spin again.
//

// // Initial Code

// function Player(balance) {
// 	var balance = balance;

// 	this.updateBalance = function(amount) {
// 		balance += amount;
// 	};

// 	this.getBalance = function() {
// 		return balance;
// 	};
// }

// function SlotMachine(amountPerCredit) {

// 	// private variables

// 	var creditCost = amountPerCredit;
// 	var multiplier = 1;
// 	var multiplierMax = 3;
// 	var numReels = 3;
// 	var payout = 10;
// 	var previousTurnPayout = 0;
// 	var recentWinPayout = 0;
// 	var reelsResult = [];

// 	// privileged functions

// 	this.getCreditCost = function(){
// 		return creditCost;
// 	};

// 	this.initialSetup = function(player){
// 		if (reelsResult.length == 0) {
// 			spin();
// 		}
// 		updateSlotDisplays(player);
// 	};

// 	this.playerBet = function(player) {
// 		changeMultiplier();
// 		updateSlotDisplays(player);
// 	};

// 	this.playerSpin = function(player) {
// 		if (creditCost * multiplier <= player.getBalance())
// 		{
// 			player.updateBalance(-1 * creditCost * multiplier);
// 			updateSlotDisplays(player);
// 			spin();
// 			creditWins(player);
// 			updateSlotDisplays(player);
// 		} else {
// 			console.log("Not enough funds.");
// 		}
// 	};

// 	// private functions

// 	function creditWins(player){

// 		// See if all three reels are equal...
// 		for (var i = 1; i < numReels; i++){
// 			if (reelsResult[i - 1] != reelsResult[i]){
// 				previousTurnPayout = "0.00";
// 				return; // ... else no money gained
// 			}
// 		}
// 		// Winner!!!
// 		var winnings = payout * multiplier;
// 		player.updateBalance(winnings);
// 		previousTurnPayout = winnings;
// 		recentWinPayout = winnings;
// 	};

// 	// Always loops between 1 - 3
// 	function changeMultiplier(){
// 		multiplier = (multiplier % multiplierMax) + 1;
// 	};

// 	function outputResults(){
// 		return "[ " + reelsResult.join(" | ") + " ]";
// 	};

// 	function spin(){
// 		for (var i = 0; i < numReels; i++){
// 			reelsResult[i] = Reel.spin();
// 		}
// 	};

// 	/*
// 		Outputs slot machine LEDs.
// 		Skips player balance if no player is defined.
// 	*/
// 	function updateSlotDisplays(player){
// 		console.log("\n\n\n\n\n");
// 		console.log("RULES: 3-in-a-row wins $" + payout + " multiplied by bet!");
// 		console.log("$" + creditCost + " per credit");
// 		console.log("Max Bet: 3 credits");
// 		console.log("Recent Win Payout: $" + recentWinPayout);
// 		console.log("Previous Turn Payout $" + previousTurnPayout);
// 		console.log("Current Bet: " + multiplier + " credit");
// 		if (player) {
// 			console.log("Balance: $" + player.getBalance());
// 		}
// 		console.log(outputResults());
// 	};

// }

// function Reel(){
// }

// // Static method
// Reel.spin = function(){
// 		var symbols = ["$","7","bar","cherry","lime"];
// 		return symbols[Math.floor(Math.random() * symbols.length)];
// }

// function runGame(){
// 	var me = new Player(100);
// 	var quarterDollarSlot = new SlotMachine(0.25);
// 	quarterDollarSlot.initialSetup(me);

// 	while (me.getBalance() >= quarterDollarSlot.getCreditCost()){
// 		betOrSpin = confirm("[OK]: Spin | [CANCEL]: Change Bet");
// 		if (betOrSpin == false){
// 			quarterDollarSlot.playerBet(me);
// 		} else {
// 			quarterDollarSlot.playerSpin(me);
// 		}
// 	}
// 	console.log("You're broke! Time to go home.");
// }

// //HTML
//
//
// 		<meta charset="utf-8">
//
//

//
Click the button to start the game.

// <button onclick="runGame()">Run Game</button>

//

//
//

// Refactored Code

function Player(balance) {
	var balance = balance;

	this.updateBalance = function(amount) {
		balance += amount;
	};

	this.getBalance = function() {
		return balance;
	};
}

function SlotMachine(amountPerCredit) {

	// private variables

	var creditCost = amountPerCredit;
	var multiplier = 1;
	var multiplierMax = 3;
	var numReels = 3;
	var payout = 10;
	var previousTurnPayout = 0;
	var recentWinPayout = 0;
	var reelsResult = [];

	// privileged functions

	this.getCreditCost = function(){
		return creditCost;
	};

	this.initialSetup = function(player){
		if (reelsResult.length == 0) {
			spin();
		}
		updateSlotDisplays(player);
	};

	this.playerBet = function(player) {
		changeMultiplier();
		updateSlotDisplays(player);
	};

	this.playerSpin = function(player) {
		if (creditCost * multiplier <= player.getBalance())
		{
			player.updateBalance(-1 * creditCost * multiplier);
			updateSlotDisplays(player);
			spin();
			creditWins(player);
			updateSlotDisplays(player);
		} else {
			alert("Not enough funds.");
		}
	};

	// private functions

	function creditWins(player){

		// See if all three reels are equal...
		for (var i = 1; i < numReels; i++){
			if (reelsResult[i - 1] != reelsResult[i]){
				previousTurnPayout = 0;
				return; // ... else no money gained
			}
		}
		// Winner!!!
		var winnings = payout * multiplier;
		player.updateBalance(winnings);
		previousTurnPayout = winnings;
		recentWinPayout = winnings;
	};

	// Always loops between 1 - 3
	function changeMultiplier(){
		multiplier = (multiplier % multiplierMax) + 1;
	};

	function outputResults(){
		for (var i = 0; i < numReels; i++){
			var elementID = "reel" + (i + 1); // build id name
			document.getElementById(elementID).innerHTML = "";
		}
	};

	function spin(){
		for (var i = 0; i < numReels; i++){
			reelsResult[i] = Reel.spin();
		}
	};

	/*
		Outputs slot machine LEDs.
		Skips player balance if no player is defined.
	*/
	function updateSlotDisplays(player){
		document.getElementById("header").innerHTML =
					"
3-of-a-Kind Slot-o-Rama
" +
					"
$" + payout + " times bet
" +
					"
Max Bet = $" + multiplierMax + "
";
		document.getElementById("credit_cost").innerHTML = "$" + creditCost + "
per credit";
		document.getElementById("recent_win_payout").innerHTML = "Recent Win Payout:
$" + recentWinPayout;
		document.getElementById("previous_turn_payout").innerHTML = "Previous Turn Payout:
$" + previousTurnPayout;
		document.getElementById("current_bet").innerHTML = "Current Bet:
" + multiplier + " credit";
		if (player) {
			document.getElementById("balance").innerHTML = "Balance:
$" + player.getBalance().toFixed(2);
		}
		outputResults();
	};

}

function Reel(){
}

// Static method
Reel.spin = function(){
		var symbols = ["dollar.png","7.png","bar.png","bar_bar.png","bar_bar_bar.png","cherries.png","grapes.png"];
		return symbols[Math.floor(Math.random() * symbols.length)];
}

function runGame(){
	var me = new Player(10);
	var quarterDollarSlot = new SlotMachine(0.25);
	quarterDollarSlot.initialSetup(me);

	document.getElementById("bet").addEventListener("click", function(){ quarterDollarSlot.playerBet(me); });
	document.getElementById("spin").addEventListener("click", function(){ quarterDollarSlot.playerSpin(me) });
}

// Reflection
//
// What was the most difficult part of this challenge?

// (1) Trying to figure out when to use the different types of object and function declaration types.
// I was finally able to figure it out after reading the following article:
// http://www.crockford.com/javascript/private.html
// It indicated how there are three types of functions:
// private, privileged and public and how they each can or cannot access local variables.
// Once I read this, it all came together.

// What did you learn about creating objects and functions that interact with one another?

// An object needs to talk to the other object via it's public and/or privileged functions.

// Did you learn about any new built-in methods you could use in your refactored solution? If so, what were they and how do they work?

// I was able to make use of JS DOM methods addEventListener and getElementById.

// How can you access and manipulate properties of objects?

// Via public/privileged methods and using dot or brackets (for public variables).

<commit_msg>Correct header to indicate max bet is 3 credits, not dollars.<commit_after>// Design Basic Game Solo Challenge

// This is a solo challenge

// Your mission description:  Build a slot machine
// Overall mission: Allow the user to "pull the handle" of a slot machine and see if they won anything.
// Goals: The player wishes to get three of a kind.
// Characters: The player and the slot machine
// Objects:
// 1. The player:
//   a. Starts out with a default sum of money on refresh. ($100)
// 2. The slot machine:
//   a. Three reels
//   b. Buttons:
//      i. Bet button to enter bet multiplier (1 - 3) per coin ($1)
//      ii. Pull button to start game
//   c. LEDs:
//      i. Balance: player's current balance
//      ii. Last win: amount last paid out
//      iii. Previous turn won: amount paid in previous turn (Usually $0.00)
//   d. Payout rules
//   	i. any one cherry = 2 credits
//	    ii. any two cherry = 5
//      iii. any bars = 5
//      iv. 3 cherries = 10
//      v. 3 single bars = 10
//      vi. 3 double bars = 25
//      vii. 3 triple bars = 40
//      viii. 3 7s = 80
//      ix. 3 $s = 800
//      x. multiplier: multiply by multiplier up to 3x
// 3. A reel
//  a. Array of Symbols
// 4. Symbol
//  a. name
//  b. vector_image
//  c. x // x-coordinate
//  d. y // y-coordinate
//
// Functions:
// slot.changeMultiplier - toggles the multiplier (1 - 3) based on # coins inserted. Updates LED display
// player.updateBalance() - debits player's account if negative, credits if positive
// slot.spin() - calls spinReel 3x
// slot.playerSpin() - debits player x bet amount, calls slot.spin(), slot.outputResults(), slot.creditWins()
// slot.spinReel() - spins one reel, returns result
// slot.outputResults() - outputs results
// slot.creditWins() - calculates if any wins and updates player balances via player.updateBalance(),  slot.updateSlotDisplays()
// slot.updateSlotDisplays() - calls setRecentWinPayout(), setPreviousTurnPayout()
// slot.setRecentWinPayout() - amount last win paid out
// slot.setPreviousTurnPayout() - amount paid out in previous turn

// Pseudocode
// Slot machine is set up with random reel values displayed (no payout) with call to slot.spin
// Last win LED is set to 0.
// Previous turn won LED is set to 0.
// Current multiplier value is 1
// Slot machine has
//
// Player has:
// balance (starts with $100)
//
// On Page Load:
// On refresh, player starts with default balance.
//
// Start of Game:
// Player presses "Bet" button which calls "setMultiplier" and toggles multiplier from 1 - 3 and debits appropriate amount.
// If the player presses "Bet" button too many times, multiplier resets back to 1 and credits player accordingly.
// Player presses "Spin" button which calls "slot.playerSpin()"
// spinReels() calls spinReel() 3x and calls outputReels() with results which updates display.
// spinReels() next calls payoutWins() with results.
// payoutWins() runs (see description under "functions").
// Slot machine is done and returns to "Start of Game" for player to place next bet and spin again.
//

// // Initial Code

// function Player(balance) {
// 	var balance = balance;

// 	this.updateBalance = function(amount) {
// 		balance += amount;
// 	};

// 	this.getBalance = function() {
// 		return balance;
// 	};
// }

// function SlotMachine(amountPerCredit) {

// 	// private variables

// 	var creditCost = amountPerCredit;
// 	var multiplier = 1;
// 	var multiplierMax = 3;
// 	var numReels = 3;
// 	var payout = 10;
// 	var previousTurnPayout = 0;
// 	var recentWinPayout = 0;
// 	var reelsResult = [];

// 	// privileged functions

// 	this.getCreditCost = function(){
// 		return creditCost;
// 	};

// 	this.initialSetup = function(player){
// 		if (reelsResult.length == 0) {
// 			spin();
// 		}
// 		updateSlotDisplays(player);
// 	};

// 	this.playerBet = function(player) {
// 		changeMultiplier();
// 		updateSlotDisplays(player);
// 	};

// 	this.playerSpin = function(player) {
// 		if (creditCost * multiplier <= player.getBalance())
// 		{
// 			player.updateBalance(-1 * creditCost * multiplier);
// 			updateSlotDisplays(player);
// 			spin();
// 			creditWins(player);
// 			updateSlotDisplays(player);
// 		} else {
// 			console.log("Not enough funds.");
// 		}
// 	};

// 	// private functions

// 	function creditWins(player){

// 		// See if all three reels are equal...
// 		for (var i = 1; i < numReels; i++){
// 			if (reelsResult[i - 1] != reelsResult[i]){
// 				previousTurnPayout = "0.00";
// 				return; // ... else no money gained
// 			}
// 		}
// 		// Winner!!!
// 		var winnings = payout * multiplier;
// 		player.updateBalance(winnings);
// 		previousTurnPayout = winnings;
// 		recentWinPayout = winnings;
// 	};

// 	// Always loops between 1 - 3
// 	function changeMultiplier(){
// 		multiplier = (multiplier % multiplierMax) + 1;
// 	};

// 	function outputResults(){
// 		return "[ " + reelsResult.join(" | ") + " ]";
// 	};

// 	function spin(){
// 		for (var i = 0; i < numReels; i++){
// 			reelsResult[i] = Reel.spin();
// 		}
// 	};

// 	/*
// 		Outputs slot machine LEDs.
// 		Skips player balance if no player is defined.
// 	*/
// 	function updateSlotDisplays(player){
// 		console.log("\n\n\n\n\n");
// 		console.log("RULES: 3-in-a-row wins $" + payout + " multiplied by bet!");
// 		console.log("$" + creditCost + " per credit");
// 		console.log("Max Bet: 3 credits");
// 		console.log("Recent Win Payout: $" + recentWinPayout);
// 		console.log("Previous Turn Payout $" + previousTurnPayout);
// 		console.log("Current Bet: " + multiplier + " credit");
// 		if (player) {
// 			console.log("Balance: $" + player.getBalance());
// 		}
// 		console.log(outputResults());
// 	};

// }

// function Reel(){
// }

// // Static method
// Reel.spin = function(){
// 		var symbols = ["$","7","bar","cherry","lime"];
// 		return symbols[Math.floor(Math.random() * symbols.length)];
// }

// function runGame(){
// 	var me = new Player(100);
// 	var quarterDollarSlot = new SlotMachine(0.25);
// 	quarterDollarSlot.initialSetup(me);

// 	while (me.getBalance() >= quarterDollarSlot.getCreditCost()){
// 		betOrSpin = confirm("[OK]: Spin | [CANCEL]: Change Bet");
// 		if (betOrSpin == false){
// 			quarterDollarSlot.playerBet(me);
// 		} else {
// 			quarterDollarSlot.playerSpin(me);
// 		}
// 	}
// 	console.log("You're broke! Time to go home.");
// }

// //HTML
//
//
// 		<meta charset="utf-8">
//
//

//
Click the button to start the game.

// <button onclick="runGame()">Run Game</button>

//

//
//

// Refactored Code

function Player(balance) {
	var balance = balance;

	this.updateBalance = function(amount) {
		balance += amount;
	};

	this.getBalance = function() {
		return balance;
	};
}

function SlotMachine(amountPerCredit) {

	// private variables

	var creditCost = amountPerCredit;
	var multiplier = 1;
	var multiplierMax = 3;
	var numReels = 3;
	var payout = 10;
	var previousTurnPayout = 0;
	var recentWinPayout = 0;
	var reelsResult = [];

	// privileged functions

	this.getCreditCost = function(){
		return creditCost;
	};

	this.initialSetup = function(player){
		if (reelsResult.length == 0) {
			spin();
		}
		updateSlotDisplays(player);
	};

	this.playerBet = function(player) {
		changeMultiplier();
		updateSlotDisplays(player);
	};

	this.playerSpin = function(player) {
		if (creditCost * multiplier <= player.getBalance())
		{
			player.updateBalance(-1 * creditCost * multiplier);
			updateSlotDisplays(player);
			spin();
			creditWins(player);
			updateSlotDisplays(player);
		} else {
			alert("Not enough funds.");
		}
	};

	// private functions

	function creditWins(player){

		// See if all three reels are equal...
		for (var i = 1; i < numReels; i++){
			if (reelsResult[i - 1] != reelsResult[i]){
				previousTurnPayout = 0;
				return; // ... else no money gained
			}
		}
		// Winner!!!
		var winnings = payout * multiplier;
		player.updateBalance(winnings);
		previousTurnPayout = winnings;
		recentWinPayout = winnings;
	};

	// Always loops between 1 - 3
	function changeMultiplier(){
		multiplier = (multiplier % multiplierMax) + 1;
	};

	function outputResults(){
		for (var i = 0; i < numReels; i++){
			var elementID = "reel" + (i + 1); // build id name
			document.getElementById(elementID).innerHTML = "";
		}
	};

	function spin(){
		for (var i = 0; i < numReels; i++){
			reelsResult[i] = Reel.spin();
		}
	};

	/*
		Outputs slot machine LEDs.
		Skips player balance if no player is defined.
	*/
	function updateSlotDisplays(player){
		document.getElementById("header").innerHTML =
					"
3-of-a-Kind Slot-o-Rama
" +
					"
$" + payout + " times bet
" +
					"
Max bet = " + multiplierMax + " credits
";
		document.getElementById("credit_cost").innerHTML = "$" + creditCost + "
per credit";
		document.getElementById("recent_win_payout").innerHTML = "Recent Win Payout:
$" + recentWinPayout;
		document.getElementById("previous_turn_payout").innerHTML = "Previous Turn Payout:
$" + previousTurnPayout;
		document.getElementById("current_bet").innerHTML = "Current Bet:
" + multiplier + " credit";
		if (player) {
			document.getElementById("balance").innerHTML = "Balance:
$" + player.getBalance().toFixed(2);
		}
		outputResults();
	};

}

function Reel(){
}

// Static method
Reel.spin = function(){
		var symbols = ["dollar.png","7.png","bar.png","bar_bar.png","bar_bar_bar.png","cherries.png","grapes.png"];
		return symbols[Math.floor(Math.random() * symbols.length)];
}

function runGame(){
	var me = new Player(10);
	var quarterDollarSlot = new SlotMachine(0.25);
	quarterDollarSlot.initialSetup(me);

	document.getElementById("bet").addEventListener("click", function(){ quarterDollarSlot.playerBet(me); });
	document.getElementById("spin").addEventListener("click", function(){ quarterDollarSlot.playerSpin(me) });
}

// Reflection
//
// What was the most difficult part of this challenge?

// (1) Trying to figure out when to use the different types of object and function declaration types.
// I was finally able to figure it out after reading the following article:
// http://www.crockford.com/javascript/private.html
// It indicated how there are three types of functions:
// private, privileged and public and how they each can or cannot access local variables.
// Once I read this, it all came together.

// What did you learn about creating objects and functions that interact with one another?

// An object needs to talk to the other object via it's public and/or privileged functions.

// Did you learn about any new built-in methods you could use in your refactored solution? If so, what were they and how do they work?

// I was able to make use of JS DOM methods addEventListener and getElementById.

// How can you access and manipulate properties of objects?

// Via public/privileged methods and using dot or brackets (for public variables).

<|endoftext|>


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

'use strict';

module.exports = {
    kafka: {
        broker: 'kafka',
        // https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md
        librdkafka: {
            'enable.auto.commit': false,
            'auto.offset.reset': 'latest',
            // Needed to lower latency
            'fetch.wait.max.ms': 10,
            //'fetch.min.bytes': 1,
            'request.required.acks': 0,
            'socket.blocking.max.ms': 100,
            'queue.buffering.max.ms': 10,
        },
        timeouts: {
            default: 5000,
            writeRequest: 45000,
        },
        topics: {
            tokenRequest: 'token_request',
            graphRequest: 'graph_request',
            writeRequest: 'write_request',
            httpResponse: 'http_response',
        }
    },
};
<commit_msg>Further reduce the latency of librdkafka<commit_after>/* Copyright 2017 Open Ag Data Alliance
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

module.exports = {
    kafka: {
        broker: 'kafka',
        // https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md
        librdkafka: {
            'enable.auto.commit': false,
            'auto.offset.reset': 'latest',
            // Needed to lower latency
            'fetch.wait.max.ms': 10,
            'fetch.error.backoff.ms': 10,
            //'fetch.min.bytes': 1,
            'request.required.acks': 0,
            'socket.blocking.max.ms': 10,
            'queue.buffering.max.ms': 5,
        },
        timeouts: {
            default: 5000,
            writeRequest: 45000,
        },
        topics: {
            tokenRequest: 'token_request',
            graphRequest: 'graph_request',
            writeRequest: 'write_request',
            httpResponse: 'http_response',
        }
    },
};
<|endoftext|>


<commit_before>(function() {
    var globe = planetaryjs.planet(),
        rotating = document.getElementById('rotating'),
        rotatingMode = false,
        geoPanel = document.getElementById('geoPanel'),
        selectedCountry = document.getElementById('selectedCountry'),
        geocoder = new google.maps.Geocoder,
        globeRadius = 240;
    // Load our custom `autorotate` plugin; see below.
    globe.loadPlugin(autorotate(5));
    // The `earth` plugin draws the oceans and the land; it's actually
    // a combination of several separate built-in plugins.
    //
    // Note that we're loading a special TopoJSON file
    // (world-110m-withlakes.json) so we can render lakes.
    globe.loadPlugin(planetaryjs.plugins.earth({
        topojson: { file:   '/world-110m-withlakes.json' },
        oceans:   { fill:   '#000080' },
        land:     { fill:   '#339966' },
        borders:  { stroke: '#008000' }
    }));
    // Load our custom `lakes` plugin to draw lakes; see below.
    globe.loadPlugin(lakes({
        fill: '#000080'
    }));
    // The `pings` plugin draws animated pings on the globe.
    globe.loadPlugin(planetaryjs.plugins.pings());
    // The `zoom` and `drag` plugins enable
    // manipulating the globe with the mouse.
    globe.loadPlugin(planetaryjs.plugins.zoom({
        scaleExtent: [globeRadius, 20 * globeRadius]
    }));
    /**
    * Turn rotating mode on/off on the globe
    */
    rotating.onclick = function () {
        rotatingMode = !rotatingMode;
        globe.plugins.autorotate[rotatingMode ? 'resume' : 'pause']();
    };
    globe.loadPlugin(planetaryjs.plugins.drag({
        // Dragging the globe should pause the
        // automatic rotation until we release the mouse.
        onDragStart: function() {
            if (rotatingMode.checked) {
                this.plugins.autorotate.pause();
            }
        },
        onDragEnd: function() {
            if (rotatingMode.checked) {
                this.plugins.autorotate.resume();
            }
        }
    }));
    // Set up the globe's initial scale, offset, and rotation.
    globe.projection.scale(globeRadius).translate([globeRadius, globeRadius]).rotate([0, -10, 0]);

    // Every few hundred milliseconds, we'll draw another random ping.
    var colors = ['red', 'yellow', 'white', 'orange', 'green', 'cyan', 'pink'];

    setInterval(function() {
        var lat = Math.random() * 170 - 85;
        var lng = Math.random() * 360 - 180;
        var color = colors[Math.floor(Math.random() * colors.length)];
        globe.plugins.pings.add(lng, lat, { color: color, ttl: 2000, angle: Math.random() * 10 });
    }, 500);

    var canvas = document.getElementById('rotatingGlobe');
    /**
    * setup the cursor as pointer while mouse pressing
    */
    canvas.onmousedown = function () {
        this.style.cursor = "pointer";
    }
    /**
    * restore the cursor while mouse releasing
    */
    canvas.onmouseup = function () {
        this.style.cursor = "";
    }
    /**
    * setup the handler for click to show geo coordinates (longitude, altitude)
    */
    canvas.addEventListener('click', function(event) {
        var x = event.x,
            y = event.y,
            coordinates;
        x -= this.offsetLeft;
        y -= this.offsetTop;
        coordinates = globe.projection.invert([x, y]);
        geoPanel.textContent = "[" + coordinates.join(",") + "]";

        geocoder.geocode({'location': { lat: coordinates[1], lng: coordinates[0] }}, function(results, status) {
            if (status === google.maps.GeocoderStatus.OK && results[0]) {
                var country = getComponent(results, 'country', 'long_name'),
                    twoLetterCode = getComponent(results, 'country');
                geoPanel.textContent = country + "(" + twoLetterCode + ")";
                // Link from the globe to the tag with id selectedCountry
                selectedCountry.value = twoLetterCode;
            }
        });
        geoPanel.style.display = 'block';
    }, false);
    // Special code to handle high-density displays (e.g. retina, some phones)
    // In the future, Planetary.js will handle this by itself (or via a plugin).
    if (window.devicePixelRatio == 2) {
        canvas.width = 2 * globeRadius + 160;
        canvas.height = 2 * globeRadius + 160;
        context = canvas.getContext('2d');
        context.scale(1.3, 1.3);
    }
    // Draw that globe!
    globe.draw(canvas);

    /**
    * We turn off rotating mode after starting
    */
    rotatingMode.checked || globe.plugins.autorotate.pause();

    // This plugin will automatically rotate the globe around its vertical
    // axis a configured number of degrees every second.
    function autorotate(degPerSec) {
        // Planetary.js plugins are functions that take a `planet` instance
        // as an argument...
        return function(planet) {
            var lastTick = null;
            var paused = false;
            planet.plugins.autorotate = {
                pause:  function() { paused = true;  },
                resume: function() { paused = false; }
            };
            // ...and configure hooks into certain pieces of its lifecycle.
            planet.onDraw(function() {
                if (paused || !lastTick) {
                    lastTick = new Date();
                } else {
                    var now = new Date();
                    var delta = now - lastTick;
                    // This plugin uses the built-in projection (provided by D3)
                    // to rotate the globe each time we draw it.
                    var rotation = planet.projection.rotate();
                    rotation[0] += degPerSec * delta / 1000;
                    if (rotation[0] >= 180) rotation[0] -= 360;
                    planet.projection.rotate(rotation);
                    lastTick = now;
                }
            });
        };
    };

    // This plugin takes lake data from the special
    // TopoJSON we're loading and draws them on the map.
    function lakes(options) {
        options = options || {};
        var lakes = null;

        return function(planet) {
            planet.onInit(function() {
                // We can access the data loaded from the TopoJSON plugin
                // on its namespace on `planet.plugins`. We're loading a custom
                // TopoJSON file with an object called "ne_110m_lakes".
                var world = planet.plugins.topojson.world;
                lakes = topojson.feature(world, world.objects.ne_110m_lakes);
            });

            planet.onDraw(function() {
                planet.withSavedContext(function(context) {
                context.beginPath();
                planet.path.context(context)(lakes);
                context.fillStyle = options.fill || 'black';
                context.fill();
                });
            });
        };
    };
    /**
     * Check argument for NULL value or change all the spaces to empty symbol
     * @param text
     * @returns {boolean}
     */
    function isNullOrWhitespace(text) {
        return text == null ? true : text.replace(/\s/gi, '').length < 1;
    }
    /**
     * Looking for a desired type in the results and getting component using typeName
     * @param {Object} results
     * @param {String} desiredType, for example 'country'
     * @param {?String} typeName, for example 'long_name'. If it doesn't set it is equal to 'short_name'
     * @returns {*}
     */
    function getComponent(results, desiredType, typeName) {
        var address_components = results[0].address_components;

        typeof typeName === 'undefined' && (typeName = 'short_name');
        for (var i = 0; i < address_components.length; i++) {
            var shortname = address_components[i].short_name,
                type = address_components[i].types;

            if (type.indexOf(desiredType) != -1) {
                return isNullOrWhitespace(address_components[i][typeName]) ? shortname : address_components[i][typeName];
            }
        }
    }
})();
<commit_msg>commented out the plugin pings to check perfomance on any mobile phone<commit_after>(function() {
    var globe = planetaryjs.planet(),
        rotating = document.getElementById('rotating'),
        rotatingMode = false,
        geoPanel = document.getElementById('geoPanel'),
        selectedCountry = document.getElementById('selectedCountry'),
        geocoder = new google.maps.Geocoder,
        globeRadius = 240;
    // Load our custom `autorotate` plugin; see below.
    globe.loadPlugin(autorotate(5));
    // The `earth` plugin draws the oceans and the land; it's actually
    // a combination of several separate built-in plugins.
    //
    // Note that we're loading a special TopoJSON file
    // (world-110m-withlakes.json) so we can render lakes.
    globe.loadPlugin(planetaryjs.plugins.earth({
        topojson: { file:   '/world-110m-withlakes.json' },
        oceans:   { fill:   '#000080' },
        land:     { fill:   '#339966' },
        borders:  { stroke: '#008000' }
    }));
    // Load our custom `lakes` plugin to draw lakes; see below.
    globe.loadPlugin(lakes({
        fill: '#000080'
    }));
    // The `zoom` and `drag` plugins enable
    // manipulating the globe with the mouse.
    globe.loadPlugin(planetaryjs.plugins.zoom({
        scaleExtent: [globeRadius, 20 * globeRadius]
    }));
    /**
    * Turn rotating mode on/off on the globe
    */
    rotating.onclick = function () {
        rotatingMode = !rotatingMode;
        globe.plugins.autorotate[rotatingMode ? 'resume' : 'pause']();
    };
    globe.loadPlugin(planetaryjs.plugins.drag({
        // Dragging the globe should pause the
        // automatic rotation until we release the mouse.
        onDragStart: function() {
            if (rotatingMode.checked) {
                this.plugins.autorotate.pause();
            }
        },
        onDragEnd: function() {
            if (rotatingMode.checked) {
                this.plugins.autorotate.resume();
            }
        }
    }));
    // Set up the globe's initial scale, offset, and rotation.
    globe.projection.scale(globeRadius).translate([globeRadius, globeRadius]).rotate([0, -10, 0]);

    // Every few hundred milliseconds, we'll draw another random ping.
    var colors = ['red', 'yellow', 'white', 'orange', 'green', 'cyan', 'pink'];

    // The `pings` plugin draws animated pings on the globe.
    /*
    globe.loadPlugin(planetaryjs.plugins.pings());
    setInterval(function() {
        var lat = Math.random() * 170 - 85;
        var lng = Math.random() * 360 - 180;
        var color = colors[Math.floor(Math.random() * colors.length)];
        globe.plugins.pings.add(lng, lat, { color: color, ttl: 2000, angle: Math.random() * 10 });
    }, 500);
*/

    var canvas = document.getElementById('rotatingGlobe');
    /**
    * setup the cursor as pointer while mouse pressing
    */
    canvas.onmousedown = function () {
        this.style.cursor = "pointer";
    }
    /**
    * restore the cursor while mouse releasing
    */
    canvas.onmouseup = function () {
        this.style.cursor = "";
    }
    /**
    * setup the handler for click to show geo coordinates (longitude, altitude)
    */
    canvas.addEventListener('click', function(event) {
        var x = event.x,
            y = event.y,
            coordinates;
        x -= this.offsetLeft;
        y -= this.offsetTop;
        coordinates = globe.projection.invert([x, y]);
        geoPanel.textContent = "[" + coordinates.join(",") + "]";

        geocoder.geocode({'location': { lat: coordinates[1], lng: coordinates[0] }}, function(results, status) {
            if (status === google.maps.GeocoderStatus.OK && results[0]) {
                var country = getComponent(results, 'country', 'long_name'),
                    twoLetterCode = getComponent(results, 'country');
                geoPanel.textContent = country + "(" + twoLetterCode + ")";
                // Link from the globe to the tag with id selectedCountry
                selectedCountry.value = twoLetterCode;
            }
        });
        geoPanel.style.display = 'block';
    }, false);
    // Special code to handle high-density displays (e.g. retina, some phones)
    // In the future, Planetary.js will handle this by itself (or via a plugin).
    if (window.devicePixelRatio == 2) {
        canvas.width = 2 * globeRadius + 160;
        canvas.height = 2 * globeRadius + 160;
        context = canvas.getContext('2d');
        context.scale(1.3, 1.3);
    }
    // Draw that globe!
    globe.draw(canvas);

    /**
    * We turn off rotating mode after starting
    */
    rotatingMode.checked || globe.plugins.autorotate.pause();

    // This plugin will automatically rotate the globe around its vertical
    // axis a configured number of degrees every second.
    function autorotate(degPerSec) {
        // Planetary.js plugins are functions that take a `planet` instance
        // as an argument...
        return function(planet) {
            var lastTick = null;
            var paused = false;
            planet.plugins.autorotate = {
                pause:  function() { paused = true;  },
                resume: function() { paused = false; }
            };
            // ...and configure hooks into certain pieces of its lifecycle.
            planet.onDraw(function() {
                if (paused || !lastTick) {
                    lastTick = new Date();
                } else {
                    var now = new Date();
                    var delta = now - lastTick;
                    // This plugin uses the built-in projection (provided by D3)
                    // to rotate the globe each time we draw it.
                    var rotation = planet.projection.rotate();
                    rotation[0] += degPerSec * delta / 1000;
                    if (rotation[0] >= 180) rotation[0] -= 360;
                    planet.projection.rotate(rotation);
                    lastTick = now;
                }
            });
        };
    };

    // This plugin takes lake data from the special
    // TopoJSON we're loading and draws them on the map.
    function lakes(options) {
        options = options || {};
        var lakes = null;

        return function(planet) {
            planet.onInit(function() {
                // We can access the data loaded from the TopoJSON plugin
                // on its namespace on `planet.plugins`. We're loading a custom
                // TopoJSON file with an object called "ne_110m_lakes".
                var world = planet.plugins.topojson.world;
                lakes = topojson.feature(world, world.objects.ne_110m_lakes);
            });

            planet.onDraw(function() {
                planet.withSavedContext(function(context) {
                context.beginPath();
                planet.path.context(context)(lakes);
                context.fillStyle = options.fill || 'black';
                context.fill();
                });
            });
        };
    };
    /**
     * Check argument for NULL value or change all the spaces to empty symbol
     * @param text
     * @returns {boolean}
     */
    function isNullOrWhitespace(text) {
        return text == null ? true : text.replace(/\s/gi, '').length < 1;
    }
    /**
     * Looking for a desired type in the results and getting component using typeName
     * @param {Object} results
     * @param {String} desiredType, for example 'country'
     * @param {?String} typeName, for example 'long_name'. If it doesn't set it is equal to 'short_name'
     * @returns {*}
     */
    function getComponent(results, desiredType, typeName) {
        var address_components = results[0].address_components;

        typeof typeName === 'undefined' && (typeName = 'short_name');
        for (var i = 0; i < address_components.length; i++) {
            var shortname = address_components[i].short_name,
                type = address_components[i].types;

            if (type.indexOf(desiredType) != -1) {
                return isNullOrWhitespace(address_components[i][typeName]) ? shortname : address_components[i][typeName];
            }
        }
    }
})();
<|endoftext|>


<commit_before>function _pd(func) {
    return function(e) {
        e.preventDefault();
        func.apply(this, arguments);
    };
}

function fieldFocused(e) {
    var tags = /input|keygen|meter|option|output|progress|select|textarea/i;
    return tags.test(e.target.nodeName);
}

function postUnsaved(data) {
    $('input[name="unsaved_data"]').val(JSON.stringify(data));
}

function loadUnsaved() {
    return JSON.parse($('input[name="unsaved_data"]').val() || '{}');
}

var escape_ = function(s) {
    if (s === undefined) {
        return;
    }
    return s.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<')
            .replace(/'/g, ''').replace(/"/g, '"');
};

// Sexy setTimeout. wait(1000).then(doSomething);
function wait(ms) {
    var $d = $.Deferred();
    setTimeout(function() {
        $d.resolve();
    }, ms);
    return $d.promise();
}

_.extend(String.prototype, {
    trim: function(str) {
        // Trim leading and trailing whitespace (like lstrip + rstrip).
        return this.replace(/^\s*/, '').replace(/\s*$/, '');
    },
    strip: function(str) {
        // Strip all whitespace.
        return this.replace(/\s/g, '');
    }
});

function makeOrGetOverlay(opts) {
    var classes = 'overlay',
        id = opts;
    if (_.isObject(opts)) {
        if ('class' in opts) {
            classes += ' ' + opts.class;
        }
        id = opts.id;
    }
    var el = $('#' + id);
    if (!el.length) {
        el = $('
');
        $('body').append(el);
    }
    return el;
}

function getTemplate($el) {
    // If the element exists, return the template.
    if ($el.length) {
        return template($el.html());
    }
    // Otherwise, return undefined.
}

// Initializes character counters for textareas.
function initCharCount(parent) {
    /*
    parent - An optional parameter that allows the effects of this function to
             be limited to a single node rather than the whole document.
    */
    var countChars = function(el, cc) {
        var $el = $(el),
            val = $el.val(),
            max = parseInt(cc.attr('data-maxlength'), 10),
            left = max - val.length,
            cc_parent = cc.parent();
        // L10n: {0} is the number of characters left.
        cc.html(format(ngettext('{0} character left.',
                                '{0} characters left.', left), [left]))
          .toggleClass('error', left < 0);
        if(left >= 0 && cc_parent.hasClass('error')) {
            cc_parent.removeClass('error');
        }
    };
    $('.char-count', parent).each(function() {
        var $this = $(this)
        var $cc = $(this),
            $form = $(this).closest('form'),
            $el;
        if ($cc.attr('data-for-startswith') !== undefined) {
            $el = $('textarea[id^="' + $cc.attr('data-for-startswith') + '"]:visible', $form);
        } else {
            $el = $('textarea#' + $cc.attr('data-for'), $form);
        }
        $el.bind('keyup blur', _.throttle(function() {
            countChars(this, $cc);
        }, 250)).trigger('blur');
    });
}

function successNotification(msg) {
    var success = $('.success h2');
    if (success.length) {
        success.text(msg);
    } else {
        $('#page').prepend($('
' +
                             '

' + msg +
                             '

'));
    }
}

$(document).ajaxSuccess(function(event, xhr, ajaxSettings) {
    z.win.trigger('resize'); // Redraw what needs to be redrawn.
}).on('click', 'a.external, a[rel=external]', function() {
    // If we're inside the Marketplace app, open external links in the Browser.
    if (z.capabilities.chromeless) {
        $(this).attr('target', '_blank');
    }
});
<commit_msg>String.prototype.trim is already a thing in JS land, sillypants<commit_after>function _pd(func) {
    return function(e) {
        e.preventDefault();
        func.apply(this, arguments);
    };
}

function fieldFocused(e) {
    var tags = /input|keygen|meter|option|output|progress|select|textarea/i;
    return tags.test(e.target.nodeName);
}

function postUnsaved(data) {
    $('input[name="unsaved_data"]').val(JSON.stringify(data));
}

function loadUnsaved() {
    return JSON.parse($('input[name="unsaved_data"]').val() || '{}');
}

var escape_ = function(s) {
    if (s === undefined) {
        return;
    }
    return s.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<')
            .replace(/'/g, ''').replace(/"/g, '"');
};

// Sexy setTimeout. wait(1000).then(doSomething);
function wait(ms) {
    var $d = $.Deferred();
    setTimeout(function() {
        $d.resolve();
    }, ms);
    return $d.promise();
}

_.extend(String.prototype, {
    strip: function(str) {
        // Strip all whitespace.
        return this.replace(/\s/g, '');
    }
});

function makeOrGetOverlay(opts) {
    var classes = 'overlay',
        id = opts;
    if (_.isObject(opts)) {
        if ('class' in opts) {
            classes += ' ' + opts.class;
        }
        id = opts.id;
    }
    var el = $('#' + id);
    if (!el.length) {
        el = $('
');
        $('body').append(el);
    }
    return el;
}

function getTemplate($el) {
    // If the element exists, return the template.
    if ($el.length) {
        return template($el.html());
    }
    // Otherwise, return undefined.
}

// Initializes character counters for textareas.
function initCharCount(parent) {
    /*
    parent - An optional parameter that allows the effects of this function to
             be limited to a single node rather than the whole document.
    */
    var countChars = function(el, cc) {
        var $el = $(el),
            val = $el.val(),
            max = parseInt(cc.attr('data-maxlength'), 10),
            left = max - val.length,
            cc_parent = cc.parent();
        // L10n: {0} is the number of characters left.
        cc.html(format(ngettext('{0} character left.',
                                '{0} characters left.', left), [left]))
          .toggleClass('error', left < 0);
        if(left >= 0 && cc_parent.hasClass('error')) {
            cc_parent.removeClass('error');
        }
    };
    $('.char-count', parent).each(function() {
        var $this = $(this)
        var $cc = $(this),
            $form = $(this).closest('form'),
            $el;
        if ($cc.attr('data-for-startswith') !== undefined) {
            $el = $('textarea[id^="' + $cc.attr('data-for-startswith') + '"]:visible', $form);
        } else {
            $el = $('textarea#' + $cc.attr('data-for'), $form);
        }
        $el.bind('keyup blur', _.throttle(function() {
            countChars(this, $cc);
        }, 250)).trigger('blur');
    });
}

function successNotification(msg) {
    var success = $('.success h2');
    if (success.length) {
        success.text(msg);
    } else {
        $('#page').prepend($('
' +
                             '

' + msg +
                             '

'));
    }
}

$(document).ajaxSuccess(function(event, xhr, ajaxSettings) {
    z.win.trigger('resize'); // Redraw what needs to be redrawn.
}).on('click', 'a.external, a[rel=external]', function() {
    // If we're inside the Marketplace app, open external links in the Browser.
    if (z.capabilities.chromeless) {
        $(this).attr('target', '_blank');
    }
});
<|endoftext|>


<commit_before>/**
 * Wechat for Bot. Connecting ChatBots
 *
 * Interface for puppet
 *
 * Class FriendRequest
 *
 * Licenst: ISC
 * https://github.com/wechaty/wechaty
 *
 * request/accept: https://github.com/wechaty/wechaty/issues/33
 *
 * 1. send request
 * 2. receive request(in friend event)
 * 3. confirmation friendship(friend event)
 *
 */

const Wechaty       = require('../wechaty')
const Contact       = require('../contact')
const Config        = require('../config')
const FriendRequest = require('../friend-request')
const log           = require('../brolog-env')

class PuppetWebFriendRequest extends FriendRequest {
  constructor() {
    log.verbose('PuppetWebFriendRequest', 'constructor()')
    super()
    this.type = '' // enum('send', 'receive', 'confirm')
  }

  receive(info) {
    log.verbose('PuppetWebFriendRequest', 'receive(%s)', info)

    if (!info || !info.UserName) {
      throw new Error('not valid RecommendInfo: ' + info)
    }
    this.info     = info

    this.contact    = Contact.load(info.UserName)
    this.hello      = info.Content
    this.ticket     = info.Ticket
    // ??? this.nick = info.NickName

    if (!this.ticket) {
      throw new Error('ticket not found')
    }

    this.type = 'receive'

    return this
  }

  confirm(contact) {
    log.verbose('PuppetWebFriendRequest', 'confirm(%s)', contact)

    if (!contact) {
      throw new Error('contact not found')
    }
    this.contact  = contact
    this.type     = 'confirm'
  }

  send(contact, hello = 'Hi') {
    log.verbose('PuppetWebFriendRequest', 'send(%s)', contact)

    if (!contact) {
      throw new Error('contact not found')
    }
    this.contact  = contact
    this.type       = 'send'

    if (hello) {
      this.hello = hello
    }

    return Config.puppetInstance()
                  .friendRequestSend(contact, hello)
  }

  accept() {
    log.verbose('FriendRequest', 'accept() %s', this.contact)

    if (this.type !== 'receive') {
      throw new Error('request on a ' + this.type + ' type')
    }

    return Config.puppetInstance()
                  .friendRequestAccept(this.contact, this.ticket)
  }

}

module.exports = PuppetWebFriendRequest.default = PuppetWebFriendRequest.PuppetWebFriendRequest = PuppetWebFriendRequest
<commit_msg>only export default in internal modules<commit_after>/**
 * Wechat for Bot. Connecting ChatBots
 *
 * Interface for puppet
 *
 * Class FriendRequest
 *
 * Licenst: ISC
 * https://github.com/wechaty/wechaty
 *
 * request/accept: https://github.com/wechaty/wechaty/issues/33
 *
 * 1. send request
 * 2. receive request(in friend event)
 * 3. confirmation friendship(friend event)
 *
 */

const Wechaty       = require('../wechaty')
const Contact       = require('../contact')
const Config        = require('../config')
const FriendRequest = require('../friend-request')
const log           = require('../brolog-env')

class PuppetWebFriendRequest extends FriendRequest {
  constructor() {
    log.verbose('PuppetWebFriendRequest', 'constructor()')
    super()
    this.type = '' // enum('send', 'receive', 'confirm')
  }

  receive(info) {
    log.verbose('PuppetWebFriendRequest', 'receive(%s)', info)

    if (!info || !info.UserName) {
      throw new Error('not valid RecommendInfo: ' + info)
    }
    this.info     = info

    this.contact    = Contact.load(info.UserName)
    this.hello      = info.Content
    this.ticket     = info.Ticket
    // ??? this.nick = info.NickName

    if (!this.ticket) {
      throw new Error('ticket not found')
    }

    this.type = 'receive'

    return this
  }

  confirm(contact) {
    log.verbose('PuppetWebFriendRequest', 'confirm(%s)', contact)

    if (!contact) {
      throw new Error('contact not found')
    }
    this.contact  = contact
    this.type     = 'confirm'
  }

  send(contact, hello = 'Hi') {
    log.verbose('PuppetWebFriendRequest', 'send(%s)', contact)

    if (!contact) {
      throw new Error('contact not found')
    }
    this.contact  = contact
    this.type       = 'send'

    if (hello) {
      this.hello = hello
    }

    return Config.puppetInstance()
                  .friendRequestSend(contact, hello)
  }

  accept() {
    log.verbose('FriendRequest', 'accept() %s', this.contact)

    if (this.type !== 'receive') {
      throw new Error('request on a ' + this.type + ' type')
    }

    return Config.puppetInstance()
                  .friendRequestAccept(this.contact, this.ticket)
  }

}

module.exports = PuppetWebFriendRequest
<|endoftext|>


<commit_before>import React from 'react';

import {connect} from 'react-redux';
// import {bindActionCreators} from 'redux';
import * as actions from '../../actions/charGenActions';
import * as api from '../../actions/apiActions';

import TextInput from '../../components/textInput';
import SelectList from '../../components/selectList';

import {classes} from '../../data/classes';
import {races} from '../../data/races';

class BasicsPage extends React.Component {

    componentWillMount(){
        console.log(this.props);
        this.props.fetchData('alignments');
    }

    render() {

        const {actions, character, alignments} = this.props;

        return (

                <TextInput
                    labelText="Name: "
                    value={character.name}
                    id="name"
                    name="name"
                    onChange={(e) => actions.updateValue('name', e.target.value)}
                    />

                <SelectList
                    labelText="Race: "
                    id="race"
                    name="selectedRace"
                    options={races}
                    value={character.race.value}
                    onChange={(e) => actions.updateRace('race', e.target.value)}
                />

                <SelectList
                    labelText="Class: "
                    id="class"
                    options={classes}
                    name="selectedClass"
                    onChange={(e) => actions.updateClass(e.target.value, 1)}
                    value={character.class.value}
                />

                <SelectList
                    labelText="Alignment: "
                    id="alignment"
                    options={alignments}
                    onChange={(e) => actions.updateValue('alignment', e.target.value)}
                    value={character.alignment}
                />

            );
        }
    }

// BasicsPage.propTypes = {
//   actions: React.PropTypes.object.isRequired,
//   character: React.PropTypes.object.isRequired
// };

function mapStateToProps(state){
    console.log(state);
    return {
        alignments: state.api,
        character: state.character
    };
}

export default connect(mapStateToProps, api)(BasicsPage);
<commit_msg>apiActions clean up<commit_after>import React from 'react';

import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as actions from '../../actions/charGenActions';
import * as apiActions from '../../actions/apiActions';

import TextInput from '../../components/textInput';
import SelectList from '../../components/selectList';

class BasicsPage extends React.Component {

    componentWillMount(){
        this.props.fetchData('alignments');
        this.props.fetchData('classes');
        this.props.fetchData('races');
    }

    render() {

        const {actions, character, alignments, races, classes} = this.props;

        return (

                <TextInput
                    labelText="Name: "
                    value={character.name}
                    id="name"
                    name="name"
                    onChange={(e) => actions.updateValue('name', e.target.value)}
                    />

                <SelectList
                    labelText="Race: "
                    id="race"
                    name="selectedRace"
                    options={races || [{id: '123', value: 'Loading'}]}
                    value={character.race.value}
                    onChange={(e) => actions.updateRace('race', e.target.value)}
                />

                <SelectList
                    labelText="Class: "
                    id="class"
                    options={classes || [{id: '123', value: 'Loading'}]}
                    name="selectedClass"
                    onChange={(e) => actions.updateClass(e.target.value, 1)}
                    value={character.class.value}
                />

                <SelectList
                    labelText="Alignment: "
                    id="alignment"
                    options={alignments || [{id: '123', value: 'Loading'}]}
                    onChange={(e) => actions.updateValue('alignment', e.target.value)}
                    value={character.alignment}
                />

            );
        }
    }

BasicsPage.propTypes = {
  actions: React.PropTypes.object.isRequired,
  character: React.PropTypes.object.isRequired,
  alignments: React.PropTypes.array,
  races: React.PropTypes.array,
  classes: React.PropTypes.array
};

function mapStateToProps(state){
    return {
        alignments: state.api.alignments,
        races: state.api.races,
        classes: state.api.classes,
        character: state.character
    };
}

// function mapDispatchToProps(dispatch) {
//     return {
//         actions: bindActionCreators(actions, dispatch),
//         apiActions: bindActionCreators(apiActions, dispatch)
//     };
// }

export default connect(
    mapStateToProps,
    apiActions)
(BasicsPage);
<|endoftext|>