You are here

jstimer.module in Javascript Timer 8

Same filename and directory in other branches
  1. 6 jstimer.module
  2. 7 jstimer.module

File

jstimer.module
View source
<?php

use Drupal\Core\File\FileSystemInterface;

/**
 * @file
 * A module which creates javascript timed dhtml things.
 */
module_load_include('inc', 'jstimer', '/jstimer.field');

/**
 * Implementation of hook_help().
 */
function jstimer_help($path, $arg) {
  switch ($path) {
    case 'admin/modules#description':
      return t('A module which creates javascript timers.');
    case 'admin/help#jstimer':
      $output = <<<HELP_TXT
<p>Please look at the readme.txt file that comes with this module.  It really has a lot of great information.</p>
<p>The javascript timer module provides an api to allow you to make dhtml widgets which are updated every second.
There are some good examples for node and block usage in the readme.txt file.
Please look at it.</p>
HELP_TXT;
      $output .= '<p>Usage Example for a Node<br/>&lt;span class="jst_timer"&gt;Count Up to 11:30<br/>&lt;span style="display:none" class="datetime"&gt;2007-02-26T09:30:00&lt;/span&gt;<br/>&lt;span style="display:none"<br/>';
      $output .= '&lt;span style="display:none" class="dir"&gt;up&lt;/span&gt;<br/>&lt;/span&gt;</p>';
      return $output;
  }
}

/**
 * Implementation of hook_theme().
 */
function jstimer_theme($existing, $type, $theme, $path) {
  $themes = array(
    'jstimer' => array(
      'variables' => array(
        'widget_name' => NULL,
        'widget_args' => NULL,
      ),
    ),
  );
  return $themes;
}
function theme_jstimer($variables) {
  $widget_name = $variables['widget_name'];
  $widget_args = $variables['widget_args'];
  $widgets = jstimer_get_widgets();
  $widget = NULL;
  foreach ($widgets as $w) {
    if ($widget_name == $w->name) {
      $widget = $w;
      break;
    }
  }
  if (!isset($widget)) {
    return "Widget {$widget_name} not found.";
  }
  if (function_exists($widget->theme_function)) {
    return call_user_func($widget->theme_function, $widget_args);
  }
  else {
    return "Widget {$widget_name} theme not found.";
  }
}

/**
 * Implementation of hook_menu
 */
function jstimer_menu() {
  $items = array();
  $items['admin/config/system/jstimer'] = array(
    'title' => 'Javascript timer',
    'description' => 'Configure Javascript timer widgets and settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'jstimer_admin_settings',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'jstimer.admin.inc',
  );
  return $items;
}
function jstimer_page_attachments_alter(array &$page) {
  $page['#attached']['library'][] = 'jstimer/jstimer';
}

/**
 * scrub the format strings for things that make bad javascript.
 *
 * @param $format_string
 *   String which needs to be cleaned.
 * @return string
 *   cleaned string which does not contain newlines, carrage returns, or single quotes.
 */
function jstimer_clean_for_javascript($format_string = '') {
  $patterns = array(
    '/\\n/',
    '/\\r/',
    '/\'/',
  );
  $replacements = array(
    '<br/>',
    '',
    '"',
  );
  return preg_replace($patterns, $replacements, $format_string);
}

/**
 * create the timer.js file and put it in the files/jstimer directory.
 *
 * @return string
 *   The full path of the file.
 */
function jstimer_build_js_cache() {

  // Create the files/jstimer
  $path = 'public://jstimer';
  \Drupal::service('file_system')
    ->prepareDirectory($path, FileSystemInterface::CREATE_DIRECTORY);
  $data = jstimer_get_javascript(TRUE);
  file_save_data($data, $path . '/timer.js', FileSystemInterface::EXISTS_REPLACE);
  \Drupal::messenger()
    ->addStatus(t('Javascript timer javascript file saved to: ') . $path . '/timer.js');
  if (!file_exists($path . '/timer.js')) {
    \Drupal::messenger()
      ->addError(t('File Create Error: timer.js could not be created'));
  }
  else {
    \Drupal::configFactory()
      ->getEditable('jstimer.settings')
      ->set('jstimer_timerjs_path', $path . '/timer.js')
      ->save();
  }
  return $path . '/timer.js';
}

/**
 * Get the list of active widgets.
 *
 * @return Array
 *   The array of stdClass objects.
 */
function jstimer_get_widgets($reset = FALSE) {
  static $widgets;
  if (!isset($widgets) || $reset) {

    // get all optional widgets
    $widgets = \Drupal::moduleHandler()
      ->invokeAll('jstwidget');
  }
  return $widgets;
}

/**
 * Get the actual javascript code that needs to be written into a file.
 * This also aggregates any optional javascript bits.
 *
 * @return string
 *   The javascript code.
 */
