You are not logged in.

[WCF 1.1.x] Datumsabfrage

1

Monday, July 16th 2012, 7:58am

Datumsabfrage

Hallo zusammen,

ich wollte gerne ein Datum abfragen innerhalb meines Formulars. Habe hier schon einen Beitrag gefunden, in welchem gestanden hat, dass ich einfach ein "Date-Feld" als Input nehmen soll - mit nichten.
Jetzt wollte ich mir der WCF-Datumseingabe (Siehe Benutzer-Editor, etc.) bedienen. Leider finde ich nirgends die Lösung, wie es Woltlab gemacht hat, oder muss ich die Lösung ohnehin selbst implementieren? Könntet ihr mir bitte weiterhelfen?

Vielen Dank!

Liebe Grüße
Dominik
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

0xLeon

Member

  • "0xLeon" is male

Posts: 710

Location: Furtwangen

Occupation: Student (Medieninformatik)

  • Send private message

2

Monday, July 16th 2012, 9:42am

Am einfachsten wäre da wohl der Inline Calender. Nur die Klasse einbinden, statische Methode der Klasse für die Template Variablen aufrufen, Template inkludieren und dann im Formular die Parameter verarbeiten. Genauer kann ich 's grad nich erklären, hab auf 'm Smartphone leider kein WCF. Aber das is jedenfalls das nötigste.
Meine Pakete
Invitation System – Plugin StoreGithub
Update Files Delete PIP – Plugin StoreGithub
Kein Support via PN oder E-Mail.

3

Monday, July 16th 2012, 10:54am

Okay, danke.
Hab schonmal PHP-seitig alles gefunden denke ich:

PHP Source code

1
require_once(WCF_DIR.'lib/page/util/InlineCalendar.class.php');
und

PHP Source code

1
InlineCalendar::assignVariables();

