├── .repo-rt ├── css ├── basic.css └── enhanced.css ├── js ├── example.js └── jQuery.tree.js ├── images ├── icon-file.gif ├── icon-folder.gif └── icon-folder-open.gif ├── extra-example-jqtheming ├── images │ ├── icon-file.gif │ ├── icon-folder.gif │ └── icon-folder-open.gif ├── css │ └── enhanced.css ├── js │ └── example.js └── index.html ├── README.md ├── license.txt └── index.html /.repo-rt: -------------------------------------------------------------------------------- 1 | RETIRED 2 | -------------------------------------------------------------------------------- /css/basic.css: -------------------------------------------------------------------------------- 1 | body { font-family: "Segoe UI", Arial, sans-serif; } -------------------------------------------------------------------------------- /js/example.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | $('#files').tree({ 3 | expanded: 'li:first' 4 | }); 5 | }); -------------------------------------------------------------------------------- /images/icon-file.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/filamentgroup/jQuery-Tree-Control/HEAD/images/icon-file.gif -------------------------------------------------------------------------------- /images/icon-folder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/filamentgroup/jQuery-Tree-Control/HEAD/images/icon-folder.gif -------------------------------------------------------------------------------- /images/icon-folder-open.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/filamentgroup/jQuery-Tree-Control/HEAD/images/icon-folder-open.gif -------------------------------------------------------------------------------- /extra-example-jqtheming/images/icon-file.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/filamentgroup/jQuery-Tree-Control/HEAD/extra-example-jqtheming/images/icon-file.gif -------------------------------------------------------------------------------- /extra-example-jqtheming/images/icon-folder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/filamentgroup/jQuery-Tree-Control/HEAD/extra-example-jqtheming/images/icon-folder.gif -------------------------------------------------------------------------------- /extra-example-jqtheming/images/icon-folder-open.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/filamentgroup/jQuery-Tree-Control/HEAD/extra-example-jqtheming/images/icon-folder-open.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | :warning: This project is archived and the repository is no longer maintained. 2 | 3 | # Code Examples from the book [Designing with Progressive Enhancement](http://filamentgroup.com/dwpe) 4 | 5 | [![Filament Group](http://filamentgroup.com/images/fg-logo-positive-sm-crop.png) ](http://www.filamentgroup.com/) 6 | 7 | This repository includes open-sourced code developed and maintained by Filament Group, Inc. as part of the book "Designing With Progressive Enhancement" (Peachpit). 8 | 9 | All examples use the [jQuery JavaScript library](http://jquery.com). 10 | 11 | These code examples use the [EnhanceJS framework](https://github.com/filamentgroup/EnhanceJS) for applying progressive enhancement based on browser capabilities testing. 12 | -------------------------------------------------------------------------------- /extra-example-jqtheming/css/enhanced.css: -------------------------------------------------------------------------------- 1 | /*note: file modified to remove colors, backgrounds, borders for jQuery UI theming */ 2 | body { font-size:62.5%; margin:20px; } 3 | #files { margin:2em 0 5em; width:400px; } 4 | .tree { font-size:1.5em; } 5 | .tree,.tree ul,.tree li { list-style:none; margin:0; padding:0; zoom: 1; } 6 | .tree ul { margin-left:8px; } 7 | .tree li a { color:#555; padding:.1em 7px .1em 27px; display:block; text-decoration:none; border:1px dashed #fff; } 8 | .tree ul.tree-group-collapsed { display:none; } 9 | 10 | /*theme additions*/ 11 | #files { border: none; padding: 0; background: none; } 12 | .tree li a { position: relative; padding:.4em 7px .4em 20px; border:1px dashed transparent; } 13 | .ui-icon { position: absolute; left: 4px; top: 50%; margin-top: -8px; } -------------------------------------------------------------------------------- /css/enhanced.css: -------------------------------------------------------------------------------- 1 | body { font-size:62.5%; margin:20px; } 2 | #files { margin:2em 0 5em; width:400px; } 3 | .tree { font-size:1.5em; } 4 | .tree,.tree ul,.tree li { list-style:none; margin:0; padding:0; zoom: 1; } 5 | .tree ul { margin-left:8px; } 6 | .tree li a { color:#555; padding:.1em 7px .1em 27px; display:block; text-decoration:none; border:1px dashed #fff; background:url(../images/icon-file.gif) 5px 50% no-repeat; } 7 | .tree li a.tree-parent { background:url(../images/icon-folder-open.gif) 5px 50% no-repeat; } 8 | .tree li a.tree-parent-collapsed { background:url(../images/icon-folder.gif) 5px 50% no-repeat; } 9 | .tree li a:hover,.tree li a.tree-parent:hover,.tree li a:focus,.tree li a.tree-parent:focus,.tree li a.tree-item-active { color:#000; border:1px solid#eee; background-color:#fafafa; -moz-border-radius:4px; -webkit-border-radius:4px; border-radius:4px; } 10 | .tree li a:focus,.tree li a.tree-parent:focus,.tree li a.tree-item-active { border:1px solid #e2f3fb; background-color:#f2fafd; } 11 | .tree ul.tree-group-collapsed { display:none; } -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010 Filament Group, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /extra-example-jqtheming/js/example.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | $('#files').tree({ 3 | expanded: 'li:first' 4 | }); 5 | 6 | //Scripting to add UI icons and behavior 7 | $('.tree') 8 | .addClass('ui-widget ui-widget-content') 9 | .bind('expand',function(event){ 10 | var target = $(event.target) || $(this).find('a[tabindex=0]'); 11 | target.find('span:eq(0)').addClass('ui-icon-folder-open'); 12 | return false; 13 | }) 14 | .bind('collapse',function(event){ 15 | var target = $(event.target) || $(this).find('a[tabindex=0]'); 16 | target.find('span:eq(0)').removeClass('ui-icon-folder-open'); 17 | return false; 18 | }) 19 | .focus(function(event){ 20 | //deactivate previously active tree node, if one exists 21 | $(this).find('.ui-state-highlight').removeClass('ui-state-highlight'); 22 | //assign 0 tabindex to focused item 23 | $(event.target).addClass('ui-state-highlight'); 24 | }) 25 | .find('a') 26 | .addClass('ui-corner-all') 27 | .hover(function(){ 28 | $(this).addClass('ui-state-hover'); 29 | },function(){ 30 | $(this).removeClass('ui-state-hover'); 31 | }) 32 | .not('.tree-parent') 33 | .prepend('') 34 | .end() 35 | .filter('.tree-parent') 36 | .prepend('') 37 | .not('.tree-parent-collapsed') 38 | .find('span:eq(0)').addClass('ui-icon-folder-open'); 39 | 40 | 41 | //add theme switcher tool for demo purposes 42 | $('
').prependTo('body').themeswitcher(); 43 | }); -------------------------------------------------------------------------------- /extra-example-jqtheming/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple Tree Demo 6 | 7 | 8 | 23 | 24 | 25 | 26 | 27 |

