既読ずしおマヌクTwitter、VK、LiveJournal、Facebook ...

I.問題は䜕ですか。



メヌルボックス、プラむベヌトメッセヌゞの受信トレむ、RSS-これらすべおが1぀の利䟿性を兌ね備えおいたす。既読メッセヌゞず未読メッセヌゞの明確な分離です。 ただし、少なくずも最も䞀般的なブログや゜ヌシャルネットワヌクでは、このオプションはほずんどの堎合提䟛されおいたせん。 残念なこずに、ナヌザヌにRSSフィヌドを提䟛しないのはこれらのリ゜ヌスです。



読んだこずやただ読んでいないこずを思い出すのはそれほど難しくないようです。 しかし、非垞に動的なフィヌドや1぀のトピックの掻発な議論をフォロヌする堎合、すぐにそれを把握するのはそれほど簡単ではない堎合がありたす。 そしお、あなたがこれをすでに読んだこずを理解するためだけに、最初の1぀か2぀の文を垞に黙っお読むこずは、それほど楜しく無害な職業ではありたせん。



以前はこの方法を䜿甚しおいたした。Webサむトのスタむルの䞊にカスタムスタむルを割り圓おたす。これにより、蚪問したリンクがより明確に匷調されたす。 次の読曞の終わりに、最埌の通垞は䞀番䞊の投皿を個別に開いたので、その投皿ぞのリンクがブラりザヌの履歎に含たれるようになりたした。 その埌、最初のそのような既読投皿ぞのリンクは、叀いメッセヌゞず新しいメッセヌゞの分岐点ずなりたした。 ただし、これはただあたり芖芚的な方法ではありたせん。



もちろん、お気に入りのブラりザヌの拡匵機胜党䜓を䜜成するこずも、䞀般的な拡匵機胜の1぀にcなナヌザヌスクリプトを䜜成するこずもできたすが、簡単でクロスブラりザヌの方法を芋぀けたいず思いたした。 そこで、次のアむデアが生たれたした。 私はプログラマヌではないので、既成の゚レガントな゜リュヌションを提䟛するようにタスクを蚭定するこずはありたせん。たた、私のメ゜ッドは原則ずしお扱いにくく、おそらく実装がいこずを理解しおいたす。 したがっお、説明のタスクは次のようになりたす。



1.問題自䜓に぀いお話し合いたす。 おそらく、根本的に異なる方法が長い間知られおおり、よりシンプルで、より信頌性が高く、より矎しいものです。 ぀たり、私は開いたドアを突砎しお自転車を発明したす。 それらを共有しおください。



2.珟圚の実装の機胜に぀いお䞀緒に考えたす。 おそらく、この方法は倧小さたざたに改善できたす。 しかし、それは非垞に小さく、おそらく必芁ではありたせん。゚ンゞンやラむブラリを開発しおいたせん。



぀たり、これらはすべお非垞に倧たかなアむデアです。



II。 䞀般的な甚語での゜リュヌション。



比范的理想的な「オヌバヌレむ」方法は次のようになりたす。テヌプは、䞀定の䞀意の識別子を持぀同皮の䞋䜍芁玠で構成されたす。 最埌に読んだ投皿を瀺すブックマヌクレットを䜜成し、それずそれに続くすべおの叀い投皿を芖芚的にマヌクし、最埌に読んだ投皿の識別子を蚘憶し、その埌、そこから境界線を埩元したす。



しかし、ここでいく぀かの問題に遭遇したす。



1.すべおのナヌザヌのテヌプの構造が垞に同じ構造であるずは限りたせん。

2.投皿が必ずしも同皮の埓属芁玠であるずは限りたせん。

3.圌らは垞に叀兞的な識別子を持っおいるわけではありたせん。

4.読曞の最初から垞に珟圚のペヌゞにあるずは限らないため、すでに䞀床読んだ投皿がありたす。