Hab mir in der Klasse angeschaut, was dort ungefähr gemacht wird und wollte mich durch die Woltlab-Templates durchforsten und danach suchen, welches Template includiert werden muss. Leider werde ich daraus nicht wirklich schlau :( (Hab mich am UserEditForm orientiert).
Deswegen hätte ich noch 4 Fragen:
  1. Wie heißt das Template, was includiert werden muss?
  2. Brauche ich template-seitig noch Textfelder/Felder irgendeiner Art, mit einem bestimmten Namen/ID?
  3. Kann ich auch mehrere dieser "Kalender" auf einer Seite einbinden?
  4. Wie kann ich die Datumsanzeige mit einem von PHP vorgegebenen Datum vorbelegen (z.B. aus der DB)?
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

This post has been edited 1 times, last edit by "dominik4545" (Jul 16th 2012, 11:06am)


0xLeon

Member

  • "0xLeon" is male

Posts: 710

Location: Furtwangen

Occupation: Student (Medieninformatik)

  • Send private message

4

Tuesday, July 17th 2012, 9:07pm

Okay, vergiss das mit Template inkludieren. Hatte irgendwie im Kopf, da gäbe es einfach ein Template, was eingebunden werden muss.
Im head-Tag muss die JavaScript-Klassendatei wcf/js/Calender.class.js eingebunden werden. Dann noch im head-Tag eine Instanz von Calender erzeugen, die drei Parameter für den Constructor stellt die InlineCalender-Klasse der Template-Engine zur Verfügung.

Im Formular musst du dann für jedes Element der Zeitangabe ein Eingabefeld erstellen, also für Tag, Monat, Jahr, Stunde und Minute. Brauchst du z.B. keine genaue Uhrzeit, die Felder einfach nicht einbauen. name und id-Attribut der Elemente bekommen einen Prefix, der bei allen Elementen gleich ist und dann eben noch eine Angabe, was das Feld annimmt. Also z.B. fooDay für den Tag und fooMonth für den Monat. Die Auswahlmöglichkeiten werden jetzt über die Template-Funktion htmlOptions ausgegeben. Hier kannst du auch einen Wert vorauswählen lassen. Nur beim Jahr brauchst du das nicht.

Jetzt fehlt noch der DropDown-Kalender. Das erklären wäre zu kompliziert, etwas Code erklärt das besser:

HTML

1
2
<a id="fooButton"><img src="{icon}datePickerOptionsM.png{/icon}" alt="" /></a>
<div id="fooCalendar" class="inlineCalendar"></div>

Um damit jetzt einen funktionierenden InlineCalender zu bekommen, fehlt noch eine Zeile JavaScript-Code:

Javascript source code

1
calendar.init('foo');
Hier ist calender die im head-tag erzeugte Instanze von Calender.

Der Rest in der PHP-Klasse deines Formulars ist einfach verarbeiten von Parametern. Um einen Timestamp zu erhalten, am besten die Funktion gmmktime verwenden.
Meine Pakete
Invitation System – Plugin StoreGithub
Update Files Delete PIP – Plugin StoreGithub
Kein Support via PN oder E-Mail.

5

Wednesday, July 18th 2012, 1:47pm

Danke für die hilfreiche Antwort!
Jetzt hab ich nur noch 2 klitzekleine Fragen:
  1. Den Kalender könnte ich doch theoretisch zweimal auf ein und derselben Seite verwenden (müsste dann nur den Präfix ändern und dann ein neues "init" machen), oder?
  2. Ich habe mir mit gmmktime einen Timestamp (lt. Beschreibung) gemacht. Wie bekomme ich daraus ein "DateTime"-Objekt, oder ein Objekt, was ich in der DB in einem DateTime-Feld abspeichern kann? Über den Konstruktor von DateTime wirft er mir immer eine Exception :(


@Moderation: dieses Thema könnte man doch z.B. in einen Tutorial-Bereich verschieben, damit jeder, der InlineCalendar verwenden will, sieht, wie es funktioniert, oder? Fände ich super, wenn es einen solchen gäbe, dann könnte man vielleicht schneller und effektiver arbeiten. Werde das in einem Feedback-Thread noch einmal erwähnen :)

#edit:
Die Frage 2 hat sich erledigt. Ich hab das @ vergessen und es partou nicht gesehen, erst ein Kumpel hat mich drauf gebracht grade :(
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

This post has been edited 1 times, last edit by "dominik4545" (Jul 18th 2012, 2:05pm)


0xLeon

Member

  • "0xLeon" is male

Posts: 710

Location: Furtwangen

Occupation: Student (Medieninformatik)

  • Send private message

6

Wednesday, July 18th 2012, 2:53pm

Erste Frage hast du dir schon beantwortet. Ja, mehrere Kalender auf einer Seite sind möglich, funktioniert dann exakt so, wie du es vermutet hast.
Zur zweiten Frage wäre noch zu sagen, dass das WCF immer mit Timestamps arbeitet. Sowohl in der Datenbank, als auch im Programmcode. Aus Konsistenzgründen wäre es wohl am besten, die selbe Verarbeitung wie im WCF zu wählen.
Meine Pakete
Invitation System – Plugin StoreGithub
Update Files Delete PIP – Plugin StoreGithub
Kein Support via PN oder E-Mail.

7

Thursday, July 19th 2012, 9:12pm

Da hätte ich noch eine Frage am Rande:
Ich hab auf Deinen Rat hin die Variable TIME_NOW angezapft und den Timestamp verwendet. Warum ist es lt. der TIME_NOW-Umwandlung 19:10, wenn es 21:10 ist? Habe ich da irgendetwas falsch gemacht?
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

nmichel

Member

Posts: 499

Occupation: Bitschieber

  • Send private message

8

Thursday, July 19th 2012, 9:24pm

19:10 (GMT) = 21:10 (localtime Berlin) - 1h (Zeitzone Berlin...) - 1h (Sommerzeit)
Der Kopf ist rund, damit das Denken die Richtung wechseln kann (Francis Picabia)

9

Thursday, July 19th 2012, 9:32pm

Das heißt, dass ich da 2 Stunden drauf rechnen muss? Ist ja doof. Vor allem, wenn ich das Plugin in ner anderen Zeitzone bereitstelle, müsste ich das ja anpassen. Gibt es da nicht eine "komfortablere" Lösung?
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

nmichel

Member

Posts: 499

Occupation: Bitschieber

  • Send private message

10

Thursday, July 19th 2012, 9:50pm

Quoted

Das heißt, dass ich da 2 Stunden drauf rechnen muss?
Während der Winterzeit nur eine Stunde ;)

Ich habe es bei mir mal so gemacht:

PHP Source code

1
2
3
4
5
6
7
8
        $this->timeNow TIME_NOW;
        $timeOffset 3600 TIMEZONE; 
        // check summer time status
        if (defined('ENABLE_DAYLIGHT_SAVING_TIME')) {
            if(ENABLE_DAYLIGHT_SAVING_TIME && @date('I'TIME_NOW+$timeOffset) == 1)    {
                $timeOffset += 3600;
            }
        }
Der Kopf ist rund, damit das Denken die Richtung wechseln kann (Francis Picabia)

Alexander Ebert

WoltLab Developer

  • "Alexander Ebert" is male

Posts: 4,773

Location: Berlin

  • Send private message

11

Thursday, July 19th 2012, 11:04pm

Alternativ kann man die Zeitzone des Servers richtig einstellen …
Alexander Ebert
Developer WoltLab® GmbH


12

Saturday, July 21st 2012, 6:36pm

Warum verwendet ihr nicht die Datumsfunktionen vom WCF?

13

Monday, July 23rd 2012, 10:09am


Warum verwendet ihr nicht die Datumsfunktionen vom WCF?

ich hab damit gerechnet, dass die TIME_NOW schon die richtige Zeit beinhaltet ^^
Was gäbe es denn WCF-seitig an Möglichkeiten?


Alternativ kann man die Zeitzone des Servers richtig einstellen …

Die Zeit ist richtig eingestellt. Bei den Threads/Posts stimmt sie jedenfalls, nur eben bei Referenz auf TIME_NOW im Plugin nicht, deswegen die Frage
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

0xLeon

Member

  • "0xLeon" is male

Posts: 710

Location: Furtwangen

Occupation: Student (Medieninformatik)

  • Send private message

14

Monday, July 23rd 2012, 11:34am

Doch, die Angabe in TIME_NOW stimmt schon. Timestamps sind per Definition auf UTC bezogen. Timestamps kennen also keine Zeitzonen, das würde nämlich erfordern, zu jedem Timestamp auch die Zeitzone zu speichern, zu welcher der Timestamp gehört. Und das würde die Geschichte nur unnötig verkomplizieren. Die Zeitzone muss nur bei der Ausgabe berücksichtigt werden. Benutzt man für die Ausgabe einer Zeit den Template Modifier date bzw. time, welcher wiederum DateUtil::formatDate() bzw. DateUtil::formatTime() verwendet, kümmt sich das WCF automatisch darum, dass die Uhrzeit passend zur Zeitzone des Users angezeigt wird.
Meine Pakete
Invitation System – Plugin StoreGithub
Update Files Delete PIP – Plugin StoreGithub
Kein Support via PN oder E-Mail.

15

Monday, July 23rd 2012, 11:37am

Okay, vielen Dank :)
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

