替换网页中的内容

替换网页中的文本内容

  1. // ==UserScript==
  2. // @name 替换网页中的内容
  3. // @name:en Replace content in a webpage(Revision)
  4. // @name:zh-CN 替换网页中的内容
  5. // @name:zh-TW 替換網頁中的內容
  6. // @namespace http://tampermonkey.net/
  7. // @version 2.0.1
  8. // @description 替换网页中的文本内容
  9. // @description:en Replace text content in a webpage(Revision)
  10. // @description:zh-CN 替换网页中的文本内容
  11. // @description:zh-TW 替換網頁中的文本內容
  12. // @author linmii
  13. // @editor zesion
  14. // @include *
  15. // @grant none
  16. // ==/UserScript==
  17. /**
  18. * TO DO List
  19. * 1.增加整页内容替换功能,个人感觉整页内容替换没什么意义
  20. *
  21. *
  22. * 已知bug
  23. * 1. 存在iframe的页面无法进行替换
  24. *
  25. *
  26. * V1.0.3 2019-08-05 更新内容
  27. * 1. 解决模态框弹出页面无法输入的问题。
  28. * 2. 增加是否替换禁用文本框内容的功能
  29. * 3. 修改脚本只替换文本框内容的功能
  30. *
  31. * V1.0.4 2019-12-31 更新内容
  32. * 1. 解决一个页面出现多个替换图标的问题。
  33. * 2. 解决在某些网页,弹窗飘到屏幕顶部无法输入的问题,如1688网站订单页面。
  34. *
  35. * V1.1 2020-02-06 更新内容,bug修复
  36. * 1. 解决弹窗在不同网页中高度不一致的问题
  37. * 2. 解决脚本在阿里云后台,谷歌云后台等某些网站无法使用的问题。
  38. *
  39. * V1.1.2
  40. * 1. 清除数据后让查找输入框获得焦点
  41. *
  42. * V2.0
  43. * 本次进行了大版本更新,基本上是重写整个插件,采用了jquery框架,解决了纯js需要适配复杂页面等问题。
  44. *
  45. * 新增功能:
  46. * 1. 重写插件,采用jquery框架,修复插件在一些页面出现的各种无法使用问题
  47. * 2. 增加勾选,实现替换功能定制化
  48. * 3. 增加打开弹窗自动定位到查找输入框,方便输入
  49. * 功能优化:
  50. * 1. 优化弹出框高度的计算方法
  51. * 2. 删除无用代码
  52. * 3. 采用css方式对弹窗进行局中,去掉臃肿的js居中算法
  53. * Bug修复:
  54. * 1. 修复某些页面弹窗显示问题,如淘宝产品详情页
  55. * 2. 修复某些页面插件报onclick, onmouseover等奇怪问题,导致插件无法使用的问题
  56. * 3. 增加勾选,实现替换功能定制化
  57. *
  58. * V2.0.1
  59. * 去掉jquery框架,继续采用原生javascrip编写插件,主要是发现jquery兼容问题比较差。
  60. * 1. 修复原生JavaScript各种报错问题。
  61. */
  62.  
  63. var elements = [];
  64.  
  65. (function () {
  66. 'use strict';
  67.  
  68. initCss();
  69. initModal();
  70. initRImg();
  71. initDialog();
  72. removeTagAttibute('tabindex');
  73.  
  74. })();
  75.  
  76. /**
  77. * 初始化css样式
  78. */
  79. function initCss() {
  80. var lmStyle = document.createElement("style");
  81. lmStyle.type = "text/css";
  82. lmStyle.innerHTML
  83. = '.lm-r-button {'
  84. + 'padding: 10px 18px;'
  85. + 'font-size: 14px;'
  86. + 'border-radius: 4px;'
  87. + 'line-height: 1;'
  88. + 'white-space: nowrap;'
  89. + 'cursor: pointer;'
  90. + 'background: #409EFF;'
  91. // + 'border: 1px solid #409EFF;'
  92. + 'border: none;'
  93. + 'color: #fff;'
  94. + 'font-weight: 500;'
  95. + '}'
  96. + '.lm-r-button:hover {background: #66b1ff; border-color: #66b1ff; color: #fff;}'
  97. + '.lm-r-button:focus {background: #66b1ff; border-color: #66b1ff; color: #fff;}'
  98. + '.lm-r-input {'
  99. + '-webkit-appearance: none;'
  100. + 'background-color: #fff;'
  101. + 'background-image: none;'
  102. + 'border-radius: 4px;'
  103. + 'border: 1px solid #dcdfe6;'
  104. + 'box-sizing: border-box;'
  105. + 'color: #606266;'
  106. + 'display: inline-block;'
  107. + 'font-size: 14px;'
  108. + 'height: 40px;'
  109. + 'line-height: 40px;'
  110. + 'outline: none;'
  111. + 'padding: 0 15px;'
  112. + 'transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);'
  113. + 'width: 100%;'
  114. + '}'
  115. + '.lm-r-input:hover {border-color: #C0C4CC;}'
  116. + '.lm-r-input:focus {border-color: #409EFF;}';
  117.  
  118. document.querySelector("head").appendChild(lmStyle);
  119. }
  120.  
  121. /**
  122. * 弹出框兼容
  123. */
  124. function removeTagAttibute(attributeName){
  125. var allTags = '*';
  126. var specificTags = ['DIV', 'ARTICLE', 'INPUT'];
  127.  
  128. var allelems = document.querySelectorAll(specificTags);
  129. var i,j= 0;
  130. for(i = 0, j = 0; i < allelems.length; i++) {
  131. allelems[i].removeAttribute(attributeName);
  132. }
  133. }
  134.  
  135. /**
  136. * 初始化R图标
  137. */
  138. function initRImg() {
  139. var rImg = document.createElement("div");
  140. rImg.id = "lm-r-img";
  141. rImg.innerText = 'R';
  142. rImg.style.cssText = "z-index: 999999; position: fixed; top: 0; left: 0; font-size: 14px; border-radius: 4px; background-color: #fff; width: 20px; height: 20px; text-align: center; opacity: 0.5; cursor: pointer; border: solid 1px #999999;";
  143. /*if (document.querySelector("body")){
  144. document.querySelector("body").prepend(rImg);
  145. }*/
  146. if(window.self === window.top){
  147. if (document.querySelector("body")){
  148. document.body.appendChild(rImg);
  149. } else {
  150. document.documentElement.appendChild(rImg);
  151. }
  152. }
  153. rImg.addEventListener('click',function () {
  154. document.querySelector("#lm-r-modal").style.display = 'block';
  155. document.querySelector("#lm-dialog-div").style.display = 'block';
  156. document.querySelector("#lm-find-content").focus();
  157. });
  158. rImg.addEventListener('mouseover', function () {
  159. document.querySelector("#lm-r-img").style.opacity = 1;
  160. });
  161. rImg.addEventListener('mouseleave', function () {
  162. document.querySelector("#lm-r-img").style.opacity = 0.5;
  163. });
  164. }
  165.  
  166. /**
  167. * 初始化遮罩
  168. */
  169. function initModal() {
  170. var lmModal = document.createElement("div");
  171. lmModal.id = 'lm-r-modal';
  172. lmModal.style.cssText = 'position: fixed; left: 0; top: 0; width: 100%; height: 100%; opacity: 0.5; background: #000; z-index: 999999; display: none;';
  173. lmModal.onclick = function () {
  174. document.querySelector("#lm-close-btn").click();
  175. };
  176. document.querySelector("body").appendChild(lmModal);
  177. }
  178.  
  179. /**
  180. * 初始化弹出框
  181. */
  182. function initDialog() {
  183. var dialogDiv = document.createElement("div");
  184. dialogDiv.id = "lm-dialog-div";
  185. var htmlText = '<div>' +
  186. '<input id="lm-find-content" class="lm-r-input" id="searchTxt" placeholder="请输入查找内容(支持正则)" >'+
  187. '</div>' +
  188. '<div style="margin-top: 5px;">' +
  189. '<input id="lm-replace-content" class="lm-r-input" placeholder="请输入替换内容">' +
  190. '</div>' +
  191. '<div id="lm-switch-div" style="margin-top: 5px;">'+
  192. '<label><input class="lm-r-checkbox" name="lm-r-checkbox[]" type="checkbox" id="lm-replace-text" value="text" checked />文本框</label>&nbsp;&nbsp;'+
  193. '<label><input class="lm-r-checkbox" name="lm-r-checkbox[]" type="checkbox" id="lm-replace-disabled" value="disabled" />禁用文本框</label><br />'+
  194. '<label><input class="lm-r-checkbox" name="lm-r-checkbox[]" type="checkbox" id="lm-replace-textarea" value="textarea" />多行文本域</label>&nbsp;&nbsp;'+
  195. '<label><input class="lm-r-checkbox" name="lm-r-checkbox[]" type="checkbox" id="lm-replace-select" value="other" disabled/>其他文本</label>'+
  196. '<br />'+
  197. '</div>'+
  198. '<div style="margin-top: 5px;">' +
  199. '<button id="lm-replace-btn" class="lm-r-button">替 换</button>' +
  200. '<button id="lm-clear-btn" class="lm-r-button" style="margin-left: 10px;">清 空</button>' +
  201. '<button id="lm-close-btn" class="lm-r-button" style="margin-left: 10px;" >关 闭</button>' +
  202. '</div>';
  203. dialogDiv.innerHTML = htmlText;
  204. dialogDiv.style.border = 'solid 1px grey';
  205. dialogDiv.style.padding = '10px';
  206. dialogDiv.style.zIndex = '99999999';
  207. dialogDiv.style.position = 'fixed';
  208. dialogDiv.style.display = 'none';
  209. dialogDiv.style.background = '#fff';
  210. dialogDiv.style.borderRadius = '4px';
  211. dialogDiv.style.fontSize = '14px';
  212. dialogDiv.style.left = '50%';
  213. dialogDiv.style.top = '40%';
  214. dialogDiv.style.marginLeft = '-100px';
  215. dialogDiv.style.marginTop = '-50px';
  216. var body = document.querySelector("body");
  217. body.appendChild(dialogDiv);
  218. }
  219.  
  220. /**
  221. * 为dialogDiv的元素添加事件
  222. */
  223. window.onload=function(){
  224. //为替换按钮添加事件
  225. var replaceBtnNode = document.getElementById("lm-replace-btn");
  226. replaceBtnNode.addEventListener("click", replaceContent);
  227.  
  228. //为关闭按钮添加事件
  229. var closeBtnNode = document.getElementById("lm-close-btn");
  230. closeBtnNode.addEventListener("click", closeBindEvent);
  231.  
  232. //为清空按钮添加事件
  233. var clearBtnNode = document.getElementById("lm-clear-btn");
  234. clearBtnNode.addEventListener("click", function(){
  235. document.querySelector("#lm-find-content").value="";
  236. document.querySelector('#lm-replace-content').value = ""
  237. document.querySelector("#lm-find-content").focus();
  238. });
  239. }
  240.  
  241. /**
  242. * 判断需要替换的元素
  243. */
  244. function replaceContent() {
  245. var replaceCounts = 0;
  246. var findText = document.querySelector("#lm-find-content").value;
  247. var replaceText = document.querySelector("#lm-replace-content").value;
  248.  
  249. elements = [];
  250.  
  251. var disabledStatus = document.querySelector("#lm-replace-disabled").checked;
  252. var checkboxEle = document.getElementsByName("lm-r-checkbox[]");
  253. var count = checkboxEle.length;
  254. for (var i = 0; i < count; i++) {
  255. if(checkboxEle[i].checked) {
  256. elements.push(checkboxEle[i].value);
  257. }
  258. }
  259.  
  260. //替换input元素内容
  261. if(elements.indexOf('text') > -1 || elements.indexOf('disabled') > -1) {
  262. replaceCounts += replaceInputContent(replaceCounts, findText, replaceText);
  263. }
  264.  
  265. //替换多行文本框内容
  266. if(elements.indexOf('textarea') > -1) {
  267. replaceCounts += replaceTextareaContent(replaceCounts, findText, replaceText);
  268. }
  269.  
  270. //替换其他文本内容
  271. if(elements.indexOf('other') > -1) {
  272. // To do...
  273. }
  274. alert("替换完成, 共替换 【"+ replaceCounts +"】 处文本.");
  275.  
  276. // 设置替换前的输入内容
  277. document.querySelector("#lm-find-content").value = findText;
  278. document.querySelector("#lm-replace-content").value = replaceText;
  279. }
  280.  
  281. /**
  282. * 替换部分文本 - 输入框和禁用输入框
  283. */
  284. function replaceInputContent(replaceCounts, findText, replaceText) {
  285. var disabledStatus = document.querySelector("#lm-replace-disabled").checked;
  286. if ("" !== findText) {
  287. var list = document.getElementsByTagName("input");
  288. var textCount = list.length;
  289. for(var i = 0;i < textCount;i++){
  290. //判断是否替换禁用文本框的内容
  291. if(true === list[i].disabled && false === disabledStatus) {
  292. continue;
  293. }
  294. if(list[i].id === 'lm-find-content' || list[i].id === 'lm-replace-content') { //如果是弹出框则跳过
  295. continue;
  296. }
  297. var txt = list[i].value;
  298. if(list[i].type==="text" && "" !== txt && txt.indexOf(findText) >= 0){
  299. var ret = txt.replace(new RegExp(findText, "gm"), replaceText);
  300. list[i].value = ret;
  301. replaceCounts++;
  302. } else {
  303. continue;
  304. }
  305. }
  306. }
  307. return replaceCounts < 1 ? 0 : replaceCounts;
  308. }
  309.  
  310. /**
  311. * 替换部分文本 - 文本域
  312. */
  313. function replaceTextareaContent(replaceCounts, findText, replaceText) {
  314. if ("" !== findText) {
  315. var list = document.getElementsByTagName("textarea");
  316. var textCount = list.length;
  317. for (var i = 0; i < textCount; i++) {
  318. var textVal = list[i].value;
  319. if("" !== textVal && textVal.indexOf(findText) >= 0) {
  320. var ret = textVal.replace(new RegExp(findText, "gm"), replaceText);
  321. list[i].value = ret;
  322. replaceCounts++;
  323. }
  324. }
  325. }
  326. return replaceCounts < 1 ? 0 : replaceCounts;
  327. }
  328.  
  329.  
  330. /**
  331. * 隐藏弹窗
  332. */
  333. function closeBindEvent() {
  334. document.querySelector("#lm-close-btn").click();
  335. document.querySelector("#lm-r-modal").style.display = 'none';
  336. document.querySelector('#lm-dialog-div').style.display = 'none';
  337. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址