Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
8.1 KiB

  1. // bplate.js
  2. /*-------------------------------------------------------------------------
  3. Purpose: Finds the next token, delimited by chDelim. Returns index or -1.
  4. */
  5. function _NextToken(sz, ichStart, chDelim)
  6. {
  7. var ich = ichStart;
  8. var cch = sz.length;
  9. while (ich < cch && sz.charAt(ich) == chDelim)
  10. {
  11. ich++;
  12. }
  13. if (ich == cch)
  14. ich = -1;
  15. return ich;
  16. }
  17. // BoilerPlate class.
  18. //
  19. // Applies the fields in a structured string record (provided to BoilerPlate_Parse)
  20. // to the contents of a document, according to custom attributes in the html.
  21. function BoilerPlate()
  22. {
  23. this._rgszFields = new Array();
  24. this._cfield = 0;
  25. }
  26. /*-------------------------------------------------------------------------
  27. Purpose: Take the string of arguments and parse it into separate fields.
  28. We'll use a sparse array to store this, indexed by field name.
  29. szArgs is in the following format:
  30. <fieldname1 "value1"><fieldname2 value2>...
  31. */
  32. function BoilerPlate_Parse(szArgs)
  33. {
  34. szArgs += " "; // Force szArgs to really be a string...
  35. // alert("Parse:" + szArgs);
  36. var ichTag = 0;
  37. while (true)
  38. {
  39. // Find tag
  40. ichTag = szArgs.indexOf("<", ichTag);
  41. if (-1 == ichTag)
  42. break;
  43. else
  44. {
  45. // We're lazy here -- if there's a tag, we expect it to be properly formed
  46. ichTag++;
  47. var ichNameEnd = szArgs.indexOf(" ", ichTag);
  48. var ichValueBegin = _NextToken(szArgs, ichNameEnd, " ");
  49. var ichValueEnd;
  50. if (szArgs.charAt(ichValueBegin) == '"')
  51. {
  52. ichValueBegin++;
  53. ichValueEnd = szArgs.indexOf('"', ichValueBegin);
  54. }
  55. else
  56. ichValueEnd = szArgs.indexOf(">", ichValueBegin);
  57. var szField = szArgs.substring(ichTag, ichNameEnd);
  58. var szValue = szArgs.substring(ichValueBegin, ichValueEnd);
  59. // alert('<' + szField + ':' + szValue + '>');
  60. this._rgszFields[szField.toLowerCase()] = szValue;
  61. this._cfield++;
  62. // Skip over the value so we don't accidentally mistake the value
  63. // for the next tag.
  64. ichTag = ichValueEnd;
  65. }
  66. }
  67. }
  68. /*-------------------------------------------------------------------------
  69. Purpose: Returns the value of the fieldname, or null if no fieldname exists
  70. */
  71. function BoilerPlate_Get(szFieldName)
  72. {
  73. var szValue = this._rgszFields[szFieldName.toLowerCase()];
  74. if ("" == szValue || "undefined" == typeof szValue)
  75. return null;
  76. return szValue;
  77. }
  78. /*-------------------------------------------------------------------------
  79. Purpose: Returns the number of field values that we have
  80. */
  81. function BoilerPlate_Length()
  82. {
  83. return this._cfield;
  84. }
  85. /*-------------------------------------------------------------------------
  86. Purpose: Finds and returns the immediate parent row, or null if not found
  87. */
  88. function _FindParentRow(elem)
  89. {
  90. // Walk up the chain of elements until we find the immediate parent row element
  91. var trLast = null;
  92. while (elem)
  93. {
  94. if ("TR" == elem.tagName.toUpperCase())
  95. return elem;
  96. elem = elem.parentElement;
  97. }
  98. return null;
  99. }
  100. /*-------------------------------------------------------------------------
  101. Purpose: Apply the fields in the object to the html. This function walks
  102. the html and looks for elements that have the following
  103. custom attributes. The value of <fieldname> should be inserted...
  104. _bpInnerText=<fieldname> - ...in the element's innertext property.
  105. _bpHref=<fieldname> - ...in the element's href property.
  106. _bpValue=<fieldname> - ...in the element's _bpVar property
  107. _bpNop=<fieldname> - ...nowhere. The element is hidden/displayed if
  108. value is valid.
  109. */
  110. function BoilerPlate_Apply()
  111. {
  112. var i;
  113. // Walk thru the document and look for our custom attributes
  114. for (i = document.all.length - 1; i >= 0; i--)
  115. {
  116. var elem = document.all.item(i);
  117. var szField;
  118. var bDeleteRow = false;
  119. var bIsElemMarked = false;
  120. var bHideElem = false;
  121. // Insert a field into the innertext property?
  122. if (null != elem._bpInnerText)
  123. {
  124. // Yes
  125. szField = this.Get(elem._bpInnerText);
  126. if (null == szField)
  127. {
  128. // Delete the row since there is no useful info to show
  129. bDeleteRow = true;
  130. bHideElem = true;
  131. szField = "n/a";
  132. }
  133. elem.innerText = szField;
  134. bIsElemMarked = true;
  135. }
  136. // Insert a field into the href property?
  137. if (null != elem._bpHref && "A" == elem.tagName)
  138. {
  139. szField = this.Get(elem._bpHref);
  140. bHideElem = false; // Reset for this case
  141. // alert("href [" + elem._bpHref + "] = " + szField);
  142. if (null != szField &&
  143. ("http:" == szField.substring(0, 5) ||
  144. "https:" == szField.substring(0, 6) ||
  145. "file:" == szField.substring(0, 5) ||
  146. "ftp:" == szField.substring(0, 4)))
  147. {
  148. // Yes
  149. elem.href = szField;
  150. // Was the friendly name unknown?
  151. if ("n/a" == elem.innerText)
  152. {
  153. // Yes; make the friendly name identical to the url
  154. elem.innerText = elem.href;
  155. }
  156. // Are the friendly name and href different?
  157. if (elem.href != elem.innerText)
  158. {
  159. // Yes; let's show the href URL in the tooltip.
  160. elem.title = elem.href;
  161. }
  162. bDeleteRow = false; // cancel any pending deletion
  163. }
  164. else
  165. {
  166. // No; change the color to match the regular text
  167. elem.style.color = document.fgColor;
  168. }
  169. bIsElemMarked = true;
  170. if ("n/a" == szField)
  171. bHideElem = true;
  172. }
  173. // Insert an arbitrary value?
  174. if (null != elem._bpValue)
  175. {
  176. // Yes
  177. elem._bpVar = this.Get(elem._bpValue);
  178. bIsElemMarked = true;
  179. }
  180. // Hide element?
  181. if (null != elem._bpNop && null == this.Get(elem._bpNop))
  182. {
  183. // Yes
  184. bHideElem = true;
  185. }
  186. // Is this element worthy of showing at all?
  187. if (bHideElem)
  188. {
  189. // No; hide it
  190. elem.style.display = 'none';
  191. }
  192. if (bIsElemMarked)
  193. {
  194. // We may think this row can be deleted, but there might be other fields
  195. // in this row that are valid, so let's mark this row and we'll make
  196. // a second pass after we're finished.
  197. var trElem = _FindParentRow(elem);
  198. if (trElem && false != trElem._bpDelete)
  199. {
  200. trElem._bpDelete = bDeleteRow;
  201. // alert("setting _bpDelete[" + trElem.rowIndex + "] = " + trElem._bpDelete);
  202. }
  203. }
  204. }
  205. // Make one final pass to delete any pending rows
  206. var rgrows = document.all.tags("TR");
  207. for (i = rgrows.length - 1; i >= 0; i--)
  208. {
  209. var trElem = rgrows[i];
  210. if (trElem && trElem._bpDelete)
  211. {
  212. var tbl = trElem.parentElement;
  213. tbl.deleteRow(trElem.rowIndex);
  214. }
  215. }
  216. }
  217. /*-------------------------------------------------------------------------
  218. Purpose: Initialize class
  219. */
  220. function InitBoilerPlateClass()
  221. {
  222. // Create and discard an initial Panel object for prototypes
  223. new BoilerPlate(null);
  224. // BoilerPlate Methods
  225. BoilerPlate.prototype.Parse = BoilerPlate_Parse;
  226. BoilerPlate.prototype.Get = BoilerPlate_Get;
  227. BoilerPlate.prototype.Length = BoilerPlate_Length;
  228. BoilerPlate.prototype.Apply = BoilerPlate_Apply;
  229. }