16

Wednesday, August 1st 2012, 10:59am

Moin Moin,

ich möchte das Thema nochmal aufgreifen...

Ich brauche im Prinzip ein Formular, in dem ein Datum eingestellt werden kann.
(siehe Anhang)
und einen Absendebutton.

Aus dem eingestellten Datum soll dann ein timestamp generiert werde, um ihn dann in die DB zu schreiben.

Vom Prinzip klingt auch alles einleuchtend, komme aber nicht weiter.
Habe mir diverse Klassen/Templates wo solche Felder vorhanden sind angeschaut
(SearchForm, CalendarEventAdd usw),
aber bekomme es nicht so umgesetzt, wie es gerne hätte.

Wer kann mir noch Hilfestellung geben?

In der meiner Klasse habe ich stehen:

Source code

1
2
require_once(WCF_DIR.'lib/form/AbstractForm.class.php');
require_once(WCF_DIR.'lib/page/util/InlineCalendar.class.php');


Das Template sieht so aus:

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{include file="documentHeader"}
<head>
	<title>{lang}wcf.cashman.title{/lang} - {PAGE_TITLE}</title>
	
	{include file='headInclude' sandbox=false}

	<script src="{@RELATIVE_WCF_DIR}js/Calendar.class.js" type="text/javascript"></script>	
	<script type="text/javascript">
		//<![CDATA[
		var calendar = new Calendar('{$monthList}', '{$weekdayList}', {@$startOfWeek});
		//]]>
	</script>
</head>
<body{if $templateName|isset} id="tpl{$templateName|ucfirst}"{/if}>
{include file='header' sandbox=false}

<div id="main">
<form enctype="multipart/form-data" method="post" action="index.php?form=CashmanCreateNewEvent">	
		<div class="border content">                      	
			<div class="container-1">
				<fieldset>
				<legend>{lang}wcf.cashman.dateselect.newevent{/lang}</legend>
				
				<div class="floatedElement floatedElementContainer">
					<div class="floatedElement">
						<label for="fromDay">{lang}wcf.global.date.day{/lang}</label>
						{htmlOptions options=$dayOptions selected=$eventDate->day id=fromDay name=fromDay}
					</div>
					
					<div class="floatedElement">
						<label for="fromMonth">{lang}wcf.global.date.month{/lang}</label>
						{htmlOptions options=$monthOptions selected=$eventDate->month id=fromMonth name=fromMonth}
					</div>
					
					<div class="floatedElement">
						<label for="fromYear">{lang}wcf.global.date.year{/lang}</label>
						<input id="fromYear" class="inputText fourDigitInput" type="text" name="fromYear" value="{@$eventDate->fromYear}" maxlength="4" />
					</div>
				
					<div class="floatedElement">
						<a id="fromButton"><img src="{icon}datePickerOptionsM.png{/icon}" alt="" /></a>
						<div id="newEvent" class="inlineCalendar"></div>
					<script type="text/javascript">
						//<![CDATA[
						calendar.init('from');
						//]]>
					</script>	
					</div>
				
				
				
				</fieldset>
			</div>
		</div>
		<div class="formSubmit">
			<input accesskey="s" type="submit" value="{lang}wcf.global.button.submit{/lang}" />
		</div>
	</form>
</div>

{include file='footer' sandbox=false}

</body>
</html>		
		
Noisemaker has attached the following image:
  • date.PNG
When nothing goes right..... go left! 8)

17

Wednesday, August 1st 2012, 11:18am

Hey,

ich sehe Deinen Fehler leider gerade nicht.
Kann Dir nur mal mein Template zeigen.
Einmal hier der Import:

HTML

1
2
3
4
5
6
7
{* import calendar *}
<script src="{@RELATIVE_WCF_DIR}js/Calendar.class.js" type="text/javascript"></script>
<script type="text/javascript">
	//<![CDATA[
	var calendar = new Calendar('{$monthList}', '{$weekdayList}', {@$startOfWeek});
	//]]>
</script

und hier der Kalender selbst:

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<div class="formElement{if $errorField == 'resigned'} formError{/if}">
							<div class="formFieldLabel">
								<label for="resigned">{lang}net.auracher.guildmanagement.memberDetails.generalInformation.resigned{/lang}</label>
							</div>
							<div class="formField">
								<div class="floatedElement">
									<label for="resignedDay">{lang}wcf.global.date.day{/lang}</label>
									{htmlOptions options=$dayOptions selected=$resignedDay id=resignedDay name=resignedDay}
								</div>
								<div class="floatedElement">
									<label for="resignedMonth">{lang}wcf.global.date.month{/lang}</label>
									{htmlOptions options=$monthOptions selected=$resignedMonth id=resignedMonth name=resignedMonth}
								</div>
								<div class="floatedElement">
									<label for="resignedYear">{lang}wcf.global.date.year{/lang}</label>
									<input id="resignedYear" class="inputText fourDigitInput" type="text" name="resignedYear" value="{@$resignedYear}" maxlength="4" />
								</div>
								<div class="floatedElement">
									<a id="resignedButton"><img src="{icon}datePickerOptionsM.png{/icon}" alt="" /></a>
									<div id="resignedCalendar" class="inlineCalendar"></div>
									<script type="text/javascript">
										//<![CDATA[
											calendar.init('resigned');
										//]]>
									</script>
								</div>
							</div>
							{if $errorField == 'resigned'}
								{if $errorType == 'invalidDate'}<p class="innerError">{lang}net.auracher.guildmanagement.error.invalidDate{/lang}</p>{/if}
								{if $errorType == 'dateInFuture'}<p class="innerError">{lang}net.auracher.guildmanagement.error.dateInFuture{/lang}</p>{/if}
								{if $errorType == 'dateBeforeJoined'}<p class="innerError">{lang}net.auracher.guildmanagement.error.dateBeforeJoined{/lang}</p>{/if}
							{/if}
						</div>


Sowie in der Klasse:

PHP Source code

1
require_once(WCF_DIR.'lib/page/util/InlineCalendar.class.php');

und unter "assignVariables" folgendes:

PHP Source code

1
2
// assign calendar-variables
            InlineCalendar::assignVariables();


Diese Schritte waren mal dazu da, den Kalender darzustellen und initialisieren. Dann zum validieren folgendes:

PHP Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// validate resigned-date
                if(isset($_REQUEST['resignedDay']) && isset($_REQUEST['resignedMonth']) && isset($_REQUEST['resignedYear'])){
                    if(intval($_REQUEST['resignedDay']) > && intval($_REQUEST['resignedMonth']) > && intval($_REQUEST['resignedYear']) > 0){
                        try {
                            $d gmmktime(null,null,null,intval($_REQUEST['resignedMonth']),intval($_REQUEST['resignedDay']),intval($_REQUEST['resignedYear']));
                            $this->resigned = new DateTime("@$d");
                        } catch (Exception $e) {
                            $this->resigned null;
                            throw new UserInputException('resigned''invalidDate');
                        }

                        if($this->resigned != null){
                            if($this->resigned > new DateTime()){
                                throw new UserInputException('resigned''dateInFuture');
                            }
                        }

                    } else {
                        $this->resigned null;
                    }
                } else if(!isset($_REQUEST['resignedDay']) && !isset($_REQUEST['resignedMonth']) && !isset($_REQUEST['resignedYear'])){
                    $this->resigned null;
                } else {
                    throw new UserInputException('resigned''invalidDate');
                }


