MDN may have intermittent access issues April 18 13:00 - April 19 01:00 UTC. See whistlepig.mozilla.org for all notifications.

mozilla
Your Search Results

    Sorting and filtering a custom tree view

    この記事はまだ日本語に翻訳されていません。MDN の翻訳はボランティアによって行われています。是非 MDN に登録し、私たちの力になって下さい。

    This is example code for sorting and filtering a custom tree view, that is, a tree whose values are loaded via JavaScript. This will not work for other types of trees, for example RDF-backed or ones created with DOM methods.

    For the sake of simplicity, strings are not localized and the data loaded is hard coded.

    Because of bug 340478, this code will only work from privileged script.

    sort.xul

    <?xml version="1.0"?>
    <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
    
    <!DOCTYPE window>
    
    <window
    	title="Sorting a custom tree view example"
    	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    	onload="init()">
    	
    	<script type="application/javascript" src="sort.js"/>
    
    	<hbox align="center" id="search-box">
    		<label accesskey="F" control="filter">Filter</label>
    		<textbox id="filter" oninput="inputFilter(event)" flex="1"/>
    		<button id="clearFilter" oncommand="clearFilter()" label="Clear" accesskey="C" disabled="true"/>
    	</hbox>
    
    	<tree id="tree" flex="1" persist="sortDirection sortResource" sortDirection="ascending" sortResource="description">
    		<treecols>
    			<treecol id="name" label="Name" flex="1" persist="width ordinal hidden" onclick="sort(this)" class="sortDirectionIndicator" sortDirection="ascending"/>
    			<splitter class="tree-splitter"/>
    			<treecol id="description" label="description" flex="1" persist="width ordinal hidden" onclick="sort(this)" class="sortDirectionIndicator"/>
    			<splitter class="tree-splitter"/>
    			<treecol id="weapon" label="Weapon" flex="1" persist="width ordinal hidden" onclick="sort(this)" class="sortDirectionIndicator"/>
    		</treecols>
    		<treechildren id="tree-children"/>
    	</tree>
    
    </window>
    

    sort.js

    var table = null;
    var data = null;
    var tree;
    var filterText = "";
    
    function init() {
    	tree = document.getElementById("tree");
    	loadTable();
    }
    
    //this function is called every time the tree is sorted, filtered, or reloaded
    function loadTable() {
    	//remember scroll position. this is useful if this is an editable table
    	//to prevent the user from losing the row they edited
    	var topVisibleRow = null;
    	if (table) {
    		topVisibleRow = getTopVisibleRow();
    	}
    	if (data == null) {
    		//put object loading code here. for our purposes, we'll hard code it.
    		data = [];
    		//the property names match the column ids in the xul. this way, we don't have to deal with
    		//mapping between the two
    		data.push({name: "Leonardo", description: "Leader", weapon: "Dual katanas"});
    		data.push({name: "Michaelangelo", description: "Party dude", weapon: "Nunchaku"});
    		data.push({name: "Donatello", description: "Does machines", weapon: "Bo"});
    		data.push({name: "Raphael", description: "Cool, but rude", weapon: "Sai"});
    		data.push({name: "Splinter", description: "Rat", weapon: "Walking stick"});
    		data.push({name: "Shredder", description: "Armored man", weapon: "Blades"});
    		data.push({name: "Casey Jones", description: "Goalie masked man", weapon: "Hockey stick"});
    		data.push({name: "April O'Neil", description: "Journalist", weapon: "None"});	
    	}
    	if (filterText == "") {
    		//show all of them
    		table = data;
    	} else {
    		//filter out the ones we want to display
    		table = [];
    		data.forEach(function(element) {
    			//we'll match on every property
    			for (var i in element) {
    				if (prepareForComparison(element[i]).indexOf(filterText) != -1) {
    					table.push(element);
    					break;
    				}
    			}
    		});
    	}
    	
    	sort();
    	//restore scroll position
    	if (topVisibleRow) {
    		setTopVisibleRow(topVisibleRow);
    	}
    }
    
    //generic custom tree view stuff
    function treeView(table) {
    	this.rowCount = table.length;
    	this.getCellText = function(row, col) {
    		return table[row][col.id];
    	};
    	this.getCellValue = function(row, col) {
    		return table[row][col.id];
    	};
    	this.setTree = function(treebox) {
    		this.treebox = treebox;
    	};
    	this.isEditable = function(row, col) {
    		return col.editable;
    	};
    	this.isContainer = function(row){ return false; };
    	this.isSeparator = function(row){ return false; };
    	this.isSorted = function(){ return false; };
    	this.getLevel = function(row){ return 0; };
    	this.getImageSrc = function(row,col){ return null; };
    	this.getRowProperties = function(row,props){};
    	this.getCellProperties = function(row,col,props){};
    	this.getColumnProperties = function(colid,col,props){};
    	this.cycleHeader = function(col, elem) {};
    }
    
    function sort(column) {
    	var columnName;
    	var order = tree.getAttribute("sortDirection") == "ascending" ? 1 : -1;
    	//if the column is passed and it's already sorted by that column, reverse sort
    	if (column) {
    		columnName = column.id;
    		if (tree.getAttribute("sortResource") == columnName) {
    			order *= -1;
    		}
    	} else {
    		columnName = tree.getAttribute("sortResource");
    	}
    
    	function columnSort(a, b) {
    		if (prepareForComparison(a[columnName]) > prepareForComparison(b[columnName])) return 1 * order;
    		if (prepareForComparison(a[columnName]) < prepareForComparison(b[columnName])) return -1 * order;
    		//tie breaker: name ascending is the second level sort
    		if (columnName != "name") {
    			if (prepareForComparison(a["name"]) > prepareForComparison(b["name"])) return 1;
    			if (prepareForComparison(a["name"]) < prepareForComparison(b["name"])) return -1;
    		}
    		return 0;
    	}
    	table.sort(columnSort);
    	//setting these will make the sort option persist
    	tree.setAttribute("sortDirection", order == 1 ? "ascending" : "descending");
    	tree.setAttribute("sortResource", columnName);
    	tree.view = new treeView(table);
    	//set the appropriate attributes to show to indicator
    	var cols = tree.getElementsByTagName("treecol");
    	for (var i = 0; i < cols.length; i++) {
    		cols[i].removeAttribute("sortDirection");
    	}
    	document.getElementById(columnName).setAttribute("sortDirection", order == 1 ? "ascending" : "descending");
    }
    
    //prepares an object for easy comparison against another. for strings, lowercases them
    function prepareForComparison(o) {
    	if (typeof o == "string") {
    		return o.toLowerCase();
    	}
    	return o;
    }
    
    function getTopVisibleRow() {
    	return tree.treeBoxObject.getFirstVisibleRow();
    }
    
    function setTopVisibleRow(topVisibleRow) {
    	return tree.treeBoxObject.scrollToRow(topVisibleRow);
    }
    
    
    function inputFilter(event) {
    	//do this now rather than doing it at every comparison
    	var value = prepareForComparison(event.target.value);
    	setFilter(value);
    	document.getElementById("clearFilter").disabled = value.length == 0;
    }
    
    function clearFilter() {
    	document.getElementById("clearFilter").disabled = true;
    	var filterElement = document.getElementById("filter");
    	filterElement.focus();
    	filterElement.value = "";
    	setFilter("");
    }
    
    function setFilter(text) {
    	filterText = text;
    	loadTable();
    }
    

    ドキュメントのタグと貢献者

    Contributors to this page: Np, futpib
    最終更新者: futpib,