jst_clock.module in Javascript Timer 8
Same filename and directory in other branches
Embeddable clock widget (optional).
File
widgets/jst_clock.moduleView 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
Name | 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 |