Vielleicht hilft Dir das bisschen weiter :)
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

18

Thursday, August 2nd 2012, 11:13am

Hiho,

es hat mir schon mal weiter geholfen.
Das Formular wird nun korrekt aufgerufen, Inline Calendar funktioniert und überträgt das Taum beim klicken in die Felder.

Es soll nun standardmäßig das aktuelle datum beim Aufruf in den Feldern stehen,
das muss ich per Javascript noch machen.

Es hapert aber beim speichern....

Deine Validierung habe ich für mich angepasst, aber beim Speichern gibts nen Error:

Source code

1
Object of class DateTime could not be converted to string


Ist DateTime() eine Funktion des Kalenders oder eine eigene?

Wie sieht denn Deine Klasse aus?

PHP Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * @see Form::validate()
 */
    public function validate() {
    
        parent::validate();    
        // validate date settings
        if(isset($_REQUEST['neweventDay']) && isset($_REQUEST['neweventMonth']) && isset($_REQUEST['neweventYear'])){
                if(intval($_REQUEST['neweventDay']) > && intval($_REQUEST['neweventMonth']) > && intval($_REQUEST['neweventYear']) > 0){
                try {
                    $d gmmktime(null,null,null,intval($_REQUEST['neweventMonth']),intval($_REQUEST['neweventDay']),intval($_REQUEST['neweventYear']));
                    $this->eventDate = new DateTime("@$d");
                } catch (Exception $e) {
                    $this->eventDate null;
                    throw new UserInputException('newevent''invalidDate');
                }

                if($this->eventDate != null){
                    if($this->eventDate > new DateTime()){
                    throw new UserInputException('newevent''dateInFuture');
                    }
                }

                } else {
                $this->eventDate null;
                }
            } else if(!isset($_REQUEST['neweventDay']) && !isset($_REQUEST['neweventMonth']) && !isset($_REQUEST['neweventYear'])){
                $this->eventDate null;
            } else {
                throw new UserInputException('newevent''invalidDate');
            }
    }


Grüße Noisemaker
When nothing goes right..... go left! 8)

19

Thursday, August 2nd 2012, 11:26am

DateTime ist ein Typ (wie String). Um daraus ein Datum als String zu machen, kannst Du Dir das formatieren:

PHP Source code

1
$this->date->format('Y-m-d')

Wie Du es genau formatieren willst, liegt in Deinem Interesse. Folgende Möglichkeiten hast Du:

PHP Source code

1
$this->date->format('Y-m-d H:i:s'// "2012-08-02 11:22:23" purzelt als String raus. 

Das Ganze kannst dann als SQL-Statement verpacken:

PHP Source code

1
$query 'INSERT INTO `wcf'.WCF_N.'_tablexyz` (`m_joined`) VALUES (\''.$this->joined->format('Y-m-d').'\');';


Ein Tipp für Dich vielleicht noch: Das "dateInFuture" macht bei Dir wahrscheinlich keinen Sinn, weil Du Events planst. Da macht dann wahrscheinlich der Umkehrschluss Sinn: dateInPast ;)
ich werfe niemandem etwas vor, höchstens hinterher :whistling:

20

Thursday, August 2nd 2012, 11:44am

Danke für die schnelle Antwort.

Ich schau mir das nachher an, muss gleich los zur Arbeit ^^

dateInFuture macht schon Sinn, weil man nur Events für den heutigen Tag oder für vergangene Tage eintragen können soll.

Event = Veranstaltung

Ich mache damit die Abrechnung eines Gastrobetriebes, damit man auch Daten nachträglich eintragen kann, brauche ich heute oder älter.
Also ist das schon richtig, wie es jetzt ist.

Um nochmal auf DateTime zurückzukommen...

Ich brauche eigentlich keinen String, sondern aus dem eingestellten Datum soll ein timestamp int(10) rauskommen,
welcher als neue Zeile in die Tabelle _events geschrieben wird und dann kommt die neue eventID (insertID) zurück.
When nothing goes right..... go left! 8)

Similar threads