Материал из Tanki Online Wiki
(Отмена правки 273950, сделанной участником Impulse (обс.))
(не показана 1 промежуточная версия этого же участника)
(нет различий)

Версия 12:40, 1 декабря 2019

/* DO NOT USE // COMMENTS */

/*=======close recent======

var el = document.getElementById("mw-content-text");
if (mw.config.values.wgTitle === "RecentChanges") {
  if (
    mw.config.values.wgUserGroups.indexOf("administrator") !== -1 ||
    mw.config.values.wgUserGroups.indexOf("bureaucrat") !== -1 ||
    mw.config.values.wgUserGroups.indexOf("editor") !== -1
  ) {
    el.style.display = "block";
  } else {
    el.parentNode.removeChild(el);
  }
}
*/


/*============================================================================*/
/* Simple polyfill */

if (!Object.keys) Object.keys = function(o) {
  if (o !== Object(o))
    throw new TypeError('Object.keys called on a non-object');
  var k = [], p;
  for (p in o) if (Object.prototype.hasOwnProperty.call(o, p)) k.push(p);
  return k;
}

/*Get random key from Object/Array*/

function getRandomKey(obj){
  var keys = Object.keys(obj);
  return keys[Math.floor(Math.random()*keys.length)];
};

function getRandomVal(obj){
  return obj[getRandomKey(obj)];
};

function getSplitNumber(num) {
  return num.toString().replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
}

function getSelectedText() {
  if (window.getSelection) {
    return window.getSelection().toString();
  } else if (document.getSelection) {
    return document.getSelection().toString();
  } else if (document.selection) {
    return document.selection.createRange().text;
  } else {
    return false;
  }
}

function isNotEmpty(_var){
  return !( _var == "" || new RegExp(/^\s+$/).test(_var) || _var == null || ((typeof _var == 'array' || typeof _var == 'object') && _var.length == 0) );
}

function isDesktopChrome() {
  var ua = window.navigator.userAgent.toLowerCase();
  return (
    window.navigator.vendor.toLowerCase().indexOf("google") > -1 &&
    window.chrome != null &&
    ua.indexOf("opr") == -1 && ua.indexOf("opera") == -1 &&
    ua.indexOf("yabrowser") == -1 && ua.indexOf("yowser") == -1 &&
    ua.indexOf("edge") == -1 &&
    ua.indexOf("android") == -1 && ua.indexOf("crios") == -1
  );
}

/*======================Base64 Encode/Decode functions========================*/
/* using: base64.encode(string), base64.decode(string) */

var base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,c,d="",C=0;for(r=base64._utf8_encode(r);C<r.length;)a=(t=r.charCodeAt(C++))>>2,h=(3&t)<<4|(e=r.charCodeAt(C++))>>4,n=(15&e)<<2|(o=r.charCodeAt(C++))>>6,c=63&o,isNaN(e)?n=c=64:isNaN(o)&&(c=64),d=d+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(c);return d},decode:function(r){var t,e,o,a,h,n,c="",d=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");d<r.length;)t=this._keyStr.indexOf(r.charAt(d++))<<2|(a=this._keyStr.indexOf(r.charAt(d++)))>>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(d++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(d++))),c+=String.fromCharCode(t),64!=h&&(c+=String.fromCharCode(e)),64!=n&&(c+=String.fromCharCode(o));return c=base64._utf8_decode(c)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=c1=c2=0;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&o<224?(c2=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&c2),e+=2):(c2=r.charCodeAt(e+1),c3=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&c2)<<6|63&c3),e+=3);return t}};

/*============================================================================================*/

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(factory);
  } else if (typeof exports === 'object') {
    module.exports = factory();
  } else {
    root.tingle = factory();
  }
}
  (this, function () {

    function Modal(options) {
      var defaults = {
        onClose: null,
        onOpen: null,
        beforeOpen: null,
        beforeClose: null,
        closeMethods: ['overlay', 'button', 'escape'],
        cssClass: []
      };
      this.opts = extend({}, defaults, options);
      this.init();
    }

    Modal.prototype.init = function () {
      if (this.modal) {
        return;
      }
      _build.call(this);
      _bindEvents.call(this);
      document.body.appendChild(this.modal);
    };

    Modal.prototype.destroy = function () {
      if (this.modal === null) {
        return;
      }
      _unbindEvents.call(this);
      this.modal.parentNode.removeChild(this.modal);
      this.modal = null;
    };

    Modal.prototype.open = function () {
      var self = this;
      if (typeof self.opts.beforeOpen === 'function') {
        self.opts.beforeOpen();
      }
      if (this.modal.style.removeProperty) {
        this.modal.style.removeProperty('display');
      } else {
        this.modal.style.removeAttribute('display');
      }
      _addClass(document.body, 'tingle-enabled');
      _addClass(this.modal, 'tingle-modal--visible');
      if (typeof self.opts.onOpen === 'function') {
        self.opts.onOpen.call(self);
      }
      this.checkOverflow();
    };

    Modal.prototype.isOpen = function () {
      return this.modal ? _hasClass(this.modal, "tingle-modal--visible") : false;
    };

    Modal.prototype.close = function () {
      if (typeof this.opts.beforeClose === "function") {
        var close = this.opts.beforeClose.call(this);
        if (!close) {
          return;
        }
      }
      var self = this;
      jQuery(this.modal).fadeOut(200, function(){
        _removeClass(document.body, 'tingle-enabled');
        _removeClass(this, 'tingle-modal--visible');

        self.modal.style.display = 'none';
        if (typeof self.opts.onClose === "function") {
          self.opts.onClose.call(this);
        }
        self.destroy();
      });
    };

    Modal.prototype.setContent = function (content) {
      if (typeof content === 'string') {
        this.modalBoxContent.innerHTML = content;
      } else {
        this.modalBoxContent.innerHTML = "";
        this.modalBoxContent.appendChild(content);
      }
    };

    Modal.prototype.getContent = function () {
      return this.modalBoxContent;
    };

    Modal.prototype.isOverflow = function () {
      return this.modalBox.clientHeight >= window.innerHeight;
    };

    Modal.prototype.checkOverflow = function () {
      if (_hasClass(this.modal, 'tingle-modal--visible')) {
        if (this.isOverflow()) {
          _addClass(this.modal, 'tingle-modal--overflow');
        } else {
          _removeClass(this.modal, 'tingle-modal--overflow');
        }
      }
    }

    function _build() {
      this.modal = document.createElement('div');
      _addClass(this.modal, 'tingle-modal');
      this.modal.style.display = 'none';
      this.opts.cssClass.forEach(function (item) {
        if (typeof item === 'string') {
          _addClass(this.modal, item);
        }
      }, this);

      this.modalCloseBtnIcon = document.createElement('button');
      _addClass(this.modalCloseBtnIcon, 'tingle-modal__closeIcon');
      _addClass(this.modalCloseBtnIcon, 'tingle-modal__close');
      //this.modalCloseBtnIcon.innerHTML = '×';
      this.modalBox = document.createElement('div');
      _addClass(this.modalBox, 'tingle-modal-box');
      this.modalBoxContent = document.createElement('div');
      _addClass(this.modalBoxContent, 'tingle-modal-box__content');
      
      this.modalBox.appendChild(this.modalBoxContent);
      //this.modalBox.appendChild(this.modalCloseBtnIcon);
      this.modal.appendChild(this.modalCloseBtnIcon);
      this.modal.appendChild(this.modalBox);
    }

    function _bindEvents() {
      this._events = {
        clickCloseBtn: this.close.bind(this),
        clickOverlay: _handleClickOutside.bind(this),
        resize: this.checkOverflow.bind(this),
        keyboardNav: _handleKeyboardNav.bind(this)
      };
      this.modalCloseBtnIcon.addEventListener('click', this._events.clickCloseBtn);
      this.modal.addEventListener('mousedown', this._events.clickOverlay);
      window.addEventListener('resize', this._events.resize);
      document.addEventListener("keydown", this._events.keyboardNav);
    }

    function _handleKeyboardNav(event) {
      if (event.which === 27 && this.isOpen()) {
        this.close();
      }
    }

    function _handleClickOutside(event) {
      if (this.opts.closeMethods.indexOf('overlay') !== -1 && !_findAncestor(event.target, 'tingle-modal') && event.clientX < this.modal.clientWidth) {
        this.close();
      }
    }

    function _findAncestor(el, cls) {
      while ((el = el.parentElement) && !_hasClass(el, cls));
      return el;
    }

    function _unbindEvents() {
      this.modalCloseBtnIcon.removeEventListener('click', this._events.clickCloseBtn);
      this.modal.removeEventListener('mousedown', this._events.clickOverlay);
      window.removeEventListener('resize', this._events.resize);
      document.removeEventListener("keydown", this._events.keyboardNav);
    }

    function _cleanClassName(target) {
      target.className = target.className.replace(/[\n\t]/g, " ").trim();
    }

    function _hasClass(target, classname) {
      _cleanClassName(target);
      return !!((" " + target.className + " ").indexOf(" " + classname.trim() + " ") > -1);
    }

    function _addClass(target, classname) {
      if (!_hasClass(target, classname)) {
        target.className += ' ' + classname.trim();
      }
    }

    function _removeClass(target, classname) {
      if (_hasClass(target, classname)) {
        var regexp = new RegExp('(\\s|^)' + classname.trim() + '(\\s|$)');
        target.className = target.className.replace(regexp, ' ').trim();
      }
    }

    function extend() {
      for (var i = 1; i < arguments.length; i++) {
        for (var key in arguments[i]) {
          if (arguments[i].hasOwnProperty(key)) {
            arguments[0][key] = arguments[i][key];
          }
        }
      }
      return arguments[0];
    }

    return {
      modal: Modal
    };

  }));


/*============================================================================================*/
/*============================================================================================*/
/*Using jQuery from here*/

jQuery.noConflict();

jQuery(document).ready(function($) {

/*============================================================================================*/

/*Any element as a link <a>*/
$(".linkElem").on('click', function(){ window.open($(this).data("url"),"_blank"); });

/*============================================================================================*/
/*To Top button*/
  $('body').append('<div id="toTop-wrapper" style="display: none;"><div id="toTop-arrow"></div></div>');
  $(function() {
    $(window).scroll(function() {
      if($(this).scrollTop() > 500) {
        $('#toTop-wrapper').fadeIn(300);	
      } else {
        $('#toTop-wrapper').fadeOut(100);
      }
    });
    $('#toTop-wrapper').click(function() {
      $('body,html').animate({ scrollTop:0 }, 200);
    });	
  });

/*============================================================================================*/
  /*opening thumbs and gallery items in a new tab*/

  $('.thumbinner a, .jdGallery .open').on('click', function(e){ 
    e.preventDefault();
    window.open(e.currentTarget.href,'_blank');
  });

/*============================================================================================*/
/* Tank Preview */

if($('.showPaint').length){ 

  var parts_url  = 'images/ru/6/66/Tank_parts_resources.json?v=016';
  var paints_url = 'images/ru/6/6d/Paints_textures.json?v=032';
  var swfobject_url = 'https://cdnjs.cloudflare.com/ajax/libs/swfobject/2.2/swfobject.min.js';

  var Viewer = {
      currentPaint: null,
      data: {},
      emptyTank: function(){
        return {
          "hull": {
            "type": null,
            "model": null
          },
          "turret": {
            "type": null,
            "model": null
          },
          "paint": {
            "type": null,
            "model": null
          }
        };
      },
      getRandomTank: function(){
        var tank = this.emptyTank();
        if(isNotEmpty(this.data)){
          tank.hull.type = getRandomKey(this.data.hulls);
          tank.turret.type = getRandomKey(this.data.turrets);
          tank.hull.model = getRandomKey(this.data.hulls[tank.hull.type]);
          tank.turret.model = getRandomKey(this.data.turrets[tank.turret.type]);
          
          return tank;
        } else {
          return false;
        }
      },
      appendViewer: function(tank, target_id){
        if(swfobject){
          swfobject.ua.pv = [100, 0, 0];

          var viewer_swf = 'images/ru/2/24/Tank_viewer.swf';
          /*var url_part = 'https://ru.tankiwiki.com/';*/
          
          var items = {
            "hull": this.data.hulls[tank.hull.type][tank.hull.model],
            "turret": this.data.turrets[tank.turret.type][tank.turret.model],
            "paint": this.data.paints[tank.paint.type][tank.paint.model]
          };
          var flashvars = {
            "itemsXml": 
              "<response>" + 
              "<hull_model>" + items.hull.model + "</hull_model>" + 
              "<hull_details>" + items.hull.details + "</hull_details>" + 
              "<hull_details_alpha>" + items.hull.alpha + "</hull_details_alpha>" + 
              "<hull_lightmap>" + items.hull.lightmap + "</hull_lightmap>" + 
              "<turret_model>" + items.turret.model + "</turret_model>" + 
              "<turret_details>" + items.turret.details + "</turret_details>" + 
              "<turret_details_alpha>" + items.turret.alpha + "</turret_details_alpha>" + 
              "<turret_lightmap>" + items.turret.lightmap + "</turret_lightmap>" + 
              "<paint_texture>" + items.paint + "</paint_texture>" + 
              "</response>"
          };
          
          var params = {
            "menu": false,
            "seamlesstabbing": false,
            "wmode": "transparent"
          }
          
          swfobject.embedSWF(viewer_swf, target_id, "600", "400", "11", false, flashvars, params, false);
        } else {
          return false;
        }
      }
  };

  $.when(
    $.getJSON(parts_url, function(json){ 
      Viewer.data.hulls = json.hulls;
      Viewer.data.turrets = json.turrets;
    }),
    $.getJSON(paints_url, function(json){ 
      Viewer.data.paints = json;
    }),
    $.getScript(swfobject_url)
  ).done(function(){
   
    var templateMenu = [
      '<div id="TankPreview__wrapper">',
      ' <div id="TankPreview__viewer"><div id="TankPreview"></div></div>',
      ' <div id="TankPreview__controls">',
      '   <div class="wrapper">',
      '         Корпус:',
      '         <select class="tanki-control" size="1" id="hullType" name="hullType" data-category="hulls" data-child="hullModel">',
      '           <option selected hidden disabled value="title">Модель</option>',
      '         </select>',
      '         <select class="tanki-control" disabled size="1" id="hullModel" name="hullModel" data-parent="hullType">',
      '           <option selected hidden disabled value="title">Грейд</option>',
      '         </select>',,
      '     </div>',
      '   <div class="wrapper">',
      '         Пушка:',
      '         <select class="tanki-control" size="1" id="turretType" name="turretType" data-category="turrets" data-child="turretModel">',
      '           <option selected hidden disabled value="title">Модель</option>',
      '         </select>',
      '         <select class="tanki-control" disabled size="1" id="turretModel" name="turretModel" data-parent="turretType">',
      '           <option selected hidden disabled value="title">Грейд</option>',
      '         </select>',
      '   </div>',
      '   <button class="tanki-control" id="showTank" disabled>Показать</button>',
      ' </div>',
      '</div>'
    ].join('\n');
    
    var modal = null;
    var embedded_id = 'TankPreview';
    
    function fillDropdown(id, isParent){
      var _select = $("#" + id);
      _select.empty();
      var $keys;
      
      if(isParent){
        _select.append($('<option selected hidden disabled value="title">Модель</option>'));
        $keys = $(Object.keys(Viewer.data[_select.data("category")]));
      } else {
        _select.append($('<option selected hidden disabled value="title">Грейд</option>'));
        var _parent = $("#" + _select.data("parent"));
        var key = _parent.find("option:selected").val();
        $keys = $(Object.keys(Viewer.data[_parent.data("category")][key]));
      }
      
      $keys.each(function(k, v) {
        _select.append($('<option value="' + v + '">' + v + '</option>'));
      });
    }
    
    function onTypeChanged(){
      var childId = $(this).data("child");
      fillDropdown(childId, false);
      $("#" + childId).removeAttr("disabled");
    }
    
    function onSelectedChanged(){
      var flag = false;
      $("#TankPreview__controls select").each(function(i, el){
        flag = flag || ($(el).children(":selected").val() == "title");
      });
      if(flag){
        $("#showTank").attr("disabled", "disabled");
      } else {
        $("#showTank").removeAttr("disabled");
      }
    }
  
    function showTank(){
      var tank = Viewer.emptyTank();
      tank.hull.type = $("#hullType option:selected").val();
      tank.turret.type = $("#turretType option:selected").val();
      tank.hull.model = $("#hullModel option:selected").val();
      tank.turret.model = $("#turretModel option:selected").val();
      tank.paint.type = Viewer.currentPaint.type;
      tank.paint.model = Viewer.currentPaint.model;

      $("#TankPreview__viewer").empty().append('<div id="' + embedded_id + '"></div>');
      Viewer.appendViewer(tank, embedded_id);
    }
    
    function showTankPreviewModal(tank){
      modal = new tingle.modal({
        closeMethods: ['button', 'escape', 'overlay'],
        onOpen: function(){
          fillDropdown("hullType", true);
          fillDropdown("turretType", true);
          $("#hullType, #turretType").change(onTypeChanged);
          $("#TankPreview__controls select").change(onSelectedChanged);
          if(isDesktopChrome()){
            $("#TankPreview").append('<a href="https://get.adobe.com/flashplayer">Включить Adobe Flash Player</a>');
          }
          $("#showTank").click(showTank);
        },
        beforeClose: function(){
          $("#hullType, #turretType").off('change');
          $("#TankPreview__controls select").off('change');
          $("#showTank").off('click');
          return true;
        }
      });
      modal.setContent(templateMenu);
      modal.open();
      Viewer.appendViewer(tank, embedded_id);
    }

    $('.showPaint').click(function() {
      Viewer.currentPaint = { 
        "type": $(this).data('paintType'),
        "model": $(this).data('paintModel')
      };
      var tank = Viewer.getRandomTank();
      tank.paint.type = Viewer.currentPaint.type;
      tank.paint.model = Viewer.currentPaint.model;
      showTankPreviewModal(tank);
    });
    
  });
  
}

/*============================================================================================*/
/*Server Online summary*/

if($("#OnlineSummary").length) {
  (function updateOnlineSummary() {
    $.getJSON("https://ru.tankiwiki.com/status.json?param=" + new Date().getTime(), function(data) {
      var online = 0;
      var inbattles = 0;
      for (var node in data.nodes) {
        online += parseInt(data.nodes[node]["online"]);
        inbattles += parseInt(data.nodes[node]["inbattles"]);
      }
      $("#OnlineSummary span:first-of-type").empty().append(getSplitNumber(online));
      $("#OnlineSummary span:last-of-type").empty().append(getSplitNumber(inbattles));
    });
    setTimeout(updateOnlineSummary, 5000);
  })();
}
/*====================================================================================*/
/*RenderModeDetector embedded SWF*/

if($("#RenderModeDetectorSWF").length) {
  $("#RenderModeDetectorSWF").append('<object type="application/x-shockwave-flash" id="RenderModeDetector" data="images/ru/4/4f/NewRenderModeDetector.swf" width="600px" height="300px"><param name="menu" value="false"><param name="scale" value="noScale"><param name="allowFullscreen" value="true"><param name="allowScriptAccess" value="always"><param name="bgcolor" value=""><param name="wmode" value="direct"></object>');
}

/*====================================================================================*/
/*SAFP link*/

if($("#SAFPlink").length) {
  $("#SAFPcopy").click(function(){
    $("<input>").appendTo('body').val($("#SAFPlink").prop('href')).select();
    try {
      document.execCommand('copy');
      $("#SAFPcopy").css({"background-color":"green", "color":"#fff"});
    } catch(err) {
      $("#SAFPcopy").css({"background-color":"red", "color":"#fff"});
    }
  });
}

/*====================================================================================*/
/*RndTxt Template*/

if ($('#RandomTextContainer').length) {
  var facts = $('#RandomTextContainer > div').toArray();
  $(getRandomVal(facts)).show();
  $('#RandomTextRefresher').click(function () {
    $(facts).hide();
    $(getRandomVal(facts)).show();
  })
}

/*====================================================================================*/
/*Homepage Turrets/Hulls Dropdowns show/hide*/

if($("#HomepageDropdowns").length){
  var cwjs_ddl = $(".cwcss_drop-down-list");
  $('.cwcss_drop-down-block').click(function() {
    for(var i = 0; i < cwjs_ddl.length; i++) {
      if(cwjs_ddl[i] == ($(this).next().find('.cwcss_drop-down-list'))[0])
      {
        $(cwjs_ddl[i]).parent().prev().toggleClass("cwcss_rotate180");
        $(cwjs_ddl[i]).slideToggle();
      }
      else
      {
        $(cwjs_ddl[i]).parent().prev().toggleClass("cwcss_rotate180", false);
        $(cwjs_ddl[i]).hide();
      }
    }
  });


  $(document).click(function(event){ 
    if(!$(event.target).hasClass('cwcss_drop-down-list') && !$(event.target).parent().hasClass('cwcss_drop-down-list') && !$(event.target).parent().parent().hasClass('cwcss_drop-down-list') && !$(event.target).parent().hasClass('cwcss_drop-down-block') && !$(event.target).hasClass('cwcss_drop-down-block') && !$(event.target).hasClass('cwcss_drop-down-list-wrapper')) 
    {
      for(var j = 0; j < cwjs_ddl.length; j++)
      {
        if($(cwjs_ddl[j]).is(":visible")) 
        {
          $(cwjs_ddl[j]).parent().prev().toggleClass("cwcss_rotate180", false);
          $(cwjs_ddl[j]).slideUp("fast");
        }
      }
    }     
  });
}

/*====================================================================================*/
/*YouTube Popup*/

if($('.ShowYouTubePopup').length){
  var modal = null;
  $('.ShowYouTubePopup').click(function () {
    showYouTubeModal($(this).data('id'));
  });
  function showYouTubeModal(yid){
    modal = new tingle.modal({
      closeMethods: ['button', 'escape']
    });
    modal.setContent('<div style="background: url(loading.gif) center no-repeat;"><iframe class="yt-video" width="640px" height="360px" src="https://www.youtube.com/embed/' + yid + '" frameborder="0" allowfullscreen></iframe></div>');
    modal.open();
  }
}

/*====================================================================================*/
/*Gif Popup*/

if($('.ShowGifPopup').length){
  var modal = null;
  $('.ShowGifPopup').click(function(e) {
    e.preventDefault();
    showGifModal($(this).attr('href'));
  });
  function showGifModal(src){
    modal = new tingle.modal({
      closeMethods: ['button', 'escape']
    });
    modal.setContent('<img src="' + src + '">');
    modal.open();
  }
}

/*====================================================================================*/
/*Maps*/

if ($(".mapScreenshotsCarousel").length) {
  $('.mapScreenshotsCarousel .carouselContainer').remove();

  $.each($(".mapScreenshotsCarousel .open"), function(k,v) {
    $($(v).children()).detach().insertAfter($(v));
  });
}
/*============================================================================================*/
/*New Pretty Spoiler*/

if ($(".pretty-spoiler").length) {

  var texts = { OPEN: "Развернуть спойлер", CLOSE: "Свернуть спойлер" };
  
  $('.pretty-spoiler > .title').click(function() {
    var content = $(this).next('div');
    changeTitleState($(this), content.is(":visible"));
    content.slideToggle(300);
  });

  function changeTitleState(elem, state) {
    if(state){
      elem.css("background-color", "rgba(255,255,255,0.1)");
      elem.prop('title', texts.OPEN);
    } else {
      elem.css("background-color", "rgba(255,255,255,0.3)");
      elem.prop('title', texts.CLOSE);
    }
    elem.children('.title-arrow').toggleClass('rotate180');
  }
}

/*============================================================================================*/
/*Modules filter*/

if($('#modules-filter').length){
  
  function getFilterMode(){
    return $('.filter-rb:checked').val() == "true";
  }
  
  function toggleModule($el, b){
    if($el.is('tr')) $el.toggleClass('hidden', b);
    if($el.is('td')) $el.toggleClass('not-visible', b);
  }
  
  function applyFilters(){
    var checked = $(this).is(':checked');
    checkboxStates.update();
    $('.filterable.' + this.id).each(function(){
      var $this = $(this);
      var $classes = $($this.prop('class').trim().split(/\s+/)).not(['filterable','hidden','not-visible']);
      if(checked){
        if($classes.not(checkboxStates["checked"]).length == 0 )
          toggleModule($this, false);
        else {
          if(getFilterMode())
            toggleModule($this, true);
          else
            toggleModule($this, false);
        }
      } else {
        if($classes.not(checkboxStates["unchecked"]).length == 0 )
          toggleModule($this, true);
        else {
          if(getFilterMode())
            toggleModule($this, true);
          else
            toggleModule($this, false);
        }
      }
    });
  }
  
  var checkboxStates = {
    "checked": [],
    "unchecked": [],
    "update": function() {
      var _this = this;
      _this["checked"] = [];
      _this["unchecked"] = [];
      $('.filter-cb:not(#all)').each(function(){
        if($(this).is(':checked')) _this["checked"].push(this.id);
        else _this["unchecked"].push(this.id);
      });
    }
  }
  
  $('.filter-cb:not(#all)').change(applyFilters);
  
  $('.filter-cb#all').change(function(){
    var checked = $(this).is(':checked');
    $('.filterable').each(function(){
      toggleModule($(this), !checked);
    });
    $('.filter-cb:not(#all)').prop('checked', checked).change(function(){});
  });
}
/*============================================================================================*/
/*Upgrades calculator*/

if($('.item-upgrades-block').length){
  
  var isMouseDown = false;

  $('.item-upgrades-block').each(function(k,v){
    $(this).append('<span class="calc-mode bg-dark"><input id="calc-cb_' + k + '" type="checkbox"><label for="calc-cb_' + k + '">Режим калькулятора</label><span class="discounts hidden"><label for="calc-discount-step_' + k + '"> Скидка на запуск: </label><input type="number" pattern="[0-9]{1,2}" value="0" min="0" max="95" step="5" class="step" id="calc-discount-step_' + k + '" ">% <label for="calc-discount-speed_' + k + '"> Скидка на ускорение: </label><input type="number" pattern="[0-9]{1,2}" value="0" min="0" max="95" step="5" class="speed" id="calc-discount-speed_' + k + '" ">% <button class="wiki-control grey-gradient reset" >Сбросить</button></span></span>');
    setInitial($(this).find('.item-upgrades-table'));
  });
  
  $(".item-upgrades-block input[type='checkbox']").change(function() {
    var parent = $(this).parents('.item-upgrades-block');
    var table = parent.find('.item-upgrades-table');
    var inputs = parent.find('input[type="number"], input[type="text"]');
    if(this.checked) {
      parent.find('.discounts').show();
      parent.find('.reset').on('click', function(){ reset(parent, table, 'soft'); });
      inputs.on('change keyup input', function(){ 
        $(this).focus();
        applyDiscount(this, parent);
        $(this).focus();
      });
      table.find('.sum').show();
      
      $(['speed','delay','step']).each(function(k,v){
        var n = k + 1;
        table.find("tr:not(.nocalc) td:nth-last-child(" + n + ")").on('mousedown', function(event){ 
          if(event.which == 1 || event.which == undefined) calculate(this, parent, v);
          if(event.which == 1) isMouseDown = true;
          return false;
        }).trigger('mousedown').on('mouseover', function(){
          if(isMouseDown) calculate(this, parent, v);
          return false;
        });
      });
      refreshSumAll(table);

    } else {
      parent.find('.reset').off('click');
      inputs.off('change');
      reset(parent, table, 'hard');
      table.find('.sum').hide();
      parent.find('.discounts').hide();
    }
  });

  function calculate(_this, parent, type) {
    var $this = $(_this);
    $this.toggleClass("highlighted");
    switch(type){
      case 'step':
        var value = parseInt($this.text());
        var td = parent.find('td.step');
        if ($this.hasClass("highlighted")) { td.text(parseInt(td.text()) + value); } 
        else { td.text(parseInt(td.text()) - value); }
        refreshSumAll(parent);
        break;
      case 'speed':
        var value = parseInt($this.text());
        var td = parent.find('td.speed');
        if ($this.hasClass("highlighted")) { td.text(parseInt(td.text()) + value); } 
        else { td.text(parseInt(td.text()) - value); }
        refreshSumAll(parent);
        break;
      case 'delay':
        var td = parent.find('td.delay');
        if ($this.hasClass("highlighted")) { 
          td.text(getDelay(getMinutes(td.text()) + getMinutes($this.text()))); 
        } else { 
          td.text(getDelay(getMinutes(td.text()) - getMinutes($this.text())));
        }
        break;
    }
    return false;
  };
    
  function applyDiscount(_this, parent) {
    var $this = $(_this);
    var _val = $this.val();
    if(parseInt(_val) > 95) $this.val(95);
    if(parseInt(_val.split('')[0]) == 0 && _val.length > 1) $this.val(_val.split('')[1]);
    if(parseInt(_val) < 0 || isNaN(parseInt(_val))) $this.val(0);

    $this.prop('disabled', true);
    var type, tdSum;
    if ($this.hasClass('step')) {
      type = 3;
      tdSum = parent.find('td.step');
    } else if ($this.hasClass('speed')) {
      type = 1;
      tdSum = parent.find('td.speed');
    } else return;

    var cells = parent.find('tr:not(.nocalc) td:nth-last-child(' + type + ')');
    var discount = parseFloat(((100 - parseInt($this.val())) / 100).toFixed(2));
    var sum = 0;
    cells.each(function(){
      var cur = $(this);
      var initialValue = parseInt(cur.data('initial'));
      var newValue = Math.floor(initialValue * discount);
      cur.text(newValue);
      if(cur.hasClass('highlighted')) sum += newValue;
    });
    tdSum.text(sum);
    refreshSumAll(parent);
    $this.prop('disabled', false);
  }
    
  function reset(parent, table, type){
    var cells = getCells(table);
    if(type == 'hard'){
      cells.off('mousedown mouseover');
    }
    parent.find('.discounts input[type="number"]').val('0').text('');
    table.find('td.step').text('0');
    table.find('td.delay').text('0');
    table.find('td.speed').text('0');
    table.find('td.sumAll').text('0');
    cells.each(function(){
      $(this).removeClass('highlighted');
      $(this).text($(this).data('initial'));
    });
  }  
  
  function getCells(table){
    return table.find("tr:not(.nocalc) td:nth-last-child(3),"
                      + "tr:not(.nocalc) td:nth-last-child(2), "
                      + "tr:not(.nocalc) td:nth-last-child(1)"
                     );
  }
  
  function setInitial(table){
    getCells(table).each(function(){
      $(this).data('initial', $(this).text());
    });
  }

  function refreshSumAll(table){
    table.find('td.sumAll').html(
      parseInt(table.find('td.step').text()) + 
      parseInt(table.find('td.speed').text())
    );
  }
  
  function getMinutes(s){
    var res = 0;
    $(s.split(' ')).each(function(){
      if(this.indexOf('д') != -1) {
        res += 24 * 60 * parseInt(this);
      }
      if(this.indexOf('ч') != -1) {
        res += 60 * parseInt(this);
      }
      if(this.indexOf('м') != -1) {
        res += parseInt(this);
      }
    });
    return res;
  }

  function getDelay(time){
    if(time == 0) {
      return 0;
    }
    if(time < 60) {
      return time + 'м';
    }
    if (time >= 60 && time < 1440) {
      var minutes = time % 60;
      var hours = (time - minutes) / 60;
      if (minutes != 0) {
        return hours + 'ч ' + minutes + 'м';
      } else {
        return hours + 'ч';
      }
    }
    if (time >= 1440) {
      var minutes = time % 60;
      var t = (time - minutes) / 60;
      var hours = t % 24;
      var days = (t - hours) / 24;
      if (minutes != 0 && hours != 0) {
        return days + 'д ' + hours + 'ч ' + minutes + 'м';
      }
      if (minutes != 0 && hours == 0) {
        return days + 'д ' + minutes + 'м';
      }
      if (minutes == 0 && hours != 0) {
        return days + 'д ' + hours + 'ч';
      }
      if (minutes == 0 && hours == 0) {
        return days + 'д';
      }
    }
  }
  $(document).mouseup(function () {
    isMouseDown = false;
  });
}

/***********************************************************************************************/

if (mw.config.values.wgPageName === 'Комплекты_товаров') { (function() {
  var hulls = {
    kind: 'hulls',
    values: ['Васп', 'Хорнет', 'Викинг', 'Диктатор', 'Хантер', 'Титан', 'Мамонт']
  };
  var turrets = {
    kind: 'turrets',
    values: ['Огнемёт', 'Фриз', 'Изида', 'Молот', 'Твинс', 'Рикошет', 'Смоки', 'Страйкер', 'Вулкан', 'Гром', 'Рельса', 'Магнум', 'Гаусс', 'Шафт']
  };
  
  function setFilters(checkAll) {
    filters[hulls.kind] = {
      shown: checkAll ? hulls.values.slice() : [],
      hidden: !checkAll ? hulls.values.slice() : [],
    };
    filters[turrets.kind] = {
      shown: checkAll ? turrets.values.slice() : [],
      hidden: !checkAll ? turrets.values.slice() : [],
    };
  }
  
  function applyFilters() {
    filters[hulls.kind].shown.forEach(function(value){
      $('tr[data-kit-hull="'+value+'"]').show();
    });
    filters[turrets.kind].shown.forEach(function(value){
      $('tr[data-kit-turret="'+value+'"]').show();
    });
    filters[hulls.kind].hidden.forEach(function(value){
      $('tr[data-kit-hull="'+value+'"]').hide();
    });
    filters[turrets.kind].hidden.forEach(function(value){
      $('tr[data-kit-turret="'+value+'"]').hide();
    });
  }
  
  function getCheckboxesHtml(entity, checked) {
    var htmlString = '';
    var checkedState = checked ? 'checked' : '';
    entity.values.forEach(function(value) {
      htmlString += '<label class="kit-filter-checkbox"><input class="tanki-control" type="checkbox" '+checkedState+' name="'+entity.kind+'" value="'+value+'">'+value+'</label>';
    });
    return htmlString;
  }
  
  function renderFilters(checked) {  
    var template = [
      '<fieldset>',
      '<legend>Показать комплекты с корпусами</legend>',
      getCheckboxesHtml(hulls, checked),
      '</fieldset>',
      '<fieldset>',
      '<legend>Показать комплекты с пушками</legend>',
      getCheckboxesHtml(turrets, checked),
      '</fieldset>',
      '<button class="tanki-control" id="setChecked">Показать всё</button>',
      '<button class="tanki-control" id="setUnchecked">Сбросить всё</button>',
    ].join('');
    $('#kit-filter').empty().html(template);
  }
  
  function bindListeners() {
    $('#kit-filter :checkbox').change(function() {
      var $this = $(this);
      var value = $this.val();
      var kind = $this.prop('name');
      if ($this.is(':checked')) {
        filters[kind].shown.push(value);
        filters[kind].hidden.splice(filters[kind].hidden.indexOf(value), 1);
      } else {
        filters[kind].hidden.push(value);
        filters[kind].shown.splice(filters[kind].shown.indexOf(value), 1);
      }
      applyFilters();
    });
    
    $('#kit-filter #setChecked').click(function() {
      setState(true);
    });
    $('#kit-filter #setUnchecked').click(function() {
      setState(false);
    });
  }
  
  function unbindListeners() {
    $('#kit-filter :checkbox').off();
    $('#kit-filter #setChecked').off();
    $('#kit-filter #setUnchecked').off();
  }
  
  function setState(flag) {
    setFilters(flag);
    unbindListeners();
    renderFilters(flag);
    bindListeners();
    applyFilters();
  }
  
  var filters = {};
  setFilters(true);
  renderFilters(true);
  bindListeners();
})();
}

/***********************************************************************************************/
if (
  mw.config.values.wgPageName === "Таблица_кланов"
  || mw.config.values.wgPageName === "Список_кланов"
) {
  window.location = "https://tankisport.com/team";
}

if(
  mw.config.values.wgNamespaceNumber === 0
  && mw.config.values.wgArticleId !== 1457
  && mw.config.values.wgArticleId !== 2226
  && mw.config.values.wgArticleId !== 3
  && mw.config.values.wgArticleId !== 634
){
  $('#bodyContent > .actions').append('<div class="vectorTabs customReport" style="float: right;"><ul><li><span><a href="#" title="Сообщить редакторам Вики об ошибке в статье или предложить улучшение">Сообщить</a></span></li></ul></div>');
  $('#mw-content-text').append('<div id="custom-report-footer">Ошибка или опечатка в тексте? Выделите её мышкой и нажмите <kbd>Ctrl</kbd>+<kbd>Enter</kbd>, чтобы сообщить о ней редакторам!</div>');
}

var formTemplate = [
  '<form id="custom-report-form" enctype="multipart/form-data">',
  '  <input type="hidden" name="lang" value="ru">',
  '  <div class="disclaimer">Эта форма НЕ ПРЕДНАЗНАЧЕНА для жалоб на игру и баны.</div>',
  '  <div class="custom-report-nickname">',
  '    <div class="field-description">Ваш игровой ник <span class="red-asterisk"></span></div>',
  '    <input class="tanki-control" type="text" id="field-nickname" autocomplete="off" autofocus maxlength="20" name="nickname">',
  '    <div class="error"></div>',
  '  </div>',
  '  <div class="custom-report-pageurl">',
  '    <div class="field-description">Ссылка на страницу <span class="red-asterisk"></span></div>',
  '    <div class="field-description more">Мы уже заполнили это поле за вас, однако если мы оказались неправы — скопируйте ссылку на нужную страницу из адресной строки браузера и вставьте её сюда.</div>',
  '    <input class="tanki-control" type="text" id="field-pageurl" autocomplete="off" name="pageurl">',
  '    <div class="error"></div>',
  '  </div>',
  '  <div class="custom-report-message">',
  '    <div class="field-description">Ваше сообщение <span class="red-asterisk"></span></div>',
  '    <div class="field-description more">Расскажите нам, что бы вы хотели изменить на указанной странице, или укажите на ошибку или неточность. Можно приложить ссылки на скриншоты.</div>',
  '    <textarea class="tanki-control" id="field-message" name="message" maxlength="1000"></textarea>',
  '    <div class="error"></div>',
  '  </div>',
  '  <div id="recaptcha-wrapper">',
  '    <div class="error"></div>',
  '  </div>',
  '  <div class="custom-report-submit">',
  '    <input class="tanki-control" type="submit" id="button-submit" name="submit" value="Отправить">',
  '  </div>',
  '  <img id="spinner" src="loading.gif">',
  '  <span class="custom-report-result"></span>',
  '</form>'
  ].join('\n');

function isNicknameValid(nickname){
  return (
    typeof nickname == 'string' &&
    new RegExp(/^[a-zA-Z0-9\-\_\.]{1,20}$/).test(nickname) &&
    new RegExp(/^[^\.\-\_](.*[^\.\-\_])?$/).test(nickname) &&
    !new RegExp(/(.)\1{5,}/g).test(nickname) &&
    _checkRepeated(nickname)          
  );
  function _checkRepeated(nick){
    var reg = new RegExp(/[\-\_\.]{2,}/g);
    var matches = nick.match(reg) || [];
    return matches.length > 0 ? (matches.length == 1 && matches[0].length==2 && nick.search(reg)==1) : true;
  }
}

function printError(_for, _message){
  $("#field-" + _for + " + .error").append(_message);
}

function getInputValues(){
  return {
    "nickname": $("#field-nickname").val(),
    "pageurl": $("#field-pageurl").val(),
    "message": $("#field-message").val(),
    "captcha": $("#g-recaptcha-response").val()
  }
}

function validateForm(type, obj){
  if(!(type === 'client' || type === 'server')) return false;
  $(".error").empty();
  if(type == 'server' && obj.status) return true;
  var regex;
  if(type == 'client') regex = new RegExp(/^(https?\:\/\/)?(ru|en|de|pl|br|es)\.tankiwiki\.com\/.*$/);
  var result = true;

  if((type == 'client' && !isNotEmpty(obj.captcha)) || (type == 'server' && obj.errors.indexOf(-1) > -1)){
    $("#recaptcha-wrapper > .error").html("Это поле обязательно для заполнения");
    result = false;
  }
    
  if((type == 'client' && isNotEmpty(obj.nickname)) || (type == 'server' && obj.errors.indexOf(10) == -1)){
    if((type == 'client' && !isNicknameValid(obj.nickname)) || (type == 'server' && obj.errors.indexOf(11) > -1)){
      printError("nickname", "Некорректный ник");
      result = false;
    }
  } else {
    printError("nickname", "Это поле обязательно для заполнения");
    result = false;
  }
      
  if((type == 'client' && isNotEmpty(obj.pageurl)) || (type == 'server' && obj.errors.indexOf(20) == -1)){
    if((type == 'client' && !regex.test(obj.pageurl)) || (type == 'server' && obj.errors.indexOf(21) > -1)){      
      printError("pageurl", "Некорректная ссылка на страницу Вики");
      result = false;
    }
  } else {
    printError("pageurl", "Это поле обязательно для заполнения");
    result = false;
  }
      
  if((type == 'client' && isNotEmpty(obj.message)) || (type == 'server' && obj.errors.indexOf(30) == -1)){
    if((type == 'client' && obj["message"].length > 1000) || (type == 'server' && obj.errors.indexOf(31) > -1)){  
      printError("message", "Длина сообщения превышает 1000 знаков");
      result = false;
    }
  } else {
    printError("message", "Это поле обязательно для заполнения");
    result = false;
  } 
  
  return result;
}

function onFormSubmit(e){
  e.preventDefault();
  if(validateForm('client', getInputValues())){
    $(".custom-report-submit").hide();
    $("#spinner").css('display', 'inline-block');
    $(".custom-report-result").html("Отправка...");
    $.post("custom/wiki_report.php", $("#custom-report-form").serialize(), function(response){
      if(validateForm('server', response)){
        $("#spinner").hide();
        $(".custom-report-result").html("Мы получили ваше сообщение и разберём его в самое ближайшее время. Спасибо!");
        setTimeout(closeModal, 2000);
      } else {
        $("#spinner").hide();
        $(".custom-report-submit").show();
      }
    });
  }
}

var modal = null;

var Recaptcha = {
  id: null,
  container: $('<div id="recaptcha"></div>')[0],
  create: function(){
    if(null === Recaptcha.id) {
      Recaptcha.id = grecaptcha.render(Recaptcha.container, {
        'sitekey' : '6LdZ6D4UAAAAAEnOOpR4RhNNCbgxVnXVacWPQBaS',
        'theme': 'dark'
      });
    } else {
      grecaptcha.reset(Recaptcha.id);
    }
    return Recaptcha.container;
  }
}

function showCustomReportForm(selection){
  modal = new tingle.modal({
    closeMethods: ['button', 'escape'],
    onOpen: function(){
      $("#custom-report-form").submit(onFormSubmit);
      $("#field-pageurl").val(decodeURIComponent(location.href));
      if(typeof selection === 'string'){
        $("#field-message").val('"'+selection+'":\n');
      }
    },
    beforeClose: function(){
      $("#custom-report-form").off('submit');
      return true;
    }
  });
  modal.setContent(formTemplate);
  modal.open();
  $("#recaptcha-wrapper").prepend(Recaptcha.create());
}

function closeModal(){
  modal.close();
}

$(".customReport").click(showCustomReportForm);

$(document).on('keydown', function (e) {
  var text = getSelectedText();
  if(text && (e.metaKey || e.ctrlKey) && e.which === 13 && (!modal || !modal.isOpen())) {
    showCustomReportForm(text);
  }
});

/*============================================================================================*/

/*if($("#add-new-paintpreview").length){
  var paints_url = "images/ru/6/6d/Paints_textures.json";
  var handler_url = "custom/paints_handler.php";
  
  $.get(paints_url + '?v=' + Date.now().toString(), function(json){
    var categoriesList = Object.keys(json);
    var paintsList = [];
    
    $(categoriesList).each(function(k, v){
      $('<option value="' + v + '">' + v + '</option>').appendTo($('#paint-category'));
      paintsList = paintsList.concat(Object.keys(json[v]));
    });
    
    $('#add-new-paintpreview').submit(function(e){
      e.preventDefault();
    
      var formData = {
        "category": $('#paint-category option:selected').val(),
        "name": $('#paint-name').val(),
        "url": $('#texture-url').val()
      };
      if(
        isNotEmpty(formData['category']) &&
        isNotEmpty(formData['name']) &&
        isNotEmpty(formData['url']) &&
        categoriesList.indexOf(formData['category']) > -1 &&
        paintsList.indexOf(formData['name']) == -1 &&
        validateTextureUrl(formData['url']) &&
        validateTextureName(formData['name'])
      ){
        $.post(handler_url, $('#add-new-paintpreview').serialize(), function(response){
          if(response.status){
            alert("Успех, всё готово");
            location.reload();
          } else {
            $('.error').html('Где-то ошибка, проверьте входные данные');
          }
        });
      } else {
        $('.error').html('Где-то ошибка, проверьте входные данные');
      }
    });
  });
  
  function validateTextureUrl(url){
    return (
      typeof url == 'string' &&
      new RegExp(/^(https?\:\/\/)?(ru|en|de|pl|br|es)\.tankiwiki\.com\/(data|images)\/([a-zA-Zа-яА-Я0-9\/\-\_\.]+)(.jpg)$/).test(url)
    );
  }
  
  function validateTextureName(name){
    return (
      typeof name == 'string' &&
      new RegExp(/^[a-zA-Zа-яА-Я0-9\ \-\_\.]{0,50}$/).test(name)
    );
  }

}*/

/*============================================================================================*/
/*jQuery(document).ready() ends here*/
});