简体   繁体   English

使用jQuery插件的代码可在Chrome中使用,但不能在Chrome扩展程序中使用?

[英]Code, using a jQuery plugin, works in Chrome, but not in a Chrome extension?

I have a small JavaScript file based in JS/jQuery and an additional library. 我有一个基于JS / jQuery的小型JavaScript文件和一个附加库。 It is running perfectly as independent files, but I am having problems getting it up and running in a Chrome extension. 它可以作为独立文件完美运行,但是我无法在Chrome扩展程序中启动并运行它。

The script checks each image of an HTML page for specific characteristics, and depending on that adds a border around the image. 该脚本检查HTML页面的每个图像是否具有特定特征,并根据此特征在图像周围添加边框。

manifest.json 的manifest.json

{
    "name": "ImageId",
    "version": "0.1",
    "manifest_version": 2,
    "browser_action":  {
        "default_icon": "icon.png"
    },
    "content_scripts" : [
        {
            "matches" : [
                "http://*/*",
                "https://*/*"
            ],
            "js" : ["jquery-1.8.3.min.js","jquery.exif.js","content_script.js"],
            "run_at" : "document_start",
            "all_frames" : false
        }
    ],
    "icons":{
        "128":"icon.png"
    }
}

content_script.js: content_script.js:

jQuery(window).load(function(){
    $('img').each(function() {

        var gpslo=0;
        var gpsla=0;
        if (typeof(gpslo) != "undefined" && gpslo != null) {
            var gpslo= $(this).exif("GPSLongitude");
            var gpsla = $(this).exif("GPSLatitude");
        }
        console.log(gpslo+"--"+ gpsla);

        if (gpslo!=0) {
            $(this).css('border', "solid 20px red");  
            $(this).click(function() {
                alert("Long: " + $(this).exif("GPSLongitude") + ", Lat: " + $(this).exif("GPSLatitude"));
            });
        }
        else {

            $(this).css('border', "solid 20px gray"); 
        };

    });
});

Now, when I run this in Chrome on a very simple 1-picture only website, I receive no error at all but just a white page. 现在,当我在一个非常简单的仅包含1张图片的网站上在Chrome中运行此程序时,我只收到白页,就没有收到任何错误。

Also everything works fine running the script outside of the extension system. 同样,在扩展系统外部运行脚本,一切都可以正常工作。 I am not quite sure how to explain this better. 我不太确定如何更好地解释这一点。 These are my first steps outside of tutorials, so please be kind :) 这些是我在教程之外的第一步,所以请客气:)

I uploaded the complete test and extension files to: Working(Html).zip and NotWorking(Chrome).zip . 我将完整的测试和扩展文件上传到: Working(Html).zipNotWorking(Chrome).zip

As Sudarshan answered , comment out that document.write code in jquery.exif.js . 当Sudarshan回答时 ,在jquery.exif.js注释掉document.write代码。 document.write in a content script erases the previous DOM, and VBscript doesn't work in Chrome anyway. 内容脚本中的document.write会删除之前的DOM,而VBscript始终无法在Chrome中运行。

