1: <?php
2: 3: 4: 5: 6:
7:
8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
24: class QTreeNav extends QControl {
25: protected $strJavaScripts = 'treenav.js';
26:
27: protected $strItemCssStyle = 'treenav_item';
28: protected $strItemSelectedCssStyle = 'treenav_item treenav_item_selected';
29: protected $strItemHoverCssStyle = 'treenav_item treenav_item_hover';
30: protected $strItemSelectedHoverCssStyle = 'treenav_item treenav_item_hover treenav_item_selected';
31:
32: protected $strLabelForRequired;
33: protected $strLabelForRequiredUnnamed;
34:
35: protected $intIndentWidth = 15;
36: protected $intItemHeight = 15;
37: protected $intItemWidth = 0;
38:
39: protected $objChildItemArray = array();
40: protected $objItemArray = array();
41: protected $intNextItemId = 1;
42: protected $objSelectedTreeNavItem = null;
43: protected $strLoader = null;
44: protected $objLoaderParent = null;
45:
46: protected $blnIsBlockElement = true;
47: protected $blnExpandOnSelect = true;
48: protected $blnAllowHover = false;
49:
50: public function __construct($objParentObject, $strControlId = null) {
51: parent::__construct($objParentObject, $strControlId);
52:
53: $this->strLabelForRequired = QApplication::Translate('%s is required');
54: $this->strLabelForRequiredUnnamed = QApplication::Translate('Required');
55: }
56:
57: public function SetLoader($strFuncName, $objParent)
58: {
59: $this->strLoader = $strFuncName;
60: $this->objLoaderParent = $objParent;
61: }
62:
63: protected function GetItemHtml($objItem) {
64: $strItemId = $this->strControlId . '_' . $objItem->ItemId;
65:
66: $objChildren = $objItem->ChildItemArray;
67: $intChildCount = count($objChildren);
68:
69: $strSubNodeHtml = '';
70: $strImageHtml = '';
71: $strLabelHtml = '';
72:
73: if ($intChildCount || $objItem->HasChildren) {
74:
75: if ($objItem->Expanded) {
76: $strImageHtml = sprintf('<span style="margin-right: 2px;"><img id="%s_image" src="%s/treenav_expanded.png" width="11" height="11" alt="" style="position: relative; top: 2px; cursor: pointer;" onclick="treenavToggleImage(\'%s\')"/></span>',
77: $strItemId, __VIRTUAL_DIRECTORY__ . __IMAGE_ASSETS__, $strItemId);
78:
79: if($intChildCount == 0 && null !== $this->strLoader && null !== $this->objLoaderParent)
80: {
81:
82: $strLoader = $this->strLoader;
83: $this->objLoaderParent->$strLoader($objItem);
84:
85:
86: $objChildren = $objItem->ChildItemArray;
87: $intChildCount = count($objChildren);
88: }
89:
90: for ($intIndex = 0; $intIndex < $intChildCount; $intIndex++) {
91: $objChildItem = $objChildren[$intIndex];
92: $strChildItemId = $this->strControlId . '_' . $objChildItem->ItemId;
93: $strSubNodeHtml .= sprintf('<div id="%s">%s</div>', $strChildItemId, $this->GetItemHtml($objChildItem, $strChildItemId));
94: }
95:
96: $strSubNodeHtml = sprintf('<div id="%s_sub" style="margin-left: %spx;">%s</div>',
97: $strItemId,
98: $this->intIndentWidth,
99: $strSubNodeHtml);
100: } else {
101: $strSubNodeHtml = sprintf('<div id="%s_sub" style="margin-left: %spx; display: none;"><span class="%s" style="cursor: auto;">%s...</span></div>',
102: $strItemId,
103: $this->intIndentWidth,
104: $this->strItemCssStyle,
105: QApplication::Translate('Loading')
106: );
107:
108: $strCommand = sprintf('onclick="treenavToggleImage(\'%s\'); qc.pA(\'%s\', \'%s\', \'QTreeNav_Expand\', \'%s\')"',
109: $strItemId,
110: $this->objForm->FormId,
111: $this->strControlId,
112: $strItemId
113: );
114:
115: $strImageHtml = sprintf('<span style="margin-right: 2px;"><img id="%s_image" src="%s/treenav_not_expanded.png" width="11" height="11" alt="" style="position: relative; top: 2px; cursor: pointer;" %s/></span>',
116: $strItemId, __VIRTUAL_DIRECTORY__ . __IMAGE_ASSETS__, $strCommand);
117: }
118:
119: } else {
120:
121: $strImageHtml = '<span style="margin-right: 2px;"><img src="' . __VIRTUAL_DIRECTORY__ . __IMAGE_ASSETS__ .
122: '/treenav_child.png" width="11" height="11" alt="" style="position: relative; top: 2px;"/></span>';
123: }
124:
125: $strCommand = sprintf('onclick="qc.pA(\'%s\', \'%s\', \'QChangeEvent\', \'%s\', \'%s\')"',
126: $this->objForm->FormId,
127: $this->strControlId,
128: $strItemId,
129: $this->objForm->DefaultWaitIcon->ControlId
130: );
131: if($this->blnAllowHover)
132: $strLabelHtml = sprintf('<span id="%s_label" class="%s" %s>%s</span>',
133: $strItemId,
134: ($objItem->Selected) ? $this->strItemSelectedCssStyle : $this->strItemCssStyle,
135: $strItemId, ($objItem->Selected) ? $this->strItemSelectedHoverCssStyle : $this->strItemHoverCssStyle ,
136: $strItemId, ($objItem->Selected) ? $this->strItemSelectedCssStyle : $this->strItemCssStyle,
137: $strCommand,
138: $objItem->Name);
139: else
140: $strLabelHtml = sprintf('<span id="%s_label" class="%s" %s>%s</span>',
141: $strItemId,
142: ($objItem->Selected) ? $this->strItemSelectedCssStyle : $this->strItemCssStyle,
143: $strCommand,
144: $objItem->Name);
145:
146:
147: if ($this->intItemWidth > 0)
148: return sprintf('<div style="height: %spx; width: %spx;">%s%s</div>%s',
149: $this->intItemHeight, $this->intItemWidth, $strImageHtml, $strLabelHtml, $strSubNodeHtml);
150: else
151: return sprintf('<div style="height: %spx;">%s%s</div>%s',
152: $this->intItemHeight, $strImageHtml, $strLabelHtml, $strSubNodeHtml);
153: }
154:
155: public function AddChildItem(QTreeNavItem $objItem) {
156: array_push($this->objChildItemArray, $objItem);
157: }
158:
159: public function AddItem(QTreeNavItem $objItem) {
160: if (array_key_exists($objItem->ItemId, $this->objItemArray))
161: throw new QCallerException('Item Id already exists in QTreeNav ' . $this->strControlId . ': ' . $objItem->ItemId, 2);
162: $this->objItemArray[$objItem->ItemId] = $objItem;
163: }
164:
165: public function GetItem($strItemId) {
166: if (strpos($strItemId, '_') !== false) {
167: $intIndexArray = explode('_', $strItemId);
168: $strItemId = $intIndexArray[1];
169: }
170:
171: if (array_key_exists($strItemId, $this->objItemArray))
172: return $this->objItemArray[$strItemId];
173: else
174: return null;
175: }
176:
177: public function GenerateItemId() {
178: $strToReturn = 'i' . $this->intNextItemId;
179: $this->intNextItemId++;
180: return $strToReturn;
181: }
182:
183: public function Clear()
184: {
185: $this->objChildItemArray = array();
186: $this->objItemArray = array();
187: $this->intNextItemId = 1;
188: $this->objSelectedTreeNavItem = null;
189: $this->blnModified = true;
190: }
191:
192: public function ParsePostData() {
193: if (array_key_exists('Qform__FormControl', $_POST) && ($_POST['Qform__FormControl'] == $this->strControlId)) {
194: if ($_POST['Qform__FormEvent'] == 'QChangeEvent') {
195: $strParameter = $_POST['Qform__FormParameter'];
196: $objItem = $this->GetItem($strParameter);
197:
198: $this->SelectedItem = $objItem;
199:
200: $strItemHtml = $this->GetItemHtml($objItem, $strParameter);
201: $strItemHtml = addslashes($strItemHtml);
202: QApplication::ExecuteJavaScript('treenavRedrawElement("' . $strParameter . '", "' . $strItemHtml . '")');
203: } else if ($_POST['Qform__FormEvent'] == 'QTreeNav_Expand') {
204: $strParameter = $_POST['Qform__FormParameter'];
205: $objItem = $this->GetItem($strParameter);
206: $objItem->Expanded = true;
207:
208: $strItemHtml = $this->GetItemHtml($objItem, $strParameter);
209: $strItemHtml = addslashes($strItemHtml);
210: QApplication::ExecuteJavaScript('treenavRedrawElement("' . $strParameter . '", "' . $strItemHtml . '")');
211: }
212: }
213: }
214:
215: public function Validate() {
216:
217: if ($this->blnRequired && $this->SelectedItem === null)
218: {
219: if ($this->strName)
220: $this->ValidationError = sprintf($this->strLabelForRequired, $this->strName);
221: else
222: $this->ValidationError = $this->strLabelForRequiredUnnamed;
223: return false;
224: }
225:
226: return true;
227: }
228:
229: public function GetControlHtml() {
230: $strAttributes = $this->GetAttributes();
231: $strStyles = $this->GetStyleAttributes();
232:
233: if ($strStyles)
234: $strStyles = sprintf(' style="%s"', $strStyles);
235:
236: $strItemHtml = '';
237: foreach ($this->objChildItemArray as $objItem) {
238: $strItemId = $this->strControlId . '_' . $objItem->ItemId;
239: $strItemHtml .= '<div id="' . $strItemId . '">' . $this->GetItemHtml($objItem) . '</div>';
240: }
241:
242: return sprintf('<div id="%s" %s%s>%s</div>',
243: $this->strControlId,
244: $strAttributes,
245: $strStyles,
246: $strItemHtml);
247: }
248:
249:
250:
251:
252:
253: public function __get($strName) {
254: switch ($strName) {
255: case "SelectedItem": return $this->objSelectedTreeNavItem;
256: case "SelectedValue":
257: if ($this->objSelectedTreeNavItem)
258: return $this->objSelectedTreeNavItem->Value;
259: else
260: return null;
261: case "ChildItemArray": return (array) $this->objChildItemArray;
262: case "ItemArray": return (array) $this->objItemArray;
263:
264: case "ItemCssStyle": return $this->strItemCssStyle;
265: case "ItemSelectedCssStyle": return $this->strItemSelectedCssStyle;
266: case "ItemHoverCssStyle": return $this->strItemHoverCssStyle;
267:
268: case "IndentWidth": return $this->intIndentWidth;
269: case "ItemHeight": return $this->intItemHeight;
270: case "ItemWidth": return $this->intItemWidth;
271:
272: case "ExpandOnSelect": return $this->blnExpandOnSelect;
273:
274: default:
275: try {
276: return parent::__get($strName);
277: } catch (QCallerException $objExc) {
278: $objExc->IncrementOffset();
279: throw $objExc;
280: }
281: }
282: }
283:
284:
285:
286:
287: public function __set($strName, $mixValue) {
288: switch ($strName) {
289: case "ItemCssStyle":
290: try {
291: $this->strItemCssStyle = QType::Cast($mixValue, QType::String);
292: break;
293: } catch (QInvalidCastException $objExc) {
294: $objExc->IncrementOffset();
295: throw $objExc;
296: }
297: case "ItemSelectedCssStyle":
298: try {
299: $this->strItemSelectedCssStyle = QType::Cast($mixValue, QType::String);
300: break;
301: } catch (QInvalidCastException $objExc) {
302: $objExc->IncrementOffset();
303: throw $objExc;
304: }
305: case "ItemHoverCssStyle":
306: try {
307: $this->strItemHoverCssStyle = QType::Cast($mixValue, QType::String);
308: break;
309: } catch (QInvalidCastException $objExc) {
310: $objExc->IncrementOffset();
311: throw $objExc;
312: }
313: case "IndentWidth":
314: try {
315: $this->intIndentWidth = QType::Cast($mixValue, QType::Integer);
316: break;
317: } catch (QInvalidCastException $objExc) {
318: $objExc->IncrementOffset();
319: throw $objExc;
320: }
321: case "ItemHeight":
322: try {
323: $this->intItemHeight = QType::Cast($mixValue, QType::Integer);
324: break;
325: } catch (QInvalidCastException $objExc) {
326: $objExc->IncrementOffset();
327: throw $objExc;
328: }
329: case "ItemWidth":
330: try {
331: $this->intItemWidth = QType::Cast($mixValue, QType::Integer);
332: break;
333: } catch (QInvalidCastException $objExc) {
334: $objExc->IncrementOffset();
335: throw $objExc;
336: }
337: case "ExpandOnSelect":
338: try {
339: $this->blnExpandOnSelect = QType::Cast($mixValue, QType::Boolean);
340: break;
341: } catch (QInvalidCastException $objExc) {
342: $objExc->IncrementOffset();
343: throw $objExc;
344: }
345:
346: case "SelectedItem":
347: try {
348: $objItem = QType::Cast($mixValue, "QTreeNavItem");
349: } catch (QInvalidCastException $objExc) {
350: $objExc->IncrementOffset();
351: throw $objExc;
352: }
353:
354:
355: if ($objItem && $this->objSelectedTreeNavItem && ((string) $this->objSelectedTreeNavItem->ItemId == (string) $objItem->ItemId))
356: return $objItem;
357:
358:
359: if ($this->objSelectedTreeNavItem) {
360:
361:
362: QApplication::ExecuteJavaScript(sprintf("treenavItemUnselect('%s_%s_label', '%s')", $this->strControlId, $this->objSelectedTreeNavItem->ItemId, $this->strItemCssStyle));
363:
364:
365: $this->objSelectedTreeNavItem->Selected = false;
366: }
367:
368: if ($this->objSelectedTreeNavItem = $objItem) {
369: $objItem->Selected = true;
370:
371: if ($this->blnExpandOnSelect)
372: $objItem->Expanded = true;
373:
374:
375: $objParent = $this->GetItem($objItem->ParentItemId);
376:
377: while ($objParent) {
378: $objParent->Expanded = true;
379: $objParent = $this->GetItem($objParent->ParentItemId);
380: }
381: }
382:
383: return $objItem;
384:
385: case "ItemExpanded":
386: $strTokenArray = explode(' ', $mixValue);
387: $objItem = $this->GetItem($strTokenArray[0]);
388: $objItem->Expanded = $strTokenArray[1];
389: return $strTokenArray[1];
390:
391: default:
392: try {
393: parent::__set($strName, $mixValue);
394: } catch (QCallerException $objExc) {
395: $objExc->IncrementOffset();
396: throw $objExc;
397: }
398: break;
399: }
400: }
401: }