1 /** 2 * @fileOverview 3 * Additions to GeoMashup for handling taxonomy terms. 4 */ 5 6 /*global GeoMashup, jQuery */ 7 /*global customGeoMashupCategoryIcon, customGeoMashupColorIcon */ 8 9 /*jslint browser: true, white: true, sloppy: true */ 10 11 jQuery.extend( GeoMashup, { 12 13 /** 14 * An object to manage taxonomy terms. 15 * @since 1.5 16 * @memberOf GeoMashup 17 */ 18 term_manager : (function() { 19 var $ = jQuery, 20 21 // Public interface 22 term_manager = {}, 23 24 // Loaded terms as { "taxonomy1": { term_count: 0, terms: { 25 // "3" : { 26 // icon : icon, 27 // points : [point], 28 // posts : [object_id], 29 // color : color_rgb, 30 // visible : true, 31 // max_line_zoom : max_line_zoom 32 // } } } 33 loaded_terms = {}, 34 35 // Structure and settings for terms in included taxonomies 36 // e.g. { "taxonomy1": { "label": "Taxonomy One", "terms": { 37 // "3": { name: "Term 3 Name", parent_id: "1", color: "red", line_zoom: "7" } 38 // } } } 39 term_properties, 40 41 // Each taxonomy gets a tree of term ids with null leaves 42 // { "taxonomy1": { "1": { "3": null }, "2": null } } 43 hierarchies = {}, 44 45 // { "taxonomy1": Element, "taxonomy2": Element } 46 legend_elements = []; 47 48 /** 49 * Search for a legend element for a taxonomy. 50 * 51 * Without a context, the current document is searched first, 52 * then the parent if available. 53 * 54 * @private 55 * 56 * @param {String} taxonomy 57 * @param {String} widget_type 'legend' or 'tabbed-index' 58 * @param {Document} context 59 * @return {Element} The legend element or null if not found. 60 */ 61 function getWidgetElement( taxonomy, widget_type, context ) { 62 var element = null; 63 64 if ( typeof context === 'undefined' ) { 65 66 element = getWidgetElement( taxonomy, widget_type, document ); 67 68 if ( !element && GeoMashup.have_parent_access ) { 69 element = getWidgetElement( taxonomy, widget_type, parent.document ); 70 } 71 72 } else { 73 74 if ( GeoMashup.opts.name ) { 75 76 element = context.getElementById( GeoMashup.opts.name + '-' + taxonomy + '-' + widget_type ); 77 78 if ( !element ) { 79 element = context.getElementById( GeoMashup.opts.name + '-' + widget_type ); 80 } 81 82 } 83 84 if ( !element ) { 85 element = context.getElementById( 'gm-term-' + widget_type ); 86 } 87 88 // Back compat names 89 if ( !element && 'category' === taxonomy ) { 90 if ( 'legend' === widget_type ) { 91 element = context.getElementById( 'gm-cat-legend' ); 92 } else { 93 element = context.getElementById( 'gm-' + widget_type ); 94 } 95 } 96 97 } 98 99 return element; 100 } 101 102 function buildTermHierarchy(taxonomy, term_id) { 103 var children, child_count, top_id, child_id, properties = term_properties[taxonomy]; 104 105 if (term_id) { // This is a recursive call 106 107 // Find children of this term and return them 108 term_id = String( term_id ); 109 children = {}; 110 child_count = 0; 111 112 $.each( properties.terms, function( child_id, term_data ) { 113 if ( term_data.parent_id && term_data.parent_id === term_id ) { 114 children[child_id] = buildTermHierarchy( taxonomy, child_id ); 115 child_count += 1; 116 } 117 }); 118 119 return (child_count > 0) ? children : null; 120 121 } else { // Top-level call 122 123 // Build a tree for each taxonomy's top level (no parent) terms 124 hierarchies[taxonomy] = {}; 125 126 $.each( properties.terms, function( top_id, term_data ) { 127 if ( !term_data.parent_id) { 128 hierarchies[taxonomy][top_id] = buildTermHierarchy( taxonomy, top_id ); 129 } 130 } ); 131 132 } 133 } 134 135 function createTermLines() { 136 137 $.each( loaded_terms, function( taxonomy, tax_data ) { 138 $.each( tax_data.terms, function ( term_id, term_data ) { 139 140 if ( term_data.max_line_zoom >= 0 ) { 141 GeoMashup.createTermLine( term_data ); 142 } 143 144 } ); 145 } ); 146 } 147 148 function sortTermLegendData( taxonomy, tax_data ) { 149 var ordered_terms = []; 150 151 $.each( tax_data.terms, function ( term_id, term_data ) { 152 var order, sort_term = term_data; 153 154 sort_term.term_id = term_id; 155 sort_term.name = term_properties[taxonomy].terms[term_id].name; 156 157 // Check for an explicit order field, otherwise use name 158 if ( term_properties[taxonomy].terms[term_id].hasOwnProperty( 'order' ) ) { 159 sort_term.order = term_properties[taxonomy].terms[term_id].order; 160 } else { 161 sort_term.order = sort_term.name.toLowerCase(); 162 } 163 164 ordered_terms.push( sort_term ); 165 } ); 166 167 ordered_terms.sort( function( a, b ) { 168 return ((a.order < b.order) ? -1 : ((a.order > b.order) ? 1 : 0)); 169 } ); 170 171 return ordered_terms; 172 } 173 174 function createTermLegends() { 175 176 $.each( loaded_terms, function( taxonomy, tax_data ) { 177 var $legend, list_tag, row_tag, term_tag, definition_tag, 178 $element, $title, format, format_match, interactive, 179 add_check_all, $check_all, default_off, 180 element = getWidgetElement( taxonomy, 'legend' ); 181 182 if ( !element ) { 183 return; 184 } 185 $element = $( element ); 186 187 if ( $element.hasClass( 'noninteractive' ) ) { 188 interactive = false; 189 } else if ( typeof GeoMashup.opts.interactive_legend === 'undefined' ) { 190 interactive = true; 191 } else { 192 interactive = GeoMashup.opts.interactive_legend; 193 } 194 195 if ( $element.hasClass( 'check-all-off' ) ) { 196 default_off = false; 197 } else if ( interactive ) { 198 add_check_all = true; 199 } 200 201 if ( $element.hasClass( 'default-off' ) ) { 202 default_off = true; 203 } else { 204 default_off = false; 205 } 206 207 format_match = /format-(\w+)/.exec( $element.attr( 'class' ) ); 208 if ( format_match ) { 209 format = format_match[1]; 210 } else if ( GeoMashup.opts.legend_format ) { 211 format = GeoMashup.opts.legend_format; 212 } else { 213 format = 'table'; 214 } 215 if ( format === 'dl' ) { 216 list_tag = 'dl'; 217 row_tag = ''; 218 term_tag = 'dt'; 219 definition_tag = 'dd'; 220 } else if ( format === 'ul' ) { 221 list_tag = 'ul'; 222 row_tag = 'li'; 223 term_tag = 'span'; 224 definition_tag = 'span'; 225 } else { 226 list_tag = 'table'; 227 row_tag = 'tr'; 228 term_tag = 'td'; 229 definition_tag = 'td'; 230 } 231 232 if ( $element.hasClass( 'titles-on' ) || ( !$element.hasClass( 'titles-off' ) && GeoMashup.opts.include_taxonomies.length > 1 ) ) { 233 234 $title = $( '<h2></h2>' ) 235 .addClass( 'gm-legend-title' ) 236 .addClass( taxonomy + '-legend-title' ) 237 .text( term_properties[taxonomy].label ); 238 /** 239 * A taxonomy legend title is being created 240 * @name GeoMashup#taxonomyLegendTitle 241 * @event 242 * @since 1.5 243 * @param {jQuery} $title Empty legend element with classes 244 * @param {String} taxonomy 245 */ 246 GeoMashup.doAction( 'taxonomyLegendTitle', $title, taxonomy ); 247 248 $element.append( $title ); 249 250 } 251 $legend = $( '<' + list_tag + ' class="gm-legend ' + taxonomy + '" />' ); 252 253 /** 254 * A taxonomy legend is being created 255 * @name GeoMashup#taxonomyLegend 256 * @event 257 * @since 1.5 258 * @param {jQuery} $legend Empty legend element with classes 259 * @param {String} taxonomy 260 */ 261 GeoMashup.doAction( 'taxonomyLegend', $legend, taxonomy ); 262 263 if ( GeoMashup.opts.name && add_check_all ) { 264 265 // Add check/uncheck all 266 $check_all = $( '<label></label>' ) 267 .text( GeoMashup.opts.check_all_label ) 268 .attr( 'for', 'gm-' + taxonomy + '-check-all' ) 269 .prepend( 270 $( '<input type="checkbox" />' ).attr( 'id', 'gm-' + taxonomy + '-check-all' ) 271 .attr( 'checked', ( default_off ? false : 'checked' ) ) 272 .change( function() { 273 if ( $( this ).is( ':checked' ) ) { 274 $legend.find( 'input.gm-' + taxonomy + '-checkbox:not(:checked)' ).click(); 275 } else { 276 $legend.find( 'input.gm-' + taxonomy + '-checkbox:checked' ).click(); 277 } 278 } ) 279 ); 280 if ( row_tag ) { 281 $legend.append( 282 $( '<' + row_tag + '/>' ).append( $( '<' + term_tag + '/>' ) ) 283 .append( $( '<' + definition_tag + '/>' ).append( $check_all ) ) 284 ); 285 } else { 286 $legend.append( $( '<' + term_tag + '/>' ) ).append( $( '<' + definition_tag + '/>' ) 287 .append( $check_all ) ); 288 } 289 } 290 291 $.each( sortTermLegendData( taxonomy, tax_data ), function ( i, sort_term ) { 292 var term_id, id, name, $entry, $key, $def, $label, $checkbox; 293 294 term_id = sort_term.term_id; 295 name = sort_term.name; 296 297 if ( GeoMashup.opts.name && interactive ) { 298 299 id = 'gm-' + taxonomy + '-checkbox-' + term_id; 300 301 $checkbox = $( '<input type="checkbox" name="term_checkbox" />' ) 302 .attr( 'id', id ) 303 .addClass( 'gm-' + taxonomy + '-checkbox' ) 304 .change( function() { 305 GeoMashup.term_manager.setTermVisibility( term_id, taxonomy, $( this ).is( ':checked' ) ); 306 }); 307 308 if ( default_off ) { 309 GeoMashup.term_manager.setTermVisibility( term_id, taxonomy, false ); 310 } else { 311 $checkbox.attr( 'checked', 'checked' ); 312 } 313 314 $label = $( '<label/>' ) 315 .attr( 'for', id ) 316 .text( name ) 317 .prepend( $checkbox ); 318 319 } else { 320 321 $label = $( '<span/>' ).text( name ); 322 323 } 324 325 $key = $( '<' + term_tag + ' class="symbol"/>').append( 326 $( '<img/>' ) 327 .attr( 'src', sort_term.icon.image ) 328 .attr( 'alt', term_id ) 329 .click( function() { 330 // Pass clicks to the checkbox 331 $label.click(); 332 return false; 333 } ) 334 ); 335 336 $def = $( '<' + definition_tag + ' class="term"/>' ).append( $label ); 337 338 /** 339 * A taxonomy legend entry is being created 340 * @name GeoMashup#termLegendEntry 341 * @event 342 * @since 1.5 343 * @param {jQuery} $key Legend key node (td or dt) 344 * @param {jQuery} $def Legend definition node (td or dd) 345 * @param {String} taxonomy 346 * @param {String} term_id 347 */ 348 GeoMashup.doAction( 'taxonomyLegendEntry', $key, $def, taxonomy, term_id ); 349 350 if (row_tag) { 351 352 $entry = $( '<' + row_tag + '/>' ) 353 .addClass( 'term-' + term_id ) 354 .append( $key ) 355 .append( $def ); 356 /** 357 * A taxonomy legend table row is being created 358 * @name GeoMashup#termLegendRow 359 * @event 360 * @since 1.5 361 * @param {jQuery} $entry Table row 362 * @param {String} taxonomy 363 * @param {String} term_id 364 */ 365 GeoMashup.doAction( 'taxonomyLegendRow', $entry, taxonomy, term_id ); 366 367 $legend.append( $entry ); 368 369 } else { 370 371 $legend.append( $key ).append( $def ); 372 373 } 374 375 }); // end each term 376 377 $( element ).append( $legend ); 378 379 } ); 380 } 381 382 term_manager.load = function() { 383 384 term_properties = GeoMashup.opts.term_properties; 385 386 if ( !term_properties ) { 387 return; 388 } 389 390 $.each( term_properties, function( taxonomy ) { 391 buildTermHierarchy( taxonomy ); 392 } ); 393 394 }; 395 396 term_manager.extendTerm = function(point, taxonomy, term_id, object) { 397 var loaded_taxonomy, 398 icon, 399 color_rgb, 400 color_name, 401 max_line_zoom; 402 403 term_id = String( term_id ); 404 405 if ( !loaded_terms.hasOwnProperty( taxonomy ) ) { 406 loaded_terms[taxonomy] = {terms: {}, term_count: 0}; 407 } 408 409 loaded_taxonomy = loaded_terms[taxonomy]; 410 411 if ( !loaded_taxonomy.terms.hasOwnProperty( term_id ) ) { 412 413 if ( term_properties[taxonomy].terms[term_id].color ) { 414 color_name = term_properties[taxonomy].terms[term_id].color; 415 } else { 416 color_name = GeoMashup.color_names[ loaded_taxonomy.term_count % GeoMashup.color_names.length ]; 417 } 418 color_rgb = GeoMashup.colors[color_name]; 419 420 // Back compat callbacks 421 if ( typeof customGeoMashupCategoryIcon === 'function' ) { 422 icon = customGeoMashupCategoryIcon( GeoMashup.opts, [term_id] ); 423 } 424 if ( !icon && typeof customGeoMashupColorIcon === 'function' ) { 425 icon = customGeoMashupColorIcon( GeoMashup.opts, color_name ); 426 } 427 if (!icon) { 428 icon = GeoMashup.colorIcon( color_name ); 429 } 430 431 if ( 'category' === taxonomy ) { 432 /** 433 * A category icon is being assigned. 434 * @name GeoMashup#categoryIcon 435 * @deprecated Use GeoMashup#termIcon 436 * @event 437 * @since 1.5 438 * @param {GeoMashupOptions} properties Geo Mashup configuration data 439 * @param {GeoMashupIcon} icon 440 * @param {String} term_id 441 */ 442 GeoMashup.doAction( 'categoryIcon', GeoMashup.opts, icon, term_id ); 443 } 444 445 /** 446 * A term icon is being assigned. 447 * @name GeoMashup#termIcon 448 * @event 449 * @since 1.5 450 * @param {GeoMashupIcon} icon 451 * @param {String} taxonomy 452 * @param {String} term_id 453 */ 454 GeoMashup.doAction( 'termIcon', icon, taxonomy, term_id ); 455 456 /** 457 * A category icon is being assigned by color. 458 * @name GeoMashup#colorIcon 459 * @event 460 * @since 1.5 461 * @param {GeoMashupOptions} properties Geo Mashup configuration data 462 * @param {GeoMashupIcon} icon 463 * @param {String} color_name 464 */ 465 GeoMashup.doAction( 'colorIcon', GeoMashup.opts, icon, color_name ); 466 467 max_line_zoom = -1; 468 if ( term_properties[taxonomy].terms[term_id].line_zoom ) { 469 max_line_zoom = term_properties[taxonomy].terms[term_id].line_zoom; 470 } 471 472 loaded_taxonomy.terms[term_id] = { 473 icon : icon, 474 points : [point], 475 objects : [object], 476 color : color_rgb, 477 visible : true, 478 max_line_zoom : max_line_zoom 479 }; 480 481 loaded_taxonomy.term_count += 1; 482 483 } else { // taxonomy term exists 484 485 loaded_taxonomy.terms[term_id].points.push( point ); 486 loaded_taxonomy.terms[term_id].objects.push( object ); 487 488 } 489 }; 490 491 /** 492 * Enable more objects to be loaded. 493 * Consider it alpha - probably needs work. 494 * @methodOf GeoMashup 495 * @since 1.5 496 */ 497 term_manager.reset = function() { 498 499 $.each( loaded_terms, function( taxonomy, tax_data ) { 500 $.each( tax_data.terms, function( term_id, term_data ) { 501 term_data.points.length = 0; 502 if ( term_data.line ) { 503 GeoMashup.hideLine( term_data.line ); 504 } 505 } ); 506 } ); 507 508 }; 509 510 /** 511 * Get a property of a loaded term. 512 * @methodOf GeoMashup 513 * @since 1.5 514 * @param taxonomy 515 * @param term_id 516 * @param property Property name 517 * @returns {*} Property value 518 */ 519 term_manager.getTermData = function( taxonomy, term_id, property ) { 520 return loaded_terms[taxonomy].terms[term_id][property]; 521 }; 522 523 /** 524 * Find a term in a hierarchy. 525 * 526 * @methodOf GeoMashup 527 * @since 1.5 528 * @param search_id 529 * @param {object|string} hierarchy Optional hierarchy structure or taxonomy name, defaults to 'category'. 530 * @returns {object} Hierarchy tree rooted at the search term or null if not found. 531 */ 532 term_manager.searchTermHierarchy = function( search_id, hierarchy ) { 533 var child_search, term_id; 534 535 if ( !hierarchy ) { 536 hierarchy = hierarchies.category; 537 } else if ( typeof hierarchy === 'string' ) { 538 hierarchy = hierarchies[hierarchy]; 539 } 540 // Use a regular loop, so it can return a value for this function 541 for( term_id in hierarchy ) { 542 if ( hierarchy.hasOwnProperty( term_id ) && typeof hierarchy[term_id] !== 'function' ) { 543 if ( term_id === search_id ) { 544 return hierarchy[term_id]; 545 } else if ( hierarchy[term_id] ) { 546 child_search = term_manager.searchTermHierarchy( search_id, hierarchy[term_id] ); 547 if (child_search) { 548 return child_search; 549 } 550 } 551 } 552 } 553 return null; 554 }; 555 556 term_manager.populateTermElements = function() { 557 558 createTermLines(); 559 createTermLegends(); 560 // The tabbed index may hide markers, so it's created last 561 term_manager.tabbed_index.create(); 562 563 }; 564 565 /** 566 * The tabbed index control object. 567 * @memberOf GeoMashup 568 * @since 1.5 569 */ 570 term_manager.tabbed_index = (function() { 571 var tabbed_index = {}, 572 tab_term_ids = [], 573 tab_hierarchy, 574 tab_index_group_size, 575 show_inactive_tab_markers, 576 $index; 577 578 function hasLocatedChildren( term_id, taxonomy, hierarchy ) { 579 var child_id; 580 581 if ( loaded_terms[taxonomy].terms[term_id] ) { 582 return true; 583 } 584 585 for ( child_id in hierarchy ) { 586 if ( hierarchy.hasOwnProperty( child_id ) && hasLocatedChildren( child_id, taxonomy, hierarchy[child_id] ) ) { 587 return true; 588 } 589 } 590 return false; 591 } 592 593 function buildTermIndex( term_id, taxonomy, children, top_level) { 594 var $term_index, $list, $sub_list, group_count, 595 // Back compat tax name 596 tax = taxonomy.replace( 'category', 'cat' ); 597 598 if ( typeof top_level === 'undefined' ) { 599 top_level = true; 600 } 601 602 $term_index = $( '<div></div>' ) 603 .attr( 'id', tabbed_index.getTermIndexId( term_id, taxonomy ) ) 604 .addClass( 'gm-tabs-panel' ) 605 .addClass( 'gm-tabs-panel-' + term_id ); 606 if ( top_level ) { 607 $term_index.addClass( 'gm-hidden' ); 608 } 609 610 $list = $( '<ul></ul>' ).addClass( 'gm-index-posts' ); 611 612 if ( loaded_terms[taxonomy].terms[term_id] ) { 613 614 loaded_terms[taxonomy].terms[term_id].objects.sort( function( a, b ) { 615 var a_name = a.title, 616 b_name = b.title; 617 618 if (a_name === b_name) { 619 return 0; 620 } else { 621 return a_name < b_name ? -1 : 1; 622 } 623 }); 624 625 $.each( loaded_terms[taxonomy].terms[term_id].objects, function( i, object ) { 626 $list.append( 627 $( '<li></li>' ).append( 628 $( '<a></a>' ) 629 .attr( 'href', '#' + GeoMashup.opts.name ) 630 .text( object.title ) 631 .click( function() { 632 GeoMashup.clickObjectMarker( object.object_id ); 633 }) 634 ) 635 ); 636 }); 637 } 638 639 if ( children ) { 640 641 group_count = 0; 642 $sub_list = $( '<ul></ul>' ).addClass( 'gm-sub-' + tax + '-index'); 643 644 $.each( children, function( child_id, grandchildren ) { 645 var $li = $( '<li></li>' ), 646 loaded_term = loaded_terms[taxonomy].terms[child_id]; 647 648 if ( loaded_term ) { 649 $li.append( $( '<img />' ).attr( 'src', loaded_term.icon.image ) ) 650 .append( $( '<span></span>' ).addClass( 'gm-sub-' + tax + '-title' ).text( loaded_term.name ) ); 651 } 652 653 $li.append( buildTermIndex( child_id, taxonomy, grandchildren, false ) ); 654 655 group_count += 1; 656 if ( tab_index_group_size && group_count%tab_index_group_size === 0) { 657 $list.append( $sub_list ); 658 $sub_list = $( '<ul></ul>' ).addClass( 'gm-sub-' + tax + '-index'); 659 } 660 }); 661 $list.append( $sub_list ); 662 663 } 664 665 $term_index.append( $list ); 666 667 return $term_index; 668 } 669 670 function buildTabbedIndex( hierarchy, taxonomy ) { 671 var $list; 672 673 $index = $( '<div></div>' ).attr( 'id', GeoMashup.opts.name + '-tab-index' ); 674 $list = $( '<ul class="gm-tabs-nav"></ul>' ); 675 676 $.each( hierarchy, function( term_id, children ) { 677 if ( hasLocatedChildren( term_id, taxonomy, children ) ) { 678 tab_term_ids.push( term_id ); 679 } 680 } ); 681 682 tab_term_ids.sort( function( a, b ) { 683 var a_name = term_properties[taxonomy].terms[a].name, 684 b_name = term_properties[taxonomy].terms[b].name; 685 686 if ( a_name === b_name ) { 687 return 0; 688 } else { 689 return a_name < b_name ? -1 : 1; 690 } 691 } ); 692 693 $.each( tab_term_ids, function( i, term_id ) { 694 var children = hierarchy[term_id], 695 $li = $( '<li></li>' ).addClass( 'gm-tab-inactive' ).addClass( 'gm-tab-inactive-' + term_id ), 696 $a = $( '<a></a>' ).attr( 'href', '#' + GeoMashup.opts.name ).click( function() { 697 tabbed_index.selectTab( term_id, taxonomy ); 698 return false; 699 }); 700 701 if ( loaded_terms[taxonomy] && loaded_terms[taxonomy].terms[term_id] ) { 702 $a.append( $( '<img />' ).attr( 'src', loaded_terms[taxonomy].terms[term_id].icon.image ) ); 703 } 704 $a.append( $( '<span></span>' ).text( term_properties[taxonomy].terms[term_id].name ) ); 705 $li.append( $a ); 706 $list.append( $li ); 707 708 if ( !show_inactive_tab_markers ) { 709 term_manager.setHierarchyVisibility( term_id, children, taxonomy, false ); 710 } 711 }); 712 713 $index.append( $list ); 714 715 $.each( hierarchy, function( term_id, children ) { 716 $index.append( buildTermIndex( term_id, taxonomy, children ) ); 717 }); 718 719 return $index; 720 } 721 722 /** 723 * Get the DOM id of term index element 724 * @since 1.5 725 * @methodOf GeoMashup.term_manager 726 * @param term_id 727 * @param taxonomy 728 * @returns {string} 729 */ 730 tabbed_index.getTermIndexId = function( term_id, taxonomy ) { 731 var tax = taxonomy.replace( 'category', 'cat' ); 732 return 'gm-' + tax + '-index-' + term_id; 733 }; 734 735 tabbed_index.create = function() { 736 var start_tab_term_id, start_tab_term_id_match, group_size_match, taxonomy, 737 disable_tab_auto_select = false, 738 $element = []; 739 740 // Determine a taxonomy to use 741 $.each( loaded_terms, function( check_taxonomy ) { 742 var element = getWidgetElement( check_taxonomy, 'tabbed-index' ); 743 if ( element ) { 744 taxonomy = check_taxonomy; 745 $element = $( element ); 746 return true; // break 747 } 748 } ); 749 if ( $element.length === 0 ) { 750 return; 751 } 752 tab_hierarchy = hierarchies[taxonomy]; 753 754 start_tab_term_id_match = /start-tab-term-(\d+)/.exec( $element.attr( 'class' ) ); 755 if ( start_tab_term_id_match ) { 756 start_tab_term_id = start_tab_term_id_match[1]; 757 } else if ( 'category' === taxonomy ) { 758 start_tab_term_id = GeoMashup.opts.start_tab_category_id; 759 } 760 761 group_size_match = /tab-index-group-size-(\d+)/.exec( $element.attr( 'class' ) ); 762 if ( group_size_match ) { 763 tab_index_group_size = group_size_match[1]; 764 } else { 765 tab_index_group_size = GeoMashup.opts.tab_index_group_size; 766 } 767 768 if ( $element.hasClass( 'show-inactive-tab-markers' ) ) { 769 show_inactive_tab_markers = true; 770 } else { 771 show_inactive_tab_markers = GeoMashup.opts.show_inactive_tab_markers; 772 } 773 774 if ( $element.hasClass( 'disable-tab-auto-select' ) ) { 775 disable_tab_auto_select = true; 776 } else if ( 'category' === taxonomy ) { 777 disable_tab_auto_select = GeoMashup.opts.disable_tab_auto_select; 778 } 779 780 if ( start_tab_term_id ) { 781 tab_hierarchy = term_manager.searchTermHierarchy( start_tab_term_id, tab_hierarchy ); 782 } 783 784 $element.append( buildTabbedIndex( tab_hierarchy, taxonomy ) ); 785 786 if ( !disable_tab_auto_select ) { 787 // Select the first tab 788 $.each( tab_term_ids, function( i, term_id ) { 789 if ( hasLocatedChildren( term_id, taxonomy, tab_hierarchy ) ) { 790 tabbed_index.selectTab( term_id, taxonomy ); 791 return false; 792 } 793 }); 794 } 795 }; 796 797 /** 798 * Make a term tab active. 799 * @methodOf GeoMashup.term_manager 800 * @since 1.5 801 * @param term_id 802 * @param taxonomy 803 * @returns {boolean} success 804 */ 805 tabbed_index.selectTab = function( term_id, taxonomy ) { 806 var $active_tab, hide_term_classes, hide_term_match, hide_term_id; 807 808 if ( !$index ) { 809 return false; 810 } 811 812 if ( $index.find( '.gm-tab-active-' + term_id ).length > 0 ) { 813 // Requested tab is already selected 814 return true; 815 } 816 817 $active_tab = $index.find( '.gm-tabs-nav .gm-tab-active' ); 818 if ( $active_tab.length > 0 ) { 819 hide_term_match = /gm-tab-active-(\d+)/.exec( $active_tab.attr( 'class' ) ); 820 if ( hide_term_match ) { 821 hide_term_id = hide_term_match[1]; 822 $active_tab.attr( 'class', 'gm-tab-inactive gm-tab-inactive-' + hide_term_id ); 823 } 824 } 825 $index.find( '.gm-tabs-nav .gm-tab-inactive-' + term_id ) 826 .attr( 'class', 'gm-tab-active gm-tab-active-' + term_id ); 827 828 // Hide previous active panel 829 $index.find( '.gm-tabs-panel.gm-active' ) 830 .removeClass( 'gm-active' ) 831 .addClass( 'gm-hidden' ); 832 833 // Show selected panel 834 $index.find( '.gm-tabs-panel-' + term_id ).removeClass( 'gm-hidden' ).addClass( 'gm-active' ); 835 836 if ( !show_inactive_tab_markers ) { 837 // Hide previous active markers 838 if ( hide_term_id ) { 839 term_manager.setHierarchyVisibility( hide_term_id, tab_hierarchy[hide_term_id], taxonomy, false ); 840 } 841 // Show selected markers second so none get re-hidden 842 term_manager.setHierarchyVisibility( term_id, tab_hierarchy[term_id], taxonomy, true ); 843 } 844 845 }; 846 847 return tabbed_index; 848 }()); 849 850 /** 851 * Show or hide a term. 852 * @methodOf GeoMashup 853 * @since 1.5 854 * @param term_id 855 * @param taxonomy 856 * @param visible 857 * @returns {boolean} Whether visibility was set. 858 */ 859 term_manager.setTermVisibility = function( term_id, taxonomy, visible ) { 860 var term_data; 861 862 if ( !loaded_terms[taxonomy] || !loaded_terms[taxonomy].terms[term_id] ) { 863 return false; 864 } 865 866 term_data = loaded_terms[taxonomy].terms[term_id]; 867 868 if ( GeoMashup.map.closeInfoWindow ) { 869 GeoMashup.map.closeInfoWindow(); 870 } 871 872 if ( term_data.line ) { 873 if ( visible && GeoMashup.map.getZoom() <= term_data.max_line_zoom ) { 874 GeoMashup.showLine( term_data.line ); 875 } else { 876 GeoMashup.hideLine( term_data.line ); 877 } 878 } 879 880 // Check for other visible terms at this location 881 loaded_terms[taxonomy].terms[term_id].visible = visible; 882 883 $.each( loaded_terms[taxonomy].terms[term_id].points, function( i, point ) { 884 GeoMashup.updateMarkerVisibility( GeoMashup.locations[point].marker ); 885 }); 886 887 GeoMashup.recluster(); 888 GeoMashup.updateVisibleList(); 889 890 return true; 891 }; 892 893 /** 894 * Get the display name of a term. 895 * @methodOf GeoMashup 896 * @since 1.5 897 * 898 * @param taxonomy 899 * @param term_id 900 * @returns {String} The term name. 901 */ 902 term_manager.getTermName = function( taxonomy, term_id ) { 903 return term_properties[taxonomy].terms[term_id].name; 904 }; 905 906 /** 907 * Determine whether a term ID is an ancestor of another. 908 * 909 * Works on the loadedMap action and after, when the term hierarchy has been 910 * determined. 911 * 912 * @methodOf GeoMashup 913 * @since 1.5 914 * @param {String} ancestor_id The term ID of the potential ancestor 915 * @param {String} child_id The term ID of the potential child 916 * @param {String} taxonomy The taxonomy of the terms. 917 * @returns {boolean} 918 */ 919 term_manager.isTermAncestor = function( ancestor_id, child_id, taxonomy ) { 920 921 if ( !term_properties[taxonomy] ) { 922 return false; 923 } 924 925 ancestor_id = ancestor_id.toString(); 926 child_id = child_id.toString(); 927 928 if ( term_properties[taxonomy].terms[child_id].parent_id ) { 929 if ( term_properties[taxonomy].terms[child_id].parent_id === ancestor_id ) { 930 return true; 931 } else { 932 return term_manager.isTermAncestor( ancestor_id, term_properties[taxonomy].terms[child_id].parent_id, taxonomy ); 933 } 934 } else { 935 return false; 936 } 937 }; 938 939 /** 940 * Show or hide category lines according to their max_line_zoom setting. 941 * 942 * @methodOf GeoMashup 943 * @since 1.5 944 * 945 * @param {number} old_zoom Previous zoom level. 946 * @param {number} new_zoom New zoom level. 947 */ 948 term_manager.updateLineZoom = function( old_zoom, new_zoom ) { 949 950 $.each( loaded_terms, function( taxonomy, tax_data ) { 951 952 $.each( tax_data.terms, function( term_id, term_data ) { 953 954 if ( term_data.visible && term_data.line ) { 955 956 if ( old_zoom <= term_data.max_line_zoom && new_zoom > term_data.max_line_zoom ) { 957 958 GeoMashup.hideLine( term_data.line ); 959 960 } else if ( old_zoom > term_data.max_line_zoom && new_zoom <= term_data.max_line_zoom ) { 961 962 GeoMashup.showLine( term_data.line ); 963 964 } 965 } 966 967 }); 968 969 }); 970 971 }; 972 973 /** 974 * Show or hide a tree of terms. 975 * @methodOf GeoMashup 976 * @since 1.5 977 * 978 * @param term_id 979 * @param hierarchy The term hierarchy ID tree. 980 * @param taxonomy 981 * @param visible 982 */ 983 term_manager.setHierarchyVisibility = function( term_id, hierarchy, taxonomy, visible ) { 984 985 term_manager.setTermVisibility( term_id, taxonomy, visible ); 986 987 hierarchy = hierarchy || {}; 988 $.each( hierarchy, function( child_id, grandchildren ) { 989 term_manager.setHierarchyVisibility( child_id, grandchildren, taxonomy, visible ); 990 } ); 991 }; 992 993 return term_manager; 994 }()), 995 996 /** 997 * Determine whether a category ID is an ancestor of another. 998 * 999 * Works on the loadedMap action and after, when the category hierarchy has been 1000 * determined. 1001 * 1002 * @methodOf GeoMashup 1003 * @deprecated 1.5 1004 * @see GeoMashup.term_manager.isTermAncestor() 1005 * 1006 * @param {String} ancestor_id The category ID of the potential ancestor 1007 * @param {String} child_id The category ID of the potential child 1008 */ 1009 isCategoryAncestor : function(ancestor_id, child_id) { 1010 return this.term_manager.isTermAncestor( ancestor_id, child_id, 'category' ); 1011 }, 1012 1013 /** 1014 * Hide markers and line for a category. 1015 * @methodOf GeoMashup 1016 * @deprecated 1.5 1017 * @see GeoMashup.term_manager.setTermVisibility() 1018 * @param {String} category_id 1019 */ 1020 hideCategory : function(category_id) { 1021 GeoMashup.term_manager.setTermVisibility( category_id, 'category', false ); 1022 }, 1023 1024 /** 1025 * Show markers for a category. Also show line if consistent with configuration. 1026 * @methodOf GeoMashup 1027 * @deprecated 1.5 1028 * @see GeoMashup.term_manager.setTermVisibility() 1029 * @param {String} category_id 1030 */ 1031 showCategory : function(category_id) { 1032 GeoMashup.term_manager.setTermVisibility( category_id, 'category', true ); 1033 }, 1034 1035 /** 1036 * Hide a category and all its child categories. 1037 * @methodOf GeoMashup 1038 * @deprecated 1.5 1039 * @see GeoMashup.term_manager.searchTermHierarchy() 1040 * @see GeoMashup.term_manager.setHierarchyVisibility() 1041 * @param {String} category_id The ID of the category to hide 1042 */ 1043 hideCategoryHierarchy : function(category_id) { 1044 var hierarchy = GeoMashup.term_manager.searchTermHierarchy( category_id, 'category' ); 1045 GeoMashup.term_manager.setHierarchyVisibility( category_id, hierarchy, 'category', false ); 1046 }, 1047 1048 /** 1049 * Show a category and all its child categories. 1050 * @methodof GeoMashup 1051 * @deprecated 1.5 1052 * @see GeoMashup.term_manager.searchTermHierarchy() 1053 * @see GeoMashup.term_manager.setHierarchyVisibility() 1054 * @param {String} category_id The ID of the category to show 1055 */ 1056 showCategoryHierarchy : function(category_id) { 1057 var hierarchy = GeoMashup.term_manager.searchTermHierarchy( category_id, 'category' ); 1058 GeoMashup.term_manager.setHierarchyVisibility( category_id, hierarchy, 'category', true ); 1059 }, 1060 1061 /** 1062 * Select a tab of the tabbed category index control. 1063 * @methodOf GeoMashup 1064 * @deprecated 1.5 1065 * @see GeoMashup.term_manager.tabbed_index.selectTab() 1066 * @param {String} select_category_id The ID of the category tab to select 1067 */ 1068 categoryTabSelect : function(select_category_id) { 1069 this.term_manager.tabbed_index.selectTab( select_category_id, 'category' ); 1070 }, 1071 1072 /** 1073 * Get the DOM ID of the element containing a category index in the 1074 * tabbed category index control. 1075 * @methodOf GeoMashup 1076 * @deprecated 1.5 1077 * @see GeoMashup.term_manager.tabbed_index.getTermIndexId() 1078 * @param {String} category_id The category ID 1079 * @return {String} DOM ID 1080 */ 1081 categoryIndexId : function(category_id) { 1082 return 'gm-cat-index-' + category_id; 1083 }, 1084 1085 createTermLine: function( term_data ) { 1086 //provider override 1087 } 1088 1089 } ); 1090 1091