001package org.gwtbootstrap3.extras.datetimepicker.client.ui.base; 002 003/* 004 * #%L 005 * GwtBootstrap3 006 * %% 007 * Copyright (C) 2016 GwtBootstrap3 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import java.util.Date; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Map; 027 028import org.gwtbootstrap3.client.shared.event.HideEvent; 029import org.gwtbootstrap3.client.shared.event.HideHandler; 030import org.gwtbootstrap3.client.shared.event.ShowEvent; 031import org.gwtbootstrap3.client.shared.event.ShowHandler; 032import org.gwtbootstrap3.client.ui.TextBox; 033import org.gwtbootstrap3.client.ui.base.HasId; 034import org.gwtbootstrap3.client.ui.base.HasPlaceholder; 035import org.gwtbootstrap3.client.ui.base.HasReadOnly; 036import org.gwtbootstrap3.client.ui.base.HasResponsiveness; 037import org.gwtbootstrap3.client.ui.base.ValueBoxBase; 038import org.gwtbootstrap3.client.ui.base.helper.StyleHelper; 039import org.gwtbootstrap3.client.ui.base.mixin.BlankValidatorMixin; 040import org.gwtbootstrap3.client.ui.base.mixin.ErrorHandlerMixin; 041import org.gwtbootstrap3.client.ui.constants.DeviceSize; 042import org.gwtbootstrap3.client.ui.form.error.ErrorHandler; 043import org.gwtbootstrap3.client.ui.form.error.ErrorHandlerType; 044import org.gwtbootstrap3.client.ui.form.error.HasErrorHandler; 045import org.gwtbootstrap3.client.ui.form.validator.HasBlankValidator; 046import org.gwtbootstrap3.client.ui.form.validator.HasValidators; 047import org.gwtbootstrap3.client.ui.form.validator.ValidationChangedEvent.ValidationChangedHandler; 048import org.gwtbootstrap3.client.ui.form.validator.Validator; 049import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.DateTimePickerDayOfWeek; 050import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.DateTimePickerFormatViewType; 051import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.DateTimePickerLanguage; 052import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.DateTimePickerPosition; 053import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.DateTimePickerView; 054import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasAutoClose; 055import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasDateTimePickerHandlers; 056import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasDaysOfWeekDisabled; 057import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasEndDate; 058import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasForceParse; 059import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasFormat; 060import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasHighlightToday; 061import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasKeyboardNavigation; 062import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasLanguage; 063import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasMaxView; 064import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasMinView; 065import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasMinuteStep; 066import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasPosition; 067import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasShowMeridian; 068import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasShowTodayButton; 069import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasShowClearButton; 070import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasStartDate; 071import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasStartView; 072import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasViewSelect; 073import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.HasWeekStart; 074import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.ChangeDateEvent; 075import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.ChangeDateHandler; 076import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.ChangeMonthEvent; 077import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.ChangeMonthHandler; 078import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.ChangeYearEvent; 079import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.ChangeYearHandler; 080import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.OutOfRangeEvent; 081import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.OutOfRangeHandler; 082 083import com.google.gwt.core.client.ScriptInjector; 084import com.google.gwt.dom.client.Element; 085import com.google.gwt.editor.client.EditorError; 086import com.google.gwt.editor.client.HasEditorErrors; 087import com.google.gwt.editor.client.LeafValueEditor; 088import com.google.gwt.event.dom.client.BlurEvent; 089import com.google.gwt.event.dom.client.BlurHandler; 090import com.google.gwt.event.logical.shared.ValueChangeEvent; 091import com.google.gwt.event.logical.shared.ValueChangeHandler; 092import com.google.gwt.event.shared.HandlerRegistration; 093import com.google.gwt.i18n.client.DateTimeFormat; 094import com.google.gwt.user.client.Event; 095import com.google.gwt.user.client.ui.HasEnabled; 096import com.google.gwt.user.client.ui.HasName; 097import com.google.gwt.user.client.ui.HasValue; 098import com.google.gwt.user.client.ui.HasVisibility; 099import com.google.gwt.user.client.ui.Widget; 100 101/** 102 * @author Joshua Godi 103 * @author Steven Jardine 104 */ 105public class DateTimePickerBase extends Widget implements HasEnabled, HasReadOnly, HasId, HasResponsiveness, HasVisibility, 106 HasPlaceholder, HasAutoClose, HasDaysOfWeekDisabled, HasEndDate, HasForceParse, HasFormat, HasHighlightToday, 107 HasKeyboardNavigation, HasMaxView, HasMinuteStep, HasMinView, HasShowMeridian, HasShowTodayButton, HasShowClearButton, HasStartDate, 108 HasStartView, HasViewSelect, HasWeekStart, HasDateTimePickerHandlers, HasLanguage, HasName, HasValue<Date>, HasPosition, 109 LeafValueEditor<Date>, HasEditorErrors<Date>, HasErrorHandler, HasValidators<Date>, HasBlankValidator<Date> { 110 111 static class DatePickerValidatorMixin extends BlankValidatorMixin<DateTimePickerBase, Date> { 112 113 private boolean showing = false; 114 115 public void setShowing(boolean showing) { 116 this.showing = showing; 117 } 118 119 public DatePickerValidatorMixin(DateTimePickerBase inputWidget, ErrorHandler errorHandler) { 120 super(inputWidget, errorHandler); 121 } 122 123 @Override 124 protected com.google.web.bindery.event.shared.HandlerRegistration setupBlurValidation() { 125 return getInputWidget().addDomHandler(new BlurHandler() { 126 @Override 127 public void onBlur(BlurEvent event) { 128 getInputWidget().validate(!showing && getValidateOnBlur()); 129 } 130 }, BlurEvent.getType()); 131 } 132 133 } 134 135 // Check http://www.gwtproject.org/javadoc/latest/com/google/gwt/i18n/client/DateTimeFormat.html 136 // for more information on syntax 137 private static final Map<Character, Character> DATE_TIME_FORMAT_MAP = new HashMap<Character, Character>(); 138 static { 139 DATE_TIME_FORMAT_MAP.put('h', 'H'); // 12/24 hours 140 DATE_TIME_FORMAT_MAP.put('H', 'h'); // 12/24 hours 141 DATE_TIME_FORMAT_MAP.put('m', 'M'); // months 142 DATE_TIME_FORMAT_MAP.put('i', 'm'); // minutes 143 DATE_TIME_FORMAT_MAP.put('p', 'a'); // meridian 144 DATE_TIME_FORMAT_MAP.put('P', 'a'); // meridian 145 } 146 147 private final TextBox textBox; 148 private DateTimeFormat dateTimeFormat; 149 private final DateTimeFormat startEndDateFormat = DateTimeFormat.getFormat("yyyy-MM-dd"); 150 private LeafValueEditor<Date> editor; 151 private final ErrorHandlerMixin<Date> errorHandlerMixin = new ErrorHandlerMixin<Date>(this); 152 private final DatePickerValidatorMixin validatorMixin = new DatePickerValidatorMixin(this, 153 errorHandlerMixin.getErrorHandler()); 154 155 /** 156 * DEFAULT values 157 */ 158 private String format = "mm/dd/yyyy hh:ii"; 159 private DateTimePickerFormatViewType formatViewType = DateTimePickerFormatViewType.DATE_TIME; 160 private DateTimePickerDayOfWeek weekStart = DateTimePickerDayOfWeek.SUNDAY; 161 private DateTimePickerDayOfWeek[] daysOfWeekDisabled = {}; 162 private boolean autoClose = false; 163 private DateTimePickerView startView = DateTimePickerView.MONTH; 164 private DateTimePickerView minView = DateTimePickerView.HOUR; 165 private DateTimePickerView maxView = DateTimePickerView.DECADE; 166 private boolean showTodayButton = false; 167 private boolean showClearButton = false; 168 private boolean highlightToday = false; 169 private boolean keyboardNavigation = true; 170 private boolean forceParse = true; 171 private int minuteStep = 5; 172 private DateTimePickerView viewSelect = DateTimePickerView.HOUR; 173 private boolean showMeridian = false; 174 private DateTimePickerLanguage language = DateTimePickerLanguage.EN; 175 private DateTimePickerPosition position = DateTimePickerPosition.BOTTOM_RIGHT; 176 177 public DateTimePickerBase() { 178 textBox = new TextBox(); 179 setElement((Element) textBox.getElement()); 180 setFormat(format); 181 } 182 183 public TextBox getTextBox() { 184 return textBox; 185 } 186 187 public void setAlignment(final ValueBoxBase.TextAlignment align) { 188 textBox.setAlignment(align); 189 } 190 191 /** {@inheritDoc} */ 192 @Override 193 public void setPlaceholder(final String placeHolder) { 194 textBox.setPlaceholder(placeHolder); 195 } 196 197 /** {@inheritDoc} */ 198 @Override 199 public String getPlaceholder() { 200 return textBox.getPlaceholder(); 201 } 202 203 public void setReadOnly(final boolean readOnly) { 204 textBox.setReadOnly(readOnly); 205 } 206 207 public boolean isReadOnly() { 208 return textBox.isReadOnly(); 209 } 210 211 212 /** {@inheritDoc} */ 213 @Override 214 public boolean isEnabled() { 215 return textBox.isEnabled(); 216 } 217 218 /** {@inheritDoc} */ 219 @Override 220 public void setEnabled(final boolean enabled) { 221 textBox.setEnabled(enabled); 222 } 223 224 /** {@inheritDoc} */ 225 @Override 226 public void setId(final String id) { 227 textBox.setId(id); 228 } 229 230 /** {@inheritDoc} */ 231 @Override 232 public String getId() { 233 return textBox.getId(); 234 } 235 236 /** {@inheritDoc} */ 237 @Override 238 public void setName(final String name) { 239 textBox.setName(name); 240 } 241 242 /** {@inheritDoc} */ 243 @Override 244 public String getName() { 245 return textBox.getName(); 246 } 247 248 /** {@inheritDoc} */ 249 @Override 250 public void setVisibleOn(final DeviceSize deviceSize) { 251 StyleHelper.setVisibleOn(this, deviceSize); 252 } 253 254 /** {@inheritDoc} */ 255 @Override 256 public void setHiddenOn(final DeviceSize deviceSize) { 257 StyleHelper.setHiddenOn(this, deviceSize); 258 } 259 260 /** {@inheritDoc} */ 261 @Override 262 public void setLanguage(final DateTimePickerLanguage language) { 263 this.language = language; 264 265 // Inject the JS for the language 266 if (language.getJs() != null) { 267 ScriptInjector.fromString(language.getJs().getText()) 268 .setWindow(ScriptInjector.TOP_WINDOW).inject(); 269 } 270 } 271 272 /** {@inheritDoc} */ 273 @Override 274 public DateTimePickerLanguage getLanguage() { 275 return language; 276 } 277 278 /** {@inheritDoc} */ 279 @Override 280 public void setPosition(final DateTimePickerPosition position) { 281 this.position = position; 282 } 283 284 /** {@inheritDoc} */ 285 @Override 286 public DateTimePickerPosition getPosition() { 287 return position; 288 } 289 290 /** 291 * Call this whenever changing any settings: minView, startView, format, etc. If you are changing 292 * format and date value, the updates must take in such order: 293 * <p/> 294 * 1. DateTimePicker.reload() 295 * 2. DateTimePicker.setValue(newDate); // Date newDate. 296 * <p/> 297 * Otherwise date value is not updated. 298 */ 299 public void reload() { 300 configure(); 301 } 302 303 public void show() { 304 show(getElement()); 305 } 306 307 public void hide() { 308 hide(getElement()); 309 } 310 311 /** {@inheritDoc} */ 312 @Override 313 public void setAutoClose(final boolean autoClose) { 314 this.autoClose = autoClose; 315 } 316 317 /** {@inheritDoc} */ 318 @Override 319 public void onShow(final Event e) { 320 validatorMixin.setShowing(true); 321 fireEvent(new ShowEvent(e)); 322 } 323 324 /** {@inheritDoc} */ 325 @Override 326 public HandlerRegistration addShowHandler(final ShowHandler showHandler) { 327 return addHandler(showHandler, ShowEvent.getType()); 328 } 329 330 /** {@inheritDoc} */ 331 @Override 332 public void onHide(final Event e) { 333 validatorMixin.setShowing(false); 334 validate(getValidateOnBlur()); 335 fireEvent(new HideEvent(e)); 336 } 337 338 /** {@inheritDoc} */ 339 @Override 340 public HandlerRegistration addHideHandler(final HideHandler hideHandler) { 341 return addHandler(hideHandler, HideEvent.getType()); 342 } 343 344 /** {@inheritDoc} */ 345 @Override 346 public void onChangeDate(final Event e) { 347 fireEvent(new ChangeDateEvent(e)); 348 ValueChangeEvent.fire(DateTimePickerBase.this, getValue()); 349 hide(); 350 } 351 352 /** {@inheritDoc} */ 353 @Override 354 public HandlerRegistration addChangeDateHandler(final ChangeDateHandler changeDateHandler) { 355 return addHandler(changeDateHandler, ChangeDateEvent.getType()); 356 } 357 358 /** {@inheritDoc} */ 359 @Override 360 public void onChangeYear(final Event e) { 361 fireEvent(new ChangeYearEvent(e)); 362 } 363 364 /** {@inheritDoc} */ 365 @Override 366 public HandlerRegistration addChangeYearHandler(final ChangeYearHandler changeYearHandler) { 367 return addHandler(changeYearHandler, ChangeYearEvent.getType()); 368 } 369 370 /** {@inheritDoc} */ 371 @Override 372 public void onChangeMonth(final Event e) { 373 fireEvent(new ChangeMonthEvent(e)); 374 } 375 376 /** {@inheritDoc} */ 377 @Override 378 public HandlerRegistration addChangeMonthHandler(final ChangeMonthHandler changeMonthHandler) { 379 return addHandler(changeMonthHandler, ChangeMonthEvent.getType()); 380 } 381 382 /** {@inheritDoc} */ 383 @Override 384 public void onOutOfRange(final Event e) { 385 fireEvent(new OutOfRangeEvent(e)); 386 } 387 388 /** {@inheritDoc} */ 389 @Override 390 public HandlerRegistration addOutOfRangeHandler(final OutOfRangeHandler outOfRangeHandler) { 391 return addHandler(outOfRangeHandler, OutOfRangeEvent.getType()); 392 } 393 394 /** {@inheritDoc} */ 395 @Override 396 public void setDaysOfWeekDisabled(final DateTimePickerDayOfWeek... daysOfWeekDisabled) { 397 setDaysOfWeekDisabled(getElement(), toDaysOfWeekDisabledString(daysOfWeekDisabled)); 398 } 399 400 /** {@inheritDoc} */ 401 @Override 402 public void setEndDate(final Date endDate) { 403 // Has to be in the format YYYY-MM-DD 404 setEndDate(startEndDateFormat.format(endDate)); 405 } 406 407 /** {@inheritDoc} */ 408 @Override 409 public void setEndDate(final String endDate) { 410 // Has to be in the format YYYY-MM-DD 411 setEndDate(getElement(), endDate); 412 } 413 414 /** {@inheritDoc} */ 415 @Override 416 public void clearEndDate() { 417 setStartDate(getElement(), null); 418 } 419 420 /** {@inheritDoc} */ 421 @Override 422 public void setForceParse(final boolean forceParse) { 423 this.forceParse = forceParse; 424 } 425 426 /** {@inheritDoc} */ 427 @Override 428 public void setHighlightToday(final boolean highlightToday) { 429 this.highlightToday = highlightToday; 430 } 431 432 /** {@inheritDoc} */ 433 @Override 434 public void setHasKeyboardNavigation(final boolean hasKeyboardNavigation) { 435 this.keyboardNavigation = hasKeyboardNavigation; 436 } 437 438 /** {@inheritDoc} */ 439 @Override 440 public void setMaxView(final DateTimePickerView dateTimePickerView) { 441 this.maxView = dateTimePickerView; 442 } 443 444 /** {@inheritDoc} */ 445 @Override 446 public void setMinView(final DateTimePickerView dateTimePickerView) { 447 this.minView = dateTimePickerView; 448 449 // We keep the view select the same as the min view 450 if (viewSelect != minView) { 451 setViewSelect(dateTimePickerView); 452 } 453 } 454 455 /** {@inheritDoc} */ 456 @Override 457 public void setMinuteStep(final int minuteStep) { 458 this.minuteStep = minuteStep; 459 } 460 461 /** {@inheritDoc} */ 462 @Override 463 public void setShowMeridian(final boolean showMeridian) { 464 this.showMeridian = showMeridian; 465 } 466 467 /** {@inheritDoc} */ 468 @Override 469 public void setShowTodayButton(final boolean showTodayButton) { 470 this.showTodayButton = showTodayButton; 471 } 472 473 /** {@inheritDoc} */ 474 @Override 475 public void setShowClearButton(final boolean showClearButton) { 476 this.showClearButton = showClearButton; 477 } 478 479 480 /** {@inheritDoc} */ 481 @Override 482 public void setStartDate(final Date startDate) { 483 // Has to be in the format YYYY-MM-DD 484 setStartDate(startEndDateFormat.format(startDate)); 485 } 486 487 /** {@inheritDoc} */ 488 @Override 489 public void setStartDate(final String startDate) { 490 // Has to be in the format YYYY-MM-DD 491 setStartDate(getElement(), startDate); 492 } 493 494 /** {@inheritDoc} */ 495 @Override 496 public void clearStartDate() { 497 setStartDate(getElement(), null); 498 } 499 500 /** {@inheritDoc} */ 501 @Override 502 public void setStartView(final DateTimePickerView dateTimePickerView) { 503 this.startView = dateTimePickerView; 504 } 505 506 /** {@inheritDoc} */ 507 @Override 508 public void setViewSelect(final DateTimePickerView dateTimePickerView) { 509 this.viewSelect = dateTimePickerView; 510 511 // We keep the min view the same as the view select 512 if (viewSelect != minView) { 513 setMinView(dateTimePickerView); 514 } 515 } 516 517 /** {@inheritDoc} */ 518 @Override 519 public void setWeekStart(final DateTimePickerDayOfWeek weekStart) { 520 this.weekStart = weekStart; 521 } 522 523 /** 524 * Convert GWT date time format to bootstrap date time format 525 * 526 * @param format date time format using GWT notation 527 * @return date time format using bootstrap notation 528 */ 529 private static String toBootstrapDateFormat(final String format) { 530 String bootstrap_format = format; 531 532 // Replace long day name "EEEE" with "DD" 533 bootstrap_format = bootstrap_format.replace("EEEE", "DD"); 534 // Replace short day name "EE" with "DD" 535 bootstrap_format = bootstrap_format.replaceAll("E{1,3}", "D"); 536 // Replace minutes "m" with "i" 537 bootstrap_format = bootstrap_format.replaceAll("m", "i"); 538 // Replace "H" with "h" and vice versa 539 bootstrap_format = bootstrap_format.replaceAll("H", "Q"); 540 bootstrap_format = bootstrap_format.replaceAll("h", "H"); 541 bootstrap_format = bootstrap_format.replaceAll("Q", "h"); 542 // Replace "a" with "P" for AM/PM markers 543 bootstrap_format = bootstrap_format.replaceAll("a", "P"); 544 545 // If there are at least 3 Ms there is month name in wording 546 if (bootstrap_format.contains("MMM")) { 547 // Replace long date month "MMMM" with "MM" 548 bootstrap_format = bootstrap_format.replace("MMMM", "MM"); 549 // Replace month name "MMM" with "M" 550 bootstrap_format = bootstrap_format.replace("MMM", "M"); 551 } 552 else { 553 // Replace month number with leading 0 "MM" with "mm" 554 bootstrap_format = bootstrap_format.replace("MM", "mm"); 555 // Replace month number "M" with "m" 556 bootstrap_format = bootstrap_format.replace("M", "m"); 557 } 558 if (!bootstrap_format.contains("yy")) { 559 // Replace full year format "y" with "yyyy" 560 bootstrap_format = bootstrap_format.replace("y", "yyyy"); 561 } 562 563 return bootstrap_format; 564 } 565 566 /** 567 * Sets format of the date using GWT notation 568 * 569 * @param format date time format in GWT notation 570 */ 571 public void setGWTFormat(final String format) { 572 this.format = toBootstrapDateFormat(format); 573 574 // Get the old value 575 final Date oldValue = getValue(); 576 577 // Make the new DateTimeFormat 578 this.dateTimeFormat = DateTimeFormat.getFormat(format); 579 580 if (oldValue != null) { 581 setValue(oldValue); 582 } 583 } 584 585 /** {@inheritDoc} */ 586 @Override 587 public void setFormat(final String format) { 588 this.format = format; 589 590 // Get the old value 591 final Date oldValue = getValue(); 592 593 // Make the new DateTimeFormat 594 setDateTimeFormat(format); 595 596 if (oldValue != null) { 597 setValue(oldValue); 598 } 599 } 600 601 private void setDateTimeFormat(final String format) { 602 final StringBuilder fb = new StringBuilder(format); 603 for (int i = 0; i < fb.length(); i++) { 604 if (DATE_TIME_FORMAT_MAP.containsKey(fb.charAt(i))) { 605 fb.setCharAt(i, DATE_TIME_FORMAT_MAP.get(fb.charAt(i))); 606 } 607 } 608 609 this.dateTimeFormat = DateTimeFormat.getFormat(fb.toString()); 610 } 611 612 /** 613 * Sets the format view type. 614 * 615 * @param formatViewType 616 * @see DateTimePickerFormatViewType 617 */ 618 public void setFormatViewType(DateTimePickerFormatViewType formatViewType) { 619 if (formatViewType != null) 620 this.formatViewType = formatViewType; 621 } 622 623 /** {@inheritDoc} */ 624 @Override 625 public Date getValue() { 626 try { 627 return dateTimeFormat != null && textBox.getValue() != null ? dateTimeFormat.parse(textBox.getValue()) : null; 628 } catch (final Exception e) { 629 return null; 630 } 631 } 632 633 public String getBaseValue() { 634 return textBox.getValue(); 635 } 636 637 /** {@inheritDoc} */ 638 @Override 639 public HandlerRegistration addValueChangeHandler(final ValueChangeHandler<Date> dateValueChangeHandler) { 640 textBox.addValueChangeHandler(new ValueChangeHandler<String>() { 641 @Override 642 public void onValueChange(ValueChangeEvent<String> event) { 643 ValueChangeEvent.fire(DateTimePickerBase.this, getValue()); 644 } 645 }); 646 return addHandler(dateValueChangeHandler, ValueChangeEvent.getType()); 647 } 648 649 /** {@inheritDoc} */ 650 @Override 651 public void setValue(final Date value) { 652 setValue(value, false); 653 } 654 655 /** {@inheritDoc} */ 656 @Override 657 public void setValue(final Date value, final boolean fireEvents) { 658 errorHandlerMixin.clearErrors(); 659 textBox.setValue(value != null ? dateTimeFormat.format(value) : null); 660 update(textBox.getElement()); 661 662 if (fireEvents) { 663 ValueChangeEvent.fire(DateTimePickerBase.this, value); 664 } 665 } 666 667 /** {@inheritDoc} */ 668 @Override 669 protected void onLoad() { 670 super.onLoad(); 671 configure(); 672 } 673 674 /** {@inheritDoc} */ 675 @Override 676 protected void onUnload() { 677 super.onUnload(); 678 remove(getElement()); 679 } 680 681 protected void configure() { 682 getElement().setAttribute("data-date-format", format); 683 684 // If configuring not for the first time, datetimepicker must be removed first. 685 this.remove(getElement()); 686 687 configure(getElement(), format, formatViewType.getValue(), weekStart.getValue(), toDaysOfWeekDisabledString(daysOfWeekDisabled), 688 autoClose, startView.getValue(), minView.getValue(), maxView.getValue(), showTodayButton, showClearButton, highlightToday, 689 keyboardNavigation, forceParse, minuteStep, viewSelect.getValue(), showMeridian, language.getCode(), position.getPosition()); 690 } 691 692 protected void execute(final String cmd) { 693 execute(getElement(), cmd); 694 } 695 696 private native void execute(Element e, String cmd) /*-{ 697 $wnd.jQuery(e).datetimepicker(cmd); 698 }-*/; 699 700 private native void remove(Element e) /*-{ 701 $wnd.jQuery(e).datetimepicker('remove'); 702 }-*/; 703 704 private native void show(Element e) /*-{ 705 $wnd.jQuery(e).datetimepicker('show'); 706 }-*/; 707 708 private native void hide(Element e) /*-{ 709 $wnd.jQuery(e).datetimepicker('hide'); 710 }-*/; 711 712 private native void update(Element e) /*-{ 713 $wnd.jQuery(e).datetimepicker('update'); 714 }-*/; 715 716 private native void setStartDate(Element e, String startDate) /*-{ 717 $wnd.jQuery(e).datetimepicker('setStartDate', startDate); 718 }-*/; 719 720 private native void setEndDate(Element e, String endDate) /*-{ 721 $wnd.jQuery(e).datetimepicker('setEndDate', endDate); 722 }-*/; 723 724 private native void setDaysOfWeekDisabled(Element e, String daysOfWeekDisabled) /*-{ 725 $wnd.jQuery(e).datetimepicker('setDaysOfWeekDisabled', daysOfWeekDisabled); 726 }-*/; 727 728 protected native void configure(Element e, String format, String formatViewType, int weekStart, 729 String daysOfWeekDisabled, boolean autoClose, int startView, int minView, int maxView, boolean todayBtn, boolean clearBtn, 730 boolean highlightToday, boolean keyboardNavigation, boolean forceParse, int minuteStep, int viewSelect, 731 boolean showMeridian, String language, String position) /*-{ 732 var that = this; 733 $wnd.jQuery(e).datetimepicker({ 734 format: format, 735 formatViewType: formatViewType, 736 language: language, 737 weekStart: weekStart, 738 daysOfWeekDisabled: daysOfWeekDisabled, 739 autoclose: autoClose, 740 startView: startView, 741 minView: minView, 742 maxView: maxView, 743 todayBtn: todayBtn, 744 clearBtn: clearBtn, 745 todayHighlight: highlightToday, 746 keyboardNavigation: keyboardNavigation, 747 forceParse: forceParse, 748 minuteStep: minuteStep, 749 showMeridian: showMeridian, 750 pickerPosition: position 751 }) 752 .on('show', function (e) { 753 that.@org.gwtbootstrap3.extras.datetimepicker.client.ui.base.DateTimePickerBase::onShow(Lcom/google/gwt/user/client/Event;)(e); 754 }) 755 .on("hide", function (e) { 756 that.@org.gwtbootstrap3.extras.datetimepicker.client.ui.base.DateTimePickerBase::onHide(Lcom/google/gwt/user/client/Event;)(e); 757 }) 758 .on("changeDate", function (e) { 759 that.@org.gwtbootstrap3.extras.datetimepicker.client.ui.base.DateTimePickerBase::onChangeDate(Lcom/google/gwt/user/client/Event;)(e); 760 }) 761 .on("changeYear", function (e) { 762 that.@org.gwtbootstrap3.extras.datetimepicker.client.ui.base.DateTimePickerBase::onChangeYear(Lcom/google/gwt/user/client/Event;)(e); 763 }) 764 .on("changeMonth", function (e) { 765 that.@org.gwtbootstrap3.extras.datetimepicker.client.ui.base.DateTimePickerBase::onChangeMonth(Lcom/google/gwt/user/client/Event;)(e); 766 }) 767 .on("outOfRange", function (e) { 768 that.@org.gwtbootstrap3.extras.datetimepicker.client.ui.base.DateTimePickerBase::onOutOfRange(Lcom/google/gwt/user/client/Event;)(e); 769 }); 770 }-*/; 771 772 protected String toDaysOfWeekDisabledString(final DateTimePickerDayOfWeek... dateTimePickerDayOfWeeks) { 773 this.daysOfWeekDisabled = dateTimePickerDayOfWeeks; 774 775 final StringBuilder builder = new StringBuilder(); 776 777 if (dateTimePickerDayOfWeeks != null) { 778 int i = 0; 779 for (final DateTimePickerDayOfWeek dayOfWeek : dateTimePickerDayOfWeeks) { 780 builder.append(dayOfWeek.getValue()); 781 782 i++; 783 if (i < dateTimePickerDayOfWeeks.length) { 784 builder.append(","); 785 } 786 } 787 } 788 return builder.toString(); 789 } 790 791 /** {@inheritDoc} */ 792 @Override 793 public com.google.web.bindery.event.shared.HandlerRegistration addValidationChangedHandler(ValidationChangedHandler handler) { 794 return validatorMixin.addValidationChangedHandler(handler); 795 } 796 797 /** {@inheritDoc} */ 798 @Override 799 public boolean getAllowBlank() { 800 return validatorMixin.getAllowBlank(); 801 } 802 803 /** {@inheritDoc} */ 804 @Override 805 public void setAllowBlank(boolean allowBlank) { 806 validatorMixin.setAllowBlank(allowBlank); 807 } 808 809 /** {@inheritDoc} */ 810 @Override 811 public void addValidator(Validator<Date> validator) { 812 validatorMixin.addValidator(validator); 813 } 814 815 /** {@inheritDoc} */ 816 @Override 817 public boolean getValidateOnBlur() { 818 return validatorMixin.getValidateOnBlur(); 819 } 820 821 /** {@inheritDoc} */ 822 @Override 823 public boolean removeValidator(Validator<Date> validator) { 824 return validatorMixin.removeValidator(validator); 825 } 826 827 /** {@inheritDoc} */ 828 @Override 829 public void reset() { 830 validatorMixin.reset(); 831 } 832 833 /** {@inheritDoc} */ 834 @Override 835 public void setValidateOnBlur(boolean validateOnBlur) { 836 validatorMixin.setValidateOnBlur(validateOnBlur); 837 } 838 839 /** {@inheritDoc} */ 840 @Override 841 public void setValidators(@SuppressWarnings("unchecked") Validator<Date>... validators) { 842 validatorMixin.setValidators(validators); 843 } 844 845 /** {@inheritDoc} */ 846 @Override 847 public boolean validate() { 848 return validatorMixin.validate(); 849 } 850 851 /** {@inheritDoc} */ 852 @Override 853 public boolean validate(boolean show) { 854 return validatorMixin.validate(show); 855 } 856 857 /** {@inheritDoc} */ 858 @Override 859 public ErrorHandler getErrorHandler() { 860 return errorHandlerMixin.getErrorHandler(); 861 } 862 863 /** {@inheritDoc} */ 864 @Override 865 public void setErrorHandler(ErrorHandler errorHandler) { 866 errorHandlerMixin.setErrorHandler(errorHandler); 867 validatorMixin.setErrorHandler(errorHandler); 868 } 869 870 /** {@inheritDoc} */ 871 @Override 872 public ErrorHandlerType getErrorHandlerType() { 873 return errorHandlerMixin.getErrorHandlerType(); 874 } 875 876 /** {@inheritDoc} */ 877 @Override 878 public void setErrorHandlerType(ErrorHandlerType errorHandlerType) { 879 errorHandlerMixin.setErrorHandlerType(errorHandlerType); 880 } 881 882 /** {@inheritDoc} */ 883 @Override 884 public void showErrors(List<EditorError> errors) { 885 errorHandlerMixin.showErrors(errors); 886 } 887 888}