However, that is not the only problem: 但是,这不是唯一的问题:

  1. When the content script is set to "run_at" : "document_start" , as in the question, you must use $(document).ready() . 当内容脚本设置为"run_at" : "document_start" ,如在问题中所示,必须使用$(document).ready() When in doubt, it never hurts to use $(document).ready() anyway. 如有疑问,无论如何都不会使用$(document).ready()

  2. When the content script is set to "run_at" : "document_idle" , as in the files you linked, the script may fire after the document.load event has . 当内容脚本设置为"run_at" : "document_idle" ,如在链接的文件中一样, 该脚本可能会在document.load事件发生后触发 So, $(window).load() will not always work. 因此, $(window).load()并不总是有效。

  3. In Chrome, at least on the test page you provided, it takes up to 6 seconds for the Exif data to come in! 在Chrome中,至少在您提供的测试页上,Exif数据最多需要6秒钟才能输入! (It's pretty much instantaneous on Firefox.) This means, you need to check the images after a time delay. (在Firefox上几乎是瞬时的。)这意味着,您需要在一段时间后检查图像。

Other, less critical, issues: 其他不太重要的问题:

  1. Use CSS classes to help with the aforementioned timed checks and to avoid inline CSS. 使用CSS类来帮助进行上述定时检查并避免内联CSS。
  2. Use jQuery's .on() , rather than .click() , so that the handler only is attached once and gracefully compensates for AJAX changes. 使用jQuery的.on()而不是.click()从而使处理程序只连接一次,并优雅地弥补了AJAX的变化。

Putting it all together, content_script.js becomes ( Update, see below this script ): 放在一起, content_script.js变成了( 更新,请参见此脚本下方 ):

$(document).ready ( function () {
    $(window).load (CompForExifPluginInitDelay);

    //--- In a content script, the load event may have already fired.
    if (document.readyState == "complete") {
        CompForExifPluginInitDelay ();
    }

    $(document.head).append ( '                             \
        <style type="text/css">                             \
            img.myExt_HasExif {                             \
                border:     20px solid red !important;      \
            }                                               \
            img.myExt_WithoutExif {                         \
                border:     20px solid gray !important;     \
            }                                               \
        </style>                                            \
    ' );

    //-- Use jQuery .on(), not .click().
    $(document.body).on ("click", "img.myExt_HasExif", popupLatLong);
} );

function CompForExifPluginInitDelay () {
    //-- Exif Init takes somewhere between 1.6 and 6 seconds on Chrome!!!
    var numChecks       = 0;
    var checkInterval   = 444;  //-- 0.4 secs is plenty fast enough
    var maxChecks       = 6 * 1000 / checkInterval + 1;

    var imageCheckTimer = setInterval ( function() {
            numChecks++;

            findImagesWithLatLong (numChecks);

            if (numChecks >= maxChecks) {
                clearInterval (imageCheckTimer);

                //-- All remaining images don't have lat-long data.
                $("img").not(".myExt_HasExif").addClass("myExt_WithoutExif");

                console.log ("***** Passes complete! *****");
            }
        },
        checkInterval
    );
}

function findImagesWithLatLong (passNum) {
    console.log ("***** Pass: ", passNum);
    $("img").not (".myExt_HasExif").each ( function (J) {
        var jThis   = $(this);
        var gpslo   = jThis.exif ("GPSLongitude");
        var gpsla   = jThis.exif ("GPSLatitude");

        console.log (J + ": ", gpslo + "--" + gpsla);
        if (gpslo != 0) {
            jThis.addClass ("myExt_HasExif");
        }
    } );
}

function popupLatLong (zEvent) {
    var jThis   = $(this);
    alert (
        "Longitude: " + jThis.exif ("GPSLongitude")
        + ", Latitude: " + jThis.exif ("GPSLatitude")
    );
}

which works in all my tests so far, (In conjunction with killing that document.write() . 到目前为止,它在我的所有测试中都有效((与杀死该document.write()结合使用document.write()




Update: Using .exifLoad() : 更新:使用.exifLoad()

As PAEz pointed out in his answer , the Chrome timing issue seems to be resolved by forcing a manual scan of the images with .exifLoad() . 正如PAEz 在回答中指出的那样,Chrome计时问题似乎可以通过使用.exifLoad()强制手动扫描图像来解决。

This works when I tested it, and would be a preferable approach to using a timer. 当我对其进行测试时,此方法有效,并且是使用计时器的首选方法。

So, PAEz's answer works (in conjunction with Sudarshan's answer), but my version of the code (addressing the other issues) would be: 因此,PAEz的答案有效(与Sudarshan的答案一起使用),但是我的代码版本(解决了其他问题)将是:

$(document).ready ( function () {
    $(window).load (findImagesWithLatLong);

    //--- In a content script, the load event may have already fired.
    if (document.readyState == "complete") {
        findImagesWithLatLong ();
    }

    $(document.head).append ( '                             \
        <style type="text/css">                             \
            img.myExt_HasExif {                             \
                border:     20px solid red !important;      \
            }                                               \
            img.myExt_WithoutExif {                         \
                border:     20px solid gray !important;     \
            }                                               \
        </style>                                            \
    ' );

    //-- Use jQuery .on(), not .click().
    $(document.body).on ("click", "img.myExt_HasExif", popupLatLong);
} );

function findImagesWithLatLong (passNum) {
    $("img").not (".myExt_HasExif").each ( function (J) {
        $(this).exifLoad ( function () {
            var jThis   = $(this);
            var gpslo   = jThis.exif ("GPSLongitude");
            var gpsla   = jThis.exif ("GPSLatitude");

            console.log (J + ": ", gpslo + "--" + gpsla);
            if (gpslo != 0)
                jThis.addClass ("myExt_HasExif");
            else
                jThis.addClass ("myExt_WithoutExif");
        }.bind (this) );
    } );
}

function popupLatLong (zEvent) {
    var jThis   = $(this);
    alert (
        "Longitude: " + jThis.exif ("GPSLongitude")
        + ", Latitude: " + jThis.exif ("GPSLatitude")
    );
}

It works after eliminating following code in jquery.exif.js 在消除jquery.exif.js中的以下代码后,它可以工作

/*document.write(
    "<script type='text/vbscript'>\r\n"
    + "Function IEBinary_getByteAt(strBinary, iOffset)\r\n"
    + " IEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\n"
    + "End Function\r\n"
    + "Function IEBinary_getLength(strBinary)\r\n"
    + " IEBinary_getLength = LenB(strBinary)\r\n"
    + "End Function\r\n"
    + "</script>\r\n"
);*/

Just eliminate the above codein jquery.exif.js it works 只需删除jquery.exif.js中的上述代码即可

Output 产量

在此处输入图片说明

Let me know if you need more information 如果您需要更多信息,请与我们联系

This is more of a comment than an answer, but it involves code so I had to do it as an answer... 这更像是评论而不是答案,但是它涉及代码,因此我不得不将其作为答案...

When I tried your working example it hardly ever worked for me as your trying to get at values that aren't present yet due to the file not being got yet by the xhr call. 当我尝试您的工作示例时,由于试图通过xhr调用尚未获取文件中的值,您对它几乎没有用。
You can fix this by changing your code to the below. 您可以通过将代码更改为以下内容来解决此问题。 This may possibly be incorporated into Brock Adams answer to avoid using CompForExifPluginInitDelay which really could be hit and miss. 可能会将其合并到Brock Adams答案中,以避免使用CompForExifPluginInitDelay ,它实际上可能会碰到和错过。

jQuery(window).load(function() {
    $('img').each(function() {
        $(this).exifLoad(function() {
            var gpslo = 0;
            var gpsla = 0;
            if(typeof(gpslo) != "undefined" && gpslo !== null) {
                var gpslo = $(this).exif("GPSLongitude");
                var gpsla = $(this).exif("GPSLatitude");
            }
            console.log(gpslo + "--" + gpsla);
            if(gpslo != 0) {
                $(this).css('border', "solid 20px red");
                $(this).click(function() {
                    alert("Longitude: " + $(this).exif("GPSLongitude") + ", Latitude: " + $(this).exif("GPSLatitude"));
                });
            } else {

                $(this).css('border', "solid 20px gray");
            };

        }.bind($(this)));
    });
});

As always, I don't really know JQuery so if this could be done in a more JQ way then please say. 和往常一样,我并不真正了解JQuery,所以如果可以通过更多JQ方式完成,请说。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM