Bug 956657 Share more charset menu code between the view source window and the browser r=Unfocused

This commit is contained in:
Neil Rashbrook
2014-02-21 00:17:13 +00:00
parent b66c4a3b03
commit 16b51b9c2f
5 changed files with 101 additions and 229 deletions

View File

@@ -2,20 +2,18 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
#filter substitution <menu id="charsetMenu"
#expand <menu id="__ID_PREFIX__charsetMenu"
label="&charsetMenu.label;" label="&charsetMenu.label;"
#ifndef OMIT_ACCESSKEYS #ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenu.accesskey;" accesskey="&charsetMenu.accesskey;"
#endif #endif
oncommand="MultiplexHandler(event)" oncommand="BrowserSetForcedCharacterSet(event.target.getAttribute('charset'));"
#ifdef OMIT_ACCESSKEYS #ifdef OMIT_ACCESSKEYS
#expand onpopupshowing="CharsetMenu.build(event.target, '__ID_PREFIX__', false);" onpopupshowing="CharsetMenu.build(event.target, false);"
#else #else
#expand onpopupshowing="CharsetMenu.build(event.target, '__ID_PREFIX__');" onpopupshowing="CharsetMenu.build(event.target);"
#endif #endif
onpopupshown="UpdateMenus(event);"> onpopupshown="UpdateCurrentCharset(this);">
<menupopup> <menupopup>
</menupopup> </menupopup>
</menu> </menu>

View File

