Hi siehe #390... es war eine falsche Fährte..
Was heißt das, wenn ich fragen darf? Verstehe jetzt überhaupt nicht, was du meinst...![]()
Hi siehe #390... es war eine falsche Fährte..
Was heißt das, wenn ich fragen darf? Verstehe jetzt überhaupt nicht, was du meinst...![]()
Das in #386 ist allerdings für mich wichtig
Ich habe mal eine "lauffähige" Version gebastelt. Da waren aber etliche Sachen anzupassen, nicht nur die inline-events. Auch die Erzeugung der toolbar hat sich in der Nightly geändert.
Allerdings ist die Anzeige total verhunzt. Da stimmt fast nichts mehr. Gibt es noch eine zusätzliche CSS Datei für das Skript? Die müsste aber dann wahrscheinlich auch noch angepasst werden. Aber das wäre mir echt zu viel Aufwand.![]()
Den Schalter für die Download-Leiste habe ich irgendwie falsch eingehängt, müsste man sich auch nochmal anschauen.
Also den Code nur als "Grundlage" für weitere Anpassungen betrachten:
// ==UserScript==
// @name ucjsDownloadsStatusModoki.uc.js
// @namespace http://space.geocities.yahoo.co.jp/gl/alice0775
// @description Downloads Status Modoki
// @include main
// @compatibility Firefox 117
// @author Alice0775
// @note DownloadsStatusModoki.uc.js.css Datei, muss in bzw. über userChrome.css geladen werden!
// @version 2023/07/17 00:00 use ES module imports
// @version 2023/06/20 remove Bug 1780695 - Remove Services.jsm
// @version 2023/06/18 21:00 null
// @version 2023/05/18 21:00
// @version 2022/11/24 21:00 Bug 1802142 - Remove no longer used browser-bottombox
// @version 2022/11/22 Bug 877389 - [meta] Replace calls to Cu.reportError, etc. from browser code, replace with console.error, etc.
// @version 2022/11/20 19:00 107+ wip
// @version 2022/04/01 23:00 Convert Components.utils.import to ChromeUtils.import
// @version 2022/02/16 Bug 1747422 - Remove preprocessor variable use from downloads CSS
// @version 2019/12/11 fix for 73 Bug 1601094 - Rename remaining .xul files to .xhtml in browser
// @version 2019/10/20 12:30 workaround Bug 1497200: Apply Meta CSP to about:downloads, Bug 1513325 - Remove textbox binding
// @version 2019/09/08 19:30 fix scrollbox
// @version 2019/05/21 08:30 fix 69.0a1 Bug 1551320 - Replace all createElement calls in XUL documents with createXULElement
// @version 2018/10/27 12:00 fix for 64+
// @version 2018/06/12 21:00 fix for private window mode
// @version 2018/06/07 12:00 fix file name for history
// @version 2018/02/10 12:00 try catch error when DO_NOT_DELETE_HISTORY = true
// @version 2017/12/10 12:00 fix error when DO_NOT_DELETE_HISTORY = true
// @version 2017/12/10 12:00 remove workaround Bug 1279329. Disable btn while clear list is doing, close button styling for 57.
// @version 2016/06/10 12:00 modify style independent of font-family
// @version 2016/06/10 07:00 modify style of close button, fix typo
// @version 2016/06/10 00:00 Workaround Bug 1279329. adjust some padding
// @version 2015/05/08 00:00 remove padding due to Bug 1160734
// @version 2014/03/31 00:00 fix for browser.download.manager.showWhenStarting
// @version 2013/12/22 13:00 chromehidden
// @version 2013/12/19 17:10 rename REMEMBERHISTOTY to DO_NOT_DELETE_HISTORY
// @version 2013/12/16 23:28 fixed initialize numDls
// @version 2013/12/16 23:24 open only download added
// @version 2013/12/16 23:10 open only download started
// @version 2013/12/16 21:20 modify css Windows7 Aero
// @version 2013/12/16 21:00 modify css
// @version 2013/12/16 19:30 add autocheck false
// @version 2013/12/16 18:31 fix pref name
// @version 2013/12/16 18:30
// @note
// ==/UserScript==
var ucjsDownloadsStatusModoki = {
_summary: null,
_list: null,
get downloadsStatusModokiBar() {
delete downloadsStatusModokiBar;
return this.downloadsStatusModokiBar = document.getElementById("downloadsStatusModokiBar");
},
get toggleMenuitem() {
delete toggleMenuitem;
return this.toggleMenuitem = document.getElementById("toggle_downloadsStatusModokiBar");
},
init: function() {
if (document.documentElement.getAttribute("chromehidden") !="" )
return;
ChromeUtils.defineESModuleGetters(this, {
Downloads: "resource://gre/modules/Downloads.sys.mjs",
});
var style = `
@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
#ucjsDownloadsStatusModoki {
width: 100%;
max-height: 100px;
height: 5.5em;
}
`.replace(/\s+/g, " ");
var sspi = document.createProcessingInstruction(
'xml-stylesheet',
'type="text/css" href="data:text/css,' + encodeURIComponent(style) + '"'
);
document.insertBefore(sspi, document.documentElement);
sspi.getAttribute = function(name) {
return document.documentElement.getAttribute(name);
};
var toolbar = document.createXULElement("vbox");
toolbar.setAttribute("id", "downloadsStatusModokiBar");
toolbar.collapsed = false;
document.getElementById('navigator-toolbox').parentNode.insertBefore(toolbar, null);
var browser = toolbar.appendChild(document.createXULElement("browser"));
browser.setAttribute("disablehistory", true);
browser.setAttribute("remote", false);
browser.setAttribute("id", "ucjsDownloadsStatusModoki");
browser.addEventListener("load", (event) => {ucjsDownloadsStatusModoki.onload(event)});
browser.setAttribute("src", "chrome://browser/content/downloads/contentAreaDownloadsView.xhtml?StatusModoki");
var menuitem = document.createXULElement("menuitem");
menuitem.setAttribute("id", "toggle_downloadsStatusModokiBar");
menuitem.setAttribute("type", "checkbox");
menuitem.setAttribute("autocheck", false);
menuitem.setAttribute("label", "Download Leiste");
menuitem.setAttribute("checked", false);
menuitem.setAttribute("accesskey", "D");
menuitem.addEventListener("command", function(event){ucjsDownloadsStatusModoki.toggleDownloadsStatusModokiBar()});
toolbar.parentNode.insertBefore(menuitem, null);
// Ensure that the DownloadSummary object will be created asynchronously.
if (!this._summary) {
this.Downloads.getSummary(this.Downloads.ALL).then(summary => {
this._summary = summary;
return this._summary.addView(this);
}).then(null, console.error);
}
if (!this._list) {
this.Downloads.getList(this.Downloads.ALL).then(list => {
this._list = list;
return this._list.addView(this);
}).then(null, console.error);
}
window.addEventListener("unload", this, false);
},
uninit: function() {
window.removeEventListener("unload", this, false);
if (this._summary) {
this._summary.removeView(this);
}
if (this._list) {
this._list.removeView(this);
}
},
handleEvent: function(event) {
switch (event.type) {
case "unload":
this.uninit();
break;
}
},
toggleDownloadsStatusModokiBar: function() {
var collapsed = this.downloadsStatusModokiBar.collapsed;
this.downloadsStatusModokiBar.collapsed = !collapsed;
this.toggleMenuitem.setAttribute("checked", collapsed);
},
openDownloadsStatusModoki: function() {
this.downloadsStatusModokiBar.collapsed = false;
this.toggleMenuitem.setAttribute("checked", true);
},
hideDownloadsStatusModoki: function() {
this.downloadsStatusModokiBar.collapsed = true;
this.toggleMenuitem.setAttribute("checked", false);
},
onDownloadAdded: function (aDownload) {
var showWhenStarting = true;
try {
showWhenStarting = Services.prefs.getBoolPref("userChrome.downloadsStatusModoki.showWhenStarting");
} catch(e) {}
this.numDls = 0;
if (showWhenStarting) {
if (this._list) {
this._list.getAll().then(downloads => {
for (let download of downloads) {
if (!download.stopped)
this.numDls++;
}
if (this.numDls > 0)
this.openDownloadsStatusModoki(false);
}).then(null, console.error);
}
}
},
onSummaryChanged: function () {
if (!this._summary)
return;
if (this._summary.allHaveStopped || this._summary.progressTotalBytes == 0) {
var closeWhenDone = false;
try {
closeWhenDone = Services.prefs.getBoolPref("userChrome.downloadsStatusModoki.closeWhenDone");
} catch(e) {}
if (closeWhenDone) {
this.hideDownloadsStatusModoki();
}
}
},
// chrome://browser/content/downloads/contentAreaDownloadsView.xhtml
onload: function(event) {
var doc = event.originalTarget;
var win = doc.defaultView;
doc.documentElement.setAttribute("ucjsDownloadsStatusModoki", "true");
var button = doc.createXULElement("button");
button.setAttribute("label", "Löschen");
button.setAttribute("id", "ucjs_clearListButton");
button.setAttribute("accesskey", "L");
var ref = doc.getElementById("downloadsListEmptyDescription");
var vbox = doc.createXULElement("vbox");
var box = vbox.appendChild(doc.createXULElement("hbox"));
box.appendChild(button);
box.appendChild(doc.createXULElement("spacer")).setAttribute("flex", 1);
var textbox = doc.createElementNS("http://www.w3.org/1999/xhtml", "input");
textbox.setAttribute("id", "downloadFilter");
textbox.setAttribute("clickSelectsAll", true);
textbox.setAttribute("type", "search");
textbox.setAttribute("placeholder", "Suchen...");
box.appendChild(textbox);
var closebtn = doc.createXULElement("toolbarbutton");
closebtn.setAttribute("id", "ucjsDownloadsStatusModoki-closebutton");
closebtn.setAttribute("class", "close-icon");
closebtn.setAttribute("tooltiptext", "Download-Leiste schließen");
box.appendChild(closebtn);
ref.parentNode.insertBefore(vbox, ref.nextSibling);
doc.getElementById("ucjs_clearListButton").addEventListener("command", function(event) {
win.ucjsDownloadsStatusModoki_clearDownloads();
});
doc.getElementById("downloadFilter")
.addEventListener("input", function(event) {
win.ucjsDownloadsStatusModoki_doSearch(event.target.value);
});
doc.getElementById("ucjsDownloadsStatusModoki-closebutton")
.addEventListener("command", function(event) {
win.ucjsDownloadsStatusModoki_doClose();
});
/*
// xxx Bug 1279329 "Copy Download Link" of context menu in Library is grayed out
var listBox = doc.getElementById("downloadsListBox");
var placesView = listBox._placesView;
if (placesView) {
var place = placesView.place;
placesView.place= null;
placesView.place = place;
}
*/
win.ucjsDownloadsStatusModoki_clearDownloads = function ucjs_clearDownloads() {
var DO_NOT_DELETE_HISTORY = true; /* custmizable true or false */
var richListBox = doc.getElementById("downloadsListBox");
var places = [];
function addPlace(aURI, aTitle, aVisitDate) {
places.push({
uri: aURI,
title: aTitle,
visits: [{
visitDate: (aVisitDate || Date.now()) * 1000,
transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
}]
});
}
function moveDownloads2History() {
if (DO_NOT_DELETE_HISTORY &&
!PrivateBrowsingUtils.isWindowPrivate(window)) {
try {
for (let element of richListBox.childNodes) {
let download = element._shell.download;
let aURI = makeURI(download.source.url);
// let aTitle = document.getAnonymousElementByAttribute(element, "class", "downloadTarget").value
let aTitle = download.target.path;
aTitle = aTitle.match( /[^\\]+$/i )[0];
aTitle = aTitle.match( /[^/]+$/i )[0];
let aVisitDate = download.endTime || download.startTime;
addPlace(aURI, aTitle, aVisitDate)
}
} catch(ex) {}
}
// Clear List
richListBox._placesView.doCommand('downloadsCmd_clearDownloads');
if (DO_NOT_DELETE_HISTORY &&
!PrivateBrowsingUtils.isWindowPrivate(window)) {
try {
if (places.length > 0) {
var asyncHistory = Components.classes["@mozilla.org/browser/history;1"]
.getService(Components.interfaces.mozIAsyncHistory);
asyncHistory.updatePlaces(places);
}
} catch(ex) {}
}
}
var btn = doc.getElementById("ucjs_clearListButton");
btn.setAttribute("disabled", true);
moveDownloads2History();
btn.removeAttribute("disabled");
// close toolbar
var closeWhenDone = false;
try {
closeWhenDone = Services.prefs.getBoolPref("userChrome.downloadsStatusModoki.closeWhenDone");
} catch(e) {}
if (closeWhenDone) {
top.ucjsDownloadsStatusModoki.hideDownloadsStatusModoki();
}
};
win.ucjsDownloadsStatusModoki_doSearch = function ucjs_doSearch(filterString) {
var richListBox = doc.getElementById("downloadsListBox");
richListBox._placesView.searchTerm = filterString;
};
win.ucjsDownloadsStatusModoki_doClose = function ucjs_doClose() {
top.ucjsDownloadsStatusModoki.hideDownloadsStatusModoki();
};
}
}
ucjsDownloadsStatusModoki.init();
Alles anzeigen
Perfekt, herzlichen Dank dafür
Gerne. Aber sonderlich viel habe ich ja nicht geändert
...
Wow, super!
Der size-Parameter stand ja schon in der Anweisung von #378 - ist nicht von mir. ![]()
Lässt sich das auch in dem kleinen Skript so ändern?
Meinst du das so?

