我在GoodReads上的阅读书架是已出版和未出版书籍的混合,很难找到可供阅读的内容。我想我可以把一个GreaseMonkey脚本放在一起,这个脚本会改变尚未发布的书籍条目的背景。
这是我到目前为止所做的:
// ==UserScript==
// @name Unpublished Lowlighter
// @description Makes the background of books not yet published on the Goodreads to-read shelf grey.
// @include http://www.goodreads.com/*
// ==/UserScript==
function dateColor() {
var books = document.getElementsByClassName('bookalike review');
for (var book in books) {
var dateString = book
.getElementsByClassName('field date_pub')
.getElementsByClassName('value')
.textContent;
var date = new Date(dateString);
var today = new Date();
if (date > today) {
book.style.backgroundColor('Lightgrey');
}
}
}
dateColor();
问题在于它不起作用。当我尝试在暂存器中运行脚本时,它给出了错误:Exception: book.getElementsByClassName is not a function
我认为Firefox支持getElementsByClassName
并且您可以在getElementsByClassName
的结果上运行它以获取子元素。我哪里错了?
编辑:这是表格中一个<tr>
的HTML代码段。我没有发布这个的原因是它真的很冗长:
<tr id="review_265364012" class="bookalike review">
<td class="field checkbox" style="display: none"><label>checkbox</label><div class="value"> <input id="checkbox_review_265364012" name="reviews[265364012]" value="265364012" type="checkbox">
</div></td> <td class="field position"><label>position</label><div class="value"> <div class="reorderControls">
<a class="actionLink" href="#" id="loading_link_434018960" method="post" onclick="$(this).hide(); $('loading_anim_434018960').show(); $('hidden_link_434018960').simulate('click');; return false;"><img alt="up" src="http://www.goodreads.com/assets/up_arrow-7957f2bae9c3456ec7359ad79b000652.gif" title="move book up"></a><img alt="Loading-trans" class="loading" id="loading_anim_434018960" src="http://www.goodreads.com/assets/loading-trans-3e04cd6ed6ad31063972e688820d7866.gif" style="display:none"><a href="/shelf/move_up/174788201?redirect_url=%2Freview%2Flist%2F4111865%3Fformat%3Dhtml%26page%3D1%26shelf%3Dto-read" class="actionLink" data-method="post" id="hidden_link_434018960" rel="nofollow" style="display: none"><img alt="up" src="http://www.goodreads.com/assets/up_arrow-7957f2bae9c3456ec7359ad79b000652.gif" title="move book up"></a>
<img src="/assets/loading.gif" class="position_loading" style="display: none">
<input id="positions_174788201" name="positions[174788201]" value="5" type="text">
<script type="text/javascript">
//<![CDATA[
var newTip = new Tip($('positions_174788201'), " <nobr>\n <a class=\"button\" href=\"#\" onclick=\"savePositionChanges(4111865); return false;\">Save position changes<\/a> \n <a href=\"#\" onclick=\"$(\'positions_174788201\').prototip.hide(); return false;\">close<\/a>\n <\/nobr>\n", { style: 'creamy', stem: 'leftMiddle', hook: { tip: 'leftMiddle', target: 'rightMiddle' }, offset: { x: 5, y: 5 }, hideOn: 'imaginaryelement', showOn: 'click', width: 'auto', hideOthers: true });
$('positions_174788201').observe('prototip:shown', function() {
if (this.up('#box')) {
$$('div.prototip')[0].setStyle({zIndex: $('box').getStyle('z-index')});
} else {
$$('div.prototip')[0].setStyle({zIndex: 6000});
}
});
//]]>
</script> <a class="actionLink" href="#" id="loading_link_434206980" method="post" onclick="$(this).hide(); $('loading_anim_434206980').show(); $('hidden_link_434206980').simulate('click');; return false;"><img alt="down" src="http://www.goodreads.com/assets/down_arrow-61b0e7292c02b1dcfd3f75a7f9b6b7ad.gif" title="move book down"></a><img alt="Loading-trans" class="loading" id="loading_anim_434206980" src="http://www.goodreads.com/assets/loading-trans-3e04cd6ed6ad31063972e688820d7866.gif" style="display:none"><a href="/shelf/move_down/174788201?redirect_url=%2Freview%2Flist%2F4111865%3Fformat%3Dhtml%26page%3D1%26shelf%3Dto-read" class="actionLink" data-method="post" id="hidden_link_434206980" rel="nofollow" style="display: none"><img alt="down" src="http://www.goodreads.com/assets/down_arrow-61b0e7292c02b1dcfd3f75a7f9b6b7ad.gif" title="move book down"></a>
</div>
</div></td> <td class="field cover"><label>cover</label><div class="value"> <a href="/book/show/12074927-the-fractal-prince"><img alt="The Fractal Prince (The Quantum Thief Trilogy #2)" src="http://photo.goodreads.com/books/1311105989s/12074927.jpg" title="The Fractal Prince (The Quantum Thief Trilogy #2)"></a>
</div></td> <td class="field title"><label>title</label><div class="value"> <a href="/book/show/12074927-the-fractal-prince" title="The Fractal Prince (The Quantum Thief Trilogy #2)">
The Fractal Prince
<span class="darkGreyText">(The Quantum Thief Trilogy #2)</span>
</a></div></td> <td class="field author"><label>author</label><div class="value"> <a href="/author/show/2768002.Hannu_Rajaniemi">Rajaniemi, Hannu</a>
</div></td> <td class="field isbn" style="display: none"><label>isbn</label><div class="value">
</div></td> <td class="field isbn13" style="display: none"><label>isbn13</label><div class="value">
</div></td> <td class="field asin" style="display: none"><label>asin</label><div class="value">
</div></td> <td class="field num_pages" style="display: none"><label>num pages</label><div class="value"> <span class="greyText">unknown</span>
</div></td> <td class="field avg_rating"><label>avg rating</label><div class="value"> 3.67
</div></td> <td class="field num_ratings" style="display: none"><label>num ratings</label><div class="value"> 9
</div></td> <td class="field date_pub"><label>date pub</label><div style="background: none repeat scroll 0% 0% Lightgrey;" class="value"> Sep 27, 2012
</div></td> <td class="field date_pub_edition" style="display: none"><label>date pub edition</label><div class="value"> <span class="greyText">unknown</span>
</div></td> <td class="field rating"><label>my rating</label><div class="value">
<span class="stars" id="stars12074927_4111865" onmouseout="mouseOutStars('12074927')"><a rel="nofollow"><img alt="didn't like it " class="star" id="star12074927_0" onclick="submitStars('12074927', 0, '/review/rate/12074927?rating=1', 4111865); return false;" onmouseover="checkStars('12074927', 0)" src="/assets/layout/gr_orange_star_inactive.png" title="didn't like it" height="15" width="15"></a><a rel="nofollow"><img alt="it was ok " class="star" id="star12074927_1" onclick="submitStars('12074927', 1, '/review/rate/12074927?rating=2', 4111865); return false;" onmouseover="checkStars('12074927', 1)" src="/assets/layout/gr_orange_star_inactive.png" title="it was ok" height="15" width="15"></a><a rel="nofollow"><img alt="liked it " class="star" id="star12074927_2" onclick="submitStars('12074927', 2, '/review/rate/12074927?rating=3', 4111865); return false;" onmouseover="checkStars('12074927', 2)" src="/assets/layout/gr_orange_star_inactive.png" title="liked it" height="15" width="15"></a><a rel="nofollow"><img alt="really liked it " class="star" id="star12074927_3" onclick="submitStars('12074927', 3, '/review/rate/12074927?rating=4', 4111865); return false;" onmouseover="checkStars('12074927', 3)" src="/assets/layout/gr_orange_star_inactive.png" title="really liked it" height="15" width="15"></a><a rel="nofollow"><img alt="it was amazing " class="star" id="star12074927_4" onclick="submitStars('12074927', 4, '/review/rate/12074927?rating=5', 4111865); return false;" onmouseover="checkStars('12074927', 4)" src="/assets/layout/gr_orange_star_inactive.png" title="it was amazing" height="15" width="15"></a></span><script language="javascript" type="text/javascript">starRatings[ratingIndex++] = [ '12074927', -1]; checkStars('12074927', -1);</script>
<span id="reviewMessage12074927_4111865"></span>
<span id="successMessage12074927_4111865"></span>
</div></td><td class="field shelves"><label>shelves</label><div class="value"> <span id="shelfList4111865_12074927"><span id="shelf_174788201"><a href="http://www.goodreads.com/review/list/4111865?shelf=to-read" class="shelfLink" title="View all books in Johan's to-read shelf.">to-read</a></span></span><br><a class="shelfChooserLink smallText" href="#" onclick="window.shelfChooser.summon(event, {bookId: 12074927, chosen: ["to-read"]}); return false;">[edit]</a>
</div></td><td class="field review" style="display: none"><label>review</label><div class="value"> <span class="greyText">None</span>
<a class="floatingBoxLink smallText" href="#" onclick="reviewEditor.summon(this, 12074927, 'review', {value: null}); return false;">[edit]</a>
<div class="clear"></div>
</div></td><td class="field notes" style="display: none"><label>notes</label><div class="value"> <span class="greyText">None</span>
<a class="floatingBoxLink smallText" href="#" onclick="reviewEditor.summon(this, 12074927, 'notes', {value: null}); return false;">[edit]</a>
</div></td><td class="field recommender" style="display: none"><label>recommender</label><div class="value"> <span class="greyText">none</span>
</div></td><td class="field comments" style="display: none"><label>comments</label><div class="value"> <a href="/review/show/265364012">0</a>
</div></td><td class="field votes" style="display: none"><label>votes</label><div class="value"> <a href="/rating/voters/265364012?resource_type=Review">0</a>
</div></td><td class="field read_count" style="display: none"><label># times read</label><div class="value"> 0
</div></td><td class="field date_started" style="display: none"><label>date started</label><div class="value"> <span class="greyText">not set</span>
<a class="floatingBoxLink smallText" href="#" onclick="reviewEditor.summon(this, 12074927, 'started_at', {value: null}); return false;">[edit]</a>
</div></td><td class="field date_read"><label>date read</label><div class="value"> <span class="greyText">not set</span>
<a class="floatingBoxLink smallText" href="#" onclick="reviewEditor.summon(this, 12074927, 'read_at', {value: null}); return false;">[edit]</a>
</div></td><td class="field date_added" style="display: none"><label>date added</label><div class="value"> <span title="January 21, 2012">
Jan 21, 2012
</span>
</div></td><td class="field date_purchased" style="display: none"><label>date purchased</label><div class="value"> <a class="smallText" href="#" id="add_for_date_purchased" onclick="new Ajax.Request('/review/update/12074927?format=json', {asynchronous:true, evalScripts:true, onFailure:function(request){Element.hide('loading_anim_206609');$('add_for_date_purchased').innerHTML = '<span class="error">ERROR</span>try again';$('add_for_date_purchased').show();}, onLoading:function(request){;Element.show('loading_anim_206609');Element.hide('add_for_date_purchased')}, onSuccess:function(request){Element.hide('loading_anim_206609');Element.show('add_for_date_purchased');var json = eval('(' + request.responseText + ')');$('review_265364012').replace(json.html);if (typeof(toggleFieldsToMatchHeader) == 'function') {toggleFieldsToMatchHeader();}}, parameters:'owned_book[book_id]=12074927&partial=bookalike&view=table' + '&authenticity_token=' + encodeURIComponent('J5JjYi/D31hPm9w3u8hM35umQTh8bK3md4dVzpi4eKQ=')}); return false;">(add)</a><img alt="Loading-trans" class="loading" id="loading_anim_206609" src="http://www.goodreads.com/assets/loading-trans-3e04cd6ed6ad31063972e688820d7866.gif" style="display:none">
</div></td><td class="field owned" style="display: none"><label>owned</label><div class="value"></div></td><td class="field purchase_location" style="display: none"><label>purchase location</label><div class="value"> <a class="smallText" href="#" id="add_for_purchase_location" onclick="new Ajax.Request('/review/update/12074927?format=json', {asynchronous:true, evalScripts:true, onFailure:function(request){Element.hide('loading_anim_953979');$('add_for_purchase_location').innerHTML = '<span class="error">ERROR</span>try again';$('add_for_purchase_location').show();}, onLoading:function(request){;Element.show('loading_anim_953979');Element.hide('add_for_purchase_location')}, onSuccess:function(request){Element.hide('loading_anim_953979');Element.show('add_for_purchase_location');var json = eval('(' + request.responseText + ')');$('review_265364012').replace(json.html);if (typeof(toggleFieldsToMatchHeader) == 'function') {toggleFieldsToMatchHeader();}}, parameters:'owned_book[book_id]=12074927&partial=bookalike&view=table' + '&authenticity_token=' + encodeURIComponent('J5JjYi/D31hPm9w3u8hM35umQTh8bK3md4dVzpi4eKQ=')}); return false;">(add)</a><img alt="Loading-trans" class="loading" id="loading_anim_953979" src="http://www.goodreads.com/assets/loading-trans-3e04cd6ed6ad31063972e688820d7866.gif" style="display:none">
</div></td><td class="field condition" style="display: none"><label>condition</label><div class="value"> <a class="smallText" href="#" id="add_for_condition" onclick="new Ajax.Request('/review/update/12074927?format=json', {asynchronous:true, evalScripts:true, onFailure:function(request){Element.hide('loading_anim_990684');$('add_for_condition').innerHTML = '<span class="error">ERROR</span>try again';$('add_for_condition').show();}, onLoading:function(request){;Element.show('loading_anim_990684');Element.hide('add_for_condition')}, onSuccess:function(request){Element.hide('loading_anim_990684');Element.show('add_for_condition');var json = eval('(' + request.responseText + ')');$('review_265364012').replace(json.html);if (typeof(toggleFieldsToMatchHeader) == 'function') {toggleFieldsToMatchHeader();}}, parameters:'owned_book[book_id]=12074927&partial=bookalike&view=table' + '&authenticity_token=' + encodeURIComponent('J5JjYi/D31hPm9w3u8hM35umQTh8bK3md4dVzpi4eKQ=')}); return false;">(add)</a><img alt="Loading-trans" class="loading" id="loading_anim_990684" src="http://www.goodreads.com/assets/loading-trans-3e04cd6ed6ad31063972e688820d7866.gif" style="display:none">
</div></td><td class="field format"><label>format</label><div class="value"></div></td><td class="field actions"><label>actions</label><div class="value"> <div class="actionsWrapper greyText smallText">
<div class="editLinkWrapper"><a class="actionLinkLite editLink" href="#" id="loading_link_818479" onclick="new Ajax.Request('/review/edit/12074927', {asynchronous:true, evalScripts:true, onFailure:function(request){Element.hide('loading_anim_818479');$('loading_link_818479').innerHTML = '<span class="error">ERROR</span>try again';$('loading_link_818479').show();}, onLoading:function(request){;Element.show('loading_anim_818479');Element.hide('loading_link_818479')}, onSuccess:function(request){Element.hide('loading_anim_818479');Element.show('loading_link_818479');}, parameters:'authenticity_token=' + encodeURIComponent('J5JjYi/D31hPm9w3u8hM35umQTh8bK3md4dVzpi4eKQ=')}); return false;">edit</a><img alt="Loading-trans" class="loading" id="loading_anim_818479" src="http://www.goodreads.com/assets/loading-trans-3e04cd6ed6ad31063972e688820d7866.gif" style="display:none"></div>
<div class="viewLinkWrapper"><a href="/review/show/265364012" class="actionLinkLite viewLink nobreak">view »</a></div>
<a href="/review/destroy/12074927?return_url=http%3A%2F%2Fwww.goodreads.com%2Freview%2Flist%2F4111865%3Fshelf%3Dto-read" class="actionLinkLite smallText deleteLink" data-confirm="Are you sure you want to remove The Fractal Prince from your books? This will permanently remove this book from your shelves, including any review, rating, tags, or notes you have added. To change the shelf this book appears on please edit the shelves." data-method="post" rel="nofollow"> <img alt="Remove from my books" src="http://www.goodreads.com/assets/layout/delete.gif" title="Remove from my books">
<span class="label">remove book</span>
</a> </div>
</div></td>
</tr>
答案 0 :(得分:6)
该代码中存在至少3个问题:
你不能那样链getElementsByClassName
。该功能在 DOM元素 上运行,但返回 对象 强>
for (var book in books)
将在未考虑的对象属性上循环,并将使此代码崩溃。 books
是 对象 ,而不是 数组 。
book.style.backgroundColor
不是函数,也不是如何设置样式。
如今,getElementsByClassName
很少是这种事情的最佳方法;使用querySelectorAll
获取更多信息:灵活性/功效/精确度。
修复所有问题,这里的代码应工作 - 假设页面结构与问题的代码结构完全匹配。发布相关的HTML代码段和/或链接到确切的页面,如果没有。
// ==UserScript==
// @name Unpublished Lowlighter
// @description Makes the background of books not yet published on the Goodreads to-read shelf grey.
// @include http://www.goodreads.com/*
// ==/UserScript==
function dateColor() {
var books = document.querySelectorAll (
".bookalike.review .field.date_pub .value"
);
var today = new Date(); // More efficient, outside the loop.
for (var J = books.length - 1; J >= 0; --J) {
var book = books[J];
var dateString = book.textContent;
var date = new Date(dateString);
if (date > today) {
book.parentNode.parentNode.style.setProperty ("background", "Lightgrey");
}
}
}
dateColor();
答案 1 :(得分:4)
还有一个问题(除了尝试在NodeList上调用getElementsByClassName
)for (var book in books)
将无法执行您想要的操作。 in
没有按照您的预期执行foreach
;它从目标对象获取每个属性。由于Javascript对象的工作方式,对于数组,这将是数组索引;对于NodeList,它是NodeList的属性(将是数组索引,加上字符串“length”和字符串“item”),这对你的循环没有用。 / p>
你需要像
这样的东西for (var i = 0; i < books.length; ++i) {
var book = books[i];
...
}
答案 2 :(得分:3)
这不起作用:
book
.getElementsByClassName('field date_pub')
.getElementsByClassName('value')
getElementsByClassName
返回相应元素的类数组对象(给定类可以有多个)。您将不得不遍历每个并在每个上执行getElementsByClassName
。默认情况下,嵌套的getElementsByClassName
未合并。
答案 3 :(得分:2)
您只能在单个Element对象上使用getElementsByClassName,而不能像getElementsByClassName返回的那样使用NodeList或HTMLCollection。也就是说,问题可能在于您的链接调用,您可以再次调用该函数。
答案 4 :(得分:2)
问题是你是从getElementsByClassName
返回的数组调用函数。
假设您只是在寻找带有类名的第一个元素,这应该可以工作:
var dateString = book
.getElementsByClassName('field date_pub')[0]
.getElementsByClassName('value')[0]
.textContent;