2

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>編集: これは、テーブル内の1 つの 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> &nbsp;\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: [&quot;to-read&quot;]}); 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=&quot;error&quot;>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&amp;partial=bookalike&amp;view=table' + '&amp;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=&quot;error&quot;>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&amp;partial=bookalike&amp;view=table' + '&amp;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=&quot;error&quot;>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&amp;partial=bookalike&amp;view=table' + '&amp;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=&quot;error&quot;>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>
4

5 に答える 5

6

そのコードには少なくとも 3 つの問題があります。

  1. そのように連鎖することはできませんgetElementsByClassName。この関数はDOM 要素を操作しますが、オブジェクトを返します。

  2. for (var book in books)考慮されていないオブジェクト プロパティでループし、このコードをクラッシュさせます。 配列booksではなくオブジェクトです。

  3. book.style.backgroundColorは関数ではなく、スタイルを設定する方法ではありません。

  4. 今日で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();
于 2012-09-22T20:42:57.857 に答える
4

getElementsByClassName( NodeListを呼び出そうとする以外に)for (var book in books)あなたが望むことをしないさらなる問題があります。あなたが期待するようにinはしません。foreachターゲットオブジェクトからすべてのプロパティを取得します。Javascriptオブジェクトの動作方法により、配列の場合、これは配列インデックスになります。NodeListの場合、これはNodeListのプロパティ(配列インデックスに加えて、文字列"length"と文字列"item"になります)であり、ループには役立ちません。

あなたは次のようなものが必要です

for (var i = 0; i < books.length; ++i) {
    var book = books[i];
    ...
}
于 2012-09-22T14:24:45.967 に答える
3

これはうまくいきません:

book
    .getElementsByClassName('field date_pub')
    .getElementsByClassName('value')

getElementsByClassName適切な要素の配列のようなオブジェクトを返します (指定されたクラスには複数の要素が存在する可能性があります)。それぞれをループして、それぞれを実行する必要getElementsByClassNameがあります。ネストされたgetElementsByClassNames はデフォルトではマージされません。

于 2012-09-22T14:20:39.753 に答える
2

getElementsByClassName で返されるような NodeList や HTMLCollection ではなく、単一の Element オブジェクトでのみ getElementsByClassName を使用できます。つまり、問題はおそらく、その関数自体を再度呼び出す連鎖呼び出しにあります。

于 2012-09-22T14:20:00.457 に答える
2

問題は、によって返された配列から関数を呼び出していることですgetElementsByClassName

クラス名を持つ最初の要素を探しているだけだと仮定すると、これはうまくいくはずです:

var dateString = book
                    .getElementsByClassName('field date_pub')[0]
                    .getElementsByClassName('value')[0]
                    .textContent;
于 2012-09-22T14:21:34.423 に答える