@@ -5139,55 +5139,15 @@ function handleDroppedLink(event, url, name)
event.preventDefault(); event.preventDefault();
}; };
function MultiplexHandler(event)
{ try {
var node = event.target;
var name = node.getAttribute('name');
if (name == 'detectorGroup') {
BrowserCharsetReload();
SelectDetector(event, false);
} else if (name == 'charsetGroup') {
var charset = node.getAttribute('id');
charset = charset.substring(charset.indexOf('charset.') + 'charset.'.length);
BrowserSetForcedCharacterSet(charset);
} else if (name == 'charsetCustomize') {
//do nothing - please remove this else statement, once the charset prefs moves to the pref window
} else {
BrowserSetForcedCharacterSet(node.getAttribute('id'));
}
} catch(ex) { alert(ex); }
}
function SelectDetector(event, doReload)
{
var uri = event.target.getAttribute("id");
var prefvalue = uri.substring(uri.indexOf('chardet.') + 'chardet.'.length);
if ("off" == prefvalue) { // "off" is special value to turn off the detectors
prefvalue = "";
}
try {
var str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
str.data = prefvalue;
gPrefService.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
if (doReload)
window.content.location.reload();
}
catch (ex) {
dump("Failed to set the intl.charset.detector preference.\n");
}
}
function BrowserSetForcedCharacterSet(aCharset) function BrowserSetForcedCharacterSet(aCharset)
{ {
if (aCharset) {
gBrowser.docShell.gatherCharsetMenuTelemetry(); gBrowser.docShell.gatherCharsetMenuTelemetry();
gBrowser.docShell.charset = aCharset; gBrowser.docShell.charset = aCharset;
// Save the forced character-set // Save the forced character-set
if (!PrivateBrowsingUtils.isWindowPrivate(window)) if (!PrivateBrowsingUtils.isWindowPrivate(window))
PlacesUtils.setCharsetForURI(getWebNavigation().currentURI, aCharset); PlacesUtils.setCharsetForURI(getWebNavigation().currentURI, aCharset);
}
BrowserCharsetReload(); BrowserCharsetReload();
} }
@@ -5196,8 +5156,8 @@ function BrowserCharsetReload()
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE); BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
} }
function charsetMenuGetElement(parent, id) { function charsetMenuGetElement(parent, charset) {
return parent.getElementsByAttribute("id", id)[0]; return parent.getElementsByAttribute("charset", charset)[0];
} }
function UpdateCurrentCharset(target) { function UpdateCurrentCharset(target) {
@@ -5207,54 +5167,19 @@ function UpdateCurrentCharset(target) {
// Uncheck previous item // Uncheck previous item
if (gPrevCharset) { if (gPrevCharset) {
var pref_item = charsetMenuGetElement(target, "charset." + gPrevCharset); var pref_item = charsetMenuGetElement(target, gPrevCharset);
if (pref_item) if (pref_item)
pref_item.setAttribute('checked', 'false'); pref_item.setAttribute('checked', 'false');
} }
var menuitem = charsetMenuGetElement(target, "charset." + FoldCharset(wnd.document.characterSet)); var menuitem = charsetMenuGetElement(target, CharsetMenu.foldCharset(wnd.document.characterSet));
if (menuitem) { if (menuitem) {
menuitem.setAttribute('checked', 'true'); menuitem.setAttribute('checked', 'true');
} }
} }
function FoldCharset(charset) {
// For substantially similar encodings, treat two encodings as the same
// for the purpose of the check mark.
if (charset == "ISO-8859-8-I") {
return "windows-1255";
}
if (charset == "gb18030") {
return "gbk";
}
return charset;
}
function UpdateCharsetDetector(target) {
var prefvalue;
try {
prefvalue = gPrefService.getComplexValue("intl.charset.detector", Ci.nsIPrefLocalizedString).data;
}
catch (ex) {}
if (!prefvalue)
prefvalue = "off";
var menuitem = charsetMenuGetElement(target, "chardet." + prefvalue);
if (menuitem)
menuitem.setAttribute("checked", "true");
}
function UpdateMenus(event) {
UpdateCurrentCharset(event.target);
UpdateCharsetDetector(event.target);
}
function charsetLoadListener() { function charsetLoadListener() {
var charset = FoldCharset(window.content.document.characterSet); var charset = CharsetMenu.fold(window.content.document.characterSet);
if (charset.length > 0 && (charset != gLastBrowserCharset)) { if (charset.length > 0 && (charset != gLastBrowserCharset)) {
gPrevCharset = gLastBrowserCharset; gPrevCharset = gLastBrowserCharset;

View File

@@ -657,84 +657,13 @@ function BrowserCharsetReload()
} }
} }
function BrowserSetForcedCharacterSet(aCharset) function BrowserSetCharacterSet(aEvent)
{ {
gBrowser.docShell.charset = aCharset; if (aEvent.target.hasAttribute("charset"))
gBrowser.docShell.charset = aEvent.target.getAttribute("charset");
BrowserCharsetReload(); BrowserCharsetReload();
} }
function MultiplexHandler(event)
{
var node = event.target;
var name = node.getAttribute("name");
if (name == "detectorGroup") {
SelectDetector(event);
BrowserCharsetReload();
} else if (name == "charsetGroup") {
var charset = node.getAttribute("id");
charset = charset.substring(charset.indexOf("charset.") + "charset.".length);
BrowserSetForcedCharacterSet(charset);
}
}
function SelectDetector(event)
{
var uri = event.target.getAttribute("id");
var prefvalue = uri.substring(uri.indexOf("chardet.") + "chardet.".length);
if ("off" == prefvalue) { // "off" is special value to turn off the detectors
prefvalue = "";
}
try {
var str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
str.data = prefvalue;
gPrefService.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
}
catch (ex) {
dump("Failed to set the intl.charset.detector preference.\n");
}
}
function FoldCharset(charset) {
// For substantially similar encodings, treat two encodings as the same
// for the purpose of the check mark.
if (charset == "ISO-8859-8-I") {
return "windows-1255";
} else if (charset == "gb18030") {
return "gbk";
}
return charset;
}
function UpdateCurrentCharset() {
var menuitem = document.getElementById("charset." + FoldCharset(content.document.characterSet));
if (menuitem)
menuitem.setAttribute("checked", "true");
}
function UpdateCharsetDetector() {
var prefvalue;
try {
prefvalue = gPrefService.getComplexValue("intl.charset.detector", Ci.nsIPrefLocalizedString).data;
}
catch (ex) {}
if (!prefvalue)
prefvalue = "off";
var menuitem = document.getElementById("chardet." + prefvalue);
if (menuitem)
menuitem.setAttribute("checked", "true");
}
function UpdateMenus() {
UpdateCurrentCharset();
UpdateCharsetDetector();
}
function BrowserForward(aEvent) { function BrowserForward(aEvent) {
try { try {
gBrowser.goForward(); gBrowser.goForward();

View File

@@ -201,11 +201,10 @@
<menu id="charsetMenu" <menu id="charsetMenu"
label="&charsetMenu.label;" label="&charsetMenu.label;"
accesskey="&charsetMenu.accesskey;" accesskey="&charsetMenu.accesskey;"
oncommand="MultiplexHandler(event);" oncommand="BrowserSetCharacterSet(event);"
onpopupshowing="CharsetMenu.build(event.target);" onpopupshowing="CharsetMenu.build(event.target);"
onpopupshown="UpdateMenus();"> onpopupshown="CharsetMenu.update(event, content.document.characterSet);">
<menupopup> <menupopup/>
</menupopup>
</menu> </menu>
<menuseparator/> <menuseparator/>
<menuitem id="menu_wrapLongLines" type="checkbox" command="cmd_wrapLongLines" <menuitem id="menu_wrapLongLines" type="checkbox" command="cmd_wrapLongLines"

View File

@@ -14,7 +14,7 @@ XPCOMUtils.defineLazyGetter(this, "gBundle", function() {
}); });
const kAutoDetectors = [ const kAutoDetectors = [
["off", "off"], ["off", ""],
["ja", "ja_parallel_state_machine"], ["ja", "ja_parallel_state_machine"],
["ru", "ruprob"], ["ru", "ruprob"],
["uk", "ukprob"] ["uk", "ukprob"]
@@ -89,33 +89,55 @@ const kPinned = [
kPinned.forEach(x => kEncodings.delete(x)); kPinned.forEach(x => kEncodings.delete(x));
function CharsetComparator(a, b) {
// Normal sorting sorts the part in parenthesis in an order that
// happens to make the less frequently-used items first.
let titleA = a.label.replace(/\(.*/, "") + b.value;
let titleB = b.label.replace(/\(.*/, "") + a.value;
// Secondarily reverse sort by encoding name to sort "windows" or
// "shift_jis" first.
return titleA.localeCompare(titleB) || b.value.localeCompare(a.value);
}
function SetDetector(event) {
let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
str.data = event.target.getAttribute("detector");
Services.prefs.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
}
function UpdateDetectorMenu(event) {
event.stopPropagation();
let detector = Services.prefs.getComplexValue("intl.charset.detector", Ci.nsIPrefLocalizedString);
let menuitem = this.getElementsByAttribute("detector", detector).item(0);
if (menuitem) {
menuitem.setAttribute("checked", "true");
}
}
let gDetectorInfoCache, gCharsetInfoCache, gPinnedInfoCache; let gDetectorInfoCache, gCharsetInfoCache, gPinnedInfoCache;
let CharsetMenu = { let CharsetMenu = {
build: function(parent, idPrefix="", showAccessKeys=true) { build: function(parent, showAccessKeys=true, showDetector=true) {
function createDOMNode(doc, nodeInfo) { function createDOMNode(doc, nodeInfo) {
let node = doc.createElement("menuitem"); let node = doc.createElement("menuitem");
node.setAttribute("type", "radio"); node.setAttribute("type", "radio");
node.setAttribute("name", nodeInfo.name); node.setAttribute("name", nodeInfo.name + "Group");
node.setAttribute(nodeInfo.name, nodeInfo.value);
node.setAttribute("label", nodeInfo.label); node.setAttribute("label", nodeInfo.label);
if (showAccessKeys && nodeInfo.accesskey) { if (showAccessKeys && nodeInfo.accesskey) {
node.setAttribute("accesskey", nodeInfo.accesskey); node.setAttribute("accesskey", nodeInfo.accesskey);
} }
if (idPrefix) {
node.id = idPrefix + nodeInfo.id;
} else {
node.id = nodeInfo.id;
}
return node; return node;
} }
if (parent.childElementCount > 0) { if (parent.hasChildNodes()) {
// Detector menu or charset menu already built // Detector menu or charset menu already built
return; return;
} }
this._ensureDataReady();
let doc = parent.ownerDocument; let doc = parent.ownerDocument;
if (showDetector) {
let menuNode = doc.createElement("menu"); let menuNode = doc.createElement("menu");
menuNode.setAttribute("label", gBundle.GetStringFromName("charsetMenuAutodet")); menuNode.setAttribute("label", gBundle.GetStringFromName("charsetMenuAutodet"));
if (showAccessKeys) { if (showAccessKeys) {
@@ -125,10 +147,13 @@ let CharsetMenu = {
let menuPopupNode = doc.createElement("menupopup"); let menuPopupNode = doc.createElement("menupopup");
menuNode.appendChild(menuPopupNode); menuNode.appendChild(menuPopupNode);
menuPopupNode.addEventListener("command", SetDetector);
menuPopupNode.addEventListener("popupshown", UpdateDetectorMenu);
this._ensureDataReady();
gDetectorInfoCache.forEach(detectorInfo => menuPopupNode.appendChild(createDOMNode(doc, detectorInfo))); gDetectorInfoCache.forEach(detectorInfo => menuPopupNode.appendChild(createDOMNode(doc, detectorInfo)));
parent.appendChild(doc.createElement("menuseparator")); parent.appendChild(doc.createElement("menuseparator"));
}
gPinnedInfoCache.forEach(charsetInfo => parent.appendChild(createDOMNode(doc, charsetInfo))); gPinnedInfoCache.forEach(charsetInfo => parent.appendChild(createDOMNode(doc, charsetInfo)));
parent.appendChild(doc.createElement("menuseparator")); parent.appendChild(doc.createElement("menuseparator"));
gCharsetInfoCache.forEach(charsetInfo => parent.appendChild(createDOMNode(doc, charsetInfo))); gCharsetInfoCache.forEach(charsetInfo => parent.appendChild(createDOMNode(doc, charsetInfo)));
@@ -147,58 +172,30 @@ let CharsetMenu = {
if (!gDetectorInfoCache) { if (!gDetectorInfoCache) {
gDetectorInfoCache = this.getDetectorInfo(); gDetectorInfoCache = this.getDetectorInfo();
gPinnedInfoCache = this.getCharsetInfo(kPinned, false); gPinnedInfoCache = this.getCharsetInfo(kPinned, false);
gCharsetInfoCache = this.getCharsetInfo([...kEncodings]); gCharsetInfoCache = this.getCharsetInfo(kEncodings);
} }
}, },
getDetectorInfo: function() { getDetectorInfo: function() {
return kAutoDetectors.map(([detectorName, nodeId]) => ({ return kAutoDetectors.map(([detectorName, nodeId]) => ({
id: "chardet." + nodeId,
label: this._getDetectorLabel(detectorName), label: this._getDetectorLabel(detectorName),
accesskey: this._getDetectorAccesskey(detectorName), accesskey: this._getDetectorAccesskey(detectorName),
name: "detectorGroup", name: "detector",
value: nodeId
})); }));
}, },
getCharsetInfo: function(charsets, sort=true) { getCharsetInfo: function(charsets, sort=true) {
let list = charsets.map(charset => ({ let list = [{
id: "charset." + charset,
label: this._getCharsetLabel(charset), label: this._getCharsetLabel(charset),
accesskey: this._getCharsetAccessKey(charset), accesskey: this._getCharsetAccessKey(charset),
name: "charsetGroup", name: "charset",
})); value: charset
} for (charset of charsets)];
if (!sort) { if (sort) {
return list; list.sort(CharsetComparator);
} }
list.sort(function (a, b) {
let titleA = a.label;
let titleB = b.label;
// Normal sorting sorts the part in parenthesis in an order that
// happens to make the less frequently-used items first.
let index;
if ((index = titleA.indexOf("(")) > -1) {
titleA = titleA.substring(0, index);
}
if ((index = titleB.indexOf("(")) > -1) {
titleA = titleB.substring(0, index);
}
let comp = titleA.localeCompare(titleB);
if (comp) {
return comp;
}
// secondarily reverse sort by encoding name to sort "windows" or
// "shift_jis" first. This works regardless of localization, because
// the ids aren't localized.
if (a.id < b.id) {
return 1;
}
if (b.id < a.id) {
return -1;
}
return 0;
});
return list; return list;
}, },
@@ -235,6 +232,30 @@ let CharsetMenu = {
} catch (ex) {} } catch (ex) {}
return ""; return "";
}, },
/**
* For substantially similar encodings, treat two encodings as the same
* for the purpose of the check mark.
*/
foldCharset: function(charset) {
switch (charset) {
case "ISO-8859-8-I":
return "windows-1255";
case "gb18030":
return "gbk";
default:
return charset;
}
},
update: function(event, charset) {
let menuitem = event.target.getElementsByAttribute("charset", this.foldCharset(charset)).item(0);
if (menuitem) {
menuitem.setAttribute("checked", "true");
}
},
}; };
Object.freeze(CharsetMenu); Object.freeze(CharsetMenu);