Eru*_*tar 4 javascript tumblr google-chrome-extension
注意:这是我之前的一个后续问题.
我决定通过#posts元素内的扩展程序将帖子显示在仪表板上.现在我的问题是Tumblr在滚动时自动删除帖子的内容.
以下是删除前正常帖子的示例:
<li class="post_container" data-pageable="post_110141415125">
<div class="post post_full ..." [...]>
<!-- ... -->
</div>
</li>
Run Code Online (Sandbox Code Playgroud)
删除其内容后,同一帖子:
<li class="post_container" data-pageable="post_110141415125" style="border-radius: 3px; height: 207px; width: 540px; background-color: rgb(255, 255, 255);">
</li>
Run Code Online (Sandbox Code Playgroud)
由于我的扩展程序将帖子重新定位为类似于pinterest的布局,因此删除帖子的内容会影响整个布局.是否可以阻止Tumblr仪表板移除每个内部的DOM元素.post?
编辑:
我removeChild在我的内容脚本中为该方法添加了这个注入代码:
function addScript(){
var script = document.createElement('script');
script.id = 'newRemoveChildScript'; ///just to find is faster in the code
script.src = chrome.extension.getURL("injectedCode.js");
$($('script')[0]).before(script); ///Script is indeed present, I checked that
}
window.onload = addScript;
Run Code Online (Sandbox Code Playgroud)
接下来我做的是injectedCode.js用第二个版本创建文件,如下所示:
(function (obj, method) {
function isPost(el) {
return (/^post_\d+$/.test(el.id) && ~el.className.indexOf('post'));
}
obj[method] = (function (obj_method) {
return function (child) {
if (isPost(child)) return child;
return obj_method.apply(this, arguments);
}
}(obj[method]));
}(Element.prototype, 'removeChild'));
Run Code Online (Sandbox Code Playgroud)
当我加载Tumblr-Dashboard时,我可以确认head-element中存在Script-element.该文件也正确链接,因为'removeChild'函数被调用一次.似乎正在删除脚本元素.
从那时起,该函数永远不会被再次调用,我可以再次看到那些"空"的帖子.
Mar*_*lli 13
免责声明:完全合法的事情发生在这里,不要惊慌!
你要问的是一些不容易做的事情,但实际上你可以阻止Tumblr在他们离开视口时滚动时隐藏帖子.更确切地说,高级程序员实际上可以操纵任何Tumblr方法使其表现得像他想要的那样,但是,现在,让我们关注你的问题.
Tumblr删除帖子的内容以使页面更轻,让您继续浏览,而不会遇到任何滞后和/或由于大量元素而难以滚动.想象一下,向下滚动一小时:你的破折号会有成千上万的帖子,你的浏览器可能会因每次滚动时必须移动的东西过多而冻结.
我没有检查和理解Tumblr代码的每一行,因为它全部被打包/缩小,并且实际上不可能理解任何方法的单行(除非你在Tumblr工作,在这种情况下祝贺),但是,基本上,我放了一些DOM断点,我检查了一些代码,当它们离开视口时删除了帖子.
Tumblr为帖子创建了一些自定义和狡猾的"滚动"事件.每次帖子超出视口一定距离时,这些事件都会触发.
现在Tumblr将一些侦听器附加到这些自定义事件上,并且在li.post_container元素上使用DOM断点,您将能够看到这些侦听器驻留在dashboard.jsJavaScript文件中.

更确切地说,删除帖子内容的代码的确切部分如下所示:
function j(t,v) { try{ t.removeChild(v) } catch(u){} }
Run Code Online (Sandbox Code Playgroud)
这里t是li.post_container和v是它的孩子:div#post_[id].
这部分代码有什么作用?没有什么特别之处:它从字面上删除了div#post_[id]父元素li.post_container.
现在Tumblr必须设置移除的帖子的容器的样式,以保持#posts元素的高度,其中包含所有帖子,否则删除帖子的内容会使页面向下滚动H像素,其中H是帖子的高度除去.
这个更改发生在另一个脚本中,这是index.js,我甚至没有仔细看看它,因为它只是不可能阅读:

顺便说一句,这个脚本并不重要,因为我们可以使用简单的CSS来防止样式更改.
现在该帖子的内容已被"删除",它看起来像这样:

