MediaWiki:Grabbox.js

From Uncyclopedia, the content-free encyclopedia
Jump to navigation Jump to search

Note: After saving, you have to bypass your browser's cache to see the changes.

  • Internet Explorer: hold down the Ctrl key and click the Refresh or Reload button, or press Ctrl+F5.
  • Firefox: hold down the Shift key while clicking Reload; alternatively press Ctrl+F5 or Ctrl-Shift-R.
  • Opera, Konqueror and Safari users can just click the Reload button.
  • Chrome: press Ctrl+F5 or Shift+F5
$(document).ready(function() {
    var isDragging = false;
    var offsetX, offsetY;
    var $currentBox;
    var originalPosition;
    var $placeholder;

    $(".grabbox-header").on("mousedown", function(e) {
        isDragging = true;
        $currentBox = $(this).closest(".grabbox");
        
        // Safety check
        if (!$currentBox.length) return;
        
        // Store original position type
        originalPosition = $currentBox.css("position");
        
        var currentOffset;
        
        // Create placeholder with same dimensions (only if it doesn't exist yet)
        if (originalPosition !== "fixed" && !$currentBox.data('placeholder')) {
            // Get offset BEFORE inserting placeholder
            currentOffset = $currentBox.offset();
            
            var boxWidth = $currentBox.outerWidth();
            var boxHeight = $currentBox.outerHeight();
            
            $placeholder = $('<div class="grabbox-placeholder"></div>').css({
                width: boxWidth + "px",
                height: boxHeight + "px",
                visibility: "hidden",
                display: $currentBox.css("display")
            });
            
            // Insert placeholder before moving box
            $currentBox.before($placeholder);
            
            // Store reference so we don't create multiple placeholders
            $currentBox.data('placeholder', $placeholder);
            
            // Now set fixed position using viewport-relative coordinates
            if (currentOffset) {
                $currentBox.css({
                    position: "fixed",
                    left: (currentOffset.left - $(window).scrollLeft()) + "px",
                    top: (currentOffset.top - $(window).scrollTop()) + "px",
                    margin: 0,
                    zIndex: 99999
                });
            }
        }
        
        // Remove any transform
        if ($currentBox.css("transform") !== "none") {
            currentOffset = currentOffset || $currentBox.offset();
            if (currentOffset) {
                $currentBox.css({
                    transform: "none",
                    left: (currentOffset.left - $(window).scrollLeft()) + "px",
                    top: (currentOffset.top - $(window).scrollTop()) + "px"
                });
            }
        }
        
        // Calculate offset from click point using viewport-relative coordinates
        offsetX = e.clientX - parseFloat($currentBox.css('left'));
        offsetY = e.clientY - parseFloat($currentBox.css('top'));
        
        $(this).css("cursor", "grabbing");
        $('body').css('user-select', 'none');
        
        e.preventDefault();
        e.stopPropagation();
    });

    $(document).on("mousemove", function(e) {
        if (isDragging && $currentBox) {
            var boxWidth = $currentBox.outerWidth();
            var boxHeight = $currentBox.outerHeight();
            
            // Calculate desired position using viewport-relative coordinates
            var newLeft = e.clientX - offsetX;
            var newTop = e.clientY - offsetY;
            
            // Only apply clamping if #mw-page-base is visible (normal page layout)
            var $pageBase = $('#mw-page-base');
            if (!$pageBase.length || $pageBase.css('display') !== 'none') {
                // Get content area bounds
                var $content = $('#mw-content-text, .mw-parser-output').first();
                if (!$content.length) $content = $('#content');
                
                var contentBounds = $content.offset();
                var contentWidth = $content.outerWidth();
                var contentHeight = $content.outerHeight();
                
                // Convert content bounds to viewport coordinates for clamping
                var viewportContentLeft = contentBounds.left - $(window).scrollLeft();
                var viewportContentTop = contentBounds.top - $(window).scrollTop();
                
                // Clamp to content bounds (in viewport coordinates)
                newLeft = Math.max(viewportContentLeft, 
                                  Math.min(newLeft, viewportContentLeft + contentWidth - boxWidth));
                newTop = Math.max(viewportContentTop, 
                                 Math.min(newTop, viewportContentTop + contentHeight - boxHeight));
            }
            
            $currentBox.css({
                left: newLeft + "px",
                top: newTop + "px"
            });
        }
    });

    $(document).on("mouseup", function() {
        if (isDragging) {
            isDragging = false;
            $(".grabbox-header").css("cursor", "grab");
            $('body').css('user-select', '');
            
            // Placeholder stays - don't remove it
            $currentBox = null;
        }
    });
    
    // Add grab cursor to headers by default
    $(".grabbox-header").css("cursor", "grab");
});