mirror of
https://github.com/Andre-Bzk/rin-mobile-userscript.git
synced 2026-11-15 09:33:08 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7f3f56456 | ||
|
|
a8ca211805 | ||
|
|
21820b88d0 |
@@ -13,6 +13,8 @@ die `.user.js`-Datei ist das Produkt.
|
|||||||
| `dev/index.php` | — | Fixture: Forumwurzel, zwei Kategorien mit Forenzeilen, keine Paginierung |
|
| `dev/index.php` | — | Fixture: Forumwurzel, zwei Kategorien mit Forenzeilen, keine Paginierung |
|
||||||
| `dev/ucp.php` | — | Fixture: Login-Formular (`mode=login`), nur ausgeloggter Zustand |
|
| `dev/ucp.php` | — | Fixture: Login-Formular (`mode=login`), nur ausgeloggter Zustand |
|
||||||
| `dev/after_login/ucp.php` | — | Fixture: dieselbe URL nach erfolgreichem Login, "Information"-Vorlage statt Formular |
|
| `dev/after_login/ucp.php` | — | Fixture: dieselbe URL nach erfolgreichem Login, "Information"-Vorlage statt Formular |
|
||||||
|
| `dev/search.php` | — | Fixture: Suchformular ohne Treffer, eingeloggt aufgenommen |
|
||||||
|
| `dev/search2.php` | — | Fixture: Suchtreffer im Modus "Posts" (15 von 1438 Treffern, `t=63042`, `per_page=15`, 96 Seiten) |
|
||||||
|
|
||||||
Die Fixtures sind ueber `.gitignore` (`dev/*.php`) ausgeschlossen. Nach einem
|
Die Fixtures sind ueber `.gitignore` (`dev/*.php`) ausgeschlossen. Nach einem
|
||||||
frischen Klon sind sie nicht da und muessen nach der Anleitung in der README neu
|
frischen Klon sind sie nicht da und muessen nach der Anleitung in der README neu
|
||||||
@@ -203,6 +205,90 @@ Original-Zurueck/Weiter-Links, das Sheet verschwindet.
|
|||||||
einer verschachtelten Tabelle, `closest('tr')` trifft die innere Zeile ohne
|
einer verschachtelten Tabelle, `closest('tr')` trifft die innere Zeile ohne
|
||||||
Autor- und Profilspalte.
|
Autor- und Profilspalte.
|
||||||
|
|
||||||
|
**Die Lupe und die Login-Pille haengen an einer gemeinsamen `margin-left:auto`
|
||||||
|
auf einem Wrapper (`.rm-auth-group`), nicht je an sich selbst.** Saesse die
|
||||||
|
Regel wie zuvor direkt auf `.rm-auth`, wuerde nur die Pille an den Rand
|
||||||
|
geschoben und die Lupe bliebe links davon kleben — mit sichtbarer Luecke
|
||||||
|
dazwischen statt „direkt links neben der Pille". Die Lupe existiert im Markup
|
||||||
|
ohnehin nur bei bestehender Sitzung; ausgeloggt bleibt der Wrapper mit der
|
||||||
|
Pille als einzigem Kind und verhaelt sich exakt wie vorher.
|
||||||
|
|
||||||
|
**`#topic-search` steht dreifach identisch im Thread-Markup** (Kopf, Fuss,
|
||||||
|
ueber der Beitragsliste), jedes Mal mit derselben, eigentlich unzulaessigen
|
||||||
|
`id`. `document.querySelector('#topic-search')` trifft einfach das erste und
|
||||||
|
verschiebt es unveraendert in die zweite Leiste — alle drei tragen dieselben
|
||||||
|
versteckten Felder (`t`, `sf`, `terms`), welches der drei benutzt wird, ist
|
||||||
|
gleichgueltig.
|
||||||
|
|
||||||
|
**`select[name="fid[]"]` ist der einzige verlaessliche Marker fuer das grosse
|
||||||
|
Suchformular auf `search.php`.** Sowohl `viewforum.php` als auch
|
||||||
|
`viewtopic.php` betten ein eigenes Mini-Suchformular ein (`#forum-search` /
|
||||||
|
`#topic-search`, „Search this forum…" / „Search this topic…"), beide mit
|
||||||
|
`action="./search.php"` und einem Feld `name="keywords"` — nach diesen Merkmalen
|
||||||
|
allein liesse sich das grosse Formular nicht von den kleinen unterscheiden.
|
||||||
|
Der mehrfach waehlbare Forenwaehler existiert dagegen nur im grossen Formular.
|
||||||
|
|
||||||
|
**Die Textfelder des Suchformulars tragen `style="width: 300px"` direkt im
|
||||||
|
Markup.** Eine externe Regel ohne `!important` sticht dagegen nicht, egal wie
|
||||||
|
spezifisch der Selektor ist — `buildSearchForm()` entfernt das
|
||||||
|
`style`-Attribut deshalb, statt gegen es anzuschreiben.
|
||||||
|
|
||||||
|
**Eine abgeschickte Suche liefert keine Themenliste, sondern einen ganz
|
||||||
|
anderen Aufbau.** Die anfaengliche Annahme, Trefferzeilen tragen dieselben
|
||||||
|
`topictitle`-Links wie eine Themenliste und laufen unveraendert durch
|
||||||
|
`buildList()`, stimmte nicht — zumindest nicht im Modus "Posts" (`sr=posts`),
|
||||||
|
der ueber die zweite Leiste im Thread entsteht, weil deren Formular kein `sr`
|
||||||
|
setzt. Jeder Treffer ist stattdessen ein Beitragsauszug: Autor, Zeitstempel,
|
||||||
|
Forum/Thema-Kontext, ein Stueck `postbody`. `buildSearchResults()` erkennt
|
||||||
|
diesen Modus an `p.topictitle` — als `<p>`, nicht als `<a>` wie das
|
||||||
|
gleichnamige Klassenpendant einer Themenzeile in `viewforum.php` — und baut
|
||||||
|
daraus eigene Karten (`buildHit()`), bevor `buildList()`s allgemeines
|
||||||
|
Zeileneinsammeln ueberhaupt anfaengt und die enthaltenen `viewtopic.php`-Links
|
||||||
|
falsch klassifizieren wuerde. Ungeprueft bleibt der Modus "Topics" (`sr=topics`,
|
||||||
|
Vorauswahl im grossen Suchformular) — dafuer liegt keine Fixture vor, dort
|
||||||
|
sehen Treffer laut phpBB-Doku tatsaechlich wie topictitle-Zeilen aus und
|
||||||
|
wuerden vermutlich durch den regulaeren Listenzweig laufen, das ist aber nicht
|
||||||
|
verifiziert.
|
||||||
|
|
||||||
|
**Ein Treffer im Modus "Posts" besteht aus drei `<tr>`, unterscheidbar nur an
|
||||||
|
der Position, nicht an einer Klasse.** Titelzeile (`p.topictitle`), Autor-
|
||||||
|
und Betreffzeile, dann Antworten/Views samt Beitragsauszug — alle drei
|
||||||
|
tragen row1/row2 wahllos, die einzige verlaessliche Zuordnung ist
|
||||||
|
`nextElementSibling` von der Titelzeile aus.
|
||||||
|
|
||||||
|
**Der Beitragsauszug haengt in `<td class="postbody">`, nicht in
|
||||||
|
`div`/`span.postbody` wie im echten Thread.** `buildHit()` verschiebt das
|
||||||
|
`<td>` trotzdem unveraendert per `appendChild()` in `.rm-body` — das ist reine
|
||||||
|
DOM-Manipulation, keine Neuparse, darum meckert der Browser nicht ueber ein
|
||||||
|
`<td>` ausserhalb einer Tabelle. Es rendert danach aber weiterhin als
|
||||||
|
`display:table-cell`, wenn `.rm-root.rm-hits .rm-body > td` das nicht
|
||||||
|
ausdruecklich auf `block` zwingt.
|
||||||
|
|
||||||
|
**"Replies: 5403" und "Views: 951837" stehen im Markup nur durch ein `<br />`
|
||||||
|
getrennt, ohne Leerzeichen.** `txt()` normalisiert Whitespace, erzeugt aber
|
||||||
|
keinen wo im Original-Markup keiner steht — `txt(meta)` liefert deshalb
|
||||||
|
`5403Views:951837` statt zwei getrennter Werte. `buildHit()` greift beide
|
||||||
|
Zahlen einzeln per Regex heraus und reicht sie an dieselbe `metaRow()` wie bei
|
||||||
|
Themenkarten weiter, die den Trenner per CSS (`::before`) selbst einfuegt.
|
||||||
|
|
||||||
|
**`input[type="submit"]`/`input[type="reset"]` setzen eigenes Padding und
|
||||||
|
Zentrierung in iOS Safari unzuverlaessig um — auch mit `-webkit-appearance:
|
||||||
|
none`.** Zuerst aufgefallen bei Suchen/Zuruecksetzen im Suchformular
|
||||||
|
nebeneinander, wo die feste Flex-Aufteilung die Verzerrung besonders sichtbar
|
||||||
|
machte: zu schmale Buttons, Text nicht mittig. `-webkit-appearance:none` plus
|
||||||
|
`box-sizing:border-box`/`line-height:normal` (erster Versuch) reichte laut
|
||||||
|
Test am Geraet nicht aus — das legt einen tieferen WebKit-Bug nahe, bei dem
|
||||||
|
`input[type=submit/reset]` die native Knopfoptik trotz `appearance:none` nicht
|
||||||
|
vollstaendig ablegt. Der tragfaehige Fix ist `inputToButton()`: die
|
||||||
|
Original-`<input>`-Elemente werden vor dem Verschieben durch echte
|
||||||
|
`<button type="submit/reset">` ersetzt (Name und Value wandern mit, am
|
||||||
|
uebermittelten Formularfeld aendert sich nichts) — `<button>` wird von WebKit
|
||||||
|
unter `appearance:none` zuverlaessig respektiert. Betrifft grundsaetzlich
|
||||||
|
jeden Submit-Button im Script: Suchformular, Login, Thread-Suchleiste nutzen
|
||||||
|
alle `inputToButton()`. Ungeprueft, ob `-webkit-appearance:none` allein bei
|
||||||
|
einer anderen iOS-Version genuegt haette — der Wechsel auf `<button>` umgeht
|
||||||
|
die Frage, statt sie zu beantworten.
|
||||||
|
|
||||||
**`DEBUG` steht auf `true`** und muss vor dem Ausliefern auf `false`. Die
|
**`DEBUG` steht auf `true`** und muss vor dem Ausliefern auf `false`. Die
|
||||||
Versionsnummer steht doppelt: im `@version`-Header und im Text des
|
Versionsnummer steht doppelt: im `@version`-Header und im Text des
|
||||||
Debug-Overlays.
|
Debug-Overlays.
|
||||||
@@ -267,6 +353,27 @@ Kategorien mit zusammen 16 Forenkarten, keine Paginierung. Zu pruefen ist
|
|||||||
zusaetzlich eine `ucp.php?mode=login&redirect=index.php`-URL — sie muss trotz
|
zusaetzlich eine `ucp.php?mode=login&redirect=index.php`-URL — sie muss trotz
|
||||||
des `index.php`-Substrings im Login-Zweig landen, nicht im Listen-Zweig.
|
des `index.php`-Substrings im Login-Zweig landen, nicht im Listen-Zweig.
|
||||||
|
|
||||||
|
Fuer das Suchformular genuegt `dev/search.php` unveraendert, URL
|
||||||
|
`search.php`: geprueft werden der Forenwaehler als Erkennungsmerkmal, das
|
||||||
|
verschobene Formular samt versteckter Felder (`t`, `sid`), die entfernten
|
||||||
|
inline-`style`-Attribute der Textfelder und die Schnellzugriffs-Chips aus
|
||||||
|
`p.searchbar`. Zu pruefen ist ausserdem `dev/viewforum.php` auf derselben
|
||||||
|
Weiche: dessen eingebettetes `#forum-search`-Mini-Formular teilt sich Aktion
|
||||||
|
und `keywords`-Feld mit dem grossen Suchformular und darf `buildSearchForm()`
|
||||||
|
nicht faelschlich auslösen, die Forenliste muss wie gewohnt Karten liefern.
|
||||||
|
|
||||||
|
Fuer Suchtreffer genuegt `dev/search2.php` unveraendert, URL beliebig (die
|
||||||
|
Erkennung haengt nicht an `location`, sondern an `p.topictitle` im Markup):
|
||||||
|
geprueft werden alle 15 Trefferkarten, die verschobene "Searched topic /
|
||||||
|
Search term used"-Zelle samt ihrer beiden Links, Autor und Zeitstempel pro
|
||||||
|
Treffer, die per Regex getrennten Antworten-/Views-Zahlen, der verschobene
|
||||||
|
`td.postbody`-Beitragsauszug und die Seitennavigation (`per_page=15`, 96
|
||||||
|
Seiten). Zu pruefen ist ausserdem, dass `dev/search.php` (das leere Formular)
|
||||||
|
weiterhin den Formular-Zweig trifft und nicht in die Treffer-Erkennung faellt,
|
||||||
|
und dass `dev/viewforum.php` weiterhin normale Karten liefert — beide haben
|
||||||
|
kein `p.topictitle`. Der Modus "Topics" (`sr=topics`) ist mangels Fixture
|
||||||
|
ungeprueft.
|
||||||
|
|
||||||
Am Geraet zu pruefen bleibt, was Blink nicht zeigt: `env(safe-area-inset-*)`,
|
Am Geraet zu pruefen bleibt, was Blink nicht zeigt: `env(safe-area-inset-*)`,
|
||||||
fixierte Leisten gegen Safaris ein- und ausfahrende Toolbar,
|
fixierte Leisten gegen Safaris ein- und ausfahrende Toolbar,
|
||||||
`-webkit-backdrop-filter`, Schriftskalierung. Details und die
|
`-webkit-backdrop-filter`, Schriftskalierung. Details und die
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ account name accordingly. The name is parsed from the link text with a
|
|||||||
if it ever fails to match — a different language, a different bracket style —
|
if it ever fails to match — a different language, a different bracket style —
|
||||||
the pill still shows "Logout", just without a name, rather than breaking.
|
the pill still shows "Logout", just without a name, rather than breaking.
|
||||||
|
|
||||||
|
Once a session exists, the login pill also carries a magnifier button
|
||||||
|
directly to its left, so it does not compete with the breadcrumb trail for
|
||||||
|
space and only shows up where cs.rin.ru's own search is actually reachable.
|
||||||
|
Outside a thread it links straight to `search.php`; inside one it instead
|
||||||
|
reveals a second bar under the crumbs with a search field, reusing the
|
||||||
|
original "Search this topic…" form in place rather than rebuilding it, so the
|
||||||
|
hidden topic-id and scope fields stay intact.
|
||||||
|
|
||||||
The login form itself is not rebuilt from scratch: the original `<form>`
|
The login form itself is not rebuilt from scratch: the original `<form>`
|
||||||
element is moved into the new layout and restyled, table rows collapsed to a
|
element is moved into the new layout and restyled, table rows collapsed to a
|
||||||
vertical stack. Reusing the element rather than reconstructing it keeps the
|
vertical stack. Reusing the element rather than reconstructing it keeps the
|
||||||
@@ -87,6 +95,27 @@ header followed by a message cell), not by its wording, and restyles it the
|
|||||||
same way as the form: the original cell — message and link included — is
|
same way as the form: the original cell — message and link included — is
|
||||||
reused in place rather than rebuilt.
|
reused in place rather than rebuilt.
|
||||||
|
|
||||||
|
`search.php` gets its own treatment when it shows the query form rather than
|
||||||
|
results. It is recognised by its forum picker — a `select[name="fid[]"]`
|
||||||
|
multi-select that only exists on this form, not on the small "Search this
|
||||||
|
forum…" / "Search this topic…" widgets embedded elsewhere — and then moved
|
||||||
|
into the new layout the same way the login form is: table rows collapsed to a
|
||||||
|
vertical stack, radio groups and selects restyled for touch, and the quick
|
||||||
|
links above it ("View new posts", "View your posts", …) turned into a row of
|
||||||
|
chips. "Search in forums" defaults to Main Forum and "Search subforums"
|
||||||
|
defaults to No, overriding the server's own blank/Yes defaults, since that is
|
||||||
|
the scope most searches from the mobile view actually want.
|
||||||
|
|
||||||
|
A submitted search lands back on `search.php`, now with results — which, in
|
||||||
|
the "Posts" display mode the in-thread search bar produces, look nothing like
|
||||||
|
a topic list: each hit is a post excerpt with its own author, timestamp, and
|
||||||
|
forum/topic context. Recognised by a `p.topictitle` marker unique to this
|
||||||
|
mode, these get their own cards, built before the regular list view's row
|
||||||
|
scanning would otherwise misread the topic and profile links inside them. The
|
||||||
|
"Topics" display mode is not handled specially — no fixture shows what it
|
||||||
|
looks like, so it still falls through to the regular list view, which may or
|
||||||
|
may not render it sensibly.
|
||||||
|
|
||||||
The script runs at `document-start`, injects a mobile viewport meta tag, and
|
The script runs at `document-start`, injects a mobile viewport meta tag, and
|
||||||
carries a `DEBUG` flag. While `DEBUG` is `true`, a green diagnostic overlay is
|
carries a `DEBUG` flag. While `DEBUG` is `true`, a green diagnostic overlay is
|
||||||
prepended to the page showing which view was chosen and how many rows were
|
prepended to the page showing which view was chosen and how many rows were
|
||||||
@@ -291,6 +320,15 @@ gegen das Markup einer echten eingeloggten Sitzung bestätigt ist; greift es
|
|||||||
einmal nicht — andere Sprache, andere Klammerform — bleibt die Pille bei
|
einmal nicht — andere Sprache, andere Klammerform — bleibt die Pille bei
|
||||||
„Logout" stehen, nur ohne Namen, statt zu reißen.
|
„Logout" stehen, nur ohne Namen, statt zu reißen.
|
||||||
|
|
||||||
|
Besteht eine Sitzung, trägt die Login-Pille zusätzlich einen Lupen-Button
|
||||||
|
direkt links neben sich, damit er nicht mit der Brotkrumenleiste um Platz
|
||||||
|
konkurriert, und erscheint nur dort, wo cs.rins eigene Suche überhaupt
|
||||||
|
erreichbar ist. Außerhalb eines Threads führt er direkt zu `search.php`;
|
||||||
|
innerhalb eines Threads blendet er stattdessen eine zweite Leiste unter den
|
||||||
|
Brotkrumen mit einem Suchfeld ein — das ist das Original-Formular „Search this
|
||||||
|
topic…", unverändert an Ort und Stelle wiederverwendet statt neu gebaut, damit
|
||||||
|
die versteckten Felder für Themen-Id und Suchbereich erhalten bleiben.
|
||||||
|
|
||||||
Das Login-Formular selbst wird nicht neu gebaut: das Original-`<form>`-Element
|
Das Login-Formular selbst wird nicht neu gebaut: das Original-`<form>`-Element
|
||||||
wandert unverändert in das neue Layout und wird umgestylt, Tabellenzeilen
|
wandert unverändert in das neue Layout und wird umgestylt, Tabellenzeilen
|
||||||
werden zu einer senkrechten Abfolge zusammengeklappt. Die Wiederverwendung
|
werden zu einer senkrechten Abfolge zusammengeklappt. Die Wiederverwendung
|
||||||
@@ -308,6 +346,29 @@ Nachrichtenzelle), und stylt sie wie das Formular um: die Original-Zelle —
|
|||||||
Nachricht und Link inklusive — wandert unverändert an ihren Platz statt neu
|
Nachricht und Link inklusive — wandert unverändert an ihren Platz statt neu
|
||||||
gebaut zu werden.
|
gebaut zu werden.
|
||||||
|
|
||||||
|
`search.php` bekommt eine eigene Behandlung, wenn es das Suchformular statt
|
||||||
|
Treffern zeigt. Erkannt wird das am Forenwähler — einem Mehrfachauswahlfeld
|
||||||
|
`select[name="fid[]"]`, das es nur in diesem Formular gibt, nicht in den
|
||||||
|
kleinen „Search this forum…" / „Search this topic…"-Widgets an anderer
|
||||||
|
Stelle — und dann wie das Login-Formular in das neue Layout verschoben:
|
||||||
|
Tabellenzeilen zu einer senkrechten Abfolge zusammengeklappt, Radio-Gruppen
|
||||||
|
und Auswahlfelder für Touch umgestylt, die Schnellzugriffe darüber („View new
|
||||||
|
posts", „View your posts", …) zu einer Reihe aus Chips. „Search in forums"
|
||||||
|
ist dabei standardmäßig auf Main Forum vorausgewählt, „Search subforums" auf
|
||||||
|
No — statt der leeren/„Yes"-Vorgabe des Servers, weil das dem Suchumfang
|
||||||
|
entspricht, der von der mobilen Ansicht aus meistens gewollt ist.
|
||||||
|
|
||||||
|
Eine abgeschickte Suche landet wieder auf `search.php`, diesmal mit Treffern —
|
||||||
|
die im Anzeigemodus „Posts", den die Suchleiste im Thread erzeugt, aber
|
||||||
|
überhaupt nicht wie eine Themenliste aussehen: jeder Treffer ist ein
|
||||||
|
Beitragsauszug mit eigenem Autor, Zeitstempel und Forum-/Thema-Kontext.
|
||||||
|
Erkannt an einem Merkmal (`p.topictitle`), das es nur in diesem Modus gibt,
|
||||||
|
bekommen sie eigene Karten, gebaut bevor das Zeileneinsammeln der gewöhnlichen
|
||||||
|
Listenansicht die enthaltenen Themen- und Profillinks falsch deuten würde.
|
||||||
|
Der Anzeigemodus „Topics" bekommt keine eigene Behandlung — keine Fixture
|
||||||
|
zeigt, wie er aussieht, er läuft also weiterhin durch die gewöhnliche
|
||||||
|
Listenansicht, was passend sein kann oder auch nicht.
|
||||||
|
|
||||||
Das Script läuft bei `document-start`, setzt ein mobiles Viewport-Meta-Tag und
|
Das Script läuft bei `document-start`, setzt ein mobiles Viewport-Meta-Tag und
|
||||||
hat ein `DEBUG`-Flag. Solange `DEBUG` auf `true` steht, wird ein grünes
|
hat ein `DEBUG`-Flag. Solange `DEBUG` auf `true` steht, wird ein grünes
|
||||||
Diagnose-Overlay über die Seite gelegt, das zeigt, welche Ansicht gewählt wurde
|
Diagnose-Overlay über die Seite gelegt, das zeigt, welche Ansicht gewählt wurde
|
||||||
|
|||||||
+416
-7
@@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name RIN Mobile
|
// @name RIN Mobile
|
||||||
// @description Mobile Ansicht fuer cs.rin.ru: Themenlisten als Karten, Threads als Beitragsstrom
|
// @description Mobile Ansicht fuer cs.rin.ru: Themenlisten als Karten, Threads als Beitragsstrom
|
||||||
// @version 3.8
|
// @version 3.14
|
||||||
// @match *://cs.rin.ru/forum/*
|
// @match *://cs.rin.ru/forum/*
|
||||||
// @run-at document-start
|
// @run-at document-start
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
@@ -17,6 +17,23 @@
|
|||||||
function txt(el) { return (el ? el.textContent || '' : '')
|
function txt(el) { return (el ? el.textContent || '' : '')
|
||||||
.replace(/\s+/g, ' ').trim(); }
|
.replace(/\s+/g, ' ').trim(); }
|
||||||
|
|
||||||
|
// input[type=submit]/[type=reset] behalten in iOS Safari trotz
|
||||||
|
// -webkit-appearance:none teils ihre native Knopfoptik und setzen eigenes
|
||||||
|
// Padding und Zentrierung nur unzuverlaessig um — ein echtes <button> wird
|
||||||
|
// unter appearance:none dagegen zuverlaessig respektiert. name und value
|
||||||
|
// wandern mit, damit sich am uebermittelten Formularfeld nichts aendert.
|
||||||
|
function inputToButton(input) {
|
||||||
|
if (!input) return null;
|
||||||
|
var btn = document.createElement('button');
|
||||||
|
btn.type = input.type;
|
||||||
|
if (input.name) btn.name = input.name;
|
||||||
|
if (input.hasAttribute('value')) btn.value = input.value;
|
||||||
|
btn.className = input.className;
|
||||||
|
btn.textContent = input.value;
|
||||||
|
input.replaceWith(btn);
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
// Der Seitentyp entscheidet, welche Ansicht gebaut wird. Beide Ansichten
|
// Der Seitentyp entscheidet, welche Ansicht gebaut wird. Beide Ansichten
|
||||||
// liegen in einem Script, weil sie sich Grundstile und Klassennamen teilen.
|
// liegen in einem Script, weil sie sich Grundstile und Klassennamen teilen.
|
||||||
// Als getrennte Scripts waren auf Threadseiten beide Stylesheets aktiv und
|
// Als getrennte Scripts waren auf Threadseiten beide Stylesheets aktiv und
|
||||||
@@ -86,10 +103,21 @@
|
|||||||
color:#eee !important; text-decoration:none !important; }
|
color:#eee !important; text-decoration:none !important; }
|
||||||
.rm-crumbs a:last-of-type { font-weight:650; }
|
.rm-crumbs a:last-of-type { font-weight:650; }
|
||||||
.rm-crumbs .rm-sep { flex:none; font-size:13px; color:#eee; opacity:.45; }
|
.rm-crumbs .rm-sep { flex:none; font-size:13px; color:#eee; opacity:.45; }
|
||||||
.rm-crumbs a.rm-auth { flex:none; margin-left:auto; padding:6px 12px !important;
|
/* Traegt die Lupe und die Login/Logout-Pille zusammen als eine Einheit
|
||||||
|
rechts — nur eine gemeinsame margin-left:auto, statt jedes Element
|
||||||
|
einzeln an den Rand zu schieben, sonst klafft zwischen beiden eine
|
||||||
|
Luecke statt "direkt links neben der Pille". */
|
||||||
|
.rm-crumbs .rm-auth-group { flex:none; margin-left:auto;
|
||||||
|
display:flex; align-items:center; gap:6px; }
|
||||||
|
.rm-crumbs a.rm-auth { flex:none; padding:6px 12px !important;
|
||||||
font-size:13px !important; border-radius:99px;
|
font-size:13px !important; border-radius:99px;
|
||||||
background:rgba(128,128,128,.18);
|
background:rgba(128,128,128,.18);
|
||||||
border:1px solid rgba(160,160,160,.4); }
|
border:1px solid rgba(160,160,160,.4); }
|
||||||
|
.rm-crumbs a.rm-search { flex:none; min-width:44px; height:29px;
|
||||||
|
display:flex; align-items:center; justify-content:center;
|
||||||
|
padding:0 16px !important; font-size:14px; border-radius:99px;
|
||||||
|
background:rgba(128,128,128,.18);
|
||||||
|
border:1px solid rgba(160,160,160,.4); }
|
||||||
/* Nur gesetzt, wenn die Leiste wirklich gebaut wurde — ohne Brotkrumen
|
/* Nur gesetzt, wenn die Leiste wirklich gebaut wurde — ohne Brotkrumen
|
||||||
im Original-DOM bleibt der Platz sonst leer reserviert. */
|
im Original-DOM bleibt der Platz sonst leer reserviert. */
|
||||||
body.rm-crumbed .rm-root {
|
body.rm-crumbed .rm-root {
|
||||||
@@ -97,6 +125,38 @@
|
|||||||
body.rm-crumbed .rm-dbg {
|
body.rm-crumbed .rm-dbg {
|
||||||
margin-top:calc(45px + env(safe-area-inset-top)); }
|
margin-top:calc(45px + env(safe-area-inset-top)); }
|
||||||
|
|
||||||
|
/* Zweite Leiste unter den Brotkrumen, nur im Thread: Ersatz fuer
|
||||||
|
"Search this topic..." der Originalseite. Das dortige Formular wird
|
||||||
|
unveraendert hierher verschoben statt neu gebaut, wie das
|
||||||
|
Login-Formular in .rm-login form. */
|
||||||
|
.rm-search-bar { box-sizing:border-box;
|
||||||
|
position:fixed; left:0; right:0; z-index:9997;
|
||||||
|
top:calc(44px + env(safe-area-inset-top));
|
||||||
|
display:flex; align-items:center;
|
||||||
|
padding:8px 12px;
|
||||||
|
background:rgba(28,28,30,.96);
|
||||||
|
-webkit-backdrop-filter:blur(12px);
|
||||||
|
backdrop-filter:blur(12px);
|
||||||
|
border-bottom:1px solid rgba(128,128,128,.3);
|
||||||
|
transform:translateY(-110%);
|
||||||
|
transition:transform .18s ease; }
|
||||||
|
.rm-search-bar.rm-open { transform:translateY(0); }
|
||||||
|
.rm-search-bar form { flex:1; min-width:0;
|
||||||
|
display:flex; align-items:center; gap:8px; }
|
||||||
|
.rm-search-bar input[type="text"] {
|
||||||
|
flex:1; min-width:0; box-sizing:border-box;
|
||||||
|
font-size:16px; padding:9px 12px; border-radius:10px;
|
||||||
|
color:#eee; background:rgba(120,120,120,.18);
|
||||||
|
border:1px solid rgba(160,160,160,.35); }
|
||||||
|
.rm-search-bar button[type="submit"] {
|
||||||
|
-webkit-appearance:none; appearance:none;
|
||||||
|
display:flex; align-items:center; justify-content:center;
|
||||||
|
box-sizing:border-box; line-height:normal; text-align:center;
|
||||||
|
flex:none; min-height:44px; font-size:14px; font-weight:650;
|
||||||
|
padding:12px 16px;
|
||||||
|
border-radius:10px; color:#fff; border:0;
|
||||||
|
background:rgba(120,170,255,.85); }
|
||||||
|
|
||||||
/* === Themen- und Forenliste === */
|
/* === Themen- und Forenliste === */
|
||||||
|
|
||||||
.rm-sec { padding:18px 14px 6px; font-size:12px; font-weight:700;
|
.rm-sec { padding:18px 14px 6px; font-size:12px; font-weight:700;
|
||||||
@@ -258,10 +318,104 @@
|
|||||||
text-decoration:none !important; color:inherit !important; }
|
text-decoration:none !important; color:inherit !important; }
|
||||||
.rm-login form input[type="checkbox"] { width:18px; height:18px;
|
.rm-login form input[type="checkbox"] { width:18px; height:18px;
|
||||||
vertical-align:middle; margin-right:8px; }
|
vertical-align:middle; margin-right:8px; }
|
||||||
.rm-login form input[type="submit"] {
|
.rm-login form button[type="submit"] {
|
||||||
width:100%; font-size:16px; font-weight:650; padding:13px;
|
-webkit-appearance:none; appearance:none;
|
||||||
margin-top:20px; border-radius:10px; color:#fff; border:0;
|
display:flex; align-items:center; justify-content:center;
|
||||||
|
box-sizing:border-box; line-height:normal; text-align:center;
|
||||||
|
width:100%; min-height:48px; font-size:16px; font-weight:650;
|
||||||
|
padding:16px 13px; margin-top:20px; border-radius:10px; color:#fff;
|
||||||
|
border:0; background:rgba(120,170,255,.85); }
|
||||||
|
|
||||||
|
/* === Suchformular (search.php ohne Treffer) === */
|
||||||
|
|
||||||
|
.rm-search-shortcuts { display:flex; flex-wrap:wrap; gap:8px;
|
||||||
|
padding:0 14px 16px; }
|
||||||
|
.rm-search-shortcuts a { font-size:13px; padding:6px 12px; border-radius:99px;
|
||||||
|
border:1px solid rgba(128,128,128,.4);
|
||||||
|
text-decoration:none !important; color:inherit !important; }
|
||||||
|
|
||||||
|
/* Derselbe Tabelle-zu-Block-Trick wie bei .rm-login form, eigener Name
|
||||||
|
statt Wiederverwendung: das Formular hier ist ein anderes und hat
|
||||||
|
andere Feldtypen (radio, select statt checkbox). */
|
||||||
|
.rm-searchform form { display:block;
|
||||||
|
padding:4px 14px calc(80px + env(safe-area-inset-bottom)); }
|
||||||
|
.rm-searchform form table, .rm-searchform form tbody,
|
||||||
|
.rm-searchform form tr, .rm-searchform form td {
|
||||||
|
display:block !important; width:100% !important; }
|
||||||
|
.rm-searchform form td { padding:0 !important; }
|
||||||
|
/* Bleibt sichtbar statt wie beim Login versteckt: die beiden th-Zeilen
|
||||||
|
("Search query", "Search options") sind hier Abschnittstrenner, keine
|
||||||
|
Formular-Kopfzelle ohne eigenen Inhalt. */
|
||||||
|
.rm-searchform form th { display:block !important; padding:16px 0 4px;
|
||||||
|
font-size:12px; font-weight:700;
|
||||||
|
text-transform:uppercase; letter-spacing:.06em;
|
||||||
|
opacity:.55; }
|
||||||
|
.rm-searchform form b.genmed { display:block; margin:14px 0 4px;
|
||||||
|
font-size:14px; font-weight:650; }
|
||||||
|
.rm-searchform form span.gensmall { display:block; margin-bottom:6px;
|
||||||
|
font-size:12px; opacity:.6; }
|
||||||
|
.rm-searchform form input[type="text"] {
|
||||||
|
box-sizing:border-box; width:100%; font-size:16px; padding:11px 12px;
|
||||||
|
border-radius:10px; color:#eee; background:rgba(120,120,120,.18);
|
||||||
|
border:1px solid rgba(160,160,160,.35); }
|
||||||
|
.rm-searchform form select {
|
||||||
|
box-sizing:border-box; width:100%; font-size:16px; padding:9px 12px;
|
||||||
|
margin-top:4px; border-radius:10px; color:#eee;
|
||||||
|
background:rgba(120,120,120,.18); border:1px solid rgba(160,160,160,.35); }
|
||||||
|
.rm-searchform form select[multiple] { font-size:15px; padding:4px; }
|
||||||
|
.rm-searchform form input[type="radio"] { width:18px; height:18px;
|
||||||
|
vertical-align:middle; margin-right:6px; }
|
||||||
|
/* Einzige Zeile ohne Block-Stapelung: Suchen/Zuruecksetzen sollen
|
||||||
|
nebeneinander stehen, nicht wie der Rest des Formulars untereinander. */
|
||||||
|
.rm-searchform form td.cat { display:flex !important; gap:10px;
|
||||||
|
padding-top:10px !important; }
|
||||||
|
/* input[type=submit]/[type=reset] behalten in iOS Safari trotz
|
||||||
|
-webkit-appearance:none teils die native Knopfoptik und setzen Padding,
|
||||||
|
Rahmen und Zentrierung nur unzuverlaessig um — deshalb echte <button>
|
||||||
|
statt der Original-<input>-Elemente, siehe inputToButton(). */
|
||||||
|
.rm-searchform form button[type="submit"],
|
||||||
|
.rm-searchform form button[type="reset"] {
|
||||||
|
-webkit-appearance:none; appearance:none;
|
||||||
|
display:flex; align-items:center; justify-content:center;
|
||||||
|
box-sizing:border-box; line-height:normal; text-align:center;
|
||||||
|
min-height:48px; font-size:16px; font-weight:650;
|
||||||
|
padding:16px 13px; border-radius:10px;
|
||||||
|
border:0; }
|
||||||
|
.rm-searchform form button[type="submit"] { flex:1; color:#fff;
|
||||||
background:rgba(120,170,255,.85); }
|
background:rgba(120,170,255,.85); }
|
||||||
|
.rm-searchform form button[type="reset"] { flex:none; color:#eee;
|
||||||
|
background:rgba(120,120,120,.18);
|
||||||
|
border:1px solid rgba(160,160,160,.45) !important; }
|
||||||
|
|
||||||
|
/* === Suchtreffer (search.php mit Ergebnissen, Modus "Posts") === */
|
||||||
|
|
||||||
|
.rm-hits-info { padding:0 14px 14px; font-size:13px; opacity:.75;
|
||||||
|
overflow-wrap:break-word; }
|
||||||
|
.rm-hits-info a { color:inherit !important; }
|
||||||
|
|
||||||
|
.rm-hit { box-sizing:border-box !important; display:block !important;
|
||||||
|
width:100% !important; padding:14px !important;
|
||||||
|
border-top:1px solid rgba(128,128,128,.25) !important; }
|
||||||
|
.rm-hit-ctx { display:block; margin-bottom:8px; font-size:12px;
|
||||||
|
font-weight:650; text-transform:uppercase; letter-spacing:.03em;
|
||||||
|
opacity:.6; text-decoration:none !important;
|
||||||
|
color:inherit !important; overflow-wrap:break-word; }
|
||||||
|
.rm-hit-head { display:flex; align-items:baseline; justify-content:space-between;
|
||||||
|
gap:8px; }
|
||||||
|
.rm-hit-user { font-size:14px; font-weight:650; }
|
||||||
|
.rm-hit-when { flex:none; font-size:12px; opacity:.55; }
|
||||||
|
/* Wiederverwendet: dieselbe .rm-meta-Regel aus der Themenliste, gleiche
|
||||||
|
"X Antworten · Y Views"-Optik. */
|
||||||
|
.rm-hit .rm-meta { margin-top:4px; }
|
||||||
|
/* .rm-body wird 1:1 vom Thread uebernommen (gleiches Beitragsmarkup),
|
||||||
|
nur der verschobene Container ist hier ein td statt div/span und
|
||||||
|
braucht die Umstellung auf Block, die .rm-body selbst nicht mitbringt. */
|
||||||
|
.rm-root.rm-hits .rm-body { margin-top:8px; }
|
||||||
|
.rm-root.rm-hits .rm-body > td { display:block !important; padding:0 !important; }
|
||||||
|
.rm-hit-go { display:inline-block; margin-top:10px; font-size:12px;
|
||||||
|
padding:5px 10px; border:1px solid rgba(128,128,128,.4);
|
||||||
|
border-radius:99px; text-decoration:none !important;
|
||||||
|
color:inherit !important; }
|
||||||
|
|
||||||
/* === Seitennavigation, beide Ansichten === */
|
/* === Seitennavigation, beide Ansichten === */
|
||||||
|
|
||||||
@@ -388,11 +542,31 @@
|
|||||||
if (!n) return;
|
if (!n) return;
|
||||||
|
|
||||||
var st = loginState();
|
var st = loginState();
|
||||||
|
var group = document.createElement('div');
|
||||||
|
group.className = 'rm-auth-group';
|
||||||
|
|
||||||
|
// Lupe nur bei bestehender Sitzung. Ausserhalb von viewtopic fuehrt sie
|
||||||
|
// direkt auf search.php, im Thread blendet sie stattdessen die zweite
|
||||||
|
// Leiste ein — Ersatz fuer "Search this topic...", das mit dem
|
||||||
|
// Original-DOM ausgeblendet wurde.
|
||||||
|
if (st.in) {
|
||||||
|
var search = document.createElement('a');
|
||||||
|
search.className = 'rm-search';
|
||||||
|
search.href = 'https://cs.rin.ru/forum/search.php';
|
||||||
|
search.textContent = '🔍';
|
||||||
|
search.setAttribute('aria-label', 'Suche');
|
||||||
|
search.addEventListener('click', function (e) {
|
||||||
|
if (view === 'thread') { e.preventDefault(); toggleThreadSearch(); }
|
||||||
|
});
|
||||||
|
group.appendChild(search);
|
||||||
|
}
|
||||||
|
|
||||||
var auth = document.createElement('a');
|
var auth = document.createElement('a');
|
||||||
auth.className = 'rm-auth';
|
auth.className = 'rm-auth';
|
||||||
auth.href = st.href;
|
auth.href = st.href;
|
||||||
auth.textContent = st.in ? (st.name || 'Logout') : 'Login';
|
auth.textContent = st.in ? (st.name || 'Logout') : 'Login';
|
||||||
bar.appendChild(auth);
|
group.appendChild(auth);
|
||||||
|
bar.appendChild(group);
|
||||||
|
|
||||||
document.body.appendChild(bar);
|
document.body.appendChild(bar);
|
||||||
document.body.classList.add('rm-crumbed');
|
document.body.classList.add('rm-crumbed');
|
||||||
@@ -946,7 +1120,199 @@
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search.php ohne Treffer zeigt nur das Suchformular — keine topictitle-
|
||||||
|
// oder forumlink-Zeilen, an denen buildList() sonst seine Karten festmacht.
|
||||||
|
// Erkannt wird das Formular am Forenwaehler select[name="fid[]"]: der
|
||||||
|
// steckt nur im grossen Suchformular, nicht in den kleinen "Search this
|
||||||
|
// forum/topic..."-Formularen auf Foren- und Themenseiten, die denselben
|
||||||
|
// Formularnamen "keywords" verwenden wuerden und sonst faelschlich
|
||||||
|
// getroffen werden koennten.
|
||||||
|
function buildSearchForm() {
|
||||||
|
var picker = document.querySelector('select[name="fid[]"]');
|
||||||
|
var form = picker && picker.closest('form');
|
||||||
|
if (!form) return false;
|
||||||
|
|
||||||
|
// Vorbelegung fuer die mobile Nutzung: Main Forum (Forum-ID 10, siehe
|
||||||
|
// dev/viewforum.php) vorausgewaehlt statt "kein Forum", Unterforen dabei
|
||||||
|
// nicht automatisch mitgesucht — das serverseitige Formular startet sonst
|
||||||
|
// mit leerem Forenwaehler und "Search subforums: Yes".
|
||||||
|
var mainForum = picker.querySelector('option[value="10"]');
|
||||||
|
if (mainForum) mainForum.selected = true;
|
||||||
|
var noSubforums = form.querySelector('input[name="sc"][value="0"]');
|
||||||
|
if (noSubforums) noSubforums.checked = true;
|
||||||
|
|
||||||
|
var root = document.createElement('div');
|
||||||
|
root.className = 'rm-root rm-searchform';
|
||||||
|
|
||||||
|
var title = document.createElement('div');
|
||||||
|
title.className = 'rm-login-title';
|
||||||
|
title.textContent = 'Suche';
|
||||||
|
root.appendChild(title);
|
||||||
|
|
||||||
|
// Schnellzugriffe (View new posts, View your posts, ...) stehen als
|
||||||
|
// eigene Linkliste ausserhalb des Formulars und würden sonst mit dem Rest
|
||||||
|
// der Originalseite verschwinden.
|
||||||
|
var quick = document.querySelector('p.searchbar');
|
||||||
|
if (quick) {
|
||||||
|
var links = quick.querySelectorAll('a');
|
||||||
|
if (links.length) {
|
||||||
|
var chips = document.createElement('div');
|
||||||
|
chips.className = 'rm-search-shortcuts';
|
||||||
|
links.forEach(function (a) {
|
||||||
|
var c = document.createElement('a');
|
||||||
|
c.href = a.href;
|
||||||
|
c.textContent = txt(a);
|
||||||
|
chips.appendChild(c);
|
||||||
|
});
|
||||||
|
root.appendChild(chips);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Die Textfelder tragen ein inline style="width: 300px", das jede externe
|
||||||
|
// Breitenregel ohne !important sticht.
|
||||||
|
form.querySelectorAll('input[type="text"]').forEach(function (inp) {
|
||||||
|
inp.removeAttribute('style');
|
||||||
|
});
|
||||||
|
|
||||||
|
form.querySelectorAll('input[type="submit"], input[type="reset"]')
|
||||||
|
.forEach(inputToButton);
|
||||||
|
|
||||||
|
root.appendChild(form);
|
||||||
|
replaceBody(root);
|
||||||
|
addCrumbs();
|
||||||
|
log.push('suche=formular');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eine Suche im Modus "Posts" (Standard beim Suchen ueber die zweite Leiste
|
||||||
|
// im Thread, da deren Formular kein sr setzt) liefert etwas ganz anderes
|
||||||
|
// als eine Themenliste: pro Treffer Autor, Zeitstempel und ein Auszug aus
|
||||||
|
// dem Beitrag selbst, keine topictitle-/forumlink-Zeilen. buildList() wuerde
|
||||||
|
// die darin enthaltenen viewtopic.php-Links trotzdem einsammeln und an
|
||||||
|
// rowKind() falsch klassifizieren, ohne diese eigene Behandlung davor.
|
||||||
|
// Erkannt wird der Treffer-Modus an p.topictitle — als <p>, nicht als <a>
|
||||||
|
// wie das gleichnamige forumlink-Gegenstueck einer Themenzeile.
|
||||||
|
function buildSearchResults() {
|
||||||
|
var hits = document.querySelectorAll('p.topictitle');
|
||||||
|
if (!hits.length) return false;
|
||||||
|
|
||||||
|
var root = document.createElement('div');
|
||||||
|
root.className = 'rm-root rm-hits';
|
||||||
|
|
||||||
|
var summary = document.querySelector('span.titles');
|
||||||
|
var title = document.createElement('div');
|
||||||
|
title.className = 'rm-login-title';
|
||||||
|
title.textContent = summary ? txt(summary) : 'Suchergebnisse';
|
||||||
|
root.appendChild(title);
|
||||||
|
|
||||||
|
// "Searched topic: ... / Search term used: ..." traegt funktionierende
|
||||||
|
// Links (erneute Suche, Sprung zum Thema) und wird deshalb wie das
|
||||||
|
// Formular selbst uebernommen statt aus dem Text nachgebaut.
|
||||||
|
var form = hits[0].closest('form');
|
||||||
|
var infoCell = form && form.querySelector('td.genmed');
|
||||||
|
if (infoCell) {
|
||||||
|
infoCell.classList.add('rm-hits-info');
|
||||||
|
root.appendChild(infoCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
var built = 0;
|
||||||
|
hits.forEach(function (p) {
|
||||||
|
try {
|
||||||
|
var card = buildHit(p);
|
||||||
|
if (card) { root.appendChild(card); built++; }
|
||||||
|
} catch (e) { log.push('treffer: ' + e.message); }
|
||||||
|
});
|
||||||
|
log.push('treffer=' + built);
|
||||||
|
if (!built) return false;
|
||||||
|
|
||||||
|
// Muss vor replaceBody() laufen: pageState() liest das Original-DOM.
|
||||||
|
var pg = pageState();
|
||||||
|
if (pg.total > 1) pageNav(root, pg);
|
||||||
|
|
||||||
|
replaceBody(root);
|
||||||
|
addCrumbs();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ein Treffer besteht aus drei aufeinanderfolgenden <tr> derselben Tabelle:
|
||||||
|
// Titelzeile (Forum/Thema), Autor- und Betreffzeile, Antworten/Views samt
|
||||||
|
// Beitragsauszug. Die Zuordnung laeuft ueber nextElementSibling statt ueber
|
||||||
|
// Klassen, weil alle drei row1/row2-Zeilen sonst gleich aussehen.
|
||||||
|
function buildHit(p) {
|
||||||
|
var titleRow = p.closest('tr');
|
||||||
|
var infoRow = titleRow && titleRow.nextElementSibling;
|
||||||
|
var bodyRow = infoRow && infoRow.nextElementSibling;
|
||||||
|
|
||||||
|
var forumA = p.querySelector('a[href*="viewforum.php"]');
|
||||||
|
var topicA = p.querySelector('a[href*="viewtopic.php"]');
|
||||||
|
if (!topicA) return null;
|
||||||
|
|
||||||
|
var el = document.createElement('div');
|
||||||
|
el.className = 'rm-hit';
|
||||||
|
|
||||||
|
var ctx = document.createElement('a');
|
||||||
|
ctx.className = 'rm-hit-ctx';
|
||||||
|
ctx.href = topicA.href;
|
||||||
|
ctx.textContent = breakable((forumA ? txt(forumA) + ' › ' : '') + txt(topicA));
|
||||||
|
el.appendChild(ctx);
|
||||||
|
|
||||||
|
var author = '', posted = '', subjectA = null;
|
||||||
|
if (infoRow) {
|
||||||
|
var ua = infoRow.querySelector('.postauthor');
|
||||||
|
author = ua ? txt(ua) : '';
|
||||||
|
subjectA = infoRow.querySelector('a[href*="viewtopic.php"]');
|
||||||
|
var pm = txt(infoRow).match(/Posted:\s*(.+)$/i);
|
||||||
|
if (pm) posted = pm[1].trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
var head = document.createElement('div');
|
||||||
|
head.className = 'rm-hit-head';
|
||||||
|
var who = document.createElement('span');
|
||||||
|
who.className = 'rm-hit-user';
|
||||||
|
who.textContent = author || 'Gast';
|
||||||
|
head.appendChild(who);
|
||||||
|
if (posted) {
|
||||||
|
var when = document.createElement('span');
|
||||||
|
when.className = 'rm-hit-when';
|
||||||
|
when.textContent = posted;
|
||||||
|
head.appendChild(when);
|
||||||
|
}
|
||||||
|
el.appendChild(head);
|
||||||
|
|
||||||
|
if (bodyRow) {
|
||||||
|
// txt() haengt "Replies:" und "Views:" ohne Trennzeichen aneinander,
|
||||||
|
// weil das <br /> dazwischen keinen Leerraum hinterlaesst — deshalb
|
||||||
|
// einzeln herausgegriffen und ueber dieselbe metaRow() wie bei
|
||||||
|
// Themenkarten mit " · " verbunden.
|
||||||
|
var metaTxt = txt(bodyRow.querySelector('.postdetails'));
|
||||||
|
var reM = metaTxt.match(/Replies:\s*([\d.,]+)/i);
|
||||||
|
var viM = metaTxt.match(/Views:\s*([\d.,]+)/i);
|
||||||
|
var metaEl = metaRow([reM ? reM[1] + ' Antworten' : '',
|
||||||
|
viM ? viM[1] + ' Views' : '']);
|
||||||
|
if (metaEl) el.appendChild(metaEl);
|
||||||
|
|
||||||
|
var pb = bodyRow.querySelector('.postbody');
|
||||||
|
if (pb) {
|
||||||
|
var wrap = document.createElement('div');
|
||||||
|
wrap.className = 'rm-body';
|
||||||
|
wrap.appendChild(pb);
|
||||||
|
el.appendChild(wrap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var jump = document.createElement('a');
|
||||||
|
jump.className = 'rm-hit-go';
|
||||||
|
jump.href = (subjectA || topicA).href;
|
||||||
|
jump.textContent = 'Zum Beitrag ↓';
|
||||||
|
el.appendChild(jump);
|
||||||
|
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
function buildList() {
|
function buildList() {
|
||||||
|
if (buildSearchForm()) return;
|
||||||
|
if (buildSearchResults()) return;
|
||||||
|
|
||||||
// Dokumentreihenfolge entscheidet: in einer Forenzeile steht der Forenname
|
// Dokumentreihenfolge entscheidet: in einer Forenzeile steht der Forenname
|
||||||
// vor dem Link auf den letzten Beitrag. Ohne diese Reihenfolge faellt die
|
// vor dem Link auf den letzten Beitrag. Ohne diese Reihenfolge faellt die
|
||||||
// Zeile als Thema an, der Forenname verschwindet und nur die Beschreibung
|
// Zeile als Thema an, der Forenname verschwindet und nur die Beschreibung
|
||||||
@@ -1032,6 +1398,47 @@
|
|||||||
// Thread
|
// Thread
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
|
// "Search this topic..." steht dreifach identisch im Original-DOM (Kopf,
|
||||||
|
// Fuss, ueber der Beitragsliste), samt versteckter Felder fuer Themen-Id
|
||||||
|
// und Scope (sf=msgonly). replaceBody() versteckt das nur per Klasse, das
|
||||||
|
// erste Formular bleibt im DOM erreichbar und wird beim ersten Antippen
|
||||||
|
// der Lupe unveraendert in die zweite Leiste verschoben statt neu gebaut —
|
||||||
|
// wie das Login-Formular in buildLogin().
|
||||||
|
var threadSearchBar = null;
|
||||||
|
|
||||||
|
function buildThreadSearch() {
|
||||||
|
var form = document.querySelector('#topic-search');
|
||||||
|
if (!form) return null;
|
||||||
|
|
||||||
|
// Die Originalseite emuliert einen Platzhalter per onclick/onblur statt
|
||||||
|
// per placeholder-Attribut.
|
||||||
|
var inp = form.querySelector('input[name="keywords"]');
|
||||||
|
if (inp) {
|
||||||
|
inp.removeAttribute('onclick');
|
||||||
|
inp.removeAttribute('onblur');
|
||||||
|
if (inp.value === 'Search this topic…') inp.value = '';
|
||||||
|
inp.placeholder = 'In diesem Thema suchen';
|
||||||
|
}
|
||||||
|
var submit = form.querySelector('input[type="submit"]');
|
||||||
|
if (submit) { submit.value = 'Suchen'; inputToButton(submit); }
|
||||||
|
|
||||||
|
var bar = document.createElement('div');
|
||||||
|
bar.className = 'rm-search-bar';
|
||||||
|
bar.appendChild(form);
|
||||||
|
document.body.appendChild(bar);
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleThreadSearch() {
|
||||||
|
if (!threadSearchBar) threadSearchBar = buildThreadSearch();
|
||||||
|
if (!threadSearchBar) return;
|
||||||
|
var open = threadSearchBar.classList.toggle('rm-open');
|
||||||
|
if (open) {
|
||||||
|
var inp = threadSearchBar.querySelector('input[type="text"]');
|
||||||
|
if (inp) inp.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Der Beitragstext liegt in einer verschachtelten Tabelle. closest('tr')
|
// Der Beitragstext liegt in einer verschachtelten Tabelle. closest('tr')
|
||||||
// trifft deshalb die innere Zeile, der Autor- und Profilspalte fehlen.
|
// trifft deshalb die innere Zeile, der Autor- und Profilspalte fehlen.
|
||||||
// Aufsteigen, bis die Zeile eine Profil- oder Autorenspalte enthaelt.
|
// Aufsteigen, bis die Zeile eine Profil- oder Autorenspalte enthaelt.
|
||||||
@@ -1234,6 +1641,8 @@
|
|||||||
if (!td.children.length && !txt(td)) td.classList.add('rm-hidden');
|
if (!td.children.length && !txt(td)) td.classList.add('rm-hidden');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
inputToButton(form.querySelector('input[type="submit"]'));
|
||||||
|
|
||||||
root.appendChild(form);
|
root.appendChild(form);
|
||||||
replaceBody(root);
|
replaceBody(root);
|
||||||
addCrumbs();
|
addCrumbs();
|
||||||
@@ -1287,7 +1696,7 @@
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
var d = document.createElement('div');
|
var d = document.createElement('div');
|
||||||
d.className = 'rm-dbg';
|
d.className = 'rm-dbg';
|
||||||
d.textContent = 'RIN Mobile v3.8\n' + log.join('\n');
|
d.textContent = 'RIN Mobile v3.13\n' + log.join('\n');
|
||||||
document.body.insertBefore(d, document.body.firstChild);
|
document.body.insertBefore(d, document.body.firstChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user