source: trunk/Packages/CoolWeb/Common/HtmlClasses.pas

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