/** * * @param string $name The element name * @param string $value The time displayed in this widget * @param array $attributes An array of HTML attributes to be merged with the default HTML attributes * @param array $errors An array of errors for the field * @return string An HTML tag string * @see sfWidgetForm */ public function render($name, $value = null, $attributes = array(), $errors = array()) { $format = true; $empty = empty($value); if ($empty) { $format = false; } if (is_array($value)) { if (!strlen($value['hour']) || !strlen($value['minute'])) { $format = false; } else { $value = $value['hour'] . ':' . $value['minute']; if (isset($value['second'])) { $value .= ':' . $value['second']; } } } if ($format) { $value = date($this->getOption('format'), strtotime($value)); } $attributes['id'] = $this->generateId($name); $html = parent::render($name, $value, $attributes, $errors); $wrapperID = $attributes['id'] . rand(0, 10000); $html = $this->wrapInDiv($html, $wrapperID); $html .= "<script type='text/javascript'>\$(document).ready(function() { timepicker2('#" . $wrapperID . "', " . json_encode($attributes) . ") });</script>"; return $html; }
/** * Constructor. * * Available options: * * * culture: The culture to use for internationalized strings (required) * * @param array $options An array of options * @param array $attributes An array of default HTML attributes * * @see sfWidgetFormTime */ protected function configure($options = array(), $attributes = array()) { parent::configure($options, $attributes); $this->addRequiredOption('culture'); $culture = isset($options['culture']) ? $options['culture'] : 'en'; // format $this->setOption('format', $this->getTimeFormat($culture, true)); // format_without_seconds $this->setOption('format_without_seconds', $this->getTimeFormat($culture, false)); }
protected function configure($options = array(), $attributes = array()) { $this->addOption('am_pm', true); $this->addOption('minute_prefix', null); parent::configure($options, $attributes); if ($options['am_pm']) { $hours = array(); for ($i = 0; $i <= 23; $i++) { $hours[$i + 1] = sprintf('%02d %s', $i % 12 + 1, $i < 12 ? 'am' : 'pm'); } $this->setOption('hours', $hours); } if ('' != (string) $options['minute_prefix']) { $minutes = $this->generateTwoCharsRange(0, 59); foreach ($minutes as $idx => $value) { $minutes[$idx] = $options['minute_prefix'] . $value; } $this->setOption('minutes', $minutes); } }
<?php /* * This file is part of the symfony package. * (c) Fabien Potencier <*****@*****.**> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ require_once dirname(__FILE__) . '/../../bootstrap/unit.php'; $t = new lime_test(43); $w = new sfWidgetFormTime(array('with_seconds' => true)); $dom = new DomDocument('1.0', 'utf-8'); $dom->validateOnParse = true; // ->render() $t->diag('->render()'); foreach (array('12:30:35', mktime(12, 30, 35, 15, 10, 2005)) as $date) { $dom->loadHTML($w->render('foo', $date)); $css = new sfDomCssSelector($dom); // selected date $t->is($css->matchSingle('#foo_hour option[value="12"][selected="selected"]')->getValue(), 12, '->render() renders a select tag for the hour'); $t->is($css->matchSingle('#foo_minute option[value="30"][selected="selected"]')->getValue(), 30, '->render() renders a select tag for the minute'); $t->is($css->matchSingle('#foo_second option[value="35"][selected="selected"]')->getValue(), 35, '->render() renders a select tag for the second'); } // time as an array $t->diag('time as an array'); $dom->loadHTML($w->render('foo', array('hour' => 12, 'minute' => '30', 'second' => 35))); $css = new sfDomCssSelector($dom); $t->is($css->matchSingle('#foo_hour option[value="12"][selected="selected"]')->getValue(), 12, '->render() renders a select tag for the hour'); $t->is($css->matchSingle('#foo_minute option[value="30"][selected="selected"]')->getValue(), 30, '->render() renders a select tag for the minute'); $t->is($css->matchSingle('#foo_second option[value="35"][selected="selected"]')->getValue(), 35, '->render() renders a select tag for the second');
/** * @param string $name The element name * @param string $value The date displayed in this widget * @param array $attributes An array of HTML attributes to be merged with the default HTML attributes * @param array $errors An array of errors for the field * * @return string An HTML tag string * * @see sfWidgetFormJQueryDate * @see sfWidgetForm */ public function render($name, $value = null, $attributes = array(), $errors = array()) { $prefix = $this->generateId($name); $image = ''; if (false !== $this->getOption('image')) { $image = sprintf(', buttonImage: "%s", buttonImageOnly: true', $this->getOption('image')); } $time_str = ''; if ($this->getOption('with_time')) { $widget = new sfWidgetFormTime(array('empty_values' => array_merge(array('hour' => '', 'minute' => '', 'second' => ''), $this->getOption('empty_values')), 'with_seconds' => $this->getOption('with_seconds'))); $time_str = $widget->render($name, $value, $attributes, $errors); } $script_to_format = '<script type="text/javascript"> function wfd_%1$s_read_linked() { var day = 1; var month = 1; var year = %2$s; if (jQuery("#%3$s").val() != "") { year = jQuery("#%3$s").val(); } else if (jQuery("#%3$s").hasClass("to_date")) { year = %4$s; } if (jQuery("#%5$s").val() != "") { month = jQuery("#%5$s").val(); } else if (jQuery("#%5$s").hasClass("to_date")) { month = 12; } if (jQuery("#%5$s").val() == "") { jQuery("#%6$s").val(""); } var daysInMonth = 32 - new Date(year, month - 1, 32).getDate(); if ((jQuery("#%3$s").val() != "") && (jQuery("#%5$s").val() != "") && (jQuery("#%6$s").val() != "")) { day = jQuery("#%6$s").val(); } else if (jQuery("#%3$s").hasClass("to_date")) { day = daysInMonth; } jQuery("#%7$s").val(year + "-" + month + "-" + day); if(jQuery("#%7$s").val() == "%4$s-12-31") { jQuery("#%7$s").val( jQuery(".from_date[id$=\\"_year\\"]").val() + "-" + jQuery(".from_date[id$=\\"_month\\"]").val() + "-" + jQuery(".from_date[id$=\\"_day\\"]").val() ); } return {}; } function wfd_%1$s_update_linked(date) { a_date = date.split("-"); jQuery("#%3$s").val(parseInt(a_date[0],10)); jQuery("#%5$s").val(parseInt(a_date[1],10)); jQuery("#%6$s").val(parseInt(a_date[2],10)); } function wfd_%1$s_check_linked_days() { var daysInMonth = 32 - new Date(jQuery("#%3$s").val(), jQuery("#%5$s").val() - 1, 32).getDate(); jQuery("#%6$s option").removeAttr("disabled"); jQuery("#%6$s option:gt(" + (%8$s) +")").attr("disabled", "disabled"); if (jQuery("#%6$s").val() > daysInMonth) { jQuery("#%6$s").val(daysInMonth); } } jQuery(document).ready(function() { jQuery("#%7$s").datepicker(jQuery.extend({}, { minDate: new Date(%2$s, 1 - 1, 1), maxDate: new Date(%9$s, 12 - 1, 31), yearRange: "%2$s:%9$s", beforeShow: wfd_%1$s_read_linked, onSelect: wfd_%1$s_update_linked, changeMonth: true, changeYear: true, showButtonPanel: false, beforeShow: function(input, inst) { var newclass = "%13$s"; if (newclass != "" && !inst.dpDiv.parent().hasClass(newclass) && jQuery("#%7$s").closest("form").hasClass(newclass)){ inst.dpDiv.wrap("<div class=\\""+newclass+"\\"></div>") } }, showOn: "button" %10$s }, jQuery.datepicker.regional["%11$s"], %12$s, {dateFormat: "yy-mm-dd"})); }); jQuery("#%6$s, #%5$s, #%3$s").change(wfd_%1$s_check_linked_days); </script>'; return parent::render($name, $value, $attributes, $errors) . $this->renderTag('input', array('type' => 'hidden', 'size' => 10, 'id' => $id = $this->generateId($name) . '_jquery_control', 'disabled' => 'disabled')) . sprintf($script_to_format, $prefix, min($this->getOption('years')), $this->generateId($name . '[year]'), date('Y'), $this->generateId($name . '[month]'), $this->generateId($name . '[day]'), $id, $this->getOption('can_be_empty') ? 'daysInMonth' : 'daysInMonth - 1', max($this->getOption('years')), $image, $this->getOption('culture'), $this->getOption('config'), $this->getOption('wrap_class')) . $time_str; }
/** * @param string $name The element name * @param string $value The date displayed in this widget (sometimes already an array with hour and minute keys) * @param array $attributes An array of HTML attributes to be merged with the default HTML attributes * @param array $errors An array of errors for the field * * @return string An HTML tag string * * @see sfWidgetForm */ public function render($name, $value = null, $attributes = array(), $errors = array()) { $prefix = $this->generateId($name); $image = ''; if (false !== $this->getOption('image')) { // TODO: clock widget handling } $hourid = $this->generateId($name . '[hour]'); $minid = $this->generateId($name . '[minute]'); $s = '<div class="a-time-wrapper" id="' . $prefix . '-time">'; $s .= '<span style="display: none">' . parent::render($name, $value, $attributes, $errors) . '</span>'; $val = ''; if (is_array($value)) { if (strlen($value['hour']) && strlen($value['minute'])) { $val = htmlspecialchars(aDate::time(sprintf("%02d:%02d:00", $value['hour'], $value['minute']), false)); } } elseif (strlen($value)) { $val = htmlspecialchars(aDate::time($value, false), ENT_QUOTES); } $s .= "<input type='text' name='a-ignored' id='{$prefix}-ui' value='{$val}' class='" . (isset($attributes['class']) ? $attributes['class'] : '') . "'><img id='{$prefix}-ui-trigger' class='ui-timepicker-trigger' src='/apostrophePlugin/images/a-icon-time.png'/>"; $s .= <<<EOM <script> \$(function() { var hour; var min; var times = [ ]; for (thour = 0; (thour < 24); thour++) { // Starting with 8am makes more sense for typical clients var hour = (thour + 8) % 24; for (min = 0; (min < 60); min += 30) { times.push(prettyTime(hour, min)); } } \$('#{$prefix}-ui').autocomplete(times, { minChars: 0, selectFirst: false, max: 100 }); // Double click on focus pops up autocomplete immediately \$('#{$prefix}-ui').focus(function() { \$(this).click(); \$(this).click() } ).next().click(function(event){ \t\tevent.preventDefault(); \t\t\$(this).prev().focus(); \t}); \$('#{$prefix}-ui').blur(function() { var val = \$(this).val(); var components = val.match(/(\\d\\d?)(:\\d\\d)?\\s*(am|pm)?/i); if (components) { var hour = components[1]; var min = components[2]; if (min) { min = min.substr(1); } if (!min) { min = '00'; } if (min < 10) { min = '0' + Math.floor(min); } var ampm = components[3] ? components[3].toUpperCase() : false; if (!ampm) { if (hour >= 8) { ampm = 'AM'; } else { ampm = 'PM'; } } var formal = hour + ':' + min + ampm; \$(this).val(formal); if ((ampm === 'AM') && (hour == 12)) { hour = 0; } if ((ampm === 'PM') && !(hour == 12)) { // Careful: force numeric hour = Math.floor(hour) + 12; } \$('#{$hourid}').val(hour); \$('#{$minid}').val(min); // Something to bind to in other places \$(this).trigger('aTimeUpdated'); } else { if (val.length) { alert("The time must be in hh:mm format, followed by AM or PM. Hint: click on the typeahead suggestions."); \$('#{$prefix}-ui').focus(); } else { // NULL is often a valid value \$('#{$hourid}').val(''); \$('#{$minid}').val(''); } } }); function prettyTime(hour, min) { var ampm = 'AM'; phour = hour; if (hour >= 12) { ampm = 'PM'; } if (hour >= 13) { phour -= 12; } if (phour == 0) { phour = 12; } pmin = min; if (min < 10) { pmin = '0' + Math.floor(min); } return phour + ':' + pmin + ampm; } \t// General useability stuff that the original date widget was lacking because it was made by robots and not actual human beings \t\$('#{$prefix}-ui-trigger').attr('title','Set A Time').hover(function(){ \t\t\$(this).fadeTo(0,.5); \t},function(){ \t\t\$(this).fadeTo(0,1); \t}); }); </script> </div> EOM; return $s; }
/** * @param string $name The element name * @param string $value The date displayed in this widget * @param array $attributes An array of HTML attributes to be merged with the default HTML attributes * @param array $errors An array of errors for the field * * @return string An HTML tag string * * @see sfWidgetForm */ public function render($name, $value = null, $attributes = array(), $errors = array()) { $prefix = $this->generateId($name); $image = ''; if (false !== $this->getOption('image')) { // TODO: clock widget handling } $hourid = $this->generateId($name . '[hour]'); $minid = $this->generateId($name . '[minute]'); $s = '<span style="display: none">' . parent::render($name, $value, $attributes, $errors) . '</span>'; $val = htmlspecialchars(pkDate::time($value), ENT_QUOTES); $s .= "<input type='text' name='pk-ignored' id='{$prefix}-ui' value='{$val}' class='" . (isset($attributes['class']) ? $attributes['class'] : '') . "'>"; $s .= <<<EOM <script> \$(function() { var hour; var min; var times = [ ]; for (thour = 0; (thour < 24); thour++) { // Starting with 8am makes more sense for typical clients var hour = (thour + 8) % 24; for (min = 0; (min < 60); min += 30) { times.push(prettyTime(hour, min)); } } \$('#{$prefix}-ui').autocomplete(times, { minChars: 0, selectFirst: false, max: 100 }); // Double click on focus pops up autocomplete immediately \$('#{$prefix}-ui').focus(function() { \$(this).click(); \$(this).click() } ); \$('#{$prefix}-ui').blur(function() { var val = \$(this).val(); var components = val.match(/(\\d\\d?)(:\\d\\d)?\\s*(am|pm)?/i); if (components) { var hour = components[1]; var min = components[2]; if (min) { min = min.substr(1); } if (!min) { min = '00'; } if (min < 10) { min = '0' + Math.floor(min); } var ampm = components[3] ? components[3].toUpperCase() : false; if (!ampm) { if (hour >= 8) { ampm = 'AM'; } else { ampm = 'PM'; } } var formal = hour + ':' + min + ampm; \$(this).val(formal); if ((ampm === 'AM') && (hour == 12)) { hour = 0; } if (ampm === 'PM') { // Careful: force numeric hour = Math.floor(hour) + 12; } \$('#{$hourid}').val(hour); \$('#{$minid}').val(min); } else { if (val.length) { alert("The time must be in hh:mm format, followed by AM or PM. Hint: click on the typeahead suggestions."); \$('#{$prefix}-ui').focus(); } } }); function prettyTime(hour, min) { var ampm = 'AM'; phour = hour; if (hour >= 12) { ampm = 'PM'; } if (hour >= 13) { phour -= 12; } if (phour == 0) { phour = 12; } pmin = min; if (min < 10) { pmin = '0' + Math.floor(min); } return phour + ':' + pmin + ampm; } }); </script> EOM; return $s; }
public function getJavaScripts() { return array_merge(parent::getJavaScripts(), array('lib.ui-core', 'lib.ui-widget', 'lib.ui-mouse', 'lib.ui-slider', 'lib.ui-datepicker', 'dmDateTimePickerPlugin.tp-add-on', 'dmDateTimePickerPlugin.tp-add-on-i18n', 'dmDateTimePickerPlugin.time-picker')); }