Перейти к содержанию

MediaWiki:Common.js

Материал из Horny Jail WIKI

Замечание: Возможно, после публикации вам придётся очистить кэш своего браузера, чтобы увидеть изменения.

  • Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl+F5 или Ctrl+R (⌘+R на Mac)
  • Google Chrome: Нажмите Ctrl+Shift+R (⌘+Shift+R на Mac)
  • Edge: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl+F5
  • Opera: Нажмите Ctrl+F5.
/**
 * Horny Jail Wiki - Enhanced JavaScript
 * Handles tabs, animations, and interactive elements
 */

mw.hook('wikipage.content').add(function ($root) {
  
  // ================== CHAOS TABS SYSTEM ==================
  $root.find('.hj-chaos-container').each(function () {
    var $container = $(this);
    var $buttons = $container.find('.hj-chaos-tab-button');
    var $blocks = $container.find('.hj-chaos-block');

    if (!$buttons.length || !$blocks.length) return;

    var CHAOS_CLASSES = 'chaos-overview chaos-calm chaos-medium chaos-high';

    function activate(key, $btn) {
      // Active button
      $buttons.removeClass('active');
      $btn.addClass('active');

      // Active block with fade animation
      $blocks.removeClass('active').hide();
      var $targetBlock = $blocks.filter('[data-chaos="' + key + '"]');
      $targetBlock.addClass('active').fadeIn(200);

      // Container class for styling
      $container.removeClass(CHAOS_CLASSES).addClass('chaos-' + key);
    }

    // Initialize
    var $activeBtn = $buttons.filter('.active').first();
    if ($activeBtn.length) {
      activate($activeBtn.data('chaos'), $activeBtn);
    } else {
      var $first = $buttons.first();
      activate($first.data('chaos'), $first);
    }

    // Click handlers
    $buttons.off('click.hjChaos').on('click.hjChaos', function () {
      var $btn = $(this);
      activate($btn.data('chaos'), $btn);
    });
  });

  // ================== CARD HOVER EFFECTS ==================
  $root.find('.hj-nav-card').each(function () {
    var $card = $(this);
    
    $card.on('mouseenter', function (e) {
      // Add subtle glow effect on mouse position
      var rect = this.getBoundingClientRect();
      var x = e.clientX - rect.left;
      var y = e.clientY - rect.top;
      
      $card.css({
        '--mouse-x': x + 'px',
        '--mouse-y': y + 'px'
      });
    });
  });

  // ================== ANIMATE ON SCROLL ==================
  if ('IntersectionObserver' in window) {
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          $(entry.target).addClass('hj-visible');
          observer.unobserve(entry.target);
        }
      });
    }, {
      threshold: 0.1,
      rootMargin: '0px 0px -50px 0px'
    });

    $root.find('.hj-animate').each(function () {
      observer.observe(this);
    });
  } else {
    // Fallback for older browsers
    $root.find('.hj-animate').addClass('hj-visible');
  }

  // ================== SMOOTH SCROLL FOR ANCHORS ==================
  $root.find('a[href^="#"]').on('click', function (e) {
    var target = $(this.getAttribute('href'));
    if (target.length) {
      e.preventDefault();
      $('html, body').animate({
        scrollTop: target.offset().top - 100
      }, 500, 'swing');
    }
  });

  // ================== COUNTER ANIMATION ==================
  $root.find('.hj-stat-value[data-count]').each(function () {
    var $this = $(this);
    var countTo = parseInt($this.data('count'), 10);
    
    if (!countTo) return;
    
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          $({ count: 0 }).animate({ count: countTo }, {
            duration: 1500,
            easing: 'swing',
            step: function () {
              $this.text(Math.floor(this.count));
            },
            complete: function () {
              $this.text(countTo);
            }
          });
          observer.unobserve(entry.target);
        }
      });
    }, { threshold: 0.5 });

    observer.observe(this);
  });

  // ================== TOOLTIP SYSTEM ==================
  $root.find('[data-hj-tooltip]').each(function () {
    var $el = $(this);
    var tooltipText = $el.data('hj-tooltip');
    
    var $tooltip = $('<div class="hj-tooltip">' + tooltipText + '</div>');
    $tooltip.css({
      position: 'absolute',
      background: 'rgba(0, 0, 0, 0.9)',
      color: '#fff',
      padding: '8px 12px',
      borderRadius: '6px',
      fontSize: '0.85em',
      zIndex: 9999,
      pointerEvents: 'none',
      opacity: 0,
      transition: 'opacity 0.2s ease',
      maxWidth: '250px',
      whiteSpace: 'normal'
    });
    
    $el.css('position', 'relative');
    
    $el.on('mouseenter', function (e) {
      $('body').append($tooltip);
      var rect = this.getBoundingClientRect();
      $tooltip.css({
        top: rect.top + window.scrollY - $tooltip.outerHeight() - 8,
        left: rect.left + (rect.width / 2) - ($tooltip.outerWidth() / 2),
        opacity: 1
      });
    });
    
    $el.on('mouseleave', function () {
      $tooltip.remove();
    });
  });

  // ================== COLLAPSIBLE SECTIONS ==================
  $root.find('.hj-collapsible-header').on('click', function () {
    var $header = $(this);
    var $content = $header.next('.hj-collapsible-content');
    var $icon = $header.find('.hj-collapsible-icon');
    
    $content.slideToggle(200);
    $header.toggleClass('hj-collapsed');
    
    if ($header.hasClass('hj-collapsed')) {
      $icon.text('▶');
    } else {
      $icon.text('▼');
    }
  });

  // ================== COPY CODE BUTTON ==================
  $root.find('pre').each(function () {
    var $pre = $(this);
    var $btn = $('<button class="hj-copy-btn" title="Скопировать">📋</button>');
    
    $btn.css({
      position: 'absolute',
      top: '8px',
      right: '8px',
      background: 'rgba(255,255,255,0.1)',
      border: 'none',
      borderRadius: '4px',
      padding: '4px 8px',
      cursor: 'pointer',
      opacity: 0,
      transition: 'opacity 0.2s'
    });
    
    $pre.css('position', 'relative');
    $pre.append($btn);
    
    $pre.on('mouseenter', function () {
      $btn.css('opacity', 1);
    }).on('mouseleave', function () {
      $btn.css('opacity', 0);
    });
    
    $btn.on('click', function () {
      var text = $pre.text().replace('📋', '').trim();
      navigator.clipboard.writeText(text).then(function () {
        $btn.text('✓');
        setTimeout(function () {
          $btn.text('📋');
        }, 1500);
      });
    });
  });

  // ================== PARALLAX HERO ==================
  var $hero = $root.find('.hj-hero');
  if ($hero.length) {
    $(window).on('scroll.hjParallax', function () {
      var scrolled = $(window).scrollTop();
      var heroHeight = $hero.outerHeight();
      
      if (scrolled < heroHeight) {
        var parallaxValue = scrolled * 0.3;
        $hero.find('.hj-hero-logo').css('transform', 'translateY(' + (parallaxValue * 0.5) + 'px)');
      }
    });
  }

  // ================== TYPING EFFECT ==================
  $root.find('.hj-typing').each(function () {
    var $el = $(this);
    var text = $el.text();
    var speed = parseInt($el.data('typing-speed'), 10) || 50;
    
    $el.text('');
    $el.css('visibility', 'visible');
    
    var i = 0;
    function type() {
      if (i < text.length) {
        $el.text($el.text() + text.charAt(i));
        i++;
        setTimeout(type, speed);
      }
    }
    
    // Start typing when visible
    var observer = new IntersectionObserver(function (entries) {
      if (entries[0].isIntersecting) {
        type();
        observer.unobserve($el[0]);
      }
    });
    observer.observe($el[0]);
  });

});

// ================== CSS ANIMATIONS (injected) ==================
(function () {
  var style = document.createElement('style');
  style.textContent = `
    .hj-animate {
      opacity: 0;
      transform: translateY(20px);
      transition: opacity 0.6s ease, transform 0.6s ease;
    }
    
    .hj-animate.hj-visible {
      opacity: 1;
      transform: translateY(0);
    }
    
    .hj-animate-delay-1 { transition-delay: 0.1s; }
    .hj-animate-delay-2 { transition-delay: 0.2s; }
    .hj-animate-delay-3 { transition-delay: 0.3s; }
    .hj-animate-delay-4 { transition-delay: 0.4s; }
    
    .hj-collapsible-header {
      cursor: pointer;
      user-select: none;
    }
    
    .hj-collapsible-header:hover {
      opacity: 0.8;
    }
    
    .hj-typing {
      visibility: hidden;
    }
  `;
  document.head.appendChild(style);
})();