1 module uim.html.apps.layout;
2 
3 import uim.html;
4 
5 /// Page layout
6   class DH5AppLayout : DH5AppObj {
7 	this() { super(); 
8 	_lang = "en"; }
9 	this(DH5App anApp) { this().app(anApp); }
10 
11 	string[] _headClasses;
12 	string[string] _headAttributes;
13 	string[] _bodyClasses;
14 	string[string] _bodyAttributes;
15 
16 	mixin(XString!("preHead"));
17 	mixin(XString!("postHead"));
18 	mixin(XString!("preContent"));
19 	mixin(XString!("postContent"));
20 	mixin(XStringArray!("requires"));
21 	
22 	mixin(OString!("lang"));
23 	mixin(OString!("title"));
24 	
25 	mixin(OProperty!("DH5Html", "html"));
26 
27 	protected DH5Meta[] _metas;
28 	DH5Meta[] metas() { return _metas; }
29 	O metas(this O)(string[string] value, string[string][] addMetas...) { this.metas([value]~addMetas); return cast(O)this;}
30 	O metas(this O)(string[string][] addMetas) { foreach(meta; addMetas) this.metas(H5Meta(meta)); return cast(O)this; }
31 
32 	O metas(this O)(DH5Meta[] addMetas...) { this.metas(addMetas); return cast(O)this; }
33 	O metas(this O)(DH5Meta[] addMetas) { _metas ~= addMetas; return cast(O)this;}
34 
35 	O clearMetas(this O)() { _metas = null; return cast(O)this; }
36 	unittest {
37 		assert(uim.html.elements.meta.toString(H5AppLayout.metas(["a":"b"]).metas)  == `<meta a="b">`);
38 		assert(uim.html.elements.meta.toString(H5AppLayout.metas([["a":"b"]]).metas)  == `<meta a="b">`);
39 		assert(uim.html.elements.meta.toString(H5AppLayout.metas(H5Meta(["a":"b"])).metas)  == `<meta a="b">`);
40 		assert(uim.html.elements.meta.toString(H5AppLayout.metas([H5Meta(["a":"b"])]).metas)  == `<meta a="b">`);
41 	}
42 
43 	DH5Link[] _links;
44 	DH5Link[] links() { return  _links; }	
45 	O links(this O)(string[string] link, string[string][] links...) { this.links([link]~links); return cast(O)this;}
46 	O links(this O)(string[string][] links) { foreach(link; links) _links ~= H5Link(link); return cast(O)this;}
47 
48 	O links(this O)(DH5Link[] links...) { this.links(links); return cast(O)this;}
49 	O links(this O)(DH5Link[] links) { _links ~= links; return cast(O)this;}
50 
51 	O clearLinks(this O)() { _links = null; return cast(O)this; }
52 	unittest {
53 		/// TODO
54 	}
55 
56 	DH5Style[] _styles;
57 	DH5Style[] styles() { return  _styles; }	
58 	O styles(this O)(string content, string[] contents...) { this.styles([content]~contents); return cast(O)this; } // <style>...</style>
59 	O styles(this O)(string[] links) { foreach(link; links) _styles ~= H5Style(content); return cast(O)this;}
60 
61 	O styles(this O)(string[string] link, string[string][] links...) { this.links([link]~links); return cast(O)this;}
62 	O styles(this O)(string[string][] links) { foreach(link; links) _links ~= H5Link(link); return cast(O)this;}
63 
64 	O styles(this O)(DH5Style[] styles...) { this.styles(styles); return cast(O)this;}
65 	O styles(this O)(DH5Style[] styles) { _styles ~= styles; return cast(O)this;}
66 	O styles(this O)(DH5Link[] links...) { this.styles(links); return cast(O)this;}
67 	O styles(this O)(DH5Link[] links) { _styles ~= links; return cast(O)this;}
68 
69 	O clearStyles(this O)() { _styles = null; return cast(O)this; }
70 	unittest {
71 		/// TODO
72 	}
73 
74 	DH5Script[] _scripts;
75 	DH5Script[] scripts() { return _scripts; }
76 	O scripts(this O)(string lib, string[] libs...) { this.scripts([lib]~libs); return cast(O)this;}
77 	O scripts(this O)(string[] libs) { foreach(lib; libs) _scripts ~= H5Script(["src":lib]); return cast(O)this;}
78 
79 	O scripts(this O)(string[string] lib, string[string][] libs...) { this.scripts([lib]~libs); return cast(O)this;}
80 	O scripts(this O)(string[string][] libs) { foreach(lib; libs) _scripts ~= H5Script(lib); return cast(O)this;}
81 
82 	O scripts(this O)(DH5Script[] libs...) { this.scripts(libs); return cast(O)this;}
83 	O scripts(this O)(DH5Script[] libs) { _scripts ~= libs; return cast(O)this;}
84 
85 	O clearScripts(this O)() { _scripts = null; return cast(O)this; }
86 	unittest {
87 		// assert(H5AppLayout.)
88 	}
89 
90   mixin(XString!("headPart"));
91 	mixin(XString!("bodyPart"));
92 
93 	/// central layout for page
94 	DH5AppLayout _layout;
95 	auto layout() { if (_layout) return _layout; return null; }
96 	O layout(this O)(DH5AppLayout newlayout) { _layout = newlayout.app(this.app); return cast(O)this; }
97 	unittest {
98 		/// TODO		
99 	}
100 
101 	string opCall() { return toString(); }
102 	string opCall(DH5AppPage page, string[string] parameters = null) { return toString(page, parameters); }
103 	string opCall(string content, string[string] parameters = null) { return toString(content, parameters); }
104 	
105 	override string toString() { return toString("", null); }
106 	string toString(DH5AppPage page, string[string] someParameters = null) {
107 		return toString(page, page.content, someParameters);
108 	}
109 
110 	string toString(DH5AppPage page, string content, string[string] someParameters = null) {
111 		// layout override app, page override layout, parameters override page
112 		string[string] newParameters;
113 
114 		if (app) newParameters = app.parameters.dup;
115 		// Layout overrides app
116 		foreach(k,v; this.parameters) newParameters[k] = v;
117 		// page overrides layout & app
118 		foreach(k,v; page.parameters) newParameters[k] = v;
119 		// parameters overrides App & layout & page
120 		foreach(k,v; someParameters) newParameters[k] = v;
121 
122 		DH5Meta[] newMetas;
123 		if (app) newMetas ~= app.metas;
124 		newMetas ~= this.metas;
125 		newMetas ~= page.metas;
126 
127 		DH5Link[] newLinks;		
128 //		if (app) newLinks = app.links;
129 		newLinks ~= this.links;
130 		newLinks ~= page.links;
131 
132 		DH5Style[] newStyles;
133 		if (app) newStyles ~= app.styles;
134 		newStyles ~= this.styles;
135 		newStyles ~= page.styles;
136 
137 		DH5Script[] newScripts;
138 		if (app) newScripts ~= app.scripts;
139 		newScripts ~= this.scripts;
140 		newScripts ~= page.scripts;
141 
142 		return htmlDocument(content, newMetas, newLinks, newStyles, newScripts, newParameters);
143 	}
144 
145 	string toString(string content, string[string] someParameters = null) {
146 		// layout override app, parameters override layout
147 		string[string] newParameters;
148 
149 		if (app) newParameters = app.parameters.dup;
150 		// Layout overrides app
151 		foreach(k,v; this.parameters) newParameters[k] = v;
152 		// parameters overrides App & layout & page
153 		foreach(k,v; someParameters) newParameters[k] = v;
154 
155 		DH5Meta[] newMetas;
156 		if (app) newMetas = app.metas;
157 		newMetas ~= this.metas;
158 
159 		DH5Link[] newLinks;		
160 //		if (app) newLinks = app.links;
161 		newLinks ~= this.links;
162 
163 		DH5Style[] newStyles;
164 		if (app) newStyles = app.styles;
165 		newStyles ~= this.styles;
166 
167 		DH5Script[] newScripts;
168 		if (app) newScripts ~= app.scripts;
169 		newScripts ~= this.scripts;
170 
171 		return htmlDocument(content, newMetas, newLinks, newStyles, newScripts, newParameters);
172 	}
173 
174 	auto htmlDocument(string content, DH5Meta[] newMetas, DH5Link[] newLinks, DH5Style[] newStyles, DH5Script[] newScripts, string[string] parameters = null) {
175 		auto finalLang = parameters.get("lang", this.lang); // if lang !in parameters use this.lang
176 		auto finalTitle = parameters.get("title", this.title);  // if title !in parameters use this.title
177 
178 		// creating HTML page
179 		_html = H5Html
180 		.attributes("lang", finalLang).attributes("dir", parameters.get("dir", "ltr"))
181 		// Head part of HTML
182 		.head(_headClasses)
183 		.head(_headAttributes)
184 		.head(finalTitle.length > 0 ? "<title>" ~ finalTitle ~ "</title>":"")
185 		.head(newMetas.asString~parameters.get("metas", ""))
186 		.head(newLinks.asString~parameters.get("links", ""))
187 		.head(newStyles.asString~parameters.get("styles", ""))
188 		.head("style" in parameters ? H5Style(parameters["style"]).toString : "")
189 		// Body part of HTML
190 		.body_(_bodyClasses)
191 		.body_(_bodyAttributes)
192 		.body_(this.layout ?  this.layout.toString(content, parameters) : content)
193 		.body_(newScripts.asString~parameters.get("scripts", ""))
194 		.body_("script" in parameters ? H5Script(parameters["script"]).toString : "");
195 
196 		return _html.toString;
197 	}
198 	unittest {
199 		// writeln(H5AppLayout);
200 		assert(H5AppLayout == `<!doctype html><html dir="ltr" lang="en"><head></head><body></body></html>`);
201 		assert(H5AppLayout()("xxx") == `<!doctype html><html dir="ltr" lang="en"><head></head><body>xxx</body></html>`);
202 	}
203 }
204 auto H5AppLayout() { return new DH5AppLayout(); }
205 
206 unittest {
207 
208 }