001/*
002 *  Copyright 2012 GWT-Bootstrap
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.github.gwtbootstrap.datepicker.client.ui.base;
017
018import com.github.gwtbootstrap.client.ui.TextBox;
019import com.github.gwtbootstrap.client.ui.base.HasAlternateSize;
020import com.github.gwtbootstrap.client.ui.base.HasId;
021import com.github.gwtbootstrap.client.ui.base.HasPlaceholder;
022import com.github.gwtbootstrap.client.ui.base.HasSize;
023import com.github.gwtbootstrap.client.ui.base.HasStyle;
024import com.github.gwtbootstrap.client.ui.base.HasVisibility;
025import com.github.gwtbootstrap.client.ui.event.HasVisibleHandlers;
026import com.github.gwtbootstrap.client.ui.base.IsResponsive;
027import com.github.gwtbootstrap.client.ui.base.IsSearchQuery;
028import com.github.gwtbootstrap.client.ui.base.PlaceholderHelper;
029import com.github.gwtbootstrap.client.ui.base.ResponsiveHelper;
030import com.github.gwtbootstrap.client.ui.base.SearchQueryStyleHelper;
031import com.github.gwtbootstrap.client.ui.base.SizeHelper;
032import com.github.gwtbootstrap.client.ui.base.Style;
033import com.github.gwtbootstrap.client.ui.base.StyleHelper;
034import com.github.gwtbootstrap.client.ui.constants.AlternateSize;
035import com.github.gwtbootstrap.client.ui.constants.Device;
036import com.github.gwtbootstrap.client.ui.event.HiddenHandler;
037import com.github.gwtbootstrap.client.ui.event.HideEvent;
038import com.github.gwtbootstrap.client.ui.event.HideHandler;
039import com.github.gwtbootstrap.client.ui.event.ShowEvent;
040import com.github.gwtbootstrap.client.ui.event.ShowHandler;
041import com.github.gwtbootstrap.client.ui.event.ShownHandler;
042import com.github.gwtbootstrap.datepicker.client.ui.util.LocaleUtil;
043import com.google.gwt.core.client.GWT;
044import com.google.gwt.dom.client.Element;
045import com.google.gwt.editor.client.IsEditor;
046import com.google.gwt.editor.client.adapters.TakesValueEditor;
047import com.google.gwt.event.dom.client.ChangeEvent;
048import com.google.gwt.event.dom.client.ChangeHandler;
049import com.google.gwt.event.dom.client.HasChangeHandlers;
050import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
051import com.google.gwt.event.logical.shared.ValueChangeEvent;
052import com.google.gwt.event.logical.shared.ValueChangeHandler;
053import com.google.gwt.event.shared.HandlerRegistration;
054import com.google.gwt.i18n.client.DateTimeFormat;
055import com.google.gwt.i18n.client.LocaleInfo;
056import com.google.gwt.user.client.Event;
057import com.google.gwt.user.client.ui.HasEnabled;
058import com.google.gwt.user.client.ui.HasName;
059import com.google.gwt.user.client.ui.HasValue;
060import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
061import com.google.gwt.user.client.ui.Widget;
062
063import java.util.Date;
064
065/**
066 * Base DatePicker component.
067 *
068 * @author Carlos Alexandro Becker
069 * @author ohashi keisuke
070 * @since 2.0.4.0
071 */
072public class DateBoxBase extends Widget implements HasValue<Date>,HasEnabled, HasValueChangeHandlers<Date>, HasVisibility,
073        HasChangeHandlers, HasVisibleHandlers, HasAllDatePickerHandlers, IsEditor<TakesValueEditor<Date>>, HasPlaceholder, HasAlternateSize, IsSearchQuery, HasSize, HasId, IsResponsive , HasStyle, HasName {
074
075    private final TextBox box;
076    private String format;
077    private String language;
078    private DateTimeFormat dtf;
079    private TakesValueEditor<Date> editor;
080
081    /** placeholderHelper */
082    private PlaceholderHelper placeholderHelper = GWT.create(PlaceholderHelper.class);
083    private boolean autoclose = false;
084
085    public DateBoxBase() {
086        this.box = new TextBox();
087        this.language = LocaleUtil.getLanguage();
088        setElement(box.getElement());
089        setFormat(DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT).getPattern().toLowerCase());
090        setWeekStart(LocaleInfo.getCurrentLocale().getDateTimeFormatInfo().firstDayOfTheWeek());
091        setValue(new Date());
092    }
093
094    public void setAlignment(TextAlignment align) {
095        box.setAlignment(align);
096    }
097
098    /**
099     * @see com.google.gwt.user.client.ui.ValueBoxBase#isReadOnly()
100     */
101    public boolean isReadOnly() {
102        return box.isReadOnly();
103    }
104
105    /**
106     * @see com.google.gwt.user.client.ui.ValueBoxBase#setReadOnly(boolean)
107     */
108    public void setReadOnly(boolean readonly) {
109        box.setReadOnly(readonly);
110    }
111
112    /**
113     * {@inheritDoc}
114     */
115    @Override
116    public void setFormat(String format) {
117        this.format = format;
118        Date oldValue = getValue();
119        this.dtf = DateTimeFormat.getFormat(format.replaceAll("mm", "MM"));
120        if (oldValue != null) {
121            setValue(oldValue);
122        }
123    }
124
125    public void setLanguage(String language) {
126        this.language = language;
127        LocaleUtil.forceLocale(language);
128    }
129
130    /**
131     * Returns the internal instance of textbox element. Use only if know what you are doing.
132     *
133     * @return internal textbox intance.
134     */
135    protected TextBox getBox() {
136        return box;
137    }
138
139    /**
140     * {@inheritDoc}
141     */
142    @Override
143    public Date getValue() {
144        try {
145            return dtf != null && box.getValue() != null ? dtf.parse(box.getValue()) : null;
146        } catch(Exception e) {
147            return null;
148        }
149    }
150
151    /**
152     * Get un-tranceform text
153     * @return text box value
154     */
155    public String getOriginalValue() {
156        return box.getValue();
157    }
158
159    /**
160     * {@inheritDoc}
161     */
162    @Override
163    public void setValue(Date value) {
164        setValue(value, false);
165    }
166
167    /**
168     * {@inheritDoc}
169     */
170    @Override
171    public void setValue(Date value, boolean fireEvents) {
172        box.setValue(value != null ? dtf.format(value) : null);
173
174        updateValue(box.getElement());
175
176        if (fireEvents) {
177            ValueChangeEvent.fire(this, value);
178        }
179    }
180
181    protected native void updateValue(Element e)/*-{
182        if($wnd.jQuery(e).data('datepicker')) {
183            $wnd.jQuery(e).data('datepicker').update();
184        }
185    }-*/;
186
187    /**
188     * {@inheritDoc}
189     */
190    @Override
191    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Date> dateValueChangeHandler) {
192        return addHandler(dateValueChangeHandler, ValueChangeEvent.getType());
193    }
194
195    /**
196     * {@inheritDoc}
197     */
198    @Override
199    protected void onLoad() {
200        super.onLoad();
201        configure();
202    }
203
204    @Override
205    protected void onUnload() {
206        super.onUnload();
207        execute("remove");
208    }
209
210    /**
211     * Configure the elements for a specific widget.
212     * Use only if you know what you are doing.
213     *
214     * @param w: the widget to configure.
215     */
216    protected void configure(Widget w) {
217        w.getElement().setAttribute("data-date-format", format);
218        w.getElement().setAttribute("data-date-language", language);
219        configure(w.getElement(), autoclose);
220    }
221
222    /**
223     * dateChange event handler.
224     */
225    public void onChange() {
226        ValueChangeEvent.fire(this, getValue());
227    }
228
229    public void onShow(Event e) {
230        fireEvent(new ShowEvent(e));
231    }
232
233    public void onHide(Event e) {
234        fireEvent(new HideEvent(e));
235    }
236    public void reconfigure() {
237        removeDataIfExists(getElement());
238        configure();
239    }
240
241    /**
242     * configure this datepicker.
243     */
244    protected void configure() {
245        configure(this);
246    }
247
248    protected native void removeDataIfExists(Element e) /*-{
249        var $that = $wnd.jQuery(e);
250        if($that.data('datepicker')) {
251            console.log($that.data());
252            $that.removeData('dateFormat');
253            $that.removeData('dateLanguage');
254            $that.removeData('dateWeekstart');
255            $that.removeData('dateStartdate');
256            $that.removeData('dateEnddate');
257            $that.removeData('dateStartView');
258            $that.removeData('datepicker');
259            $that.off();
260        }
261    }-*/;
262
263    /**
264     * call jquery datepicker plugin in a element.
265     *
266     * @param e: Element that will be transformed in a datepicker.
267     * @param autoclose  is autoclose?
268     */
269    protected native void configure(Element e, boolean autoclose) /*-{
270        var that = this;
271        $wnd.jQuery(e).datepicker({autoclose : autoclose})
272        .on('change' , function() {
273            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onChange()();
274        })
275        .on("show", function (e) {
276            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onShow(Lcom/google/gwt/user/client/Event;)(e);
277        })
278        .on("hide", function (e) {
279            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onHide(Lcom/google/gwt/user/client/Event;)(e);
280        });
281    }-*/;
282
283    private native void execute(Element e, String cmd) /*-{
284        $wnd.jQuery(e).datepicker(cmd);
285    }-*/;
286
287    private void execute(String cmd) {
288        execute(getElement(), cmd);
289    }
290
291    /**
292     * {@inheritDoc}
293     */
294    @Override
295    public void show() {
296        execute("show");
297    }
298
299    /**
300     * {@inheritDoc}
301     */
302    @Override
303    public void hide() {
304        execute("hide");
305    }
306
307    /**
308     * {@inheritDoc}
309     */
310    @Override
311    public void toggle() {
312        //TODO 2012/06/21 ohashi keisuke shoud be support
313        throw new UnsupportedOperationException("not support toggle");
314    }
315
316    /**
317     * {@inheritDoc}
318     */
319    @Override
320    public HandlerRegistration addHideHandler(HideHandler handler) {
321        return addHandler(handler, HideEvent.getType());
322    }
323
324    /**
325     * {@inheritDoc}
326     */
327    @Override
328    public HandlerRegistration addHiddenHandler(HiddenHandler handler) {
329        //TODO 2012/06/21 ohashi keisuke shoud be support
330        throw new UnsupportedOperationException("not support hidden event");
331    }
332
333    /**
334     * {@inheritDoc}
335     */
336    @Override
337    public HandlerRegistration addShowHandler(ShowHandler handler) {
338        return addHandler(handler, ShowEvent.getType());
339    }
340
341    /**
342     * {@inheritDoc}
343     */
344    @Override
345    public HandlerRegistration addShownHandler(ShownHandler handler) {
346        //TODO 2012/06/21 ohashi keisuke shoud be support
347        throw new UnsupportedOperationException("not support shown event");
348    }
349
350    /**
351     * {@inheritDoc}
352     */
353    @Override
354    public void setWeekStart(int start) {
355        getElement().setAttribute("data-date-weekstart", start + "");
356    }
357
358    /**
359     * {@inheritDoc}
360     */
361    @Override
362    public void setStartDate(String startDate) {
363        getElement().setAttribute("data-date-startdate", startDate);
364    }
365
366    /**
367     * {@inheritDoc}
368     */
369    @Override
370    public void setStartDate_(Date startDate) {
371        setStartDate(dtf.format(startDate));
372    }
373
374
375    /**
376     * {@inheritDoc}
377     */
378    @Override
379    public void setEndDate(String endDate) {
380        getElement().setAttribute("data-date-enddate", endDate);
381    }
382
383    /**
384     * {@inheritDoc}
385     */
386    @Override
387    public void setEndDate_(Date endDate) {
388        setEndDate(dtf.format(endDate));
389    }
390
391    /**
392     * {@inheritDoc}
393     */
394    @Override
395    public void setAutoClose(boolean autoclose) {
396        this.autoclose = autoclose;
397    }
398
399    /**
400     * {@inheritDoc}
401     */
402    @Override
403    public void setStartView(ViewMode mode) {
404        setStartView(mode.name());
405    }
406
407    /**
408     * {@inheritDoc}
409     */
410    @Override
411    public void setStartView(String mode) {
412        getElement().setAttribute("data-date-start-view", mode.toLowerCase());
413    }
414
415        /**
416         * Retuen Editor
417         * @return editor
418         */
419        @Override
420        public TakesValueEditor<Date> asEditor() {
421                if(editor == null){
422                        editor = TakesValueEditor.of(this);
423                }
424                return editor;
425        }
426
427    @Override
428    public HandlerRegistration addChangeHandler(ChangeHandler handler) {
429        return addHandler(handler, ChangeEvent.getType());
430    }
431
432    /**
433     * {@inheritDoc}
434     */
435    @Override
436    public void setPlaceholder(String placeholder) {
437        placeholderHelper.setPlaceholer(getElement(), placeholder);
438    }
439
440    /**
441     * {@inheritDoc}
442     */
443    @Override
444    public String getPlaceholder() {
445        return placeholderHelper.getPlaceholder(getElement());
446    }
447
448    /**
449     * {@inheritDoc}
450     */
451    @Override
452    public void setSearchQuery(boolean searchQuery) {
453        SearchQueryStyleHelper.setSearchQuery(this, searchQuery);
454    }
455
456    /**
457     * {@inheritDoc}
458     */
459    @Override
460    public boolean isSearchQuery() {
461        return SearchQueryStyleHelper.isSearchQuery(this);
462    }
463
464    /**
465     * {@inheritDoc}
466     */
467    @Override
468    public void setAlternateSize(AlternateSize size) {
469        StyleHelper.changeStyle(this, size, AlternateSize.class);
470    }
471
472    /**
473     * {@inheritDoc}
474     */
475    @Override
476    public void setSize(int size) {
477        SizeHelper.setSize(this, size);
478    }
479
480    /**
481     * {@inheritDoc}
482     */
483    @Override
484    public String getId() {
485        return getElement().getId();
486    }
487
488    /**
489     * {@inheritDoc}
490     */
491    @Override
492    public void setId(String id) {
493        getElement().setId(id);
494    }
495
496    /**
497     * {@inheritDoc}
498     */
499    @Override
500    public void setShowOn(Device device) {
501        ResponsiveHelper.setShowOn(this, device);
502    }
503
504    /**
505     * {@inheritDoc}
506     */
507    @Override
508    public void setHideOn(Device device) {
509        ResponsiveHelper.setHideOn(this, device);
510
511    }
512
513    /**
514     * {@inheritDoc}
515     */
516    @Override
517    public void setStyle(Style style) {
518        StyleHelper.setStyle(this, style);
519    }
520
521    /**
522     * {@inheritDoc}
523     */
524    @Override
525    public void addStyle(Style style) {
526        StyleHelper.addStyle(this, style);
527    }
528
529    /**
530     * {@inheritDoc}
531     */
532    @Override
533    public void removeStyle(Style style) {
534        StyleHelper.removeStyle(this, style);
535
536    }
537
538    /**
539     * {@inheritDoc}
540     */
541    @Override
542    public boolean isEnabled() {
543        return false;
544    }
545
546    /**
547     * {@inheritDoc}
548     */
549    @Override
550    public void setEnabled(boolean enabled) {
551        box.setEnabled(enabled);
552    }
553
554    /**
555     * {@inheritDoc}
556     */
557        @Override
558        public void setName(String name) {
559                box.setName(name);
560        }
561
562         /**
563     * {@inheritDoc} 
564     */
565        @Override
566        public String getName() {
567                return box.getName();
568        }
569}