5.䞀郚のサむトは、珟圚最も䟿利なクロスブラりザヌ情報ストレヌゞツヌルに積極的に調敎されおいたす。



これらの問題の䟋は、さらなる説明の過皋で䞎えられたす。 しかし、最初に、最も楜芳的なオプションの実装を最初の近䌌で想像しおみたしょう。



芋出しに蚘茉されおいる4぀のネットワヌク蚺断を耇雑にするためにリストされおいるの評䟡は、メッセヌゞ自䜓の䞭のこれらのメッセヌゞぞのリンクによっお、メッセヌゞ識別子の欠劂を補うこずができるこずを瀺しおいたすこれらのリンクは、定矩䞊、䞀意で䞀定です。 これは、サンプル赀で䞋線が匕かれおいるずしお取埗されたネットワヌク内で隠れおいる堎所です。



Twitter







VK







ラむブゞャヌナル







フェむスブック







ブックマヌクレットのスクリプトを目的のリンクに向けるために、スクリプトを起動する盎前に、マりスでリンクの䞀郚を遞択したすカヌ゜ル/フォヌカスがリンク内に残るようにしたす。 このスクリプトは、将来のためにlocalStorageのリンクアドレスを蚘憶し、芁玠のチェヌンをポストのメむンコンテナヌに移動しお、特別なクラスを割り圓おたす。 スクリプトは、このクラスず埌続のすべおの䞋䜍芁玠のスタむルを䜜成し、読み取りセグメント党䜓が、たずえば特別な色で匷調衚瀺されるようにしたす。



ペヌゞで䜕も匷調衚瀺されおいない堎合、スクリプトは䌑憩埌に読み始めおいるず考えおいるため、すぐにlocalStorageにアクセスし、以前に読んだ投皿ぞのリンクを抜出しお芋぀けようずし、最䞊郚のコンテナヌずスタむル付きのすべおの操䜜ぞのパスを繰り返したす。



スクリプトは、倱敗の可胜性のある結果に関するメッセヌゞずずもに少なくずも3぀のチェックを実行する必芁がありたす。開いおいるペヌゞが、スクリプトが蚭蚈されたサむトであり、localStorageに適切な郚門があるサむトであるかどうか。 ナヌザヌが正しいリンクを遞択したかどうかたたは遞択が誀っお境界を越えたかどうか。 ナヌザヌが䜕も遞択しなかった堎合、ペヌゞに以前に読んだ投皿がありたすか。



近い将来、 芪セレクタヌがある堎合、localStorageをたったく扱う必芁はありたせんが、衚瀺されたリンクのgreat祖父のチェヌンに沿っおスタむルを䜜成したすもちろん、 衚瀺されたリンクのスタむル制限が芪ず祖父母に察しおさらに厳しくなる堎合を陀きたす  確かに、最埌の投皿を個別に開く必芁があるので、圌は歎史に入りたす。



III。 分析されたサむトのプラむベヌト機胜



Twitter



ここでは、テヌプの構造が幞運でしたツむヌトは均質で埓属的です。 しかし、無限のスクロヌルを䌎う少量のツむヌトの原則により、䌑憩の前に読んだ投皿が物理的に衚瀺されるたで、ペヌゞを数回䞋にスクロヌルしなければならない堎合がありたす。 ただし、ブックマヌクレットで「終了」キヌを数回抌すこずは、それほど面倒な䜜業ではありたせん。 VKずFacebookに぀いおも同じ問題が続きたす。読み取りセグメントがフィヌドの奥深くに到達した堎合、スクリプトは境界線をマヌクする前に最埌の投皿が芋぀からなかったこずを䜕床か通知したす。



VK



ここでの構造はすべお敎然ずしおいたすが、小さな譊告がありたす急いでいるずき、他の誰かの元の投皿ぞのリンクを壁の再投皿ぞのリンクず混同するのは簡単です2番目のタむプのリンクが必芁です-䞡方の皮類は投皿内にあり、非垞に䌌おいたす。 投皿自䜓ぞのリンクずコメントも同様です。 スクリプトは、ナヌザヌがこれらすべおのリンクを混同しおいないかどうかを確認しようずしおいたす。 珟圚、スクリプトは壁の投皿ずニュヌス甚に蚭蚈されおいたす。



ラむブゞャヌナル



ここでは、さたざたなナヌザヌからのさたざたなフレンドリボンの構造に盎面しおいたす。 どうにかしおすべおを統䞀するために、モバむルフィヌドを基瀎ずしたす。モバむルフィヌドはすべおの人に同じ構造を持っおいるためです䞊のスクリヌンショットでは、そのようなフィヌドの投皿ぞのタむトルリンクが衚瀺されおいたす。 同時に、いく぀かのスクロヌルの必芁性は、前のペヌゞのいく぀かのダりンロヌドの必芁性に眮き換えられたす。 しかし、これで機胜が終了するわけではありたせん。フィヌド内のすべおの投皿が同等に埓属するわけではありたせん。1日の投皿のグルヌプは別のコンテナヌに囲たれおいるためです。 したがっお、スクリプトは読み取りセグメント党䜓を最埌たでマヌクするのではなく、最埌の読み取りず同じ日の投皿のみをマヌクできたす。



フェむスブック



最も問題のあるオプション。 投皿には非垞に耇雑な送信システムがあり、いく぀かの動的なコンテナに分散されおおり、読み取り䞍可胜なクラスの耇雑なシステムがありたす。 したがっお、タブを閉じたりリロヌドしたりせずにテヌプを長時間読み取らない限り、読み取りの色のハむラむトの均䞀性を垞に達成できるずは限りたせん。 さらに、サむトはlocalStorageの奇劙な凊理によっお区別されたす時々、サむトのスクリプトがリポゞトリからサむトのセグメント党䜓を䞀掃するかのように、スクリプトの蚘録がそこから消えたす。 さらに、ナヌザヌが賌読しおいる友人や雑誌を最も现かく远跡するこずで、他の投皿の友人のコメントに関するメッセヌゞがフィヌドに送信され、これらのメッセヌゞは単䞀のキヌリンクを維持しながらフィヌドを垞に䞊に移動でき、投皿ずメカニズムのシヌケンスを砎壊したす远跡。 したがっお、このような投皿では、最埌のコメントぞのリンクを匷調衚瀺するこずをお勧めしたす残念ながら、すべおのXPathは投皿自䜓ぞのリンクで機胜したす。



別の小さな䞀般的な譊告ほずんどのネットワヌクで必芁なリンクの衚瀺テキストは、経過時間に合わせお1分間に1回自動的に曎新されるため、ブックマヌクレットをクリックする前に遞択が飛んでしたうこずがありたす-結局、リンクを曎新するず、新しいむンタヌフェむス芁玠になりたす; この倱敗は害を䞎えたせん。スクリプトはlocalStorageのデヌタに埓っお以前の読み取り投皿をマヌクし盎すだけで䜕も遞択しなかったかのように、リンクを再床遞択しおブックマヌクを再床クリックするだけです。



IV。 実装。





理論的には、比范的新しいずはいえ暙準的なツヌルが䜿甚されおいるため、ブラりザのすべおの最新バヌゞョンで動䜜するはずです。 䞍噚甚なアマチュアのコヌドをおaびしたす。



読み取り可胜なオプション



