1/* global job_manager_ajax_filters */ 2jQuery( document ).ready( function( $ ) { 3 var session_storage_prefix = 'job_listing_'; 4 5 /** 6 * Check if we should maintain the state. 7 */ 8 function is_state_storage_enabled( $target ) { 9 if ( ! supports_html5_session_storage() ) { 10 return false; 11 } 12 13 // Check to see if it is globally disabled. 14 if ( $( document.body ).hasClass( 'disable-job-manager-form-state-storage' ) ) { 15 return false; 16 } 17 18 // Check if it is disabled on this specific element. 19 if ( $target.data( 'disable-form-state-storage' ) ) { 20 return false; 21 } 22 23 return true; 24 } 25 26 /** 27 * Check if the sessionStorage object is available. 28 */ 29 function supports_html5_session_storage() { 30 return window.sessionStorage && typeof window.sessionStorage.setItem === 'function'; 31 } 32 33 /** 34 * Get the session storage key for the job listings instance. 35 */ 36 function get_session_storage_key( $target ) { 37 var index = $( 'div.job_listings' ).index( $target ); 38 var unique_page_id = $target.data( 'post_id' ); 39 40 if ( typeof unique_page_id === 'undefined' || ! unique_page_id ) { 41 unique_page_id = window.location.href.replace( location.hash, '' ); 42 } 43 44 return session_storage_prefix + unique_page_id + '_' + index; 45 } 46 47 /** 48 * Store the filter form values and possibly the rendered results in sessionStorage. 49 */ 50 function store_state( $target, state ) { 51 if ( ! is_state_storage_enabled( $target ) ) { 52 return false; 53 } 54 55 if ( typeof state !== 'object' ) { 56 state = {}; 57 } 58 59 var session_storage_key = get_session_storage_key( $target ); 60 61 try { 62 return window.sessionStorage.setItem( session_storage_key, JSON.stringify( state ) ); 63 } catch ( e ) { 64 // If the usage is full or the browser has denied us access, continue gracefully. 65 } 66 67 return false; 68 } 69 70 /** 71 * Retrieve the stored form values and maybe the rendered results from sessionStorage. 72 */ 73 function get_state( $target ) { 74 if ( ! is_state_storage_enabled( $target ) ) { 75 return false; 76 } 77 78 var session_storage_key = get_session_storage_key( $target ); 79 80 try { 81 var state = window.sessionStorage.getItem( session_storage_key ); 82 if ( state ) { 83 return JSON.parse( state ); 84 } 85 } catch ( e ) { 86 // If the browser has denied us access, continue gracefully as if there wasn't any stored state. 87 } 88 89 return false; 90 } 91 92 /** 93 * Toggle the `persist_results` boolean based on whether we not the rendered results to persist when moving away from page. 94 */ 95 function persist_results( $target, persist ) { 96 if ( ! is_state_storage_enabled( $target ) || ! $target ) { 97 return false; 98 } 99 100 var state = get_state( $target ); 101 if ( ! state ) { 102 return false; 103 } 104 105 state.persist_results = persist; 106 107 return store_state( $target, state ); 108 } 109 110 /** 111 * Persist the state of the form. 112 */ 113 function persist_form( $target ) { 114 if ( ! is_state_storage_enabled( $target ) || ! $target ) { 115 return false; 116 } 117 118 var state = get_state( $target ); 119 if ( ! state ) { 120 return false; 121 } 122 123 var $form = $target.find( '.job_filters' ); 124 state.form = $form.serialize(); 125 126 return store_state( $target, state ); 127 } 128 129 /** 130 * Store the rendered results with the state in sessionStorage. 131 */ 132 function save_results( $target, results ) { 133 if ( ! is_state_storage_enabled( $target ) ) { 134 return false; 135 } 136 137 var state = get_state( $target ); 138 if ( ! state ) { 139 state = { 140 persist_results: false 141 }; 142 } 143 144 var $results = $target.find( '.job_listings' ); 145 146 // Cache all loaded $results. 147 results.html = $results.html(); 148 149 state.results = results; 150 151 return store_state( $target, state ); 152 } 153 154 /** 155 * Clear the stored state of the form values and possibly the rendered results from sessionStorage. 156 */ 157 function clear_state( $target ) { 158 if ( ! is_state_storage_enabled( $target ) ) { 159 return false; 160 } 161 162 var session_storage_key = get_session_storage_key( $target ); 163 164 try { 165 window.sessionStorage.removeItem( session_storage_key ); 166 } catch ( e ) { 167 return false; 168 } 169 170 return true; 171 } 172 173 /** 174 * Clear the rendered results from the stored state in sessionStorage. 175 */ 176 function clear_results( $target ) { 177 if ( ! is_state_storage_enabled( $target ) ) { 178 return false;
179 } 180 181 var state = get_state( $target ); 182 if ( ! state ) { 183 state = {}; 184 } 185 186 state.results = null; 187 188 return store_state( $target, state ); 189 } 190 191 /** 192 * Clear the form from the stored state in sessionStorage. 193 */ 194 function clear_form( $target ) { 195 if ( ! is_state_storage_enabled( $target ) ) { 196 return false; 197 } 198 199 var state = get_state( $target ); 200 if ( ! state ) { 201 state = {}; 202 } 203 204 state.form = null; 205 206 return store_state( $target, state ); 207 } 208 209 /** 210 * Handle restoring the results from sessionStorage or the Ajax call. 211 */ 212 function handle_result( $target, result, append ) { 213 var $results = $target.find( '.job_listings' ); 214 var $showing = $target.find( '.showing_jobs' ); 215 216 if ( typeof append !== 'boolean' ) { 217 append = false; 218 } 219 220 if ( typeof result.showing === 'string' && result.showing ) { 221 var $showing_el = jQuery( '<span>' ).html( result.showing ); 222 $showing 223 .show() 224 .html( '' ) 225 .html( result.showing_links ) 226 .prepend( $showing_el ); 227 } else { 228 $showing.hide(); 229 } 230 231 if ( result.showing_all ) { 232 $showing.addClass( 'wp-job-manager-showing-all' ); 233 } else { 234 $showing.removeClass( 'wp-job-manager-showing-all' ); 235 } 236 237 if ( result.html ) { 238 if ( append ) { 239 $results.append( result.html ); 240 } else { 241 $results.html( result.html ); 242 } 243 } 244 245 if ( true === $target.data( 'show_pagination' ) ) { 246 $target.find( '.job-manager-pagination' ).remove(); 247 248 if ( result.pagination ) { 249 $target.append( result.pagination ); 250 } 251 } else { 252 if ( ! result.found_jobs || result.max_num_pages <= result.data.page ) { 253 $( '.load_more_jobs:not(.load_previous)', $target ).hide(); 254 } else { 255 $( '.load_more_jobs', $target ).show(); 256 } 257 $( '.load_more_jobs', $target ) 258 .removeClass( 'loading' ) 259 .data( 'page', result.data.page ); 260 $( 'li.job_listing', $results ).css( 'visibility', 'visible' ); 261 } 262 263 return true; 264 } 265 266 // Preserve form when not refreshing page. 267 $(document).on( 'click', 'a', function() { 268 // We're moving away to another page. Let's make sure the form persist. 269 $( 'div.job_listings' ).each( function() { 270 persist_form( $( this ) ); 271 } ); 272 } ); 273 274 $(document).on( 'submit', 'form', function() { 275 // We're moving away from current page from another form. Let's make sure the form persist. 276 $( 'div.job_listings' ).each( function() { 277 persist_form( $( this ) ); 278 } ); 279 280 } ); 281 282 var xhr = []; 283 $( 'div.job_listings' ) 284 .on( 'click', 'li.job_listing a', function() { 285 var $target = $( this ).closest( 'div.job_listings' ); 286 287 // We're moving away to a job listing. Let's make sure the results persist. 288 persist_results( $target, true ); 289 } ) 290 .on( 'click', '.job-manager-pagination a', function() { 291 var $target = $( this ).closest( 'div.job_listings' ); 292 var page = $( this ).data( 'page' ); 293 294 $target.triggerHandler( 'update_results', [ page, false ] ); 295 296 $( 'body, html' ).animate( 297 { 298 scrollTop: $target.offset().top, 299 }, 300 600 301 ); 302 303 return false; 304 } ) 305 .on( 'update_results', function( event, page, append ) { 306 var data = ''; 307 var $target = $( this ); 308 var $form = $target.find( '.job_filters' ); 309 var $results = $target.find( '.job_listings' ); 310 var per_page = $target.data( 'per_page' ); 311 var orderby = $target.data( 'orderby' ); 312 var order = $target.data( 'order' ); 313 var featured = $target.data( 'featured' ); 314 var filled = $target.data( 'filled' ); 315 var job_types = $target.data( 'job_types' ); 316 var post_status = $target.data( 'post_status' ); 317 var index = $( 'div.job_listings' ).index( this ); 318 var categories, keywords, location; 319 320 if ( index < 0 ) { 321 return; 322 } 323 324 clear_state( $target ); 325 326 if ( xhr[ index ] ) { 327 xhr[ index ].abort(); 328 } 329 330 if ( ! append || 1 === page ) { 331 $( 'li.job_listing, li.no_job_listings_found', $results ).css( 'visibility', 'hidden' ); 332 $results.addClass('loading'); 333 } 334 335 $target.find( '.load_more_jobs' ).data( 'page', page ); 336 337 if ( true === $target.data( 'show_filters' ) ) { 338 var filter_job_type = []; 339 340 $( 341 ':input[name="filter_job_type[]"]:checked, :input[name="filter_job_type[]"][type="hidden"], :input[name="filter_job_type"]', 342 $form 343 ).each( function() {
344 filter_job_type.push( $( this ).val() ); 345 } ); 346 347 categories = $form 348 .find( ':input[name^="search_categories"]' ) 349 .map( function() { 350 return $( this ).val(); 351 } ) 352 .get(); 353 354 keywords = ''; 355 location = ''; 356 var $keywords = $form.find( ':input[name="search_keywords"]' ); 357 var $location = $form.find( ':input[name="search_location"]' ); 358 359 // Workaround placeholder scripts 360 if ( $keywords.val() !== $keywords.attr( 'placeholder' ) ) { 361 keywords = $keywords.val(); 362 } 363 364 if ( $location.val() !== $location.attr( 'placeholder' ) ) { 365 location = $location.val(); 366 } 367 368 data = { 369 // lang: job_manager_ajax_filters.lang, 370 customlang: job_manager_ajax_filters.lang, 371 search_keywords: keywords, 372 search_location: location, 373 search_categories: categories, 374 filter_job_type: filter_job_type, 375 filter_post_status: post_status, 376 per_page: per_page, 377 orderby: orderby, 378 order: order, 379 page: page, 380 featured: featured, 381 filled: filled, 382 show_pagination: $target.data( 'show_pagination' ), 383 form_data: $form.serialize(), 384 }; 385 } else { 386 categories = $target.data( 'categories' ); 387 keywords = $target.data( 'keywords' ); 388 location = $target.data( 'location' ); 389 390 if ( categories ) { 391 if ( typeof categories !== 'string' ) { 392 categories = String( categories ); 393 } 394 categories = categories.split( ',' ); 395 } 396 397 data = { 398 // lang: job_manager_ajax_filters.lang, 399 customlang: job_manager_ajax_filters.lang, 400 search_categories: categories, 401 search_keywords: keywords, 402 search_location: location, 403 filter_post_status: post_status, 404 filter_job_type: job_types, 405 per_page: per_page, 406 orderby: orderby, 407 order: order, 408 page: page, 409 featured: featured, 410 filled: filled, 411 show_pagination: $target.data( 'show_pagination' ), 412 }; 413 } 414 415 xhr[ index ] = $.ajax( { 416 type: 'POST', 417 url: job_manager_ajax_filters.ajax_url.toString().replace( '%%endpoint%%', 'get_listings' ), 418 data: data, 419 success: function( result ) { 420 if ( result ) { 421 try { 422 result.data = data; 423 424 handle_result( $target, result, append ); 425 426 $results.removeClass( 'loading' ); 427 $target.triggerHandler( 'updated_results', result ); 428 429 save_results( $target, result ); 430 } catch ( err ) { 431 if ( window.console ) { 432 window.console.log( err ); 433 } 434 } 435 } 436 }, 437 error: function( jqXHR, textStatus, error ) { 438 if ( window.console && 'abort' !== textStatus ) { 439 window.console.log( textStatus + ': ' + error ); 440 } 441 }, 442 statusCode: { 443 404: function() { 444 if ( window.console ) { 445 window.console.log( 446 'Error 404: Ajax Endpoint cannot be reached. Go to Settings > Permalinks and save to resolve....' 447 ); 448 } 449 }, 450 }, 451 } ); 452 } ); 453 454 $( 455 '#search_keywords, #search_location, .job_types :input, #search_categories, .job-manager-filter' 456 ) 457 .change( function() { 458 var $target = $( this ).closest( 'div.job_listings' ); 459 $target.triggerHandler( 'update_results', [ 1, false ] ); 460 store_state( $target ); 461 } ) 462 .on( 'keyup', function( e ) { 463 if ( e.which === 13 ) { 464 $( this ).trigger( 'change' ); 465 } 466 } ); 467 468 $( '.job_filters' ) 469 .on( 'click', '.reset', function() { 470 var $target = $( this ).closest( 'div.job_listings' ); 471 var $form = $( this ).closest( 'form' ); 472 473 $form 474 .find( 475 ':input[name="search_keywords"], :input[name="search_location"], .job-manager-filter' 476 ) 477 .not( ':input[type="hidden"]' ) 478 .val( '' ) 479 .trigger( 'change.select2' ); 480 $form 481 .find( ':input[name^="search_categories"]' ) 482 .not( ':input[type="hidden"]' ) 483 .val( '' ) 484 .trigger( 'change.select2' ); 485 $( ':input[name="filter_job_type[]"]', $form ) 486 .not( ':input[type="hidden"]' ) 487 .attr( 'checked', 'checked' ); 488 489 $target.triggerHandler( 'reset' ); 490 $target.triggerHandler( 'update_results', [ 1, false ] ); 491 store_state( $target ); 492 493 return false; 494 } ) 495 .on( 'submit', function() { 496 return false;
497 } ); 498 499 $( document.body ).on( 'click', '.load_more_jobs', function() { 500 var $target = $( this ).closest( 'div.job_listings' ); 501 var page = parseInt( $( this ).data( 'page' ) || 1, 10 ); 502 503 $( this ).addClass( 'loading' ); 504 505 page = page + 1; 506 $( this ).data( 'page', page ); 507 508 $target.triggerHandler( 'update_results', [ page, true ] ); 509 return false; 510 } ); 511 512 if ( $.isFunction( $.fn.select2 ) && typeof job_manager_select2_args !== 'undefined' ) { 513 var select2_args = job_manager_select2_args; 514 select2_args[ 'allowClear' ] = true; 515 select2_args[ 'minimumResultsForSearch' ] = 10; 516 517 $( 'select[name^="search_categories"]:visible' ).select2( select2_args ); 518 } 519 520 // Initial job and $form population 521 $( window ).on( 'load', function() { 522 $( 'div.job_listings' ).each( function() { 523 var $target = $( this ); 524 var $form = $target.find( '.job_filters' ); 525 var results_loaded = false; 526 var state = get_state( $target ); 527 528 if ( state ) { 529 // Restore the results from cache. 530 if ( state.results ) { 531 results_loaded = handle_result( $target, state.results ); 532 533 // We don't want this to continue to persist unless we click on another link. 534 persist_results( $target, false ); 535 clear_form( $target ); 536 } 537 538 // Restore the form state. 539 if ( typeof state.form === 'string' && '' !== state.form ) { 540 // When deserializing a form, we need to first uncheck the checkboxes that are by default checked. 541 $form.find('input[type=checkbox]').prop('checked', false); 542 $form.deserialize(state.form); 543 $form 544 .find(':input[name^="search_categories"]') 545 .not(':input[type="hidden"]') 546 .trigger('change.select2'); 547 } 548 } 549 550 if ( ! results_loaded && $form.length > 0 ) { 551 // If we didn't load results from cache, load page 1. 552 $target.triggerHandler( 'update_results', [ 1, false ] ); 553 } 554 } ); 555 } ); 556 557 $( window ).on( 'unload', function() { 558 $( 'div.job_listings' ).each( function() { 559 var state = get_state( $( this ) ); 560 if ( state && ! state.persist_results ) { 561 clear_results( $( this ) ); 562 } 563 } ); 564 565 return true; 566 } ); 567} );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.