2011-10-09 69 views

回答

5

我知道你问jQuery和Greasemonkey的这样做,但让我断完全不同替代,Fiddler

如果您使用新版本的jQuery测试网站,并且您实际上想测试任何重大更改等。你想测试的网站,因为它将是,而基于JavaScript(greasemonkey)的事后更换不是一个准确的模拟。

随着小提琴手,你可以取代浏览器请求(浏览器不知道)的jQuery文件。通过这种方式,你可以完全测试它,你直接在页面中放置新版本,没有页面内的JS技巧可能完全不准确(处理程序已经连接,加载顺序等)。 )

Eric Law提琴手(创造者)对如何做的正是这个极好的博客文章:

Swapping out JQuery with Fiddler

该职位是为与换出缩小的版本写完整版(也方便!)用于调试的较新版本,请务必注意两种用途......它们都是非常有用可节省一些调试/测试时间。

10

制作一个开发环境,使用源代码管理和书面发布清单将为您节省很多的痛苦(并且是大多数付费工作的一项要求)。
~~~

替换现有页面上的jQuery的版本(你不控制)最好的办法是:

  1. 停止网页的本地jQuery的加载。
  2. 创建一个包含您想要的jQuery版本的<script>节点,该节点在使用jQuery的任何后续脚本之前加载之前的

不幸的是,Greasemonkey不能做#1。它只能在加载之后篡改页面的原生jQuery - 这种方法可能有效,但会降低页面速度并降低竞争条件的风险。

所以,我建议两个工具的解决方案:

  1. 确保您的Firefox有the Adblock add-on(这是一个很好的附加使用irregardless)和/或the RequestPolicy add-on

  2. 使用的AdblockRequestPolicy暂时阻止老的jQuery。
    例如,对于StackOverflow,块http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js。 (注意:RequestPolicy可以限制网址拦截只有一个特定的网站。)

  3. 然后使用Greasemonkey的加载的jQuery(Adblock的或者它可以做的irregardless RequestPolicy设置)所需版本在页面的开头。

    例如,该脚本将升级的元SO的jQuery来1.6.2,在与所述块一起从第2步:

    // ==UserScript== 
    // @name   _upgrade jQuery 
    // @include   http://meta.stackexchange.com/questions/* 
    // @run-at   document-start 
    // ==/UserScript== 
    
    /*--- Important! 
         (1) We need another add-on, besides Greasemonkey, to 
          disable the old, undesired script. 
         (2) The DOM is not available yet 
          (@run-at == document-start). 
         (3) We cannot use a loop to check for the DOM because 
          loading is halted while the loop runs. 
         (4) setTimeout() and setInterval() are not fast enough due 
          to minimum interval clamping. By the time they detect 
          the DOM, scripts that we need to precede may have 
          loaded. 
         (5) Therefor, we use a "set Zero Timeout" function as 
          explained by David Baron at 
           http://dbaron.org/log/20100309-faster-timeouts . 
         (6) By the time FF reports that the `document.head` is 
          available, several head elements have loaded! 
          (Is this a bug?) 
          That means that if any dependent scripts are loaded 
          before we can inject our jQuery version, then we must 
          also reload those dependent scripts. 
    */ 
    
    ////// setZeroTimeout() implementation: BEGIN 
    
    /*--- Only add setZeroTimeout to the window object, and hide 
        everything else in a closure. 
    */ 
    (function() { 
        var timeouts = []; 
        var messageName = "zero-timeout-message"; 
    
        /*--- Like setTimeout, but only takes a function argument. 
         There's no time argument (always zero) and no arguments. 
         You have to use a closure. 
        */ 
        function setZeroTimeout(fn) { 
         timeouts.push(fn); 
         window.postMessage(messageName, "*"); 
        } 
    
        function handleMessage(event) { 
         if (event.source == window && event.data == messageName) { 
          event.stopPropagation(); 
          if (timeouts.length > 0) { 
           var fn = timeouts.shift(); 
           fn(); 
          } 
         } 
        } 
    
        window.addEventListener ("message", handleMessage, true); 
    
        // Add the one thing we want added to the window object. 
        window.setZeroTimeout = setZeroTimeout; 
    })(); 
    
    ////// setZeroTimeout() implementation: END 
    
    /*--- Now wait for the DOM and then add our version of jQuery, 
        first thing. 
    */ 
    function SearchForDOM() { 
    
        var targetNode; 
        if (typeof document.head == "undefined") 
         targetNode = document.querySelector ("head, body"); 
        else 
         targetNode = document.head; 
        if (targetNode) { 
    
         var scriptNode  = document.createElement ("script"); 
         scriptNode.src  = 'http://ajax.googleapis.com/ajax/' 
              + 'libs/jquery/1.6.2/jquery.min.js'; 
         targetNode.appendChild (scriptNode); 
    
         /*--- By the time FF reports that the head element is 
          available, a key dependent script has loaded! 
          So, we reload it here, so that it can run with jQuery 
          available. 
         */ 
         var scriptNode  = document.createElement ("script"); 
         scriptNode.src  = location.protocol 
              + '\/\/' + location.host 
              + '/content/js/stub.js?v=49f661361016'; 
         targetNode.appendChild (scriptNode); 
        } 
        else 
         setZeroTimeout (SearchForDOM); 
    } 
    
    SearchForDOM(); 
    


    注意:由于JS,GM,和Firefox的局限性,可能还需要重新加载依赖于jQuery的脚本。 (这是元堆栈溢出的情况下,此刻。)

+0

原来我试图做同样的事情!我试图在FF56中重新加载SO,因为谷歌CDN的门槛为0速度。我使用uMatrix来阻止它。在文档准备就绪的情况下,将脚本节点扫描到队列中,反转并追加每个脚本以从jquery开始。在此之前,我尝试运行@ document-start和beforescriptexecute事件来拦截页面加载扼流圈。现在m试着用window.eval()方法。它完美无瑕。所以。只是为了表示感谢你的0timout技巧。 – Ben

0

什么不适合我的情况,似乎适合这个问题,不需要阻止者。由Greasemonkey:

// ==UserScript== 
// @name  alternative jquery 
// @namespace [email protected] 
// @description intercept 
// @include  https://somehost.com/* 
// @grant  GM_getResourceText 
// @resource jquery_new jquery_new.js 
// @run-at  document-start 
// @version  1 
// ==/UserScript== 

var jquery_source = GM_getResourceText('jquery_new'); 
console.log('jQuery Lenght =',jquery_source.length); 

window.addEventListener('beforescriptexecute', 
function(e){ 
    if (e.target.src && 
     e.target.src.search('/1.12.4/jquery.min.js') >= 0) { 
      console.log('intercepted: '+e.target.src); 
      e.preventDefault(); 
      e.stopPropagation(); 
      window.eval(jquery_source); 
     } 
}); 

注:下跌 - beforescriptexecute火灾最初的剧本被检索并准备执行之后,所以应原外部js文件加载失败,这种做法是行不通的。