function jstimer_get_javascript($reset = FALSE) {

  // Get all widgets
  $widget_list = jstimer_get_widgets($reset);

  // Collect implementation js and instantiation js.
  $active_widgets = array();
  $widget_implementation_code = '';
  foreach ($widget_list as $widget) {
    $active_widgets[] = "new " . $widget->js_name . "()";
    $widget_implementation_code .= $widget->js_code;
  }
  $active_widgets_instantiation = implode(",\n      ", $active_widgets);

  /* Begin Javascript heredoc.
   * This is not indented so javascript is more readable in web browser.
   * This creates a js file to facilitate caching.
   */
  $ouput = <<<JAVASCRIPT_CODE

// bootstrap
Drupal.behaviors.jstimer = {
  attach: function(context) {
    Drupal.jstimer.countdown_auto_attach(
      new Array(
        {<span class="php-variable">$active_widgets_instantiation</span>}
      )
    );
  }
}

// Namespace for most of the javascript functions.
Drupal.jstimer = {};

Drupal.jstimer.once = 0;

// Array that holds all elements that need to be updated.
Drupal.jstimer.timer_stack = new Array();

// Attach all active widgets to their respective dom objects.
Drupal.jstimer.countdown_auto_attach = function (jstimer_active_widgets) {

  // Call .attach() on the active widget items.
  for (var i=0; i<jstimer_active_widgets.length; i++) {
    jstimer_active_widgets[i].attach();
  }

  // If you have any widget items, start the timing loop.
  if ( Drupal.jstimer.timer_stack.length > 0 && Drupal.jstimer.once < 1) {
    Drupal.jstimer.timer_loop();
    Drupal.jstimer.once++;
  }

}

// The timing loop.
Drupal.jstimer.timer_loop = function() {
  // run backwards so we can remove items and not messup the loop data.
  for (var i = Drupal.jstimer.timer_stack.length - 1; i >= 0; i--) {
    if ( Drupal.jstimer.timer_stack[i].update() == false ) {
      Drupal.jstimer.timer_stack.splice(i, 1);
    }
  }

  // Stop the timer if there are not more timer items.
  if ( Drupal.jstimer.timer_stack.length > 0 ) {
    setTimeout('Drupal.jstimer.timer_loop()',999);
  }
}

{<span class="php-variable">$widget_implementation_code</span>}




// Util functions
function LZ(x) {
  return (x >= 10 || x < 0 ? "" : "0") + x;
}

// iso8601 date parsing routines.  Extends the built-in javascript date object.
Date.prototype.jstimer_set_iso8601_date = function (string) {
  var iso8601_re = /^(?:(\\d{4})(?:-(\\d{2})(?:-(\\d{2}))?)?)?(?:[T ](\\d{2}):(\\d{2})(?::(\\d{2})(.\\d+)?)?((?:[+-](\\d{2}):(\\d{2}))|Z)?)?\$/;
  var date_bits = iso8601_re.exec(string);
  var date_obj = null;
  if ( date_bits ) {
    date_bits.shift();
    date_bits[1] && date_bits[1]--; // normalize month
    date_bits[6] && (date_bits[6] *= 1000); // convert mils
    date_obj = new Date(date_bits[0]||1970, date_bits[1]||0, date_bits[2]||0, date_bits[3]||0, date_bits[4]||0, date_bits[5]||0, date_bits[6]||0);

    if (date_bits[0] < 1000) {
      date_obj.setFullYear(date_bits[0]);
    }

    //timezone handling
    var zone_offset = 0;  // in minutes
    var zone_plus_minus = date_bits[7] && date_bits[7].charAt(0);
    // get offset from isostring time to Z time
    if ( zone_plus_minus != 'Z' ) {
      zone_offset = ((date_bits[8] || 0) * 60) + (Number(date_bits[9]) || 0);
      if ( zone_plus_minus != '-' ) {
        zone_offset *= -1;
      }
    }
    // convert offset to localtime offset, will include daylight savings
    if ( zone_plus_minus ) {
      zone_offset -= date_obj.getTimezoneOffset();
    }
    if ( zone_offset ) {
      date_obj.setTime(date_obj.getTime() + zone_offset * 60000);
    }
  }

  // set this object to current localtime representation
  try {
    this.setTime(date_obj.getTime());
  }
  catch(e) {
    throw new Object({name:"DatePatternFail",message:"jstimer: Date does not have proper format (ISO8601, see readme.txt)."});
  }
}
Date.prototype.jstimer_get_moy = function () {
  var myMonths=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
  return myMonths[this.getMonth()];
}
Date.prototype.jstimer_get_dow = function () {
  var myDays=["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
  return myDays[this.getDay()];
}

JAVASCRIPT_CODE;
  return $ouput;
}

Functions

Namesort descending Description
jstimer_build_js_cache create the timer.js file and put it in the files/jstimer directory.
jstimer_clean_for_javascript scrub the format strings for things that make bad javascript.
jstimer_get_javascript Get the actual javascript code that needs to be written into a file. This also aggregates any optional javascript bits.
jstimer_get_widgets Get the list of active widgets.
jstimer_help Implementation of hook_help().
jstimer_menu Implementation of hook_menu
jstimer_page_attachments_alter
jstimer_theme Implementation of hook_theme().
theme_jstimer