1: <?php
2:
3: namespace Zippy\Html;
4:
5: use Zippy\Interfaces\Binding;
6: use Zippy\Interfaces\EventReceiver;
7: use Zippy\Exception as ZE;
8: use Zippy\WebApplication;
9:
10: /**
11: * Базовый класс для всех HTML компонентов
12: *
13: * Каждый компонент имеет уникальный в пределах страницы номер элемента
14: * соответствующий аттрибуту 'zippy' из соответствующего тэга HTML шаблона
15: * Иерархия компонентов должна строго соответстввовать иерархии вложенных HTML тэгов
16: */
17: abstract class HtmlComponent
18: {
19: public $id;
20: protected $disabled = false;
21: protected $visible = true;
22: private $attributes = array();
23: // private $cssstyle = "";
24: // private $cssclass = "";
25: protected $owner = null;
26:
27: // public $uid;
28: // private static $uidcounter = 0;
29: // protected $HtmlTag=null;
30:
31: public $tag = null; //Позволяет связать с компонентом произвольные двнные
32:
33: /**
34: * Конструктор
35: *
36: * @param string
37: */
38:
39: public function __construct($id) {
40: if (!is_string($id) || strlen($id) == 0) {
41: throw new ZE(sprintf(ERROR_INVALID_CREATE_ID, get_class($this)));
42: }
43: if (in_array($id, array('add'))) {
44: throw new ZE(sprintf(ERROR_INVALID_ID, $id));
45: }
46: $this->id = $id;
47: $this->attributes["id"] = $id;
48:
49:
50: // $this->uid = ++self::$uidcounter; // номер екземпляра
51: }
52:
53: public function __toString() {
54: $str = get_class($this) . ' ' . $this->id;
55: if ($this->owner != null) {
56: $str = ' ' . $this->owner . '->' . get_class($this) . ' ' . $this->id;
57: }
58: return $str;
59: }
60:
61: /**
62: * Установить аттрибут для отобюражения в HTML тэге
63: * @param string Имя атрибута
64: * @param string Значение аттрибута
65: */
66: public function setAttribute($name, $value=null) {
67:
68: $this->attributes[$name] = $value;
69: /*
70:
71: if(\Zippy\WebApplication::$app->getRequest()->isAjaxRequest()) {
72:
73: if(strlen($value) >0) {
74: $js= "$('#{$this->id}').attr('{$name}','{$value}')" ;
75: } else {
76: $js= "$('#{$this->id}').attr('{$name}',null)" ;
77: }
78:
79: \Zippy\WebApplication::$app->getResponse()->addAjaxResponse($js) ;
80: }
81: */
82: }
83:
84: /**
85: * Получить атрибут
86: * @param string Имя атрибута
87: * @return string
88: */
89: public function getAttribute($name) {
90: if (isset($this->attributes[$name])) {
91: return $this->attributes[$name] instanceof Binding ? $this->attributes[$name]->getValue() : $this->attributes[$name];
92: } else {
93: return null;
94: }
95: }
96:
97: /**
98: * Возвращает список наименований аттрибутов
99: * @return array
100: */
101: public function getAttributeNames() {
102: return array_keys($this->attributes);
103: }
104:
105: /**
106: * Установка коонтейнера -владельца
107: * @param HtmlContainer Владелец
108: */
109: public function setOwner(HtmlContainer $owner) {
110: $this->owner = $owner;
111: }
112:
113: /**
114: * Вызывается после добавления к владельцу
115: */
116: protected function onAdded() {
117:
118: }
119:
120: /**
121: * Получить ссылку на владедца
122: *
123: * @return HtmlContainer
124: */
125: public function getOwner() {
126: return $this->owner;
127: }
128:
129: /**
130: * Возвращает ссылку на объект страницы в которую добавлен компонент
131: * @return WebPage
132: */
133: public function getPageOwner() {
134: if ($this->owner == null) {
135: return null;
136: }
137: if ($this->owner instanceof \Zippy\Html\WebPage) {
138: return $this->owner;
139: } else {
140: return $this->owner->getPageOwner();
141: }
142: }
143:
144: /**
145: * Возвращает ссылку на объект формы в которую добавлен компонент
146: * @return Form
147: */
148: public function getFormOwner() {
149: if ($this->owner == null) {
150: return null;
151: }
152: if ($this->owner instanceof \Zippy\Html\Form\Form) {
153: return $this->owner;
154: } else {
155: return $this->owner->getFormOwner();
156: }
157: }
158:
159: /**
160: * Управляет видимостью компонента
161: * Невидимый компонент не рендерится
162: * @param boolean
163: */
164: public function setVisible($visible) {
165: $this->visible = $visible;
166:
167:
168: }
169:
170: /**
171: * Прверяет видимость компонента
172: * @return boolean
173: */
174: public function isVisible() {
175: return $this->visible;
176: }
177:
178: /**
179: * Метод перегружаемый компонентами для имплементации своего рендеринга
180: */
181: protected function RenderImpl() {
182:
183: }
184:
185: /**
186: * Метод отвечающий за рендеринг компонента
187: * @param MarkupXmlNode
188: */
189: public function Render() {
190:
191: $HtmlTag = $this->getTag();
192:
193:
194: if (isset($this->attributes["class"])) {
195: if (strlen($this->attributes["class"]) > 0) {
196: $HtmlTag->addClass($this->attributes["class"]) ;
197: } else {
198: $HtmlTag->removeClass($this->attributes["class"]) ;
199: }
200: }
201:
202:
203: foreach($HtmlTag->attributes as $a){
204: $attributes[$a->nodeName] =$a->nodeValue;
205: };
206:
207:
208: if (isset($this->attributes["style"])) {
209: if (strlen($this->attributes["style"]) > 0) {
210: $attributes['style'] = ($attributes['style'] ??'') . '; ' . ($this->attributes["style"] ??'');
211: } else {
212: $attributes['style'] = str_replace(($this->attributes["style"] ??''), "", ($attributes['style'] ??''));
213: }
214: }
215:
216: unset($attributes["zippy"]);
217:
218: $attributes['id'] = $this->id;
219:
220:
221: foreach ($attributes as $key => $value) {
222:
223: if (!array_key_exists($key, $this->attributes)) {
224: $this->attributes[$key] = $value;
225: }
226: }
227:
228:
229: $this->beforeRender();
230: //вызываем имплементацию рендеринга наследуемым классом
231: $this->RenderImpl();
232: //рендерим аттрибуты
233: foreach ($this->attributes as $name => $value) {
234: $attr = $this->getAttribute($name);
235:
236: if (strlen($attr) == 0) {
237: $HtmlTag->removeAttr($name);
238: } else{
239: $HtmlTag->attr($name, $attr);
240: }
241: }
242: $this->afterRender();
243: }
244:
245: /**
246: * Возвращает ссылку на HTML таг. Используется библиотека PHPQuery
247: */
248: protected function getTag() : \DOMWrap\Element {
249: $p = $this->getPageOwner() ;
250:
251: $HtmlTag = WebApplication::$dom->find('[zippy="' . $this->id . '"]');
252:
253: if ($HtmlTag->count() > 1) {
254: throw new ZE(sprintf(ERROR_MARKUP_NOTUNIQUEID, $this->id));
255: }
256: if ($HtmlTag->count() == 0) {
257: $tag = 'zippy="' . $this->id . '"';
258:
259: throw new ZE(sprintf(ERROR_MARKUP_NOTFOUND, $tag));
260: }
261: return $HtmlTag->first();
262: }
263:
264: /**
265: * Метод, вызываемый перед рендерингом
266: * в качестве параметра передаются атрибуты с html тега
267: */
268: protected function beforeRender() {
269:
270: }
271:
272: /**
273: * Метод, вызываемый после рендерингв
274: */
275: protected function afterRender() {
276:
277: }
278:
279:
280: /**
281: * возвращает связаный тег
282: *
283: */
284: protected function getLabelTag() {
285: return WebApplication::$dom->find('[data-label="' . $this->id . '"]');
286: }
287: protected function getLabelTagFor() {
288: return WebApplication::$dom->find('[for="' . $this->id . '"]');
289: }
290:
291:
292:
293: public function getHTML(){
294: try{
295: $HtmlTag = $this->getTag();
296: $tn= $HtmlTag->tagName;
297: $attr="";
298: foreach($HtmlTag->attributes as $a){
299: $attr = $attr. " {$a->nodeName}=\"{$a->nodeValue}\" ";
300: };
301:
302: $html = "<{$tn} {$attr} >". $HtmlTag->html() . "</{$tn}>";
303:
304: return $html;
305:
306:
307: } catch(\Exception $e) {
308: return null;
309: }
310: }
311:
312:
313:
314: }
315: