代码之家  ›  专栏  ›  技术社区  ›  kolrie

有没有办法在浏览器中“热插拔”JavaScript代码?

  •  16
  • kolrie  · 技术社区  · 16 年前

    是否有任何工具可以让您在执行网页时“热交换”JavaScript内容?

    我正在寻找类似HotSpot为Java所做的事情,一种不用重新加载整个页面就可以“热部署”新JS代码的方法。

    外面有类似的东西吗?

    在人们不理解“热插拔”时进行澄清,如 :

    “热插拔”是指允许我更改页面本身及其.js文件中包含的部分代码。

    这种方法将简化调试和错误修复,因为您不需要重新加载页面并从头开始交互。

    6 回复  |  直到 16 年前
        1
  •  4
  •   Erlend Halvorsen    16 年前

    有趣的想法:)

    我编写了以下bookmarklet:

    function reload(){var scripts=document.getElementsByTagName("script");var head=document.getElementsByTagName("head")[0];var newScripts=[];var removeScripts=[];for(var i=0;i<scripts.length;i++){var parent=scripts[i].parentNode;if(parent==head&&scripts[i].src){var newScript={};newScript.src=scripts[i].src;newScript.innerHTML=scripts[i].innerHTML;newScripts.push(newScript);removeScripts.push(scripts[i]);}}for(var i=0;i<removeScripts.length;i++){head.removeChild(removeScripts[i]);}for(var i=0;i<newScripts.length;i++){var script=document.createElement("script");script.src=newScripts[i].src;script.type="text/javascript";script.innerHTML=newScripts[i].innerHTML;head.appendChild(script);}}
    

    将其添加到新书签的位置,它将重新加载<头>。不确定这在实践中会有多好,但值得一试:)我想你在编写脚本时必须非常小心,以免多次将内容添加到页面正文中,等等。也许支持“reload=”true“属性会很有用,这样你就可以只将库标记为可重新加载。

    完整资料来源:

    function reload() {
        var scripts = document.getElementsByTagName("script");
        var head = document.getElementsByTagName("head")[0];
        var newScripts = [];
        var removeScripts = [];
        for(var i=0; i < scripts.length; i++) {
            var parent = scripts[i].parentNode;
            if(parent == head && scripts[i].src) {
                var newScript = {};
                newScript.src = scripts[i].src;
                newScript.innerHTML = scripts[i].innerHTML;
                newScripts.push(newScript);
                removeScripts.push(scripts[i]);
            }
        }
    
        for(var i=0; i < removeScripts.length; i++) {
            head.removeChild(removeScripts[i]);
        }
    
        for(var i=0; i < newScripts.length; i++) {
            var script = document.createElement("script");
            script.src = newScripts[i].src;
            script.type = "text/javascript";
            script.innerHTML = newScripts[i].innerHTML;
            head.appendChild(script);
        }
    }
    
        2
  •  3
  •   geoathome    10 年前

    hotswap.js

    希望能有帮助。

    使现代化 :我已将完整库源附加到此处。要使用它,只需将内容复制到一个文件(例如:hotswap.js)中,并将脚本标记插入您的网站,如下所示:

    <script src="hotswap.js"></script>
    

    应用程序编程接口:

    // refresh .js files
    hotswap.refreshAllJs(arrExcludedFiles);
    hotswap.refreshJs(arrIncludedFiles);
    
    // refresh .css files
    hotswap.refreshAllCss(arrExcludedFiles);
    hotswap.refreshCss(arrIncludedFiles);
    
    // refresh images
    hotswap.refreshAllImg(arrExcludedFiles);
    hotswap.refreshImg(arrIncludedFiles);
    
    // show a gui (this is optional and not required for hotswap to work) (Click on the "H").
    hotswap.createGui();
    
    // Examples:
    // refresh all .js files
    hotswap.refreshAllJs();
    
    // refresh main.css only
    hotswap.refreshCss( ["main.js"] );
    
    // refresh all images (img tags) except "dont-refreh-me.png".
    hotswap.refreshAllImg( ["dont-refreh-me.png"] );
    

    完整来源(0.2.0版):

    我不得不删除所有评论,使其低于30000字符的回答限制。 我知道内联html+css很难看,但我想把它保存在一个.js文件中。

    (function() {
        var root = this;
        var previousHotswap = root.hotswap;
        var hotswap = function()
        {
            if (!(this instanceof hotswap))
            {
                return new hotswap();
            }
            else
            {
                return this;
            }
        };
        root.hotswap = hotswap();
        hotswap.prototype.VERSION = '0.2.0';
        hotswap.prototype.RND_PARAM_NAME = 'hs982345jkasg89zqnsl';
        hotswap.prototype.FILE_REMOVAL_DELAY = 400;
        hotswap.prototype.CSS_HTML_PREFIX = 'hs982345jkasg89zqnsl';
        hotswap.prototype._prefix = false;
        hotswap.prototype._prefixCache = [];
        hotswap.prototype._guiCache = {};
        hotswap.prototype._guiGuiRefreshInterval = null;
        hotswap.prototype._guiHtml = '' +
            '<style type="text/css">'+
            '    #PREFIX'+
            '    {'+
            '        display: block;'+
            '        position: fixed;'+
            '        top: 20%;/*distance from top*/'+
            '        right: 0;'+
            '        z-index: 99999;'+
            '        width: 20em;'+
            '        height: auto;'+
            '        color: black;'+
            '        background-color: #666666;'+
            '        font-family: Verdana, sans-serif;'+
            '        font-size: 0.8em;'+
            '        -webkit-box-shadow: 0 0px 0.3em 0.1em #999999;'+
            '        -moz-box-shadow: 0 0px 0.3em 0.1em #999999;'+
            '        box-shadow: 0 0px 0.3em 0.1em #999999;'+
            '    }'+
            '    #PREFIX.mini'+
            '    {'+
            '        width: 2.9em;'+
            '        height: 2.9em;'+
            '        overflow:hidden;'+
            '    }'+
            '    #PREFIX.mini .PREFIX-header input, #PREFIX.mini .PREFIX-list, #PREFIX.mini .PREFIX-footer'+
            '    {'+
            '        display:none;'+
            '    }'+
            '        #PREFIX.mini .PREFIX-header div'+
            '    {'+
            '        display: block;'+
            '        width: 100%;'+
            '        height: 100%;'+
            '    }'+
            '    #PREFIX input'+
            '    {'+
            '        font-size: 1.0em;'+
            '        border: 0.1em solid #999999;'+
            '        border-radius: 0.2em;'+
            '        padding: 0.2em 0.1em;'+
            '        }'+
            '    #PREFIX .PREFIX-header'+
            '    {'+
            '        height: 2.4em;'+
            '        overflow:hidden;'+
            '        padding: 0.4em;'+
            '        color: white;'+
            '        background-color: black;'+
            '        }'+
            '    #PREFIX .PREFIX-header input'+
            '    {'+
            '        width: 83.5%;'+
            '        height: 1.6em;'+
            '    }'+
            '    #PREFIX .PREFIX-header div'+
            '    {'+
            '        position: absolute;'+
            '        top:0;'+
            '        right:0;'+
            '        width: 14.5%;'+
            '        height: 1.6em;'+
            '        line-height: 1.4em;'+
            '        text-align: center;'+
            '        font-size: 2em;'+
            '        font-weight: bold;'+
            '        cursor: pointer;'+
            '    }'+
            '    #PREFIX .PREFIX-header div:hover'+
            '    {'+
            '        background-color: #444444;'+
            '    }'+
            '    #PREFIX .PREFIX-list'+
            '    {'+
            '        width: 100%;'+
            '        height: 22em;'+
            '        overflow: auto;'+
            '    }'+
            '    #PREFIX ul'+
            '    {'+
            '        list-style-type: none;'+
            '        list-style-position: inside;'+
            '        padding: 0;'+
            '        margin: 0.5em 0.5em 1.2em 0.5em;'+
            '    }'+
            '    #PREFIX ul li'+
            '    {'+
            '        margin: 0.3em;'+
            '        padding: 0.5em 0.5em;'+
            '        color: white;'+
            '        background-color: #717171;'+
            '        font-size: 0.9em;'+
            '        line-height: 1.5em;'+
            '        cursor: pointer;'+
            '    }'+
            '    #PREFIX ul li:hover'+
            '    {'+
            '        background-color: #797979;'+
            '    }'+
            '    #PREFIX ul li.template'+
            '    {'+
            '        display: none;'+
            '    }'+
            '    #PREFIX ul li.active'+
            '    {'+
            '        background-color: black;'+
            '    }'+
            '    #PREFIX ul li.PREFIX-headline'+
            '    {'+
            '        color: white;'+
            '        background-color: transparent;'+
            '        text-align: center;'+
            '        font-weight: bold;'+
            '        cursor: default;'+
            '    }'+
            '    #PREFIX .PREFIX-footer'+
            '    {'+
            '        padding: 0;'+
            '        margin:0;'+
            '        background-color: #444444;'+
            '    }'+
            '    #PREFIX .PREFIX-footer ul'+
            '    {'+
            '        margin: 0;'+
            '        padding: 0.5em;'+
            '    }'+
            '    #PREFIX .PREFIX-footer ul li'+
            '    {'+
            '        color: white;'+
            '        background-color: black;'+
            '        font-size: 1.0em;'+
            '        border-radius: 0.5em;'+
            '        text-align: center;'+
            '        height: 2.2em;'+
            '        line-height: 2.2em;'+
            '    }'+
            '    #PREFIX .PREFIX-footer ul li input.PREFIX-seconds'+
            '    {'+
            '        text-align: center;'+
            '        width: 2em;'+
            '    }'+
            '    #PREFIX .PREFIX-footer ul li:hover'+
            '    {'+
            '        background-color: #222222;'+
            '        }'+
            '    #PREFIX .PREFIX-footer ul li.inactive'+
            '    {'+
            '        background-color: #666666;'+
            '        cursor: default;'+
            '    }'+
            '    </style>'+
            '    <div id="PREFIX" class="mini">'+
            '        <div class="PREFIX-header">'+
            '            <input id="PREFIX-prefix" placeholder="prefix" type="text" name="" />'+
            '            <div id="PREFIX-toggle">H</div>'+
            '        </div>'+
            '        <div class="PREFIX-list">'+
            '            <ul id="PREFIX-css">'+
            '                <li class="PREFIX-headline">CSS</li>'+
            '                <li class="template"></li>'+
            '            </ul>'+
            '            <ul id="PREFIX-js">'+
            '                <li class="PREFIX-headline">JS</li>'+
            '                <li class="template"></li>'+
            '            </ul>'+
            '            <ul id="PREFIX-img">'+
            '                <li class="PREFIX-headline">IMG</li>'+
            '                <li class="template"></li>'+
            '            </ul>'+
            '        </div>'+
            '        <div class="PREFIX-footer">'+
            '            <ul>'+
            '                <li id="PREFIX-submit-selected">refresh selected</li>'+
            '                <li id="PREFIX-submit-start">refresh every <input  class="PREFIX-seconds" type="text" value="1" /> sec.</li>'+
            '                <li id="PREFIX-submit-stop" class="inactive">stop refreshing</li>'+
            '                <li id="PREFIX-submit-refresh-list">refresh list</li>'+
            '            </ul>'+
            '        </div>'+
            '    </div>';
        var
            xGetElementById       = function(sId){ return document.getElementById(sId) },
            xGetElementsByTagName = function(sTags){ return document.getElementsByTagName(sTags) },
            xAppendChild          = function(parent, child){ return parent.appendChild(child) },
            xCloneNode            = function(node){ return document.cloneNode(node) },
            xCreateElement        = function(sTag){ return document.createElement(sTag) },
            xCloneNode            = function(ele, deep){ return ele.cloneNode(deep) },
            xRemove = function(ele)
            {
                if( typeof ele.parentNode != "undefined" && ele.parentNode )
                {
                    ele.parentNode.removeChild( ele );
                }
            },
            xAddEventListener = function(ele, sEvent, fn, bCaptureOrBubble)
            {
                if( xIsEmpty(bCaptureOrBubble) )
                {
                    bCaptureOrBubble = false;
                }
                if (ele.addEventListener)
                {
                    ele.addEventListener(sEvent, fn, bCaptureOrBubble);
                    return true;
                }
                else if (ele.attachEvent)
                {
                    return ele.attachEvent('on' + sEvent, fn);
                }
                else
                {
                    ele['on' + sEvent] = fn;
                }
            },
            xStopPropagation = function(evt)
            {
                if (evt && evt.stopPropogation)
                {
                    evt.stopPropogation();
                }
                else if (window.event && window.event.cancelBubble)
                {
                    window.event.cancelBubble = true;
                }
            },
            xPreventDefault = function(evt)
            {
                if (evt && evt.preventDefault)
                {
                    evt.preventDefault();
                }
                else if (window.event && window.event.returnValue)
                {
                    window.eventReturnValue = false;
                }
            },
            xContains = function(sHaystack, sNeedle)
            {
                return sHaystack.indexOf(sNeedle) >= 0
            },
            xStartsWith = function(sHaystack, sNeedle)
            {
                return sHaystack.indexOf(sNeedle) === 0
            },
            xReplace = function(sHaystack, sNeedle, sReplacement)
            {
                if( xIsEmpty(sReplacement) )
                {
                    sReplacement = "";
                }
                return sHaystack.split(sNeedle).join(sReplacement);
            },
            xGetAttribute = function(ele, sAttr)
            {
                var result = (ele.getAttribute && ele.getAttribute(sAttr)) || null;
                if( !result ) {
                    result = ele[sAttr];
                }
                if( !result ) {
                    var attrs = ele.attributes;
                    var length = attrs.length;
                    for(var i = 0; i < length; i++)
                        if(attrs[i].nodeName === sAttr)
                            result = attrs[i].nodeValue;
                }
                return result;
            },
            xSetAttribute = function(ele, sAttr, value)
            {
                if(ele.setAttribute)
                {
                    ele.setAttribute(sAttr, value)
                }
                else
                {
                    ele[sAttr] = value;
                }
            },
            xGetParent = function(ele)
            {
                return ele.parentNode || ele.parentElement;
            },
            xInsertAfter = function( refEle, newEle )
            {
                return xGetParent(refEle).insertBefore(newEle, refEle.nextSibling);
            },
            xBind = function(func, context)
            {
                if (Function.prototype.bind && func.bind === Function.prototype.bind)
                {
                    return func.bind(context);
                }
                else
                {
                    return function() {
                        if( arguments.length > 2 )
                        {
                            return func.apply(context, arguments.slice(2));
                        }
                        else
                        {
                            return func.apply(context);
                        }
                    };
                }
            },
            xIsEmpty = function(value)
            {
                var ret = true;
                if( value instanceof Object )
                {
                    for(var i in value){ if(value.hasOwnProperty(i)){return false}}
                    return true;
                }
                ret = typeof value === "undefined" || value === undefined || value === null || value === "";
                return ret;
            },
            xAddClass = function(ele, sClass)
            {
                var clazz = xGetAttribute( ele, "class" );
                if( !xHasClass(ele, sClass) )
                {
                    xSetAttribute( ele, "class", clazz + " " + sClass );
                }
            },
            xRemoveClass = function(ele, sClass)
            {
                var clazz = xGetAttribute( ele, "class" );
                if( xHasClass(ele, sClass) )
                {
                    xSetAttribute( ele, "class", xReplace( clazz, sClass, "" ) );
                }
            },
            xHasClass = function(ele, sClass)
            {
                var clazz = xGetAttribute( ele, "class" );
                return !xIsEmpty(clazz) && xContains( clazz, sClass );
            };
        hotswap.prototype._recreate = function( type, xcludedFiles, xcludeComparator, nDeleteDelay, bForceRecreation )
        {
            if( typeof nDeleteDelay == "undefined")
            {
                nDeleteDelay = 0;
            }
    
            if( typeof bForceRecreation == "undefined")
            {
                bForceRecreation = false;
            }
    
            var tags = this._getFilesByType(type, xcludedFiles, xcludeComparator);
            var newTags = [];
            var removeTags = [];
            var i, src, detected, node, srcAttributeName;
            for(i=0; i<tags.length; i++)
            {
                node = tags[i].node;
                srcAttributeName = tags[i].srcAttributeName;
                var newNode = {
                    node: null,
                    oldNode: node,
                    parent: xGetParent(node)
                };
                if( bForceRecreation )
                {
                    newNode.node = xCreateElement("script");
                }
                else
                {
                    newNode.node = xCloneNode(node, false);
                }
                for (var p in node) {
                    if (node.hasOwnProperty(p)) {
                        newNode.node.p = node.p;
                    }
                }
                src = xGetAttribute( node, srcAttributeName );
                xSetAttribute( newNode.node, srcAttributeName, this._updatedUrl(src) );
                newTags.push(newNode);
                removeTags.push(node);
            }
            for(var i=0; i < newTags.length; i++) {
                xInsertAfter(newTags[i].oldNode, newTags[i].node);
            }
            if( nDeleteDelay > 0 )
            {
                for(var i=0; i < removeTags.length; i++) {
                    xSetAttribute(removeTags[i], "data-hotswap-deleted", "1");
                }
    
                setTimeout( function() {
                    for(var i=0; i < removeTags.length; i++) {
                        xRemove(removeTags[i]);
                    }
                }, nDeleteDelay);
            }
            else
            {
                for(var i=0; i < removeTags.length; i++) {
                    xRemove(removeTags[i]);
                }
            }
        };
        hotswap.prototype._reload = function( type, xcludedFiles, xcludeComparator )
        {
            var tags = this._getFilesByType(type, xcludedFiles, xcludeComparator);
            var i, src, node, srcAttributeName;
            for(i=0; i<tags.length; i++)
            {
                node = tags[i].node;
                srcAttributeName = tags[i].srcAttributeName;
                // update the src property
                src = xGetAttribute( node, srcAttributeName );
                xSetAttribute( node, srcAttributeName, this._updatedUrl(src) );
            }
        };
        hotswap.prototype._getFilesByType = function( type, xcludedFiles, xcludeComparator )
        {
            var files;
            switch(type)
            {
                case "css":
                    files = this._getFiles(
                        "css",
                        "link",
                        function(ele)
                        {
                            return (xGetAttribute(ele, "rel") == "stylesheet" || xGetAttribute(ele, "type") == "text/css");
                        },
                        "href",
                        xcludedFiles,
                        xcludeComparator
                    )
                    break;
    
                case "js":
                    files = this._getFiles(
                        "js",
                        "script",
                        function(ele)
                        {
                            return (xGetAttribute(ele, "type") == "" || xGetAttribute(ele, "type") == "text/javascript");
                        },
                        "src",
                        xcludedFiles,
                        xcludeComparator
                    )
                    break;
    
                case "img":
                    files = this._getFiles(
                        "img",
                        "img",
                        function(ele)
                        {
                            return (xGetAttribute(ele, "src") != "");
                        },
                        "src",
                        xcludedFiles,
                        xcludeComparator
                    )
                    break;
            }
    
            return files;
        }
        hotswap.prototype._getFiles = function( type, tagName, tagFilterFunc, srcAttributeName, xcludedFiles, xcludeComparator )
        {
            if( typeof xcludedFiles == "undefined" || !xcludedFiles)
            {
                xcludedFiles = [];
            }
    
            if( typeof xcludeComparator == "undefined" || !xcludeComparator)
            {
                xcludeComparator = false;
            }
    
            var fileNodes = [];
            var tags = xGetElementsByTagName(tagName);
            var src, detected, node;
            for(var i=0; i<tags.length; i++) {
                node = tags[i];
                src = xGetAttribute(node,[srcAttributeName]);
                if( xIsEmpty( xGetAttribute(node, "data-hotswap-deleted") ) )
                {
                    if(src && tagFilterFunc(node))
                    {
                        detected = false;
                        for(var j=0; j<xcludedFiles.length; j++) {
                            if( xContains(src,xcludedFiles[j]) )
                            {
                                detected = true;
                                break;
                            }
                        }
                        if( detected == xcludeComparator )
                        {
                            fileNodes.push({
                                type: type,
                                node : node,
                                tagName : tagName,
                                srcAttributeName : srcAttributeName
                            });
                        }
                    }
                }
            }
    
            return fileNodes;
        };
        hotswap.prototype._updatedUrl = function( url, getCleanUrl )
        {
            var cleanUrl;
            if( typeof getCleanUrl == "undefined")
            {
                getCleanUrl = false;
            }
            url = cleanUrl = url.replace(new RegExp("(\\?|&)"+this.RND_PARAM_NAME+"=[0-9.]*","g"), "");
            var queryString = "", randomizedQueryString = "";
            if( xContains(url, "?") )
            {
                if(xContains(url, "&" + this.RND_PARAM_NAME))
                {
                    queryString = url.split("&" + this.RND_PARAM_NAME).slice(1,-1).join("");
                }
                randomizedQueryString = queryString + "&" + this.RND_PARAM_NAME + "=" + Math.random() * 99999999;
            }
            else
            {
                if(xContains(url, "?" + this.RND_PARAM_NAME))
                {
                    queryString = url.split("?" + this.RND_PARAM_NAME).slice(1,-1).join("");
                }
                randomizedQueryString = queryString + "?" + this.RND_PARAM_NAME + "=" + Math.random() * 99999999;
            }
            var foundAt = -1;
            if( !xIsEmpty( this._prefixCache ) )
            {
                for(var i=0; i<this._prefixCache.length; ++i)
                {
                    if( !xIsEmpty(this._prefixCache[i]) && foundAt < 0 )
                    {
                        for(var h=0; h<this._prefixCache[i].length; ++h)
                        {
                            if( this._prefixCache[i][h] == cleanUrl + queryString )
                            {
                                cleanUrl = this._prefixCache[i][0];
                                foundAt = i;
                                break;
                            }
                        }
                    }
                }
            }
    
            var prefixHistory = [cleanUrl + queryString];
            var applyPrefix = true;
            if( prefixHistory[0].match( new RegExp('^[A-Za-z0-9-_]+://') ) )
            {
                applyPrefix = false;
            }
            var prefix = this._prefix;
            if( !xIsEmpty(this._prefix) && this._prefix )
            {
                prefixHistory.push( this._prefix + cleanUrl + queryString );
                if(foundAt >= 0)
                {
                    this._prefixCache[foundAt] = prefixHistory;
                }
                else
                {
                    this._prefixCache.push( prefixHistory );
                }
            }
            else
            {
                prefix = "";
            }
            if( !applyPrefix )
            {
                prefix = "";
            }
            url = prefix + cleanUrl + randomizedQueryString;
    
            return (getCleanUrl) ? (cleanUrl + queryString) : url;
        }
        hotswap.prototype.refreshAllJs = function( excludedFiles )
        {
            if( typeof excludedFiles == "undefined" || !excludedFiles)
            {
                excludedFiles = []
            }
            excludedFiles.push("hotswap.js");
    
            this._recreate( "js", excludedFiles, false, 0, true );
        };
        hotswap.prototype.refreshJs = function( includedFiles )
        {
            this._recreate( "js", includedFiles, true, 0, true );
        };
        hotswap.prototype.refreshAllCss = function( excludedFiles )
        {
            this._recreate( "css", excludedFiles, false, this.FILE_REMOVAL_DELAY );
        };
        hotswap.prototype.refreshCss = function( includedFiles )
        {
            this._recreate( "css", includedFiles, true, this.FILE_REMOVAL_DELAY );
        };
        hotswap.prototype.refreshAllImg = function( excludedFiles )
        {
            this._reload( "img", excludedFiles, false );
        };
        hotswap.prototype.refreshImg = function( includedFiles )
        {
            this._reload( "img", includedFiles, true );
        };
        hotswap.prototype.setPrefix = function( prefix )
        {
            this._prefix = prefix;
            var gui = xGetElementById(this.CSS_HTML_PREFIX + "_wrapper");
            if( gui )
            {
                if( !xIsEmpty(this._prefix) && this._prefix )
                {
                    xGetElementById(this.CSS_HTML_PREFIX+"-prefix").value = this._prefix;
                }
                else
                {
                    xGetElementById(this.CSS_HTML_PREFIX+"-prefix").value = "";
                }
            }
        }
        hotswap.prototype.getPrefix = function()
        {
            return this._prefix;
        }
        hotswap.prototype.createGui = function( nDistanceFromTopInPercent )
        {
            if( xIsEmpty(nDistanceFromTopInPercent) )
            {
                nDistanceFromTopInPercent = 20;
            }
            var gui = xGetElementById(this.CSS_HTML_PREFIX + "_wrapper");
            if( gui )
            {
                xRemove(xGetElementById(this.CSS_HTML_PREFIX + "_wrapper"));
            }
            gui = xCreateElement("div");
            xSetAttribute( gui, "id", this.CSS_HTML_PREFIX + "_wrapper" );
            var guiHtml = xReplace( this._guiHtml, "PREFIX", this.CSS_HTML_PREFIX );
            guiHtml = xReplace( guiHtml, '20%;/*distance from top*/', nDistanceFromTopInPercent+'%;/*distance from top*/' );
            gui.innerHTML = guiHtml;
            xAppendChild( xGetElementsByTagName("body")[0], gui );
            if( !xIsEmpty(this._guiCache) )
            {
                this._guiCache = {};
            }
            this._guiCreateFilesList();
            if( !xIsEmpty(this._prefix) && this._prefix )
            {
                xGetElementById(this.CSS_HTML_PREFIX+"-prefix").value = this._prefix;
            }
            var self = this;
            xAddEventListener( xGetElementById(this.CSS_HTML_PREFIX+"-toggle"), "click", function(evt)
            {
                var gui = xGetElementById(self.CSS_HTML_PREFIX);
                if( xHasClass(gui, "mini") )
                {
                    xRemoveClass( gui, "mini" );
                }
                else
                {
                    xAddClass( gui, "mini" );
                }
            });
            xAddEventListener( xGetElementById(this.CSS_HTML_PREFIX+"-prefix"), "blur", function(evt)
            {
                self._guiPrefixChanged(evt.target);
            });
            xAddEventListener( xGetElementById(this.CSS_HTML_PREFIX+"-submit-selected"), "click", function(evt)
            {
                self._guiRefreshSelected()
            });
            xAddEventListener( xGetElementById(this.CSS_HTML_PREFIX+"-submit-start"), "click", function(evt)
            {
                if( xGetAttribute(evt.target, "class") != this.CSS_HTML_PREFIX+"-seconds" )
                {
                    var input, nSeconds = 1;
                    var children = evt.target.children;
                    for(var i=0; i<children.length; ++i)
                    {
                        if( xGetAttribute(children[i], "class") == this.CSS_HTML_PREFIX+"-seconds" )
                        {
                            nSeconds = children[i].value;
                        }
                    }
    
                    self._guiRefreshSelected();
                    self._guiRefreshStart( nSeconds );
                }
            });
            xAddEventListener( xGetElementById(this.CSS_HTML_PREFIX+"-submit-stop"), "click", function(evt)
            {
                self._guiRefreshStop();
            });
            xAddEventListener( xGetElementById(this.CSS_HTML_PREFIX+"-submit-refresh-list"), "click", xBind(self.guiRefreshFilesList,self) );
        }
    
        hotswap.prototype._guiCreateFilesList = function()
        {
            this._guiCache.files = [];
            this._guiCache.activeFiles = {
                "css" : [],
                "js" : [],
                "img" : []
            };
    
            var self = this;
            var createFilesList = function(list, files)
            {
                var i, j, r, clone, template, file, fileName, nodesToRemove = [];
                for(j=0; j<list.children.length; ++j)
                {
                    if( xHasClass( list.children[j], "template" ) )
                    {
                        template = list.children[j];
                    }
                    else
                    {
                        if( !xHasClass( list.children[j], self.CSS_HTML_PREFIX + "-headline" ) )
                        {
                            nodesToRemove.push(list.children[j]);
                        }
                    }
                }
                for(r=0; r<nodesToRemove.length; ++r)
                {
                    xRemove( nodesToRemove[r] );
                }
                for(i=0; i<files.length; ++i)
                {
                    file = files[i];
                    clone = xCloneNode( template );
                    xRemoveClass( clone, "template" );
                    fileName = self._updatedUrl( xGetAttribute( file.node, file.srcAttributeName ), true );
                    if( !xContains(self._guiCache.files,fileName) )
                    {
                        self._guiCache.files.push(fileName);
                        clone.innerHTML = fileName;
                        xAppendChild( list, clone );
                        xAddEventListener( clone, "click", (function(type, fileName){
                            return function(evt){
                                xStopPropagation(evt);
                                xPreventDefault(evt);
                                self._guiClickedFile(evt.target, type, fileName);
                            };
                        })(file.type, fileName)
                        );
                    }
                }
            }
    
            createFilesList( xGetElementById(this.CSS_HTML_PREFIX+"-css"), this._getFilesByType("css") );
            createFilesList( xGetElementById(this.CSS_HTML_PREFIX+"-js"), this._getFilesByType("js", ["hotswap.js"]) );
            createFilesList( xGetElementById(this.CSS_HTML_PREFIX+"-img"), this._getFilesByType("img") );
        }
        hotswap.prototype.deleteGui = function()
        {
            var gui = xGetElementById(this.CSS_HTML_PREFIX + "_wrapper");
            if( gui )
            {
                xRemove(xGetElementById(this.CSS_HTML_PREFIX + "_wrapper"));
            }
        }
        hotswap.prototype._guiPrefixChanged = function(ele)
        {
            if( ele )
            {
                this.setPrefix(ele.value);
            }
        },
    
        hotswap.prototype._guiClickedFile = function( ele, sType, sFileName )
        {
            var activeFiles = this._guiCache.activeFiles[sType];
            if( xContains( activeFiles, sFileName ) )
            {
                xRemoveClass(ele, "active");
                activeFiles.splice( activeFiles.indexOf(sFileName), 1 )
            }
            else
            {
                xAddClass(ele, "active");
                activeFiles.push( sFileName );
            }
        },
    
        hotswap.prototype._guiRefreshSelected = function()
        {
            var activeFiles = this._guiCache.activeFiles;
            if( activeFiles['css'].length > 0 )
            {
                this.refreshCss( activeFiles['css'] );
            }
            if( activeFiles['js'].length > 0 )
            {
                this.refreshJs( activeFiles['js'] );
            }
            if( activeFiles['img'].length > 0 )
            {
                this.refreshImg( activeFiles['img'] );
            }
        },
    
        hotswap.prototype._guiRefreshStart = function( nSeconds )
        {
            if( this._guiGuiRefreshInterval !== null )
            {
                this._guiRefreshStop();
            }
            var self = this;
            this._guiGuiRefreshInterval = setInterval( xBind(this._guiRefreshSelected, this), nSeconds * 1000 );
            xAddClass( xGetElementById(this.CSS_HTML_PREFIX+"-submit-start"), "inactive" );
            xRemoveClass( xGetElementById(this.CSS_HTML_PREFIX+"-submit-stop"), "inactive" );
        },
    
        hotswap.prototype._guiRefreshStop = function()
        {
            if( this._guiGuiRefreshInterval !== null )
            {
                clearInterval(this._guiGuiRefreshInterval);
            }
            this._guiGuiRefreshInterval = null;
            xRemoveClass( xGetElementById(this.CSS_HTML_PREFIX+"-submit-start"), "inactive" );
            xAddClass( xGetElementById(this.CSS_HTML_PREFIX+"-submit-stop"), "inactive" );
        }
    
        hotswap.prototype.guiRefreshFilesList = function()
        {
            this._guiCreateFilesList();
        }
    
    }).call(this);
    
        3
  •  1
  •   lock    16 年前

    如果你不太信任mootools,那么jquery也有同样的插件 如果你不需要框架,你可以通过dom添加这些脚本

    但是我确信你不允许改变你已经定义的头部脚本

        4
  •  1
  •   VirtuosiMedia    16 年前

    我不熟悉HotSport,但如果您谈论的是动态加载JavaScript,是的,您可以这样做。 MooTools 允许您这样做,您也可以这样做 jQuery , Prototype , Dojo YUI ,我相信大多数其他框架也能做到这一点。你也可以用它 native JavaScript .

        5
  •  1
  •   Alexander Mills    7 年前

    您可以使用RequireJS前端模块系统轻松地重新加载JavaScript代码,我最近(2015年9月)写了一篇关于它的文章

    https://medium.com/@the1mills/hot-reloading-with-react-requirejs-7b2aa6cb06e1

    您基本上删除了AMD模块的缓存,RequireJS将从文件系统中获取新的缓存。

    诀窍是使用WebSocket(socket.io工作正常)告诉浏览器文件已更改,并删除缓存并重新要求文件。

    其余信息在文章中

        6
  •  0
  •   Community kfsone    7 年前

    如果你想这样做的话 JavaScript文件,请参阅 this question 对于一些足够相似的东西,你应该能够得到基本的想法。