DWPE tree widget with jQuery UI theming

28 | 29 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple Tree Demo 6 | 7 | 26 | 27 | 38 | 39 | 40 | 41 |
42 |

Filament Group

43 |
44 | 45 | 46 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /js/jQuery.tree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * -------------------------------------------------------------------- 3 | * jQuery tree plugin 4 | * Author: Scott Jehl, scott@filamentgroup.com 5 | * Copyright (c) 2009 Filament Group 6 | * licensed under MIT (filamentgroup.com/examples/mit-license.txt) 7 | * -------------------------------------------------------------------- 8 | */ 9 | $.fn.tree = function(settings){ 10 | var o = $.extend({ 11 | expanded: '' 12 | },settings); 13 | 14 | return $(this).each(function(){ 15 | if( !$(this).parents('.tree').length ){ 16 | //save reference to tree UL 17 | var tree = $(this); 18 | 19 | //add the role and default state attributes 20 | if( !$('body').is('[role]') ){ $('body').attr('role','application'); } 21 | //add role and class of tree 22 | tree.attr({'role': 'tree'}).addClass('tree'); 23 | //set first node's tabindex to 0 24 | tree.find('a:eq(0)').attr('tabindex','0'); 25 | //set all others to -1 26 | tree.find('a:gt(0)').attr('tabindex','-1'); 27 | //add group role and tree-group-collapsed class to all ul children 28 | tree.find('ul').attr('role','group').addClass('tree-group-collapsed'); 29 | //add treeitem role to all li children 30 | tree.find('li').attr('role','treeitem'); 31 | //find tree group parents 32 | tree.find('li:has(ul)') 33 | .attr('aria-expanded', 'false') 34 | .find('>a') 35 | .addClass('tree-parent tree-parent-collapsed'); 36 | 37 | //expanded at load 38 | tree 39 | .find(o.expanded) 40 | .attr('aria-expanded', 'true') 41 | .find('>a') 42 | .removeClass('tree-parent-collapsed') 43 | .next() 44 | .removeClass('tree-group-collapsed'); 45 | 46 | 47 | //bind the custom events 48 | tree 49 | //expand a tree node 50 | .bind('expand',function(event){ 51 | var target = $(event.target) || tree.find('a[tabindex=0]'); 52 | target.removeClass('tree-parent-collapsed'); 53 | target.next().hide().removeClass('tree-group-collapsed').slideDown(150, function(){ 54 | $(this).removeAttr('style'); 55 | target.parent().attr('aria-expanded', 'true'); 56 | }); 57 | }) 58 | //collapse a tree node 59 | .bind('collapse',function(event){ 60 | var target = $(event.target) || tree.find('a[tabindex=0]'); 61 | target.addClass('tree-parent-collapsed'); 62 | target.next().slideUp(150, function(){ 63 | target.parent().attr('aria-expanded', 'false'); 64 | $(this).addClass('tree-group-collapsed').removeAttr('style'); 65 | }); 66 | }) 67 | .bind('toggle',function(event){ 68 | var target = $(event.target) || tree.find('a[tabindex=0]'); 69 | //check if target parent LI is collapsed 70 | if( target.parent().is('[aria-expanded=false]') ){ 71 | //call expand function on the target 72 | target.trigger('expand'); 73 | } 74 | //otherwise, parent must be expanded 75 | else{ 76 | //collapse the target 77 | target.trigger('collapse'); 78 | } 79 | }) 80 | //shift focus down one item 81 | .bind('traverseDown',function(event){ 82 | var target = $(event.target) || tree.find('a[tabindex=0]'); 83 | var targetLi = target.parent(); 84 | if(targetLi.is('[aria-expanded=true]')){ 85 | target.next().find('a').eq(0).focus(); 86 | } 87 | else if(targetLi.next().length) { 88 | targetLi.next().find('a').eq(0).focus(); 89 | } 90 | else { 91 | targetLi.parents('li').next().find('a').eq(0).focus(); 92 | } 93 | }) 94 | //shift focus up one item 95 | .bind('traverseUp',function(event){ 96 | var target = $(event.target) || tree.find('a[tabindex=0]'); 97 | var targetLi = target.parent(); 98 | if(targetLi.prev().length){ 99 | if( targetLi.prev().is('[aria-expanded=true]') ){ 100 | targetLi.prev().find('li:visible:last a').eq(0).focus(); 101 | } 102 | else{ 103 | targetLi.prev().find('a').eq(0).focus(); 104 | } 105 | } 106 | else { 107 | targetLi.parents('li:eq(0)').find('a').eq(0).focus(); 108 | } 109 | }); 110 | 111 | 112 | //and now for the native events 113 | tree 114 | .focus(function(event){ 115 | //deactivate previously active tree node, if one exists 116 | tree.find('[tabindex=0]').attr('tabindex','-1').removeClass('tree-item-active'); 117 | //assign 0 tabindex to focused item 118 | $(event.target).attr('tabindex','0').addClass('tree-item-active'); 119 | }) 120 | .click(function(event){ 121 | //save reference to event target 122 | var target = $(event.target); 123 | //check if target is a tree node 124 | if( target.is('a.tree-parent') ){ 125 | target.trigger('toggle'); 126 | target.eq(0).focus(); 127 | //return click event false because it's a tree node (folder) 128 | return false; 129 | } 130 | }) 131 | .keydown(function(event){ 132 | var target = tree.find('a[tabindex=0]'); 133 | //check for arrow keys 134 | if(event.keyCode == 37 || event.keyCode == 38 || event.keyCode == 39 || event.keyCode == 40){ 135 | //if key is left arrow 136 | if(event.keyCode == 37){ 137 | //if list is expanded 138 | if(target.parent().is('[aria-expanded=true]')){ 139 | target.trigger('collapse'); 140 | } 141 | //try traversing to parent 142 | else { 143 | target.parents('li:eq(1)').find('a').eq(0).focus(); 144 | } 145 | } 146 | //if key is right arrow 147 | if(event.keyCode == 39){ 148 | //if list is collapsed 149 | if(target.parent().is('[aria-expanded=false]')){ 150 | target.trigger('expand'); 151 | } 152 | //try traversing to child 153 | else { 154 | target.parents('li:eq(0)').find('li a').eq(0).focus(); 155 | } 156 | } 157 | //if key is up arrow 158 | if(event.keyCode == 38){ 159 | target.trigger('traverseUp'); 160 | } 161 | //if key is down arrow 162 | if(event.keyCode == 40){ 163 | target.trigger('traverseDown'); 164 | } 165 | //return any of these keycodes false 166 | return false; 167 | } 168 | //check if enter or space was pressed on a tree node 169 | else if((event.keyCode == 13 || event.keyCode == 32) && target.is('a.tree-parent')){ 170 | target.trigger('toggle'); 171 | //return click event false because it's a tree node (folder) 172 | return false; 173 | } 174 | }); 175 | } 176 | }); 177 | }; --------------------------------------------------------------------------------