简体   繁体   English

渲染和执行<script> on pageload after injecting it from external .js file

[英]Rendering and executing <script> on pageload after injecting it from external .js file

I'm still a beginner with JavaScript and am trying to use it to make the Etsy Mini API responsive.我仍然是 JavaScript 的初学者,正在尝试使用它来使 Etsy Mini API 响应。 I have two <script> s that need to be added to a <div> in order for the mini shop to appear:我有两个<script>需要添加到<div>以便迷你商店出现:

<script type='text/javascript' src='https://www.etsy.com/assets/js/etsy_mini_shop.js'></script>
<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',4,3,0,'https://www.etsy.com');</script>

In the second <script> , I can specify the size of a thumbnail grid, (4x3 in the example above), but this grid is not responsive, so if it's loaded on a device with a smaller screen, or if a laptop's browser window is resized, the 4x3 grid might be too big.在第二个<script>中,我可以指定缩略图网格的大小(上例中为 4x3),但该网格没有响应性,因此如果它加载到屏幕较小的设备上,或者笔记本电脑的浏览器窗口调整大小后,4x3 网格可能太大。 I want to use media queries in an external .js file to change this thumbnail grid, and this is where I'm running into problems.我想在外部 .js 文件中使用媒体查询来更改此缩略图网格,这就是我遇到问题的地方。

Below is my current external .js file:以下是我当前的外部 .js 文件:

var products = document.getElementById("products-card");
var grid5x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',5,3,0,'https://www.etsy.com');</script>";
var grid4x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',4,3,0,'https://www.etsy.com');</script>";
var grid3x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',3,3,0,'https://www.etsy.com');</script>";
var grid2x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',2,3,0,'https://www.etsy.com');</script>";
var grid1x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',1,3,0,'https://www.etsy.com');</script>";

(function () {
    function resize() {
        var min_2500 = window.matchMedia('only screen and (min-width: 2500px)').addListener(function () {
            products.innerText = grid5x3;
        });
        var min_1900_max_2499 = window.matchMedia('only screen and (min-width: 1900px) and ' +
        '(max-width: 2499px)').addListener(function () {
            products.innerText = grid4x3;
        });
        var min_1200_max_1899 = window.matchMedia('only screen and (min-width: 1200px) and ' +
        '(max-width: 1899px)').addListener(function () {
            products.innerText = grid3x3;
        });
        var min_900_max_1199 = window.matchMedia('only screen and (min-width: 900px) and ' +
        '(max-width: 1199px)').addListener(function () {
            products.innerText = grid2x3;
        });
        var max_899 = window.matchMedia('only screen and (max-width: 899px)').addListener(function () {
            products.innerText = grid1x3;
        });
    }

    resize();
}());

And here is the .html:这是.html:

<head>
  ...
  <script type='text/javascript' src='https://www.etsy.com/assets/js/etsy_mini_shop.js'></script>
</head>
<body>
  ...
  <div class="products-card" id="products-card"></div>
  ...
</body>

Problem 1: The script isn't executed, but rather the actual text, <script> tags included, appears in the <div> .问题 1:脚本没有被执行,而是实际的文本,包括<script>标签,出现在<div>中。 How can I change my Javascript to make the script execute and render the mini shop?如何更改我的 Javascript 以使脚本执行并呈现迷你商店?

Problem 2: The <div> is empty upon page load, but after the browser screen is resized and hits one of the cutoffs specified in the media queries, the text appears and changes properly according to the media queries.问题 2:页面加载时<div>为空,但在调整浏览器屏幕大小并达到媒体查询中指定的截止点之一后,文本会根据媒体查询正确显示并更改。 How can I make the shop render in the <div> on page load and not just when the browser window is resized?如何使商店在页面加载时呈现在<div>中,而不仅仅是在调整浏览器窗口大小时?

UPDATE 1 So I discovered that using innerText/innerHTML does not allow any scripts to be executed/rendered when injected into the html file ( based on an answer here ).更新 1所以我发现使用 innerText/innerHTML 在注入 html 文件时不允许执行/渲染任何脚本( 基于此处的答案)。 Here is my new .js file:这是我的新 .js 文件:

