https://www.thekickaround.com/wp-content/plugins/stream-player-pro/js/radio-player.js?ver=1780414532
1/* =============================== */ 2/* === Radio Player Javascript === */ 3/* --------- Version 1.0.5 ------- */ 4/* =============================== */ 5 6/* === Debounce Delay Callback === */ 7var radio_player_debounce = (function () { 8 var player_debouncers = {}; 9 return function (callback, ms, uniqueId) { 10 if (!uniqueId) {uniqueId = "nonuniqueid";} 11 if (player_debouncers[uniqueId]) {clearTimeout (player_debouncers[uniqueId]);} 12 player_debouncers[uniqueId] = setTimeout(callback, ms); 13 }; 14})(); 15 16/* === Cookie Value Function === */ 17radio_player_cookie = { 18 set: function (name, value, days) { 19 if (days) { 20 var date = new Date(); 21 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 22 var expires = '; expires=' + date.toUTCString(); 23 } else {var expires = '';} 24 document.cookie = 'radio_player_' + name + '=' + JSON.stringify(value) + expires + '; path=/'; 25 }, 26 get: function(name) { 27 var nameeq = 'radio_player_' + name + '=', ca = document.cookie.split(';'); 28 for (var i = 0; i < ca.length; i++) { 29 var c = ca[i]; 30 while (c.charAt(0) == ' ') { 31 c = c.substring(1, c.length); 32 if (c.indexOf(nameeq) == 0) { 33 /* 1.0.1: fix for possible empty value */ 34 value = c.substring(nameeq.length, c.length).trim(); 35 if (value == '') {return null;} 36 return JSON.parse(value); 37 } 38 } 39 } 40 return null; 41 }, 42 delete: function(name) { 43 radio_player_cookie.set(name,'',-1); 44 } 45} 46 47/* === Load Audio Functions === */ 48 49/* --- check data for format/script --- */ 50function radio_player_check_format(data) { 51 52 if (radio_player.debug) {console.log(data);} 53 script = false; scripts = radio_player.scripts; 54 url = data.url; fallback = data.fallback; format = fformat = ''; 55 if (typeof data.format != 'undefined') {format = data.format.toLowerCase();} 56 if (typeof data.fformat != 'undefined') {fformat = data.fformat.toLowerCase();} 57 58 /* attempt to get format from URL */ 59 /* TODO: add more possible formats for detection ? */ 60 formats = ['mp3','aac','m4a','mp4','ogg','oga','webm','rtmpa','wav','flac']; 61 if (format == '') { 62 if (radio_player.debug) {console.log('Detecting stream format from URL '+url);} 63 for (i = 0; i < formats.length; i++) { 64 length = formats[i].length; 65 if (url.substr(-length,length) == formats[i]) {format = formats[i];} 66 } 67 /* 2.5.18: added partial path match URL checking */ 68 if (format == '') { 69 for (i = 0; i < formats.length; i++) { 70 checkurl = new URL(url); urlpath = checkurl.pathname + checkurl.search; 71 if (urlpath.indexOf(formats[i]) > -1) {format = formats[i];} 72 } 73 } 74 } 75 if (fformat == '') { 76 if (radio_player.debug) {console.log('Detecting fallback format from URL '+url);} 77 for (i = 0; i < formats.length; i++) { 78 length = formats[i].length; 79 if (fallback.substr(-length,length) == formats[i]) {fformat = formats[i];} 80 } 81 /* 2.5.18: added partial path match URL checking */ 82 if (fformat = '') { 83 for (i = 0; i < formats.length; i++) { 84 checkurl = new URL(fallback); urlpath = checkurl.pathname + checkurl.search; 85 if (urlpath.indexOf(formats[i]) > -1) {fformat = formats[i];} 86 } 87 } 88 } 89 90 /* --- check against default script setting */ 91 if (radio_player.settings.script) { 92 defaultscript = radio_player.settings.script; 93 if (defaultscript in scripts) { 94 if (format in radio_player.formats[defaultscript]) {script = defaultscript;} 95 else if (fformat in radio_player.formats[defaultscript]) { 96 /* switch to fallback format as recognized */ 97 /* TODO: could test/improve this process ? */ 98 script = defaultscript; a = url; b = format; 99 url = fallback; format = fformat; fallback = a; fformat = b; 100 } 101 } 102 } 103 104 /* check formats against available scripts */ 105 if (!script) { 106 if (('amplitude' in scripts) && (format in radio_player.formats.amplitude)) {script = 'amplitude';} 107 else if (('jplayer' in scripts) && (format in radio_player.formats.jplayer)) {script = 'jplayer';} 108 /* else if (('audio5' in scripts) && (format in radio_player.formats.audio5)) {script = 'audio5';} 109 else if (('howler' in scripts) && (format in radio_player.formats.howler)) {script = 'howler';} 110 else if (('mediaelements' in scripts) && (format in radio_player.formats.mediaelements)) {script = 'mediaelements';} */ 111 if (!script) { 112 if (('amplitude' in scripts) && (fformat in radio_player.formats.amplitude)) {script = 'amplitude';} 113 else if (('jplayer' in scripts) && (fformat in radio_player.formats.jplayer)) {script = 'jplayer';} 114 /* else if (('audio5' in scripts) && (fformat in radio_player.formats.audio5)) {script = 'audio5';} 115 else if (('howler' in scripts) && (fformat in radio_player.formats.howler)) {script = 'howler';} 116 else if (('mediaelements' in scripts) && (fformat in radio_player.formats.mediaelements)) {script = 'mediaelements';} */ 117 if (script) {a = url; b = format; url = fallback; format = fformat; fallback = a; fformat = b;} 118 } 119 if (!script) { 120 if ('amplitude' in scripts) {script = 'amplitude';} 121 else if ('jplayer' in scripts) {script = 'jplayer';} 122 /* else if ('audio5' in scripts) {script = 'audio5';} 123 else if ('howler' in scripts) {script = 'howler';} */ 124 } 125 } 126 127 data.script = script; data.url = url; data.format = format; data.fallback = fallback; data.fformat = fformat; 128 return data; 129} 130 131/* --- load default radio stream --- */ 132function radio_player_load_radio(start) { 133 script = radio_player.settings.script; instance = radio_player_data.state.instance; 134 data = radio_player.stream_data; data.type = 'stream'; 135 player = radio_player_load_stream(script, instance, data, start); 136} 137 138/* --- load HLS source --- */ 139function radio_player_load_hls(script, instance, data, start) { 140 if (!instance) {instance = radio_player_default_instance();} 141 data.type = 'hls'; radio_player_data.data[instance] = data; 142 jQuery('#radio_player_'+instance).attr('data-channel', data.channel); 143 player = radio_player_load_audio(script, instance, data, false); 144 radio_player_hls_source(instance, data.url, start); 145} 146 147/* --- load a station --- */ 148function radio_player_load_station(script, instance, data, start) { 149 150 if (!instance) {instance = radio_player_default_instance();} 151 data.type = 'station'; radio_player_data.data[instance] = data; 152 jQuery('#radio_player_'+instance).attr('data-station', data.station); 153 154 data = radio_player_check_format(data); script = data.script; 155 player = radio_player_load_audio(script, instance, data, start); 156 if (radio_player.debug) {console.log('Load Station '+station+' - Script: '+script+' - Instance: '+instance+' URL: '+data.url+' Format: '+data.format+' Start:'+start);} 157 if (player && start) { 158 setTimeout(function() {radio_player_play_on_load(player, script, instance);}, 50); 159 } 160} 161 162/* --- load a channel --- */ 163function radio_player_load_channel(script, instance, data, start) { 164 165 if (!instance) {instance = radio_player_default_instance();} 166 data.type = 'channel'; radio_player_data.data[instance] = data; 167 jQuery('#radio_player_'+instance).attr('data-channel', data.channel); 168 169 data = radio_player_check_format(data); script = data.script; 170 player = radio_player_load_audio(script, instance, data, start); 171 if (radio_player.debug) {console.log('Load Channel '+channel+' - Script: '+script+' - Instance: '+instance+' URL: '+data.url+' Format: '+data.format+' Start:'+start);} 172 if (player && start) { 173 setTimeout(function() {radio_player_play_on_load(player, script, instance);}, 50); 174 } 175} 176 177/* --- load a stream --- */ 178function radio_player_load_stream(script, instance, data, start) { 179 180 if (!instance) {instance = radio_player_default_instance();} 181 data.type = 'stream'; radio_player_data.data[instance] = data; 182 183 data = radio_player_check_format(data); script = data.script;
184 if (radio_player.debug) {console.log('Load Stream - Script: '+script+' - Instance: '+instance+' URL: '+data.url+' Format: '+data.format+' Start:'+start);} 185 player = radio_player_load_audio(script, instance, data, start); 186 if (player && start) {radio_player_play_on_load(player, script, instance);} 187} 188 189/* --- load a file --- */ 190function radio_player_load_file(script, instance, data, start) { 191 192 if (!instance) {instance = radio_player_default_instance();} 193 data.type = 'file'; radio_player_data.data[instance] = data; 194 195 data = radio_player_check_format(data); script = data.script; 196 player = radio_player_load_audio(script, instance, data, start); 197 if (radio_player.debug) {console.log('Load File - Script: '+script+' - Instance: '+instance+' URL: '+data.url+' Format: '+data.format+' Start:'+start);} 198 if (player && start) {radio_player_play_on_load(player, script, instance);} 199} 200 201/* --- load audio in player --- */ 202function radio_player_load_audio(script, instance, data, start) { 203 if (typeof radio_player_cancel_autoresume == 'function') {radio_player_cancel_autoresume({message:'Audio Loading'});} /* ??? */ 204 url = data.url; format = data.format; fallback = data.fallback; fformat = data.fformat; type = data.type; 205 radio_player_set_data_state(script, instance, data, start); 206 loaded = radio_player_check_script(script); 207 if (loaded) { 208 if (radio_player.hasOwnProperty('delayed_player')) {clearInterval(radio_player.delayed_player);} 209 /* initialize the player if script is already loaded */ 210 if (script == 'amplitude') {player = radio_player_amplitude(instance, url, format, fallback, fformat);} 211 else if (script == 'jplayer') {player = radio_player_jplayer(instance, url, format, fallback, fformat);} 212 /* else if (script == 'audio5') {player = radio_player_audio5(instance, url, format, fallback, fformat);} 213 else if (script == 'howler') {player = radio_player_howler(instance, url, format, fallback, fformat);} 214 else if (script == 'mediaelements') {player = radio_player_mediaelements(instance, url, format, fallback, fformat);} */ 215 if (player) { 216 detail = {script:script, instance:instance, url:url, format:format, fallback:fallback, fformat:fformat, type:type, start:start} 217 radio_player_event_handler('loading', detail); 218 /* note: radio_player_play_on_load called outside this function */ 219 } 220 return player; 221 } else { 222 /* delay initialization until script is loaded */ 223 if (radio_player.debug) {console.log('Script not ready, initializing Delayed Player');} 224 radio_player.delayed_data = {'time':0, 'start':start, 'script':script, 'instance':instance, 'url':url, 'format':format, 'fallback':fallback, 'fformat':fformat}; 225 if (radio_player.hasOwnProperty('delayed_player')) {clearInterval(radio_player.delayed_player);} 226 radio_player.delayed_player = setInterval(function() { 227 radio_player.delayed_data.time++; data = radio_player.delayed_data; script = data.script; player = false; 228 if (data.time > 10) {console.log('Script load timed out. Please try again...'); clearInterval(radio_player.delayed_player);} 229 if ((script == 'amplitude') && (typeof window.Amplitude != 'undefined') && (typeof radio_player_amplitude != 'undefined')) { 230 clearInterval(radio_player.delayed_player); 231 player = radio_player_amplitude(data.instance, data.url, data.format, data.fallback, data.fformat); 232 } else if ((script == 'jplayer') && (typeof jQuery.jPlayer != 'undefined') && (typeof radio_player_jplayer != 'undefined')) { 233 clearInterval(radio_player.delayed_player); 234 player = radio_player_jplayer(data.instance, data.url, data.format, data.fallback, data.fformat); 235 } /* else if ((script == 'audio5') && (typeof window.audio5 != 'undefined') && (typeof radio_player_audio5 != 'undefined')) { 236 clearInterval(radio_player.delayed_player); 237 player = radio_player_audio5(data.instance, data.url, data.format, data.fallback, data.fformat); 238 } else if ((script == 'howler') && (typeof window.Howl != 'undefined') && (typeof radio_player_howler != 'undefined')) { 239 clearInterval(radio_player.delayed_player); 240 player = radio_player_howler(data.instance, data.url, data.format, data.fallback, data.fformat); 241 } else if ((script == 'mediaelement') && (typeof window.???? != 'undefined') && (typeof radio_player_mediaelement != 'undefined')) { 242 clearInterval(radio_player.delayed_player); 243 player = radio_player_mediaelements(instance, url, format, fallback, fformat);} 244 */ 245 if (player) { 246 radio_player_event_handler('loading', data); 247 radio_player_set_data_state(script, instance, data, data.start); 248 /* note: radio_player_play_on_load must be called inside delayed function */ 249 if (data.start) {radio_player_play_on_load(player, data.script, data.instance);} 250 } 251 }, 1000); 252 return false; 253 } 254} 255 256/* --- auto start on player load ---*/ 257function radio_player_play_on_load(player, script, instance) { 258 if (typeof player != 'undefined') { 259 if (radio_player.debug) {console.log('Loaded '+script+' script: '+(typeof player));} 260 detail = radio_player_data.data[instance]; detail.script = script, detail.instance = instance; 261 if ((script == 'amplitude') || (script == 'howler')) { 262 try {console.log(script+': Play'); player.play(); 263 radio_player_custom_event('rp-play', detail); 264 } catch(e) {console.log(script+' error: could not play stream.'); console.log(e);} 265 } else if (script == 'jplayer') { 266 if (radio_player.jplayer_ready) { 267 try {console.log(script+': Play'); player.jPlayer('play'); 268 radio_player_custom_event('rp-play', detail); 269 } catch(e) {console.log(script+' error: could not play stream.'); console.log(e);} 270 } else { 271 /* jPlayer not ready, wait until ready to play */ 272 if (radio_player.debug) {console.log('jPlayer is not yet ready...');} 273 if (radio_player.hasOwnProperty('jplayer_load')) {clearInterval(radio_player.jplayer_load);} 274 radio_player.jplayer_load = setInterval(function() { 275 if (radio_player.jplayer_ready) { 276 clearInterval(radio_player.jplayer_load); 277 if (radio_player.debug) {console.log('Triggering jPlayer play.');} 278 try {player = radio_player_data.players[radio_player.jplayer_instance]; 279 player.jPlayer('play'); radio_player_custom_event('rp-play', detail); 280 } catch(e) {console.log(script+' error: jPlayer could not play stream.'); console.log(e);} 281 } 282 }, 250); 283 } 284 } else if (script == 'audio5') { 285 try {console.log(script+': Play'); player.play(); 286 radio_player_custom_event('rp-play', detail); 287 } catch(e) {console.log(script+' error: could not play stream.'); console.log(e);} 288 } 289 } else if (radio_player.debug) { 290 console.log(script+' script not yet loaded...'); console.log(player); 291 } 292} 293 294// --- check/load a player script --- 295function radio_player_check_script(script) { 296 loading = false; head = document.getElementsByTagName('head')[0]; 297 if (script == 'amplitude') { 298 if (typeof window.Amplitude == 'undefined') {
299 if (radio_player.debug) {console.log('Dynamically Loading Amplitude Player Script...');} 300 el = document.createElement('script'); el.src = radio_player.scripts.amplitude; head.appendChild(el); loading = true; 301 } 302 } else if (script == 'jplayer') { 303 if (typeof jQuery.jPlayer == 'undefined') { 304 if (radio_player.debug) {console.log('Dynamically Loading jPlayer Script...');} 305 el = document.createElement('script'); el.src = radio_player.scripts.jplayer; head.appendChild(el); loading = true; 306 } 307 } /* else if (script == 'audio5') { 308 if (typeof window.audio5 == 'undefined') { 309 if (radio_player.debug) {console.log('Dynamically Loading audio5 Player Script...');} 310 el = document.createElement('script'); el.src = radio_player.scripts.audio5; head.appendChild(el); loading = true; 311 } 312 } else if (script == 'howler') { 313 if (typeof window.Howl == 'undefined') { 314 if (radio_player.debug) {console.log('Dynamically Loading Howler Player Script...');} 315 el = document.createElement('script'); el.src = radio_player.scripts.howler; head.appendChild(el); loading = true; 316 } 317 } else if ( ( script == 'mediaelement') && (typeof mejs == 'undefined' ) ) { 318 el = document.createElement('script'); el.src = radio_player.scripts.media; head.appendChild(el); 319 el = document.createElement('script'); el.src = radio_player.scripts.elements; head.appendChild(el); 320 el = document.createElement('script'); el.src = funcs; head.appendChild(el); 321 loading = true; 322 } */ 323 if (loading) {return false;} 324 return true; 325} 326 327/* --- player failed fallback to another script --- */ 328function radio_player_player_fallback(instance, script) { 329 if (typeof radio_player.delayed_player != 'undefined') {clearInterval(radio_player.delayed_player);} 330 if (typeof radio_player_data.failed[instance] != 'undefined') {j = radio_player_data.failed[instance].length;} 331 else {radio_player_data.failed[instance] = []; j = 0;} 332 333 scripta = script+'-a'; scriptb = script+'-b'; 334 if (!(scripta in radio_player_data.failed[instance])) { 335 radio_player_data.failed[instance][j] = scripta; 336 } else if (!(scriptb in radio_player_data.failed[instance])) { 337 radio_player_data.failed[instance][j] = scriptb; 338 } 339 jQuery('#radio_container_'+instance).removeClass('playing').removeClass('loaded'); 340 data = radio_player_data.data[instance]; data.instance = instance; 341 radio_player_event_handler('failed', data); 342 343 /* retry different script with stored player instance data */ 344 newscript = twoscript = false; 345 if (radio_player.scripts.length) { 346 for (k in radio_player.scripts) { 347 founda = foundb = false; 348 for (j = 0; j < radio_player_data.failed[instance].length; j++) { 349 if (radio_player_data.failed[instance][j] == k+'-a') {founda = true;} 350 if (radio_player_data.failed[instance][j] == k+'-b') {foundb = true;} 351 } 352 if (!founda || !foundb) { 353 if (!newscript) {newscript = k;} else {twoscript = k;} 354 } 355 } 356 } 357 358 /* maybe swap to fallback stream data to retry */ 359 if (newscript && !foundb) { 360 if (data.fallback != '') { 361 if (radio_player.debug) {console.log('Switching to Fallback Stream');} 362 tmpa = data.url; data.url = data.fallback; data.fallback = tmpa; 363 tmpb = data.format; data.fformat = data.format; data.fformat = tmpb; 364 data.switched = true; radio_player_data.data[instance] = data; 365 radio_player_load_audio(newscript,instance,data,data.start); return; 366 } else { 367 /* no fallback, set as failed and try next script */ 368 j++; radio_player_data.failed[instance][j] = scriptb; 369 if (twoscript) {newscript = twoscript;} else {newscript = false;} 370 } 371 } 372 373 /* try new script */ 374 if (newscript) { 375 if ((typeof data.switched != 'undefined') && data.switched) { 376 /* switch data back to original for new script retry */ 377 tmpa = data.url; data.url = data.fallback; data.fallback = tmpa; 378 tmpb = data.format; data.fformat = data.format; data.fformat = tmpb; 379 data.switched = false; radio_player_data.data[instance] = data; 380 } 381 radio_player_data.data[instance].script = newscript; 382 if (radio_player.debug) {console.log('Trying New Player Script: '+newscript); console.log(data);}
383 radio_player_load_audio(newscript,instance,data,data.start); 384 } else { 385 if (radio_player.debug) {console.log('Exhausted All Player Script Type Attempts');} 386 radio_player_data.failed = []; /* reset */ 387 } 388} 389 390/* --- show manual script switcher --- */ 391function radio_player_show_switcher(instance) { 392 jQuery('#radio_container_'+instance+' .rp-show-switcher').hide(); 393 jQuery('#radio_container_'+instance+' .rp-script-select').show(); 394} 395 396/* --- switch player script --- */ 397function radio_player_switch_script(instance, script) { 398 radio_player.loading = true; 399 data = radio_player_data.data[instance]; 400 if ((typeof radio_player_data.players[instance] != 'undefined') && (typeof radio_player_data.scripts[instance] != script)) {radio_player_stop_instance(instance,true);} 401 player = radio_player_load_audio(script,instance,data,data.start); 402 if (player && data.start) {radio_player_play_on_load(player,script,instance);} 403} 404 405/* === Player Functions and Event Callbacks === */ 406 407/* --- get player source --- */ 408function radio_player_get_source(player, script) { 409 src = false; 410 if (script == 'amplitude') {src = player.getAudio().src;} 411 else if (script == 'jplayer') {src = player.data('jPlayer').status.src;} 412 /* else if (script == 'audio5') {src = player.???;} */ 413 /* else if (script == 'howler') {src = player.???;} */ 414 return src; 415} 416 417/* --- get instance audio element --- */ 418function radio_player_audio_element(instance) { 419 if (typeof radio_player_data.players[instance] == 'undefined') {return false;} 420 player = radio_player_data.players[instance]; 421 script = radio_player_data.scripts[instance]; 422 if (script == 'amplitude') {audio = player.getAudio();} 423 else if (script == 'jplayer') {audio = player.data('jPlayer').htmlElement.audio;} 424 /* else if (script == 'howler') {audio = ???;} */ 425 return audio; 426} 427 428/* --- get event source --- */ 429function radio_player_event_source(e) { 430 src = false; instance = e.detail.instance; 431 if (e.detail.player != null) { 432 player = e.detail.player; script = e.detail.script; 433 src = radio_player_get_source(player,script); 434 } else if (typeof radio_player_data.players[instance] != 'undefined') { 435 player = radio_player_data.players[instance]; 436 script = radio_player_data.scripts[instance]; 437 src = radio_player_get_source(player,script); 438 } else if (typeof radio_player_data.data[instance] != 'undefined') { 439 src = radio_player_data.data[instance].url; 440 } 441 return src; 442} 443 444/* --- get data for channel id --- */ 445function radio_player_channel_data(channel) { 446 for (i in radio_player_data.channels) { 447 data = radio_player_data.channels[i]; 448 if (parseInt(data.id) == parseInt(channel)) {return data;} 449 } 450 return false; 451} 452 453/* --- get data for station id --- */ 454function radio_player_station_data(station) { 455 for (i in radio_player_data.stations) { 456 data = radio_player_data.stations[i]; 457 if (parseInt(data.id) == parseInt(station)) {return data;} 458 } 459 return false; 460} 461 462/* --- play source --- */ 463function radio_player_play_source(instance) { 464 container = jQuery('#radio_container_'+instance); 465 script = radio_player.settings.script; 466 if (typeof container.attr('data-script') != 'undefined') {script = container.attr('data-script');} 467 468 data = radio_player_get_data(instance); 469 if (data.type == 'file') { 470 radio_player_load_file(script, instance, data, true); 471 } else if (data.type == 'channel') { 472 radio_player_load_channel(script, instance, data, true); 473 } else if (data.type == 'station') { 474 radio_player_load_station(script, instance, data, true); 475 } else if (data.type == 'stream') { 476 radio_player_load_stream(script, instance, data, true); 477 } else if (data.type == 'hls') { 478 radio_player_load_hls(script, instance, data, true); 479 } 480} 481 482/* --- get data to play --- */ 483function radio_player_get_data(instance) { 484 container = jQuery('#radio_container_'+instance); 485 data = false; /* ensure reset */ 486 if (typeof container.attr('data-href') != 'undefined') { 487 href = container.attr('data-href'); 488 if (href.trim() != '') { 489 format = container.attr('data-format'); 490 fallback = container.attr('data-fallback'); 491 fformat = container.attr('data-fformat'); 492 data = {url:href, format:format, fallback:fallback, fformat:fformat, type:'file'}; 493 if (radio_player.debug) {console.log('File Source Data:');} 494 } 495 } 496 if (!data) { 497 /* get HLS data */ 498 if ((typeof container.attr('data-hls') != 'undefined') && (container.attr('data-hls') != '')) { 499 url = container.attr('data-hls'); 500 channel = parseInt(container.attr('data-channel')); 501 if (Number.isNaN(channel)) {channel = 0;} 502 data = {url:url, format:'hls', fallback:false, fformat:false, channel:channel, type:'hls'}; 503 if (radio_player.debug) {console.log('HLS Source Data:');} 504 } 505 } 506 if (!data) { 507 /* get channel data */ 508 channel = parseInt(container.attr('data-channel')); 509 if (!Number.isNaN(channel)) {
510 data = radio_player_channel_data(channel); data.type = 'channel'; data.channel = channel; 511 if (radio_player.debug) {console.log('Channel Source Data:');} 512 } 513 } 514 if (!data) { 515 /* get station data */ 516 station = parseInt(container.attr('data-station')); 517 if (!Number.isNaN(station)) { 518 data = radio_player_station_data(station); data.type = 'station'; data.station = station; 519 if (radio_player.debug) {console.log('Station Source Data:');} 520 } 521 } 522 /* get default stream data */ 523 if (!data) { 524 data = radio_player.stream_data; data.type = 'stream'; 525 if (radio_player.debug) {console.log('Stream Source Data:');} 526 } 527 if (radio_player.debug) {console.log(data);} 528 return data; 529} 530 531/* --- play player instance --- */ 532var radio_player_retry = {} 533function radio_player_play_instance(instance) { 534 if (typeof radio_player_autoresume == 'object') {radio_player_autoresume.cancelled = true;} 535 if (radio_player_is_playing(instance)) {return;} 536 radio_player.loading = true; 537 container = jQuery('#radio_container_'+instance); 538 if (container.hasClass('rewound') || container.hasClass('timeshift')) { 539 audio = radio_player_audio_element(instance); 540 hls.config.autoStartLoad = true; hls.startLoad(); 541 hls.attachMedia(audio); 542 audio.play().catch( () => { radio_player_hls_source(instance,false,true); }); 543 } /* else { */ 544 player = radio_player_data.players[instance]; script = radio_player_data.scripts[instance]; 545 if (script == 'amplitude') {player.play();} 546 else if (script == 'jplayer') {player.jPlayer('play');} 547 else if ((script == 'audio5') || (script == 'howler')) {player.play();} 548 if (radio_player.debug) {console.log('Playing '+script+' Player Instance '+instance);} 549 /* } */ 550 radio_player_custom_event('rp-play', {player:player, script:script, instance:instance}); 551} 552 553/* --- pause player instance --- */ 554function radio_player_pause_instance(instance) { 555 /* if (!radio_player_is_loading(instance) && !radio_player_is_playing(instance)) {return;} */ 556 player = radio_player_data.players[instance]; script = radio_player_data.scripts[instance]; 557 detail = {player:player, script:script, instance:instance}; 558 radio_player_custom_event('rp-before-pause', detail); 559 if (radio_player.debug) {console.log('Pausing '+script+' Player Instance '+instance);} 560 container = jQuery('#radio_container_'+instance); 561 audio = radio_player_audio_element(instance); 562 if (script == 'amplitude') { 563 if (container.hasClass('rewound') || container.hasClass('timeshift')) {audio.pause();} 564 else {src = player.getAudio().src;} 565 } 566 if ((script == 'amplitude') || (script == 'audio5') || (script == 'howler')) {player.pause();} 567 else if (script == 'jplayer') {player.jPlayer('pause');} 568 if (script == 'amplitude') { 569 /* amplitude empty src on pause error fix! */ 570 if (container.hasClass('rewound') || container.hasClass('timeshift')) { 571 hls.config.autoStartLoad = false; hls.stopLoad(); 572 /* hls.attachMedia(audio); */ audio.pause(); 573 } else {player.getAudio().src = src;} 574 } 575 radio_player_custom_event('rp-pause', detail); 576} 577 578/* --- stop player instance --- */ 579function radio_player_stop_instance(instance) { 580 player = radio_player_data.players[instance]; script = radio_player_data.scripts[instance]; 581 if (radio_player.debug) {console.log('Stopping '+script+' Player Instance '+instance);} 582 if (script == 'amplitude') { 583 /* ? amplitude bug: 'stop is not a function'! ? */ 584 try {player.stop();} catch(e) {player.pause();} 585 } else if (script == 'jplayer') {player.jPlayer('stop');} 586 else if (script == 'audio5') {player.destroy();} 587 else if (script == 'howler') {player.unload();} 588 radio_player_custom_event('rp-stop', {player:player, script:script, instance:instance}); 589} 590 591/* --- mute or unmute player --- */ 592function radio_player_mute_instance(instance, player, script, mute) { 593 container = jQuery('#radio_container_'+instance); 594 if (script == 'amplitude') { 595 volume = player.getVolume(); 596 if (mute) { 597 container.attr('data-volume',volume); 598 if (radio_player.debug) {console.log('Set Pre-muted Volume: '+volume);} 599 player.setVolume(0); 600 } else if (volume == 0) { 601 if (typeof container.attr('data-volume') != 'undefined') { 602 volume = container.attr('data-volume'); 603 if (radio_player.debug) {console.log('Restore Pre-muted Volume: '+volume);}
604 try {player.setVolume(volume);} catch(e) {} 605 } 606 } 607 } else if (script == 'audio5') { 608 volume = player.volume(); 609 if (mute) { 610 container.attr('data-volume',(volume * 100)); 611 if (radio_player.debug) {console.log('Set Pre-muted Volume: '+volume);} 612 player.volume(0); 613 } else if (volume == 0) { 614 if (typeof container.attr('data-volume') != 'undefined') { 615 volume = parseInt(container.attr('data-volume')) / 100; 616 if (radio_player.debug) {console.log('Restore Pre-muted Volume: '+volume);} 617 try {player.volume(volume);} catch(e) {} 618 } 619 } 620 } else if (script == 'jplayer') { 621 if (mute) {player.jPlayer('mute');} else {player.jPlayer('unmute');} 622 } else if (script == 'howler') { 623 if (mute) {player.mute(true);} else {player.mute(false);} 624 } 625} 626 627/* --- check if player is playing */ 628function radio_player_is_playing(instance) { 629 instances = Object.keys(radio_player_data.players); 630 if (!instances.includes(instance)) {return false;} 631 player = radio_player_data.players[instance]; script = radio_player_data.scripts[instance]; 632 if (script == 'amplitude') { 633 state = player.getPlayerState(); 634 playing = (state == 'playing'); 635 } else if (script == 'jplayer') { 636 /* ? possible bug: get status not working ? */ 637 try {playing = !player.data('jPlayer').status.paused;} 638 catch(e) {playing = !player.data().jPlayer.status.paused;} 639 } else if (script == 'audio5') { 640 playing = player.playing; 641 } else if (script == 'howler') { 642 playing = player.playing(); 643 } 644 if (radio_player.debug) { 645 if (playing) {console.log('Player Instance '+instance+' ('+script+') is playing.');} 646 else {console.log('Player Instance '+instance+' ('+script+') is not playing.');} 647 } 648 return playing; 649} 650 651/* --- check if player instance is loading --- */ 652function radio_player_is_loading(instance) { 653 player = jQuery('#radio_player_'+instance); 654 if (player.hasClass('loading')) {return true;} 655 return false; 656} 657 658/* --- change player volume --- */ 659function radio_player_change_volume(instance, volume) { 660 container = jQuery('#radio_container_'+instance); 661 container.attr('data-volume',volume); 662 if ((volume == 100) && !container.hasClass('maxed')) {container.addClass('maxed');} 663 else {container.removeClass('maxed');} 664 slider = jQuery('#radio_container_'+instance+' .rp-volume-slider'); 665 if (!slider.hasClass('changed')) {slider.addClass('changed');} 666 667 if (typeof radio_player_data.players[instance] != 'undefined') { 668 player = radio_player_data.players[instance]; script = radio_player_data.scripts[instance]; 669 radio_player_set_volume(instance,volume); 670 detail = {player:player, script:script, instance:instance, volume:volume}; 671 radio_player_custom_event('rp-volume', detail); 672 } else { 673 detail = {player:null, script: null, instance: instance, volume: volume}; 674 } 675 radio_player_custom_event('rp-volume',detail); 676} 677 678/* --- set player volume --- */ 679function radio_player_set_volume(instance, volume) { 680 player = radio_player_data.players[instance]; script = radio_player_data.scripts[instance]; 681 if (script == 'amplitude') { 682 player.setVolume(volume); newvolume = player.getVolume(); 683 if (radio_player.debug) {console.log('Amplitude New Volume: '+volume+' - Now: '+newvolume);} 684 } else if (script == 'jplayer') { 685 volume = parseFloat(volume / 100); 686 /* note: this catches (browser?) error "cannot set to non-finite value" in jPlayer _html_setProperty */ 687 try {player.jPlayer('volume', volume); newvolume = player.jPlayer('volume');} catch(e) {} 688 if (radio_player.debug) {console.log('jPlayer New Volume: '+volume+' - Now: '+newvolume);} 689 } else if (script == 'audio5') { 690 volume = parseFloat(volume / 100); 691 player.volume(volume); newvolume = player.volume(); 692 if (radio_player.debug) {console.log('audio5 New Volume: '+volume+' - Now: '+newvolume);} 693 } else if (script == 'howler') { 694 volume = parseFloat(volume / 100); 695 player.volume(volume); newvolume = player.volume(); 696 if (radio_player.debug) {console.log('Howler New Volume: '+volume+' - Now: '+newvolume);} 697 } 698} 699 700/* --- get player volume --- */ 701function radio_player_get_volume(instance) { 702 player = radio_player_data.players[instance]; script = radio_player_data.scripts[instance]; 703 if (script == 'amplitude') {volume = player.getVolume();} 704 else if (script == 'jplayer') {volume = (player.jPlayer('volume') * 100);} 705 else if ((script == 'audio5') || (script == 'howler')) {volume = (player.volume() * 100);} 706 return volume; 707} 708 709/* --- set all volume sliders --- */ 710function radio_player_volume_sliders(volume) { 711 jQuery('.radio-container').each(function() { 712 instance = jQuery(this).attr('data-instance'); 713 radio_player_volume_slider(instance,volume); 714 }); 715} 716 717/* --- set slider volume with background div width fix --- */ 718function radio_player_volume_slider(instance, volume) { 719 jQuery('#radio_container_'+instance+', #rp_container_'+instance).each(function() { 720 slider = jQuery(this).find('.rp-volume-slider'); 721 slider.addClass('changed'); 722 sliderbg = jQuery(this).find('.rp-volume-slider-bg'); 723 thumb = jQuery(this).find('.rp-volume-thumb'); 724 if (slider.length) { 725 sliderbg.hide(); slider.val(volume); swidth = slider.width(); 726 thumb.show(); twidth = thumb.width(); thumb.hide(); 727 mwidth = parseInt(sliderbg.css('margin-left').replace('px',''));
728 bgwidth = parseInt((swidth - twidth) * (volume / 100)) - mwidth; 729 sliderbg.attr('style', 'width: '+bgwidth+'px !important;').show(); 730 /* if (radio_player.debug) { 731 newwidth = parseInt(sliderbg.css('width')); console.log('Volume Slider BF: Slider '+swidth+' : Thumb '+twidth+' : Margin '+mwidth+' : BG '+bgwidth+' : Now '+newwidth); 732 } */ 733 if (volume == 0) {jQuery(this).addClass('minned');} else {jQuery(this).removeClass('minned');} 734 if (volume == 100) {jQuery(this).addClass('maxed');} else {jQuery(this).removeClass('maxed');} 735 } 736 }); 737} 738 739/* --- mute or unmute a player -- */ 740function radio_player_mute_unmute(instance, mute) { 741 jQuery('#radio_container_'+instance+', #rp_container_'+instance).each(function() { 742 if (mute) {jQuery(this).addClass('muted').removeClass('maxed');} else {jQuery(this).removeClass('muted');} 743 }); 744 detail = {player:null, script:null, instance:instance, mute:mute}; 745 if (typeof radio_player_data.players[instance] != 'undefined') { 746 player = radio_player_data.players[instance]; script = radio_player_data.scripts[instance]; 747 radio_player_mute_instance(instance,player,script,mute); 748 detail = {player:player, script:script, instance:instance, mute:mute}; 749 } 750 if (mute) {radio_player_custom_event('rp-muted', detail);} 751 else {radio_player_custom_event('rp-unmuted', detail);} 752} 753 754/* --- get page default instance --- */ 755function radio_player_default_instance() { 756 instance = false; 757 jQuery('.radio-player').each(function() { 758 if (!instance && jQuery(this).hasClass('default-player')) { 759 instance = parseInt(jQuery(this).attr('id').replace('radio_player_', '')); 760 return instance; 761 } 762 }); 763 return instance; 764} 765 766/* --- pause all other instances */ 767function radio_player_pause_others(instance) { 768 if (!radio_player.settings.singular) {return;} 769 if (typeof radio_player_toggle_current == 'function') {return;} /* skip for pro */ 770 /* broadcast playing message to other windows */ 771 radio_player_broadcast_playing(instance); 772} 773 774/* --- get instance from event target --- */ 775function radio_player_event_instance(e, name, script) { 776 instance = false; 777 if (radio_player.debug) { 778 console.log(script+' Player Event: '+name); 779 if ((script == 'jplayer') && (typeof e.jPlayer.error != 'undefined')) {console.log(e.jPlayer.error);} 780 else if ((typeof e.target.error != 'undefined') && (e.target.error != null)) {console.log(e.target.error);} 781 } 782 if ((typeof e.target != 'undefined') && (e.target != null)) { 783 if (radio_player.debug) {console.log('Event Target'); console.log(e.target);} 784 if (e.target.hasAttribute('instance-id')) { 785 instance = e.target.getAttribute('instance-id'); 786 } else if (jQuery(e.target)) { 787 instance = parseInt(jQuery(e.target).attr('id').replace('radio_player_','')); 788 } 789 } 790 /* if (instance && radio_player.debug) {console.log('Event Player Instance: '+instance);} */ 791 return instance; 792} 793 794/* --- match instance from player object --- */ 795function radio_player_match_instance(obj, e, script) { 796 instance = false; 797 for (i = 0; i < radio_player_data.players.length; i++) { 798 if (obj == radio_player_data.players[i]) {instance = i;} 799 } 800 return instance; 801} 802 803/* --- player event handler --- */ 804function radio_player_event_handler(action, detail) { 805 if (typeof detail != 'object') { 806 if (radio_player.debug) {console.log('Event Handler Error for Action: '+action); console.log(detail);} 807 return; 808 } 809 instance = detail.instance; script = detail.script; 810 if (radio_player.debug) {console.log(script+' Player Instance '+instance+' : '+action);} 811 jQuery('#radio_container_'+instance+', #rp_container_'+instance).each(function() { 812 if (action == 'loading') {jQuery(this).removeClass('loaded playing stopped paused error');} 813 else if (action == 'loaded') {jQuery(this).removeClass('loading error');} 814 else if (action == 'playing') {jQuery(this).removeClass('paused stopped error');} 815 else if (action == 'paused') {jQuery(this).removeClass('playing stopped'); } 816 else if (action == 'stopped') {jQuery(this).removeClass('playing paused loaded loading'); radio_player_set_state('playing',false);} 817 else if (action == 'error') {jQuery(this).removeClass('playing paused loaded loading');} 818 if (!jQuery(this).hasClass(action)) {jQuery(this).addClass(action);} 819 }); 820 if (action == 'playing') {radio_player_set_state('playing',true);} 821 if ((action == 'paused') || (action == 'stopped')) {radio_player_set_state('playing',false);} 822 radio_player_custom_event('rp-'+action, detail); 823} 824 825/* --- player volume changed --- */ 826function radio_player_volume_changed(instance, script, volume) { 827 if (radio_player.debug) {console.log(script+' Player Instance '+instance+': Changed Volume to '+volume);} 828 slider = jQuery('#radio_container_'+instance+' .rp-volume-slider'); 829 if (!slider.hasClass('changed')) {jQuery('#radio_container_'+instance+' .rp-volume-slider').addClass('changed');} 830 831 radio_player_custom_event('rp-volume-changed', {instance:instance, script:script, volume:volume}); 832 radio_player_set_state('volume', volume); 833} 834 835/* --- sleep delay function (blocking!) --- */ 836function radio_player_sleep_delay(sleep_ms) { 837 var radio_player_sleep_start = new Date().getTime(); 838 while (sleep_ms > (new Date().getTime() - radio_player_sleep_start)) {} 839} 840 841/* === User Player State Functions === */ 842 843/* --- load player state --- */ 844function radio_player_load_state() { 845 if (typeof radio_player_data.state.checked == 'undefined') { 846 playing = radio_player_cookie.get('playing'); 847 if (playing) {radio_player_data.state.playing = playing;} 848 channel = radio_player_cookie.get('channel'); 849 if (channel != null) {radio_player_data.state.channel = channel;} 850 station = radio_player_cookie.get('station'); 851 if (station != null) {radio_player_data.state.station = station;} 852 volume = radio_player_cookie.get('volume'); 853 if (volume != null) {radio_player_data.state.volume = volume;} 854 mute = radio_player_cookie.get('mute'); 855 if (mute != null) {radio_player_data.state.mute = mute;} 856 if (radio_player.debug) { 857 console.log('Loaded User Player State - Playing: '+playing+' - Station: '+station+' - Volume: '+volume+ ' - Muted: '+mute+' - Data: '); 858 } 859 data = radio_player_cookie.get('data'); 860 if ((data != null) && (data.url != '')) { 861 radio_player_data.state.data = data; 862 if ((data.instance == false) || (data.instance == 'undefined')) {data.instance = 1;} 863 radio_player_data.data[data.instance] = data; 864 if (radio_player.debug) {console.log('Radio State Data:'); console.log(radio_player_data.data);} 865 } 866 if ((volume != null) && (data != null)) {radio_player_volume_sliders(volume);} 867 868 /* set sync debug cookie switch */ 869 if (typeof radio_player.sync_debug != 'undefined') { 870 if (radio_player.sync_debug == 'on') { 871 radio_player.sync_debug = true; 872 radio_player_cookie.set('sync_debug',1,7); 873 } else if (radio_player.sync_debug == 'off') { 874 radio_player.sync_debug = false; 875 radio_player_cookie.delete('sync_debug'); 876 } else { 877 sync_debug = radio_player_cookie.get('sync_debug'); 878 if (sync_debug != null) {radio_player.sync_debug = true;} 879 else {radio_player.sync_debug = false;} 880 } 881 } else {radio_player.sync_debug = false;} 882 radio_player_data.state.checked = true; 883 } 884} 885 886/* --- store user player state --- */ 887function radio_player_set_state(key, value) { 888 changed = false; 889 if ((key == 'playing') && (value != radio_player_data.state.playing)) { 890 radio_player_cookie.set('playing', value, 7); 891 radio_player_data.state.playing = value; changed = true; 892 } else if ((key == 'channel') && value && (value > 0) && (value != radio_player_data.state.channel)) { 893 radio_player_cookie.set('channel', value, 30); 894 radio_player_data.state.channel = value; changed = true; 895 } else if ((key == 'station') && value && (value > 0) && (value != radio_player_data.state.station)) { 896 radio_player_cookie.set('station', value, 30); 897 radio_player_data.state.station = value; changed = true; 898 } else if ((key == 'volume') && (value != radio_player_data.state.volume)) { 899 radio_player_cookie.set('volume', value, 365); 900 radio_player_data.state.volume = value; changed = true; 901 } else if ((key == 'mute') && (value != radio_player_data.state.mute)) { 902 radio_player_cookie.set('mute', value, 1); 903 radio_player_data.state.mute = value; changed = true; 904 } 905 if (changed) {radio_player_data.state.changed = true;} 906 detail = {'state': radio_player_data.state} 907 radio_player_custom_event('rp-set-state', detail); 908} 909 910/* --- store player instance data */ 911function radio_player_set_data_state(script, instance, data, start) { 912 url = data.url; format = data.format; fallback = data.fallback; fformat = data.fformat; type = data.type; 913 if (typeof radio_player_data.data[instance] != 'undefined') { 914 cdata = radio_player_data.data[instance]; 915 if ( (cdata.script != script) || (cdata.url != url) || (cdata.format != format) || (cdata.fallback != fallback) || (cdata.fformat != fformat) || (cdata.start != start) ) { 916 radio_player_data.failed[instance] = new Array(); 917 } 918 radio_player.previous_data = data; 919 } 920 data = {'script':script, 'instance':instance, 'url':url, 'format':format, 'fallback':fallback, 'fformat':fformat, 'type':type, 'start':start}; 921 if (radio_player.debug) {console.log('Setting Data State:'); console.log(data);} 922 radio_player_data.data[instance] = data; 923 if (radio_player_data.state.data != data) { 924 radio_player_data.state.data = data; 925 radio_player_cookie.set('data', data, 7); 926 radio_player_data.state.changed = true; 927 } 928} 929 930/* --- save user meta values --- */ 931function radio_player_save_user_state() { 932 if (radio_player_data.state.changed) { 933 state = radio_player_data.state; 934 if (state.loggedin && !state.saving) { 935 if (state.playing) {playing = '1';} else {playing = '0';} 936 if (state.station) {station = state.station;} else {station = '0';} 937 if (state.channel) {channel = state.channel;} else {channel = '0';} 938 if (state.volume) {volume = state.volume;} else {volume = '';} 939 if (state.mute) {mute = '1';} else {mute = '0';} 940 timestamp = Math.floor( (new Date()).getTime() / 1000 ); 941 url = radio_player.settings.ajaxurl+'?action=radio_player_state'; 942 /* ? TODO: instance ? */ 943 url += '&playing='+playing+'&station='+station+'&channel='+channel+'&volume='+volume+'&mute='+mute+'×tamp='+timestamp; 944 if (radio_player.debug) {url += '&player-debug=1';} 945 /* document.getElementById('radio-player-state-iframe').src = url; */ 946 radio_player_data.state.saving = true; 947 jQuery.get(url, function(data) { 948 if (radio_player.debug) {console.log(data);} 949 radio_player_data.state.saving = false; 950 }); 951 } 952 } 953 radio_player_data.state.changed = false; 954} 955 956/* --- volume change audio test --- */ 957/* ref: https://stackoverflow.com/a/62094756/5240159 */ 958/* 2.5.6: fix radio.debug to radio_player.debug */ 959/* 2.5.13: append testaudio to document body for more robust test */ 960function radio_player_volume_test() { 961 isIOS = ['iPad Simulator','iPhone Simulator','iPod Simulator','iPad','iPhone','iPod'].includes(navigator.platform); 962 if (radio_player.debug && isIOS) {console.log('iOS Mobile Device Detected. ');} 963 isAppleDevice = navigator.userAgent.includes('Macintosh'); 964 if (radio_player.debug && isAppleDevice) {console.log('Apple Device Detected.');} 965 isTouchScreen = navigator.maxTouchPoints >= 1;
966 if (radio_player.debug && isTouchScreen) {console.log('Touch Screen Detected. ');} 967 iosAudioFailure = false; testaudio = new Audio(); document.body.appendChild(testaudio); 968 try {testaudio.volume = 0.5;} catch(e) {if (radio_player.debug) {console.log('Caught Volume Change Error.');} iosAudioFailure = true;} 969 if (testaudio.volume === 1) {if (radio_player.debug) {console.log('Volume could not be changed.');} iosAudioFailure = true;} 970 return isIOS || (isAppleDevice && (isTouchScreen || iosAudioFailure)); 971} 972 973/* === Multi-Window/Tab Support === */ 974 975/* --- set/get window tab unique ID --- */ 976function radio_player_window_guid() { 977 if (!window.tabId) { 978 if (window.sessionStorage.tabId) { 979 window.tabId = window.sessionStorage.tabId; 980 window.sessionStorage.removeItem('tabId'); 981 } else { 982 window.tabId = Math.floor(Math.random() * 10000000); 983 } 984 } 985 /* console.log('Window Guid:'+window.tabId); */ 986 return window.tabId; 987} 988 989/* --- broadcast pause all message to other windows --- */ 990function radio_player_broadcast_playing(instance) { 991 if ((instance === false) || (typeof sysend == 'undefined')) {return;} 992 if (!radio_player.settings.singular) {return;} 993 994 action = 'pauseothers'; 995 player = radio_player_data.players[instance]; 996 script = radio_player_data.scripts[instance] 997 url = radio_player_get_source(player,script); 998 windowid = radio_player_window_guid(); 999 1000 message = windowid+'::'+instance+'::'+action+'::'+url; 1001 if (radio_player.sync_debug) {console.log('Broadcast Message: '+message);} 1002 sysend.broadcast('radio-play', {message: message}); 1003} 1004 1005/* --- check to pause player on receiving message --- */ 1006function radio_player_check_to_pause(broadcast) { 1007 if (!radio_player.settings.singular) {return;} 1008 parts = broadcast.message.split('::'); 1009 winid = parseInt(parts[0]); winstance = parseInt(parts[1]); action = parts[2]; url = parts[3]; 1010 if (radio_player.sync_debug) {console.log('Received Message from Window ID '+winid+' Instance '+winstance+' Type '+action+' URL '+url);} 1011 windowid = radio_player_window_guid(); 1012 if (!radio_player_data.players.length) {return;} 1013 for (instance in radio_player_data.players) { 1014 if ( (winid != windowid) || ((winid == windowid) && (winstance != instance)) ) { 1015 if (radio_player_is_playing(instance)) { 1016 if (radio_player.sync_debug) {console.log('Pausing Window '+windowid+' Instance '+instance);} 1017 radio_player_pause_instance(instance); 1018 } 1019 } 1020 } 1021} 1022 1023 1024/* === Audio Player Scripts === */ 1025 1026/* Amplitude Player Script */ 1027var radio_player_amp_doc_listeners = false; 1028function radio_player_amplitude(instance, url, format, fallback, fformat) { 1029 1030 container = jQuery('#radio_container_'+instance); 1031 if (url == '') {url = radio_player.settings.url;} 1032 if (url == '') {return;} 1033 if (!format || (format == '')) {format = 'aac';} 1034 /* if (fallback == '') {fallback = radio_player.settings.fallback;} */ 1035 if (!fallback || !fformat || (fformat == '')) {fallback = ''; fformat = '';} 1036 1037 /* set song streams */ 1038 songs = new Array(); 1039 songs[0] = {'name': '', 'artist': '', 'album': '', 'url': url, 'cover_art_url': '', 'live': true}; 1040 /* if ('' != fallback) {songs[1] = {'name': '', 'artist': '', 'album': '', 'url': fallback, 'cover_art_url': '', 'live': true};} */ 1041 1042 /* set volume */ 1043 if (container.find('.rp-volume-slider').length && container.find('.rp-volume-slider').hasClass('changed')) { 1044 volume = container.find('.rp-volume-slider').val(); 1045 } else if (typeof container.attr('data-volume') != 'undefined') { 1046 volume = container.attr('data-volume'); 1047 } else if (typeof radio_player_data.state.volume != 'undefined') { 1048 volume = radio_player_data.state.volume; 1049 } else {volume = radio_player.settings.volume;} 1050 radio_player_volume_slider(instance, volume); 1051 1052 /* initialize player */ 1053 if (radio_player.debug) {console.log('Init Amplitude: '+instance+' : '+url+' : '+format+' : '+fallback+' : '+fformat+' : '+volume);} 1054 radio_player_instance = Amplitude; 1055 radio_player_instance.init({ 1056 'debug': radio_player.debug, 1057 'songs': songs, 1058 'volume': volume, 1059 'volume_increment': 5, 1060 'volume_decrement': 5, 1061 'continue_next': false, 1062 'preload': 'none', 1063 }); 1064 radio_player_data.players[instance] = radio_player_instance; 1065 radio_player_data.scripts[instance] = 'amplitude'; 1066 1067 /* set instance on audio source */ 1068 audio = radio_player_instance.getAudio(); 1069 if (radio_player.debug) {console.log('Amplitude Audio Element:'); console.log(audio);} 1070 audio.setAttribute('instance-id', instance); 1071 1072 /* amp 5.0.3 bind loaded to canplay event (as initialized callback not firing!) */ 1073 /* amp 5.3.2 initialized callback is now firing */ 1074 audio.addEventListener('canplay', function(e) { 1075 radio_player.loading = false; 1076 instance = radio_player_event_instance(e, 'Loaded', 'amplitude'); 1077 radio_player_event_handler('loaded', {instance:instance, script:'amplitude'}); 1078 }, false); 1079 1080 /* amp 5.0.3: bind play(ing) event (as play callback not firing!) */ 1081 /* amp 5.3.2: play callback is now firing */ 1082 audio.addEventListener('playing', function(e) { 1083 radio_player.loading = false; 1084 instance = radio_player_event_instance(e, 'Playing', 'amplitude'); 1085 radio_player_event_handler('playing', {instance:instance, script:'amplitude'}); 1086 radio_player_pause_others(instance); 1087 }, false); 1088 1089 /* bind volume change event */ 1090 audio.addEventListener('volumechange', function(e) { 1091 instance = radio_player_event_instance(e, 'Volume', 'amplitude'); 1092 if (instance && (radio_player_data.scripts[instance] == 'amplitude')) { 1093 volume = radio_player_data.players[instance].getConfig().volume; 1094 radio_player_volume_changed(instance, 'amplitude', volume); 1095 } 1096 }, false); 1097 1098 /* bind error event (as event not being passed in callback) */ 1099 /* warning: triggered if audio src is not reset after pause! */ 1100 audio.addEventListener('error', function(e) { 1101 if ((typeof e.target.error.code != 'undefined') && e.target.error.code == 4) { 1102 if (radio_player.debug) {console.log('Skipping Amplitude Empty Audio Source Bug');} 1103 return; 1104 } 1105 instance = radio_player_event_instance(e, 'Error', 'amplitude'); 1106 if (radio_player.debug) {console.log('Amplitude Error Event'); console.log(e);} 1107 radio_player_event_handler('error', {instance:instance, script:'amplitude'}); 1108 radio_player_player_fallback(instance, 'amplitude', 'Amplitude Error'); 1109 }, false); 1110 1111 /* add document listeners only once */ 1112 if (!radio_player_amp_doc_listeners) { 1113 radio_player_amp_doc_listeners = true; 1114 1115 /* listen for pause event */ 1116 document.addEventListener('rp-pause', function(e) { 1117 instance = e.detail.instance; 1118 if (radio_player_data.scripts[instance] == 'amplitude') { 1119 radio_player_event_handler('paused', {instance:instance, script:'amplitude'}); 1120 } 1121 }, false); 1122 1123 /* listen for stop event */ 1124 document.addEventListener('rp-stop', function(e) { 1125 instance = e.detail.instance; 1126 if (radio_player_data.scripts[instance] == 'amplitude') { 1127 radio_player_event_handler('stopped', {instance:instance, script:'amplitude'}); 1128 } 1129 }, false); 1130 } 1131 1132 /* match script select dropdown value */ 1133 if (container.find(' .rp-script-select').length) {container.find('.rp-script-select').val('amplitude');} 1134 1135 return radio_player_instance; 1136} 1137 1138 1139/* jPlayer Player Script */ 1140function radio_player_jplayer(instance, url, format, fallback, fformat) { 1141 1142 player_id = 'radio_player_'+instance; 1143 container_id = 'radio_container_'+instance; 1144 container = jQuery('#'+container_id); 1145 if (url == '') {url = radio_player.settings.url;} 1146 if (url == '') {return;} 1147 if (!format || (format == '') || (format == 'aac')) {format = 'm4a';} 1148 /* if (fallback == '') {fallback = radio_player.settings.fallback;} */ 1149 if (!fallback || !fformat || (fformat == '')) {fallback = ''; fformat = '';} 1150 if (fformat == 'aac') {fformat = 'm4a';} 1151 1152 /* set volume */ 1153 if (container.find('.rp-volume-slider').length && container.find('.rp-volume-slider').hasClass('changed')) { 1154 volume = container.find('.rp-volume-slider').val(); 1155 } else if (typeof container.attr('data-volume') != 'undefined') { 1156 volume = container.attr('data-volume'); 1157 } else if (typeof radio_player_data.state.volume != 'undefined') { 1158 volume = radio_player_data.state.volume; 1159 } else {volume = radio_player.settings.volume;} 1160 radio_player_volume_slider(instance,volume); 1161 volume = parseFloat(volume / 100); 1162 if (radio_player.debug) {console.log('jPlayer init Volume: '+volume);} 1163 1164 media = {}; /* media.title = ''; */ media[format] = url; supplied = format; 1165 /* if (fallback && fformat) {media[fformat] = fallback; supplied += ', '+fformat;} */ 1166 radio_player.jplayer_media = media; 1167 radio_player.jplayer_ready = false; 1168 radio_player.jplayer_instance = instance; 1169 1170 /* load jplayer */ 1171 if (radio_player.debug) {console.log('Init jPlayer: '+instance+' : '+url+' : '+format+' : '+fallback+' : '+fformat+' : '+volume);} 1172 radio_player_instance = jQuery('#'+player_id).jPlayer({ 1173 ready: function () { 1174 console.log(radio_player.jplayer_media); 1175 jQuery(this).jPlayer('setMedia', radio_player.jplayer_media); 1176 radio_player.jplayer_ready = true; 1177 }, 1178 supplied: supplied, 1179 cssSelectorAncestor: '#'+container_id, 1180 swfPath: '', /* radio_player.settings.swf_path, */ 1181 idPrefix: 'rp', 1182 preload: 'none', 1183 volume: volume, 1184 globalVolume: true, 1185 useStateClassSkin: true, 1186 autoBlur: false, 1187 smoothPlayBar: true, 1188 keyEnabled: true, 1189 remainingDuration: false, 1190 toggleDuration: false, 1191 backgroundColor: 'transparent', 1192 }); 1193 radio_player_data.players[instance] = radio_player_instance; 1194 radio_player_data.scripts[instance] = 'jplayer'; 1195 1196 audio = radio_player_instance.data('jPlayer').htmlElement.audio; 1197 if (radio_player.debug) {console.log('jPlayer Audio Element:'); console.log(audio);} 1198 audio.setAttribute('instance-id', instance); 1199 1200 /* bind load event */ 1201 jQuery('#'+player_id).bind(jQuery.jPlayer.event.load, function(e) { 1202 radio_player.loading = false; 1203 instance = radio_player_event_instance(e, 'Loaded', 'jplayer'); 1204 radio_player_event_handler('loaded', {instance:instance, script:'jplayer'}); 1205 }); 1206 1207 /* bind play event */ 1208 jQuery('#'+player_id).bind(jQuery.jPlayer.event.play, function(e) { 1209 radio_player.loading = false; 1210 instance = radio_player_event_instance(e, 'Playing', 'jplayer'); 1211 radio_player_event_handler('playing', {instance:instance, script:'jplayer'}); 1212 radio_player_pause_others(instance); 1213 }); 1214 1215 /* bind pause and stop events */ 1216 jQuery('#'+player_id).bind(jQuery.jPlayer.event.pause, function(e) { 1217 instance = radio_player_event_instance(e, 'Paused', 'jplayer'); 1218 radio_player_event_handler('paused', {instance:instance, script:'jplayer'}); 1219 }); 1220 jQuery('#'+player_id).bind(jQuery.jPlayer.event.stop, function(e) { 1221 instance = radio_player_event_instance(e, 'Stopped', 'jplayer'); 1222 radio_player_event_handler('stopped', {instance:instance, script:'jplayer'}); 1223 }); 1224 1225 /* bind volume change event */ 1226 jQuery('#'+player_id).bind(jQuery.jPlayer.event.volumechange, function(e) { 1227 instance = radio_player_event_instance(e, 'Volume', 'jplayer'); 1228 if (instance && (radio_player_data.scripts[instance] == 'jplayer')) { 1229 radio_player_volume_changed(instance, 'jplayer', volume); 1230 } 1231 }); 1232 1233 /* bind can play debug message */ 1234 jQuery('#'+player_id).bind(jQuery.jPlayer.event.canplay, function(e) { 1235 instance = radio_player_event_instance(e, 'CanPlay', 'jplayer'); 1236 console.log('jPlayer Instance '+instance+' Can Play'); 1237 }); 1238 1239 /* bind player error event to fallback scripts */ 1240 jQuery('#'+player_id).bind(jQuery.jPlayer.event.error, function(e) { 1241 radio_player.jplayer_ready = false; 1242 instance = radio_player_event_instance(e, 'Error', 'jplayer'); 1243 radio_player_event_handler('error', {instance:instance, script:'jplayer'}); 1244 radio_player_player_fallback(instance, 'jplayer', 'jPlayer Error'); 1245 }); 1246 1247 /* match script select dropdown value */ 1248 if (container.find('.rp-script-select').length) {container.find('.rp-script-select').val('jplayer');} 1249 1250 return radio_player_instance; 1251} 1252 1253/* Howler Player Script */ 1254function radio_player_howler(instance, url, format, fallback, fformat) { 1255 1256 container = jQuery('#radio_container_'+instance); 1257 if (url == '') {url = radio_player.settings.url;} 1258 if (url == '') {return;} 1259 if (!format || (format == '')) {format = 'aac';} 1260 /* if (fallback == '') {fallback = radio_player.settings.fallback;} */ 1261 if (!fallback || !fformat || (fformat == '')) {fallback = ''; fformat = '';} 1262 1263 /* set sources */ 1264 sources = new Array(); formats = new Array(); 1265 sources[0] = url; /* if (fallback != '') {sources[1] = fallback;} */ 1266 formats[0] = format; /* if ((fallback != '') && (fformat != '')) {formats[1] = fformat;} */ 1267 1268 /* set volume */ 1269 if (container.find('.rp-volume-slider').length && container.find('.rp-volume-slider').hasClass('changed')) { 1270 volume = container.find('.rp-volume-slider').val(); 1271 } else if (typeof container.attr('data-volume') != 'undefined') { 1272 volume = container.attr('data-volume'); 1273 } else if (typeof radio_player_data.state.volume != 'undefined') { 1274 volume = radio_player_data.state.volume; 1275 } else {volume = radio_player.settings.volume;} 1276 radio_player_volume_slider(instance,volume); 1277 volume = parseFloat(volume / 100); 1278 1279 /* intialize player */ 1280 if (radio_player.debug) {console.log('Init Howler: '+instance+' : '+url+' : '+format+' : '+fallback+' : '+fformat+' : '+volume);} 1281 radio_player_instance = new Howl({ 1282 src: sources, 1283 format: formats, 1284 html5: false, 1285 autoplay: false, 1286 preload: false, 1287 volume: volume, 1288 onload: function(e) { 1289 /* possible bug: maybe not always being triggered ? */ 1290 radio_player.loading = false; 1291 instance = radio_player_match_instance(this, e, 'howler'); 1292 radio_player_event_handler('loaded', {instance:instance, script:'howler'}); 1293 }, 1294 onplay: function(e) { 1295 radio_player.loading = false; 1296 instance = radio_player_match_instance(this, e, 'howler'); 1297 radio_player_event_handler('playing', {instance:instance, script:'howler'}); 1298 radio_player_pause_others(instance); 1299 }, 1300 onpause: function(e) { 1301 instance = radio_player_match_instance(this, e, 'howler'); 1302 radio_player_event_handler('paused', {instance:instance, script:'howler'}); 1303 }, 1304 onstop: function(e) { 1305 instance = radio_player_match_instance(this, e, 'howler'); 1306 radio_player_event_handler('stopped', {instance:instance, script:'howler'}); 1307 }, 1308 onvolume: function(e) { 1309 instance = radio_player_match_instance(this, e, 'howler'); 1310 if (instance && (radio_player_data.scripts[instance] == 'howler')) { 1311 volume = this.volume() * 100; 1312 if (volume > 100) {volume = 100;} 1313 radio_player_volume_changed(instance, 'howler', volume); 1314 } 1315 }, 1316 onloaderror: function(id,e) { 1317 instance = radio_player_match_instance(this, e, 'howler'); 1318 radio_player_event_handler('error', {instance:instance, script:'howler'}); 1319 if (radio_player.debug) {console.log('Load Error, Howler Instance: '+instance+', Sound ID: '+id);} 1320 radio_player_player_fallback(instance, 'howler', 'Howler Load Error'); 1321 }, 1322 onplayerror: function(id,e) { 1323 instance = radio_player_match_instance(this, e, 'howler'); 1324 radio_player_event_handler('error', {instance:instance, script:'howler'}); 1325 if (radio_player.debug) {console.log('Play Error, Howler Instance: '+instance+', Sound ID: '+id);} 1326 radio_player_player_fallback(instance, 'howler', 'Howler Play Error'); 1327 }, 1328 }); 1329 radio_player_data.players[instance] = radio_player_instance; 1330 radio_player_data.scripts[instance] = 'howler'; 1331 1332 /* match script select dropdown value */ 1333 if (container.find('.rp-script-select').length) {container.find('.rp-script-select').val('howler');} 1334 1335 return radio_player_instance; 1336} 1337 1338 1339/* === Document Ready Functions === */ 1340 1341/* --- add player event listeners --- */ 1342var radio_player_initializing; 1343jQuery(document).ready(function() { 1344 1345 /* --- set window unique ID --- */ 1346 radio_player_window_guid(); 1347 1348 /* --- preserve window tab ID on tab reload --- */ 1349 window.addEventListener('beforeunload', function (e) { 1350 window.sessionStorage.tabId = window.tabId; return null; 1351 }); 1352 1353 /* --- prevent conflict on duplicate script load --- */ 1354 if (radio_player_initializing) {return;} 1355 radio_player_initializ
1355ing = true; 1356 1357 /* --- preload pause image --- */ 1358 /* src = jQuery('.rp-pause-image-preload').attr('src'); image = new Image(); image.src = src; */ 1359 1360 /* listen for window broadcast messages */ 1361 if (typeof sysend != 'undefined') { 1362 sysend.on('radio-play', function(message) {radio_player_check_to_pause(message);} ); 1363 /* sysend.on('radio-request', function(message) {radio_player_broadcast_action(message);} ); */ 1364 radio_player_custom_event('rp-sysend', false); 1365 } 1366 1367 /* --- hide all volume controls if no support (iOS) --- */ 1368 novolumesupport = radio_player_volume_test(); 1369 if (novolumesupport) { 1370 jQuery('.rp-volume-controls').each(function() { 1371 jQuery(this).hide(); 1372 jQuery('.rp-volume-button').hide(); 1373 container = jQuery(this).closest('.radio-container'); 1374 if (container.length) {container.addClass('no-volume-controls');} 1375 container = jQuery(this).closest('.rp-container'); 1376 if (container.length) {container.addClass('no-volume-controls');} 1377 }); 1378 jQuery('.rp-volume-button').hide(); 1379 } 1380 1381 /* --- bind pause/play button clicks --- */ 1382 jQuery('.rp-play-pause-button').on('click', function(e) { 1383 e.stopImmediatePropagation(); e.preventDefault(); 1384 container = jQuery(this).closest('.radio-container'); 1385 if (!container.length) {container = jQuery(this).closest('.rp-container');} 1386 instance = container.attr('data-instance'); 1387 if (radio_player.debug) {console.log('Play/Pause Button Click on Instance '+instance);} 1388 1389 /* maybe toggle currently playing radio */ 1390 inst = instance; 1391 if (typeof radio_player_toggle_current == 'function') { 1392 if (radio_player.debug) {console.log('Trigger Toggle of Player. New Instance '+instance);} 1393 done = radio_player_toggle_current(instance); 1394 if (done) {return;} 1395 } 1396 instance = inst; /* <- this is a fix */ 1397 1398 /* check to pause or play */ 1399 if (radio_player_is_loading(instance) || radio_player_is_playing(instance)) { 1400 if (radio_player.debug) {console.log('Trigger Pause of Player Instance '+instance);} 1401 radio_player_pause_instance(instance); 1402 } else { 1403 if (radio_player.debug) {console.log('Trigger Play of Player Instance '+instance);} 1404 instances = Object.keys(radio_player_data.players); 1405 jQuery('#radio_player_'+instance).addClass('loading'); 1406 if (instances.includes(instance)) { 1407 radio_player_play_instance(instance); 1408 } else { 1409 radio_player_play_source(instance); 1410 } 1411 } 1412 }); 1413 1414 /* --- bind volume slider background changes --- */ 1415 jQuery('.rp-volume-slider').on('mousemove', function() { 1416 container = jQuery(this).closest('.radio-container, .rp-container'); 1417 instance = container.attr('data-instance'); 1418 volume = parseInt(jQuery(this).val()); 1419 radio_player_volume_slider(instance,volume); 1420 }); 1421 1422 /* --- bind volume slider changes --- */ 1423 jQuery('.rp-volume-slider').on('change', function() { 1424 container = jQuery(this).closest('.radio-container, .rp-container'); 1425 instance = container.attr('data-instance'); 1426 if (radio_player.debug) {console.log('Volume Click Instance '+instance+': '+volume);} 1427 volume = parseInt(jQuery(this).val()); 1428 if (volume == 0) {mute = true;} else {mute = false;} 1429 radio_player_volume_slider(instance,volume); 1430 radio_player_change_volume(instance,volume); 1431 radio_player_set_state('volume',volume); 1432 }); 1433 1434 /* ---- bind mute clicks --- */ 1435 jQuery('.rp-mute').on('click', function() { 1436 container = jQuery(this).closest('.radio-container, .rp-container'); 1437 instance = container.attr('data-instance'); 1438 if (radio_player.debug) {console.log('Mute Click Instance '+instance);} 1439 if (typeof radio_player_toggle_mute == 'function') { 1440 done = radio_player_toggle_mute(instance); if (done) {return;} 1441 } 1442 mute = (!container.hasClass('muted')); 1443 radio_player_mute_unmute(instance,mute); 1444 radio_player_set_state('mute',mute); 1445 }); 1446 1447 /* --- bind max volume clicks --- */ 1448 jQuery('.rp-volume-max').on('click', function() { 1449 container = jQuery(this).closest('.radio-container, .rp-container'); 1450 instance = container.attr('data-instance'); 1451 if (!container.hasClass('maxed')) {container.addClass('maxed');} 1452 container.find('.rp-volume-slider').val(100); 1453 radio_player_volume_slider(instance,100); 1454 radio_player_change_volume(instance,100); 1455 radio_player_mute_unmute(instance,false); 1456 radio_player_set_state('mute',false); 1457 }); 1458 1459 /* --- bind volume decrease/increase clicks --- */ 1460 jQuery('.rp-volume-down, .rp-volume-up').on('click', function() { 1461 container = jQuery(this).closest('.radio-container, .rp-container'); 1462 instance = container.attr('data-instance'); 1463 slider = container.find('.rp-volume-slider'); 1464 oldvolume = parseInt(slider.val()); 1465 if (jQuery(this).hasClass('rp-volume-down')) { 1466 volume = oldvolume - 5; if (volume < 0) {volume = 0;} slider.val(volume); 1467 if (radio_player.debug) {console.log('Volume Down Instance '+instance+': '+oldvolume
1467+' to '+volume);} 1468 } else if (jQuery(this).hasClass('rp-volume-up')) { 1469 volume = oldvolume + 5; if (volume > 100) {volume = 100;} slider.val(volume); 1470 if (radio_player.debug) {console.log('Volume Up Instance '+instance+': '+oldvolume+' to '+volume);} 1471 } 1472 radio_player_volume_slider(instance,volume); 1473 radio_player_change_volume(instance,volume); 1474 radio_player_set_state('volume',volume); 1475 /* if (volume > 0) {mute = false;} else {mute = true;} 1476 radio_player_mute_unmute(instance,mute); 1477 radio_player_set_state('mute',mute); */ 1478 }); 1479 1480 /* --- detect script selection switcher change --- */ 1481 jQuery('.rp-script-select').change(function() { 1482 container = jQuery(this).closest('.radio-container, .rp-container'); 1483 instance = container.attr('data-instance'); 1484 script = jQuery(this).val(); radio_player_switch_script(instance,script); 1485 }); 1486 1487 /* --- add player listener to cancel loading flag --- */ 1488 document.addEventListener('rp-play', function(e) { 1489 instance = e.detail.instance; 1490 jQuery('#radio_player_'+instance).addClass('loading'); 1491 }, false); 1492 document.addEventListener('rp-playing', function(e) { 1493 instance = e.detail.instance; 1494 jQuery('#radio_player_'+instance).removeClass('loading'); 1495 }, false); 1496 document.addEventListener('rp-pause', function(e) { 1497 instance = e.detail.instance; 1498 jQuery('#radio_player_'+instance).removeClass('loading'); 1499 }, false); 1500 document.addEventListener('rp-stop', function(e) { 1501 instance = e.detail.instance; 1502 jQuery('#radio_player_'+instance).removeClass('loading'); 1503 }, false); 1504 1505 /* --- pause on media elements player play --- */ 1506 jQuery('audio.mejs__player').on('play', function(e) { 1507 if (!radio_player.settings.singular) {return;} 1508 jQuery('.radio-container').each(function() { 1509 instance = jQuery(this).attr('data-instance'); 1510 radio_player_pause_instance(instance); 1511 radio_player_broadcast_playing(instance); 1512 }); 1513 }); 1514 1515 /* --- pause media elements on player play --- */ 1516 document.addEventListener('rp-play', function(e) { 1517 if (!radio_player.settings.singular) {return;} 1518 jQuery('audio.mejs__player').each(function() { 1519 el = jQuery(this)[0]; 1520 if (!el.paused) { 1521 el.pause(); 1522 if (radio_player.debug) {console.log( 'Paused MediaElement Audio: '+el.src);} 1523 } 1524 }); 1525 }, false); 1526 1527}); 1528 1529 1530/* === Custom Events === */ 1531 1532/* --- Trigger Custom Event --- */ 1533function radio_player_custom_event(name, detail) { 1534 params = {bubbles: false, cancelable: false, detail: detail} 1535 var event = new CustomEvent(name, params); document.dispatchEvent(event); 1536 if (radio_player.debug) {console.log('Radio Player Custom Event: '+name);} 1537} 1538 1539/* --- CustomEvent support polyfill --- */ 1540(function () { 1541 if (typeof window.CustomEvent === 'function') {return false;} 1542 function CustomEvent(event, params) { 1543 params = params || {bubbles: false, cancelable: false, detail: undefined}; 1544 var evt = document.createEvent('CustomEvent'); 1545 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 1546 return evt; 1547 } 1548 CustomEvent.prototype = window.Event.prototype; 1549 window.CustomEvent = CustomEvent; 1550})();
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.