/toolkit/content/widgets/text.xml

http://github.com/zpao/v8monkey · XML · 374 lines · 334 code · 39 blank · 1 comment · 0 complexity · 79dbab15dd10d5f233da9c74b3746f35 MD5 · raw file

  1. <?xml version="1.0"?>
  2. <bindings id="textBindings"
  3. xmlns="http://www.mozilla.org/xbl"
  4. xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  5. xmlns:html="http://www.w3.org/1999/xhtml">
  6. <!-- bound to <description>s -->
  7. <binding id="text-base">
  8. <implementation implements="nsIDOMXULDescriptionElement, nsIAccessibleProvider">
  9. <property name="accessibleType" readonly="true">
  10. <getter>
  11. <![CDATA[
  12. return Components.interfaces.nsIAccessibleProvider.XULText;
  13. ]]>
  14. </getter>
  15. </property>
  16. <property name="disabled" onset="if (val) this.setAttribute('disabled', 'true');
  17. else this.removeAttribute('disabled');
  18. return val;"
  19. onget="return this.getAttribute('disabled') == 'true';"/>
  20. <property name="value" onget="return this.getAttribute('value');"
  21. onset="this.setAttribute('value', val); return val;"/>
  22. <property name="crop" onget="return this.getAttribute('crop');"
  23. onset="this.setAttribute('crop', val); return val;"/>
  24. </implementation>
  25. </binding>
  26. <binding id="text-label" extends="chrome://global/content/bindings/text.xml#text-base">
  27. <implementation implements="nsIDOMXULLabelElement">
  28. <property name="accessKey">
  29. <getter>
  30. <![CDATA[
  31. var accessKey = this.getAttribute('accesskey');
  32. return accessKey ? accessKey[0] : null;
  33. ]]>
  34. </getter>
  35. <setter>
  36. <![CDATA[
  37. this.setAttribute('accesskey', val);
  38. return val;
  39. ]]>
  40. </setter>
  41. </property>
  42. <property name="control" onget="return getAttribute('control');">
  43. <setter>
  44. <![CDATA[
  45. // After this gets set, the label will use the binding #label-control
  46. this.setAttribute('control', val);
  47. return val;
  48. ]]>
  49. </setter>
  50. </property>
  51. </implementation>
  52. </binding>
  53. <binding id="label-control" extends="chrome://global/content/bindings/text.xml#text-label">
  54. <content>
  55. <html:span anonid="accessKeyParens"><children/></html:span>
  56. </content>
  57. <implementation implements="nsIDOMXULLabelElement">
  58. <constructor>
  59. <![CDATA[
  60. try {
  61. var prefs = Components.classes["@mozilla.org/preferences-service;1"].
  62. getService(Components.interfaces.nsIPrefBranch);
  63. this.mUnderlineAccesskey = (prefs.getIntPref("ui.key.menuAccessKey") != 0);
  64. const nsIPrefLocalizedString =
  65. Components.interfaces.nsIPrefLocalizedString;
  66. const prefNameInsertSeparator =
  67. "intl.menuitems.insertseparatorbeforeaccesskeys";
  68. const prefNameAlwaysAppendAccessKey =
  69. "intl.menuitems.alwaysappendaccesskeys";
  70. var val = prefs.getComplexValue(prefNameInsertSeparator,
  71. nsIPrefLocalizedString).data;
  72. this.mInsertSeparator = (val == "true");
  73. val = prefs.getComplexValue(prefNameAlwaysAppendAccessKey,
  74. nsIPrefLocalizedString).data;
  75. this.mAlwaysAppendAccessKey = (val == "true");
  76. }
  77. catch (e) { }
  78. this.formatAccessKey();
  79. ]]>
  80. </constructor>
  81. <method name="formatAccessKey">
  82. <body>
  83. <![CDATA[
  84. if (!this.mUnderlineAccesskey)
  85. return;
  86. var control = this.labeledControlElement;
  87. if (!control) {
  88. var bindingParent = document.getBindingParent(this);
  89. if (bindingParent instanceof Components.interfaces.nsIDOMXULLabeledControlElement) {
  90. control = bindingParent; // For controls that make the <label> an anon child
  91. }
  92. }
  93. if (control) {
  94. control.labelElement = this;
  95. }
  96. var afterLabel = document.getAnonymousElementByAttribute(this, "anonid", "accessKeyParens");
  97. afterLabel.textContent = ""; // This does not clear real nodes!
  98. var oldAccessKey = this.getElementsByAttribute('class', 'accesskey').item(0);
  99. if (oldAccessKey) { // Clear old accesskey
  100. this.mergeElement(oldAccessKey);
  101. }
  102. var oldHiddenSpan =
  103. this.getElementsByAttribute('class', 'hiddenColon').item(0);
  104. if (oldHiddenSpan) {
  105. this.mergeElement(oldHiddenSpan);
  106. }
  107. var accessKey = this.accessKey;
  108. var labelText = this.textContent;
  109. if (!accessKey || !labelText || !control) {
  110. return;
  111. }
  112. var accessKeyIndex = -1;
  113. if (!this.mAlwaysAppendAccessKey) {
  114. accessKeyIndex = labelText.indexOf(accessKey);
  115. if (accessKeyIndex < 0) { // Try again in upper case
  116. accessKeyIndex =
  117. labelText.toUpperCase().indexOf(accessKey.toUpperCase());
  118. }
  119. }
  120. const HTML_NS = "http://www.w3.org/1999/xhtml";
  121. var span = document.createElementNS(HTML_NS, "span");
  122. span.className = "accesskey";
  123. // Note that if you change the following code, see the comment of
  124. // nsTextBoxFrame::UpdateAccessTitle.
  125. // If accesskey is not in string, append in parentheses
  126. if (accessKeyIndex < 0) {
  127. // If end is colon, we should insert before colon.
  128. // i.e., "label:" -> "label(X):"
  129. var colonHidden = false;
  130. if (/:$/.test(labelText)) {
  131. labelText = labelText.slice(0, -1);
  132. var hiddenSpan = document.createElementNS(HTML_NS, "span");
  133. hiddenSpan.className = "hiddenColon";
  134. hiddenSpan.style.display = "none";
  135. // Hide the last colon by using span element.
  136. // I.e., label<span style="display:none;">:</span>
  137. this.wrapChar(hiddenSpan, labelText.length);
  138. colonHidden = true;
  139. }
  140. // If end is space(U+20),
  141. // we should not add space before parentheses.
  142. var endIsSpace = false;
  143. if (/ $/.test(labelText)) {
  144. endIsSpace = true;
  145. }
  146. if (this.mInsertSeparator && !endIsSpace)
  147. afterLabel.textContent = " (";
  148. else
  149. afterLabel.textContent = "(";
  150. span.textContent = accessKey.toUpperCase();
  151. afterLabel.appendChild(span);
  152. if (!colonHidden)
  153. afterLabel.appendChild(document.createTextNode(")"));
  154. else
  155. afterLabel.appendChild(document.createTextNode("):"));
  156. return;
  157. }
  158. this.wrapChar(span, accessKeyIndex);
  159. ]]>
  160. </body>
  161. </method>
  162. <method name="wrapChar">
  163. <parameter name="element"/>
  164. <parameter name="index"/>
  165. <body>
  166. <![CDATA[
  167. var treeWalker = document.createTreeWalker(this,
  168. NodeFilter.SHOW_TEXT,
  169. null,
  170. true);
  171. var node = treeWalker.nextNode();
  172. while (index >= node.length) {
  173. index -= node.length;
  174. node = treeWalker.nextNode();
  175. }
  176. if (index) {
  177. node = node.splitText(index);
  178. }
  179. node.parentNode.insertBefore(element, node);
  180. if (node.length > 1) {
  181. node.splitText(1);
  182. }
  183. element.appendChild(node);
  184. ]]>
  185. </body>
  186. </method>
  187. <method name="mergeElement">
  188. <parameter name="element"/>
  189. <body>
  190. <![CDATA[
  191. if (element.previousSibling instanceof Text) {
  192. element.previousSibling.appendData(element.textContent)
  193. }
  194. else {
  195. element.parentNode.insertBefore(element.firstChild, element);
  196. }
  197. element.parentNode.removeChild(element);
  198. ]]>
  199. </body>
  200. </method>
  201. <field name="mUnderlineAccesskey">
  202. !/Mac/.test(navigator.platform)
  203. </field>
  204. <field name="mInsertSeparator">true</field>
  205. <field name="mAlwaysAppendAccessKey">false</field>
  206. <property name="accessKey">
  207. <getter>
  208. <![CDATA[
  209. var accessKey = null;
  210. var labeledEl = this.labeledControlElement;
  211. if (labeledEl) {
  212. accessKey = labeledEl.getAttribute('accesskey');
  213. }
  214. if (!accessKey) {
  215. accessKey = this.getAttribute('accesskey');
  216. }
  217. return accessKey ? accessKey[0] : null;
  218. ]]>
  219. </getter>
  220. <setter>
  221. <![CDATA[
  222. // If this label already has an accesskey attribute store it here as well
  223. if (this.hasAttribute('accesskey')) {
  224. this.setAttribute('accesskey', val);
  225. }
  226. var control = this.labeledControlElement;
  227. if (control) {
  228. control.setAttribute('accesskey', val);
  229. }
  230. this.formatAccessKey();
  231. return val;
  232. ]]>
  233. </setter>
  234. </property>
  235. <property name="labeledControlElement" readonly="true"
  236. onget="var control = this.control; return control ? document.getElementById(control) : null;" />
  237. <property name="control" onget="return this.getAttribute('control');">
  238. <setter>
  239. <![CDATA[
  240. var control = this.labeledControlElement;
  241. if (control) {
  242. control.labelElement = null; // No longer pointed to be this label
  243. }
  244. this.setAttribute('control', val);
  245. this.formatAccessKey();
  246. return val;
  247. ]]>
  248. </setter>
  249. </property>
  250. </implementation>
  251. <handlers>
  252. <handler event="click" action="if (this.disabled) return;
  253. var controlElement = this.labeledControlElement;
  254. if(controlElement)
  255. controlElement.focus();
  256. "/>
  257. </handlers>
  258. </binding>
  259. <binding id="text-link" extends="chrome://global/content/bindings/text.xml#text-label">
  260. <implementation implements="nsIAccessibleProvider">
  261. <property name="accessibleType" readonly="true">
  262. <getter>
  263. <![CDATA[
  264. return Components.interfaces.nsIAccessibleProvider.XULLink;
  265. ]]>
  266. </getter>
  267. </property>
  268. <property name="href" onget="return this.getAttribute('href');"
  269. onset="this.setAttribute('href', val); return val;" />
  270. <method name="open">
  271. <parameter name="aEvent"/>
  272. <body>
  273. <![CDATA[
  274. var href = this.href;
  275. if (!href || this.disabled || aEvent.defaultPrevented)
  276. return;
  277. var uri = null;
  278. try {
  279. const nsISSM = Components.interfaces.nsIScriptSecurityManager;
  280. const secMan =
  281. Components.classes["@mozilla.org/scriptsecuritymanager;1"]
  282. .getService(nsISSM);
  283. const ioService =
  284. Components.classes["@mozilla.org/network/io-service;1"]
  285. .getService(Components.interfaces.nsIIOService);
  286. uri = ioService.newURI(href, null, null);
  287. var nullPrincipal =
  288. Components.classes["@mozilla.org/nullprincipal;1"]
  289. .createInstance(Components.interfaces.nsIPrincipal);
  290. try {
  291. secMan.checkLoadURIWithPrincipal(nullPrincipal, uri,
  292. nsISSM.DISALLOW_INHERIT_PRINCIPAL)
  293. }
  294. catch (ex) {
  295. var msg = "Error: Cannot open a " + uri.scheme + ": link using \
  296. the text-link binding.";
  297. Components.utils.reportError(msg);
  298. return;
  299. }
  300. const cID = "@mozilla.org/uriloader/external-protocol-service;1";
  301. const nsIEPS = Components.interfaces.nsIExternalProtocolService;
  302. var protocolSvc = Components.classes[cID].getService(nsIEPS);
  303. // if the scheme is not an exposed protocol, then opening this link
  304. // should be deferred to the system's external protocol handler
  305. if (!protocolSvc.isExposedProtocol(uri.scheme)) {
  306. protocolSvc.loadUrl(uri);
  307. aEvent.preventDefault()
  308. return;
  309. }
  310. }
  311. catch (ex) {
  312. Components.utils.reportError(ex);
  313. }
  314. // otherwise, fall back to opening the anchor directly
  315. var win = window;
  316. if (window instanceof Components.interfaces.nsIDOMChromeWindow) {
  317. while (win.opener && !win.opener.closed)
  318. win = win.opener;
  319. }
  320. if (uri)
  321. win.open(uri.spec);
  322. else
  323. win.open(href);
  324. aEvent.preventDefault();
  325. ]]>
  326. </body>
  327. </method>
  328. </implementation>
  329. <handlers>
  330. <handler event="click" phase="capturing" button="0" action="this.open(event)"/>
  331. <handler event="keypress" preventdefault="true" keycode="VK_ENTER" action="this.click()" />
  332. <handler event="keypress" preventdefault="true" keycode="VK_RETURN" action="this.click()" />
  333. </handlers>
  334. </binding>
  335. </bindings>