├── .gitignore ├── LICENSE ├── README.md ├── demo └── basic.html └── src ├── jquery.ts3viewer.js ├── jquery.ts3viewer.min.js └── themes ├── classic ├── loader.gif ├── spacer_dashdotdotline.gif ├── spacer_dashdotline.gif ├── spacer_dashline.gif ├── spacer_dotline.gif ├── spacer_solidline.gif ├── tree.css └── tree.png ├── colored ├── loader.gif ├── spacer_dashdotdotline.gif ├── spacer_dashdotline.gif ├── spacer_dashline.gif ├── spacer_dotline.gif ├── spacer_solidline.gif ├── tree.css ├── tree.png ├── tree@2x.png └── tree@3x.png └── mono ├── loader.gif ├── spacer_dashdotdotline.gif ├── spacer_dashdotline.gif ├── spacer_dashline.gif ├── spacer_dotline.gif ├── spacer_solidline.gif ├── tree.css ├── tree.png ├── tree@2x.png └── tree@3x.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Planet TeamSpeak 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 all 13 | 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 THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jQuery [REST API TSViewer](https://www.planetteamspeak.com/rest-api/) 2 | 3 | Current Version: **1.0.0** 4 | 5 | This simple jQuery plugin provides a drop-in dynamic TeamSpeak 3 Server tree - aka TSViewer - that requires **no server-side scripting language** on your end. The [Simple REST API](https://www.planetteamspeak.com/rest-api/) hosted by [Planet TeamSpeak](https://www.planetteamspeak.com/) does all the queries, sorts channels and clients and even downloads all the remote icons for you. In addition, the result is cached, so your TS3 Server is not getting hammered with requests. You can also create your own API endpoints using the [TS3 PHP Framework](https://github.com/planetteamspeak/ts3phpframework/). 6 | 7 | All the required JavaScript and CSS files can be used directly from the [Planet TeamSpeak](https://www.planetteamspeak.com/) CDN: 8 | 9 | 10 | 11 | 12 | We provide three different themes to match the look and feel of the official TeamSpeak 3 Client: 13 | 14 | * `classic` - classic icons from TS3 Client releases up to version 3.0.15 15 | * `colored` - modern colored icons introduced with version 3.0.16 in 2014 (HiDPI support) 16 | * `mono` - modern monochrome icons introduced with version 3.0.16 in 2014 (HiDPI support) 17 | 18 | ## Installation / Configuration 19 | 20 | ### Options 21 | 22 | Upon initialization, the plugin takes the following options: 23 | 24 | | Key | Default | Optional | Description | 25 | | -----------|:-------:|---------:|--------------------------------------------| 26 | | host | `null` | No | IP address of the TeamSpeak 3 Server | 27 | | port | `null` | No | UDP port number of the TeamSpeak 3 Server | 28 | | iconUrl | ... | Yes | API endpoint URL for remote icon downloads | 29 | | dataUrl | ... | Yes | API endpoint URL for JSON data results | 30 | | serverTip | `null` | Yes | Pattern for server tooltips | 31 | | channelTip | `null` | Yes | Pattern for channel tooltips | 32 | | clientTip | `null` | Yes | Pattern for client tooltips | 33 | 34 | **_Note:_** While `host` and `port` are mandatory options, they might be obsolete when you're using custom API endpoints. 35 | 36 | Both API endpoint URLs support variables such as `$host`, `$port` and `$icon` for individual customization. For example, if all of your remote icon files are uploaded to a webserver in PNG format, you can use an `iconURL` like this: 37 | 38 | https://www.domain.tld/icons/$icon.png 39 | 40 | The `$icon` variable will be replaced by the crc32 polynomial of the icon file. This is an unsigned integer equal to the icon ID that is used as a value for the `i_icon_id` permission on a TeamSpeak 3 Server. 41 | 42 | ### Quick Start 43 | 44 | To add the TSViewer to your site, simply include jQuery and the plugin on a page. Then select a container element and call the `tsviewer` method with the IP address and port number of your TeamSpeak 3 Server. 45 | 46 | ```html 47 |
48 | 49 | 50 | 51 | 52 | 58 | ``` 59 | 60 | ### Customization 61 | 62 | The tooltip patterns can be customized with several property variables taken from the JSON result. For example, this is what a server/client tooltip pattern could look like: 63 | 64 | Version $version on $platform 65 | 66 | In addition, you can specify callbacks for advanced code enhancements such as context menus or drag & drop. 67 | 68 | ```html 69 |
70 | 71 | 72 | 73 | 74 | 108 | ``` 109 | 110 | ## Requirements 111 | 112 | ### Using the Simple REST API 113 | 114 | Using the default settings, the plugin with utilize the [Simple REST API](https://www.planetteamspeak.com/rest-api/) endpoints at `api.planetteamspeak.com` to gather the necessary data from a TeamSpeak 3 Server. Therefore, the server must meet the following requirements: 115 | 116 | * The TS3 Server must report to the official server list on `weblist.teamspeak.com` and appear in the [Global Server List](https://www.planetteamspeak.com/serverlist/) on the [Planet TeamSpeak](https://www.planetteamspeak.com/) website. 117 | * The owner of the TS3 Server must register (claim) it on the on the [Planet TeamSpeak](https://www.planetteamspeak.com/) website and enable ServerQuery connectivity in the [Control Panel](https://www.planetteamspeak.com/control/servers/). 118 | 119 | ### Using the TS3 PHP Framework 120 | 121 | If you don't want to use the [Simple REST API](https://www.planetteamspeak.com/rest-api/), you can also create your own API endpoints using the [TS3 PHP Framework](https://github.com/planetteamspeak/ts3phpframework/). 122 | 123 | #### The `servernodes` API endpoint (`dataUrl`) 124 | 125 | In the he following example, we connect to the ServerQuery interface of a TeamSpeak 3 Server and gather information about its channel structure and clients connected. The result is returned in JSON format. 126 | 127 | ```php 128 | status = 'success'; 139 | $res->result = json_decode($ts3->getViewer(new TeamSpeak3_Viewer_Json())); 140 | } 141 | catch(TeamSpeak3_Exception $e) 142 | { 143 | $res->status = 'error'; 144 | $res->result = (object) array('code' => $e->getCode(), 'message' => $e->getMessage()); 145 | } 146 | 147 | header('Access-Control-Allow-Origin: *'); 148 | header('Content-Type: application/json'); 149 | 150 | echo json_encode($res); 151 | ``` 152 | 153 | #### The `servericon` API endpoint (`iconUrl`) 154 | 155 | To download an icon from a TeamSpeak 3 Server, we need to initialize the filetransfer via ServerQuery first. The code snippet below gets the contents of the icon file from the server and sends the result including the appropriate MIME type. 156 | 157 | ```php 158 | transferInitDownload(rand(0x0000, 0xFFFF), 0, '/icon_' . $ico); 168 | 169 | $ft = TeamSpeak3::factory('filetransfer://' . $init['host'] . ':' . $init['port']); 170 | $data = $ft->download($init['ftkey'], $init['size']); 171 | } 172 | catch(TeamSpeak3_Exception $e) 173 | { 174 | $data = file_get_contents('custom_error_icon.png'); 175 | } 176 | 177 | header('Content-Type: ' . TeamSpeak3_Helper_Convert::imageMimeType($data)); 178 | 179 | echo $data; 180 | ``` 181 | 182 | ## License 183 | Copyright © Planet TeamSpeak.
184 | Licensed under the MIT license. 185 | -------------------------------------------------------------------------------- /demo/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | REST API TSViewer - Basic Example 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 62 | 63 | 64 | 65 | 66 | 67 |
68 | 69 |

70 | REST API TSViewer Demo 71 |

72 | 73 |
74 | 77 | 78 | 81 | 82 | 85 |
86 | 87 |
88 | 89 |
90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /src/jquery.ts3viewer.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery TS3 Viewer v1.0.0 3 | * https://www.planetteamspeak.com 4 | * 5 | * Copyright (c) Planet TeamSpeak. All rights reserved. 6 | * Released under the MIT license. 7 | */ 8 | 9 | (function($) 10 | { 11 | /** 12 | * Constructor 13 | * 14 | * @param array options 15 | * @returns void 16 | */ 17 | $.fn.tsviewer = function(options) 18 | { 19 | $.fn.tsviewer.element = this; 20 | $.fn.tsviewer.options = $.extend({}, $.fn.tsviewer.options, options); 21 | 22 | $.fn.tsviewer.init(); 23 | $.fn.tsviewer.hook(); 24 | }; 25 | 26 | /** 27 | * Settings 28 | */ 29 | $.fn.tsviewer.element = null; 30 | $.fn.tsviewer.options = { 31 | // connection 32 | host: null, 33 | port: null, 34 | // data sources 35 | iconUrl: 'https://api.planetteamspeak.com/servericon/$host:$port/?id=$icon&img=1', 36 | dataUrl: 'https://api.planetteamspeak.com/servernodes/$host:$port/', 37 | // tooltip settings 38 | serverTip: '', 39 | channelTip: '', 40 | clientTip: '', 41 | // callback settings 42 | onNode: function() {}, 43 | onReady: function() {}, 44 | onError: function() {} 45 | }; 46 | 47 | /** 48 | * Initializes the plugin 49 | */ 50 | $.fn.tsviewer.init = function() 51 | { 52 | // generate base element 53 | $.fn.tsviewer.element.html(''); 54 | 55 | // prepare data sources based on server addr/port 56 | $.fn.tsviewer.options.iconUrl = $.fn.tsviewer.options.iconUrl.replace('$host', $.fn.tsviewer.options.host).replace('$port', $.fn.tsviewer.options.port); 57 | $.fn.tsviewer.options.dataUrl = $.fn.tsviewer.options.dataUrl.replace('$host', $.fn.tsviewer.options.host).replace('$port', $.fn.tsviewer.options.port); 58 | 59 | // refresh 60 | $.fn.tsviewer.refresh(true); 61 | }; 62 | 63 | /** 64 | * Requests data and starts rendering the nodes 65 | */ 66 | $.fn.tsviewer.refresh = function(loader) 67 | { 68 | // fire up the ajax request 69 | var req = $.ajax($.fn.tsviewer.options.dataUrl); 70 | 71 | // animation 72 | if(loader === true) 73 | { 74 | $('#tsv-container-ts3').html('
  • Loading ...
  • '); 75 | } 76 | 77 | // ajax request is done 78 | req.done(function(json, status, request) 79 | { 80 | if(json.status !== 'success' || !$.isArray(json.result.data)) 81 | { 82 | return $.fn.tsviewer.error(request, json.result.message); 83 | } 84 | 85 | $('#tsv-container-ts3').html(''); 86 | 87 | for(var i = 0; i < json.result.data.length; i++) 88 | { 89 | $.fn.tsviewer.render(json.result.data[i], i); 90 | } 91 | 92 | $.fn.tsviewer.options.onReady.call(this, json.result.data, i); 93 | }); 94 | 95 | // ajax request failed 96 | req.fail(function(request, status, error) 97 | { 98 | return $.fn.tsviewer.error(request, 'failed to retrieve tsviewer data'); 99 | }); 100 | }; 101 | 102 | /** 103 | * Expand all nodes in the tree 104 | */ 105 | $.fn.tsviewer.expand = function() 106 | { 107 | $.fn.tsviewer.element.find('.tsv-sibling.collapsed').each(function() { 108 | $(this).parents('.tsv-wrapper').siblings('ul').show(); 109 | $(this).toggleClass('expanded'); 110 | $(this).toggleClass('collapsed'); 111 | }); 112 | }; 113 | 114 | /** 115 | * Collapse all nodes in the tree 116 | */ 117 | $.fn.tsviewer.collapse = function() 118 | { 119 | $.fn.tsviewer.element.find('.tsv-sibling.expanded').each(function() { 120 | $(this).parents('.tsv-wrapper').siblings('ul').hide(); 121 | $(this).toggleClass('expanded'); 122 | $(this).toggleClass('collapsed'); 123 | }); 124 | }; 125 | 126 | /** 127 | * Expand/Collapse a specific node in the tree 128 | */ 129 | $.fn.tsviewer.hook = function() 130 | { 131 | $.fn.tsviewer.element.on('click', '.tsv-sibling.expanded, .tsv-sibling.collapsed', function() 132 | { 133 | $(this).parents('.tsv-wrapper').siblings('ul').toggle(); 134 | $(this).toggleClass('expanded'); 135 | $(this).toggleClass('collapsed'); 136 | }); 137 | }; 138 | 139 | /** 140 | * Renders a single node in the tree 141 | */ 142 | $.fn.tsviewer.render = function(node, num) 143 | { 144 | // fix node class for spacers 145 | if(node.class === 'channel' && node.props.flags & 0x80) 146 | { 147 | node.class = 'spacer ' + node.props.spacer.replace('custom', ''); 148 | 149 | if(node.props.spacer.substr(0, 6) !== 'custom') 150 | { 151 | node.name = ''; 152 | } 153 | else if(node.name.length && node.props.spacer.substr(node.props.spacer.length-6) === 'repeat') 154 | { 155 | while(node.name.length < 256) 156 | { 157 | node.name += node.name; 158 | } 159 | } 160 | } 161 | 162 | // generate node object 163 | var object = $('
  • '); 164 | 165 | // append node to parent container 166 | $('#tsv-container-' + node.parent).append(object); 167 | 168 | // generate block elements 169 | var wrapper = $('
    '); 170 | var nodebox = $('
    '); 171 | var infobox = $('
    '); 172 | var iconbox = $('
    '); 173 | var tooltip = ''; 174 | 175 | // assign wrapper 176 | object.append(wrapper); 177 | object.append('
    '); 178 | 179 | // assign elements 180 | wrapper.append(nodebox); 181 | nodebox.append(infobox); 182 | nodebox.append(iconbox); 183 | 184 | // render siblings 185 | for(var i = 0; i < node.siblings.length; i++) 186 | { 187 | infobox.append('
    '); 188 | } 189 | 190 | // line endings 191 | if(node.level > 1) 192 | { 193 | infobox.append('
    '); 194 | } 195 | 196 | // render node icon 197 | if(node.class.substr(0, 6) !== 'spacer') 198 | { 199 | if(node.class === 'channel' && node.props.flags & 0x40) 200 | { 201 | node.image += '-subscribed'; 202 | } 203 | 204 | infobox.append('
    '); 205 | } 206 | 207 | // do node specifics 208 | if(node.class === 'server') 209 | { 210 | tooltip += $.fn.tsviewer.options.serverTip; 211 | } 212 | else if(node.class === 'channel') 213 | { 214 | if(node.props.flags & 0x01) iconbox.append('
    '); 215 | if(node.props.flags & 0x02) iconbox.append('
    '); 216 | if(node.props.flags & 0x10) iconbox.append('
    '); 217 | if(node.props.flags & 0x20) iconbox.append('
    '); 218 | 219 | node.props.codec = $.fn.tsviewer.codec(node.props.codec); 220 | 221 | tooltip += $.fn.tsviewer.options.channelTip; 222 | } 223 | else if(node.class === 'client') 224 | { 225 | if(node.props.flags & 0x08) iconbox.append('
    '); 226 | if(node.props.flags & 0x04) iconbox.append('
    '); 227 | if(node.props.flags & 0x10) iconbox.append('
    '); 228 | if(node.props.flags & 0x20) iconbox.append('
    '); 229 | 230 | for(var i = 0; i < node.props.memberof.length; i++) 231 | { 232 | iconbox.append($.fn.tsviewer.icon(node.props.memberof[i].icon, $('
    ').text(node.props.memberof[i].name).html() + ' [' + (node.props.memberof[i].flags & 32 ? 'Server' : 'Channel') + ' Group]')); 233 | } 234 | 235 | tooltip += $.fn.tsviewer.options.clientTip; 236 | } 237 | 238 | // prepare tooltip 239 | if(tooltip.length) 240 | { 241 | for(var prop in node.props) 242 | { 243 | tooltip = tooltip.replace('$' + prop, node.props[prop]); 244 | } 245 | } 246 | 247 | // assign information to block elements 248 | iconbox.append($.fn.tsviewer.icon(node.props.icon, node.class.charAt(0).toUpperCase() + node.class.slice(1) + ' Icon')); 249 | infobox.append('' + (node.name ? $('
    ').text(node.name).html() : ' ') + ''); 250 | 251 | // set nodebox width 252 | $.fn.tsviewer.width(nodebox, iconbox); 253 | 254 | // callback 255 | $.fn.tsviewer.options.onNode.call(this, object, node); 256 | 257 | // prepare children 258 | if(node.children > 0) 259 | { 260 | object.append('
      '); 261 | } 262 | }; 263 | 264 | /** 265 | * Returns the base URL of the current script 266 | */ 267 | $.fn.tsviewer.base = function() 268 | {}; 269 | 270 | /** 271 | * Returns the HTML to render an icon 272 | */ 273 | $.fn.tsviewer.icon = function(id, title) 274 | { 275 | if(id > 0) 276 | { 277 | if(id < 1000) 278 | { 279 | return '
      '; 280 | } 281 | else 282 | { 283 | return '
      '; 284 | } 285 | } 286 | 287 | return ''; 288 | }; 289 | 290 | /** 291 | * Returns the codec name based on an ID 292 | */ 293 | $.fn.tsviewer.codec = function(codec) 294 | { 295 | if(codec === 0x00) return 'Speex Narrowband'; 296 | if(codec === 0x01) return 'Speex Wideband'; 297 | if(codec === 0x02) return 'Speex Ultra-Wideband'; 298 | if(codec === 0x03) return 'CELT Mono'; 299 | if(codec === 0x04) return 'Opus Voice'; 300 | if(codec === 0x05) return 'Opus Music'; 301 | 302 | return codec; 303 | }; 304 | 305 | /** 306 | * Calculates and sets width for the icon sidebar 307 | */ 308 | $.fn.tsviewer.width = function(nodebox, iconbox) 309 | { 310 | var width = iconbox.width(); 311 | 312 | nodebox.css({ marginRight: width }); 313 | iconbox.css({ marginRight: -width, width: width }); 314 | }; 315 | 316 | /** 317 | * Sets an error message 318 | */ 319 | $.fn.tsviewer.error = function(request, error) 320 | { 321 | $.fn.tsviewer.options.onError.call(this, error); 322 | 323 | $('#tsv-container-ts3').html('
    • ' + $.fn.tsviewer.options.host + ':' + $.fn.tsviewer.options.port + '
    • '); 324 | }; 325 | 326 | /** 327 | * Shortcut method to refresh the tree 328 | */ 329 | $.fn.tsviewerRefresh = function(loader) 330 | { 331 | if($.fn.tsviewer.element) 332 | { 333 | $.fn.tsviewer.refresh(loader); 334 | } 335 | }; 336 | 337 | /** 338 | * Shortcut method to expand the tree 339 | */ 340 | $.fn.tsviewerExpand = function() 341 | { 342 | if($.fn.tsviewer.element) 343 | { 344 | $.fn.tsviewer.expand(); 345 | } 346 | }; 347 | 348 | /** 349 | * Shortcut method to collapse the tree 350 | */ 351 | $.fn.tsviewerCollapse = function() 352 | { 353 | if($.fn.tsviewer.element) 354 | { 355 | $.fn.tsviewer.collapse(); 356 | } 357 | }; 358 | }(jQuery)); 359 | -------------------------------------------------------------------------------- /src/jquery.ts3viewer.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery TS3 Viewer v1.0.0 3 | * https://www.planetteamspeak.com 4 | * 5 | * Copyright (c) Planet TeamSpeak. All rights reserved. 6 | * Released under the MIT license. 7 | */ 8 | !function(e){e.fn.tsviewer=function(s){e.fn.tsviewer.element=this,e.fn.tsviewer.options=e.extend({},e.fn.tsviewer.options,s),e.fn.tsviewer.init(),e.fn.tsviewer.hook()},e.fn.tsviewer.element=null,e.fn.tsviewer.options={host:null,port:null,iconUrl:"https://api.planetteamspeak.com/servericon/$host:$port/?id=$icon&img=1",dataUrl:"https://api.planetteamspeak.com/servernodes/$host:$port/",serverTip:"",channelTip:"",clientTip:"",onNode:function(){},onReady:function(){},onError:function(){}},e.fn.tsviewer.init=function(){e.fn.tsviewer.element.html('
        '),e.fn.tsviewer.options.iconUrl=e.fn.tsviewer.options.iconUrl.replace("$host",e.fn.tsviewer.options.host).replace("$port",e.fn.tsviewer.options.port),e.fn.tsviewer.options.dataUrl=e.fn.tsviewer.options.dataUrl.replace("$host",e.fn.tsviewer.options.host).replace("$port",e.fn.tsviewer.options.port),e.fn.tsviewer.refresh(!0)},e.fn.tsviewer.refresh=function(s){var t=e.ajax(e.fn.tsviewer.options.dataUrl);s===!0&&e("#tsv-container-ts3").html('
      • Loading ...
      • '),t.done(function(s,t,n){if("success"!==s.status||!e.isArray(s.result.data))return e.fn.tsviewer.error(n,s.result.message);e("#tsv-container-ts3").html("");for(var i=0;i');e("#tsv-container-"+s.parent).append(n);var i=e('
        '),r=e('
        '),a=e('
        '),o=e('
        '),l="";n.append(i),n.append('
        '),i.append(r),r.append(a),r.append(o);for(var p=0;p
        ');if(s.level>1&&a.append('
        0?" expanded":"")+'">
        '),"spacer"!==s["class"].substr(0,6)&&("channel"===s["class"]&&64&s.props.flags&&(s.image+="-subscribed"),a.append('
        ')),"server"===s["class"])l+=e.fn.tsviewer.options.serverTip;else if("channel"===s["class"])1&s.props.flags&&o.append('
        '),2&s.props.flags&&o.append('
        '),16&s.props.flags&&o.append('
        '),32&s.props.flags&&o.append('
        '),s.props.codec=e.fn.tsviewer.codec(s.props.codec),l+=e.fn.tsviewer.options.channelTip;else if("client"===s["class"]){8&s.props.flags&&o.append('
        '),4&s.props.flags&&o.append('
        '),16&s.props.flags&&o.append('
        '),32&s.props.flags&&o.append('
        ');for(var p=0;p").text(s.props.memberof[p].name).html()+" ["+(32&s.props.memberof[p].flags?"Server":"Channel")+" Group]"));l+=e.fn.tsviewer.options.clientTip}if(l.length)for(var v in s.props)l=l.replace("$"+v,s.props[v]);o.append(e.fn.tsviewer.icon(s.props.icon,s["class"].charAt(0).toUpperCase()+s["class"].slice(1)+" Icon")),a.append('"+(s.name?e("
        ").text(s.name).html():" ")+""),e.fn.tsviewer.width(r,o),e.fn.tsviewer.options.onNode.call(this,n,s),s.children>0&&n.append('
          ')},e.fn.tsviewer.base=function(){},e.fn.tsviewer.icon=function(s,t){return s>0?1e3>s?'
          ':'
          ':""},e.fn.tsviewer.codec=function(e){return 0===e?"Speex Narrowband":1===e?"Speex Wideband":2===e?"Speex Ultra-Wideband":3===e?"CELT Mono":4===e?"Opus Voice":5===e?"Opus Music":e},e.fn.tsviewer.width=function(e,s){var t=s.width();e.css({marginRight:t}),s.css({marginRight:-t,width:t})},e.fn.tsviewer.error=function(s,t){e.fn.tsviewer.options.onError.call(this,t),e("#tsv-container-ts3").html('
        • '+e.fn.tsviewer.options.host+":"+e.fn.tsviewer.options.port+"
        • ")},e.fn.tsviewerRefresh=function(s){e.fn.tsviewer.element&&e.fn.tsviewer.refresh(s)},e.fn.tsviewerExpand=function(){e.fn.tsviewer.element&&e.fn.tsviewer.expand()},e.fn.tsviewerCollapse=function(){e.fn.tsviewer.element&&e.fn.tsviewer.collapse()}}(jQuery); 9 | -------------------------------------------------------------------------------- /src/themes/classic/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/classic/loader.gif -------------------------------------------------------------------------------- /src/themes/classic/spacer_dashdotdotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/classic/spacer_dashdotdotline.gif -------------------------------------------------------------------------------- /src/themes/classic/spacer_dashdotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/classic/spacer_dashdotline.gif -------------------------------------------------------------------------------- /src/themes/classic/spacer_dashline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/classic/spacer_dashline.gif -------------------------------------------------------------------------------- /src/themes/classic/spacer_dotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/classic/spacer_dotline.gif -------------------------------------------------------------------------------- /src/themes/classic/spacer_solidline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/classic/spacer_solidline.gif -------------------------------------------------------------------------------- /src/themes/classic/tree.css: -------------------------------------------------------------------------------- 1 | .tsv-container { 2 | text-align: left; 3 | list-style: none; 4 | padding: 0px !important; 5 | margin: 0px !important; 6 | } 7 | 8 | .tsv-wrapper { 9 | width: 100%; 10 | height: 16px; 11 | line-height: 1.25em; 12 | font-size: 1.0em; 13 | } 14 | 15 | .tsv-infos { 16 | width: 100%; 17 | float: left; 18 | text-overflow: ellipsis; 19 | white-space: nowrap; 20 | overflow: hidden; 21 | } 22 | 23 | .tsv-icons { 24 | float: right; 25 | } 26 | 27 | .tsv-clear { 28 | clear: both; 29 | } 30 | 31 | .tsv-node.error { 32 | color: red; 33 | } 34 | 35 | .tsv-spacer.left { 36 | text-align: left; 37 | } 38 | 39 | .tsv-spacer.center { 40 | text-align: center; 41 | } 42 | 43 | .tsv-spacer.right { 44 | text-align: right; 45 | } 46 | 47 | .tsv-spacer.solidline .tsv-name, 48 | .tsv-spacer.dashline .tsv-name, 49 | .tsv-spacer.dashdotline .tsv-name, 50 | .tsv-spacer.dashdotdotline .tsv-name, 51 | .tsv-spacer.dotline .tsv-name { 52 | margin-left: 16px; 53 | background-repeat: repeat-x; 54 | display: block; 55 | } 56 | 57 | .tsv-spacer.solidline .tsv-name { 58 | background-image: url('spacer_solidline.gif'); 59 | } 60 | 61 | .tsv-spacer.dashline .tsv-name { 62 | background-image: url('spacer_dashline.gif'); 63 | } 64 | 65 | .tsv-spacer.dashdotline .tsv-name { 66 | background-image: url('spacer_dashdotline.gif'); 67 | } 68 | 69 | .tsv-spacer.dashdotdotline .tsv-name { 70 | background-image: url('spacer_dashdotdotline.gif'); 71 | } 72 | 73 | .tsv-spacer.dotline .tsv-name { 74 | background-image: url('spacer_dotline.gif'); 75 | } 76 | 77 | .tsv-spacer.repeat .tsv-infos { 78 | text-overflow: clip; 79 | overflow: hidden; 80 | } 81 | 82 | .tsv-icon, 83 | .tsv-sibling { 84 | width: 16px; 85 | height: 16px; 86 | background-image: url('tree.png'); 87 | background-size: 160px 64px; 88 | float: left; 89 | } 90 | 91 | .tsv-sibling-blank { 92 | background-position: 160px 0px; 93 | } 94 | 95 | .tsv-sibling-mid { 96 | background-position: 144px 0px; 97 | } 98 | 99 | .tsv-sibling-line { 100 | background-position: 128px 0px; 101 | } 102 | 103 | .tsv-sibling-end { 104 | background-position: 112px 0px; 105 | } 106 | 107 | .tsv-sibling-mid.expanded { 108 | background-position: 64px 16px; 109 | cursor: pointer; 110 | } 111 | 112 | .tsv-sibling-mid.collapsed { 113 | background-position: 48px 16px; 114 | cursor: pointer; 115 | } 116 | 117 | .tsv-sibling-end.expanded { 118 | background-position: 32px 16px; 119 | cursor: pointer; 120 | } 121 | 122 | .tsv-sibling-end.collapsed { 123 | background-position: 16px 16px; 124 | cursor: pointer; 125 | } 126 | 127 | .tsv-icon { 128 | margin-right: 3px; 129 | } 130 | 131 | .tsv-icon.tsv-server-open { 132 | background-position: 96px 0px; 133 | } 134 | 135 | .tsv-icon.tsv-server-pass { 136 | background-position: 80px 0px; 137 | } 138 | 139 | .tsv-icon.tsv-server-full { 140 | background-position: 64px 0px; 141 | } 142 | 143 | .tsv-icon.tsv-channel-open { 144 | background-position: 48px 0px; 145 | } 146 | 147 | .tsv-icon.tsv-channel-pass { 148 | background-position: 32px 0px; 149 | } 150 | 151 | .tsv-icon.tsv-channel-full { 152 | background-position: 16px 0px; 153 | } 154 | 155 | .tsv-icon.tsv-client-idle { 156 | background-position: 160px 48px; 157 | } 158 | 159 | .tsv-icon.tsv-client-talk { 160 | background-position: 144px 48px; 161 | } 162 | 163 | .tsv-icon.tsv-client-cc-idle { 164 | background-position: 128px 48px; 165 | } 166 | 167 | .tsv-icon.tsv-client-cc-talk { 168 | background-position: 112px 48px; 169 | } 170 | 171 | .tsv-icon.tsv-client-mic-muted { 172 | background-position: 96px 48px; 173 | } 174 | 175 | .tsv-icon.tsv-client-mic-disabled { 176 | background-position: 80px 48px; 177 | } 178 | 179 | .tsv-icon.tsv-client-snd-muted { 180 | background-position: 64px 48px; 181 | } 182 | 183 | .tsv-icon.tsv-client-snd-disabled { 184 | background-position: 48px 48px; 185 | } 186 | 187 | .tsv-icon.tsv-client-away { 188 | background-position: 32px 48px; 189 | } 190 | 191 | .tsv-icon.tsv-client-cc { 192 | background-position: 16px 48px; 193 | } 194 | 195 | .tsv-icon.tsv-client-query { 196 | background-position: 160px 32px; 197 | } 198 | 199 | .tsv-icon.tsv-client-priority { 200 | background-position: 144px 32px; 201 | } 202 | 203 | .tsv-icon.tsv-client-talker { 204 | background-position: 128px 32px; 205 | } 206 | 207 | .tsv-icon.tsv-channel-open-subscribed { 208 | background-position: 112px 32px; 209 | } 210 | 211 | .tsv-icon.tsv-channel-pass-subscribed { 212 | background-position: 96px 32px; 213 | } 214 | 215 | .tsv-icon.tsv-channel-full-subscribed { 216 | background-position: 80px 32px; 217 | } 218 | 219 | .tsv-icon.tsv-channel-flag-music { 220 | background-position: 64px 32px; 221 | } 222 | 223 | .tsv-icon.tsv-channel-flag-moderated { 224 | background-position: 48px 32px; 225 | } 226 | 227 | .tsv-icon.tsv-channel-flag-password { 228 | background-position: 32px 32px; 229 | } 230 | 231 | .tsv-icon.tsv-channel-flag-default { 232 | background-position: 16px 32px; 233 | } 234 | 235 | .tsv-icon.tsv-group-100 { 236 | background-position: 128px 16px; 237 | } 238 | 239 | .tsv-icon.tsv-group-200 { 240 | background-position: 144px 16px; 241 | } 242 | 243 | .tsv-icon.tsv-group-300 { 244 | background-position: 112px 16px; 245 | } 246 | 247 | .tsv-icon.tsv-group-500 { 248 | background-position: 96px 16px; 249 | } 250 | 251 | .tsv-icon.tsv-group-600 { 252 | background-position: 160px 16px; 253 | } 254 | 255 | .tsv-icon.tsv-error { 256 | background-position: 80px 16px; 257 | } 258 | 259 | .tsv-icon.tsv-loader { 260 | background: url('loader.gif'); 261 | } 262 | -------------------------------------------------------------------------------- /src/themes/classic/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/classic/tree.png -------------------------------------------------------------------------------- /src/themes/colored/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/loader.gif -------------------------------------------------------------------------------- /src/themes/colored/spacer_dashdotdotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/spacer_dashdotdotline.gif -------------------------------------------------------------------------------- /src/themes/colored/spacer_dashdotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/spacer_dashdotline.gif -------------------------------------------------------------------------------- /src/themes/colored/spacer_dashline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/spacer_dashline.gif -------------------------------------------------------------------------------- /src/themes/colored/spacer_dotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/spacer_dotline.gif -------------------------------------------------------------------------------- /src/themes/colored/spacer_solidline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/spacer_solidline.gif -------------------------------------------------------------------------------- /src/themes/colored/tree.css: -------------------------------------------------------------------------------- 1 | .tsv-container { 2 | text-align: left; 3 | list-style: none; 4 | padding: 0px !important; 5 | margin: 0px !important; 6 | } 7 | 8 | .tsv-wrapper { 9 | width: 100%; 10 | height: 16px; 11 | line-height: 1.25em; 12 | font-size: 1.0em; 13 | } 14 | 15 | .tsv-infos { 16 | width: 100%; 17 | float: left; 18 | text-overflow: ellipsis; 19 | white-space: nowrap; 20 | overflow: hidden; 21 | } 22 | 23 | .tsv-icons { 24 | float: right; 25 | } 26 | 27 | .tsv-clear { 28 | clear: both; 29 | } 30 | 31 | .tsv-node.error { 32 | color: red; 33 | } 34 | 35 | .tsv-spacer.left { 36 | text-align: left; 37 | } 38 | 39 | .tsv-spacer.center { 40 | text-align: center; 41 | } 42 | 43 | .tsv-spacer.right { 44 | text-align: right; 45 | } 46 | 47 | .tsv-spacer.solidline .tsv-name, 48 | .tsv-spacer.dashline .tsv-name, 49 | .tsv-spacer.dashdotline .tsv-name, 50 | .tsv-spacer.dashdotdotline .tsv-name, 51 | .tsv-spacer.dotline .tsv-name { 52 | margin-left: 16px; 53 | background-repeat: repeat-x; 54 | display: block; 55 | } 56 | 57 | .tsv-spacer.solidline .tsv-name { 58 | background-image: url('spacer_solidline.gif'); 59 | } 60 | 61 | .tsv-spacer.dashline .tsv-name { 62 | background-image: url('spacer_dashline.gif'); 63 | } 64 | 65 | .tsv-spacer.dashdotline .tsv-name { 66 | background-image: url('spacer_dashdotline.gif'); 67 | } 68 | 69 | .tsv-spacer.dashdotdotline .tsv-name { 70 | background-image: url('spacer_dashdotdotline.gif'); 71 | } 72 | 73 | .tsv-spacer.dotline .tsv-name { 74 | background-image: url('spacer_dotline.gif'); 75 | } 76 | 77 | .tsv-spacer.repeat .tsv-infos { 78 | text-overflow: clip; 79 | overflow: hidden; 80 | } 81 | 82 | .tsv-icon, 83 | .tsv-sibling { 84 | width: 16px; 85 | height: 16px; 86 | background-image: url('tree@3x.png'); 87 | background-size: 160px 64px; 88 | float: left; 89 | } 90 | 91 | .tsv-sibling-blank { 92 | background-position: 160px 0px; 93 | } 94 | 95 | .tsv-sibling-mid { 96 | background-position: 144px 0px; 97 | } 98 | 99 | .tsv-sibling-line { 100 | background-position: 128px 0px; 101 | } 102 | 103 | .tsv-sibling-end { 104 | background-position: 112px 0px; 105 | } 106 | 107 | .tsv-sibling-mid.expanded { 108 | background-position: 64px 16px; 109 | cursor: pointer; 110 | } 111 | 112 | .tsv-sibling-mid.collapsed { 113 | background-position: 48px 16px; 114 | cursor: pointer; 115 | } 116 | 117 | .tsv-sibling-end.expanded { 118 | background-position: 32px 16px; 119 | cursor: pointer; 120 | } 121 | 122 | .tsv-sibling-end.collapsed { 123 | background-position: 16px 16px; 124 | cursor: pointer; 125 | } 126 | 127 | .tsv-icon { 128 | margin-right: 3px; 129 | } 130 | 131 | .tsv-icon.tsv-server-open { 132 | background-position: 96px 0px; 133 | } 134 | 135 | .tsv-icon.tsv-server-pass { 136 | background-position: 80px 0px; 137 | } 138 | 139 | .tsv-icon.tsv-server-full { 140 | background-position: 64px 0px; 141 | } 142 | 143 | .tsv-icon.tsv-channel-open { 144 | background-position: 48px 0px; 145 | } 146 | 147 | .tsv-icon.tsv-channel-pass { 148 | background-position: 32px 0px; 149 | } 150 | 151 | .tsv-icon.tsv-channel-full { 152 | background-position: 16px 0px; 153 | } 154 | 155 | .tsv-icon.tsv-client-idle { 156 | background-position: 160px 48px; 157 | } 158 | 159 | .tsv-icon.tsv-client-talk { 160 | background-position: 144px 48px; 161 | } 162 | 163 | .tsv-icon.tsv-client-cc-idle { 164 | background-position: 128px 48px; 165 | } 166 | 167 | .tsv-icon.tsv-client-cc-talk { 168 | background-position: 112px 48px; 169 | } 170 | 171 | .tsv-icon.tsv-client-mic-muted { 172 | background-position: 96px 48px; 173 | } 174 | 175 | .tsv-icon.tsv-client-mic-disabled { 176 | background-position: 80px 48px; 177 | } 178 | 179 | .tsv-icon.tsv-client-snd-muted { 180 | background-position: 64px 48px; 181 | } 182 | 183 | .tsv-icon.tsv-client-snd-disabled { 184 | background-position: 48px 48px; 185 | } 186 | 187 | .tsv-icon.tsv-client-away { 188 | background-position: 32px 48px; 189 | } 190 | 191 | .tsv-icon.tsv-client-cc { 192 | background-position: 16px 48px; 193 | } 194 | 195 | .tsv-icon.tsv-client-query { 196 | background-position: 160px 32px; 197 | } 198 | 199 | .tsv-icon.tsv-client-priority { 200 | background-position: 144px 32px; 201 | } 202 | 203 | .tsv-icon.tsv-client-talker { 204 | background-position: 128px 32px; 205 | } 206 | 207 | .tsv-icon.tsv-channel-open-subscribed { 208 | background-position: 112px 32px; 209 | } 210 | 211 | .tsv-icon.tsv-channel-pass-subscribed { 212 | background-position: 96px 32px; 213 | } 214 | 215 | .tsv-icon.tsv-channel-full-subscribed { 216 | background-position: 80px 32px; 217 | } 218 | 219 | .tsv-icon.tsv-channel-flag-music { 220 | background-position: 64px 32px; 221 | } 222 | 223 | .tsv-icon.tsv-channel-flag-moderated { 224 | background-position: 48px 32px; 225 | } 226 | 227 | .tsv-icon.tsv-channel-flag-password { 228 | background-position: 32px 32px; 229 | } 230 | 231 | .tsv-icon.tsv-channel-flag-default { 232 | background-position: 16px 32px; 233 | } 234 | 235 | .tsv-icon.tsv-group-100 { 236 | background-position: 128px 16px; 237 | } 238 | 239 | .tsv-icon.tsv-group-200 { 240 | background-position: 144px 16px; 241 | } 242 | 243 | .tsv-icon.tsv-group-300 { 244 | background-position: 112px 16px; 245 | } 246 | 247 | .tsv-icon.tsv-group-500 { 248 | background-position: 96px 16px; 249 | } 250 | 251 | .tsv-icon.tsv-group-600 { 252 | background-position: 160px 16px; 253 | } 254 | 255 | .tsv-icon.tsv-error { 256 | background-position: 80px 16px; 257 | } 258 | 259 | .tsv-icon.tsv-loader { 260 | background: url('loader.gif'); 261 | } 262 | -------------------------------------------------------------------------------- /src/themes/colored/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/tree.png -------------------------------------------------------------------------------- /src/themes/colored/tree@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/tree@2x.png -------------------------------------------------------------------------------- /src/themes/colored/tree@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/colored/tree@3x.png -------------------------------------------------------------------------------- /src/themes/mono/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/loader.gif -------------------------------------------------------------------------------- /src/themes/mono/spacer_dashdotdotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/spacer_dashdotdotline.gif -------------------------------------------------------------------------------- /src/themes/mono/spacer_dashdotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/spacer_dashdotline.gif -------------------------------------------------------------------------------- /src/themes/mono/spacer_dashline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/spacer_dashline.gif -------------------------------------------------------------------------------- /src/themes/mono/spacer_dotline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/spacer_dotline.gif -------------------------------------------------------------------------------- /src/themes/mono/spacer_solidline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/spacer_solidline.gif -------------------------------------------------------------------------------- /src/themes/mono/tree.css: -------------------------------------------------------------------------------- 1 | .tsv-container { 2 | text-align: left; 3 | list-style: none; 4 | padding: 0px !important; 5 | margin: 0px !important; 6 | } 7 | 8 | .tsv-wrapper { 9 | width: 100%; 10 | height: 16px; 11 | line-height: 1.25em; 12 | font-size: 1.0em; 13 | } 14 | 15 | .tsv-infos { 16 | width: 100%; 17 | float: left; 18 | text-overflow: ellipsis; 19 | white-space: nowrap; 20 | overflow: hidden; 21 | } 22 | 23 | .tsv-icons { 24 | float: right; 25 | } 26 | 27 | .tsv-clear { 28 | clear: both; 29 | } 30 | 31 | .tsv-node.error { 32 | color: red; 33 | } 34 | 35 | .tsv-spacer.left { 36 | text-align: left; 37 | } 38 | 39 | .tsv-spacer.center { 40 | text-align: center; 41 | } 42 | 43 | .tsv-spacer.right { 44 | text-align: right; 45 | } 46 | 47 | .tsv-spacer.solidline .tsv-name, 48 | .tsv-spacer.dashline .tsv-name, 49 | .tsv-spacer.dashdotline .tsv-name, 50 | .tsv-spacer.dashdotdotline .tsv-name, 51 | .tsv-spacer.dotline .tsv-name { 52 | margin-left: 16px; 53 | background-repeat: repeat-x; 54 | display: block; 55 | } 56 | 57 | .tsv-spacer.solidline .tsv-name { 58 | background-image: url('spacer_solidline.gif'); 59 | } 60 | 61 | .tsv-spacer.dashline .tsv-name { 62 | background-image: url('spacer_dashline.gif'); 63 | } 64 | 65 | .tsv-spacer.dashdotline .tsv-name { 66 | background-image: url('spacer_dashdotline.gif'); 67 | } 68 | 69 | .tsv-spacer.dashdotdotline .tsv-name { 70 | background-image: url('spacer_dashdotdotline.gif'); 71 | } 72 | 73 | .tsv-spacer.dotline .tsv-name { 74 | background-image: url('spacer_dotline.gif'); 75 | } 76 | 77 | .tsv-spacer.repeat .tsv-infos { 78 | text-overflow: clip; 79 | overflow: hidden; 80 | } 81 | 82 | .tsv-icon, 83 | .tsv-sibling { 84 | width: 16px; 85 | height: 16px; 86 | background-image: url('tree@3x.png'); 87 | background-size: 160px 64px; 88 | float: left; 89 | } 90 | 91 | .tsv-sibling-blank { 92 | background-position: 160px 0px; 93 | } 94 | 95 | .tsv-sibling-mid { 96 | background-position: 144px 0px; 97 | } 98 | 99 | .tsv-sibling-line { 100 | background-position: 128px 0px; 101 | } 102 | 103 | .tsv-sibling-end { 104 | background-position: 112px 0px; 105 | } 106 | 107 | .tsv-sibling-mid.expanded { 108 | background-position: 64px 16px; 109 | cursor: pointer; 110 | } 111 | 112 | .tsv-sibling-mid.collapsed { 113 | background-position: 48px 16px; 114 | cursor: pointer; 115 | } 116 | 117 | .tsv-sibling-end.expanded { 118 | background-position: 32px 16px; 119 | cursor: pointer; 120 | } 121 | 122 | .tsv-sibling-end.collapsed { 123 | background-position: 16px 16px; 124 | cursor: pointer; 125 | } 126 | 127 | .tsv-icon { 128 | margin-right: 3px; 129 | } 130 | 131 | .tsv-icon.tsv-server-open { 132 | background-position: 96px 0px; 133 | } 134 | 135 | .tsv-icon.tsv-server-pass { 136 | background-position: 80px 0px; 137 | } 138 | 139 | .tsv-icon.tsv-server-full { 140 | background-position: 64px 0px; 141 | } 142 | 143 | .tsv-icon.tsv-channel-open { 144 | background-position: 48px 0px; 145 | } 146 | 147 | .tsv-icon.tsv-channel-pass { 148 | background-position: 32px 0px; 149 | } 150 | 151 | .tsv-icon.tsv-channel-full { 152 | background-position: 16px 0px; 153 | } 154 | 155 | .tsv-icon.tsv-client-idle { 156 | background-position: 160px 48px; 157 | } 158 | 159 | .tsv-icon.tsv-client-talk { 160 | background-position: 144px 48px; 161 | } 162 | 163 | .tsv-icon.tsv-client-cc-idle { 164 | background-position: 128px 48px; 165 | } 166 | 167 | .tsv-icon.tsv-client-cc-talk { 168 | background-position: 112px 48px; 169 | } 170 | 171 | .tsv-icon.tsv-client-mic-muted { 172 | background-position: 96px 48px; 173 | } 174 | 175 | .tsv-icon.tsv-client-mic-disabled { 176 | background-position: 80px 48px; 177 | } 178 | 179 | .tsv-icon.tsv-client-snd-muted { 180 | background-position: 64px 48px; 181 | } 182 | 183 | .tsv-icon.tsv-client-snd-disabled { 184 | background-position: 48px 48px; 185 | } 186 | 187 | .tsv-icon.tsv-client-away { 188 | background-position: 32px 48px; 189 | } 190 | 191 | .tsv-icon.tsv-client-cc { 192 | background-position: 16px 48px; 193 | } 194 | 195 | .tsv-icon.tsv-client-query { 196 | background-position: 160px 32px; 197 | } 198 | 199 | .tsv-icon.tsv-client-priority { 200 | background-position: 144px 32px; 201 | } 202 | 203 | .tsv-icon.tsv-client-talker { 204 | background-position: 128px 32px; 205 | } 206 | 207 | .tsv-icon.tsv-channel-open-subscribed { 208 | background-position: 112px 32px; 209 | } 210 | 211 | .tsv-icon.tsv-channel-pass-subscribed { 212 | background-position: 96px 32px; 213 | } 214 | 215 | .tsv-icon.tsv-channel-full-subscribed { 216 | background-position: 80px 32px; 217 | } 218 | 219 | .tsv-icon.tsv-channel-flag-music { 220 | background-position: 64px 32px; 221 | } 222 | 223 | .tsv-icon.tsv-channel-flag-moderated { 224 | background-position: 48px 32px; 225 | } 226 | 227 | .tsv-icon.tsv-channel-flag-password { 228 | background-position: 32px 32px; 229 | } 230 | 231 | .tsv-icon.tsv-channel-flag-default { 232 | background-position: 16px 32px; 233 | } 234 | 235 | .tsv-icon.tsv-group-100 { 236 | background-position: 128px 16px; 237 | } 238 | 239 | .tsv-icon.tsv-group-200 { 240 | background-position: 144px 16px; 241 | } 242 | 243 | .tsv-icon.tsv-group-300 { 244 | background-position: 112px 16px; 245 | } 246 | 247 | .tsv-icon.tsv-group-500 { 248 | background-position: 96px 16px; 249 | } 250 | 251 | .tsv-icon.tsv-group-600 { 252 | background-position: 160px 16px; 253 | } 254 | 255 | .tsv-icon.tsv-error { 256 | background-position: 80px 16px; 257 | } 258 | 259 | .tsv-icon.tsv-loader { 260 | background: url('loader.gif'); 261 | } 262 | -------------------------------------------------------------------------------- /src/themes/mono/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/tree.png -------------------------------------------------------------------------------- /src/themes/mono/tree@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/tree@2x.png -------------------------------------------------------------------------------- /src/themes/mono/tree@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetteamspeak/jquery-ts3viewer/203bbb77304a42cb61159b6ec842d4e39cc065d1/src/themes/mono/tree@3x.png --------------------------------------------------------------------------------