var products = document.getElementById("products-card");
var grid5x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',5,3,0,'https://www.etsy.com');";
var grid4x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',4,3,0,'https://www.etsy.com');";
var grid3x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',3,3,0,'https://www.etsy.com');";
var grid2x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',2,3,0,'https://www.etsy.com');";
var grid1x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',1,3,0,'https://www.etsy.com');";

(function () {
    function resize() {
        var min_2500 = window.matchMedia('only screen and (min-width: 2500px)').addListener(function () {
            var eval_grid5x3 = eval(grid5x3);
            products.innerText = eval_grid5x3;
        });
        var min_1900_max_2499 = window.matchMedia('only screen and (min-width: 1900px) and ' +
        '(max-width: 2499px)').addListener(function () {
            var eval_grid4x3 = eval(grid4x3);
            products.innerText = eval_grid4x3;
        });
        var min_1200_max_1899 = window.matchMedia('only screen and (min-width: 1200px) and ' +
        '(max-width: 1899px)').addListener(function () {
            var eval_grid3x3 = eval(grid3x3);
            products.innerText = eval_grid3x3;
        });
        var min_900_max_1199 = window.matchMedia('only screen and (min-width: 900px) and ' +
        '(max-width: 1199px)').addListener(function () {
            var eval_grid2x3 = eval(grid2x3);
            products.innerText = eval_grid2x3;
        });
        var max_899 = window.matchMedia('only screen and (max-width: 899px)').addListener(function () {
            var eval_grid1x3 = eval(grid1x3);
            products.innerText = eval_grid1x3;
        });
    }

    resize();
}());

While this does render the Etsy mini shop, it does so with some odd behaviors:虽然这确实渲染了 Etsy 迷你商店,但它有一些奇怪的行为:

  1. The entire <body> is replaced with the injected script, when I expected the targeted <div> to be replaced with the script.当我期望目标<div>被脚本替换时,整个<body>被注入的脚本替换。

  2. Every time I resize the screen, it adds another Etsy mini shop (it does not replace the one that is currently there), resulting in the page becoming filled with numerous shops.每次我调整屏幕大小时,它都会添加另一个 Etsy 迷你商店(它不会替换当前存在的那个),导致页面充满了许多商店。

  3. The issue of it not rendering on pageload is still there.它没有在页面加载时呈现的问题仍然存在。

Apologies if this is a rather simple question.抱歉,如果这是一个相当简单的问题。 I've spent a lot of time Googling solutions but nothing I've tried has worked.我花了很多时间谷歌搜索解决方案,但我尝试过的都没有奏效。 The code I have above is the closest I've come to having a responsive Etsy Mini shop.我上面的代码是我最接近响应式 Etsy Mini 商店的代码。 Thanks for any answers/comments/suggestions!感谢您的任何回答/意见/建议!

You should always put your JS script just before the close of the body tag so that way everything is loaded on the page then the JS file is executed or else it would run the file first then load the page causing it to not perform any function since the HTML is not yet loaded.您应该始终将 JS 脚本放在 body 标记的关闭之前,这样所有内容都加载到页面上,然后执行 JS 文件,否则它会先运行文件然后加载页面,导致它不执行任何功能,因为HTML 尚未加载。 The code is always read from left to right and top to bottom.代码总是从左到右,从上到下阅读。 Hope this helps.希望这可以帮助。

I tried getting this to work with the "update and refresh the <script> tag" approach, and just wasn't able to get things to render correctly.我尝试让它与“更新和刷新<script>标签”方法一起使用,但无法正确渲染。 However, I did a little digging and it turns out Etsy.Mini just injects an <iframe> into the page.然而,我做了一点挖掘,结果发现Etsy.Mini只是在页面中注入了一个<iframe> If you grab that <iframe> and update the URL within, you can change the sizing of the Etsy Mini.如果您抓取该<iframe>并更新其中的 URL,则可以更改 Etsy Mini 的大小。

Here's an example of an <iframe> loaded by Etsy Mini.这是 Etsy Mini 加载的<iframe>示例。

<iframe frameborder="0"
    src="https://www.etsy.com/mini.php?shop_id=9999999&amp;image_type=gallery&amp;rows=5&amp;columns=5&amp;featured=0"
    width="975" height="1025">
</iframe>

