| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- namespace("WM");
- WM.Treeview = (function()
- {
- var Margin = 10;
- var tree_template_html = " \
- <div class='Treeview'> \
- <div class='TreeviewItemChildren' style='width:90%;float:left'></div> \
- <div class='TreeviewScrollbarInset'> \
- <div class='TreeviewScrollbar'></div> \
- </div> \
- <div style='clear:both'></div> \
- </div>";
- var item_template_html = " \
- <div class='TreeViewItem basicfont notextsel'> \
- <img src='' class='TreeviewItemImage'> \
- <div class='TreeviewItemText'></div> \
- <div style='clear:both'></div> \
- <div class='TreeviewItemChildren'></div> \
- <div style='clear:both'></div> \
- </div>";
- // TODO: Remove parent_node (required for stuff that doesn't use the WM yet)
- function Treeview(x, y, width, height, parent_node)
- {
- // Cache initialisation options
- this.ParentNode = parent_node;
- this.Position = [ x, y ];
- this.Size = [ width, height ];
- this.Node = null;
- this.ScrollbarNode = null;
- this.SelectedItem = null;
- this.ContentsNode = null;
- // Setup options
- this.HighlightOnHover = false;
- this.EnableScrollbar = true;
- this.HorizontalLayoutDepth = 1;
- // Generate an empty tree
- this.Clear();
- }
- Treeview.prototype.SetHighlightOnHover = function(highlight)
- {
- this.HighlightOnHover = highlight;
- }
- Treeview.prototype.SetEnableScrollbar = function(enable)
- {
- this.EnableScrollbar = enable;
- }
- Treeview.prototype.SetHorizontalLayoutDepth = function(depth)
- {
- this.HorizontalLayoutDepth = depth;
- }
- Treeview.prototype.SetNodeSelectedHandler = function(handler)
- {
- this.NodeSelectedHandler = handler;
- }
- Treeview.prototype.Clear = function()
- {
- this.RootItem = new WM.TreeviewItem(this, null, null, null, null);
- this.GenerateHTML();
- }
- Treeview.prototype.Root = function()
- {
- return this.RootItem;
- }
- Treeview.prototype.ClearSelection = function()
- {
- if (this.SelectedItem != null)
- {
- DOM.Node.RemoveClass(this.SelectedItem.Node, "TreeviewItemSelected");
- this.SelectedItem = null;
- }
- }
- Treeview.prototype.SelectItem = function(item, mouse_pos)
- {
- // Notify the select handler
- if (this.NodeSelectedHandler)
- this.NodeSelectedHandler(item.Node, this.SelectedItem, item, mouse_pos);
- // Remove highlight from the old selection
- this.ClearSelection();
- // Swap in new selection and apply highlight
- this.SelectedItem = item;
- DOM.Node.AddClass(this.SelectedItem.Node, "TreeviewItemSelected");
- }
- Treeview.prototype.GenerateHTML = function()
- {
- // Clone the template and locate important nodes
- var old_node = this.Node;
- this.Node = DOM.Node.CreateHTML(tree_template_html);
- this.ChildrenNode = DOM.Node.FindWithClass(this.Node, "TreeviewItemChildren");
- this.ScrollbarNode = DOM.Node.FindWithClass(this.Node, "TreeviewScrollbar");
- DOM.Node.SetPosition(this.Node, this.Position);
- DOM.Node.SetSize(this.Node, this.Size);
- // Generate the contents of the treeview
- GenerateTree(this, this.ChildrenNode, this.RootItem.Children, 0);
- // Cross-browser (?) means of adding a mouse wheel handler
- var mouse_wheel_event = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
- DOM.Event.AddHandler(this.Node, mouse_wheel_event, Bind(OnMouseScroll, this));
- DOM.Event.AddHandler(this.Node, "dblclick", Bind(OnMouseDoubleClick, this));
- DOM.Event.AddHandler(this.Node, "mousedown", Bind(OnMouseDown, this));
- DOM.Event.AddHandler(this.Node, "mouseup", OnMouseUp);
- // Swap in the newly generated control node if it's already been attached to a parent
- if (old_node && old_node.parentNode)
- {
- old_node.parentNode.removeChild(old_node);
- this.ParentNode.appendChild(this.Node);
- }
- if (this.EnableScrollbar)
- {
- this.UpdateScrollbar();
- DOM.Event.AddHandler(this.ScrollbarNode, "mousedown", Bind(OnMouseDown_Scrollbar, this));
- DOM.Event.AddHandler(this.ScrollbarNode, "mouseup", Bind(OnMouseUp_Scrollbar, this));
- DOM.Event.AddHandler(this.ScrollbarNode, "mouseout", Bind(OnMouseUp_Scrollbar, this));
- DOM.Event.AddHandler(this.ScrollbarNode, "mousemove", Bind(OnMouseMove_Scrollbar, this));
- }
- else
- {
- DOM.Node.Hide(DOM.Node.FindWithClass(this.Node, "TreeviewScrollbarInset"));
- }
- }
-
- Treeview.prototype.UpdateScrollbar = function()
- {
- if (!this.EnableScrollbar)
- return;
- var scrollbar_scale = Math.min((this.Node.offsetHeight - Margin * 2) / this.ChildrenNode.offsetHeight, 1);
- this.ScrollbarNode.style.height = parseInt(scrollbar_scale * 100) + "%";
- // Shift the scrollbar container along with the parent window
- this.ScrollbarNode.parentNode.style.top = this.Node.scrollTop;
- var scroll_fraction = this.Node.scrollTop / (this.Node.scrollHeight - this.Node.offsetHeight);
- var max_height = this.Node.offsetHeight - Margin;
- var max_scrollbar_offset = max_height - this.ScrollbarNode.offsetHeight;
- var scrollbar_offset = scroll_fraction * max_scrollbar_offset;
- this.ScrollbarNode.style.top = scrollbar_offset;
- }
- function GenerateTree(self, parent_node, items, depth)
- {
- if (items.length == 0)
- return null;
- for (var i in items)
- {
- var item = items[i];
- // Create the node for this item and locate important nodes
- var node = DOM.Node.CreateHTML(item_template_html);
- var img = DOM.Node.FindWithClass(node, "TreeviewItemImage");
- var text = DOM.Node.FindWithClass(node, "TreeviewItemText");
- var children = DOM.Node.FindWithClass(node, "TreeviewItemChildren");
- // Attach the item to the node
- node.TreeviewItem = item;
- item.Node = node;
- // Add the class which highlights selection on hover
- if (self.HighlightOnHover)
- DOM.Node.AddClass(node, "TreeviewItemHover");
- // Instruct the children to wrap around
- if (depth >= self.HorizontalLayoutDepth)
- node.style.cssFloat = "left";
- if (item.OpenImage == null || item.CloseImage == null)
- {
- // If there no images, remove the image node
- node.removeChild(img);
- }
- else
- {
- // Set the image source to open
- img.src = item.OpenImage.src;
- img.style.width = item.OpenImage.width;
- img.style.height = item.OpenImage.height;
- item.ImageNode = img;
- }
- // Setup the text to display
- text.innerHTML = item.Label;
- // Add the div to the parent and recurse into children
- parent_node.appendChild(node);
- GenerateTree(self, children, item.Children, depth + 1);
- item.ChildrenNode = children;
- }
- // Clear the wrap-around
- if (depth >= self.HorizontalLayoutDepth)
- DOM.Node.AppendClearFloat(parent_node.parentNode);
- }
- function OnMouseScroll(self, evt)
- {
- // Get mouse wheel movement
- var delta = evt.detail ? evt.detail * -1 : evt.wheelDelta;
- delta *= 8;
- // Scroll the main window with wheel movement and clamp
- self.Node.scrollTop -= delta;
- self.Node.scrollTop = Math.min(self.Node.scrollTop, (self.ChildrenNode.offsetHeight - self.Node.offsetHeight) + Margin * 2);
- self.UpdateScrollbar();
- }
- function OnMouseDoubleClick(self, evt)
- {
- DOM.Event.StopDefaultAction(evt);
- // Get the tree view item being clicked, if any
- var node = DOM.Event.GetNode(evt);
- var tvitem = GetTreeviewItemFromNode(self, node);
- if (tvitem == null)
- return;
- if (tvitem.Children.length)
- tvitem.Toggle();
- }
- function OnMouseDown(self, evt)
- {
- DOM.Event.StopDefaultAction(evt);
- // Get the tree view item being clicked, if any
- var node = DOM.Event.GetNode(evt);
- var tvitem = GetTreeviewItemFromNode(self, node);
- if (tvitem == null)
- return;
- // If clicking on the image, expand any children
- if (node.tagName == "IMG" && tvitem.Children.length)
- {
- tvitem.Toggle();
- }
- else
- {
- var mouse_pos = DOM.Event.GetMousePosition(evt);
- self.SelectItem(tvitem, mouse_pos);
- }
- }
- function OnMouseUp(evt)
- {
- // Event handler used merely to stop events bubbling up to containers
- DOM.Event.StopPropagation(evt);
- }
- function OnMouseDown_Scrollbar(self, evt)
- {
- self.ScrollbarHeld = true;
- // Cache the mouse height relative to the scrollbar
- self.LastY = evt.clientY;
- self.ScrollY = self.Node.scrollTop;
- DOM.Node.AddClass(self.ScrollbarNode, "TreeviewScrollbarHeld");
- DOM.Event.StopDefaultAction(evt);
- }
- function OnMouseUp_Scrollbar(self, evt)
- {
- self.ScrollbarHeld = false;
- DOM.Node.RemoveClass(self.ScrollbarNode, "TreeviewScrollbarHeld");
- }
- function OnMouseMove_Scrollbar(self, evt)
- {
- if (self.ScrollbarHeld)
- {
- var delta_y = evt.clientY - self.LastY;
- self.LastY = evt.clientY;
- var max_height = self.Node.offsetHeight - Margin;
- var max_scrollbar_offset = max_height - self.ScrollbarNode.offsetHeight;
- var max_contents_scroll = self.Node.scrollHeight - self.Node.offsetHeight;
- var scale = max_contents_scroll / max_scrollbar_offset;
- // Increment the local float variable and assign, as scrollTop is of type int
- self.ScrollY += delta_y * scale;
- self.Node.scrollTop = self.ScrollY;
- self.Node.scrollTop = Math.min(self.Node.scrollTop, (self.ChildrenNode.offsetHeight - self.Node.offsetHeight) + Margin * 2);
- self.UpdateScrollbar();
- }
- }
- function GetTreeviewItemFromNode(self, node)
- {
- // Walk up toward the tree view node looking for this first item
- while (node && node != self.Node)
- {
- if ("TreeviewItem" in node)
- return node.TreeviewItem;
- node = node.parentNode;
- }
- return null;
- }
- return Treeview;
- })();
|