ComboBox.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. namespace("WM");
  2. WM.ComboBoxPopup = (function()
  3. {
  4. var body_template_html = "<div class='ComboBoxPopup'></div>";
  5. var item_template_html = " \
  6. <div class='ComboBoxPopupItem notextsel'> \
  7. <div class='ComboBoxPopupItemText'></div> \
  8. <div class='ComboBoxPopupItemIcon'><img src='BrowserLibImages/tick.gif'></div> \
  9. <div style='clear:both'></div> \
  10. </div>";
  11. function ComboBoxPopup(combo_box)
  12. {
  13. this.ComboBox = combo_box;
  14. this.ParentNode = combo_box.Node;
  15. this.ValueNodes = [ ];
  16. // Create the template node
  17. this.Node = DOM.Node.CreateHTML(body_template_html);
  18. DOM.Event.AddHandler(this.Node, "mousedown", Bind(SelectItem, this));
  19. this.CancelDelegate = Bind(this, "Cancel");
  20. }
  21. ComboBoxPopup.prototype.SetValues = function(values)
  22. {
  23. // Clear existing values
  24. this.Node.innerHTML = "";
  25. // Generate HTML nodes for each value
  26. this.ValueNodes = [ ];
  27. for (var i in values)
  28. {
  29. var item_node = DOM.Node.CreateHTML(item_template_html);
  30. var text_node = DOM.Node.FindWithClass(item_node, "ComboBoxPopupItemText");
  31. item_node.Value = values[i];
  32. text_node.innerHTML = values[i];
  33. this.Node.appendChild(item_node);
  34. this.ValueNodes.push(item_node);
  35. }
  36. }
  37. ComboBoxPopup.prototype.Show = function(selection_index)
  38. {
  39. // Initially match the position of the parent node
  40. var pos = DOM.Node.GetPosition(this.ParentNode);
  41. DOM.Node.SetPosition(this.Node, pos);
  42. // Take the width/z-index from the parent node
  43. this.Node.style.width = this.ParentNode.offsetWidth;
  44. this.Node.style.zIndex = this.ParentNode.style.zIndex + 1;
  45. // Setup event handlers
  46. DOM.Event.AddHandler(document.body, "mousedown", this.CancelDelegate);
  47. // Show the popup so that the HTML layout engine kicks in before
  48. // the layout info is used below
  49. this.ParentNode.appendChild(this.Node);
  50. // Show/hide the tick image based on which node is selected
  51. for (var i in this.ValueNodes)
  52. {
  53. var node = this.ValueNodes[i];
  54. var icon_node = DOM.Node.FindWithClass(node, "ComboBoxPopupItemIcon");
  55. if (i == selection_index)
  56. {
  57. icon_node.style.display = "block";
  58. // Also, shift the popup up so that the mouse is over the selected item and is highlighted
  59. var item_pos = DOM.Node.GetPosition(this.ValueNodes[selection_index]);
  60. var diff_pos = [ item_pos[0] - pos[0], item_pos[1] - pos[1] ];
  61. pos = [ pos[0] - diff_pos[0], pos[1] - diff_pos[1] ];
  62. }
  63. else
  64. {
  65. icon_node.style.display = "none";
  66. }
  67. }
  68. DOM.Node.SetPosition(this.Node, pos);
  69. }
  70. ComboBoxPopup.prototype.Hide = function()
  71. {
  72. DOM.Event.RemoveHandler(document.body, "mousedown", this.CancelDelegate);
  73. this.ParentNode.removeChild(this.Node);
  74. }
  75. function SelectItem(self, evt)
  76. {
  77. // Search for which item node is being clicked on
  78. var node = DOM.Event.GetNode(evt);
  79. for (var i in self.ValueNodes)
  80. {
  81. var value_node = self.ValueNodes[i];
  82. if (DOM.Node.Contains(node, value_node))
  83. {
  84. // Set the value on the combo box
  85. self.ComboBox.SetValue(value_node.Value);
  86. self.Hide();
  87. break;
  88. }
  89. }
  90. }
  91. function Cancel(self, evt)
  92. {
  93. // Don't cancel if the mouse up is anywhere on the popup or combo box
  94. var node = DOM.Event.GetNode(evt);
  95. if (!DOM.Node.Contains(node, self.Node) &&
  96. !DOM.Node.Contains(node, self.ParentNode))
  97. {
  98. self.Hide();
  99. }
  100. DOM.Event.StopAll(evt);
  101. }
  102. return ComboBoxPopup;
  103. })();
  104. WM.ComboBox = (function()
  105. {
  106. var template_html = " \
  107. <div class='ComboBox'> \
  108. <div class='ComboBoxText notextsel'></div> \
  109. <div class='ComboBoxIcon'><img src='BrowserLibImages/up_down.gif'></div> \
  110. <div style='clear:both'></div> \
  111. </div>";
  112. function ComboBox()
  113. {
  114. this.OnChange = null;
  115. // Create the template node and locate key nodes
  116. this.Node = DOM.Node.CreateHTML(template_html);
  117. this.TextNode = DOM.Node.FindWithClass(this.Node, "ComboBoxText");
  118. // Create a reusable popup
  119. this.Popup = new WM.ComboBoxPopup(this);
  120. // Set an empty set of values
  121. this.SetValues([]);
  122. this.SetValue("&lt;empty&gt;");
  123. // Create the mouse press event handlers
  124. DOM.Event.AddHandler(this.Node, "mousedown", Bind(OnMouseDown, this));
  125. this.OnMouseOutDelegate = Bind(OnMouseUp, this, false);
  126. this.OnMouseUpDelegate = Bind(OnMouseUp, this, true);
  127. }
  128. ComboBox.prototype.SetOnChange = function(on_change)
  129. {
  130. this.OnChange = on_change;
  131. }
  132. ComboBox.prototype.SetValues = function(values)
  133. {
  134. this.Values = values;
  135. this.Popup.SetValues(values);
  136. }
  137. ComboBox.prototype.SetValue = function(value)
  138. {
  139. // Set the value and its HTML rep
  140. var old_value = this.Value;
  141. this.Value = value;
  142. this.TextNode.innerHTML = value;
  143. // Call change handler
  144. if (this.OnChange)
  145. this.OnChange(value, old_value);
  146. }
  147. ComboBox.prototype.GetValue = function()
  148. {
  149. return this.Value;
  150. }
  151. function OnMouseDown(self, evt)
  152. {
  153. // If this check isn't made, the click will trigger from the popup, too
  154. var node = DOM.Event.GetNode(evt);
  155. if (DOM.Node.Contains(node, self.Node))
  156. {
  157. // Add the depression class and activate release handlers
  158. DOM.Node.AddClass(self.Node, "ComboBoxPressed");
  159. DOM.Event.AddHandler(self.Node, "mouseout", self.OnMouseOutDelegate);
  160. DOM.Event.AddHandler(self.Node, "mouseup", self.OnMouseUpDelegate);
  161. DOM.Event.StopAll(evt);
  162. }
  163. }
  164. function OnMouseUp(self, confirm, evt)
  165. {
  166. // Remove depression class and remove release handlers
  167. DOM.Node.RemoveClass(self.Node, "ComboBoxPressed");
  168. DOM.Event.RemoveHandler(self.Node, "mouseout", self.OnMouseOutDelegate);
  169. DOM.Event.RemoveHandler(self.Node, "mouseup", self.OnMouseUpDelegate);
  170. // If this is a confirmed press and there are some values in the list, show the popup
  171. if (confirm && self.Values.length > 0)
  172. {
  173. var selection_index = self.Values.indexOf(self.Value);
  174. self.Popup.Show(selection_index);
  175. }
  176. DOM.Event.StopAll(evt);
  177. }
  178. return ComboBox;
  179. })();