home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 January / 01_02.iso / software / netscape62win / browser.xpi / bin / chrome / comm.jar / content / communicator / contentAreaDD.js < prev    next >
Encoding:
JavaScript  |  2001-06-28  |  9.7 KB  |  285 lines

  1. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * The Original Code is mozilla.org code.
  14.  *
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are
  17.  * Copyright (C) 1998 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributors:
  21.  * 
  22.  *   Alec Flett      <alecf@netscape.com>
  23.  *   Ben Goodger     <ben@netscape.com>
  24.  *   Mike Pinkerton  <pinkerton@netscape.com>
  25.  *   Blake Ross      <blakeross@telocity.com>
  26.  *   
  27.  */
  28.  
  29. var contentAreaDNDObserver = {
  30.   onDragStart: function (aEvent, aXferData, aDragAction)
  31.     {
  32.       if (aEvent.getPreventDefault())
  33.         throw Components.results.NS_ERROR_FAILURE;
  34.  
  35.       // only drag form elements by using the alt key,
  36.       // otherwise buttons and select widgets are hard to use
  37.       if ('form' in aEvent.target && !aEvent.altKey)
  38.         throw Components.results.NS_ERROR_FAILURE;
  39.  
  40.       var draggedNode = aEvent.target;
  41.  
  42.       // the resulting strings from the beginning of the drag
  43.       var titlestring = null;
  44.       var urlstring = null;
  45.       // htmlstring will be filled automatically if you fill urlstring
  46.       var htmlstring = null;
  47.       var isAnchor = false;
  48.       var domselection = aEvent.view.getSelection();
  49.       if (domselection && !domselection.isCollapsed && 
  50.           domselection.containsNode(draggedNode,false))
  51.         {
  52.           // track down the anchor node, if any
  53.  
  54.           var firstAnchor = this.findFirstAnchor(domselection.anchorNode);
  55.  
  56.           if (firstAnchor && domselection.containsNode(firstAnchor,false)) {
  57.             isAnchor = true;
  58.             urlstring = firstAnchor.href;
  59.           }
  60.  
  61.           var privateSelection = domselection.QueryInterface(Components.interfaces.nsISelectionPrivate);
  62.           if (privateSelection)
  63.           {
  64.           
  65.             // the window has a selection so we should grab that rather
  66.             // than looking for specific elements
  67.             htmlstring = privateSelection.toStringWithFormat("text/html", 128+256, 0);
  68.             titlestring = privateSelection.toStringWithFormat("text/plain", 0, 0);
  69.           } else {
  70.             titlestring = domselection.toString();
  71.           }
  72.         }
  73.       else 
  74.         {
  75.           if (aEvent.altKey && findParentNode(draggedNode, 'a'))
  76.             return false;
  77.           
  78.           switch (draggedNode.localName.toUpperCase())
  79.             {
  80.               case 'AREA':
  81.               case 'IMG':
  82.                 var imgsrc = draggedNode.getAttribute("src");
  83.                 var baseurl = window._content.location.href;
  84.                 // need to do some stuff with the window._content.location
  85.                 // (path?) to get base URL for image.
  86.  
  87.                 // use alt text as the title of the image, if  it's there
  88.                 titlestring = draggedNode.getAttribute("alt");
  89.                 urlstring = imgsrc;
  90.                 htmlstring = "<img src=\"" + urlstring + "\">";
  91.  
  92.                 // if the image is also a link, then re-wrap htmlstring in
  93.                 // an anchor tag
  94.                 linkNode = findParentNode(draggedNode, 'a');
  95.                 if (linkNode) {
  96.                   isAnchor = true;
  97.                   urlstring = this.getAnchorUrl(linkNode);
  98.                   htmlstring = this.createLinkText(urlstring, htmlstring);
  99.                 }
  100.                 break;
  101.               case 'A':
  102.                 urlstring = this.getAnchorUrl(draggedNode);
  103.                 titlestring = this.getNodeString(draggedNode);
  104.                  // this causes d&d problems on windows -- see bug 68058
  105.                  //aDragAction.action =  Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
  106.                 isAnchor = true;
  107.                 break;
  108.                 
  109.               default:
  110.                 var linkNode = findParentNode(draggedNode, 'a');
  111.                 
  112.                 if (linkNode) {
  113.                   urlstring = this.getAnchorUrl(linkNode);
  114.                   titlestring = this.getNodeString(linkNode);
  115.                   // select node now!
  116.                   // this shouldn't be fatal, and
  117.                   // we should still do the drag if this fails
  118.                   try {
  119.                     this.normalizeSelection(linkNode, domselection);
  120.                   } catch (ex) {
  121.                     // non-fatal, so catch & ignore
  122.                   }
  123.   
  124.                  isAnchor = true;
  125.                  // this causes d&d problems on windows -- see bug 68058
  126.                  //aDragAction.action = Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
  127.                 }
  128.                 else {
  129.                   // Need to throw to indicate that the drag target should not 
  130.                   // allow drags.
  131.                   throw Components.results.NS_OK;
  132.                 }
  133.                 break;
  134.             }
  135.         }
  136.  
  137.       // default text value is the URL
  138.       if (!titlestring) titlestring = urlstring;
  139.  
  140.       // if we haven't constructed a html version, make one now
  141.       if (!htmlstring && urlstring)
  142.         htmlstring = this.createLinkText(urlstring, titlestring);
  143.  
  144.       // now create the flavour lists
  145.       aXferData.data = new TransferData();
  146.       if (urlstring && isAnchor) {
  147.         aXferData.data.addDataForFlavour("text/x-moz-url", urlstring + "\n" + titlestring);
  148.       }
  149.  
  150.       aXferData.data.addDataForFlavour("text/unicode", isAnchor ? urlstring :  titlestring);
  151.       aXferData.data.addDataForFlavour("text/html", htmlstring);
  152.  
  153.       // we use the url for text/unicode data if an anchor is being dragged, rather than
  154.       // the title text of the link or the alt text for an anchor image. 
  155.     },
  156.  
  157.   onDragOver: function (aEvent, aFlavour, aDragSession)
  158.     {
  159.       if (aEvent.getPreventDefault())
  160.         return;
  161.         
  162.       // if the drag originated w/in this content area, bail
  163.       // early. This avoids loading a URL dragged from the content
  164.       // area into the very same content area (which is almost never
  165.       // the desired action). This code is a bit too simplistic and
  166.       // may have problems with nested frames, but that's not my
  167.       // problem ;)
  168.       if (aDragSession.sourceDocument == aEvent.view.document) {
  169.         aDragSession.canDrop = false;
  170.         return;
  171.       }
  172.       // this causes d&d problems on windows -- see bug 68058
  173.       //aDragSession.dragAction = Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
  174.     },
  175.  
  176.   onDrop: function (aEvent, aXferData, aDragSession)
  177.     {
  178.       var url = retrieveURLFromData(aXferData.data, aXferData.flavour.contentType);
  179.  
  180.       // valid urls don't contain spaces ' '; if we have a space it isn't a valid url so bail out
  181.       if (!url || !url.length || url.indexOf(" ", 0) != -1) 
  182.         return;
  183.  
  184.       switch (document.firstChild.getAttribute('windowtype')) {
  185.         case "navigator:browser":
  186.           loadURI(getShortcutOrURI(url));
  187.           break;
  188.         case "navigator:view-source":
  189.           viewSource(url);
  190.           break;
  191.       }
  192.     },
  193.  
  194.   getSupportedFlavours: function ()
  195.     {
  196.       var flavourSet = new FlavourSet();
  197.       flavourSet.appendFlavour("text/x-moz-url");
  198.       flavourSet.appendFlavour("text/unicode");
  199.       flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
  200.       return flavourSet;
  201.     },
  202.  
  203.   createLinkText: function(url, text)
  204.   {
  205.     return "<a href=\"" + url + "\">" + text + "</a>";
  206.   },
  207.  
  208.   findFirstAnchor: function(node)
  209.   {
  210.     if (!node) return null;
  211.  
  212.     while (node) {
  213.       if (node.nodeType == Node.ELEMENT_NODE &&
  214.           node.localName.toLowerCase() == "a")
  215.         return node;
  216.       
  217.       var childResult = this.findFirstAnchor(node.firstChild);
  218.       if (childResult)
  219.         return childResult;
  220.  
  221.       node = node.nextSibling;
  222.     }
  223.     return null;
  224.   },
  225.   
  226.   normalizeSelection: function(baseNode, domselection)
  227.   {
  228.     var parent = baseNode.parentNode;
  229.     if (!parent) return;
  230.     if (!domselection) return;
  231.  
  232.     var nodelist = parent.childNodes;
  233.     var index;
  234.     for (index = 0; index<nodelist.length; index++)
  235.     {
  236.       if (nodelist.item(index) == baseNode)
  237.         break;
  238.     }
  239.  
  240.     if (index >= nodelist.length) {
  241.       throw Components.results.NS_ERROR_FAILURE;
  242.     }
  243.  
  244.     // now make the selection contain all of the parent's children up to
  245.     // the selected one
  246.     domselection.collapse(parent,index);
  247.     domselection.extend(parent,index+1);
  248.   },
  249.  
  250.   getAnchorUrl: function(linkNode)
  251.   {
  252.     return linkNode.href || linkNode.name || null;
  253.   },
  254.  
  255.   getNodeString: function(node)
  256.   {
  257.     // use a range to get the text-equivalent of the node
  258.     var range = document.createRange();
  259.     range.selectNode(node);
  260.     return range.toString();
  261.   }
  262.   
  263. };
  264.  
  265.  
  266. function retrieveURLFromData (aData, flavour)
  267. {
  268.   switch (flavour) {
  269.   case "text/unicode":
  270.     // this might not be a url, but we'll return it anyway
  271.     return aData;
  272.   case "text/x-moz-url":
  273.     var data = aData.toString();
  274.     var separator = data.indexOf("\n");
  275.     if (separator != -1)
  276.       data = data.substr(0, separator);
  277.     return data;
  278.   case "application/x-moz-file":
  279.     return aData.URL;
  280.   }             
  281.   return null;                                                         
  282. }
  283.  
  284.  
  285.