source: trunk/HtmlClasses.pas

Last change on this file was 32, checked in by chronos, 6 months ago
  • Modified: Removed U prefix from units names.
  • Modified: Use TFormEx for all forms.
File size: 17.0 KB
Line 
1unit HtmlClasses;
2
3interface
4
5uses
6 XmlClasses, Classes, SysUtils, Generics.Collections, Generics, IpAddress;
7
8type
9 { TURL }
10
11 TURL = class(TPersistent)
12 private
13 function GetAsString: string;
14 procedure SetAsString(Value: string);
15 public
16 Scheme: string;
17 UserName: string;
18 Password: string;
19 Host: THostAddress;
20 Port: Word;
21 Path: string;
22 Query: string;
23 Fragment: string;
24 constructor Create;
25 destructor Destroy; override;
26 property AsString: string read GetAsString write SetAsString;
27 end;
28
29 { THtmlElement }
30
31 THtmlElement = class
32 protected
33 function GetAsXmlElement: TXmlElement; virtual;
34 public
35 Id: string;
36 Name: string;
37 ClassId: string;
38 Style: string;
39 procedure Assign(Source: THtmlElement); virtual;
40 property AsXmlElement: TXmlElement read GetAsXmlElement;
41 end;
42
43 THtmlString = class;
44 THtmlBlock = class;
45 THtmlList = class;
46 THtmlInput = class;
47
48 { THtmlElements }
49
50 THtmlElements = class(TObjectList<THtmlElement>)
51 function AddString(Text: string = ''): THtmlString;
52 function AddBlock: THtmlBlock;
53 function AddList: THtmlList;
54 function AddInput: THtmlInput;
55 end;
56
57 TBlockType = (btNoTag, btBlockLevel, btInline);
58
59 { THtmlString }
60
61 THtmlString = class(THtmlElement)
62 protected
63 function GetAsXmlElement: TXmlElement; override;
64 public
65 Text: string;
66 procedure Assign(Source: THtmlElement); override;
67 end;
68
69 { THtmlLineBreak }
70
71 THtmlLineBreak = class(THtmlElement)
72 protected
73 function GetAsXmlElement: TXmlElement; override;
74 public
75 constructor Create;
76 end;
77
78 THtmlBlock = class(THtmlElement)
79 protected
80 function GetAsXmlElement: TXmlElement; override;
81 public
82 BlockType: TBlockType;
83 SubItems: THtmlElements;
84 constructor Create;
85 destructor Destroy; override;
86 end;
87
88 TListType = (ltUnordered, ltOrdered);
89
90 { THtmlList }
91
92 THtmlList = class(THtmlElement)
93 protected
94 function GetAsXmlElement: TXmlElement; override;
95 public
96 ListType: TListType;
97 SubItems: THtmlElements;
98 constructor Create;
99 destructor Destroy; override;
100 end;
101
102 THtmlLink = class(THtmlElement)
103 protected
104 function GetAsXmlElement: TXmlElement; override;
105 public
106 Target: TURL;
107 Content: THtmlElement;
108 constructor Create;
109 destructor Destroy; override;
110 end;
111
112 TSizeUnits = (suPixels, suPercents);
113
114 THtmlSize = record
115 Width: Integer;
116 Height: Integer;
117 Units: TSizeUnits;
118 end;
119
120 THtmlImage = class(THtmlElement)
121 protected
122 function GetAsXmlElement: TXmlElement; override;
123 public
124 Size: THtmlSize;
125 Source: TURL;
126 AlternateText: string;
127 constructor Create;
128 destructor Destroy; override;
129 end;
130
131 THtmlInputType = (itText, itComboBox, itRadioButton, itReset, itPassword,
132 itSubmit, itHidden, itFileSelect, itButton, itCheckBox);
133
134 { THtmlInput }
135
136 THtmlInput = class(THtmlElement)
137 protected
138 function GetAsXmlElement: TXmlElement; override;
139 public
140 InputType: THtmlInputType;
141 Value: Variant;
142 ItemName: string;
143 procedure Assign(Source: THtmlElement); override;
144 constructor Create;
145 destructor Destroy; override;
146 end;
147
148 { THtmlForm }
149
150 THtmlForm = class(THtmlBlock)
151 protected
152 function GetAsXmlElement: TXmlElement; override;
153 public
154 Method: string;
155 Action: TURL;
156 constructor Create;
157 destructor Destroy; override;
158 end;
159
160 THtmlDocument = class
161 private
162 function GetAsXmlDocument: TXmlDocument;
163 public
164 Title: string;
165 ContentEncoding: string;
166 ContentLanguage: string;
167 Body: THtmlBlock;
168 Styles: TStringList;
169 Scripts: TStringList;
170 property AsXmlDocument: TXmlDocument read GetAsXmlDocument;
171 constructor Create;
172 destructor Destroy; override;
173 end;
174
175 { THtmlCell }
176
177 THtmlCell = class(THtmlElement)
178 protected
179 function GetAsXmlElement: TXmlElement; override;
180 public
181 RowSpan: Integer;
182 ColSpan: Integer;
183 Value: THtmlElement;
184 constructor Create;
185 destructor Destroy; override;
186 end;
187
188 { THtmlCells }
189
190 THtmlCells = class(TObjectList<THtmlCell>)
191 function AddCell: THtmlCell;
192 end;
193
194 { THtmlRow }
195
196 THtmlRow = class(THtmlElement)
197 protected
198 function GetAsXmlElement: TXmlElement; override;
199 public
200 Cells: THtmlCells;
201 constructor Create;
202 destructor Destroy; override;
203 end;
204
205 { THtmlRows }
206
207 THtmlRows = class(TObjectList<THtmlRow>)
208 function AddRow: THtmlRow;
209 end;
210
211 { THtmlTable }
212
213 THtmlTable = class(THtmlElement)
214 protected
215 function GetAsXmlElement: TXmlElement; override;
216 public
217 Rows: THtmlRows;
218 constructor Create;
219 destructor Destroy; override;
220 end;
221
222 { TQueryString }
223
224 TQueryString = class
225 Data: TStringList;
226 procedure SetStringServer;
227 procedure SetString(QueryString: string);
228 function GetString: string;
229 constructor Create;
230 destructor Destroy; override;
231 end;
232
233
234implementation
235
236function LeftCutString(var Source, Output: string; Delimiter: string; Allowed: string = ''): Boolean;
237var
238 I, J: Integer;
239 Matched: Boolean;
240begin
241 I := 1;
242 Matched := True;
243 while (I <= Length(Source)) and Matched do begin
244 Matched := False;
245 if (Source[I] >= 'A') and (Source[I] <= 'Z') then Matched := True
246 else if (Source[I] >= 'a') and (Source[I] <= 'z') then Matched := True
247 else if (Source[I] >= '0') and (Source[I] <= '9') then Matched := True
248 else for J := 1 to Length(Allowed) do
249 if Source[I] = Allowed[J] then Matched := True;
250 if Matched then Inc(I);
251 end;
252 if (Delimiter = Copy(Source, I, Length(Delimiter))) or (I = Length(Source)) then begin
253 Output := Copy(Source, 1, I - 1);
254 Delete(Source, 1, Length(Output) + Length(Delimiter));
255 Result := True;
256 end else begin
257 Output := '';
258 Result := False;
259 end;
260end;
261
262function RightCutString(var Source, Output: string; Delimiter: string; Allowed: string = ''): Boolean;
263var
264 I, J: Integer;
265 Matched: Boolean;
266begin
267 I := Length(Source);
268 Matched := True;
269 while (I > 0) and Matched do begin
270 Matched := False;
271 if (Source[I] >= 'A') and (Source[I] <= 'Z') then Matched := True;
272 if (Source[I] >= 'a') and (Source[I] <= 'z') then Matched := True;
273 if (Source[I] >= '0') and (Source[I] <= '9') then Matched := True;
274 for J := 1 to Length(Allowed) do
275 if Source[I] = Allowed[J] then Matched := True;
276 if Matched then Dec(I);
277 end;
278 if (Delimiter = Copy(Source, I - Length(Delimiter) + 1, Length(Delimiter))) or (I = 0) then begin
279 Output := Copy(Source, I+1, Length(Source) - I);
280 Delete(Source, I, Length(Output) + Length(Delimiter));
281 Result := True;
282 end else begin
283 Output := '';
284 Result := False;
285 end;
286end;
287
288{ THtmlCells }
289
290function THtmlCells.AddCell: THtmlCell;
291begin
292 Result := THtmlCell.Create;
293 Add(Result);
294end;
295
296{ THtmlRows }
297
298function THtmlRows.AddRow: THtmlRow;
299begin
300 Result := THtmlRow.Create;
301 Add(Result);
302end;
303
304{ THtmlList }
305
306function THtmlList.GetAsXmlElement: TXmlElement;
307var
308 I: Integer;
309begin
310 Result := TXmlTag.Create;
311 with TXmlTag(Result) do begin
312 case ListType of
313 ltOrdered: Name := 'ol';
314 ltUnordered: Name := 'ul';
315 end;
316 for I := 0 to SubItems.Count - 1 do begin
317 with SubElements.AddTag('li') do
318 SubElements.Add(SubItems[I].AsXmlElement);
319 end;
320 end;
321end;
322
323constructor THtmlList.Create;
324begin
325 inherited;
326 SubItems := THtmlElements.Create;
327end;
328
329destructor THtmlList.Destroy;
330begin
331 FreeAndNil(SubItems);
332 inherited;
333end;
334
335{ THtmlElements }
336
337function THtmlElements.AddString(Text: string = ''): THtmlString;
338begin
339 Result := THtmlString.Create;
340 Result.Text := Text;
341 Add(Result);
342end;
343
344function THtmlElements.AddBlock: THtmlBlock;
345begin
346 Result := THtmlBlock.Create;
347 Add(Result);
348end;
349
350function THtmlElements.AddList: THtmlList;
351begin
352 Result := THtmlList.Create;
353 Add(Result);
354end;
355
356function THtmlElements.AddInput: THtmlInput;
357begin
358 Result := THtmlInput.Create;
359 Add(Result);
360end;
361
362{ THtmlCell }
363
364function THtmlCell.GetAsXmlElement: TXmlElement;
365begin
366 Result := inherited GetAsXmlElement;
367 TXmlTag(Result).Name := 'td';
368 with TXmlTag(Result).Attributes do begin
369 if ColSpan > 1 then Add('colspan', IntToStr(ColSpan));
370 if RowSpan > 1 then Add('rowspan', IntToStr(RowSpan));
371 end;
372 TXmlTag(Result).SubElements.Add(Value.AsXmlElement);
373end;
374
375constructor THtmlCell.Create;
376begin
377 ColSpan := 1;
378 RowSpan := 1;
379end;
380
381destructor THtmlCell.Destroy;
382begin
383 FreeAndNil(Value);
384 inherited;
385end;
386
387{ THtmlRow }
388
389function THtmlRow.GetAsXmlElement: TXmlElement;
390var
391 Column: Integer;
392begin
393 Result := inherited GetAsXmlElement;
394 TXmlTag(Result).Name := 'tr';
395 for Column := 0 to Cells.Count - 1 do
396 TXmlTag(Result).SubElements.Add(Cells[Column].AsXmlElement);
397end;
398
399constructor THtmlRow.Create;
400begin
401 Cells := THtmlCells.Create;
402end;
403
404destructor THtmlRow.Destroy;
405begin
406 FreeAndNil(Cells);
407 inherited;
408end;
409
410{ THtmlTable }
411
412function THtmlTable.GetAsXmlElement: TXmlElement;
413var
414 Row: Integer;
415begin
416 Result := inherited;
417 with TXmlTag(Result) do begin
418 Name := 'table';
419 for Row := 0 to Rows.Count - 1 do
420 SubElements.Add(Rows[Row].AsXmlElement);
421 end;
422end;
423
424constructor THtmlTable.Create;
425begin
426 Rows := THtmlRows.Create;
427end;
428
429destructor THtmlTable.Destroy;
430begin
431 FreeAndNil(Rows);
432 inherited;
433end;
434
435{ THtmlLineBreak }
436
437function THtmlLineBreak.GetAsXmlElement: TXmlElement;
438begin
439 Result := inherited GetAsXmlElement;
440 TXmlTag(Result).Name := 'br';
441end;
442
443constructor THtmlLineBreak.Create;
444begin
445end;
446
447{ THtmlInput }
448
449function THtmlInput.GetAsXmlElement: TXmlElement;
450var
451 InputTypeString: string;
452begin
453 Result := TXmlTag.Create;
454 with TXmlTag(Result) do begin
455 Name := 'input';
456 case InputType of
457 itButton: InputTypeString := 'button';
458 itRadioButton: InputTypeString := 'radio';
459 itCheckBox: InputTypeString := 'checkbox';
460 itText: InputTypeString := 'text';
461 itFileSelect: InputTypeString := 'file';
462 itSubmit: InputTypeString := 'submit';
463 itHidden: InputTypeString := 'hidden';
464 itPassword: InputTypeString := 'password';
465 end;
466 Attributes.Add('type', InputTypeString);
467 Attributes.Add('value', Value);
468 if Self.ItemName <> '' then
469 Attributes.Add('name', Self.ItemName);
470 end;
471end;
472
473procedure THtmlInput.Assign(Source: THtmlElement);
474begin
475 inherited Assign(Source);
476 InputType := THtmlInput(Source).InputType;
477 Value := THtmlInput(Source).Value;
478 ItemName := THtmlInput(Source).ItemName;
479end;
480
481constructor THtmlInput.Create;
482begin
483end;
484
485destructor THtmlInput.Destroy;
486begin
487 inherited;
488end;
489
490{ THtmlForm }
491
492function THtmlForm.GetAsXmlElement: TXmlElement;
493begin
494 Result := TXmlTag.Create;
495 with TXmlTag(Result) do begin
496 Name := 'form';
497 Attributes.Add('action', Action.AsString);
498 Attributes.Add('method', Method);
499 end;
500end;
501
502constructor THtmlForm.Create;
503begin
504 inherited;
505 Action := TURL.Create;
506 BlockType := btBlockLevel;
507 Method := 'get';
508end;
509
510destructor THtmlForm.Destroy;
511begin
512 FreeAndNil(Action);
513 inherited;
514end;
515
516{ THtmlDocument }
517
518constructor THtmlDocument.Create;
519begin
520 Body := THtmlBlock.Create;
521 Styles := TStringList.Create;
522 Scripts := TStringList.Create;
523 ContentLanguage := 'en';
524 ContentEncoding := 'utf-8';
525end;
526
527destructor THtmlDocument.Destroy;
528begin
529 FreeAndNil(Body);
530 FreeAndNil(Styles);
531 FreeAndNil(Scripts);
532 inherited;
533end;
534
535function THtmlDocument.GetAsXmlDocument: TXmlDocument;
536var
537 I: Integer;
538begin
539 Result := TXmlDocument.Create;
540 with Result, Content do begin
541 with SubElements.AddTag('!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"') do begin
542 EndTagSymbol := '';
543 end;
544 with SubElements.AddTag('html') do begin
545 with SubElements.AddTag('head') do begin
546 with SubElements.AddTag('title') do begin
547 SubElements.AddString(Title);
548 end;
549 with SubElements.AddTag('meta') do begin
550 Attributes.Add('http-equiv', 'Content-Language');
551 Attributes.Add('content', ContentLanguage);
552 end;
553 with SubElements.AddTag('meta') do begin
554 Attributes.Add('http-equiv', 'Content-Type');
555 Attributes.Add('content', 'text/html; charset=' + ContentEncoding);
556 end;
557 with SubElements.AddTag('meta') do begin
558 Attributes.Add('name', 'viewport');
559 Attributes.Add('content', 'width=device-width, initial-scale=1');
560 end;
561 for I := 0 to Styles.Count - 1 do
562 with SubElements.AddTag('link') do begin
563 Attributes.Add('rel', 'stylesheet');
564 Attributes.Add('href', Styles[I]);
565 Attributes.Add('type', 'text/css');
566 Attributes.Add('media', 'all');
567 end;
568 for I := 0 to Scripts.Count - 1 do
569 with SubElements.AddTag('script') do begin
570 ShringEmpty := False;
571 Attributes.Add('type', 'text/javascript');
572 Attributes.Add('src', Scripts[I]);
573 end;
574 end;
575 with SubElements.AddTag('body') do begin
576 SubElements.Add(Body.AsXmlElement);
577 end;
578 end;
579 end;
580end;
581
582{ THtmlBlock }
583
584constructor THtmlBlock.Create;
585begin
586 inherited;
587 SubItems := THtmlElements.Create;
588end;
589
590destructor THtmlBlock.Destroy;
591begin
592 FreeAndNil(SubItems);
593 inherited;
594end;
595
596function THtmlBlock.GetAsXmlElement: TXmlElement;
597var
598 I: Integer;
599begin
600 Result := TXmlTag.Create;
601 with TXmlTag(Result) do begin
602 case BlockType of
603 btBlockLevel: Name := 'div';
604 btInline: Name := 'span';
605 btNoTag: Name := '';
606 end;
607 for I := 0 to SubItems.Count - 1 do
608 SubElements.Add(SubItems[I].AsXmlElement);
609 end;
610end;
611
612{ THtmlElement }
613
614function THtmlElement.GetAsXmlElement: TXmlElement;
615begin
616 Result := TXmlTag.Create;
617 with TXmlTag(Result).Attributes do begin
618 if Name <> '' then Add('name', Name);
619 if Style <> '' then Add('style', Style);
620 if ClassId <> '' then Add('class', ClassId);
621 if Id <> '' then Add('id', Id);
622 end;
623end;
624
625procedure THtmlElement.Assign(Source: THtmlElement);
626begin
627 Id := Source.Id;
628 Name := Source.Name;
629 ClassId := Source.ClassId;
630 Style := Source.Style;
631end;
632
633{ TURL }
634
635constructor TURL.Create;
636begin
637 Host := THostAddress.Create;
638end;
639
640destructor TURL.Destroy;
641begin
642 FreeAndNil(Host);
643 inherited;
644end;
645
646function TURL.GetAsString: string;
647begin
648 Result := '';
649 if Scheme <> '' then Result := Scheme + '://';
650 if UserName <> '' then begin
651 Result := Result + UserName;
652 if UserName <> '' then Result := Result + ':' + Password;
653 Result := Result + '@';
654 end;
655 if Host.AsString <> '' then Result := Result + Host.AsString;
656 if Port <> 0 then Result := Result + ':' + IntToStr(Port);
657 if Path <> '' then Result := Result + Path;
658 if Query <> '' then Result := Result + '?' + Query;
659 if Fragment <> '' then Result := Result + '#' + Fragment;
660end;
661
662procedure TURL.SetAsString(Value: string);
663var
664 HostAddr: string;
665 HostPort: string;
666begin
667 LeftCutString(Value, Scheme, '://');
668 if LeftCutString(Value, UserName, ':') then LeftCutString(Value, Password, '@')
669 else LeftCutString(Value, UserName, '@');
670 RightCutString(Value, Fragment, '#');
671 RightCutString(Value, Query, '?', '=&');
672 if LeftCutString(Value, HostAddr, ':', '.') then begin
673 LeftCutString(Value, HostPort, '');
674 Port := StrToInt(HostPort);
675 end else LeftCutString(Value, HostAddr, '', '.');
676 Host.AsString := HostAddr;
677 LeftCutString(Value, Path, '', '/.');
678end;
679
680{ THtmlLink }
681
682constructor THtmlLink.Create;
683begin
684 Target := TURL.Create;
685end;
686
687destructor THtmlLink.Destroy;
688begin
689 FreeAndNil(Target);
690 inherited;
691end;
692
693function THtmlLink.GetAsXmlElement: TXmlElement;
694begin
695 Result := TXmlTag.Create;
696 with TXmlTag(Result) do begin
697 Name := 'a';
698 Attributes.Add('href', Target.AsString);
699 if Assigned(Content) then SubElements.Add(Content.AsXmlElement);
700 end;
701end;
702
703{ THtmlString }
704
705function THtmlString.GetAsXmlElement: TXmlElement;
706begin
707 Result := TXmlString.Create;
708 TXmlString(Result).Text := Text;
709end;
710
711procedure THtmlString.Assign(Source: THtmlElement);
712begin
713 inherited Assign(Source);
714 Text := THtmlString(Source).Text;
715end;
716
717{ THtmlImage }
718
719constructor THtmlImage.Create;
720begin
721 Source := TURL.Create;
722end;
723
724destructor THtmlImage.Destroy;
725begin
726 FreeAndNil(Source);
727 inherited;
728end;
729
730function THtmlImage.GetAsXmlElement: TXmlElement;
731begin
732 Result := TXmlTag.Create;
733 with TXmlTag(Result) do begin
734 Name := 'img';
735 Attributes.Add('src', Source.AsString);
736 Attributes.Add('width', IntToStr(Size.Width));
737 Attributes.Add('height', IntToStr(Size.Height));
738 Attributes.Add('alt', AlternateText);
739 end;
740end;
741
742procedure TQueryString.SetStringServer;
743begin
744 //$this->SetString($_SERVER['QUERY_STRING']);
745end;
746
747procedure TQueryString.SetString(QueryString: string);
748begin
749 (*
750 $this->Data = array();
751 $Parts = explode('&', $QueryString);
752 foreach($Parts as $Part)
753 {
754 if($Part != '')
755 {
756 $Item = explode('=', $Part);
757 $this->Data[$Item[0]] = $Item[1];
758 end;
759 end;*)
760end;
761
762function TQueryString.GetString: string;
763begin
764 (*$Parts = array();
765 foreach($this->Data as $Index => $Item)
766 {
767 $Parts[] = $Index.'='.$Item;
768 }
769 return(implode('&', $Parts));*)
770end;
771
772constructor TQueryString.Create;
773begin
774 Data := TStringList.Create;
775end;
776
777destructor TQueryString.Destroy;
778begin
779 FreeAndNil(Data);
780 inherited;
781end;
782
783end.
Note: See TracBrowser for help on using the repository browser.