try {
CustomizableUI.createWidget({
id: "Notepad",
label: "Notepad++",
tooltiptext: "Notepad++ Start",
defaultArea: CustomizableUI.AREA_NAVBAR,
onCreated: btn => btn.image = "moz-icon:file:///C://Program Files//Notepad++//notepad++.exe?size=16",
onCommand: function(event) {
var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath("C:\\Program Files\\Notepad++\\notepad++.exe");
if (file.exists()) file.launch();
}
});
} catch(e) {}
Alles anzeigen
Man beachte die notwendige, unterschiedliche Verwendung von slash/backslash in den Pfadangaben! Man könnte natürlich eine Pfadvariable nutzen und dann im Aufruf file.initWithPath die slashes vorher umdrehen - oder quick&dirty, so wie oben.
Das sehe ich komplett anders.
[...]
Dem wäre nicht so, wäre JavaScript tatsächlich eine „überholte Sprache“.
Ich glaube gar nicht, dass du das so komplett anders siehst
. Ich hatte geschrieben "konzeptionell überholte Sprache". Die Kompatibilitätsproblematik hat man bei sehr vielen Sprachen bzw. überall da, wo stark verbreitete Software eingesetzt wird (z.B. windows). Das ist zwar unschön, aber auch kaum vermeidbar. Wenn in sehr "alten" Sprachen bestimmte Konzepte nicht verwirklicht wurden, wie in 'C' (ca. 1970) oder Fortran (1957), dann ist das natürlich verzeihlich, weil sie in einer Zeit mit anderen Anforderungen entwickelt wurden, wo diese Konzepte noch nicht, oder nur als theoretische oder experimentelle Ideen im akademischen Bereich existiert haben. Aber als JavaScript erschienen ist (1995), gab es diese Konzepte schon und zwar als nutzbare Programmiersprachen z.B. C++, Java etwa zeitgleich.
Ich will JavaScript gar nicht schlecht machen. Die Sprache ist nun mal da, wird auch noch weiterentwickelt (was gut ist!) und ist extrem weit verbreitet. Das ist der status quo und daraus sollte man eben das Bestmögliche machen. Ich bin ja auch nicht der Meinung, dass deine Hinweise falsch sind, haben für mich persönlich nur eine andere Priorität.
Hat die länge/größe von einem Skript Einfluss auf die Performance vom Firefox?
Prinzipiell kann man das nicht beantworten. Es kommt immer darauf an, wie oft der (zusätzliche) Code zur Ausführung kommt und vor allem wann. Wenn der gesamte Code nur einmal beim Start eine gewisse Last erzeugt ist das sicherlich vernachlässigbar. Ständig oder periodisch aufgerufener Code erzeugt natürlich eine Dauerlast. Das muss wirklich konkret am Skript betrachtet werden. Wenn hingegen Ressourcen (in beträchtlichem Umfang!) durch den zusätzlichen Code beansprucht werden, dann kann sich das natürlich auch auf die Performance auswirken.
Im konkreten Beispiel glaube ich nicht, dass die relativ kleinen Button-Icons so viel Ressourcen fressen, dass man das in irgendeiner Form spürt. Auch die notwendigen, zusätzlichen Abfragen der Buttons sind für die Performance unerheblich.
Nach Möglichkeit sollte immer === verwendet werden.
Notwendig, weil JS über nur über die fehleranfällige 'dynamische Typisierung' verfügt, die Ursache vieler Fehler ist. Einerseits ist JS so verzeihend, dass alles irgendwie mit allem verglichen werden kann, andererseits werden dann wieder "strict"-Anweisungen bzw Operatoren wie "===" nachträglich (2015!) hinzugefügt, damit der Wildwuchs nicht zu groß wird. Daher resultiert auch die unterschiedliche Qualität der meisten Skripte. Die wenigen Vorgaben, die diese Sprache macht und die dynamischen Optimierungen verleiten dazu, dass jeder quasi seinen eigenen "privaten Code" in JS schreiben kann (ist in 'C' leider ähnlich). Daher gibt es auch kaum eine Sprache, die schwerer zu lesen ist als JS (mal von irgendwelchen experimentellen oder spaßhaften Sprachen abgesehen).
Die Hinweise, die du zur "Codequalität" bringst sind zwar richtig, aber für mich irgendwie nur ein Pflaster für eine konzeptionell überholte Sprache.
Lustig(?) "Wtfjs":
wtfjs - a little code blog about that language we love despite giving us so much to hate
Den Fehler hast du behoben, aber grisu2099 fragte nach der Prüfung, ob es bereits eine existierende Datei gibt, was du bemängelt hattest.
Stimmt. Hatte seine Frage nur flugs überflogen und dann total falsch interpretiert ...
Zur Frage von grisu2099 selber: Nein, werde ich auch nicht machen, da ich dieses Skript für absolut überflüssig halte. Wir hatten hier früher schon mal Diskussionen darüber. Zumindest unter Windows wird vom Betriebssystem selbst eine sehr gute und flexible Lösung, die den gleichen Komfort bietet, angeboten.
Hab ich das in deiner Version in #4149 richtig verstanden, daß du da jetzt diese Abfrage eingebaut hast?
Ja. Mit dieser Version wird kein Fehler mehr erzeugt...
Der Fehler in der Konsole besagt, dass das Skript ausgeführt wird, obwohl überhaupt kein Speichern Dialog (ID=unknownContentType) angezeigt wird. Wenn man vorher auf null prüft kann man den Fehler vermeiden und der "Speichern nach"-Button wird immer dann erzeugt, wenn der Dialog auch wirklich vorhanden ist.
Aber das Skript ist Mist. Es wird nicht einmal gefragt, ob eine eventuell schon existierende Datei überschrieben werden soll. Das Skript schreibt einfach drüber!
![]()
// ==UserScript==
// @include chrome://mozapps/content/downloads/unknownContentType.xhtml
// @charset UTF-8
// @version Fx114+
// ==/UserScript==
(function () {
const Cu = Components.utils;
const { FileUtils } = ChromeUtils.importESModule( 'resource://gre/modules/FileUtils.sys.mjs');
if (!window.Services) Cu.import('resource://gre/modules/Services.jsm');
setTimeout(function () {
saveTo();
}, 200);
function saveTo() {
// Config
const dirArray = [
['D:\\Download Firefox', 'Download Firefox'],
['D:\\Download Firefox\\Dokumente'],
['D:\\Download Firefox\\Bilder'],
['D:\\Download Firefox\\Software'],
['D:\\Download Firefox\\Ablage'],
['D:\\Download Firefox\\Sonstiges'],
["C:\\", "C:"],
["E:\\", "E:"],
];
if(document.getElementById('unknownContentType') == null) return;
const button = document.getElementById('unknownContentType').getButton('cancel');
const saveTo = button.parentNode.insertBefore(document.createXULElement('button'), button);
const saveToMenu = saveTo.appendChild(document.createXULElement('menupopup'));
saveTo.classList.toggle('dialog-button');
saveTo.label = 'Speichern nach';
saveTo.type = 'menu';
const css =`
hbox.dialog-button-box button.dialog-button menupopup {
background: gold !important;
min-width: 220px !important;
padding: 5px !important;
margin: 15px 0 0 -62px !important;
border: 3px solid dodgerblue !important;
}
hbox.dialog-button-box button.dialog-button menupopup menuitem{
appearance: none !important;
color: blue !important;
background: #fefefc !important;
border: 1px solid silver !important;
margin-top: 1px !important;
border-radius: 7px !important;
padding-left: 12px !important;
}
hbox.dialog-button-box button.dialog-button menupopup menuitem:hover {
background: greenyellow !important;
border: 1px solid red !important;
}
hbox.dialog-button-box button.dialog-button menupopup menuitem.menuitem-iconic label.menu-iconic-text {
color: blue !important;
font-size: 15px !important;
font-weight: 600 !important;
margin-left: 12px !important;
margin-top: 1px !important;
} `;
const sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
const uri = Services.io.newURI('data:text/css,' + encodeURIComponent(css));
sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
dirArray.forEach(function (directory) {
const [name, dir] = [directory[1], directory[0]];
const mi = document.createXULElement('menuitem');
const item = saveToMenu.appendChild(mi);
item.setAttribute('label', (name || (dir.match(/[^\\/]+$/) || [dir])[0]));
item.setAttribute('image', 'moz-icon:file:///' + dir + '\\');
item.setAttribute('class', 'menuitem-iconic');
item.addEventListener('command', function () {
const locationtext = document.getElementById('locationtext');
const pathFile = dir + '\\' + (locationtext ? locationtext.value : document.getElementById('location').value);
const file = new FileUtils.File(pathFile);
dialog.mLauncher.saveDestinationAvailable(file);
dialog.onCancel = function () {};
close();
});
});
}
}());
Alles anzeigen
Diese Version funktioniert einwandfrei.
Vielen Dank!!
Gerne. Freut mich, wenn es jetzt funktioniert. ![]()
Gute Vorsätze für 2025: In Zukunft werde ich jedes Skript vorher testen, bevor ich es "veröffentliche". ![]()
Das ist aber erstens kein Tooltip und zweitens zeigt der Screenshot von lenny2 in Beitrag #314 einen Tooltip. Daher gehe ich mal davon aus, dass das gemeint ist.
Ich meine aber auch, dass lenny2 den Eintrag meint, den 2002Andreas gezeigt hat...![]()
Zwei Gründe warum die Kompakt-Lösung nicht funktioniert hat.
1) Ich hatte eine ganz andere, ältere Version auf GitHub als Basis genommen. In der neueren Version gibt es noch zusätzliche Inline-Events, die ich nicht berücksichtigt hatte.
Eine Bitte: in Zukunft immer gleich das ganze Skript posten, sonst wird es wirklich schwierig und fehleranfällig.
2) Die Variable el hatte ich fälschlicherweise als e1 gelesen. Daher hatte das Skript natürlich sofort eine Exception geschmissen.
Ich habe es jetzt nicht wirklich gründlich getestet, aber jetzt sollte die geänderte Funktion passen. Egal welches Skript du letztendlich verwendest, würde ich mich freuen, wenn du diese Lösung auch mal antesten könntest...![]()
function $C(name, attr) {
var el = document.createXULElement(name);
if (attr) Object.keys(attr).forEach(function(n) {
if(n == "oncommand") {
el.addEventListener('command', function(event) { Function(attr[n])(); });
}
else if(n == "onclick") {
el.addEventListener('click', function(event) { Function(attr[n])(); });
}
else if(n == "onmouseup") {
el.addEventListener('mouseup', function(event) { Function(attr[n])(); });
}
else {
el.setAttribute(n, attr[n]);
}
});
return el;
}
Alles anzeigen
Habe ich auch getestet, dann geht das Script auch nicht mehr:
Das wusste ich nicht, dass du es schon getestet hattest. Wenn es bei dir nicht läuft, dann kann ich das nur untersuchen, wenn ich das Skript bei mir installiere. Weiß aber nicht, ob ich das zeitnah machen werde ... ![]()
Was das Script: usercssloader.uc.js betrifft habe ich gestern
weiter gemacht aber es funktioniert nicht.
Hallo Endor
Ich hatte dir hier:
eine (ungetestete) Lösung angeboten. Wenn du magst, dann probier sie einfach aus. Dafür musst du nur eine einzige Funktion austauschen, sonst kannst du alles andere so lassen, wie es bisher war...
Die Frage hatte ich übersehen.
Kein Problem...![]()
Man kann natürlich auch diesen Weg gehen. Dann muss man halt in dieser Funktion den Namen der Eigenschaft prüfen und für die on*-Eigenschaften den Listener ensprechend setzen statt das Attribut. Dann darf man nur nicht vergessen, den Namen dynamisch anzupassen, denn das on gehört ja nicht in den Event-Namen und der erste Buchstabe muss klein sein.
Ja, so habe ich es ja in dem Beispielcode auch gemacht. Ganz verstehe ich nicht, was du meinst
. 'oncommand' und 'onclick' werden nicht in die Attribute geschrieben, sondern stattdessen eben der entsprechende EventListener hinzugefügt mit 'command' und 'click'. Für alle anderen Eigenschaften des übergebenen Objekts wird die vorgegebene Standardzuweisung el.setAttribute(n, attr[n]); verwendet.
Wieso das $ verwendet wird, weiß ich nicht. Wenn ich so etwas sehe, vermute ich als erstes, dass der ursprüngliche Entwickler aus der jQuery-Entwicklung kommt und das daher hat. Aber vielleicht hatte der Entwickler auch eine ganz eigene Konvention, wann er das Dollar-Zeichen verwendet. Das müsste man den Entwickler mal fragen. Schlimmer finde ich, dass Funktionen als $, $A und $C benannt sind. Schön kurz, ja, aber nicht lesbar an den Stellen, an denen die Funktionen verwendet werden.
Ja sehe ich auch so. In einigen Scriptsprachen wird auch dieses $ vor dem Variablennamen verwendet. Wahrscheinlich noch nicht ganz in der 'neuen' Sprache angekommen, da nutzt man dann immer wieder gerne gewohnte Strukturen aus der "Heimatsprache". Habe da auch so ein paar Baustellen...![]()
Würde mich schon interessieren, ob der Code auch funktioniert. Aber ich könnte Endor auch verstehen, wenn er es nicht nochmal testen möchte, wenn die andere Herangehensweise funktioniert hat.![]()
Wenn die Funktion selbst nicht verändert werden soll, kann man das Element nutzen, welche die Methode zurück gibt. Weist man den Rückgabewert einer Variablen zu, kann man darauf dann addEventListener ausführen.
Wenn man sich das gesamte Skript anschaut, ist es dann nicht tatsächlich besser '$C()' (warum dieses überflüssige '$'-Zeichen?) zu verändern und dort den EventListener hinzuzufügen?
Sonst müsste man ja zigmal Variablen definieren und jedes Mal einen Eventlistener erstellen. So kann man direkt in der Funktion das gerade erzeugte Element nutzen und es gibt den Code für den Eventlistener für alle Elemente nur einmal.
Normalerweise würde ich es ja testen, aber mit dem 'userCSSLoader' ist mir das ehrlich gesagt zu viel Aufwand.
Hier die geändert $C()-Funktion (ab Zeile 630)
Das ist ungetestet und kann sowohl syntaktische, als auch semantische Fehler aufweisen, was sogar sehr wahrscheinlich ist![]()
Original:
function $C(name, attr) {
var el = document.createXULElement(name);
if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) });
return el;
}
Neu:
function $C(name, attr) {
var el = document.createXULElement(name);
if (attr) Object.keys(attr).forEach(function(n) {
if(n == "oncommand") {
e1.addEventListener('command', function(event) { Function(attr[n])(); });
}
else if(n == "onclick") {
e1.addEventListener('click', function(event) { Function(attr[n])(); });
}
else {
el.setAttribute(n, attr[n]);
}
});
return el;
}
Alles anzeigen
Um welches Skript geht es eigentlich genau, bei der Konversation mit FuchsFan ?
Das hier:
Gern geschehen
und danke für die Erklärung zum Sinn dieses Skripts. ![]()
Es würde mich freuen, wenn sich das mal jemand ansehen/anpassen könnte, evtl. lerne ich dadurch ja doch etwas.
Man sollte "nur von den Besten lernen" ... also nicht von mir
. Aber hier mal das Skript. Hoffe es läuft.
Setzt das wirklich nur den mediasource-Eintrag in about:config? Keine Ahnung wozu das gut ist...![]()
(function() {
if(location.href != 'chrome://browser/content/browser.xhtml') return;
try {
CustomizableUI.createWidget({
id: 'menu-button',
type: 'custom',
defaultArea: CustomizableUI.AREA_NAVBAR,
onBuild: function(aDocument) {
var button = aDocument.createXULElement('toolbarbutton');
var attributes = {
id: 'menu-button',
class: 'toolbarbutton-1 chromeclass-toolbar-additional',
removable: 'true',
label: 'Videos aufnehmen können',
tooltiptext: Services.prefs.getBoolPref('media.mediasource.enabled') ?
'Videos gesperrt' : 'Videos frei'
};
for (var a in attributes) {
button.setAttribute(a, attributes[a]);
};
return button;
}
});
} catch(e) { };
document.getElementById('menu-button').addEventListener('command', function(event) {
var isEnabled = !Services.prefs.getBoolPref('media.mediasource.enabled');
Services.prefs.setBoolPref('media.mediasource.enabled', isEnabled);
event.target.ownerGlobal.BrowserCommands.reload();
var windows = Services.wm.getEnumerator('navigator:browser');
while (windows.hasMoreElements()) {
let button = windows.getNext().document.getElementById('menu-button');
if (isEnabled)
button.setAttribute('tooltiptext', 'Videos gesperrt')
else
button.setAttribute('tooltiptext', 'Videos frei');
};
}, true);
if (document.documentElement.hasAttribute('privatebrowsingmode') &&
!Services.prefs.getBoolPref('media.mediasource.enabled'))
{
let button = document.getElementById('menu-button');
button.click();
window.addEventListener('unload', function() {
button.click();
});
};
var css =
'#menu-button[tooltiptext="Videos gesperrt"] {list-style-image: url("file:///C:/Users/weiss/AppData/Roaming/Mozilla/Firefox/Profiles/i3gghgwc.default/chrome/Icons/.2.svg")}' +
'#menu-button[tooltiptext="Videos frei"] {list-style-image: url("file:///C:/Users/weiss/AppData/Roaming/Mozilla/Firefox/Profiles/i3gghgwc.default/chrome/Icons/.1.svg")}';
var stylesheet = document.createProcessingInstruction('xml-stylesheet', 'type="text/css" href="data:text/css;utf-8,' + encodeURIComponent(css) + '"');
document.insertBefore(stylesheet, document.documentElement);
})();
Alles anzeigen
Danke!
![]()
Wieder eine Hürde genommen.
Gerne. Freut mich, wenn es jetzt läuft... ![]()
Worin bestehen die Vor, bzw. Nachteile der jeweiligen Versionen?
Ergänzend zu dem was Sören Hentzschel geschrieben hat:
Die 1.Version mit Function erzeugt aus dem String eine anonyme Funktion die dann zur Laufzeit (und damit auch im Debugger) aufgerufen wird. Das ist besonders bei generischen Funktionen hilfreich, die zur Laufzeit unterschiedliche command-events bekommen, wie wir es z.B. beim extraConfigMenu-Skript der Fall ist. Macht man es so, wie in der zweiten Version, dann müsste man eine Vielzahl von neuen Funktionsaufrufen schreiben oder Funktionen als Parameter übergeben. Im Normalfall
ist es meiner Erachtens gleich, was für eine Version verwendet wird. Da es eigentlich immer nur einen(!) Funktionsaufruf für einen command-event geben sollte. In dieser Funktion wird dann das Ereignis behandelt. In vielen unserer genutzten Skripte steht aber oft schon der halbe Code in dem 'oncommand'-Attribute, was mehr als schlecht zu lesen und verstehen ist.