File manager - Edit - /home/monara/public_html/efm_web/wp-content/plugins/radio-station/includes/master-schedule.php
Back
<?php if ( !defined( 'ABSPATH' ) ) exit; /* * Master Show schedule * Author: Nikki Blight * @Since: 2.1.1 */ // - Master Schedule Shortcode // - Schedule Loader Script // - AJAX Schedule Loader // - Show Genre Selector // - Table View Javascript // - Tabbed View Javascript // - List View Javascript // ------------------------- // Master Schedule Shortcode // ------------------------- // 2.5.0: added optional radio-schedule shortcode alias add_shortcode( 'radio-schedule', 'radio_station_master_schedule' ); add_shortcode( 'master-schedule', 'radio_station_master_schedule' ); function radio_station_master_schedule( $atts ) { global $radio_station_data; // 2.5.0: maybe set schedule instances array if ( !isset( $radio_station_data['schedules'] ) ) { $radio_station_data['schedules'] = array(); } if ( !isset( $radio_station_data['schedules']['instances'] ) ) { $radio_station_data['schedules']['instances'] = -1; } $radio_station_data['schedules']['instances']++; $instances = $radio_station_data['schedules']['instances']; // 2.5.10.1: allow specifying instance value for AJAX loading if ( isset( $atts['instance'] ) ) { $instance = $atts['instance']; unset( $atts['instance'] ); } // --- make attributes backward compatible --- // 2.3.0: convert old list attribute to view if ( !isset( $atts['view'] ) && isset( $atts['list'] ) ) { if ( 1 === (int) $atts['list'] ) { $atts['list'] = 'list'; } $atts['view'] = $atts['list']; unset( $atts['list'] ); } // 2.3.0: convert show_djs attribute to show_hosts if ( !isset( $atts['show_hosts'] ) && isset( $atts['show_djs'] ) ) { $atts['show_hosts'] = $atts['show_djs']; unset( $atts['show_djs'] ); } // 2.3.0: convert display_show_time attribute to show_times if ( !isset( $atts['show_times'] ) && isset( $atts['display_show_time'] ) ) { $atts['show_times'] = $atts['display_show_time']; unset( $atts['display_show_time'] ); } // 2.3.0: convert single_day attribute to days if ( !isset( $atts['days'] ) && isset( $atts['single_day'] ) ) { $atts['days'] = $atts['single_day']; unset( $atts['single_day'] ); } // 2.5.0: convert time attribute to time_format if ( isset( $atts['time'] ) ) { $atts['time_format'] = $atts['time']; unset( $atts['time'] ); } // 2.5.0: convert widget option time_header to clock/timezone atts if ( isset( $atts['time_header'] ) ) { if ( 'clock' == $atts['time_header'] ) { $atts['clock'] = 1; $atts['timezone'] = 0; } elseif ( 'timezone' == $atts['time_header'] ) { $atts['clock'] = 0; $atts['timezone'] = 1; } elseif ( 'none' == $atts['time_header'] ) { $atts['clock'] = 0; $atts['timezone'] = 0; } } if ( RADIO_STATION_DEBUG ) { echo '<span style="display:none;">Master Schedule Shortcode Attributes: ' . esc_html( print_r( $atts, true ) ) . '</span>'; } // 2.5.10.1: get default AJAX loading setting $ajax = ( 'yes' == radio_station_get_setting( 'schedule_ajax' ) ) ? 1 : 0; // --- get default clock display settings --- $clock = radio_station_get_setting( 'schedule_clock' ); $time_format = (int) radio_station_get_setting( 'clock_time_format' ); // --- merge shortcode attributes with defaults --- // 2.3.0: added show_desc (default off) // 2.3.0: added show_hosts (alias of show_djs) // 2.3.0: added show_file attribute (default off) // 2.3.0: added show_encore attribute (default on) // 2.3.0: added display clock attribute (default on) // 2.3.0: added display selector attribute (default on) // 2.3.0: added link_hosts attribute (default off) // 2.3.0: set default time format according to plugin setting // 2.3.0: set default table display to new table formatting // 2.3.2: added start_day attribute (for use width days) // 2.3.2: added display_day, display_date and display_month attributes // 2.3.3.9: added start_date attribute for non-now schedules // 2.3.3.9: added active_date attribute for schedule switching $defaults = array( // --- schedule view --- 'view' => 'table', // --- control display options --- 'selector' => 1, 'clock' => $clock, 'timezone' => 1, // --- schedule display options --- 'days' => false, 'start_day' => false, 'start_date' => false, 'active_date' => false, 'display_day' => 'short', 'display_date' => 'jS', 'display_month' => 'short', 'time_format' => $time_format, // --- show display options --- 'show_link' => 1, 'show_times' => 1, 'show_image' => 0, 'show_desc' => 0, 'show_hosts' => 0, 'link_hosts' => 0, 'show_genres' => 0, 'show_encore' => 1, 'show_file' => 0, // --- instance values --- // 2.5.10.1: add AJAX attribute value 'ajax' => $ajax, 'widget' => 0, 'block' => 0, // 'instance' => $instance, // --- converted and deprecated --- // 'list' => 0, // 'show_djs' => 0, // 'display_show_time' => 1, ); // 2.3.0: change some defaults for tabbed and list view // 2.3.2: check for comma separated view list $view = ''; $views = array(); if ( isset( $atts['view'] ) ) { // 2.3.2: view value to lowercase to be case insensitive $view = $atts['view'] = strtolower( $atts['view'] ); if ( strstr( $atts['view'], ',' ) ) { $views = explode( ',', $atts['view'] ); foreach ( $views as $i => $aview ) { if ( 'tabbed' == $aview ) { $aview = 'tabs'; } $views[$i] = trim( $aview ); } // 2.3.3.9: set default view for multiviews to table $defaults['default_view'] = 'table'; } elseif ( 'tabbed' == $view ) { // 2.3.3.9: fix for possible misspelt tab view $view = 'tabs'; } // 2.3.3.9: set prefixed defaults for multiple views if ( 'tabs' == $atts['view'] ) { // 2.3.2: add show descriptions default for tabbed view // 2.3.2: add display_day and display_date attributes // 2.3.3: revert show description default for tabbed view // 2.3.3.8: add default show image position (left aligned) // 2.3.3.8: add default for hide past shows (false) // 2.5.0: change date display default to true $defaults['show_image'] = 1; $defaults['show_hosts'] = 1; $defaults['show_genres'] = 1; $defaults['display_day'] = 'full'; $defaults['display_date'] = true; $defaults['image_position'] = 'left'; $defaults['hide_past_shows'] = false; } elseif ( in_array( 'tabs', $views ) ) { // note: these apply to tab view only $defaults['image_position'] = 'left'; $defaults['hide_past_shows'] = false; // 2.5.0: remove default separate view settings for widgets if ( ( !isset( $atts['widget'] ) || !$atts['widget'] ) && ( !isset( $atts['block'] ) || !$atts['block'] ) ) { $defaults['tabs_show_image'] = 1; $defaults['tabs_show_hosts'] = 1; $defaults['tabs_show_genres'] = 1; $defaults['tabs_display_day'] = 'full'; $defaults['tabs_display_date'] = true; } } if ( 'list' == $atts['view'] ) { // 2.3.2: add display date attribute $defaults['show_genres'] = 1; $defaults['display_date'] = false; } elseif ( in_array( 'list', $views ) ) { // 2.5.0: remove default separate view settings for widgets if ( ( !isset( $atts['widget'] ) || !$atts['widget'] ) && ( !isset( $atts['block'] ) || !$atts['block'] ) ) { $defaults['list_show_genres'] = 1; $defaults['list_display_date'] = false; } } if ( ( 'divs' == $atts['view'] ) || ( in_array( 'divs', $views ) ) ) { // 2.3.3.8: moved divs view only default here // 2.3.3.9: added check if divs in views array $defaults['divheight'] = 45; } } // 2.3.3.9: filter defaults according to view(s) $defaults = apply_filters( 'radio_station_master_schedule_default_atts', $defaults, $view, $views, $atts ); // --- merge attributes with defaults --- $atts = shortcode_atts( $defaults, $atts, 'master-schedule' ); if ( RADIO_STATION_DEBUG ) { echo '<span style="display:none;">Master Schedule Shortcode Attributes: ' . esc_html( print_r( $atts, true ) ) . '</span>'; } // 2.5.0: force empty start_day string to false if ( '' == $atts['start_day'] ) { $atts['start_day'] = false; } // --- enqueue schedule stylesheet --- // 2.3.0: use abstracted method for enqueueing widget styles radio_station_enqueue_style( 'schedule' ); // --- set initial empty output string --- $output = ''; // 2.3.3.9: remove check if clock shortcode present // 2.3.3.6: set new line for easier debug viewing // 2.5.0: just set new line for output readability // $newline = "\n"; // --- table for selector and clock --- // 2.3.0: moved out from templates to apply to all views // 2.3.2: moved shortcode calls inside and added filters // 2.5.0: added instances IDs and use class for selector $id = ( 0 == $instances ) ? '' : '-' . $instances; $output .= '<div id="master-schedule-controls-wrapper' . esc_attr( $id ) . '" class="master-schedule-controls-wrapper">' . "\n"; $controls = array(); // --- display radio clock or timezone (or neither) --- if ( $atts['clock'] ) { // --- radio clock --- $clock_atts = apply_filters( 'radio_station_schedule_clock', array(), $atts ); $controls['clock'] = '<div id="master-schedule-clock-wrapper' . esc_attr( $id ) . '" class="master-schedule-clock-wrapper">' . "\n"; $controls['clock'] .= radio_station_clock_shortcode( $clock_atts ); $controls['clock'] .= "\n" . '</div>' . "\n"; } elseif ( $atts['timezone'] ) { // --- radio timezone --- $timezone_atts = apply_filters( 'radio_station_schedule_clock', array(), $atts ); $controls['timezone'] = '<div id="master-schedule-timezone-wrapper' . esc_attr( $id ) . '" class="master-schedule-timezone-wrapper">' . "\n"; $controls['timezone'] .= radio_station_timezone_shortcode( $timezone_atts ); $controls['timezone'] .= "\n" . '</div>' . "\n"; } // --- genre selector --- if ( $atts['selector'] ) { $controls['selector'] = '<div id="master-schedule-selector-wrapper' . esc_attr( $id ) . '" class="master-schedule-selector-wrapper">' . "\n"; $controls['selector'] .= radio_station_master_schedule_genre_selector( $instances ); $controls['selector'] .= "\n" . '</div>' . "\n"; } // 2.3.1: add filters for control order $control_order = array( 'clock', 'timezone', 'selector' ); $control_order = apply_filters( 'radio_station_schedule_control_order', $control_order, $atts ); // 2.3.1: add filter for controls HTML $controls = apply_filters( 'radio_station_schedule_controls', $controls, $atts ); // --- add ordered controls to output --- if ( is_array( $control_order ) && ( count( $control_order ) > 0 ) ) { foreach ( $control_order as $control ) { if ( isset( $controls[$control] ) && ( '' != $control ) ) { $output .= $controls[$control]; } } } $output .= '<br></div><br>' . "\n"; $output = apply_filters( 'radio_station_schedule_controls_output', $output, $atts ); // --- hidden inputs for calendar start/active dates --- // 2.3.3.9: added for schedule week change reloading if ( isset( $atts['start_date'] ) && $atts['start_date'] ) { // 2.5.6: use radio_station_get_time instead of date // 2.5.10.1: revert this change as causing incorrect invalidation if ( date( 'Y-m-d', strtotime( $atts['start_date'] ) ) == $atts['start_date'] ) { $start_date = $atts['start_date']; } } if ( !isset( $start_date ) ) { $now = radio_station_get_now(); $start_date = radio_station_get_time( 'date', $now ); } $output .= '<input type="hidden" id="schedule-start-date" value="' . esc_attr( $start_date ) . '">'; $active_date = $start_date; if ( isset( $atts['active_date'] ) && $atts['active_date'] ) { // 2.5.6: use radio_station_get_time instead of date if ( $atts['active_date'] == radio_station_get_time( 'Y-m-d', strtotime( $atts['active_date'] ) ) ) { $active_date = $atts['active_date']; } } $output .= '<input type="hidden" id="schedule-active-date" value="' . esc_attr( $active_date ) . '">'; // 2.3.3.9: also added schedule start day input // 2.5.13: ensure start day string is lowercase $start_day = ( $atts['start_day'] ) ? strtolower( $atts['start_day'] ) : ''; $output .= '<input type="hidden" id="schedule-active-day" value="' . esc_attr( $start_day ) . '">'; $output .= '<input type="hidden" id="schedule-start-day" value="' . esc_attr( $start_day ) . '">'; // --- enqueue schedule loader script --- $js = radio_station_master_schedule_loader_js( $atts ); // 2.5.0: use radio_station_add_inline_script radio_station_add_inline_script( 'radio-station', $js ); // --- schedule display override --- // 2.3.1: add full schedule override filter // 2.3.3.9: add existing controls output to filter // 2.5.10.1: maybe merge instance ID back into atts value if ( isset( $instance ) ) { $atts = array_merge( $atts, array( 'instance' => $instance ) ); } $override = apply_filters( 'radio_station_schedule_override', $output, $atts ); if ( strstr( $override, '<!-- SCHEDULE OVERRIDE -->' ) ) { $override = str_replace( '<!-- SCHEDULE OVERRIDE -->', '', $override ); // 2.5.0: added wrapper to shortcode output $output = '<div id="master-schedule' . esc_attr( $id ) . '" class="master-schedule">' . $override . '</div>' . "\n"; return $output; } // ------------------------- // New Master Schedule Views // ------------------------- // --- load master schedule template --- // 2.2.7: added tabbed master schedule template // 2.2.7: add tabbed view javascript to footer // 2.3.0: use new data model for table and tabs view // 2.3.0: check for user theme templates // 2.3.3.9: use output buffering on templates // 2.3.3.9: get and enqueue scripts inline directly if ( 'table' == $atts['view'] ) { // 2.5.10.1: added check for specified instance if ( !isset( $instance ) ) { // 2.5.0: set view instance number if ( !isset( $radio_station_data['schedules']['table'] ) ) { $radio_station_data['schedules']['table'] = -1; } $radio_station_data['schedules']['table']++; $instance = $radio_station_data['schedules']['table']; } // 2.5.6: fix for missing id definition $id = ( 0 == $instance ) ? '' : '-' . $instance; // --- load table view template --- ob_start(); $template = radio_station_get_template( 'file', 'master-schedule-table.php' ); require $template; $html = ob_get_contents(); ob_end_clean(); // --- enqueue table view script --- $js = radio_station_master_schedule_table_js(); // 2.5.0: use radio_station_add_inline_script radio_station_add_inline_script( 'radio-station', $js ); // --- filter and return --- // 2.5.0: added prefixed filter for consistency $html = apply_filters( 'radio_station_master_schedule_table_view', $html, $atts ); // note: keep backwards compatible non-prefixed filter $html = apply_filters( 'master_schedule_table_view', $html, $atts ); // 2.5.0: added shortcode wrapper $output = '<div id="master-schedule' . esc_attr( $id ) . '" class="master-schedule">' . $output . $html . '</div>' . "\n"; return $output; } elseif ( 'tabs' == $atts['view'] ) { // 2.5.10.1: added check for specified instance if ( !isset( $instance ) ) { // 2.5.0: set view instance number if ( !isset( $radio_station_data['schedules']['tabs'] ) ) { $radio_station_data['schedules']['tabs'] = -1; } $radio_station_data['schedules']['tabs']++; $instance = $radio_station_data['schedules']['tabs']; } // 2.5.6: fix for missing id definition $id = ( 0 == $instance ) ? '' : '-' . $instance; // --- load tabs view template --- ob_start(); $template = radio_station_get_template( 'file', 'master-schedule-tabs.php' ); require $template; $html = ob_get_contents(); ob_end_clean(); // --- enqueue tabs view script --- $js = radio_station_master_schedule_tabs_js(); // 2.5.0: use radio_station_add_inline_script radio_station_add_inline_script( 'radio-station', $js ); // --- filter and return --- // 2.5.0: added prefixed filter for consistency $html = apply_filters( 'radio_station_master_schedule_tabs_view', $html, $atts ); // note: keep backwards compatible non-prefixed filter $html = apply_filters( 'master_schedule_tabs_view', $html, $atts ); // 2.5.0: added shortcode wrapper $output = '<div id="master-schedule' . esc_attr( $id ) . '" class="master-schedule">' . $output . $html . '</div>' . "\n"; return $output; } elseif ( 'list' == $atts['view'] ) { // 2.5.10.1: added check for specified instance if ( !isset( $instance ) ) { // 2.5.0: set view instance number if ( !isset( $radio_station_data['schedules']['list'] ) ) { $radio_station_data['schedules']['list'] = -1; } $radio_station_data['schedules']['list']++; $instance = $radio_station_data['schedules']['list']; } // 2.5.6: fix for missing id definition $id = ( 0 == $instance ) ? '' : '-' . $instance; // --- load list view template --- ob_start(); $template = radio_station_get_template( 'file', 'master-schedule-list.php' ); require $template; $html = ob_get_contents(); ob_end_clean(); // --- enqueue list view script --- $js = radio_station_master_schedule_list_js(); // 2.5.0: use radio_station_add_inline_script radio_station_add_inline_script( 'radio-station', $js ); // --- filter and return --- // 2.5.0: added prefixed filter for consistency $html = apply_filters( 'radio_station_master_schedule_list_view', $html, $atts ); // note: keep backwards compatible non-prefixed filter $html = apply_filters( 'master_schedule_list_view', $html, $atts ); // 2.5.0: added shortcode wrapper $output = '<div id="master-schedule' . esc_attr( $id ) . '" class="master-schedule">' . $output . $html . '</div>' . "\n"; return $output; } // ---------------------- // Legacy Master Schedule // ---------------------- // note: Legacy and Divs Views do not include Schedule Overrides global $wpdb; // 2.3.0: remove unused default DJ name option // $default_dj = get_option( 'dj_default_name' ); // --- check to see what day of the week we need to start on --- $start_of_week = get_option( 'start_of_week' ); $days_of_the_week = array( 'Sunday' => array(), 'Monday' => array(), 'Tuesday' => array(), 'Wednesday' => array(), 'Thursday' => array(), 'Friday' => array(), 'Saturday' => array(), ); $week_start = array_slice( $days_of_the_week, $start_of_week ); foreach ( $days_of_the_week as $i => $weekday ) { if ( $start_of_week > 0 ) { $add = $days_of_the_week[$i]; unset( $days_of_the_week[$i] ); $days_of_the_week[$i] = $add; } $start_of_week--; } // --- create the master_list array based on the start of the week --- $master_list = array(); for ( $i = 0; $i < 24; $i++ ) { $master_list[$i] = $days_of_the_week; } // --- get the show schedules, excluding shows marked as inactive --- $show_shifts = $wpdb->get_results( "SELECT meta.post_id, meta.meta_value FROM {$wpdb->postmeta} AS meta JOIN {$wpdb->postmeta} AS active ON meta.post_id = active.post_id JOIN {$wpdb->posts} as posts ON posts.ID = meta.post_id WHERE meta.meta_key = 'show_sched' AND posts.post_status = 'publish' AND ( active.meta_key = 'show_active' AND active.meta_value = 'on' )" ); // --- insert scheduled shifts into the master list --- foreach ( $show_shifts as $shift ) { $shift->meta_value = maybe_unserialize( $shift->meta_value ); // if a show is not scheduled yet, unserialize will return false... fix that. if ( !is_array( $shift->meta_value ) ) { $shift->meta_value = array(); } foreach ( $shift->meta_value as $time ) { // 2.3.0: added check for show disabled switch if ( !isset( $time['disabled'] ) || ( 'yes' == $time['disabled'] ) ) { // --- switch to 24-hour time --- if ( 'pm' === $time['start_meridian'] && 12 !== (int) $time['start_hour'] ) { $time['start_hour'] += 12; } if ( 'am' === $time['start_meridian'] && 12 === (int) $time['start_hour'] ) { $time['start_hour'] = 0; } if ( 'pm' === $time['end_meridian'] && 12 !== (int) $time['end_hour'] ) { $time['end_hour'] += 12; } if ( 'am' === $time['end_meridian'] && 12 === (int) $time['end_hour'] ) { $time['end_hour'] = 0; } // --- check if we are spanning multiple days --- $time['multi-day'] = 0; if ( $time['start_hour'] > $time['end_hour'] || $time['start_hour'] === $time['end_hour'] ) { $time['multi-day'] = 1; } $master_list[$time['start_hour']][$time['day']][$time['start_min']] = array( 'id' => $shift->post_id, 'time' => $time, ); } } } // --- sort the array by time --- foreach ( $master_list as $hour => $days ) { foreach ( $days as $day => $min ) { ksort( $min ); $master_list[$hour][$day] = $min; // we need to take into account shows that start late at night and end the following day foreach ( $min as $i => $time ) { // if it ends at midnight, we don't need to worry about carry-over if ( 0 === (int) $time['time']['end_hour'] && 0 === (int) $time['time']['end_min'] ) { continue; } // if it ends after midnight, fix it // if it starts at night and ends in the morning, end hour is on the following day if ( ( 'pm' === $time['time']['start_meridian'] && 'am' === $time['time']['end_meridian'] ) || // if the start and end times are identical, assume the end time is the following day ( $time['time']['start_hour'] . $time['time']['start_min'] . $time['time']['start_meridian'] === $time['time']['end_hour'] . $time['time']['end_min'] . $time['time']['end_meridian'] ) || // if the start hour is in the morning, and greater than the end hour, assume end hour is the following day ( 'am' === $time['time']['start_meridian'] && $time['time']['start_hour'] > $time['time']['end_hour'] ) ) { if ( 12 === (int) $atts['time'] ) { $time['time']['real_start'] = ( $time['time']['start_hour'] - 12 ) . ':' . $time['time']['start_min']; } else { $pad_hour = ''; if ( $time['time']['start_hour'] < 10 ) { $pad_hour = '0'; } $time['time']['real_start'] = $pad_hour . $time['time']['start_hour'] . ':' . $time['time']['start_min']; } $time['time']['rollover'] = 1; // 2.3.0: use new get next day function $nextday = radio_station_get_next_day( $day ); $master_list[0][$nextday]['00'] = $time; } } } } // --- check for schedule overrides --- // ? TODO - check/include schedule overrides in legacy template views // $overrides = radio_station_master_get_overrides( true ); // --- include the specified master schedule output template --- // 2.3.0: check for user theme templates if ( 'divs' == $atts['view'] ) { $output = ''; // no selector / clock support $template = radio_station_get_template( 'file', 'master-schedule-div.php' ); require $template; } elseif ( 'legacy' == $atts['view'] ) { $template = radio_station_get_template( 'file', 'master-schedule-legacy.php' ); require $template; } return $output; } // ---------------------- // Schedule Loader Script // ---------------------- function radio_station_master_schedule_loader_js( $atts ) { // --- set AJAX URL with attribute keys --- $loader_url = add_query_arg( 'action', 'radio_station_schedule', admin_url( 'admin-ajax.php' ) ); // --- schedule loader function --- // 2.5.0: added instance ID argument // 2.5.10.1: reload multiviews to match direction change $js = "function radio_load_schedule(instance,direction,view,clear) { /* handle multi-views */ if (direction && view) { if (view == 'table') {id = 'master-program-schedule';} else {id = 'master-schedule-'+view;} if (instance > 0) {id += '-'+instance;} container = jQuery('#'+id).closest('.master-schedule'); if ((view != 'table') && container.find('.master-program-schedule').length) { i = container.find('.master-program-schedule').attr('id').replace('master-program-schedule','').replace('-',''); setTimeout(function(i,direction) {radio_load_schedule(i,direction,'table',false);}, 800); } if ((view != 'tabs') && container.find('.master-schedule-tabs').length) { i = container.find('.master-schedule-tabs').attr('id').replace('master-schedule-tabs','').replace('-',''); setTimeout(function(i,direction) {radio_load_schedule(i,direction,'tabs',false);}, 900); } if ((view != 'list') && container.find('.master-schedule-list').length) { i = container.find('.master-schedule-list').attr('id').replace('master-schedule-list','').replace('-',''); setTimeout(function(i,direction) {radio_load_schedule(i,direction,'list',false);}, 1000); } if ((view != 'grid') && container.find('.master-schedule-grid').length) { i = container.find('.master-schedule-grid').attr('id').replace('master-schedule-grid','').replace('-',''); setTimeout(function(i,direction) {radio_load_schedule(i,direction,'grid',false);}, 1100); } if ((view != 'Calendar') && container.find('.master-schedule-calendar').length) { i = container.find('.master-schedule-calendar').attr('id').replace('master-schedule-calendar','').replace('-',''); setTimeout(function(i,direction) {radio_load_schedule(i,direction,'calendar',false);}, 1200); } } if (document.getElementById('schedule-loader-frame')) { view = radio_cookie.get('admin_schedule_view'); radio_load_view(view); return; } startday = document.getElementById('schedule-start-day').value; startdate = document.getElementById('schedule-start-date').value; activedate = document.getElementById('schedule-active-date').value; activeday = document.getElementById('schedule-active-day').value; if (!view) { if ((0 == instance) || (false === instance)) {id = '';} else {id = '-'+instance;} if (jQuery('.master-schedule-view-tab.current-view').length) { view = jQuery('.master-schedule-view-tab.current-view').attr('data'); } else { if (jQuery('#master-program-schedule'+id).length) {view = 'table';} else if (jQuery('#master-schedule-tabs'+id).length) {view = 'tabs';} else if (jQuery('#master-schedule-list'+id).length) {view = 'list';} else if (jQuery('#master-schedule-grid'+id).length) {view = 'grid';} else if (jQuery('#master-schedule-calendar'+id).length) {view = 'calendar';} } } if (radio.debug) {console.log('Reloading Schedule View: '+view);} if (!view) {return;} if (!direction) {offset = 0;} else if (direction == 'previous') {offset = -(7 * 24 * 60 * 60 * 1000);} else if (direction == 'next') {offset = (7 * 24 * 60 * 60 * 1000);} newdate = new Date(new Date(startdate).getTime() + offset).toISOString().substr(0,10); timestamp = Math.floor((new Date()).getTime() / 1000); url = '" . esc_url( $loader_url ); // 2.6.0: add args directly to avoid double escaping $ignore_keys = array( 'start_date', 'view', 'ajax' ); foreach ( $atts as $key => $value ) { if ( !in_array( $key, $ignore_keys ) ) { $js .= '&' . esc_js( $key ) . '=' . esc_js( $value ); } } $js .= "&view='+view+'&instance='+instance+'×tamp='+timestamp+'&start_date='+newdate+'&active_date='+activedate; if (startday != '') {url += '&start_day='+startday;} if (activeday != '') {url += '&active_day='+activeday;} if (clear) {url += '&clear=1';} if (radio.debug) {url += '&rs-debug=1'; console.log('Reload View URL: '+url);} /* if (document.getElementById('schedule-'+view+'-loader').src != url) { document.getElementById('schedule-'+view+'-loader').src = url; } */ iframe_id = 'master-schedule-'+view+'-'+instance+'-loader'; iframe = document.getElementById(iframe_id); if (iframe) { if (iframe.src == url) {return;} iframe.src = url; } else { iframe = document.createElement('iframe'); iframe.id = iframe_id; iframe.src = url; iframe.style.display = 'none'; document.getElementsByTagName('head')[0].appendChild(iframe); } if (radio.debug) {console.log('Loading Schedule via Iframe '+iframe_id+' - URL: '+url);} }" . "\n"; // 2.5.10.1: added multi-schedule reloader $js .= "function radio_load_schedules() { tables = jQuery('.master-program-schedule'); tabs = jQuery('.master-schedule-tabs'); lists = jQuery('.master-schedule-list'); grids = jQuery('.master-schedule-grid'); calendars = jQuery('.master-schedule-calendar'); if (tables.length) {tables.each(function() { instance = jQuery(this).attr('id').replace('master-program-schedule-',''); if (radio.debug) {console.log('Refreshing Table Instance '+instance);} radio_load_schedule(instance,false,'table',true); }); } if (tabs.length) {tabs.each(function() { instance = jQuery(this).attr('id').replace('master-schedule-tabs-',''); if (radio.debug) {console.log('Refreshing Tabs Instance '+instance);} radio_load_schedule(instance,false,'tabs',true); }); } if (lists.length) {lists.each(function() { instance = jQuery(this).attr('id').replace('master-schedule-list-',''); if (radio.debug) {console.log('Refreshing List Instance '+instance);} radio_load_schedule(instance,false,'list',true); }); } if (grids.length) {grids.each(function() { instance = jQuery(this).attr('id').replace('master-schedule-grid-',''); if (radio.debug) {console.log('Refreshing Grid Instance '+instance);} radio_load_schedule(instance,false,'grid',true); }); } if (calendars.length) {calendars.each(function() { instance = jQuery(this).attr('id').replace('master-schedule-calendar-',''); if (radio.debug) {console.log('Refreshing Calendar Instance '+instance); radio_load_schedule(instance,false,'calendar',true);} }); } }" . "\n"; // 2.5.10.1: check for AJAX attribute to refresh schedule on pageload if ( isset( $atts['ajax'] ) && $atts['ajax'] ) { $js .= "jQuery(document).ready(function() {radio_load_schedules();}, 500);" . "\n"; } // --- filter and return --- // 2.5.14: added missing attributes argument to filter $js = apply_filters( 'radio_station_master_schedule_loader_js', $js, $atts ); return $js; } // -------------------- // AJAX Schedule Loader // -------------------- add_action( 'wp_ajax_radio_station_schedule', 'radio_station_ajax_schedule_loader' ); add_action( 'wp_ajax_nopriv_radio_station_schedule', 'radio_station_ajax_schedule_loader' ); function radio_station_ajax_schedule_loader() { // --- maybe clear cached data --- if ( isset( $_REQUEST['clear'] ) && ( '1' === sanitize_text_field( $_REQUEST['clear'] ) ) ) { radio_station_clear_cached_data( false ); } // 2.5.0: get schedule instance ID $instance = absint( $_REQUEST['instance'] ); // 2.5.13 use the active day if set $active_date = sanitize_text_field( $_REQUEST['active_date'] ); $active_day = sanitize_text_field( $_REQUEST['active_day'] ); $day = ( '' != $active_day ) ? $active_day : strtolower( date( 'l', strtotime( $active_date ) ) ); // --- sanitize shortcode attributes --- $debug = false; // $debug = true; $atts = radio_station_sanitize_shortcode_values( 'master-schedule' ); if ( RADIO_STATION_DEBUG || $debug ) { echo "Full Request Inputs: " . esc_html( print_r( array_map( 'sanitize_text_field', $_REQUEST ), true ) ); echo "Sanitized Master Schedule Shortcode Attributes: " . esc_html( print_r( $atts, true ) ); } /* foreach ( array_keys( $_REQUEST ) as $key ) { if ( !isset( $atts[$key] ) ) { echo 'Possible missing key? ' . $key . "\n"; } } */ // --- output schedule contents --- // 2.5.0: remove unused schedule contents wrap // TODO: test wp_kses on master schedule output echo radio_station_master_schedule( $atts ); $js = ''; if ( strstr( $atts['view'], ',' ) ) { $views = explode( ',', $atts['view'] ); } else { $views = array( $atts['view'] ); } // echo "Views: " . esc_html( print_r( $views, true ) ) . "\n"; foreach ( $views as $view ) { $view = trim( $view ); // --- set schedule element ID --- if ( 'table' == $view ) { $schedule_id = 'master-program-schedule'; } elseif ( 'tabs' == $view ) { $schedule_id = 'master-schedule-tabs'; $panels_id = 'master-schedule-tab-panels'; } elseif ( 'list' == $view ) { $schedule_id = 'master-list'; } elseif ( 'grid' == $view ) { $schedule_id = 'master-schedule-grid'; } elseif ( 'calendar' == $view ) { $schedule_id = 'master-schedule-calendar'; } // 2.5.0: maybe append instance ID if ( $instance > 0 ) { $schedule_id .= '-' . $instance; // 2.5.10.1: fix to variable typo if ( isset( $panels_id ) ) { $panels_id .= '-' . $instance; } } // --- get schedule shortcode output --- $js .= "schedule = document.getElementById('" . esc_attr( $schedule_id ) . "').innerHTML;" . "\n"; if ( isset( $panels_id ) ) { $js .= "panels = document.getElementById('" . esc_attr( $panels_id ) . "').innerHTML;" . "\n"; } // --- send new schedule to parent window --- $js .= "if (parent.document.getElementById('" . esc_attr( $schedule_id ) . "')) {" . "\n"; $js .= "parent.document.getElementById('" . esc_attr( $schedule_id ) . "').innerHTML = schedule;" . "\n"; $js .= "}" . "\n"; if ( isset( $panels_id ) ) { $js .= "parent.document.getElementById('" . esc_attr( $panels_id ) . "').innerHTML = panels;" . "\n"; // 2.5.0: unset panels to prevent possible multiple views conflict unset( $panels_id ); } // --- copy the new start date value to the parent window --- // TODO: get by child class of schedule_id if multiview? $js .= "start_date = document.getElementById('schedule-start-date').value;" . "\n"; $js .= "parent.document.getElementById('schedule-start-date').value = start_date;" . "\n"; // $js .= "console.log('New Start Date: '+start_date);" . "\n"; } // --- maybe retrigger view(s) javascript in parent window --- // (uses set interval cycle in case script not yet loaded) $js .= "var genres_highlighted = false;" . "\n"; $js .= "function radio_schedule_init() {" . "\n"; // --- genre highlighter --- $js .= "if (!genres_highlighted && (typeof parent.radio_genre_highlight == 'function')) {" . "\n"; // TODO: add (wrapper) instance to radio_genre_highlight call // $js .= "parent.radio_genre_highlight();" . "\n"; $js .= "genres_highlighted = true;" . "\n"; $js .= "}" . "\n"; // 2.5.0: loop views to add individual init scripts foreach ( $views as $view ) { $init_js = ''; if ( 'table' == $view ) { $init_js .= "if (typeof parent.radio_table_initialize == 'function') {" . "\n"; // 2.5.0: set table state to uninitialized $init_js .= "parent.radio_table_init = false;" . "\n"; $init_js .= "parent.radio_table_initialize();" . "\n"; $init_js .= "}" . "\n"; } elseif ( 'tabs' == $view ) { $init_js .= "if (typeof parent.radio_tabs_initialize == 'function') {" . "\n"; $init_js .= "parent.radio_tabs_init = false;" . "\n"; // 2.5.14: removed duplicate function as already called via initialize // $schedule_id = 'master-schedule-tabs'; // if ( $instance > 0 ) { // $schedule_id .= '-' . $instance; // } // $init_js .= "parent.radio_tabs_active_tab('" . esc_js( $day ) . "','" . esc_js( $schedule_id ) . "');" . "\n"; $init_js .= "parent.radio_tabs_initialize();" . "\n"; $init_js .= "}" . "\n"; } elseif ( 'list' == $view ) { // 2.5.14: use radio list initialize for consistency $init_js .= "if (typeof parent.radio_list_initialize == 'function') {" . "\n"; $init_js .= "parent.radio_list_init= false;" . "\n"; $init_js .= "parent.radio_list_initialize();" . "\n"; $init_js .= "}" . "\n"; } // 2.5.0: added individual init script filtering $init_js = apply_filters( 'radio_station_master_schedule_init_script', $init_js, $view, $atts ); $js .= $init_js; } // --- maybe retrigger convert to user times --- $js .= "if (typeof parent.radio_convert_times == 'function') {parent.radio_convert_times();}" . "\n"; // --- placeholder for extra loader functions --- // (do not remove or modify this line - for backwards compatibility) $js .= "/* LOADER PLACEHOLDER */" . "\n"; $js .= "clearInterval(schedule_loader);" . "\n"; // $js .= "console.log('Schedule Reinitialization Complete');" . "\n"; $js .= "}" . "\n"; // --- loop until fired as complete --- $js .= "schedule_loader = setInterval(radio_schedule_init, 2000);" . "\n"; // --- filter load script and output --- $js = apply_filters( 'radio_station_master_schedule_load_script', $js, $atts ); if ( '' != $js ) { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo "<script>" . $js . "</script>"; } exit; } // ------------------- // Show Genre Selector // ------------------- // 2.3.3.9: change name from radio_station_master_schedule_selector function radio_station_master_schedule_genre_selector( $instance ) { // --- get genres --- // 2.5.6: add taxonomy to get_terms arguments $args = array( 'taxonomy' => RADIO_STATION_GENRES_SLUG, 'hide_empty' => true, 'orderby' => 'name', 'order' => 'ASC', ); // 2.5.6: remove deprecated second argument from get_terms // $genres = get_terms( RADIO_STATION_GENRES_SLUG, $args ); $genres = get_terms( $args ); // 2.3.2: bug out if there are no genre terms if ( !$genres || !is_array( $genres ) ) { return ''; } // --- open genre highlighter div --- $id = ( 0 == $instance ) ? '' : '-' . $instance; $html = '<div id="master-genre-list' . esc_attr( $id ) . '" class="master-genre-list">'; $html .= '<span class="heading">' . esc_html( __( 'Genres', 'radio-station' ) ) . ': </span>'; // --- genre highlight links --- // 2.3.0: fix by imploding with genre link spacer // 2.3.3.9: escape genre slug and assign javascript to onclick $genre_links = array(); foreach ( $genres as $i => $genre ) { $slug = sanitize_title_with_dashes( $genre->name ); // 2.5.0: added instance argument to genre highlight function $onclick = "radio_genre_highlight(" . esc_js( $instance ) . ",'" . esc_js( $slug ) . "');"; $title = __( 'Click to toggle Highlight of Shows with this Genre.', 'radio-station' ); // 2.5.0: remove element ID in favour of class $genre_link = '<a class="genre-highlight genre-highlight-' . esc_attr( $slug ) . '" href="javascript:void(0);" onclick="' . $onclick . '" title="' . esc_attr( $title ) . '">'; $genre_link .= esc_html( $genre->name ) . '</a>'; $genre_links[] = $genre_link; } $html .= implode( ' | ', $genre_links ); $html .= '</div>'; // --- genre highlighter script --- // 2.3.0: improved to highlight / unhighlight multiple genres // 2.3.0: improved to work with table, tabs or list view // 2.3.3.9: added genre class targets for grid and calendar views // 2.3.3.9: added accepting false to retrigger highlights for AJAX // 2.5.0: added instance argument to genre highlight function // 2.5.0: modified to use traversal via passed wrapper instance // 2.5.0: added genre- prefix to class selectors $js = "var radio_genres_selected = new Array(); function radio_genre_highlight(instance,genre) { if (0 == instance) {id = '';} else {id = '-'+instance;} wrapper = jQuery('#master-schedule'+id); classes = ['.master-show-entry', '.master-schedule-tabs-show', '.master-list-day-item', '.master-schedule-grid-show', '.master-schedule-calendar-date', '.master-schedule-calendar-show', '.shows-slider-item']; if (radio.debug) {console.log('Genres Before: '+radio_genres_selected[instance]);} if (genre === false) { for (i = 0; i < classes.length; i++) { wrapper.find(classes[i]).removeClass('highlighted'); } if (typeof radio_genres_selected.instance != 'undefined') { for (i = 0; i < radio_genres_selected[instance].length; i++) { wrapper.find('.genre-'+radio_genres_selected[instance][i]).addClass('highlighted'); } } } else { if (wrapper.find('.genre-highlight-'+genre).hasClass('highlighted')) { wrapper.find('.genre-highlight-'+genre).removeClass('highlighted'); for (i = 0; i < classes.length; i++) { wrapper.find(classes[i]).removeClass('highlighted'); } j = 0; new_genre_highlights = new Array(); if (typeof radio_genres_selected[instance] != 'undefined') { for (i = 0; i < radio_genres_selected[instance].length; i++) { if (radio_genres_selected[instance][i] != genre) { wrapper.find('.genre-'+radio_genres_selected[instance][i]).addClass('highlighted'); new_genre_highlights[j] = radio_genres_selected[instance][i]; j++; } } } radio_genres_selected[instance] = new_genre_highlights; } else { wrapper.find('.genre-highlight-'+genre).addClass('highlighted'); wrapper.find('.genre-'+genre).addClass('highlighted'); if (typeof radio_genres_selected[instance] == 'undefined') {radio_genres_selected[instance] = new Array();} radio_genres_selected[instance][radio_genres_selected[instance].length] = genre; } } if (radio.debug) {console.log('Genres After: '+radio_genres_selected[instance]);} }"; // --- enqueue script --- // 2.3.0: add script code to existing handle // 2.5.0: use radio_station_add_inline_script radio_station_add_inline_script( 'radio-station', $js ); return $html; } // --------------------- // Table View Javascript // --------------------- // 2.3.0: added for table responsiveness // 2.5,0: use DOM traversals with jQuery and classes function radio_station_master_schedule_table_js() { // 2.3.2: added current show highlighting cycle // 2.3.2: fix to currenthour substr // 2.3.3.5: change selected day and arrow logic (to single day shifting) // 2.3.3.6: also highlight split shift via matching shift class // 2.3.3.9: prefix show-info selector with .master-program-hour-row // 2.3.3.9: use setInterval instead of setTimeout for highlighting // 2.3.3.9: check for required elements before executing functions // 2.3.3.9: fix to check before and after current time not show $js = "/* Initialize Table */ var radio_table_init = false; jQuery(document).ready(function() { radio_table_initialize(); var radio_table_highlighting = setInterval(radio_table_highlight, 60000); }); jQuery(window).resize(function () { radio_resize_debounce(function() {radio_table_responsive(false,false);}, 500, 'scheduletable'); }); /* Table Initialize */ function radio_table_initialize() { radio_table_responsive(false,false); radio_table_highlight(); if (typeof radio_table_start_hours != 'undefined') {radio_table_start_hours();} radio_table_init = true; } /* Current Time Highlighting */ function radio_table_highlight() { if (!jQuery('.master-program-schedule').length) {return;} jQuery('.master-program-schedule').each(function() { var scheduletable = jQuery(this); radio.current_time = Math.floor((new Date()).getTime() / 1000); radio.offset_time = radio.current_time + radio.timezone.offset; if (radio.debug) {console.log(radio.current_time+' - '+radio.offset_time);} if (radio.timezone.adjusted) {radio.offset_time = radio.current_time;} jQuery(this).find('.master-program-day').each(function() { start = parseInt(jQuery(this).find('.rs-start-time').attr('data')); end = parseInt(jQuery(this).find('.rs-end-time').attr('data')); if ( (start < radio.offset_time) && (end > radio.offset_time) ) { jQuery(this).addClass('current-day'); } else {jQuery(this).removeClass('current-day');} }); jQuery(this).find('.master-program-hour').each(function() { hour = parseInt(jQuery(this).find('.master-program-server-hour').attr('data')); offset_time = radio.current_time + radio.timezone.offset; current = new Date(offset_time * 1000).toISOString(); currenthour = current.substr(11, 2); if (currenthour.substr(0,1) == '0') {currenthour = currenthour.substr(1,1);} if (hour == currenthour) {jQuery(this).addClass('current-hour');} else {jQuery(this).removeClass('current-hour');} }); for (i = 0; i < 7; i++) { jQuery(this).find('.day-'+i).each(function() { var radio_table_shift = false; jQuery(this).find('.master-show-entry').each(function() { start = parseInt(jQuery(this).find('.rs-start-time').attr('data')); end = parseInt(jQuery(this).find('.rs-end-time').attr('data')); if (radio.debug) {console.log(jQuery(this)); console.log(start+' - '+end);} if ( (start < radio.offset_time) && (end > radio.offset_time) ) { if (radio.debug) {console.log('^ Now Playing ^');} jQuery(this).removeClass('before-current').removeClass('after-current').addClass('nowplaying'); /* also highlight split shift via matching shift class */ if (jQuery(this).hasClass('overnight')) { classes = jQuery(this).attr('class').split(/\s+/); for (i = 0; i < classes.length; i++) { if (classes[i].substr(0,6) == 'split-') {radio_table_shift = classes[i];} } } } else { jQuery(this).removeClass('nowplaying'); if (start > radio.offset_time) {jQuery(this).addClass('after-current');} else if (end < radio.offset_time) {jQuery(this).addClass('before-current');} } }); if (radio_table_shift) { scheduletable.find('.'+radio_table_shift).removeClass('before-current').removeClass('after-current').addClass('nowplaying'); } }); } }); } /* Make Table Responsive */ function radio_table_responsive(leftright,instance) { if (!jQuery('.master-program-schedule').length) {return;} if (instance) { if (0 == instance) {id = '';} else {id = '-'+instance;} tableschedules = jQuery('#master-program-schedule'+id); } else {tableschedules = jQuery('.master-program-schedule');} tableschedules.each(function() { if (jQuery(this).find('.master-program-day').length) { fallback = -1; selected = -1; foundday = false; if (!leftright || (leftright == 'left')) { if (jQuery(this).find('.master-program-day.first-column').length) { start = jQuery(this).find('.master-program-day.first-column'); } else {start = jQuery(this).find('.master-program-day').first(); fallback = 0;} classes = start.attr('class').split(' '); } else if (leftright == 'right') { if (jQuery(this).find('.master-program-day.last-column').length) { end = jQuery(this).find('.master-program-day.last-column'); } else {end = jQuery(this).find('.master-program-day').last(); fallback = 6;} classes = end.attr('class').split(' '); } for (i = 0; i < classes.length; i++) { if (classes[i].indexOf('day-') === 0) {selected = parseInt(classes[i].replace('day-',''));} } if (selected < 0) {selected = fallback;} if (radio.debug) {console.log('Current Column: '+selected);} if (leftright == 'left') {selected--;} else if (leftright == 'right') {selected++;} if (selected < 0) {selected = 0;} else if (selected > 6) {selected = 6;} if (!jQuery(this).find('.master-program-day.day-'+selected).length) { while (!foundday) { if (leftright == 'left') {selected--;} else if (leftright == 'right') {selected++;} if (jQuery(this).find('.master-program-day.day-'+selected).length) {foundday = true;} if ((selected < 0) || (selected > 6)) {selected = fallback; foundday = true;} } } if (radio.debug) {console.log('Selected Column: '+selected);} /* totalwidth = jQuery(this).find('.master-program-hour-heading').width(); */ jQuery(this).find('.master-program-day, .master-program-hour-row .show-info').removeClass('first-column').removeClass('last-column').hide(); jQuery(this).css('width','100%'); tablewidth = jQuery(this).width(); jQuery(this).css('width','auto').css('overflow','visible'); columns = 0; firstcolumn = -1; lastcolumn = 7; endtable = false; for (i = selected; i < 7; i++) { if (!endtable && (jQuery(this).find('.master-program-day.day-'+i).length)) { if ((i > 0) && (i == selected)) {jQuery(this).find('.master-program-day.day-'+i).addClass('first-column'); firstcolumn = i;} else if (i < 6) {jQuery(this).find('.master-program-day.day-'+i).addClass('last-column');} jQuery(this).find('.master-program-day.day-'+i+', .master-program-hour-row .show-info.day-'+i).show(); colwidth = jQuery(this).find('.master-program-day.day-'+i).width(); /* totalwidth = totalwidth + colwidth; */ totalwidth = jQuery(this).width(); if (radio.debug) {console.log('('+colwidth+') : '+totalwidth+' / '+tablewidth);} jQuery(this).find('.master-program-day.day-'+i).removeClass('last-column'); if (totalwidth > tablewidth) { if (radio.debug) {console.log('Hiding Column '+i);} jQuery(this).find('.master-program-day.day-'+i+', .master-program-hour-row .show-info.day-'+i).hide(); endtable = true; } else { if (radio.debug) {console.log('Showing Column '+i);} jQuery(this).find('.master-program-day.day-'+i).removeClass('last-column'); totalwidth = totalwidth - colwidth + jQuery(this).find('.master-program-day.day-'+i).width(); lastcolumn = i; columns++; } } } if (lastcolumn < 6) {jQuery(this).find('.master-program-day.day-'+lastcolumn).addClass('last-column');} jQuery(this).css('overflow',''); if (leftright == 'right') { for (i = (selected - 1); i > -1; i--) { if (!endtable && (jQuery(this).find('.master-program-day.day-'+i).length)) { jQuery(this).find('.master-program-day.day-'+i+', .master-program-hour-row .show-info.day-'+i).show(); colwidth = jQuery(this).find('.master-program-day.day-'+i).width(); totalwidth = totalwidth + colwidth; if (radio.debug) {console.log('('+colwidth+') : '+totalwidth+' / '+tablewidth);} if (totalwidth > tablewidth) { if (radio.debug) {console.log('Hiding Column '+i);} jQuery(this).find('.master-program-day.day-'+i+', .master-program-hour-row .show-info.day-'+i).hide(); endtable = true; } else { if (radio.debug) {console.log('Showing Column '+i);} jQuery(this).find('.master-program-day').removeClass('first-column'); jQuery(this).find('.master-program-day.day-'+i).addClass('first-column'); columns++; } } } } jQuery(this).css('width','100%'); } }); } /* Shift Day Left / Right */ function radio_shift_day(leftright,instance) { radio_table_responsive(leftright,instance); return false; }" . "\n"; // --- filter and return --- // 2.3.3.9: add filter and return instead of inline enqueue $js = apply_filters( 'radio_station_master_schedule_table_js', $js ); return $js; } // ---------------------- // Tabbed View Javascript // ---------------------- // 2.2.7: added for tabbed schedule view // TODO: use traversals with instance IDs function radio_station_master_schedule_tabs_js() { // --- tab switching function --- // 2.3.2: added fallback if current day is not viewed // 2.3.3.6: allow for clicking on date to change days // 2.3.3.8: make entire heading label div clickable to change tabs // 2.3.3.9: make into function and add to document ready code block // 2.5.0: use relative traversal from click target instead of IDs // 2.5.13: change active day input value on tab change $js = "function radio_tabs_clicks() { if (radio_tabs_init) {return;} if (radio.debug) {console.log('Adding Tabbed Schedule Tab Clicks');} jQuery('.master-schedule-tabs-headings').on('click', function (event) { event.preventDefault(); if (jQuery(event.target).hasClass('master-schedule-tabs-headings')) {day = jQuery(event.target).attr('data-href');} else {day = jQuery(event.target).closest('.master-schedule-tabs-headings').attr('data-href');} if (radio.debug) {console.log('Switching Tab to Day: '+day);} document.getElementById('schedule-active-day').value = day; schedule = jQuery(event.target).closest('.master-schedule-tabs'); panels = schedule.parent().find('.master-schedule-tab-panels'); schedule.find('.master-schedule-tabs-day').removeClass('active-day-tab'); schedule.find('.master-schedule-tabs-day-'+day).addClass('active-day-tab'); panels.find('.master-schedule-tabs-panel').removeClass('active-day-panel'); panels.find('.master-schedule-tabs-panel-'+day).addClass('active-day-panel'); return false; }); }" . "\n"; // --- tabbed view responsiveness --- // 2.3.0: added for tabbed responsiveness // 2.3.2: display selected day message if outside view // 2.3.3.5: change selected day and arrow logic (to single day shifting) // 2.3.3.6: also highlight split shift via matching shift class // 2.3.3.9: use setInterval instead of setTimeout for highlighting check // 2.3.3.9: check for required elements before executing functions // 2.3.3.9: fix to check before and after current time not show // 2.3.3.9: adjust responsive tabs for possible loader control presence // 2.5.13: set active tab to active day value if set $js .= "/* Initialize Tabs */ var radio_tabs_init = false; jQuery(document).ready(function() { radio_tabs_initialize(); var radio_tab_highlighting = setInterval(radio_tabs_show_highlight, 60000); }); jQuery(window).resize(function () { radio_resize_debounce(function() {radio_tabs_responsive(false,false);}, 500, 'scheduletabs'); }); /* Initialize Tabs */ function radio_tabs_initialize() { radio_tabs_clicks(); radio_tabs_responsive(false,false); radio_tabs_show_highlight(); if (typeof radio_tabs_start_hours != 'undefined') {radio_tabs_start_hours();} } /* Set Day Tab on Load */ function radio_tabs_active_tab(day,scheduleid) { if (radio_tabs_init) {return;} if (day) { jQuery('#'+scheduleid+' .master-schedule-tabs-day').removeClass('active-day-tab'); jQuery('#'+scheduleid+' .master-schedule-tabs-day-'+day).addClass('active-day-tab'); panelid = scheduleid.replace('-tabs','-tab-panels'); jQuery('#'+panelid+' .master-schedule-tabs-panel').removeClass('active-day-panel'); jQuery('#'+panelid+' .master-schedule-tabs-panel-'+day).addClass('active-day-panel'); } else { jQuery('#'+scheduleid+' .master-schedule-tabs-day').first().addClass('active-day-tab'); jQuery('#'+scheduleid+' .master-schedule-tabs-panel').first().addClass('active-day-panel'); } radio_tabs_init = true; } /* Current Show Highlighting */ function radio_tabs_show_highlight() { if (!jQuery('.master-schedule-tabs').length) {return;} jQuery('.master-schedule-tabs').each(function() { scheduleid = jQuery(this).attr('id'); radio.current_time = Math.floor( (new Date()).getTime() / 1000 ); radio.offset_time = radio.current_time + radio.timezone.offset; if (radio.debug) {console.log(radio.current_time+' - '+radio.offset_time);} if (radio.timezone.adjusted) {radio.offset_time = radio.current_time;} day = false; active_day = document.getElementById('schedule-active-day').value; if (active_day != '') {day = active_day;} jQuery(this).find('.master-schedule-tabs-day').each(function() { start = parseInt(jQuery(this).find('.rs-start-time').attr('data')); end = parseInt(jQuery(this).find('.rs-end-time').attr('data')); if ((start < radio.offset_time) && (end > radio.offset_time)) { jQuery(this).addClass('current-day'); tabday = jQuery(this).attr('id').replace('master-schedule-tabs-header-', ''); radio_tabs_active_tab(tabday,scheduleid); } else {jQuery(this).removeClass('current-day');} }); radio_tabs_active_tab(day,scheduleid); /* fallback */ var radio_tabs_split = false; jQuery(this).parent().find('.master-schedule-tabs-show').each(function() { start = parseInt(jQuery(this).find('.rs-start-time').attr('data')); end = parseInt(jQuery(this).find('.rs-end-time').attr('data')); if (radio.debug) {console.log(start+' - '+end);} if ( (start < radio.offset_time) && (end > radio.offset_time) ) { if (radio.debug) {console.log('^ Now Playing ^');} jQuery(this).removeClass('before-current').removeClass('after-current').addClass('nowplaying'); /* also highlight split shift via matching shift class */ if (jQuery(this).hasClass('overnight')) { classes = jQuery(this).attr('class').split(/\s+/); for (i = 0; i < classes.length; i++) { if (classes[i].substr(0,6) == 'split-') {radio_tabs_split = classes[i];} } } } else { jQuery(this).removeClass('nowplaying'); if (start > radio.offset_time) {jQuery(this).addClass('after-current');} else if (end < radio.offset_time) {jQuery(this).addClass('before-current');} } }); if (radio_tabs_split) { jQuery(this).parent().find('.'+radio_tabs_split).removeClass('before-current').removeClass('after-current').addClass('nowplaying'); } }); } /* Make Tabs Responsive */ function radio_tabs_responsive(leftright,instance) { if (!jQuery('.master-schedule-tabs').length) {return;} if (instance) { if (0 == instance) {id = '';} else {id = '-'+instance;} tabschedules = jQuery('#master-schedule-tabs'+id); } else {tabschedules = jQuery('.master-schedule-tabs');} tabschedules.each(function() { if (jQuery(this).find('.master-schedule-tabs-day').length) { fallback = -1; selected = -1; foundtab = false; if (!leftright || (leftright == 'left')) { if (jQuery(this).find('.master-schedule-tabs-day.first-tab').length) { start = jQuery(this).find('.master-schedule-tabs-day.first-tab'); } else {start = jQuery(this).find('.master-schedule-tabs-day').first(); fallback = 0;} classes = start.attr('class').split(' '); } else if (leftright == 'right') { if (jQuery(this).find('.master-schedule-tabs-day.last-tab').length) { end = jQuery(this).find('.master-schedule-tabs-day.last-tab'); } else {end = jQuery(this).find('.master-schedule-tabs-day').last(); fallback = 6;} classes = end.attr('class').split(' '); } for (i = 0; i < classes.length; i++) { if (classes[i].indexOf('day-') === 0) {selected = parseInt(classes[i].replace('day-',''));} } if (selected < 0) {selected = fallback;} if (radio.debug) {console.log('Current Tab: '+selected);} if (leftright == 'left') {selected--;} else if (leftright == 'right') {selected++;} if (selected < 0) {selected = 0;} else if (selected > 6) {selected = 6;} if (!jQuery(this).find('.master-schedule-tabs-day.day-'+selected).length) { while (!foundtab) { if (leftright == 'left') {selected--;} else if (leftright == 'right') {selected++;} if (jQuery(this).find('.master-schedule-tabs-day.day-'+selected).length) {foundtab = true;} if ((selected < 0) || (selected > 6)) {selected = fallback; foundtab = true;} } } if (radio.debug) {console.log('Selected Tab: '+selected);} jQuery(this).css('width','100%'); tabswidth = jQuery(this).width(); jQuery(this).css('width','auto'); jQuery(this).find('.master-schedule-tabs-day').removeClass('first-tab').removeClass('last-tab').hide(); totalwidth = 0; tabs = 0; firsttab = -1; lasttab = 7; endtabs = false; if (jQuery(this).find('.master-schedule-tabs-loader-left').length) {totalwidth = totalwidth + jQuery(this).find('.master-schedule-tabs-loader-left').width();} if (jQuery(this).find('.master-schedule-tabs-loader-right').length) {totalwidth = totalwidth + jQuery(this).find('.master-schedule-tabs-loader-right').width();} if (radio.debug) {console.log('Tabs Start Width: '+totalwidth);} for (i = selected; i < 7; i++) { if (!endtabs && (jQuery(this).find('.master-schedule-tabs-day.day-'+i).length)) { if ((i > 0) && (i == selected)) {jQuery(this).find('.master-schedule-tabs-day.day-'+i).addClass('first-tab'); firsttab = i;} else if (i < 6) {jQuery(this).find('.master-schedule-tabs-day.day-'+i).addClass('last-tab');} tabwidth = jQuery(this).find('.master-schedule-tabs-day.day-'+i).show().width(); mleft = parseInt(jQuery(this).find('.master-schedule-tabs-day.day-'+i).css('margin-left').replace('px','')); mright = parseInt(jQuery(this).find('.master-schedule-tabs-day.day-'+i).css('margin-right').replace('px','')); /* totalwidth = totalwidth + tabwidth + mleft + mright; */ totalwidth = 0; jQuery(this).find('li').each(function() { if (jQuery(this).is(':visible')) { totalwidth += jQuery(this).width(); totalwidth += parseInt(jQuery(this).css('margin-left').replace('px','')); totalwidth += parseInt(jQuery(this).css('margin-right').replace('px','')); } }); if (radio.debug) {console.log(tabwidth+' - ('+mleft+'/'+mright+') - '+totalwidth+' / '+tabswidth);} if (totalwidth > tabswidth) { if (radio.debug) {console.log('Hiding Tab '+i);} jQuery(this).find('.master-schedule-tabs-day.day-'+i).hide(); endtabs = true; } else { jQuery(this).find('.master-schedule-tabs-day.day-'+i).removeClass('last-tab'); totalwidth = totalwidth - tabwidth + jQuery(this).find('.master-schedule-tabs-day.day-'+i).width(); if (radio.debug) {console.log('Showing Tab '+i);} lasttab = i; tabs++; } } } if (lasttab < 6) {jQuery(this).find('.master-schedule-tabs-day.day-'+lasttab).addClass('last-tab');} if (leftright == 'right') { for (i = (selected - 1); i > -1; i--) { if (!endtabs && (jQuery(this).find('.master-schedule-tabs-day.day-'+i).length)) { tabwidth = jQuery(this).find('.master-schedule-tabs-day.day-'+i).show().width(); mleft = parseInt(jQuery(this).find('.master-schedule-tabs-day.day-'+i).css('margin-left').replace('px','')); mright = parseInt(jQuery(this).find('.master-schedule-tabs-day.day-'+i).css('margin-right').replace('px','')); totalwidth = totalwidth + tabwidth + mleft + mright; if (radio.debug) {console.log(tabwidth+' - ('+mleft+'/'+mright+') - '+totalwidth+' / '+tabswidth);} if (totalwidth > tabswidth) { if (radio.debug) {console.log('Hiding Tab '+i);} jQuery(this).find('.master-schedule-tabs-day.day-'+i).hide(); endtabs = true; } else { jQuery(this).find('.master-schedule-tabs-day').removeClass('first-tab'); jQuery(this).find('.master-schedule-tabs-day.day-'+i).addClass('first-tab'); if (radio.debug) {console.log('Showing Tab '+i);} tabs++; } } } } jQuery(this).css('width','100%'); /* display selected day message if outside view */ activeday = false; for (i = 0; i < 7; i++) { if (jQuery(this).find('.master-schedule-tabs-day.day-'+i).length) { if (jQuery(this).find('.master-schedule-tabs-day.day-'+i).hasClass('active-day-tab')) {activeday = i;} } } jQuery(this).find('.master-schedule-tabs-selected').hide(); if ( activeday && ( (activeday > lasttab) || (activeday < firsttab ) ) ) { jQuery(this).find('.master-schedule-tabs-selected-'+activeday).show(); } if (radio.debug) { console.log('Active Day: '+activeday); console.log('Selected: '+selected); console.log('Fallback: '+fallback); console.log('First Tab: '+firsttab); console.log('Last Tab: '+lasttab); console.log('Visible Tabs: '+tabs); } } }); } /* Shift Day Left / Right */ function radio_shift_tab(leftright,instance) { radio_tabs_responsive(leftright,instance); return false; }" . "\n"; // --- filter and return --- // 2.3.3.9: add filter and return instead of inline enqueue $js = apply_filters( 'radio_station_master_schedule_tabs_js', $js ); return $js; } // -------------------- // List View Javascript // -------------------- // 2.3.2: added for list schedule view // TODO: use traversals with instance IDs function radio_station_master_schedule_list_js() { // --- list view javascript --- // 2.3.3.6: also highlight split shift via matching shift class // 2.3.3.9: use setInterval instead of setTimeout for highlighting // 2.3.3.9: check for required elements before executing functions // 2.3.3.9: fix to check before and after current time not show $js = "/* Initialize List */ var radio_list_init = false; jQuery(document).ready(function() { radio_list_initialize(); var radio_list_highlighting = setInterval(radio_list_highlight, 60000); }); /* Initialize List */ function radio_list_initialize() { radio_list_init = true; radio_list_highlight(); if (typeof radio_list_start_hours != 'undefined') {radio_list_start_hours();} } /* Current Show Highlighting */ function radio_list_highlight() { if (!jQuery('.master-list-day').length) {return;} radio.current_time = Math.floor( (new Date()).getTime() / 1000 ); radio.offset_time = radio.current_time + radio.timezone.offset; if (radio.timezone.adjusted) {radio.offset_time = radio.current_time;} jQuery('.master-list-day').each(function() { start = parseInt(jQuery(this).find('.rs-start-time').first().attr('data')); end = parseInt(jQuery(this).find('.rs-end-time').first().attr('data')); if ( (start < radio.offset_time) && (end > radio.offset_time) ) { jQuery(this).addClass('current-day'); } else {jQuery(this).removeClass('current-day');} }); var radio_list_split = false; jQuery('.master-list-day-item').each(function() { start = parseInt(jQuery(this).find('.rs-start-time').attr('data')); end = parseInt(jQuery(this).find('.rs-end-time').attr('data')); if ( (start < radio.offset_time) && (end > radio.offset_time) ) { radio_list_current = true; if (radio.debug) {console.log('^ Now Playing ^');} jQuery(this).addClass('nowplaying'); /* also highlight split shift via matching shift class */ if (jQuery(this).hasClass('overnight')) { classes = jQuery(this).attr('class').split(/\s+/); for (i = 0; i < classes.length; i++) { if (classes[i].substr(0,6) == 'split-') {radio_list_split = classes[i];} } } } else { jQuery(this).removeClass('nowplaying'); if (start > radio.offset_time) {jQuery(this).addClass('after-current');} else if (end < radio.offset_time) {jQuery(this).addClass('before-current');} } }); if (radio_list_split) { jQuery('.'+radio_list_split).removeClass('before-current').removeClass('after-current').addClass('nowplaying'); } }" . "\n"; // --- filter and return --- // 2.3.3.9: add filter and return instead of inline enqueue $js = apply_filters( 'radio_station_master_schedule_list_js', $js ); return $js; }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings