home *** CD-ROM | disk | FTP | other *** search
/ Computer Active Guide 2009 July / CAG7.ISO / Internetas / SafariSetup.exe / AppleApplicationSupport.msi / WebKit.resources_inspector_ObjectPropertiesSection.js < prev    next >
Encoding:
JavaScript  |  2010-06-03  |  9.4 KB  |  268 lines

  1. /*
  2.  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
  3.  * Copyright (C) 2009 Joseph Pecoraro
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  18.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  21.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  22.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27. WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
  28. {
  29.     this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
  30.     this.object = object;
  31.     this.ignoreHasOwnProperty = ignoreHasOwnProperty;
  32.     this.extraProperties = extraProperties;
  33.     this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement;
  34.     this.editable = true;
  35.  
  36.     WebInspector.PropertiesSection.call(this, title, subtitle);
  37. }
  38.  
  39. WebInspector.ObjectPropertiesSection.prototype = {
  40.     onpopulate: function()
  41.     {
  42.         this.update();
  43.     },
  44.  
  45.     update: function()
  46.     {
  47.         var self = this;
  48.         var callback = function(properties) {
  49.             if (!properties)
  50.                 return;
  51.             self.updateProperties(properties);
  52.         };
  53.         InjectedScriptAccess.get(this.object.injectedScriptId).getProperties(this.object, this.ignoreHasOwnProperty, true, callback);
  54.     },
  55.  
  56.     updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer)
  57.     {
  58.         if (!rootTreeElementConstructor)
  59.             rootTreeElementConstructor = this.treeElementConstructor;
  60.             
  61.         if (!rootPropertyComparer)
  62.             rootPropertyComparer = WebInspector.ObjectPropertiesSection.CompareProperties;
  63.             
  64.         if (this.extraProperties)
  65.             for (var i = 0; i < this.extraProperties.length; ++i)
  66.                 properties.push(this.extraProperties[i]);
  67.                 
  68.         properties.sort(rootPropertyComparer);
  69.  
  70.         this.propertiesTreeOutline.removeChildren();
  71.  
  72.         for (var i = 0; i < properties.length; ++i)
  73.             this.propertiesTreeOutline.appendChild(new rootTreeElementConstructor(properties[i]));
  74.  
  75.         if (!this.propertiesTreeOutline.children.length) {
  76.             var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
  77.             var infoElement = new TreeElement(title, null, false);
  78.             this.propertiesTreeOutline.appendChild(infoElement);
  79.         }
  80.         this.propertiesForTest = properties;
  81.     }
  82. }
  83.  
  84. WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
  85.  
  86. WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB) 
  87. {
  88.     var a = propertyA.name;
  89.     var b = propertyB.name;
  90.     if (a === "__proto__")
  91.         return 1;
  92.     if (b === "__proto__")
  93.         return -1;
  94.  
  95.     // if used elsewhere make sure to
  96.     //  - convert a and b to strings (not needed here, properties are all strings)
  97.     //  - check if a == b (not needed here, no two properties can be the same)
  98.  
  99.     var diff = 0;
  100.     var chunk = /^\d+|^\D+/;
  101.     var chunka, chunkb, anum, bnum;
  102.     while (diff === 0) {
  103.         if (!a && b)
  104.             return -1;
  105.         if (!b && a)
  106.             return 1;
  107.         chunka = a.match(chunk)[0];
  108.         chunkb = b.match(chunk)[0];
  109.         anum = !isNaN(chunka);
  110.         bnum = !isNaN(chunkb);
  111.         if (anum && !bnum)
  112.             return -1;
  113.         if (bnum && !anum)
  114.             return 1;
  115.         if (anum && bnum) {
  116.             diff = chunka - chunkb;
  117.             if (diff === 0 && chunka.length !== chunkb.length) {
  118.                 if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case)
  119.                     return chunka.length - chunkb.length;
  120.                 else
  121.                     return chunkb.length - chunka.length;
  122.             }
  123.         } else if (chunka !== chunkb)
  124.             return (chunka < chunkb) ? -1 : 1;
  125.         a = a.substring(chunka.length);
  126.         b = b.substring(chunkb.length);
  127.     }
  128.     return diff;
  129. }
  130.  
  131. WebInspector.ObjectPropertyTreeElement = function(property)
  132. {
  133.     this.property = property;
  134.  
  135.     // Pass an empty title, the title gets made later in onattach.
  136.     TreeElement.call(this, "", null, false);
  137. }
  138.  
  139. WebInspector.ObjectPropertyTreeElement.prototype = {
  140.     onpopulate: function()
  141.     {
  142.         if (this.children.length && !this.shouldRefreshChildren)
  143.             return;
  144.  
  145.         var callback = function(properties) {
  146.             this.removeChildren();
  147.             if (!properties)
  148.                 return;
  149.  
  150.             properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
  151.             for (var i = 0; i < properties.length; ++i) {
  152.                 this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i]));
  153.             }
  154.         };
  155.         InjectedScriptAccess.get(this.property.value.injectedScriptId).getProperties(this.property.value, false, true, callback.bind(this));
  156.     },
  157.  
  158.     ondblclick: function(event)
  159.     {
  160.         this.startEditing();
  161.     },
  162.  
  163.     onattach: function()
  164.     {
  165.         this.update();
  166.     },
  167.  
  168.     update: function()
  169.     {
  170.         this.nameElement = document.createElement("span");
  171.         this.nameElement.className = "name";
  172.         this.nameElement.textContent = this.property.name;
  173.  
  174.         var separatorElement = document.createElement("span");
  175.         separatorElement.className = "separator";
  176.         separatorElement.textContent = ": ";
  177.         
  178.         this.valueElement = document.createElement("span");
  179.         this.valueElement.className = "value";
  180.         this.valueElement.textContent = this.property.value.description;
  181.         if (typeof this.property.value.propertyLength !== "undefined")
  182.             this.valueElement.textContent += " (" + this.property.value.propertyLength + ")";
  183.         if (this.property.isGetter)
  184.             this.valueElement.addStyleClass("dimmed");
  185.         if (this.property.isError)
  186.             this.valueElement.addStyleClass("error");
  187.  
  188.         this.listItemElement.removeChildren();
  189.  
  190.         this.listItemElement.appendChild(this.nameElement);
  191.         this.listItemElement.appendChild(separatorElement);
  192.         this.listItemElement.appendChild(this.valueElement);
  193.         this.hasChildren = this.property.value.hasChildren;
  194.     },
  195.  
  196.     updateSiblings: function()
  197.     {
  198.         if (this.parent.root)
  199.             this.treeOutline.section.update();
  200.         else
  201.             this.parent.shouldRefreshChildren = true;
  202.     },
  203.  
  204.     startEditing: function()
  205.     {
  206.         if (WebInspector.isBeingEdited(this.valueElement) || !this.treeOutline.section.editable)
  207.             return;
  208.  
  209.         var context = { expanded: this.expanded };
  210.  
  211.         // Lie about our children to prevent expanding on double click and to collapse subproperties.
  212.         this.hasChildren = false;
  213.  
  214.         this.listItemElement.addStyleClass("editing-sub-part");
  215.  
  216.         WebInspector.startEditing(this.valueElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
  217.     },
  218.  
  219.     editingEnded: function(context)
  220.     {
  221.         this.listItemElement.scrollLeft = 0;
  222.         this.listItemElement.removeStyleClass("editing-sub-part");
  223.         if (context.expanded)
  224.             this.expand();
  225.     },
  226.  
  227.     editingCancelled: function(element, context)
  228.     {
  229.         this.update();
  230.         this.editingEnded(context);
  231.     },
  232.  
  233.     editingCommitted: function(element, userInput, previousContent, context)
  234.     {
  235.         if (userInput === previousContent)
  236.             return this.editingCancelled(element, context); // nothing changed, so cancel
  237.  
  238.         this.applyExpression(userInput, true);
  239.  
  240.         this.editingEnded(context);
  241.     },
  242.  
  243.     applyExpression: function(expression, updateInterface)
  244.     {
  245.         expression = expression.trim();
  246.         var expressionLength = expression.length;
  247.         var self = this;
  248.         var callback = function(success) {
  249.             if (!updateInterface)
  250.                 return;
  251.  
  252.             if (!success)
  253.                 self.update();
  254.  
  255.             if (!expressionLength) {
  256.                 // The property was deleted, so remove this tree element.
  257.                 self.parent.removeChild(this);
  258.             } else {
  259.                 // Call updateSiblings since their value might be based on the value that just changed.
  260.                 self.updateSiblings();
  261.             }
  262.         };
  263.         InjectedScriptAccess.get(this.property.parentObjectProxy.injectedScriptId).setPropertyValue(this.property.parentObjectProxy, this.property.name, expression.trim(), callback);
  264.     }
  265. }
  266.  
  267. WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
  268.