You are here

jst_clock.module in Javascript Timer 8

Same filename and directory in other branches
  1. 6 widgets/jst_clock.module
  2. 7 widgets/jst_clock.module

Embeddable clock widget (optional).

File

widgets/jst_clock.module
View source
<?php

/**
 * @file
 * Embeddable clock widget (optional).
 */
use Drupal\Core\Form\FormStateInterface;

/**
 * Implementation of hook_jstwidget().
 *
 * @returns stdClass
 *   Keys include: ->name, ->theme_function, ->js_name, and ->js_code.
 */
function jst_clock_jstwidget() {
  $mod_path = drupal_get_path('module', 'jst_clock');
  $config = \Drupal::config('jstimer.settings');
  $svg_file = $config
    ->get('jst_clock_sva_file');
  $ret = new stdClass();
  $ret->name = 'jst_clock';
  $ret->label = t('Clock');
  $ret->theme_function = 'jst_clock_show';
  $ret->js_name = 'Drupal.jstimer.jst_clock';
  $clock_type = $config
    ->get('jstimer_jst_clock_type');
  $ret->js_code = <<<JAVASCRIPT_CODE

/*
 * Clock widget
 */
Drupal.jstimer.jst_clock = function() {
  this.selector = ".jst_clock";
  this.attach = function() {
    jQuery(this.selector).each(
      function(i) {
        if (!this.getAttribute("jst_clock_attached")) {
            var t = new Drupal.jstimer.jst_clock_item(jQuery(this));
            Drupal.jstimer.timer_stack[Drupal.jstimer.timer_stack.length] = t;
            this.setAttribute("jst_clock_attached", true);
        }
      }
    );
  }
}

Drupal.jstimer.jst_clock_item = function(ele) {

  // class methods first so you can use them in the constructor.
  this.loadProps = function() {
    for (var prop in this.props) {
      var prop_selector = "span[class="+prop+"]";
      if ( this.element.children(prop_selector).length > 0 ) {
        this.props[prop] = this.element.children(prop_selector).html();
      }
    }

    // If browser doesn't support the html canvas element, default to 12-hour clock.
    if ( !supports_canvas() &&  this.props['clock_type'] == 2 ) {
      this.props['clock_type'] = 0;
    }
  }

  this.update = function() {
    var timenow = new Date();
    var hr = timenow.getHours();
    var min = timenow.getMinutes();
    var sec = timenow.getSeconds();
    if ( this.props['clock_type'] == 0 ) {
      var am_pm = ""
      if ( hr <= 12 ) {
        am_pm = "am";
      } else {
        am_pm = "pm";
        hr = hr - 12;
      }
      this.element.html(hr + ":" + LZ(min) + ":" + LZ(sec) + am_pm);
    } else if ( this.props['clock_type'] == 1 ) {
      this.element.html(hr + ":" + LZ(min) + ":" + LZ(sec));
    } else if ( this.props['clock_type'] == 2 ) {
      if ( this.canvas ) {
        var ctx = this.canvas[0].getContext("2d");

        // save original context
        ctx.save(); // 1

        // clear and set defaults.
        ctx.clearRect(0,0,this.props['size'],this.props['size']);
        ctx.translate((this.props['size']/2),(this.props['size']/2));
        ctx.scale(0.4,0.4);
        ctx.rotate(-Math.PI/2);
        ctx.strokeStyle = "black";
        ctx.fillStyle = "white";
        ctx.lineWidth = 8;
        ctx.lineCap = "round";
        ctx.save(); // 2

        // render hour tick marks
        for (var i=0;i<12;i++){
         ctx.beginPath();
         ctx.rotate(Math.PI/6);
         ctx.moveTo(this.props['size']-20,0);
         ctx.lineTo(this.props['size'],0);
         ctx.stroke();
        }
        ctx.restore();  // 1

        ctx.fillStyle = "black";

        // render hour hand
        ctx.save(); // 3
        var hr_hand_size = 0.4 * this.props['size'];
        ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
        ctx.lineWidth = 14;
        ctx.beginPath();
        ctx.moveTo(-20,0);
        ctx.lineTo(hr_hand_size, 0);
        ctx.stroke();
        ctx.restore();   // 2

        // render minute hand
        var min_hand_size = 0.85 * this.props['size'];
        ctx.save(); // 4
        ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )
        ctx.lineWidth = 10;
        ctx.beginPath();
        ctx.moveTo(-28,0);
        ctx.lineTo(min_hand_size, 0);
        ctx.stroke();
        ctx.restore();  // 3

        // render second hand
        ctx.save(); // 5
        var sec_hand_size = 0.85 * this.props['size'];
        ctx.rotate(sec * Math.PI/30);
        ctx.strokeStyle = "#D40000";
        ctx.fillStyle = "#D40000";
        ctx.lineWidth = 6;
        ctx.beginPath();
        ctx.moveTo(-30,0);
        ctx.lineTo(sec_hand_size, 0);
        ctx.stroke();
        ctx.beginPath();
        ctx.arc(0,0,10,0,Math.PI*2,true);
        ctx.fill();
        ctx.beginPath();
        ctx.arc(sec_hand_size, 0, 10, 0, Math.PI*2, true);
        ctx.stroke();
        ctx.fillStyle = "#555";
        ctx.arc(0,0,3,0,Math.PI*2,true);
        ctx.fill();
        ctx.restore();  // 4

        // render clock face circle
        ctx.save(); // 6
        ctx.beginPath();
        ctx.lineWidth = 14;
        ctx.strokeStyle = '#325FA2';
        ctx.arc(0,0,this.props['size'],0,Math.PI*2,true);
        ctx.stroke();
        ctx.restore(); // 5

        // Days box
        //ctx.save(); // 7
        //ctx.rotate(90 * Math.PI / 180);
        //ctx.fillStyle    = '#FFFFFF';
        //ctx.fillRect(0, this.props['size']/3, 100, 60);
        //ctx.strokeStyle = '#325FA2';
        //ctx.strokeRect(0, this.props['size']/3, 100, 60);
        //ctx.restore(); // 6

        // days text
        //ctx.rotate(90 * Math.PI / 180);
        //ctx.fillStyle    = '#0000FF';
        //ctx.font         = 'courier-new 30px';
        //ctx.fillText  ('Days', 110, (this.props['size']/3)+50);
        ctx.restore();  // 7
      }
    }

    // SVG Clock
    else if ( this.props['clock_type'] == 3 ) {
      if (this.clock && !this.clockSvgWin) {
        this.clockSvgWin = getSvgWindow(clock);
      }
      if (this.clock && this.clockSvgWin) {
        try{
          this.clockSvgWin.animate();
        }
        catch(err) {
          //Some browsers will have a timing error and require one more iteration.
        }
      }
    }
    return true;
  }

  // begin constructor
  this.element = ele; // jquery ele
  this.props = {clock_type:{<span class="php-variable">$clock_type</span>}, size:200};
  this.loadProps();

  // add canvas if analog.
  if ( this.props['clock_type'] == 2 ) {
    this.canvas = jQuery('<canvas class="ct_clock_canvas"><p>Your browser doesn\\'t support canvas.</p></canvas>');
    this.canvas.attr("width",this.props['size']);
    this.canvas.attr("height",this.props['size']);
    this.element.append(this.canvas);
  }
  else if ( this.props['clock_type'] == 3 ) {
    var clock = jQuery('<object data="/{<span class="php-variable">$mod_path</span>}/clocks/{<span class="php-variable">$svg_file</span>}" type="image/svg+xml"></object>');
    clock.attr('width',this.props['size']);
    clock.attr('height',this.props['size']);
    this.element.html('');
    this.element.append(clock);
    this.clock = clock;
  }


}

function supports_canvas() {
  return !!document.createElement('canvas').getContext;
}

function getSvgWindow(clock) {
  var svgDoc;
  var svgWin;
  var jsClock = clock.get(0);
  if (jsClock.contentDocument) {
    svgDoc = jsClock.contentDocument; //get the inner DOM of alpha.svg
  }
  else {
    try {
      svgDoc = jsClock.getSVGDocument();
    }
    catch(exception) {
      // Ignore errors, this exception will fire if the DOM is not loaded yet.
    }
  }

  if (svgDoc && svgDoc.defaultView) {
    svgWin = svgDoc.defaultView;
  }
  else if (jsClock.window) {
    svgWin = jsClock.window;
  }
  else try {
    svgWin = jsClock.getWindow();
  }
  catch(exception) {
    // Ignore errors, this exception will fire if the DOM is not loaded yet.
  }
  return svgWin;
}

// End of clock widget.

JAVASCRIPT_CODE;
  return $ret;
}

