为了提高网站的可用性,我想用Greasemonkey(JavaScript)更改以下内容:
data-bind="text: 'Price: ' + db.totalpr().toFixed(2) + ' GBP'"`
到
data-bind="text: 'Price: ' + db.totalpr().toFixed(2)*current_exchange_rate + ' USD'"`
曾尝试
document.body.innerHTML = document.body.innerHTML.replace(text_to_find, text_to_replace)
但是一个页面丢失了事件而没有加载任何数据:“Price”不加载任何内容并保持空白。
然后我发现了这个:Replace text in a website
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");
}
}
但是,不幸的是,它不适用于我的情况:它可以将“Price”替换为我想要的任何文本而不是
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>
答案 0 :(得分:1)
这看起来是&#34; X Y问题&#34;。见下面的折叠...
问题意味着更换属性,而不是文本。 (而且,只是属性,以便你不打破那个由ajax驱动的页面。)
由于它是由ajax驱动的,因此您需要MutationObserver
或waitForKeyElements
之类的内容。
这是一个脚本,显示如何替换这些属性:
// ==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)
}
}
current_exchange_rate
在脚本中是硬编码的。无论如何,获取实时值超出了此问题和covered elsewhere的范围。
替换这些属性值不太可能实现您真正想要的(以美元显示价格)。如果页面由Knockout.js驱动(看起来似乎是),则尤其如此。
要更改显示的价格,请使用与linked answer ...
非常相似的技巧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);
}
答案 1 :(得分:1)
如果页面使用knockout.js,我建议如下。
注意:这仅在应用绑定后才有效。如果您在此之前应用js代码,则应该单独替换绑定。就像你已经做过的那样,但要注意&#34; .toFixed(2)&#34;问题(参见Mike McCaughan的评论)。如果这就是它无法正常工作的原因,您还应该在控制台日志中看到错误。
$( document ).ready(function() {
// Their code. Just for demonstration.
var viewModel = {
db: {
totalpr: new ko.observable(123.1234)
}
};
ko.applyBindings(viewModel);
// Your Greasemonkey code starts here:
var current_exchange_rate = 1.41; // Hard coded for demo purposes only.
var priceElements = $("h5[data-bind*= 'db.totalpr().toFixed(2)']")
$.each(priceElements, function(index, value) {
var data = ko.dataFor(value);
// Add your new value to their model. Use ko.pureComputed to ensure its changed as soon as totalpr changes.
data.db.modifiedTotalPr = ko.pureComputed(function () {
return data.db.totalpr() * current_exchange_rate;
});
// Update data-bind attribute.
$(value).attr("data-bind" , "text: 'Price: ' + db.modifiedTotalPr().toFixed(2) + ' USD'")
// Apply binding.
ko.cleanNode(value)
ko.applyBindings(data, value);
});
});
&#13;
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<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>
&#13;