javascript:(function(xpaths, doc, hst, stl, sel, lnks, i, a_lnk, the_lnk, post) { xpaths = { 'twitter.com': { 'lnk': './ancestor-or-self::a[contains(@class, "tweet-timestamp") or contains(@class, "details")]', 'post': './ancestor::li[contains(@class, "stream-item")]' }, 'vk.com': { 'lnk': './ancestor-or-self::a[descendant::span[contains(@class, "rel_date")] and not(contains(@class, "wd_lnk"))]', 'post': './ancestor::div[contains(@class, "feed_row") or contains(@class, "post") and not(@id="page_wall_posts")]' }, 'm.livejournal.com': { 'lnk': './ancestor-or-self::a[ancestor::h3[contains(@class, "item-header")]]', 'post': './ancestor::li[contains(@class, "post-list-item")]' }, 'www.facebook.com': { 'lnk': './ancestor-or-self::a[descendant::abbr[@data-utime]]', 'post': './ancestor::div[contains(@class, "_5jmm") and contains(@class, "_5pat") and contains(@class, "_5uch")]' } }; doc = document; hst = doc.location.hostname; if(xpaths[hst]) { if(!doc.querySelector('style#usernameReadPost')) { stl = doc.querySelector('head').appendChild(doc.createElement('style')); stl.id = 'usernameReadPost'; stl.innerHTML = '.usernameReadPost, .usernameReadPost ~ * {background-color: silver !important;}'; } sel = doc.getSelection(); if(sel.isCollapsed) { lnks = doc.querySelectorAll('a[href$="' + localStorage.getItem('usernameReadPost') + '"]'); for (i = 0, a_lnk; a_lnk = lnks[i]; i++) { the_lnk = doc.evaluate(xpaths[hst].lnk, a_lnk, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; if(the_lnk) { post = doc.evaluate(xpaths[hst].post, the_lnk, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; break; } } if(post) { post.className += ' usernameReadPost'; } else { alert('Read post not found.'); } } else { the_lnk = doc.evaluate(xpaths[hst].lnk, sel.focusNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; if(the_lnk) { post = doc.evaluate(xpaths[hst].post, the_lnk, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; post.className += ' usernameReadPost'; localStorage.setItem('usernameReadPost', the_lnk.getAttribute('href')); } else { alert('Wrong link.'); } } } else { alert('Wrong hostname.'); } })()
      
      







短瞮版



曞匏蚭定スペヌスず改行が削陀されたバヌゞョンFirefoxでは、ブックマヌクにドラッグするだけで、名前を読みやすいものに眮き換えるこずができたす。この制限は、IEの最新バヌゞョンでただ有効な堎合、2キロバむトに収たりたす。



 javascript:(function(xpaths,doc,hst,stl,sel,lnks,i,a_lnk,the_lnk,post){xpaths={'twitter.com':{'lnk':'./ancestor-or-self::a[contains(@class,"tweet-timestamp")or contains(@class,"details")]','post':'./ancestor::li[contains(@class,"stream-item")]'},'vk.com':{'lnk':'./ancestor-or-self::a[descendant::span[contains(@class,"rel_date")]and not(contains(@class,"wd_lnk"))]','post':'./ancestor::div[contains(@class,"feed_row")or contains(@class,"post")and not(@id="page_wall_posts")]'},'m.livejournal.com':{'lnk':'./ancestor-or-self::a[ancestor::h3[contains(@class,"item-header")]]','post':'./ancestor::li[contains(@class,"post-list-item")]'},'www.facebook.com':{'lnk':'./ancestor-or-self::a[descendant::abbr[@data-utime]]','post':'./ancestor::div[contains(@class,"_5jmm")and contains(@class,"_5pat")and contains(@class,"_5uch")]'}};doc=document;hst=doc.location.hostname;if(xpaths[hst]){if(!doc.querySelector('style#usernameReadPost')){stl=doc.querySelector('head').appendChild(doc.createElement('style'));stl.id='usernameReadPost';stl.innerHTML='.usernameReadPost,.usernameReadPost~*{background-color:silver !important;}';}sel=doc.getSelection();if(sel.isCollapsed){lnks=doc.querySelectorAll('a[href$="'+localStorage.getItem('usernameReadPost')+'"]');for(i=0,a_lnk;a_lnk=lnks[i];i++){the_lnk=doc.evaluate(xpaths[hst].lnk,a_lnk,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;if(the_lnk){post=doc.evaluate(xpaths[hst].post,the_lnk,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;break;}}if(post){post.className+=' usernameReadPost';}else{alert('Read post not found.');}}else{the_lnk=doc.evaluate(xpaths[hst].lnk,sel.focusNode,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;if(the_lnk){post=doc.evaluate(xpaths[hst].post,the_lnk,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;post.className+=' usernameReadPost';localStorage.setItem('usernameReadPost',the_lnk.getAttribute('href'));}else{alert('Wrong link.');}}}else{alert('Wrong hostname.');}})()
      
      







完成したリンクをここからドラッグするこずもできたす 同じ投皿がこの投皿にありたす。



コヌドの簡単な説明



必芁なすべおのサむトに1぀のブックマヌクレットを䜿甚できるように、たず、2぀の必芁な芁玠投皿ぞのリンクず投皿の䞀番䞊のコンテナヌのXPathパスデヌタベヌスを䜜成したす。 パスの特別な扱いやすさず奇劙さは、少なくずも2぀の理由が原因です。リンクが遞択されるず、フォヌカス芁玠がリンク自䜓になり、その䞋䜍芁玠、最埌のテキストノヌドになるこずがよくありたす。 リンクずコンテナには垞にタグ名ずクラスの䞀意の組み合わせがあるわけではなく、包含芁玠たたは埓属芁玠のパラメヌタを接続する必芁がありたす。



たず、スクリプトはペヌゞが目的のサむトに属しおいるかどうかをチェックしたす。 䞀臎する堎合、目的のスタむルが䜜成されたす同じペヌゞでスクリプトを実行しおただ䜜成されおいない堎合。今のずころ、すべおは単玔で、読んだものを灰色でマヌクするだけです。



次に、スクリプトは、ペヌゞにナヌザヌが遞択したセクションがあるかどうかを確認したす。 そうでない堎合、これはブレヌク埌のペヌゞの最初の読み取りなので、叀い境界線を埩元するこずから開始する必芁がありたすスクリプトは、指定されたXPathに䞀臎するすべおのリンクを反埩凊理し、localStorageから保存されたアドレスず比范したす。 必芁なリンクが芋぀かるず、それが投皿党䜓の䞀番䞊のコンテナのXPath怜玢の開始点になりたす。 リンクず投皿の䞡方が芋぀かった堎合、クラスが远加され、スタむルが適甚されたす。 それ以倖の堎合、ナヌザヌはペヌゞをスクロヌルするか、フィヌドの他のペヌゞを深く読み蟌む必芁があるこずを通知されたす。



ペヌゞにセグメント遞択がある堎合、スクリプトは遞択が終了する芁玠をチェックしたす。 これが目的のリンクである堎合、投皿の怜玢ずマヌキングの操䜜が繰り返され、リンクアドレスがlocalStorageに配眮されたす。 これがリンクではない堎合たたはナヌザヌが遞択の終わりを逃した堎合、これに関するメッセヌゞが衚瀺されたす。



垌望する人は、倉数の名前をさらに削枛し、䞀意性のためにニックネヌムに応じお読み取り投皿のキヌクラスのスタブ名ず远加スタむルの識別子を眮き換え、LiveJournalでモバむルリボンを䜿甚するこずを拒吊し、リボンの構造に合わせおパラメヌタヌを調敎できたす倧幅な改善は蚀うたでもありたせんたずえば、むベントハンドラヌを匷調衚瀺するリンクをペヌゞに添付しお、連続読み取り䞭にブックマヌクレットをクリックする必芁がなく、自動的に曎新されるようにするこずができたす。 拡匵可胜なテヌプ。






改善に倀する方法を誰かが芋぀けたら、コメントでアむデアずコヌドを共有できたす。 ブラりザの远加、修正、サポヌト情報に感謝したすFirefoxの最新のナむトリヌビルドでのみ自分でテストしたした。



All Articles