/**
 * Implementation of hook_form_alter().
 * Add the clock widget specific settings to admin screen.
 */
function jst_clock_form_jstimer_admin_settings_alter(&$form, FormStateInterface $form_state, $form_id) {
  $config = \Drupal::config('jstimer.settings');
  $form['jst_clock'] = array(
    '#type' => 'fieldset',
    '#title' => t('Clock widget'),
    '#weight' => 5,
  );
  $form['jst_clock']['jstimer_jst_clock_demo'] = array(
    '#markup' => '<div class="jst_clock"></div>' . t('After saving, you need to reload the page to see the new clock.'),
  );
  $form['jst_clock']['jstimer_jst_clock_type'] = array(
    '#type' => 'radios',
    '#title' => t('Clock type'),
    '#default_value' => $config
      ->get('jstimer_jst_clock_type'),
    '#options' => array(
      0 => t('12-hour plain text'),
      1 => t('24-hour plain text'),
      2 => t('Analog canvas'),
      3 => t('Analog SVG'),
    ),
    '#description' => t("The analog clocks are experimental and only works on Firefox, Opera, and Safari and IE9."),
  );
  $form['jst_clock']['jst_clock_sva_file'] = array(
    '#type' => 'textfield',
    '#title' => t('Clock svg file'),
    '#default_value' => $config
      ->get('jst_clock_sva_file'),
    '#description' => t('The name of the svg file to use for the SVG clock.  They are stored in the widgets/clocks sub directory.'),
  );
  $form['buttons']['#weight'] = 10;

  // Put this module's submit handler first so it can save before javascript file is built.
  array_unshift($form['#submit'], 'jst_clock_admin_settings_submit');
}
function jst_clock_admin_settings_submit($form, FormStateInterface $form_state) {
  $config = \Drupal::configFactory()
    ->getEditable('jstimer.settings');
  $config
    ->set('jstimer_jst_clock_type', $form_state
    ->getValue('jstimer_jst_clock_type'));
  $config
    ->set('jst_clock_sva_file', $form_state
    ->getValue('jst_clock_sva_file'));
  $config
    ->save();
}
function jst_clock_show($widget_args) {
  $output = '<span class="jst_clock">';
  $valid_atts = array(
    'clock_type',
    'size',
  );
  foreach ($valid_atts as $att) {
    if (isset($widget_args[$att])) {
      $output .= '<span style="display:none" class="' . $att . '">' . $widget_args[$att] . '</span>';
    }
  }
  $output .= '</span>';
  return $output;
}

/**
 * Implementation of hook_install().
 */
function jst_clock_install() {
  jstimer_build_js_cache();
  drupal_clear_js_cache();
}

Functions

Namesort descending Description
jst_clock_admin_settings_submit
jst_clock_form_jstimer_admin_settings_alter Implementation of hook_form_alter(). Add the clock widget specific settings to admin screen.
jst_clock_install Implementation of hook_install().
jst_clock_jstwidget Implementation of hook_jstwidget().
jst_clock_show