0

我有一个正在修改 Shopify 应用程序的脚本(这意味着脚本是通过第三方进程附加的,我无法访问它们。)我希望我的脚本仅在脚本完全执行完成后加载,但我可以'不知道用什么来表示这个过程已经完成。

这是我的脚本(目前使用 setInterval 作为权宜之计):

$(window).load(function(){
    var check = setInterval(function() {
        let sprCheck = window['SPR'];
        var spr = $("#shopify-product-reviews"),
            container = spr.find(".spr-content"),
            reviewButton = spr.find(".spr-summary-actions-newreview");

        if (sprCheck) {

            clearInterval(check);

            var reviews = spr.find('.spr-reviews'),
            reviewButtonWrap = spr.find('.spr-summary-actions'),
            form = spr.find('.spr-form'),
            toggleContainer = spr.find('.spr-summary-actions-togglereviews'),
            reviewButtonLabel = reviewButton.text();

            reviewButtonWrap.detach().appendTo(container);
            spr.css('overflow','visible');
            form.detach().insertAfter(reviews);
            if (reviews.children().length) {
                reviewButtonWrap.css('display', 'none');
            }
            toggleContainer.click(function() {
                reviewButtonWrap.toggle();
            });

            spr.fadeTo(300, 1);
            reviewButton.click(function(){
                if (form.is(':visible')) {
                    reviewButton.text('Cancel Review');
                    reviewButton.addClass('spr-close-form');
                } else {
                    reviewButton.text(reviewButtonLabel);
                    reviewButton.removeClass('spr-close-form');
                }
            });
        } 
    }, 300);
})

这是附上他们的脚本的地方:

(function() {
  function asyncLoad() {
    var urls = ["\/\/productreviews.shopifycdn.com\/assets\/v4\/spr.js?shop=sukker-sweet-phase-2.myshopify.com"];
    for (var i = 0; i < urls.length; i++) {
      var s = document.createElement('script');
      s.type = 'text/javascript';
      s.async = true;
      s.src = urls[i];
      var x = document.getElementsByTagName('script')[0];
      x.parentNode.insertBefore(s, x);
    }
  };
  if(window.attachEvent) {
    window.attachEvent('onload', asyncLoad);
  } else {
    window.addEventListener('load', asyncLoad, false);
  }
})();

这是他们的脚本本身:

    e = function() {
        "use strict";
        window.innerShiv = function() {
            function n(e, t, r) {
                return /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i.test(r) ? e : t + "></" + r + ">"
            }
            var s, o = document,
                d = "abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" ");
            return function(e, t) {
                if (!s && ((s = o.createElement("div")).innerHTML = "<nav></nav>", 1 !== s.childNodes.length)) {
                    for (var r = o.createDocumentFragment(), a = d.length; a--;) r.createElement(d[a]);
                    r.appendChild(s)
                }
                if (e = e.replace(/^\s\s*/, "").replace(/\s\s*$/, "").replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "").replace(/(<([\w:]+)[^>]*?)\/>/g, n), s.innerHTML = (r = e.match(/^<(tbody|tr|td|col|colgroup|thead|tfoot)/i)) ? "<table>" + e + "</table>" : e, r = r ? s.getElementsByTagName(r[1])[0].parentNode : s, !1 === t) return r.childNodes;
                a = o.createDocumentFragment();
                for (var i = r.childNodes.length; i--;) a.appendChild(r.firstChild);
                return a
            }
        }()
    }, t = {
        exports: {}
    }, e.call(t.exports, t, t.exports), t.exports;
    var e, t;
    (function() {
        window.SPR = function() {
            function n() {}
            return n.shop = Shopify.shop, n.host = "//productreviews.shopifycdn.com", n.version = "v4", n.api_url = n.host + "/proxy/" + n.version, n.badgeEls = [], n.reviewEls = [], n.elSettings = {}, n.$ = void 0, n.extraAjaxParams = {
                shop: n.shop
            }, n.registerCallbacks = function() {
                return this.$(document).bind("spr:badge:loaded", "undefined" != typeof SPRCallbacks && null !== SPRCallbacks ? SPRCallbacks.onBadgeLoad : void 0), this.$(document).bind("spr:product:loaded", "undefined" != typeof SPRCallbacks && null !== SPRCallbacks ? SPRCallbacks.onProductLoad : void 0), this.$(document).bind("spr:reviews:loaded", "undefined" != typeof SPRCallbacks && null !== SPRCallbacks ? SPRCallbacks.onReviewsLoad : void 0), this.$(document).bind("spr:form:loaded", "undefined" != typeof SPRCallbacks && null !== SPRCallbacks ? SPRCallbacks.onFormLoad : void 0), this.$(document).bind("spr:form:success", "undefined" != typeof SPRCallbacks && null !== SPRCallbacks ? SPRCallbacks.onFormSuccess : void 0), this.$(document).bind("spr:form:failure", "undefined" != typeof SPRCallbacks && null !== SPRCallbacks ? SPRCallbacks.onFormFailure : void 0)
            }, n.loadStylesheet = function() {
                var e;
                return (e = document.createElement("link")).setAttribute("rel", "stylesheet"), e.setAttribute("type", "text/css"), e.setAttribute("href", "https://productreviews.shopifycdn.com/assets/v4/spr-805222bdeda8199e3a86a468a398e3070e6126868692225ffa23ac7502b1eca2.css"), e.setAttribute("media", "screen"), document.getElementsByTagName("head")[0].appendChild(e)
            }, n.initRatingHandler = function() {
                return n.$(document).on("mouseover mouseout", "form a.spr-icon-star", function(e) {
                    var t, r, a;
                    return t = e.currentTarget, a = n.$(t).attr("data-value"), r = n.$(t).parent(), "mouseover" === e.type ? (r.find("a.spr-icon:lt(" + a + ")").addClass("spr-icon-star-hover"), r.find("a.spr-icon:gt(" + (a - 1) + ")").removeClass("spr-icon-star-hover")) : r.find("a.spr-icon").removeClass("spr-icon-star-hover")
                })
            }, n.initDomEls = function() {
                return this.badgeEls = this.$(".shopify-product-reviews-badge[data-id]"), this.reviewEls = this.$("#shopify-product-reviews[data-id]"), this.$.each(this.reviewEls, (a = this, function(e, t) {
                    var r;
                    return r = a.$(t).attr("data-id"), a.elSettings[r] = {}, a.elSettings[r].reviews_el = "#" + (a.$(t).attr("data-reviews-prefix") ? a.$(t).attr("data-reviews-prefix") : "reviews_"), a.elSettings[r].form_el = "#" + (a.$(t).attr("data-form-prefix") ? a.$(t).attr("data-form-prefix") : "form_")
                }));
                var a
            }, n.loadProducts = function() {
                return this.$.each(this.reviewEls, (i = this, function(e, t) {
                    var r, a;
                    if (r = i.$(t).attr("data-id"), "false" !== i.$(t).attr("data-autoload")) return a = i.$.extend({
                        product_id: r,
                        version: i.version
                    }, i.extraAjaxParams), i.$.get(i.api_url + "/reviews/product", a, i.productCallback, "jsonp")
                }));
                var i
            }, n.loadBadges = function() {
                var e, t, r, a, i, n;
                if (0 < (r = this.$.map(this.badgeEls, (n = this, function(e) {
                        return n.$(e).attr("data-id")
                    }))).length) {
                    for (t = 7, i = []; 0 < (e = r.splice(0, t)).length;) a = this.$.extend(this.extraAjaxParams, {
                        product_ids: e
                    }), i.push(this.$.get(this.api_url + "/reviews/badges", a, this.badgesCallback, "jsonp"));
                    return i
                }
            }, n.pageReviews = function(e) {
                var t, r, a;
                return a = this.$(e).data("product-id"), r = this.$(e).data("page"), t = this.$.extend({
                    page: r,
                    product_id: a
                }, this.extraAjaxParams), this.$.get(this.api_url + "/reviews", t, this.paginateCallback, "jsonp"), !1
            }, n.submitForm = function(e) {
                var t, r, a;
                return t = this.$(e).serializeObject(), t = this.$.extend(t, this.extraAjaxParams), t = (t = this.$.param(t)).replace(/%0D%0A/g, "%0A"), this.$.ajax({
                    url: this.api_url + "/reviews/create",
                    type: "GET",
                    dataType: "jsonp",
                    data: t,
                    success: this.formCallback,
                    beforeSend: (a = this, function() {
                        return a.$(".spr-button-primary").attr("disabled", "disabled")
                    }),
                    complete: (r = this, function() {
                        return r.$(".spr-button-primary").removeAttr("disabled")
                    })
                }), !1
            }, n.reportReview = function(e) {
                var t;
                return confirm("Are you sure you want to report this review as inappropriate?") && (t = this.$.extend({
                    id: e
                }, this.extraAjaxParams), this.$.get(this.api_url + "/reviews/report", t, this.reportCallback, "jsonp")), !1
            }, n.toggleReviews = function(e) {
                return this.$("#shopify-product-reviews[data-id='" + e + "']").find(".spr-reviews").toggle()
            }, n.toggleForm = function(e) {
                return this.$("#shopify-product-reviews[data-id='" + e + "']").find(".spr-form").toggle()
            }, n.setRating = function(e) {
                var t, r, a;
                return t = this.$(e).parents("form"), a = this.$(e).attr("data-value"), r = this.$(e).parent(), t.find("input[name='review[rating]']").val(a), this.setStarRating(a, r)
            }, n.setStarRating = function(e, t) {
                return t.find("a:lt(" + e + ")").removeClass("spr-icon-star-empty spr-icon-star-hover"), t.find("a:gt(" + (e - 1) + ")").removeClass("spr-icon-star-hover").addClass("spr-icon-star-empty")
            }, n.badgesCallback = function(e) {
                var r;
                return r = e.badges, n.$.map(n.badgeEls, function(e) {
                    var t;
                    if (t = n.$(e).attr("data-id"), r[t] !== undefined) return n.$(e).replaceWith(r[t]), n.triggerEvent("spr:badge:loaded", {
                        id: t
                    })
                })
            }, n.productCallback = function(e) {
                var t;
                return t = e.remote_id.toString(), n.renderProduct(t, e.product_stripped, e.aggregate_rating), n.renderForm(t, e.form), n.renderReviews(t, e.reviews)
            }, n.renderProduct = function(t, r, a) {
                return this.$.map(this.reviewEls, (i = this, function(e) {
                    if (t === i.$(e).attr("data-id")) return i.$(e).html([innerShiv(r, !1), a]), i.triggerEvent("spr:product:loaded", {
                        id: t
                    })
                }));
                var i
            }, n.renderForm = function(e, t) {
                return this.$(this.elSettings[e].form_el + e).html(t), this.triggerEvent("spr:form:loaded", {
                    id: e
                })
            }, n.renderReviews = function(e, t) {
                return n.$(n.elSettings[e].reviews_el + e).html(t), n.triggerEvent("spr:reviews:loaded", {
                    id: e
                })
            }, n.formCallback = function(e) {
                var t, r, a, i;
                return i = e.status, a = e.remote_id, r = e.form, (t = n.$(n.elSettings[a].form_el + a)).html(r), "failure" === i && n.initStarRating(t), "success" === i && (n.$("#shopify-product-reviews[data-id='" + a + "'] .spr-summary-actions-newreview").hide(), n.$(".spr-form-message-success").focus()), n.triggerEvent("spr:form:" + i, {
                    id: a
                })
            }, n.initStarRating = function(e) {
                var t, r, a;
                if ((a = e.find("input[name='review[rating]']")) && a.val()) return r = a.val(), t = e.find(".spr-starrating"), this.setStarRating(r, t)
            }, n.paginateCallback = function(e) {
                var t, r;
                return r = e.remote_id.toString(), t = e.reviews, n.renderReviews(r, t)
            }, n.reportCallback = function(e) {
                var t;
                return t = "#report_" + e.id, n.$(t).replaceWith("<span class='spr-review-reportreview'>" + n.$(t).attr("data-msg") + "</span>")
            }, n.loadjQuery = function(e) {
                return n.loadScript("//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js", function() {
                    return n.$ = jQuery.noConflict(!0), e()
                })
            }, n.loadScript = function(e, t) {
                var r;
                return (r = document.createElement("script")).type = "text/javascript", r.readyState ? r.onreadystatechange = function() {
                    if ("loaded" === r.readyState || "complete" === r.readyState) return r.onreadystatechange = null, t()
                } : r.onload = function() {
                    return t()
                }, r.src = e, document.getElementsByTagName("head")[0].appendChild(r)
            }, n.loadjQueryExtentions = function(r) {
                return r.fn.serializeObject = function() {
                    var e, t;
                    return e = {}, t = this.serializeArray(), r.each(t, function() {
                        return e[this.name] ? (e[this.name].push || (e[this.name] = [e[this.name]]), e[this.name].push(this.value || "")) : e[this.name] = this.value || ""
                    }), e
                }
            }, n.triggerEvent = function(e, t) {
                return this.$(document).trigger(e, t)
            }, n
        }(), SPR.loadStylesheet(), SPR.loadjQuery(function() {
            return SPR.$.ajaxSetup({
                cache: !1
            }), SPR.loadjQueryExtentions(SPR.$), SPR.$(document).ready(function() {
                return SPR.registerCallbacks(), SPR.initRatingHandler(), SPR.initDomEls(), SPR.loadProducts(), SPR.loadBadges()
            })
        })
    }).call(this)
}("undefined" != typeof global ? global : "undefined" != typeof window && window);
4

2 回答 2

0

我认为你有两个选择。

  1. 像你一样(一次又一次地检查更改是否完成)

  2. 使用MutationObserver,如果你想这样做,请务必进行大量测试。

对于您的解决方案,我认为您错过的是更好的检查(sprCheck)。如果您说有时在元素存在时触发该功能,但尚未在正确的位置,那么您还必须在继续之前检查元素是否在正确的检查中。

于 2020-02-12T16:08:07.383 回答
0

在附加脚本的地方,您可以尝试添加 onload 属性:

var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.onload = "functionToRunMyOwnScript()"

如果您无法访问它附加的位置,我个人认为使用间隔没有任何问题,就像您目前正在做的那样。

于 2020-02-07T14:52:50.853 回答