*为了清楚起见:我添加了文本和墓碑,你实际上没有看到它们哈哈
所以,最后,当一个帖子离开视口时,会发生以下变化:
<li class="post_container" [...]>
<div id="post_[id]" class="post post_full ..." [...]>
<!-- post body... -->
</div>
</li>
Run Code Online (Sandbox Code Playgroud)
对此:
<li class="post_container" [...] style="border-radius: 3px; height: Hpx; width: Wpx; background-color: rgb(255, 255, 255);">
</li>
Run Code Online (Sandbox Code Playgroud)
现在我们知道Tumblr在滚动仪表板时的行为,我们可以阻止它删除帖子并将它们设计为看起来像带有圆形边框的空白色死区块.
在关心防止移除柱子之前,我们应该将它们设置为不具有固定的高度和宽度,从而覆盖Tumblr离开视口时应用于它们的样式.
我们可以在页面中注入一些简单的CSS,制定规则!important以防止内联样式覆盖它们.这是我们要添加的CSS:
li.post_container {
height: auto !important;
width: 540px !important;
/* 540px is the default width
* change it to any amount that applies to your layout
*/
}
Run Code Online (Sandbox Code Playgroud)
或者,使用JavaScript,我们可以:
var s = document.createElement('style');
s.textContent = 'li.post_container{height:auto!important;width:540px!important;}';
document.head.appendChild(s);
Run Code Online (Sandbox Code Playgroud)
如果我们不想浪费时间考虑一个好的解决方案,我们可以实现最简单的解决方案,并且,在几行代码中我们可以:
复制removeChild方法Element.prototype,并称之为_removeChild.
用一个 "过滤"调用它的函数替换原来的函数,决定删除除帖子之外的任何内容.
这是解决问题的简单而愚蠢的代码:
Element.prototype._removeChild = Element.prototype.removeChild
Element.prototype.removeChild = function(child) {
// Check if the element is a post (e.g. the id looks like "post_123456...")
if (/^post_\d+$/.test(child.id)) {
// If so, stop here by returning the post
// This will make Tumblr believe the post has been removed
return child;
}
// Otherwise the element isn't a post, so we can remove it
return Element.prototype._removeChild.apply(this, arguments);
}
Run Code Online (Sandbox Code Playgroud)
没有注释的代码长度:5行
您可以检查明显多于一个条件:例如,你可以检查帖子包含的类post和post_full,或者如果它是parentElement有阶级post_container,等等......这完全取决于你.
完成这种操作的一种更优雅,更狡猾的方法是使用一些闭包和更复杂的逻辑来"编辑"原始Element.prototype.removeChild方法.这就是我们要做的事情:
创建一个闭包,我们将在其中重新定义Element.prototype.removeChild为帖子添加"过滤器" 的方法.
在这个闭包中,我们将定义我们可以调用的自定义过滤器函数isPost(),以过滤将要删除的元素.
使用第二个闭包,我们将重新定义Element.prototype.removeChild方法,使其行为如下:
使用我们之前创建的过滤器功能检查要删除的元素isPost().
如果要删除的元素是帖子,则在此处停止,不要将其删除.
否则继续并Element.prototype.removeChild使用该.apply方法调用原始方法.
它可能看起来很难,但代码并不难理解,我通过评论来实现它以使其更易于理解,这里是:
(function (obj, method) {
// This is all wrapped inside a closure
// to make the new removeChild method remember the isPost function
// and maintain all the work invisible to the rest of the code in the page
function isPost(el) {
// Check if the element is a post
// This will return true if el is a post, otherwise false
return (/^post_\d+$/.test(el.id) && ~el.className.indexOf('post'));
}
// Edit the Element.prototype.removeChild assigning to it our own function
obj[method] = (function (obj_method) {
return function (child) {
// This is the function that will be assigned to removeChild
// It is wrapped in a closure to make the check before removing the element
// Check if the element that is going to be removed is a post
if (isPost(child)) return child;
// If so, stop here by returning the post
// This will make Tumblr believe the post has been removed
// Otherwise continue and remove it
return obj_method.apply(this, arguments);
}
}(obj[method]));
}(Element.prototype, 'removeChild'));
Run Code Online (Sandbox Code Playgroud)
没有注释的代码长度:11行
由于内容脚本在隐藏的不同window对象中工作,因此内容脚本代码无法与页面代码交互,因此您必须直接在内容脚本的页面中注入代码.为此,您需要创建一个<script>元素并将其插入<head>页面中.您可以将要注入的代码存储在一个新脚本中(让我们调用它injectedCode.js)并使用它chrome.runtime.getURL来获取要在<script>src中使用的绝对URL .
重要提示:您需要将injectedCode.js文件添加到您的"web_accessible_resources"字段中manifest.json,以便可以从Tumblr访问该文件,如下所示:
"web_accessible_resources": ["/injectedCode.js"]
Run Code Online (Sandbox Code Playgroud)
然后,你可以创建一个<script>设置.src你injectedCode.js是这样的:
/* In your content script: */
var s = document.createElement('script');
s.src = chrome.extension.getURL("/injectedCode.js");
document.head.appendChild(s);
Run Code Online (Sandbox Code Playgroud)
这些只是实现您想要做的两种方法:防止Tumblr在滚动时隐藏帖子.显然还有很多其他方法可以做到这一点,例如使用MutationObservers来检查子树修改,删除所有帖子并创建一个新的容器,其中包含新的个人事件和方法来模拟Tumblr,插入Tumblr代码并直接编辑它(几乎不可能,也没有多少合法性,等等.
我还想强调一个事实,这只是一个问题的答案,我不负责不正确地使用这些操作来伤害你的扩展程序的用户.
| 归档时间: |
|
| 查看次数: |
1072 次 |
| 最近记录: |