<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko">
	<id>https://wiki.1if.in/index.php?action=history&amp;feed=atom&amp;title=%EC%82%AC%EC%9A%A9%EC%9E%90%3AEllif%2FWikiVault.js</id>
	<title>사용자:Ellif/WikiVault.js - 편집 역사</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.1if.in/index.php?action=history&amp;feed=atom&amp;title=%EC%82%AC%EC%9A%A9%EC%9E%90%3AEllif%2FWikiVault.js"/>
	<link rel="alternate" type="text/html" href="https://wiki.1if.in/index.php?title=%EC%82%AC%EC%9A%A9%EC%9E%90:Ellif/WikiVault.js&amp;action=history"/>
	<updated>2026-06-09T03:15:22Z</updated>
	<subtitle>이 문서의 편집 역사</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://wiki.1if.in/index.php?title=%EC%82%AC%EC%9A%A9%EC%9E%90:Ellif/WikiVault.js&amp;diff=7866&amp;oldid=prev</id>
		<title>Ellif: 새 문서: $(document).ready(function() {     if ($(&quot;#wikivault-floating-button&quot;).length) return;      const WIKI_VAULT = {         MAIN_URI: &#039;https://tedbot.toolforge.org&#039;,         JS_CONTENT_API: &#039;/api/get-js-content&#039;,         INIT_API: &#039;/api/init&#039;,         IS_DEMO: false,         STORAGE_KEYS: {             LAST_MODIFIED: &#039;wikivault_last_modified&#039;,             CACHED_CODE: &#039;wikivault_cached_code&#039;,             BUTTON_POSITION: &#039;wikivault_button_position&#039;         }     };      const FLOAT...</title>
		<link rel="alternate" type="text/html" href="https://wiki.1if.in/index.php?title=%EC%82%AC%EC%9A%A9%EC%9E%90:Ellif/WikiVault.js&amp;diff=7866&amp;oldid=prev"/>
		<updated>2025-05-10T17:25:19Z</updated>

		<summary type="html">&lt;p&gt;새 문서: $(document).ready(function() {     if ($(&amp;quot;#wikivault-floating-button&amp;quot;).length) return;      const WIKI_VAULT = {         MAIN_URI: &amp;#039;https://tedbot.toolforge.org&amp;#039;,         JS_CONTENT_API: &amp;#039;/api/get-js-content&amp;#039;,         INIT_API: &amp;#039;/api/init&amp;#039;,         IS_DEMO: false,         STORAGE_KEYS: {             LAST_MODIFIED: &amp;#039;wikivault_last_modified&amp;#039;,             CACHED_CODE: &amp;#039;wikivault_cached_code&amp;#039;,             BUTTON_POSITION: &amp;#039;wikivault_button_position&amp;#039;         }     };      const FLOAT...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;새 문서&lt;/b&gt;&lt;/p&gt;&lt;div&gt;$(document).ready(function() {&lt;br /&gt;
    if ($(&amp;quot;#wikivault-floating-button&amp;quot;).length) return;&lt;br /&gt;
&lt;br /&gt;
    const WIKI_VAULT = {&lt;br /&gt;
        MAIN_URI: &amp;#039;https://tedbot.toolforge.org&amp;#039;,&lt;br /&gt;
        JS_CONTENT_API: &amp;#039;/api/get-js-content&amp;#039;,&lt;br /&gt;
        INIT_API: &amp;#039;/api/init&amp;#039;,&lt;br /&gt;
        IS_DEMO: false,&lt;br /&gt;
        STORAGE_KEYS: {&lt;br /&gt;
            LAST_MODIFIED: &amp;#039;wikivault_last_modified&amp;#039;,&lt;br /&gt;
            CACHED_CODE: &amp;#039;wikivault_cached_code&amp;#039;,&lt;br /&gt;
            BUTTON_POSITION: &amp;#039;wikivault_button_position&amp;#039;&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const FLOATING_BUTTON_SVG = &amp;#039;&amp;lt;svg xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; viewBox=&amp;quot;0 0 24 24&amp;quot; fill=&amp;quot;none&amp;quot;&amp;gt;&amp;#039; +&lt;br /&gt;
        &amp;#039;&amp;lt;circle cx=&amp;quot;12&amp;quot; cy=&amp;quot;12&amp;quot; r=&amp;quot;10&amp;quot; stroke=&amp;quot;var(--background-color-progressive-subtle)&amp;quot; stroke-width=&amp;quot;1.5&amp;quot; fill=&amp;quot;none&amp;quot;&amp;gt;&amp;lt;/circle&amp;gt;&amp;#039; +&lt;br /&gt;
        &amp;#039;&amp;lt;rect x=&amp;quot;11&amp;quot; y=&amp;quot;9&amp;quot; width=&amp;quot;2&amp;quot; height=&amp;quot;10&amp;quot; transform=&amp;quot;rotate(55 12 12)&amp;quot; fill=&amp;quot;var(--background-color-progressive-subtle)&amp;quot;&amp;gt;&amp;lt;/rect&amp;gt;&amp;#039; +&lt;br /&gt;
        &amp;#039;&amp;lt;path d=&amp;quot;M11.5 4.5h1.5v1.5h-1.5zM14.5 6h1.5v1.5h-1.5zM12.5 7.5h1.5v1.5h-1.5zM9.5 6h1.5v1.5h-1.5z&amp;quot; fill=&amp;quot;var(--background-color-progressive-subtle)&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;&amp;#039; +&lt;br /&gt;
        &amp;#039;&amp;lt;/svg&amp;gt;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
    const BUTTON_STYLES = {&lt;br /&gt;
        position: &amp;#039;fixed&amp;#039;,&lt;br /&gt;
        right: &amp;#039;20px&amp;#039;,&lt;br /&gt;
        top: &amp;#039;50%&amp;#039;,&lt;br /&gt;
        transform: &amp;#039;translateY(-50%)&amp;#039;,&lt;br /&gt;
        width: &amp;#039;50px&amp;#039;,&lt;br /&gt;
        height: &amp;#039;50px&amp;#039;,&lt;br /&gt;
        &amp;#039;background-color&amp;#039;: &amp;#039;#b0c4de&amp;#039;,&lt;br /&gt;
        color: &amp;#039;white&amp;#039;,&lt;br /&gt;
        display: &amp;#039;flex&amp;#039;,&lt;br /&gt;
        &amp;#039;justify-content&amp;#039;: &amp;#039;center&amp;#039;,&lt;br /&gt;
        &amp;#039;align-items&amp;#039;: &amp;#039;center&amp;#039;,&lt;br /&gt;
        &amp;#039;border-radius&amp;#039;: &amp;#039;50%&amp;#039;,&lt;br /&gt;
        cursor: &amp;#039;not-allowed&amp;#039;,&lt;br /&gt;
        opacity: &amp;#039;1.0&amp;#039;,&lt;br /&gt;
        &amp;#039;box-shadow&amp;#039;: &amp;#039;0 2px 3px rgba(0,0,0,0.1)&amp;#039;,&lt;br /&gt;
        &amp;#039;z-index&amp;#039;: &amp;#039;1000&amp;#039;,&lt;br /&gt;
        &amp;#039;touch-action&amp;#039;: &amp;#039;none&amp;#039;&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    function createFloatingButton() {&lt;br /&gt;
        const button = $(&amp;quot;&amp;lt;div&amp;gt;&amp;quot;, {&lt;br /&gt;
            id: &amp;quot;wikivault-floating-button&amp;quot;,&lt;br /&gt;
            html: FLOATING_BUTTON_SVG&lt;br /&gt;
        }).css(BUTTON_STYLES).appendTo(&amp;#039;body&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
        // Load saved position&lt;br /&gt;
        const savedPosition = localStorage.getItem(WIKI_VAULT.STORAGE_KEYS.BUTTON_POSITION);&lt;br /&gt;
        if (savedPosition) {&lt;br /&gt;
            try {&lt;br /&gt;
                const pos = JSON.parse(savedPosition);&lt;br /&gt;
                button.css({&lt;br /&gt;
                    position: &amp;#039;fixed&amp;#039;,&lt;br /&gt;
                    left: pos.left + &amp;#039;px&amp;#039;,&lt;br /&gt;
                    top: pos.top + &amp;#039;px&amp;#039;,&lt;br /&gt;
                    right: &amp;#039;&amp;#039;,&lt;br /&gt;
                    transform: &amp;#039;&amp;#039;&lt;br /&gt;
                });&lt;br /&gt;
            } catch (e) {&lt;br /&gt;
                console.error(&amp;quot;WikiVault: Failed to parse saved button position:&amp;quot;, e);&lt;br /&gt;
                localStorage.removeItem(WIKI_VAULT.STORAGE_KEYS.BUTTON_POSITION);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Make the button draggable&lt;br /&gt;
        var isDragging = false;&lt;br /&gt;
        var offsetX, offsetY;&lt;br /&gt;
        var startX, startY;&lt;br /&gt;
        var DRAG_THRESHOLD = 5; // pixels&lt;br /&gt;
&lt;br /&gt;
        function startDrag(e) {&lt;br /&gt;
            if (e.button === 2) return; // Prevent right-click drag&lt;br /&gt;
            isDragging = false; // Reset dragging state&lt;br /&gt;
            const event = e.originalEvent.touches ? e.originalEvent.touches[0] : e;&lt;br /&gt;
            const buttonRect = button[0].getBoundingClientRect();&lt;br /&gt;
            offsetX = event.clientX - buttonRect.left;&lt;br /&gt;
            offsetY = event.clientY - buttonRect.top;&lt;br /&gt;
            startX = event.clientX;&lt;br /&gt;
            startY = event.clientY;&lt;br /&gt;
            $(&amp;#039;body&amp;#039;).css(&amp;#039;user-select&amp;#039;, &amp;#039;none&amp;#039;);&lt;br /&gt;
            button.data(&amp;#039;original-cursor&amp;#039;, button.css(&amp;#039;cursor&amp;#039;));&lt;br /&gt;
            button.css(&amp;#039;cursor&amp;#039;, &amp;#039;grabbing&amp;#039;);&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function moveDrag(e) {&lt;br /&gt;
            if (!startX || !startY) return;&lt;br /&gt;
            &lt;br /&gt;
            const event = e.originalEvent.touches ? e.originalEvent.touches[0] : e;&lt;br /&gt;
            &lt;br /&gt;
            // Calculate distance from start point&lt;br /&gt;
            const dx = event.clientX - startX;&lt;br /&gt;
            const dy = event.clientY - startY;&lt;br /&gt;
            const distance = Math.sqrt(dx * dx + dy * dy);&lt;br /&gt;
            &lt;br /&gt;
            // Only start dragging if we&amp;#039;ve moved beyond the threshold&lt;br /&gt;
            if (!isDragging &amp;amp;&amp;amp; distance &amp;gt; DRAG_THRESHOLD) {&lt;br /&gt;
                isDragging = true;&lt;br /&gt;
                button.data(&amp;#039;dragging&amp;#039;, true);&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            if (!isDragging) return;&lt;br /&gt;
            &lt;br /&gt;
            const viewportWidth = $(window).width();&lt;br /&gt;
            const viewportHeight = $(window).height();&lt;br /&gt;
            const buttonWidth = button.outerWidth();&lt;br /&gt;
            const buttonHeight = button.outerHeight();&lt;br /&gt;
&lt;br /&gt;
            var newLeft = event.clientX - offsetX;&lt;br /&gt;
            var newTop = event.clientY - offsetY;&lt;br /&gt;
&lt;br /&gt;
            // Ensure button stays within viewport&lt;br /&gt;
            newLeft = Math.max(0, Math.min(newLeft, viewportWidth - buttonWidth));&lt;br /&gt;
            newTop = Math.max(0, Math.min(newTop, viewportHeight - buttonHeight));&lt;br /&gt;
&lt;br /&gt;
            button.css({&lt;br /&gt;
                position: &amp;#039;fixed&amp;#039;,&lt;br /&gt;
                left: newLeft + &amp;#039;px&amp;#039;,&lt;br /&gt;
                top: newTop + &amp;#039;px&amp;#039;,&lt;br /&gt;
                right: &amp;#039;auto&amp;#039;,&lt;br /&gt;
                transform: &amp;#039;none&amp;#039;&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            e.preventDefault();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function endDrag() {&lt;br /&gt;
            if (!isDragging) {&lt;br /&gt;
                // console.log(&amp;quot;Button clicked&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            isDragging = false;&lt;br /&gt;
            button.data(&amp;#039;dragging&amp;#039;, false);&lt;br /&gt;
            startX = null;&lt;br /&gt;
            startY = null;&lt;br /&gt;
&lt;br /&gt;
            const pos = {&lt;br /&gt;
                left: parseInt(button.css(&amp;#039;left&amp;#039;)),&lt;br /&gt;
                top: parseInt(button.css(&amp;#039;top&amp;#039;))&lt;br /&gt;
            };&lt;br /&gt;
            localStorage.setItem(WIKI_VAULT.STORAGE_KEYS.BUTTON_POSITION, JSON.stringify(pos));&lt;br /&gt;
&lt;br /&gt;
            $(&amp;#039;body&amp;#039;).css(&amp;#039;user-select&amp;#039;, &amp;#039;&amp;#039;);&lt;br /&gt;
            button.css(&amp;#039;cursor&amp;#039;, button.data(&amp;#039;original-cursor&amp;#039;));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Event listeners&lt;br /&gt;
        button.on(&amp;#039;mousedown touchstart&amp;#039;, startDrag);&lt;br /&gt;
        $(document).on(&amp;#039;mousemove touchmove&amp;#039;, moveDrag);&lt;br /&gt;
        $(document).on(&amp;#039;mouseup touchend&amp;#039;, endDrag);&lt;br /&gt;
&lt;br /&gt;
        // Handle window resize&lt;br /&gt;
        $(window).on(&amp;#039;resize&amp;#039;, function() {&lt;br /&gt;
            const savedPosition = localStorage.getItem(WIKI_VAULT.STORAGE_KEYS.BUTTON_POSITION);&lt;br /&gt;
            if (savedPosition) {&lt;br /&gt;
                try {&lt;br /&gt;
                    const pos = JSON.parse(savedPosition);&lt;br /&gt;
                    const viewportWidth = $(window).width();&lt;br /&gt;
                    const viewportHeight = $(window).height();&lt;br /&gt;
                    const buttonWidth = button.outerWidth();&lt;br /&gt;
                    const buttonHeight = button.outerHeight();&lt;br /&gt;
&lt;br /&gt;
                    // Ensure button stays within viewport&lt;br /&gt;
                    const newLeft = Math.min(pos.left, viewportWidth - buttonWidth);&lt;br /&gt;
                    const newTop = Math.min(pos.top, viewportHeight - buttonHeight);&lt;br /&gt;
&lt;br /&gt;
                    button.css({&lt;br /&gt;
                        left: newLeft + &amp;#039;px&amp;#039;,&lt;br /&gt;
                        top: newTop + &amp;#039;px&amp;#039;,&lt;br /&gt;
                        right: &amp;#039;&amp;#039;,&lt;br /&gt;
                        transform: &amp;#039;&amp;#039;&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    // Update saved position if it was adjusted&lt;br /&gt;
                    if (newLeft !== pos.left || newTop !== pos.top) {&lt;br /&gt;
                        localStorage.setItem(WIKI_VAULT.STORAGE_KEYS.BUTTON_POSITION, &lt;br /&gt;
                            JSON.stringify({ left: newLeft, top: newTop }));&lt;br /&gt;
                    }&lt;br /&gt;
                } catch (e) {&lt;br /&gt;
                    console.error(&amp;quot;WikiVault: Failed to handle resize:&amp;quot;, e);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        window.dispatchEvent(new Event(&amp;#039;resize&amp;#039;));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getWikiVaultUri(api) {&lt;br /&gt;
        return WIKI_VAULT.MAIN_URI + api;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function decodeResponse(response) {&lt;br /&gt;
        return response.split(&amp;quot;&amp;quot;).map(function(char) {&lt;br /&gt;
            return String.fromCharCode(char.charCodeAt(0) - 3);&lt;br /&gt;
        }).join(&amp;quot;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function executeCode(code) {&lt;br /&gt;
        try {&lt;br /&gt;
            const decodedResponse = decodeResponse(code);&lt;br /&gt;
            new Function(decodedResponse)();&lt;br /&gt;
        } catch (e) {&lt;br /&gt;
            console.error(&amp;quot;Script Execution Error:&amp;quot;, e);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadAndExecuteScript() {&lt;br /&gt;
        if (WIKI_VAULT.IS_DEMO) return;&lt;br /&gt;
&lt;br /&gt;
        $.ajax({&lt;br /&gt;
            url: getWikiVaultUri(WIKI_VAULT.INIT_API),&lt;br /&gt;
            type: &amp;#039;GET&amp;#039;,&lt;br /&gt;
            success: function(initResponse) {&lt;br /&gt;
                const serverLastModified = Math.floor(initResponse.lastModified);&lt;br /&gt;
                const cachedLastModified = localStorage.getItem(WIKI_VAULT.STORAGE_KEYS.LAST_MODIFIED);&lt;br /&gt;
                const cachedCode = localStorage.getItem(WIKI_VAULT.STORAGE_KEYS.CACHED_CODE);&lt;br /&gt;
&lt;br /&gt;
                if (cachedCode &amp;amp;&amp;amp; cachedLastModified &amp;amp;&amp;amp; serverLastModified === Number(cachedLastModified)) {&lt;br /&gt;
                    executeCode(cachedCode);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                $.ajax({&lt;br /&gt;
                    url: getWikiVaultUri(WIKI_VAULT.JS_CONTENT_API),&lt;br /&gt;
                    type: &amp;#039;GET&amp;#039;,&lt;br /&gt;
                    dataType: &amp;#039;text&amp;#039;,&lt;br /&gt;
                    success: function(response) {&lt;br /&gt;
                        localStorage.setItem(WIKI_VAULT.STORAGE_KEYS.CACHED_CODE, response);&lt;br /&gt;
                        localStorage.setItem(WIKI_VAULT.STORAGE_KEYS.LAST_MODIFIED, serverLastModified);&lt;br /&gt;
                        executeCode(response);&lt;br /&gt;
                    },&lt;br /&gt;
                    error: function(xhr, status, error) {&lt;br /&gt;
                        console.error(&amp;quot;Script Fetch Failed:&amp;quot;, status, error);&lt;br /&gt;
                        if (cachedCode) {&lt;br /&gt;
                            executeCode(cachedCode);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            },&lt;br /&gt;
            error: function(xhr, status, error) {&lt;br /&gt;
                console.error(&amp;quot;Init Request Failed:&amp;quot;, status, error);&lt;br /&gt;
                const cachedCode = localStorage.getItem(WIKI_VAULT.STORAGE_KEYS.CACHED_CODE);&lt;br /&gt;
                if (cachedCode) {&lt;br /&gt;
                    executeCode(cachedCode);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    createFloatingButton();&lt;br /&gt;
    loadAndExecuteScript();&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Ellif</name></author>
	</entry>
</feed>