The key to this is the URL in the src section of that <iframe> .关键是<iframe>src部分中的 URL。 There are two properties of note in the URL, rows and columns . URL 中有两个值得注意的属性rowscolumns Updating these properties while the page is rendered will change the sizing of the Etsy Mini, and thereby achieve something akin to bastardized responsiveness.在呈现页面时更新这些属性将改变 Etsy Mini 的大小,从而实现类似于混蛋响应的效果。

First, wrap your Etsy Mini script tags in a <div> with some id.首先,将您的 Etsy Mini 脚本标签包装在带有一些 id 的<div>中。 This allows you to easily find the <iframe> .这使您可以轻松找到<iframe> It'll be the only one inside of the <div> so long as you don't put anything else within except the <script> tags.这将是<div>中唯一的一个,只要您除了<script>标记之外没有放置任何其他内容。

<div id="etsy-iframe-container">
    <script type='text/javascript' src='https://www.etsy.com/assets/js/etsy_mini_shop.js'></script>
    <script type='text/javascript'> new Etsy.Mini(9999999, 'gallery', 5, 5, 0, 'https://www.etsy.com');</script>
</div>

For reference purposes, since Etsy has erased all official trace of it from their website (but as of 2022 it still works!) the structure of an Etsy.Mini is.出于参考目的,由于 Etsy 已从其网站上删除了它的所有官方痕迹(但截至 2022 年它仍然有效!) Etsy.Mini的结构是。

Etsy.Mini(
    shopId (Integer), 
    type (String: 'gallery' or 'thumbnail'), 
    columns (Integer), 
    rows (Integer), 
    showUpTo4FeaturedItemsFirst (Boolean: 0 or 1), 
    etsyHomepageUrl (String: must be 'https://www.etsy.com')
)

You can get your Etsy shop id by pasting in your shop URL here .您可以通过在此处粘贴您的商店 URL 来获取您的 Etsy 商店 ID。 After wrapping your Etsy Mini <script> tags in a <div> , you can use the JavaScript below (create a custom JS file and load it into your HTML document) to resize the <iframe> dynamically by modifying its URL.将 Etsy Mini <script>标签包装在<div>中后,您可以使用下面的 JavaScript(创建自定义 JS 文件并将其加载到 HTML 文档中)通过修改其 URL 来动态调整<iframe>的大小。

This is based on knowledge of the current screen's dimensions.这是基于对当前屏幕尺寸的了解。 A single Etsy Mini cell is always 184px in width and height.单个 Etsy Mini 单元格的宽度和高度始终为184px I discovered this by inspecting one in a Browser.我通过在浏览器中检查一个发现了这一点。 With this knowledge, you can calculate how many Etsy Mini's will fit horizontally on the screen and update the <iframe> accordingly.有了这些知识,您就可以计算出有多少 Etsy Mini 可以水平放置在屏幕上,并相应地更新<iframe> The same approach could be used for updating the number of rows, but I don't think that's really necessary given that most browsers support infinite scroll these days.可以使用相同的方法来更新行数,但鉴于现在大多数浏览器都支持无限滚动,我认为这并不是真正必要的。 Setting the minColumns and maxColumns allows you to provide some bounds for what the Etsy Mini should look like at extremes.设置minColumnsmaxColumns允许您为 Etsy Mini 在极端情况下的外观提供一些界限。

let resizeEtsyMini = () => {
    let minColumns = 1;
    let maxColumns = 5;
    let clientWidth = document.documentElement.clientWidth;
    let etsyMiniColumns = Math.floor(clientWidth / 184);

    if (etsyMiniColumns < minColumns) {
        etsyMiniColumns = minColumns;
    }
    else if (etsyMiniColumns > maxColumns) {
        etsyMiniColumns = maxColumns
    }
    
    // Row value can be whatever, browsers have infinite scroll these days.
    setEtsyMiniSize(5, etsyMiniColumns, clientWidth);
}

let setEtsyMiniSize = (rows, columns, iframeWidth) => {
    let etsyIframe = document.getElementById("etsy-iframe-container").getElementsByTagName("iframe");
    let etsyURL = new URL(etsyIframe[0].src);
    etsyURL.searchParams.set("rows", rows);
    etsyURL.searchParams.set("columns", columns);

    etsyIframe[0].src = etsyURL.toString();
    etsyIframe[0].width = iframeWidth;
}

// On initial page load, and on every window resize, call resizeEtsyMini.
window.onload = window.onresize = resizeEtsyMini;

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

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