home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 March / PCWorld_2005-03_cd.bin / komunikace / kmeleon / kmeleon09.exe / comm.jar / content / navigator / linkToolbarHandler.js < prev    next >
Text File  |  2003-06-24  |  8KB  |  290 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Eric Hodel's <drbrain@segment7.net> code.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Eric Hodel.
  18.  * Portions created by the Initial Developer are Copyright (C) 2001
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  *      Christopher Hoess <choess@force.stwing.upenn.edu>
  23.  *      Tim Taylor <tim@tool-man.org>
  24.  *      Stuart Ballard <sballard@netreach.net>
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  28.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the MPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the MPL, the GPL or the LGPL.
  37.  *
  38.  * ***** END LICENSE BLOCK ***** */
  39.  
  40. /** 
  41.  * LinkToolbarHandler is a Singleton that displays LINK elements 
  42.  * and nodeLists of LINK elements in the Link Toolbar.  It
  43.  * associates the LINK with a corresponding LinkToolbarItem based 
  44.  * on it's REL attribute and the toolbar item's ID attribute.
  45.  * LinkToolbarHandler is also a Factory and will create 
  46.  * LinkToolbarItems as necessary.
  47.  */
  48. function LinkToolbarHandler()
  49. {
  50.   this.items = new Array();
  51.   this.hasItems = false;
  52. }
  53.  
  54. LinkToolbarHandler.prototype.handle =
  55. function(element)
  56. {
  57.   // XXX: if you're going to re-enable handling of anchor elements,
  58.   //    you'll want to change this to AnchorElementDecorator
  59.   var linkElement = new LinkElementDecorator(element);
  60.  
  61.   if (linkElement.isIgnored()) return;
  62.  
  63.   for (var i = 0; i < linkElement.relValues.length; i++) {
  64.     var linkType = LinkToolbarHandler.getLinkType(linkElement.relValues[i]);
  65.     if (linkType) {
  66.       if (!this.hasItems) {
  67.         this.hasItems = true;
  68.         linkToolbarUI.activate();
  69.       }
  70.       this.getItemForLinkType(linkType).displayLink(linkElement);
  71.     }
  72.   }
  73. }
  74.  
  75. LinkToolbarHandler.getLinkType =
  76. function(relAttribute)
  77. {
  78.   switch (relAttribute.toLowerCase()) {
  79.     case "start":
  80.     case "top":
  81.     case "origin":
  82.       return "top";
  83.  
  84.     case "up":
  85.     case "parent":
  86.       return "up";
  87.  
  88.     case "begin":
  89.     case "first":
  90.       return "first";
  91.  
  92.     case "next":
  93.     case "child":
  94.       return "next";
  95.  
  96.     case "prev":
  97.     case "previous":
  98.       return "prev";
  99.  
  100.     case "end":
  101.     case "last":
  102.       return "last";
  103.  
  104.     case "author":
  105.     case "made":
  106.       return "author";
  107.  
  108.     case "contents":
  109.     case "toc":
  110.       return "toc";
  111.  
  112.     case "prefetch":
  113.       return null;
  114.  
  115.     default:
  116.       return relAttribute.toLowerCase();
  117.   }
  118. }
  119.  
  120. LinkToolbarHandler.prototype.getItemForLinkType =
  121. function(linkType) {
  122.   if (!(linkType in this.items && this.items[linkType]))
  123.     this.items[linkType] = LinkToolbarHandler.createItemForLinkType(linkType);
  124.  
  125.   return this.items[linkType];
  126. }
  127.  
  128. LinkToolbarHandler.createItemForLinkType =
  129. function(linkType)
  130. {
  131.   if (!document.getElementById("link-" + linkType))
  132.     return new LinkToolbarTransientMenu(linkType);
  133.  
  134.   // XXX: replace switch with polymorphism
  135.   switch(document.getElementById("link-" + linkType).localName) {
  136.     case "toolbarbutton":
  137.       return new LinkToolbarButton(linkType);
  138.  
  139.     case "menuitem":
  140.       return new LinkToolbarItem(linkType);
  141.  
  142.     case "menu":
  143.       return new LinkToolbarMenu(linkType);
  144.  
  145.     default:
  146.       return new LinkToolbarTransientMenu(linkType);
  147.   }
  148. }
  149.  
  150. LinkToolbarHandler.prototype.clearAllItems =
  151. function()
  152. {
  153.   // Hide the 'miscellaneous' separator
  154.   document.getElementById("misc-separator").setAttribute("collapsed", "true");
  155.  
  156.   // Disable the individual items
  157.   for (var linkType in this.items)
  158.     this.items[linkType].clear();
  159.  
  160.   // Store the fact that the toolbar is empty
  161.   this.hasItems = false;
  162. }
  163.  
  164. const linkToolbarHandler = new LinkToolbarHandler();
  165.  
  166.  
  167. function LinkElementDecorator(element) {
  168.   /*
  169.    * XXX: this is an incomplete decorator, because it doesn't implement
  170.    *      the full Element interface.  If you need to use a method 
  171.    *      or member in the Element interface, just add it here and
  172.    *      have it delegate to this.element
  173.    *
  174.    * XXX: would rather add some methods to Element.prototype instead of
  175.    *    using a decorator, but Element.prototype is no longer exposed 
  176.    *      since the XPCDOM landing, see bug 83433
  177.    */
  178.  
  179.   if (!element) return; // skip the rest on foo.prototype = new ThisClass calls
  180.   
  181.   this.element = element;
  182.   
  183.   this.rel = LinkElementDecorator.convertRevMade(element.rel, element.rev);
  184.   if (this.rel)
  185.     this.relValues = this.rel.split(" ");
  186.   this.rev = element.rev;
  187.   this.title = element.title;
  188.   this.href = element.href;
  189.   this.hreflang = element.hreflang;
  190.   this.media = element.media;
  191.   this.longTitle = null;
  192. }
  193.  
  194. LinkElementDecorator.prototype.isIgnored =
  195. function()
  196. {
  197.   if (!this.rel) return true;
  198.   for (var i = 0; i < this.relValues.length; i++)
  199.     if (/^stylesheet$|^icon$|^fontdef$|^p3pv|^schema./i.test(this.relValues[i]))
  200.       return true;
  201.   return false;
  202. }
  203.  
  204. LinkElementDecorator.convertRevMade =
  205. function(rel, rev) 
  206. {
  207.   if (!rel && rev && /\bmade\b/i.test(rev))
  208.     return rev;
  209.   else
  210.     return rel;
  211. }
  212.  
  213. LinkElementDecorator.prototype.getTooltip =
  214. function() 
  215. {
  216.   return this.getLongTitle() != "" ? this.getLongTitle() : this.href;
  217. }
  218.  
  219. LinkElementDecorator.prototype.getLabel =
  220. function() 
  221. {
  222.   return this.getLongTitle() != "" ? this.getLongTitle() : this.rel;
  223. }
  224.  
  225. LinkElementDecorator.prototype.getLongTitle =
  226. function() 
  227. {
  228.   if (this.longTitle == null)
  229.     this.longTitle = this.makeLongTitle();
  230.  
  231.   return this.longTitle;
  232. }
  233.  
  234. LinkElementDecorator.prototype.makeLongTitle =
  235. function()
  236. {
  237.   var prefix = "";
  238.  
  239.   // XXX: lookup more meaningful and localized version of media, 
  240.   //   i.e. media="print" becomes "Printable" or some such
  241.   // XXX: use localized version of ":" separator
  242.   if (this.media && !/\ball\b|\bscreen\b/i.test(this.media))
  243.     prefix += this.media + ": ";
  244.   if (this.hreflang)
  245.     prefix += languageDictionary.lookupLanguageName(this.hreflang)
  246.           + ": ";
  247.  
  248.   return this.title ? prefix + this.title : prefix;
  249. }
  250.  
  251. function AnchorElementDecorator(element) {
  252.   this.constructor(element);
  253. }
  254. AnchorElementDecorator.prototype = new LinkElementDecorator;
  255.  
  256. AnchorElementDecorator.prototype.getLongTitle =
  257. function() 
  258. {
  259.   return this.title ? this.__proto__.getLongTitle.apply(this) 
  260.       : getText(this.element);
  261. }
  262.  
  263. AnchorElementDecorator.prototype.getText =
  264. function(element)
  265. {
  266.   return condenseWhitespace(getTextRecursive(element));
  267. }
  268.  
  269. AnchorElementDecorator.prototype.getTextRecursive =
  270. function(node) 
  271. {
  272.   var text = "";
  273.   node.normalize();
  274.   if (node.hasChildNodes()) {
  275.     for (var i = 0; i < node.childNodes.length; i++) {
  276.       if (node.childNodes.item(i).nodeType == Node.TEXT_NODE)
  277.         text += node.childNodes.item(i).nodeValue;
  278.       else if (node.childNodes.item(i).nodeType == Node.ELEMENT_NODE)
  279.         text += getTextRecursive(node.childNodes.item(i));
  280.     }
  281.   }
  282.  
  283.   return text;
  284. }
  285.  
  286. AnchorElementDecorator.prototype.condenseWhitespace =
  287. function(text)
  288. {
  289.   return text.replace(/\W*$/, "").replace(/^\W*/, "").replace(/\W+/g, " ");
  290. }