Schaltflächenskripte und ihre Symbole

  • Firefox-Version
    Betriebssystem

    (Entsprechend der Hinweise in unten folgenden Antworten überarbeitet.)

    Symbole in Skripten werden bisher, soweit ich es bemerkt habe, entweder mit Absolutpfaden angegeben oder als Data-URI mit Base64-kodiertem Inhalt.

    Ich hatte nun eine Idee und bei Aris nachgefragt, ob man es umsetzen könne, dass ein Skript seinen eigenen Pfad erkennt, so dass man dann Symbole aus auch einem relativ verlinkten Verzeichnis unterhalb dieses Skriptpfads auslesen könnte – und in der Tat, man kann (dem folgte die zuerst hier präsentierte, inzwischen überarbeitete Version).

    Man fügt in die userChrome.js oder jedes einzelne Schaltflächenskript ganz zu Beginn diese Zeile ein (Konstantenname ziemlich egal):

    JavaScript
    const ProfilePath = PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome'));

    Und das kann man dann weiterverwenden. Ich gebe mal ein Beispiel, bei mir als website_mozilla-addons.uc.js gespeichert, Anmerkungen nach dem Skript:

    Die Datei muss wie üblich in UTF-8 abgespeichert werden; ich hatte das selbst zunächst nicht berücksichtigt und nach dem nicht vorhandenen Fehler im Skript gesucht (beachte in den Kommentaren die Umlaute, die kein ASCII sind).

    Ich habe also zusätzlich noch einen Parameter IconPath (als Konstante) angelegt und darin einen Pfad zu einer Datei; wie im Kommentar nachzulesen, muss sich dieser Pfad zur Bilddatei innerhalb des Profils befinden. Wie Sören unten in Beitrag #9 gezeigt hat, könnte man auch direkt das Unterverzeichnis in ProfilePath registrieren (oder sogar weitere Unterunterverzeichnisse, siehe meine Frage in Beitrag #11 und Sörens folgende Antwort), die Variante in meinem Beispiel bietet aber etwas mehr Variabilität.

    Innerhalb von const CSS werden dann beide Konstanten genutzt. Statt " + ProfilePath + IconPath + " könnte man aber auch weiterhin einen Absolutpfad – das kann auch ein chrome-URI für ein mit dem Firefox ausgeliefertes Symbol sein – oder einen Data-URI eintragen. MoreCSS ist vor allem sinnvoll für CSS-Filter oder zusätzliche Umrandungen oder einen anderen Hintergrund pro Symbol.

    Vorteile:

    • Man spart sich die Base64-Kodierung.
    • Wenn ich mich nicht irre, verringert das Laden einer Bilddatei den Speicherbedarf.
    • Man muss keine Absolutpfade angeben und die Bilddateien befinden sich direkt im Profil, was zusammen die Portabilität erhöht (Testprofile, Sicherungen).

    Unabhängig davon hat der Konfigurationsbereich mit Variablen oder Konstanten meiner Meinung nach noch weitere Vorteile:

    • Alles, was für jedes Skript individuell zu ändern ist, steht in einem Block sehr weit vorn.
    • Allein die Button-ID wird immer mindestens zweimal benötigt (im AnimationToggleButton-Skript immerhin achtmal), was ohne Variable/Konstante die Fehleranfälligkeit bei Änderungen erhöht. Achtung: In einigen Skripten (das AnimationToggleButton-Skript ist ein Beispiel) gibt es einen Bereich mit einer OnClick- oder OnCommand-Funktion, wo die ID weiterhin explizit eingetragen werden muss (wobei man es auf einmal optimieren kann), weil dieser Teil so wie eingetragen in das Browser-DOM eingefügt wird.
    • Alles in allem weit geringerer Änderungsaufwand, auch wegen des Wegfalls der Base64-Kodierung.

    Wenn es um externe Webseiten geht, besteht das größte Problem nun nur noch darin, das Seitensymbol (Favicon) herunterzuladen und unter Umständen in ein kleineres Format zu konvertieren (in meinem Beispiel amo.png: ).

  • Hallo,

    der Gedanke ist gut, die Umsetzung nicht zukunftssicher: osfile.jsm wird aus Firefox verschwinden. Ein Großteil der Vorkommnisse im Firefox-Code wurde bereits ersetzt.

    Ersetze:

    JavaScript
    Components.utils.import('resource://gre/modules/osfile.jsm');
    const ProfilePath = OS.Path.toFileURI(OS.Path.join(OS.Constants.Path.profileDir, "chrome"));

    Durch:

    JavaScript
    const ProfilePath = PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome'));

    Eine Import-Zeile sollte es hierfür nicht benötigen.

  • Das Folgende (hier ein Codeschnipsel für einen Menüeintrag) funktioniert bei mir bisher noch unter Windows und Linux ohne Änderungen. Die Icons sind im Ordner "icons" unter dem Ordner "chrome" abgelegt.

    Code
    var currentProfileDirectory = Services.dirsvc.get("ProfD", Ci.nsIFile).path.replace(/\\/g, "/");
    var buttonicon = "googletranslate.png"
    menuitem.style.listStyleImage = 'url("' + ("file:" + currentProfileDirectory + "/chrome/icons/" + buttonicon) + '")';

    FF 115.x ESR auf Win10 Pro 64bit

    FF 115.x ESR auf Linux Mint

  • Das Auslesen des eigenen Profile-Directory und das Zusammenfügen mit einem Unterordner/Dateinamen wird doch eigentlich schon seit Längerem so gehandhabt. z.B. auch in der 'userChromeShadow.uc.js':

    let path = PathUtils.join(PathUtils.profileDir, 'chrome', 'userChromeShadow.css');

    Wie Sören geschrieben hat, ist dann auch kein 'import' (mehr) nötig...

  • :/

    Was habe ich denn durch das ganze gewonnen?

    Ich nutze :

    JavaScript
    let currentProfileDirectory = Services.dirsvc.get("ProfD", Ci.nsIFile).path.replace(/\\/g, "/");  // Pfadangabe zum Profilordner
    let buttonicon = "test.png"  // Name & Dateiendung des anzuzeigenden Symbols
    style: 'list-style-image: url("' + ("file:" + currentProfileDirectory + "/chrome/icons/" + buttonicon) +'");',

    Und "/chrome/icons/" könnte ich auch noch in eine Variable packen,

    nur wofür das ganze oben?

    OK, da in meiner userChromeShadow.uc.js die Variable let path = PathUtils.join(PathUtils.profileDir, 'chrome', 'userChromeShadow.css'); angelegt ist,

    könnte ich auch die Variable let ProfilePath = PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome'));

    zum chrome-Ordner nutzen.

    Dann würde wohl sich der Code so ändern

    JavaScript
    let ProfilePath = PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome'));
    
    let buttonicon = "test.png";
    
    style: "list-style-image: url('" + ProfilePath + "/icons/" + buttonicon) +"');"

    Aber habe ich dadurch irgendwas gewonnen? :/

    Und wenn ich jetzt noch aus "/icons/" + buttonicon => IconPath mache, ...

    OK, ist etwas kürzerer Code.

    JavaScript
    style: 'list-style-image: url('" + ProfilePath + IconPath ) +"');'

    So habe ich mir wohl selbst die Antwort erarbeitet,

    und das zu so später Stunde.

    Mit <3lichem Gruß

    Mira

    5 Mal editiert, zuletzt von Mira_Belle (5. Januar 2023 um 10:53)

  • Was habe ich denn durch das ganze gewonnen?

    Direkt in den ersten zwei Absätzen steht, was der Anwendungsfall ist: Wenn jemand bisher einen absoluten Pfad angibt (oder eine Grafik einbettet).

    Dein bisheriger Weg mag auch funktionieren. Schöner ist aber sicher der Weg über die PathUtils. Denn mit einem regulären Ausdruck zu arbeiten und etwas zu ersetzen, ist unnötig und ineffizient. Dann kommt dazu, dass der Weg über die Services-Methode weder Leerzeichen kodiert noch das file://-Protokoll ergänzt wird noch den chrome-Ordner beinhaltet.

    Vergleiche:

    JavaScript
    PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome'));
    // "file:///Users/sorenhentzschel/Library/Application%20Support/Firefox/Profiles/7th0bcyz.default-nightly/chrome/"

    Dein Code gibt aus:

    JavaScript
    Services.dirsvc.get('ProfD', Ci.nsIFile).path.replace(/\\/g, '/');
    // "/Users/sorenhentzschel/Library/Application Support/Firefox/Profiles/7th0bcyz.default-nightly"

    Um auf das gleiche Resultat zu kommen, müsste dein Code so aussehen:

    JavaScript
    encodeURI('file://' + Services.dirsvc.get('ProfD', Ci.nsIFile).path.replace(/\\/g, '/') + '/chrome/');
    // "file:///Users/sorenhentzschel/Library/Application%20Support/Firefox/Profiles/7th0bcyz.default-nightly/chrome/"

    Da ist die PathUtils-Variante meiner Meinung nach die bequemere zum Arbeiten.

  • @Sören Hentzschel

    Und wieder einmal ein Danke!

    Ich nutze jetzt eine Mischung aus beidem.

    JavaScript
    let ProfilePath = PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome'));
    let buttonicon = "bookmark-hollow.svg";
    style: "list-style-image: url('" + ProfilePath + "/icons/" + buttonicon + "');"

    Das mit dem Profilpfad fand ich schon cool,

    nur die Sache mit dem IconPath gefiel mir nicht!

    Deshalb die Mischung.

    So habe ich den Profilpfad und das Symbol getrennt!

    Gäbe es denn die Möglichkeit, den Profilpfad auf "chrome" und einen Ordner darunter zu verknüpfen?

    Denn ...

    JavaScript
    let ProfilePath = PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome/icon'));

    ... funktionierte bei mir nicht.

    Und ...

    JavaScript
    let IconPath = "/icons/";

    extra noch anzulegen, nur um dann ...

    JavaScript
    style: "list-style-image: url('" + ProfilePath + IconPhath + buttonicon + "');"

    ... daraus zu machen, macht m.M. auch nicht wirklich Sinn, finde ich.

    Sieht halt vielleicht schöner aus.

    Mit <3lichem Gruß

    Mira

    Einmal editiert, zuletzt von Mira_Belle (5. Januar 2023 um 13:46)

  • style: "list-style-image: url('" + ProfilePath + "/icons/" + buttonicon + "');"

    Das „/“ vor „icons“ kannst du entfernen, denn das Ergebnis der PathUtils-Methode endet bereits mit einem „/“ (vorausgesetzt es handelt sich um einen bereits existierenden Ordner, was in diesem Fall sicherlich zutrifft).

    Gäbe es denn die Möglichkeit, den Profilpfad auf "chrome" und einen Ordner darunter zu verknüpfen?

    JavaScript
    PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome', 'icons'));
  • osfile.jsm wird aus Firefox verschwinden.

    Dann auch noch einmal hier: Danke, Sören!

    Das Auslesen des eigenen Profile-Directory und das Zusammenfügen mit einem Unterordner/Dateinamen wird doch eigentlich schon seit Längerem so gehandhabt. z.B. auch in der 'userChromeShadow.uc.js':

    Hmmpf, stimmt. Ist mir leider nicht aufgefallen, weil ich es bisher nicht benötigt habe.

    OK, ist etwas kürzerer Code.

    Ich hab mich dafür entschieden, das aufzuteilen, weil ich das für etwas verständlicher halte.

    denn das Ergebnis der PathUtils-Methode endet bereits mit einem „/“ (vorausgesetzt es handelt sich um einen bereits existierenden Ordner, was in diesem Fall sicherlich zutrifft).

    Aah, wichtige Info. Bei der überholten Methode muss man ihn zu Beginn einfügen.

    PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome', 'icons'));

    Und wenn ich ein weiteres Unterunterverzeichnis einbinden wollte, wird das als weiterer String hinten angehängt, also wie folgend?

    JavaScript
    PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome', 'icons', 'websites'));