1/////////////////////////////////////////// 2// utility functions 3/////////////////////////////////////////// 4 5function console_log( msg ) 6{ 7 if( ( window['console'] !== undefined ) ) 8 console.log( msg ); 9} 10 11function is_touch_device() 12{ 13 return 'ontouchstart' in window // works on most browsers 14 || 'onmsgesturechange' in window; // works on ie10 15} 16 17function wkd_set_cookie(name, value, days) 18{ 19 if (days) { 20 var date = new Date(); 21 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 22 var expires = "; expires=" + date.toGMTString(); 23 } else var expires = ""; 24 document.cookie = escape(name) + "=" + escape(value) + expires + "; path=/"; 25} 26 27function wkd_get_cookie(name) 28{ 29 var nameEQ = escape(name) + "="; 30 var ca = document.cookie.split(';'); 31 for (var i = 0; i < ca.length; i++) 32 { 33 var c = ca[i]; 34 while (c.charAt(0) == ' ') c = c.substring(1, c.length); 35 if (c.indexOf(nameEQ) == 0) return unescape(c.substring(nameEQ.length, c.length)); 36 } 37 return null; 38} 39 40function wkd_remove_cookie(name) 41{ 42 wkd_set_cookie(name, "", -1); 43} 44 45function get_human_readable_time( seconds ) 46{ 47 var time_lengths = [60, 1]; 48 var output = ''; 49 50 for ( var s = 0; s < time_lengths.length; s++ ) 51 { 52 var d = Math.floor( seconds / time_lengths[s] ); 53 var readable = d; 54 if ( readable < 10 ) 55 readable = '0' + readable; 56 57 if ( s > 0 ) 58 output = output + ':'; 59 output = output + readable; 60 seconds -= ( d * time_lengths[s] ); 61 } 62 63 return output; 64} 65 66/////////////////////////////////////////// 67// site functions 68/////////////////////////////////////////// 69 70function wkd_toggle_menu() 71{ 72 jQuery('body').toggleClass( 'menu_open' ); 73} 74function wkd_close_menu() 75{ 76 jQuery('body').removeClass( 'menu_open' ); 77} 78 79function wkd_toggle_buy() 80{ 81 $('body').toggleClass( 'buy_open' ); 82} 83function wkd_close_buy() 84{ 85 $('body').removeClass( 'buy_open' ); 86} 87 88function wkd_toggle_search() 89{ 90 $('body').toggleClass( 'search_open' ); 91 if ( $('body').hasClass( 'search_open') ) 92 $('#search_text').focus(); 93} 94function wkd_close_search() 95{ 96 $('body').removeClass( 'search_open' ); 97} 98 99function wkd_do_search() 100{ 101 var search_text = $('#search_text').val(); 102 if ( search_text.match( /^\s*$/) ) 103 return false; 104 105 document.location.href = '/?s=' + encodeURIComponent( search_text ); 106 return false; 107} 108 109$(document).ready( function() { 110 111 112 $('.hero_slider').each( function() { 113 $(this).slick( { 114 infinite: false, 115 dots: true, 116 arrows: true, 117 adaptiveHeight: false, 118 autoplay: true, 119 autoplaySpeed: 3000, 120 speed: 1000, 121 slidesToShow: 1, 122 slidesToScroll: 1 123 } ); 124 } ); 125 126 $('.hero_slider_custom').each( function() { 127 $(this).slick( { 128 infinite: false, 129 dots: true, 130 arrows: true, 131 adaptiveHeight: false, 132 autoplay: true, 133 autoplaySpeed: 3000, 134 speed: 1000, 135 slidesToShow: 1, 136 slidesToScroll: 1 137 } ); 138 } ); 139 $('.hero_slider_custom .slick-next').each( function() { 140 console_log( "Overriding next button." ); 141 $(this).click( function( evt ) { 142 var slide_num = $('.hero_slider_custom').slick('slickCurrentSlide'); 143 // if this is the last slide, loop back to the start 144 if ( slide_num >= wkd_total_features - 1 ) 145 { 146 console_log( "Looping to zero." ); 147 $('.hero_slider_custom').slick( 'slickGoTo', 0 ); 148 } 149 } ); 150 } ); 151 $('.hero_slider_custom .slick-prev').each( function() { 152 console_log( "Overriding previous button." ); 153 $(this).click( function( evt ) { 154 var slide_num = $('.hero_slider_custom').slick('slickCurrentSlide'); 155 // if this is the last slide, loop back to the start 156 if ( slide_num <= 0 ) 157 { 158 console_log( "Looping to the end." ); 159 $('.hero_slider_custom').slick( 'slickGoTo', wkd_total_features - 1 ); 160 } 161 } ); 162 } ); 163 164 // thumbnail sliders 165 $('.thumb_slider').each( function() { 166 console_log( "Initializing thumbnail slider." ); 167 $(this).slick( { 168 infinite: false, 169 dots: false, 170 arrows: true, 171 adaptiveHeight: false, 172 autoplay: true, 173 autoplaySpeed: 3000, 174 speed: 1000, 175 slidesToShow: 5, 176 slidesToScroll: 5 177 } ); 178 } ); 179} ); 180 181 182 183/////////////////////////////////////////// 184// podcast player 185/////////////////////////////////////////// 186var wkd_last_audio_time = 0; 187var wkd_last_audio_id = ''; 188var wkd_last_audio_src = ''; 189var wkd_audio_reboot = false; 190var wkd_timeline_drag = false; 191var wkd_timeline_drag_x = 0; 192var wkd_audio_playing = null; 193var wkd_audio_mouse_y = 0; 194var wkd_audio_buffered = 0; 195 196function wkd_render_player( audio_id ) 197{ 198 var audio = $('#' + audio_id); 199 if ( !audio ) 200 { 201 throw new Error( "Invalid DOM ID passed to wkd_render_player: " + audio_id ); 202 return; 203 } 204 205 var audio_obj = document.getElementById( audio_id ); 206 audio_obj.onerror = function( e ) { 207 208 console_log( "Media error. Attempting to restart..." ); 209 210 wkd_audio_reboot = true; 211 wkd_last_audio_id = this.id; 212 wkd_last_audio_src = this.src; 213 wkd_last_audio_time = this.currentTime; 214 215 $('#' + wkd_last_audio_id ).remove(); 216 setTimeout( function() { 217 console_log( "Reloading audio object." ); 218 $('#' + wkd_last_audio_id + '_player').before( 219 $( '<audio src="' + wkd_last_audio_src + '" id="' + wkd_last_audio_id + '" class="wkd_player_audio"></audio>' ) 220 ); 221 setTimeout( function() { 222 console_log( "Attempting to resume playing." ); 223 var audio_obj = document.getElementById( wkd_last_audio_id ); 224 audio_obj.currentTime = wkd_last_audio_time; 225 audio_obj.play(); 226 wkd_audio_reboot = false; 227 228 }, 100 ); 229 }, 200 ); 230 }; 231 audio_obj.onended = function() { 232 wkd_toggle_audio_play( this.id ); 233 }; 234 235 // build the player shell 236 var player_id = audio_id + '_player';
237 var player = $('<div></div>'); 238 player.attr( 'id', player_id ).attr( 'aria-label', 'Podcast Player' ).attr( 'data-audio-id', audio_id ).addClass( 'wkd_player' ); 239 240 // build the play/pause button 241 var play_button = $('<div></div>'); 242 play_button.addClass( 'play_button mode_pause' ); 243 play_button.attr( 'data-audio-id', audio_id ).attr( 'aria-controls', audio_id ).attr( 'role', 'button' ).attr( 'tabindex', '0' ).attr( 'aria-label', 'Play and pause' ); 244 play_button.bind( 'click keypress', function( evt ) { 245 if ( evt.keyCode || evt.which ) 246 { 247 var code = evt.keyCode || evt.which; 248 if ( evt.type != "click" && code != 1 && code != 13 && code != 32 ) 249 return true; 250 } 251 252 var audio_id = $(this).attr( 'data-audio-id' ); 253 var audio_obj = document.getElementById( audio_id ); 254 255 // pause any already-playing players 256 $('.wkd_player_audio').each( function() { 257 var aid = $(this).attr('id'); 258 if ( aid && aid != audio_id ) 259 { 260 wkd_toggle_audio_play( aid, -1 ); 261 } 262 } ); 263 264 // toggle the targeted player 265 wkd_toggle_audio_play( audio_id, audio_obj.paused ); 266 wkd_audio_playing = audio_obj; 267 } ); 268 player.append( play_button ); 269 270 // add the time played text 271 var time_played = $('<div></div>'); 272 time_played.addClass( 'time_played' ); 273 time_played.attr( 'data-audio-id', audio_id ); 274 time_played.html('<span>00:00</span>'); 275 player.append( time_played ); 276 277 // add rewind button 278 var rewind = $('<div></div>'); 279 rewind.addClass( 'rewind' ); 280 rewind.attr( 'data-audio-id', audio_id ).attr( 'role', 'button').attr( 'tabindex', '0' ).attr( 'aria-label', 'Rewind ten seconds' ); 281 rewind.bind( 'click keypress', function( evt ) { 282 if ( evt.keyCode || evt.which ) 283 { 284 var code = evt.keyCode || evt.which; 285 if ( evt.type != "click" && code != 1 && code != 13 && code != 32 ) 286 return true; 287 } 288 289 var audio = document.getElementById( audio_id ); 290 if ( !audio.duration ) 291 return; 292 293 var updated_time = audio_obj.currentTime - 10; 294 if ( updated_time < 0 ) 295 updated_time = 0; 296 audio_obj.currentTime = updated_time; 297 } ); 298 player.append( rewind ); 299 300 // add the timeline 301 var timeline = $('<div></div>'); 302 timeline.addClass( 'timeline' ); 303 timeline.attr( 'data-audio-id', audio_id ); 304 var timeline_track = $('<span class="timeline_outer"><span class="timeline_buffered"><span class="timeline_inner"></span></span></span>'); 305 timeline_track.click( function( e ) { 306 if ( wkd_audio_reboot ) 307 return; 308 309 } ); 310 timeline_track.mousedown( function( e ) { 311 wkd_timeline_drag = $(this); 312 wkd_set_timeline( wkd_timeline_drag, e.pageX ); 313 e.stopPropagation(); 314 315 } ); 316 timeline_track.mouseout( function( e ) { 317 if ( wkd_timeline_drag ) 318 { 319 wkd_set_timeline( wkd_timeline_drag, e.pageX ); 320 } 321 } ); 322 timeline.append( timeline_track ); 323 player.append( timeline ); 324 325 // add total-time panel 326 var time_total = $('<div></div>' ); 327 time_total.addClass( 'time_total' ); 328 time_total.attr( 'data-audio-id', audio_id ); 329 if ( audio.attr('data-audio-time') ) 330 { 331 time_total.html('<span>' + audio.attr('data-audio-time') + '</span>' ); 332 } 333 player.append( time_total ); 334 335 336 // add the volume control 337 var volume_block = $('<div></div>' ); 338 volume_block.addClass( 'volume_toggle volume_on' ); 339 volume_block.attr( 'data-audio-id', audio_id ).attr( 'role', 'button').attr( 'tabindex', '0' ).attr( 'aria-label', 'Mute' ); 340 volume_block.on( 'click keypress', function( evt ) { 341 if ( wkd_audio_reboot ) 342 return; 343 344 if ( evt.keyCode || evt.which ) 345 { 346 var code = evt.keyCode || evt.which; 347 if ( evt.type != "click" && code != 1 && code != 13 && code != 32 ) 348 return true; 349 } 350 351 var audio = document.getElementById( audio_id ); 352 if ( !audio.duration ) 353 return; 354 355 if ( $(this).hasClass( 'volume_on' ) ) 356 { 357 $(this).removeClass( 'volume_on' ); 358 $(this).addClass( 'volume_off' ); 359 audio.volume = 0; 360 } else { 361 $(this).removeClass( 'volume_off' ); 362 $(this).addClass( 'volume_on' ); 363 audio.volume = 1; 364 } 365 } ); 366 player.append( volume_block ); 367 368 // build the download button 369 var download_file = audio.attr( 'data-filename' ); 370 var download_url = audio_obj.src; 371 var download_target = ' target="_blank" '; 372 if ( download_url.match( /omny\.fm/i) ) 373 { 374 download_target = ''; 375 download_url += '?requestSource=Widget&utm_source=Embed&download=true'; 376 } 377 player.append( $('<div class="download"><a ' + download_target + ' href="' + download_url + '" title="Download full audio" download="' + download_file + '"><span>Download</span></a></div>' ) ); 378 audio.before( player ); 379 380 // if this is a reboot, attempt to move back to where we were in time 381 if ( wkd_last_audio_time > 0 ) 382 { 383 audio_obj.play(); 384 audio_obj.currentTime = wkd_last_audio_time; 385 } 386} 387 388function wkd_set_timeline( timeline_block, mouse_x ) 389{ 390 var audio_id = timeline_block.parent().attr( 'data-audio-id' ); 391 var audio = document.getElementById( audio_id ); 392 var offset = timeline_block.offset(); 393 var rel_x = mouse_x - offset.left; 394 var percent_clicked = rel_x / timeline_block.width(); 395 396 if ( !audio.duration ) 397 return; 398 399 // if they're clicking close enough to the start, start over 400 if ( 100 * percent_clicked < 1 ) 401 percent_clicked = 0; 402 var new_time = Math.round( audio.duration * percent_clicked ); 403 if ( new_time >= audio.duration ) 404 new_time = audio.duration; 405 406 wkd_last_audio_time = new_time; 407 audio.currentTime = new_time; 408 if ( new_time >= audio.duration ) 409 wkd_toggle_audio_play( audio_id ); 410} 411 412function wkd_toggle_audio_play( audio_id, play ) 413{ 414 var audio_obj = document.getElementById(audio_id); 415 var play_button = $('#' + audio_id + '_player .play_button').first(); 416 if ( audio_obj.volume < 0 ) 417 audio_obj.volume = 1; 418 419 play_button.removeClass( 'mode_pause' ); 420 play_button.removeClass( 'mode_play' ); 421 422 if ( play && play != -1 && audio_obj.paused ) 423 { 424 play_button.addClass( 'mode_play' ); 425 audio_obj.play(); 426 } else { 427 play_button.addClass( 'mode_pause' ); 428 audio_obj.pause(); 429 } 430} 431 432function wkd_update_audio_players() 433{ 434 if ( wkd_audio_reboot ) 435 return; 436 437 $('.wkd_player_audio').each( function() { 438 var audio_id = $(this).attr('id'); 439 var audio_obj = document.getElementById( audio_id ); 440 if ( audio_obj && audio_obj.duration ) 441 { 442 var buffered = audio_obj.buffered.end(audio_obj.buffered.length - 1); 443 var buffered_percent = ( 100 * ( buffered / audio_obj.duration ) ).toFixed(2); 444 445// var percent_complete = ( 100 * ( audio_obj.currentTime / audio_obj.duration ) ).toFixed( 2 ); 446 var percent_complete = ( audio_obj.currentTime / audio_obj.duration ); 447 var percent_width = Math.floor( $('#' + audio_id + '_player .timeline_outer').width() * percent_complete ); 448 449 $('#' + audio_id + '_player .timeline span.timeline_inner').css( { 450 'width' : '' + percent_width + 'px' 451 } ); 452 453 $('#' + audio_id + '_player .timeline span.timeline_buffered').css( { 454 'width' : '' + buffered_percent + '%' 455 } ); 456 457 var time_played = get_human_readable_time( audio_obj.currentTime ); 458 var time_total = get_human_readable_time( audio_obj.duration ); 459 $('#' + audio_id + '_player .time_played').html( '<span>' + time_played + '</span>' ); 460 $('#' + audio_id + '_player .time_total').html( '<span>' + time_total + '</span>' ); 461 if ( audio_obj.currentTime >= audio_obj.duration ) 462 wkd_toggle_audio_play( audio_id ); 463 464 } 465 } ); 466} 467 468function wkd_bind_player_input() 469{ 470 /* 471 $(document).keypress( function( e ) { 472 if ( e.charCode == KEY_CODE_SPACE && wkd_audio_playing != null ) 473 { 474 wkd_toggle_audio_play( wkd_audio_playing.id, wkd_audio_playing.paused ); 475 } 476 } ); 477 */ 478 $(document).mousemove( function( e ) { 479 if ( wkd_timeline_drag ) 480 { 481 wkd_set_timeline( wkd_timeline_drag, e.pageX ); 482 e.stopPropagation(); 483 } 484 } ); 485 $(document).mouseup( function( e ) { 486 if ( wkd_timeline_drag ) 487 { 488 wkd_set_timeline( wkd_timeline_drag, e.pageX ); 489 wkd_timeline_drag = null; 490 e.stopPropagation(); 491 } 492 } ); 493 494} 495 496$(function() { 497 498 var player_found = false; 499 $('.wkd_player_audio').each( function() { 500// console_log( "Found player: " + $(this).attr('id') ); 501 player_found = true; 502 wkd_render_player( $(this).attr('id') ); 503 } ); 504 505 if ( player_found ) 506 wkd_bind_player_input(); 507} ); 508 509var wkd_player_updates = setInterval( "wkd_update_audio_players()", 250 ); 510 511function wkd_series_links( id ) 512{ 513 wkd_close_series_links(); 514 var series_links = $('#series_links_' + id); 515 series_links.detach(); 516 $('body').append( series_links ); 517 $('body').addClass( 'series_open' ); 518 series_links.addClass('series_links_open'); 519} 520function wkd_close_series_links() 521{ 522 $('.series_links').each( function() { 523 $(this).removeClass('series_links_open'); 524 } ); 525 $('body').removeClass( 'series_open' ); 526} 527 528function wkd_expand_transcript(button) 529{ 530 if ( $('#transcript_inner').hasClass( 'expanded' ) ) 531 { 532 $('#transcript_inner').css( 'height', '650px' ).removeClass( 'expanded' ); 533 $(button).html("Read full Transcript"); 534 } else { 535 $('#transcript_inner').css( 'height', 'auto' ).addClass( 'expanded' ); 536 $(button).html("Collapse Transcript"); 537 } 538} 539 540// cookie notification pop-up 541function wkd_pop_cookie_note( force ) 542{ 543 var note_popped = wkd_get_cookie('fre_cookie_note_2023'); 544 if ( note_popped && !force ) 545 { 546 $('#fre_cookie_modal').hide(); 547 } else { 548 $('#fre_cookie_modal').css( { display: "block" } ); 549 setTimeout( function() { 550 $('body').addClass( 'cookie_note_popped' ); 551 }, 100 ); 552 } 553} 554function wkd_hide_cookie_note() 555{ 556 $('body').removeClass( 'cookie_note_popped' ); 557} 558function wkd_set_cookie_note() 559{ 560 wkd_set_cookie( 'fre_cookie_note_2023', '1', 730 ); 561 $('body').removeClass( 'cookie_note_popped' ); 562} 563 564$(document).ready( function() { 565 $('.payment-form-plan-list .sc-plan-selector__mp-tier-label').each( function() { 566 // monthly 567 console.log( 'For: ' + $(this).attr('for') ); 568 var plan = $(this).attr('for'); 569 if ( plan == 'plan-8939' || plan == 'plan-9259' ) 570 { 571 $(this).html('<img src="/wp-content/themes/freakonomics_2021/images/plus_button_monthlyb.png" alt="Monthly plan">'); 572 573 // annually 574 } else if ( plan == 'plan-8938' || plan == 'plan-9258' ) { 575 $(this).html('<img src="/wp-content/themes/freakonomics_2021/images/plus_button_annualb.png" alt="Annual plan">'); 576 577 } 578 } ); 579} );
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.