Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在HTML中替换数据绑定中的值而不丢失事件_Javascript_Html_Greasemonkey_Tampermonkey - Fatal编程技术网

Javascript 在HTML中替换数据绑定中的值而不丢失事件

Javascript 在HTML中替换数据绑定中的值而不丢失事件,javascript,html,greasemonkey,tampermonkey,Javascript,Html,Greasemonkey,Tampermonkey,为了提高网站的可用性,我想用Greasemonkey(JavaScript)更改以下内容: 到 试过 document.body.innerHTML = document.body.innerHTML.replace(text_to_find, text_to_replace) 但是页面会丢失事件,并且不会加载任何数据:“Price”不会加载任何内容并保持为空 然后我发现: 到 有没有办法让它在不损失活动的情况下工作 更新: <div class="row"> <di

为了提高网站的可用性,我想用Greasemonkey(JavaScript)更改以下内容:

试过

document.body.innerHTML = document.body.innerHTML.replace(text_to_find, text_to_replace)
但是页面会丢失事件,并且不会加载任何数据:“Price”不会加载任何内容并保持为空

然后我发现:

有没有办法让它在不损失活动的情况下工作

更新:

<div class="row">
    <div class="col-md-5">
        <h5 data-bind="text: 'Price: ' + db.totalpr().toFixed(2) + ' GBP'" style="margin-left:7px"></h5>
    </div>
</div>

这条线看起来是一个“X Y问题”。看下面的折叠


这个问题意味着替换属性,而不是文本。(并且,只需修改属性,这样就不会破坏ajax驱动的页面。)

因为它是ajax驱动的,所以需要类似于
MutationObserver
waitforkyelments
的东西

下面的脚本演示了如何替换这些类型的属性:

// ==UserScript==
// @name     _Dynamically replace JS-coded attributes
// @match    *://YOUR_SERVER.COM/YOUR_PATH/*
// @require  https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// @grant    GM.openInTab 
// ==/UserScript==
//- The @grant directives are needed to restore the proper sandbox.

var current_exchange_rate = 1.41;  //  Hard coded for demo purposes only.

waitForKeyElements ("[data-bind]", ReplacePriceAttributes);

function ReplacePriceAttributes (jNode) {
    // Following could alternatively could use `.data("bind")` since attribute is of `data-` type.
    var oldBind = jNode.attr ("data-bind");
    if (/Price:/.test (oldBind) ) {
        let newBind = oldBind.replace ("db.totalpr().toFixed(2)", `( db.totalpr() * ${current_exchange_rate} ).toFixed(2)`);
        jNode.attr ("data-bind", newBind)
    }
}
当前汇率在脚本中是硬编码的。获取实时值超出了这个问题的范围,无论如何


真正的问题是: 替换这些属性值不太可能达到您真正想要的效果(以美元显示价格)。如果页面是由Knockout.js驱动的(看起来是这样的),这一点尤其正确

要更改您看到的显示价格,请使用与


如果页面使用knockout.js,我建议如下

注意:这仅在应用绑定后才起作用。如果在此之前应用js代码,则只需替换绑定即可。就像你已经做过的一样,但是要注意“.toFixed(2)”问题(参见Mike McCaughan的评论)。如果这就是它无法工作的原因,那么您还应该在控制台日志中看到错误

