1: <?php
2: /**
3: * QHtmlAttributeManager class
4: *
5: * This class is designed to be used as a base class for controls and other classes that need to manage HTML attributes.
6: *
7: * @package Controls
8: */
9:
10: /**
11: * A base class for objects that manage html attributes. Uses array functions and defines a couple of arrays to manage
12: * the attributes. Values will be html escaped when printed.
13: *
14: * Includes:
15: * - helper functions to manage the class, style, and data-* attributes specially.
16: * - helper functions to manage 'name-*' classes that are found in css frameworks like
17: * Bootstrap and Foundation.
18: * - helpers for __get and __set functions, partially for backwards compatibility and also to make the setting
19: * of some attributes and styles easier (so you don't have to remember how to set them).
20: *
21: * Usage: Use the helper functions to setup your styles, classes, data-* and other attributes, then call
22: * renderHtmlAttributes() to render the attributes to insert them into a tag.
23: *
24: *
25: * @property string $AccessKey allows you to specify what Alt-Letter combination will automatically focus that control on the form
26: * @property string $BackColor sets the CSS background-color of the control
27: * @property string $BorderColor sets the CSS border-color of the control
28: * @property string $BorderWidth sets the CSS border-width of the control
29: * @property string $BorderStyle is used to set CSS border-style by {@link QBorderStyle}
30: * @property string $BorderCollapse defines the BorderCollapse css style for a table
31: * @property string $CssClass sets or returns the CSS class for this control. When setting, if you precede the class name
32: * with a plus sign (+), it will add the class(es) to the currently existing classes, rather than replace them. Can add or
33: * set more than one class at once by separating names with a space.
34: * @property string $Cursor is used to set CSS cursor property by {@link QCursor}
35: * @property boolean $Display shows or hides the control using the CSS display property. In either case, the control is
36: * still rendered on the page. See the Visible property if you wish to not render a control.
37: * @property string $DisplayStyle is used to set CSS display property by {@link QDisplayStyle}
38: * @property boolean $Enabled specifies whether or not this is enabled (it will grey out the control and make it
39: * inoperable if set to true)
40: * @property boolean $FontBold sets the font bold or normal
41: * @property boolean $FontItalic sets the Font italic or normal
42: * @property string $FontNames sets the name of used fonts
43: * @property boolean $FontOverline
44: * @property string $FontSize sets the font-size of the control
45: * @property boolean $FontStrikeout
46: * @property boolean $FontUnderline sets the font underlined
47: * @property string $ForeColor sets the CSS color property, which controls text color
48: * @property string $Height
49: * @property string $Left CSS left property
50: * @property integer $Opacity sets the opacity of the control (0-100)
51: * @property string $Overflow is used to set CSS overflow property by {@link QOverflow}
52: * @property string $Position is used to set CSS position property by {@link QPosition}
53: * @property integer $TabIndex specifies the index/tab order on a form
54: * @property string $ToolTip specifies the text to be displayed when the mouse is hovering over the control
55: * @property string $Top
56: * @property string $Width
57: * @property string $HorizontalAlign sets the CSS text-align property
58: * @property string $VerticalAlign sets the CSS vertical-align property
59: * @property-write mixed $Padding sets the CSS padding property. Will accepts a string, which is passed verbatim, or
60: * an array, either numerically indexed, in which case it is in top, right, bottom, left order, or keyed with the
61: * names 'top', 'right', 'bottom', 'left'.
62: * @property-write mixed $Margin sets the CSS margin property. Will accepts a string, which is passed verbatim, or
63: * an array, either numerically indexed, in which case it is in top, right, bottom, left order, or keyed with the
64: * names 'top', 'right', 'bottom', 'left'
65: * @property-write array $Data a key/value array of data-* items to set. Keys can be in camelCase notation, in which case they will be
66: * converted to dashed notation. Use GetDataAttribute() to retrieve the value of a data attribute.
67: * @property boolean $NoWrap sets the CSS white-space property to nowrap
68: * @property boolean $ReadOnly is the "readonly" html attribute (making a textbox "ReadOnly" is similar to setting the textbox to Enabled
69: * Readonly textboxes are selectedable, and their values get posted. Disabled textboxes are not selectable and values do not post.
70: * @property string $AltText text used for 'alt' attribute in images
71: * @property string $OrderedListType type for ordered lists. Expects a QOrderedListType.
72: * @property string $UnorderedListStyle style for unordered lists. Expects a QUnorderedListType.
73: */
74:
75: class QHtmlAttributeManagerBase extends QBaseClass {
76: /** @var array attributes stored in PHP native format so they can be retrieved. Escaping happens when they are drawn. */
77: protected $attributes = array();
78: protected $styles = array();
79:
80: /**
81: * Sets the given html attribute to the given value.
82: * @param $strName
83: * @param $strValue
84: * @return boolean true if the attribute changed value
85: */
86: public function SetHtmlAttribute ($strName, $strValue) {
87: if (!is_null($strValue)) {
88: if (!isset($this->attributes[$strName]) || $this->attributes[$strName] !== $strValue) {
89: // only make a change if it has actually changed value.
90: $this->attributes[$strName] = $strValue;
91: $this->MarkAsModified();
92: return true;
93: }
94: } else {
95: if (isset($this->attributes[$strName])) {
96: unset($this->attributes[$strName]);
97: $this->MarkAsModified();
98: return true;
99: }
100: }
101: return false;
102: }
103:
104: /**
105: * Removes the given html attribute.
106: *
107: * @param $strName
108: */
109: public function RemoveHtmlAttribute ($strName) {
110: $this->SetHtmlAttribute($strName, null);
111: }
112:
113: /**
114: * Gets the Html Attribute, or return null if it does not exist.
115: *
116: * @param $strName
117: * @return null
118: */
119: public function GetHtmlAttribute ($strName) {
120: if (isset ($this->attributes[$strName])) {
121: return $this->attributes[$strName];
122: }
123: else {
124: return null;
125: }
126: }
127:
128: /**
129: * Returns an attribute array, with styles rendered.
130: * @param array|null $attributeOverrides
131: * @param array|null $styleOverrides
132: * @param array|null $selection an array of titles of attributes that you want the result to be limited to
133: * @return array
134: */
135: public function GetHtmlAttributes($attributeOverrides = null, $styleOverrides = null, $selection = null) {
136: $attributes = $this->attributes;
137: if ($attributeOverrides) {
138: $attributes = array_merge ($attributes, $attributeOverrides);
139: }
140: $strStyles = $this->RenderCssStyles($styleOverrides);
141: if ($strStyles) {
142: $attributes['style'] = $strStyles;
143: }
144: if ($selection) {
145: $attributes = array_intersect_key($attributes, array_fill_keys($selection, 1));
146: }
147: return $attributes;
148: }
149:
150: /**
151: * Returns true if the given attribute is set.
152: *
153: * @param string $strName
154: * @return bool
155: */
156: public function HasHtmlAttribute ($strName) {
157: return (isset($this->attributes[$strName]));
158: }
159:
160: /**
161: * Sets the given value as an html "data-*" attribute. The named value will be retrievable in jQuery by using
162: * '.data("$strName");'
163: *
164: * Note: Data name cases are handled specially in jQuery. Names are supposed to only be lower case. jQuery
165: * converts dashed notation to camelCase.
166: *
167: * For example, if your html looks like this:
168: *
169: * <div id='test1' data-test-case="my test"></div>
170: *
171: * You would get that value in jQuery by doing:
172: *
173: * $j('#test1').data('testCase');
174: *
175: * Conversion to special html data-* name formatting is handled here automatically. So if you SetDataAttribute('testCase') here,
176: * you can get it using .data('testCase') in jQuery
177: *
178: * @param $strName
179: * @param $strValue
180: */
181: public function SetDataAttribute ($strName, $strValue) {
182: $strName = 'data-' . JavaScriptHelper::dataNameFromCamelCase($strName);
183: $this->SetHtmlAttribute($strName, $strValue);
184: }
185:
186: /**
187: * Gets the data-* attribute value that was set previously in PHP.
188: *
189: * Does NOT call into javascript to return a value that was set on the browser side. You need to use another
190: * mechanism to retrieve that.
191: *
192: * @param $strName
193: * @return null
194: */
195: public function GetDataAttribute ($strName) {
196: $strName = 'data-' . JavaScriptHelper::dataNameFromCamelCase($strName);
197: return $this->GetHtmlAttribute($strName);
198: }
199:
200: /**
201: * Removes the given data attribute.
202: * @param $strName
203: */
204: public function RemoveDataAttribute ($strName) {
205: $strName = 'data-' . JavaScriptHelper::dataNameFromCamelCase($strName);
206: $this->RemoveHtmlAttribute($strName);
207: }
208:
209:
210:
211: /**
212: * Sets the Css named value to the given property.
213: *
214: * If blnIsLength is true, we assume the value is a unit length specifier, and so send it to the QHtml helper
215: * function, which has the ability to perform arithmetic operations on the old value.
216: *
217: * Will set the value of the parent classes blnModified value if something changes.
218: *
219: * @param string $strName
220: * @param string $strValue
221: * @param bool $blnIsLength true if this is a unit specifier e.g. 2px
222: * @return bool true if the style was actually changed (vs. it was already set that way)
223: */
224: public function SetCssStyle ($strName, $strValue, $blnIsLength = false) {
225: $ret = false;
226: if (!is_null($strValue)) {
227: if ($blnIsLength) {
228: if (isset($this->styles[$strName])) {
229: $oldValue = $this->styles[$strName];
230: } else {
231: $oldValue = '';
232: }
233: if (QHtml::SetLength ($oldValue, $strValue)) {
234: $ret = true;
235: $this->MarkAsModified();
236: $this->styles[$strName] = $oldValue; // oldValue was updated
237: }
238: }
239: elseif (!isset($this->styles[$strName]) || $this->styles[$strName] !== $strValue) {
240: $this->styles[$strName] = $strValue;
241: $this->MarkAsModified();
242: $ret = true;
243: }
244: } else {
245: if (isset($this->styles[$strName])) {
246: unset($this->styles[$strName]);
247: $this->MarkAsModified();
248: $ret = true;
249: }
250: }
251: return $ret;
252: }
253:
254: /**
255: * Removes the given CSS style property.
256: * @param $strName
257: * @return bool true if the style was removed, false if it wasn't there to begin with
258: */
259: public function RemoveCssStyle ($strName) {
260: return $this->SetCssStyle ($strName, null);
261: }
262:
263: /**
264: * Return true if the CSS style has been set.
265: * @param $strName
266: * @return bool
267: */
268: public function HasCssStyle ($strName) {
269: return isset($this->styles[$strName]);
270: }
271:
272: /**
273: * Retrieves the given CSS style property value.
274: * @param $strName
275: * @return string|null
276: */
277: public function GetCssStyle ($strName) {
278: if (isset ($this->styles[$strName])) {
279: return $this->styles[$strName];
280: }
281: else {
282: return null;
283: }
284: }
285:
286: /**
287: * Sets a box style, like margin or padding. Can accept:
288: * - string, which will pass the string verbatim to the shortcut prefix (e.g. margin: 0px 1px)
289: * - array, which can accept two styles:
290: * - [top, right, bottom, left], or
291: * - ['top'=>top, 'bottom'=>bottom, etc.]
292: *
293: * When passing an array, missing items or null items will be ignored. Also, you can use arithmetic operations
294: * to change the current value (provided you set a previous value).
295: *
296: * For example:
297: * $obj->setCssBoxStyle ('padding', ['right'=>3]);
298: * $obj->setCssBoxStyle ('padding', ['right'=>'*4']);
299: * Will set the padding-right to 12.
300: *
301: * @param string $strPrefix
302: * @param string|array $mixValue
303: */
304: public function SetCssBoxValue($strPrefix, $mixValue) {
305: if (is_string($mixValue)) {
306: // shortcut
307: $this->SetCssStyle($strPrefix, $mixValue);
308: } elseif (is_array($mixValue)) {
309: if (array_key_exists(0, $mixValue)) {
310: // top right bottom left, numerically indexed
311: if (isset($mixValue[0])) $this->SetCssStyle($strPrefix. '-top', $mixValue[0], true);
312: if (isset($mixValue[1])) $this->SetCssStyle($strPrefix. '-right', $mixValue[1], true);
313: if (isset($mixValue[2])) $this->SetCssStyle($strPrefix. '-bottom', $mixValue[2], true);
314: if (isset($mixValue[3])) $this->SetCssStyle($strPrefix. '-left', $mixValue[3], true);
315: } else {
316: // assume key/value
317: if (isset($mixValue['top'])) $this->SetCssStyle($strPrefix. '-top', $mixValue['top'], true);
318: if (isset($mixValue['right'])) $this->SetCssStyle($strPrefix. '-right', $mixValue['right'], true);
319: if (isset($mixValue['bottom'])) $this->SetCssStyle($strPrefix. '-bottom', $mixValue['bottom'], true);
320: if (isset($mixValue['left'])) $this->SetCssStyle($strPrefix. '-left', $mixValue['left'], true);
321: }
322: }
323: }
324:
325:
326: /**
327: * Sets the CSS class to the given value(s). Multiple class names can be separated with a space. If you
328: * preceed the class names with a plus(+) they will be added to the current class. If a minus (-) they
329: * will be removed.
330: *
331: * @param $strNewClass
332: */
333: public function SetCssClass($strNewClass) {
334: assert ('$strNewClass[0] != "+" || $strNewClass[1] == " "'); // If a plus sign, be sure to follow with a space. For consistency.
335: if (substr($strNewClass, 0, 2) == '+ ') {
336: $ret = $this->AddCssClass(substr($strNewClass, 2));
337: }
338: elseif (substr($strNewClass, 0, 2) == '- ') {
339: $ret = $this->RemoveCssClass(substr($strNewClass, 2));
340: }
341: else {
342: $ret = $this->SetHtmlAttribute('class', $strNewClass);
343: }
344: return $ret;
345: }
346:
347: /**
348: * Adds a css class name to the 'class' property. Prevents duplication.
349: * @param string $strNewClass
350: * @return bool true if the class was not already attached.
351: */
352: public function AddCssClass($strNewClass) {
353: $ret = false;
354: if (!$strNewClass) return false;
355:
356: $strClasses = $this->GetHtmlAttribute('class');
357: if (is_null($strClasses)) {
358: $strClasses= '';
359: }
360: if (QHtml::AddClass($strClasses, $strNewClass)) {
361: $this->SetHtmlAttribute('class', $strClasses);
362: $ret = true;
363: }
364: return $ret;
365: }
366:
367: /**
368: * This will remove a css class name from the 'class' property (if it exists).
369: * @param string $strCssClass
370: */
371: public function RemoveCssClass($strCssClass) {
372: if (!$strCssClass) return;
373: $strClasses = $this->GetHtmlAttribute('class');
374: if ($strClasses && QHtml::RemoveClass($strClasses, $strCssClass)) {
375: $this->SetHtmlAttribute('class', $strClasses);
376: }
377: }
378:
379: /**
380: * Many CSS frameworks use families of classes, which are built up from a base family name. For example,
381: * Bootstrap uses 'col-lg-6' to represent a column that is 6 units wide on large screens and Foundation
382: * uses 'large-6' to do the same thing. This utility removes classes that start with a particular prefix
383: * to remove whatever sizing class was specified.
384: *
385: * @param string $strPrefix
386: */
387: public function RemoveCssClassesByPrefix($strPrefix) {
388: if (!$strPrefix) return;
389: $strClasses = $this->GetHtmlAttribute('class');
390: if ($strClasses && QHtml::RemoveClassesByPrefix($strClasses, $strPrefix)) {
391: $this->SetHtmlAttribute('class', $strClasses);
392: }
393: }
394:
395:
396: /**
397: * Return true if the given class is in the attribute list.
398: *
399: * @param $strClass
400: * @return bool
401: */
402: public function HasCssClass($strClass) {
403: if (!isset($this->attributes['class'])) return false;
404: $strClasses = explode (' ', $this->attributes['class']);
405: return (in_array($strClass, $strClasses));
406: }
407:
408: /**
409: * Permanently overrides the current styles with a new set of attributes and styles.
410: *
411: * @param QHtmlAttributeManager $objNewStyles
412: */
413: protected function Override(QHtmlAttributeManager $objNewStyles) {
414: $this->attributes = array_merge($this->attributes, $objNewStyles->attributes);
415: $this->styles = array_merge($this->styles, $objNewStyles->styles);
416: }
417:
418: /**
419: * Mark the parent class as modified. The host class must implement this if this functionality is desired.
420: */
421: public function MarkAsModified() {}
422:
423: /**
424: * Returns the html for the attributes. Allows the given arrays to override the attributes and styles before
425: * rendering.
426: * @param null|string $attributeOverrides
427: * @param null|string $styleOverrides
428: * @return string
429: */
430: public function RenderHtmlAttributes($attributeOverrides = null, $styleOverrides = null) {
431: return QHtml::RenderHtmlAttributes($this->GetHtmlAttributes($attributeOverrides, $styleOverrides));
432: }
433:
434: /**
435: * Returns the styles rendered as a css style string.
436: * @param null|string $styleOverrides
437: * @return string
438: */
439: public function RenderCssStyles($styleOverrides = null) {
440: $styles = $this->styles;
441: if ($styleOverrides) {
442: $styles = array_merge($styles, $styleOverrides);
443: }
444: return QHtml::RenderStyles($styles);
445: }
446:
447: /**
448: * Helper function to render the current attributes and styles in a tag. Overrides will be merged in with
449: * current values before creating the output, but they will not affect the current values.
450: *
451: * @param $strTag
452: * @param null|array $attributeOverrides key/value pairs of values for attribute overrides
453: * @param null|array $styleOverrides key/value pairs of values for style overrides
454: * @param null|string $strInnerHtml inner html to render. Will NOT be escaped.
455: * @param bool $blnIsVoidElement true if it should not have innerHtml or a closing tag.
456: * @return string HTML out. Attributes will be escaped as needed, but innerHtml will be raw, so be careful.
457: */
458: protected function RenderTag($strTag, $attributeOverrides = null, $styleOverrides = null, $strInnerHtml = null, $blnIsVoidElement = false, $blnNoSpace = false) {
459: $strAttributes = $this->RenderHtmlAttributes($attributeOverrides, $styleOverrides);
460: return QHtml::RenderTag($strTag, $strAttributes, $strInnerHtml, $blnIsVoidElement, $blnNoSpace);
461: }
462:
463:
464: /**
465: * PHP magic method.
466: *
467: * The attributes include general attributes that span across most kinds of QControls. Attributes that are specific
468: * to a particular kind of tag might appear just in that control's definition.
469: *
470: * @param string $strName
471: * @return mixed
472: * @throws Exception|QCallerException
473: */
474: public function __get($strName) {
475: switch ($strName) {
476: // Styles
477: case "BackColor": return $this->GetCssStyle('background-color');
478: case "BorderColor": return $this->GetCssStyle('border-color');
479: case "BorderStyle": return $this->GetCssStyle('border-style');
480: case "BorderWidth": return $this->GetCssStyle('border-width');
481: case "BorderCollapse": return $this->GetCssStyle('border-collapse');
482: case "Display": return !($this->GetCssStyle('display') === QDisplayStyle::None);
483: case "DisplayStyle": return $this->GetCssStyle('display');
484: case "FontBold": return $this->GetCssStyle('font-weight') == 'bold';
485: case "FontItalic": return $this->GetCssStyle('font-style') == 'italic';
486: case "FontNames": return $this->GetCssStyle('font-family');
487: case "FontOverline": return $this->GetCssStyle('text-decoration') == 'overline';
488: case "FontStrikeout": return $this->GetCssStyle('text-decoration') == 'line-through';
489: case "FontUnderline": return $this->GetCssStyle('text-decoration') == 'underline';
490: case "FontSize": return $this->GetCssStyle('font-size');
491: case "ForeColor": return $this->GetCssStyle('color');
492: case "Opacity": return $this->GetCssStyle('opacity');
493: case "Cursor": return $this->GetCssStyle('cursor');
494: case "Height": return $this->GetCssStyle('height');
495: case "Width": return $this->GetCssStyle('width');
496: case "Overflow": return $this->GetCssStyle('overflow');
497: case "Position": return $this->GetCssStyle('position');
498: case "Top": return $this->GetCssStyle('top');
499: case "Left": return $this->GetCssStyle('left');
500: case "HorizontalAlign": return $this->GetCssStyle('text-align');
501: case "VerticalAlign": return $this->GetCssStyle('vertical-align');
502: case "Wrap": throw new Exception ("Wrap is deprecated. Use NoWrap instead");
503: case "NoWrap": return $this->GetCssStyle('white-space') == 'nowrap';
504: case "UnorderedListStyle": return $this->GetCssStyle('list-style-type');
505:
506: // Attributes
507: case "CssClass": return $this->GetHtmlAttribute('class');
508: case "AccessKey": return $this->GetHtmlAttribute('accesskey');
509: case "Enabled": return $this->GetHtmlAttribute('disabled') === null;
510: case "TabIndex": return $this->GetHtmlAttribute('tabindex');
511: case "ToolTip": return $this->GetHtmlAttribute('title');
512: case "ReadOnly": return $this->HasHtmlAttribute('readonly');
513: case "AltText": return $this->HasHtmlAttribute('alt');
514: case "OrderedListType": return $this->GetHtmlAttribute('type');
515:
516: default:
517: try {
518: return parent::__get($strName);
519: } catch (QCallerException $objExc) {
520: $objExc->IncrementOffset();
521: throw $objExc;
522: }
523: }
524: }
525:
526:
527: /**
528: * PHP magic method
529: *
530: * @param string $strName
531: * @param string $mixValue
532: *
533: * @return mixed
534: * @throws Exception|QCallerException|QInvalidCastException
535: */
536: public function __set($strName, $mixValue) {
537: switch ($strName) {
538: // Styles
539: case "BackColor":
540: try {
541: $this->SetCssStyle('background-color', QType::Cast($mixValue, QType::String));
542: break;
543: } catch (QInvalidCastException $objExc) {
544: $objExc->IncrementOffset();
545: throw $objExc;
546: }
547: case "BorderColor":
548: try {
549: $this->SetCssStyle('border-color', QType::Cast($mixValue, QType::String));
550: break;
551: } catch (QInvalidCastException $objExc) {
552: $objExc->IncrementOffset();
553: throw $objExc;
554: }
555: case "BorderStyle":
556: try {
557: $this->SetCssStyle('border-style', QType::Cast($mixValue, QType::String));
558: break;
559: } catch (QInvalidCastException $objExc) {
560: $objExc->IncrementOffset();
561: throw $objExc;
562: }
563: case "BorderWidth":
564: try {
565: $this->SetCssStyle('border-width', QType::Cast($mixValue, QType::String), true);
566: if (!$this->HasCssStyle ('border-style')) {
567: $this->SetCssStyle('border-style', 'solid');
568: }
569: break;
570: } catch (QInvalidCastException $objExc) {
571: $objExc->IncrementOffset();
572: throw $objExc;
573: }
574: case "BorderCollapse":
575: try {
576: $this->SetCssStyle('border-collapse', QType::Cast($mixValue, QType::String));
577: break;
578: } catch (QInvalidCastException $objExc) {
579: $objExc->IncrementOffset();
580: throw $objExc;
581: }
582:
583: case "Display": // QControl changes the meaning of this to a boolean
584: case "DisplayStyle":
585: if (is_bool($mixValue)) {
586: if ($mixValue) {
587: $this->RemoveCssStyle('display'); // do the default
588: }
589: else {
590: $this->SetCssStyle('display', QDisplayStyle::None);
591: }
592: } else {
593: try {
594: $this->SetCssStyle('display', QType::Cast($mixValue, QType::String));
595: break;
596: } catch (QInvalidCastException $objExc) {
597: $objExc->IncrementOffset();
598: throw $objExc;
599: }
600: }
601:
602: case "FontBold":
603: try {
604: $this->SetCssStyle('font-weight', QType::Cast($mixValue, QType::Boolean) ? 'bold' : null);
605: break;
606: } catch (QInvalidCastException $objExc) {
607: $objExc->IncrementOffset();
608: throw $objExc;
609: }
610:
611: case "FontItalic":
612: try {
613: $this->SetCssStyle('font-style', QType::Cast($mixValue, QType::Boolean) ? 'italic' : null);
614: break;
615: } catch (QInvalidCastException $objExc) {
616: $objExc->IncrementOffset();
617: throw $objExc;
618: }
619:
620: case "FontNames":
621: try {
622: $this->SetCssStyle('font-family', QType::Cast($mixValue, QType::String));
623: break;
624: } catch (QInvalidCastException $objExc) {
625: $objExc->IncrementOffset();
626: throw $objExc;
627: }
628:
629: case "FontOverline":
630: try {
631: $this->SetCssStyle('text-decoration', QType::Cast($mixValue, QType::Boolean) ? 'overline' : null);
632: break;
633: } catch (QInvalidCastException $objExc) {
634: $objExc->IncrementOffset();
635: throw $objExc;
636: }
637: case "FontStrikeout":
638: try {
639: $this->SetCssStyle('text-decoration', QType::Cast($mixValue, QType::Boolean) ? 'line-through' : null);
640: break;
641: } catch (QInvalidCastException $objExc) {
642: $objExc->IncrementOffset();
643: throw $objExc;
644: }
645: case "FontUnderline":
646: try {
647: $this->SetCssStyle('text-decoration', QType::Cast($mixValue, QType::Boolean) ? 'underline' : null);
648: break;
649: } catch (QInvalidCastException $objExc) {
650: $objExc->IncrementOffset();
651: throw $objExc;
652: }
653: case "FontSize":
654: try {
655: $this->SetCssStyle('font-size', QType::Cast($mixValue, QType::String), true);
656: break;
657: } catch (QInvalidCastException $objExc) {
658: $objExc->IncrementOffset();
659: throw $objExc;
660: }
661:
662: case "ForeColor":
663: try {
664: $this->SetCssStyle('color', QType::Cast($mixValue, QType::String));
665: break;
666: } catch (QInvalidCastException $objExc) {
667: $objExc->IncrementOffset();
668: throw $objExc;
669: }
670: case "Opacity":
671: try {
672: $mixValue = QType::Cast($mixValue, QType::Integer);
673: if (($mixValue < 0) || ($mixValue > 100)) {
674: throw new QCallerException('Opacity must be an integer value between 0 and 100');
675: }
676: $this->SetCssStyle('opacity', $mixValue);
677: break;
678: } catch (QInvalidCastException $objExc) {
679: $objExc->IncrementOffset();
680: throw $objExc;
681: }
682: case "Cursor":
683: try {
684: $this->SetCssStyle('cursor', QType::Cast($mixValue, QType::String));
685: break;
686: } catch (QInvalidCastException $objExc) {
687: $objExc->IncrementOffset();
688: throw $objExc;
689: }
690:
691: case "Height":
692: try {
693: $this->SetCssStyle('height', QType::Cast($mixValue, QType::String), true);
694: break;
695: } catch (QInvalidCastException $objExc) {
696: $objExc->IncrementOffset();
697: throw $objExc;
698: }
699:
700: case "Width":
701: try {
702: $this->SetCssStyle('width', QType::Cast($mixValue, QType::String), true);
703: break;
704: } catch (QInvalidCastException $objExc) {
705: $objExc->IncrementOffset();
706: throw $objExc;
707: }
708:
709: case "Overflow":
710: try {
711: $this->SetCssStyle('overflow', QType::Cast($mixValue, QType::String));
712: break;
713: } catch (QInvalidCastException $objExc) {
714: $objExc->IncrementOffset();
715: throw $objExc;
716: }
717: case "Position":
718: try {
719: $this->SetCssStyle('position', QType::Cast($mixValue, QType::String));
720: break;
721: } catch (QInvalidCastException $objExc) {
722: $objExc->IncrementOffset();
723: throw $objExc;
724: }
725: case "Top":
726: try {
727: $this->SetCssStyle('top', QType::Cast($mixValue, QType::String), true);
728: break;
729: } catch (QInvalidCastException $objExc) {
730: $objExc->IncrementOffset();
731: throw $objExc;
732: }
733: case "Left":
734: try {
735: $this->SetCssStyle('left', QType::Cast($mixValue, QType::String), true);
736: break;
737: } catch (QInvalidCastException $objExc) {
738: $objExc->IncrementOffset();
739: throw $objExc;
740: }
741: case "HorizontalAlign":
742: try {
743: $this->SetCssStyle('text-align', QType::Cast($mixValue, QType::String));
744: break;
745: } catch (QInvalidCastException $objExc) {
746: $objExc->IncrementOffset();
747: throw $objExc;
748: }
749: case "VerticalAlign":
750: try {
751: $this->SetCssStyle('vertical-align', QType::Cast($mixValue, QType::String));
752: break;
753: } catch (QInvalidCastException $objExc) {
754: $objExc->IncrementOffset();
755: throw $objExc;
756: }
757: case "Wrap": // Wrap is now an actual attribute. Original developer used Wrap instead of NoWrap, not anticipating future change to HTML
758: throw new QCallerException ("Wrap is deprecated. Use NoWrap instead");
759: break;
760:
761: case "NoWrap":
762: try {
763: $this->SetCssStyle('white-space', QType::Cast($mixValue, QType::Boolean) ? 'nowrap' : null);
764: break;
765: } catch (QInvalidCastException $objExc) {
766: $objExc->IncrementOffset();
767: throw $objExc;
768: }
769:
770: case "Padding": // top right bottom left
771: $this->SetCssBoxValue('padding', $mixValue);
772: break;
773:
774: case "Margin": // top right bottom left
775: $this->SetCssBoxValue('margin', $mixValue);
776: break;
777:
778: case "UnorderedListStyle":
779: try {
780: $this->SetCssStyle('list-style-type', QType::Cast($mixValue, QType::String));
781: break;
782: } catch (QInvalidCastException $objExc) {
783: $objExc->IncrementOffset();
784: throw $objExc;
785: }
786:
787: // Attributes
788: case "CssClass":
789: try {
790: $strCssClass = QType::Cast($mixValue, QType::String);
791: $this->SetCssClass($strCssClass);
792: break;
793: } catch (QInvalidCastException $objExc) {
794: $objExc->IncrementOffset();
795: throw $objExc;
796: }
797: case "AccessKey":
798: try {
799: $this->SetHtmlAttribute('accesskey', QType::Cast($mixValue, QType::String));
800: break;
801: } catch (QInvalidCastException $objExc) {
802: $objExc->IncrementOffset();
803: throw $objExc;
804: }
805: case "Enabled":
806: try {
807: $this->SetHtmlAttribute('disabled', QType::Cast($mixValue, QType::Boolean) ? null : 'disabled');
808: break;
809: } catch (QInvalidCastException $objExc) {
810: $objExc->IncrementOffset();
811: throw $objExc;
812: }
813:
814: /* case "Required": Not supported consistently by browsers. We handle this inhouse */
815:
816: case "TabIndex":
817: try {
818: $this->SetHtmlAttribute('tabindex', QType::Cast($mixValue, QType::String));
819: break;
820: } catch (QInvalidCastException $objExc) {
821: $objExc->IncrementOffset();
822: throw $objExc;
823: }
824: case "ToolTip":
825: try {
826: $this->SetHtmlAttribute('title', QType::Cast($mixValue, QType::String));
827: break;
828: } catch (QInvalidCastException $objExc) {
829: $objExc->IncrementOffset();
830: throw $objExc;
831: }
832:
833: case "Data":
834: try {
835: $dataArray = QType::Cast($mixValue, QType::ArrayType);
836: foreach ($dataArray as $key=>$value) {
837: $this->SetDataAttribute($key, $value);
838: }
839: break;
840: } catch (QInvalidCastException $objExc) {
841: $objExc->IncrementOffset();
842: throw $objExc;
843: }
844:
845: case "ReadOnly":
846: try {
847: $this->SetHtmlAttribute('readonly', QType::Cast($mixValue, QType::Boolean) ? 'readonly' : null);
848: break;
849: } catch (QInvalidCastException $objExc) {
850: $objExc->IncrementOffset();
851: throw $objExc;
852: }
853:
854: case "AltText":
855: try {
856: $this->SetHtmlAttribute('alt', QType::Cast($mixValue, QType::String));
857: break;
858: } catch (QInvalidCastException $objExc) {
859: $objExc->IncrementOffset();
860: throw $objExc;
861: }
862:
863: case "OrderedListType":
864: try {
865: $this->SetHtmlAttribute('type', QType::Cast($mixValue, QType::String));
866: break;
867: } catch (QInvalidCastException $objExc) {
868: $objExc->IncrementOffset();
869: throw $objExc;
870: }
871:
872: default:
873: try {
874: return parent::__set($strName, $mixValue);
875: } catch (QCallerException $objExc) {
876: $objExc->IncrementOffset();
877: throw $objExc;
878: }
879: }
880: return true;
881: }
882: }