$(文档).ready(函数(){
//他们的代码。只是为了演示。
var viewModel={
db:{
totalpr:新的可观测ko(123.1234)
}
};
应用绑定(视图模型);
//您的Greasemonkey代码从这里开始:
var current\u exchange\u rate=1.41;//硬编码仅用于演示目的。
var priceElements=$(“h5[数据绑定*='db.totalpr().toFixed(2)'”)
$.each(价格元素、函数(索引、值){
var数据=ko.dataFor(值);
//将您的新值添加到他们的模型中。使用ko.pureComputed确保其在totalpr更改时立即更改。
data.db.modifiedTotalPr=ko.pureComputed(函数(){
返回data.db.totalpr()*当前汇率;
});
//更新数据绑定属性。
$(value).attr(“数据绑定”,“文本:'Price:'+db.modifiedTotalPr().toFixed(2)+'USD')
//应用绑定。
ko.cleanNode(值)
ko.应用绑定(数据、值);
});
});


更改innerHTML会抹去一切,唯一的方法是直接调整元素,但如果页面在脚本到达之前使用了属性,您就无能为力了。例如,当我将“Price”更改为“PriceUSD”时,它会在加载数据之前显示一秒钟,然后再次更改为“Price”.i18n有一些非常好的资源。你不必重新发明这个轮子:你不能将一个字符串(toFixed()
的结果是一个字符串)乘以一个数字。您可能需要
(data.totalpr()*当前汇率)。toFixed(2)
。但是,我相信@epascarello的意思是,您可能无法像那样更改属性中的值。等到值被呈现到DOM中,然后将该值解析为一个数字并在那里应用更改。如果我认为该页面使用knockout.js,我是否正确?我不确定这是否有效。如果是knockout.js:knockout绑定通常在初始化时应用,之后只在内部处理。若要更改该绑定,您需要清除该节点,并使用相应的数据重新应用该绑定到该节点。@Paul,GTK。你有没有一个页面可以使用类似于
db.totalpr()
的东西供我使用?试试看:我会同时检查是否有淘汰方案。:)我想您的代码现在可以工作了。:)直到现在我才知道,但我喜欢这个主意。唯一的注释问题可能是,在本例中,您需要解析数据中的值。@BrockAdams谢谢您的代码!我已经测试了它好几个小时,试图找出它为什么不改变值——不幸的是,它无法工作,我做了一些调试:它找到了正确的数据绑定,更改了应该更改的内容,但Firefox没有更新我屏幕上的内容——例如,我想将“Price”更改为“PriceUSD”:oldBind显示“Price”,newBind显示“PriceUSD”,我在屏幕上看到的是“Price”,而不是“PriceUSD”。我们快到了!有趣的是,看看OP是否对此做出了回应。以及当价格上涨时是否有副作用。(这似乎改变了演示文稿和数据。?)如果他们的代码写得很好,他们可能在提交时使用了
db.totalpr()
。代码不会影响其现有数据。它只是添加了一个自定义字段。如果出现任何问题,也可以编写一个自定义的小视图模型,只显示修改后的totalpr,并让数据保持原样。@Paul感谢您的代码!不幸的是,无法使其工作:priceElements数组中有许多“垃圾”元素,代码以@$开头。在我的情况下,每个(priceElements、函数(索引、值)从未执行过……priceElements数组只能在选择器$(“h5[data bind*='db.totalpr().toFixed(2)]”的情况下包含垃圾(所有h5,都有一个包含db.totalpr().toFixed(2)的数据绑定)应用于许多元素。是这样吗?你有控制台错误吗?@Paul实际上每页有1-5个h5数据绑定。我应该得到什么错误?
function replaceTextOnPage(from, to){
  getAllTextNodes().forEach(function(node){
    node.nodeValue = node.nodeValue.replace(new RegExp(quote(from), 'g'), to);
  });

  function getAllTextNodes(){
    var result = [];

    (function scanSubTree(node){
      if(node.childNodes.length) 
        for(var i = 0; i < node.childNodes.length; i++) 
          scanSubTree(node.childNodes[i]);
      else if(node.nodeType == Node.TEXT_NODE) 
        result.push(node);
    })(document);

    return result;
  }

  function quote(str){
    return (str+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
  }
}
db.totalpr().toFixed(2)
"db.totalpr().toFixed(2)*current_exchange_rate"
<div class="row">
    <div class="col-md-5">
        <h5 data-bind="text: 'Price: ' + db.totalpr().toFixed(2) + ' GBP'" style="margin-left:7px"></h5>
    </div>
</div>
// ==UserScript==
// @name     _Dynamically replace JS-coded attributes
// @match    *://YOUR_SERVER.COM/YOUR_PATH/*
// @require  https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// @grant    GM.openInTab 
// ==/UserScript==
//- The @grant directives are needed to restore the proper sandbox.

var current_exchange_rate = 1.41;  //  Hard coded for demo purposes only.

waitForKeyElements ("[data-bind]", ReplacePriceAttributes);

function ReplacePriceAttributes (jNode) {
    // Following could alternatively could use `.data("bind")` since attribute is of `data-` type.
    var oldBind = jNode.attr ("data-bind");
    if (/Price:/.test (oldBind) ) {
        let newBind = oldBind.replace ("db.totalpr().toFixed(2)", `( db.totalpr() * ${current_exchange_rate} ).toFixed(2)`);
        jNode.attr ("data-bind", newBind)
    }
}
waitForKeyElements ("[data-bind]", ReplacePriceText);

function ReplacePriceText (jNode) {
    var oldPriceTxt = jNode.text ();
    /* Appropriate HTML not provided by question asker, but convert price text
        as shown in linked answer, setting newPriceTxt
    */
    jNode.text (newPriceTxt);
}