1: <?php
2: /**
3: * This file contains the QCheckBox class.
4: *
5: * @package Controls
6: */
7:
8: /**
9: * This class will render an HTML Checkbox.
10: *
11: * Labels are a little tricky with checkboxes. There are two built-in ways to make labels:
12: * 1) Assign a Name property, and render using something like RenderWithName
13: * 2) Assign a Text property, in which case the checkbox will be wrapped with a label and the text you assign.
14: *
15: * @package Controls
16: *
17: * @property string $Text is used to display text that is displayed next to the checkbox. The text is rendered as an html "Label For" the checkbox.
18: * @property string $TextAlign specifies if "Text" should be displayed to the left or to the right of the checkbox.
19: * @property boolean $Checked specifices whether or not hte checkbox is checked
20: * @property boolean $HtmlEntities specifies whether the checkbox text will have to be run through htmlentities or not.
21: */
22: class QCheckBox extends QControl {
23: /** @var string Tag for rendering the control */
24: protected $strTag = 'input';
25: protected $blnIsVoidElement = true;
26:
27: // APPEARANCE
28: /** @var string Text opposite to the checkbox */
29: protected $strText = null;
30: /** @var QTextAlign|string the alignment of the string */
31: protected $strTextAlign = QTextAlign::Right;
32:
33: // BEHAVIOR
34: /** @var bool Should the htmlentities function be run on the control's text (strText)? */
35: protected $blnHtmlEntities = true;
36:
37: // MISC
38: /** @var bool Determines whether the checkbox is checked? */
39: protected $blnChecked = false;
40:
41: /**
42: * @var QTagStyler for labels of checkboxes. If side-by-side labeling, the styles will be applied to a
43: * span that wraps both the checkbox and the label.
44: */
45: protected $objLabelStyle;
46:
47:
48: //////////
49: // Methods
50: //////////
51:
52: /**
53: * Parses the Post Data submitted for the control and sets the values
54: * according to the data submitted
55: */
56: public function ParsePostData() {
57: $val = $this->objForm->CheckableControlValue($this->strControlId);
58: if ($val !== null) {
59: $this->blnChecked = QType::Cast($val, QType::Boolean);
60: }
61: }
62:
63: /**
64: * Returns the HTML code for the control which can be sent to the client.
65: *
66: * Note, previous version wrapped this in a div and made the control a block level control unnecessarily. To
67: * achieve a block control, set blnUseWrapper and blnIsBlockElement.
68: *
69: * @return string THe HTML for the control
70: */
71: protected function GetControlHtml() {
72: $attrOverride = array('type'=>'checkbox', 'name'=>$this->strControlId, 'value'=>'true');
73: return $this->RenderButton($attrOverride);
74: }
75:
76: /**
77: * Render the button code. Broken out to allow QRadioButton to use it too.
78: *
79: * @param $attrOverride
80: * @return string
81: */
82: protected function RenderButton ($attrOverride) {
83: if ($this->blnChecked) {
84: $attrOverride['checked']='checked';
85: }
86:
87: if (strlen($this->strText)) {
88: $strText = ($this->blnHtmlEntities) ? QApplication::HtmlEntities($this->strText) : $this->strText;
89: if (!$this->blnWrapLabel) {
90: $strLabelAttributes = ' for="' . $this->strControlId .'"';
91: } else {
92: $strLabelAttributes = $this->RenderLabelAttributes();
93: }
94: $strCheckHtml = QHtml::RenderLabeledInput(
95: $strText,
96: $this->strTextAlign == QTextAlign::Left,
97: $this->RenderHtmlAttributes($attrOverride),
98: $strLabelAttributes,
99: $this->blnWrapLabel
100: );
101: if (!$this->blnWrapLabel) {
102: // Additionally wrap in a span so we can associate the label with the checkbox visually and apply the styles
103: $strCheckHtml = QHtml::RenderTag('span', $this->RenderLabelAttributes(), $strCheckHtml);
104: }
105: }
106: else {
107: $strCheckHtml = $this->RenderTag('input', $attrOverride, null, null, true);
108: }
109: return $strCheckHtml;
110: }
111:
112: /**
113: * Return a styler to style the label that surrounds the control if the control has text.
114: * @return QTagStyler
115: */
116: public function getCheckLabelStyler() {
117: if (!$this->objLabelStyle) {
118: $this->objLabelStyle = new QTagStyler();
119: }
120: return $this->objLabelStyle;
121: }
122:
123: /**
124: * There is a little bit of a conundrum here. If there is text assigned to the checkbox, we wrap
125: * the checkbox in a label. However, in this situation, its unclear what to do with the class and style
126: * attributes that are for the checkbox. We are going to let the developer use the label styler to make
127: * it clear what their intentions are.
128: * @return string
129: */
130: protected function RenderLabelAttributes() {
131: $objStyler = new QTagStyler();
132: $attributes = $this->GetHtmlAttributes(null, null, ['title']); // copy tooltip to wrapping label
133: $objStyler->SetAttributes($attributes);
134: $objStyler->Override($this->getCheckLabelStyler());
135:
136: if (!$this->Enabled) {
137: $objStyler->AddCssClass('disabled'); // add the disabled class to the label for styling
138: }
139: if (!$this->Display) {
140: $objStyler->Display = false;
141: }
142: return $objStyler->RenderHtmlAttributes();
143: }
144:
145: /**
146: * Checks whether the post data submitted for the control is valid or not
147: * Right now it tests whether or not the control was marked as required and then tests whether it
148: * was checked or not
149: * @return bool
150: */
151: public function Validate() {
152: if ($this->blnRequired) {
153: if (!$this->blnChecked) {
154: if ($this->strName)
155: $this->ValidationError = QApplication::Translate($this->strName) . ' ' . QApplication::Translate('is required');
156: else
157: $this->ValidationError = QApplication::Translate('Required');
158: return false;
159: }
160: }
161: return true;
162: }
163:
164: /**
165: * Returns the current state of the control to be able to restore it later.
166: */
167: public function GetState(){
168: return array('checked'=>$this->Checked);
169: }
170:
171: /**
172: * Restore the state of the control.
173: *
174: * @param mixed $state
175: */
176: public function PutState($state) {
177: if (isset($state['checked'])) {
178: $this->Checked = $state['checked'];
179: }
180: }
181:
182: /////////////////////////
183: // Public Properties: GET
184: /////////////////////////
185: /**
186: * PHP __get magic method implementation
187: * @param string $strName Name of the property
188: *
189: * @return mixed
190: * @throws QCallerException
191: */
192: public function __get($strName) {
193: switch ($strName) {
194: // APPEARANCE
195: case "Text": return $this->strText;
196: case "TextAlign": return $this->strTextAlign;
197:
198: // BEHAVIOR
199: case "HtmlEntities": return $this->blnHtmlEntities;
200:
201: // MISC
202: case "Checked": return $this->blnChecked;
203: default:
204: try {
205: return parent::__get($strName);
206: } catch (QCallerException $objExc) {
207: $objExc->IncrementOffset();
208: throw $objExc;
209: }
210: }
211: }
212:
213: /////////////////////////
214: // Public Properties: SET
215: /////////////////////////
216: /**
217: * PHP __set magic method implementation
218: * @param string $strName
219: * @param string $mixValue
220: *
221: * @return mixed
222: * @throws QInvalidCastException|QCallerException
223: */
224: public function __set($strName, $mixValue) {
225: switch ($strName) {
226: // APPEARANCE
227:
228: case "Text":
229: try {
230: $val = QType::Cast($mixValue, QType::String);
231: if ($val !== $this->strText) {
232: $this->strText = $val;
233: $this->blnModified = true;
234: }
235: return $this->strText;
236: } catch (QInvalidCastException $objExc) {
237: $objExc->IncrementOffset();
238: throw $objExc;
239: }
240:
241: case "TextAlign":
242: try {
243: $val = QType::Cast($mixValue, QType::String);
244: if ($val !== $this->strTextAlign) {
245: $this->strTextAlign = $val;
246: $this->blnModified = true;
247: }
248: break;
249: } catch (QInvalidCastException $objExc) {
250: $objExc->IncrementOffset();
251: throw $objExc;
252: }
253:
254: case "HtmlEntities":
255: try {
256: $this->blnHtmlEntities = QType::Cast($mixValue, QType::Boolean);
257: break;
258: } catch (QInvalidCastException $objExc) {
259: $objExc->IncrementOffset();
260: throw $objExc;
261: }
262:
263: // MISC
264: case "Checked":
265: try {
266: $val = QType::Cast($mixValue, QType::Boolean);
267: if ($val != $this->blnChecked) {
268: $this->blnChecked = $val;
269: $this->AddAttributeScript('prop', 'checked', $val);
270: }
271: break;
272: } catch (QInvalidCastException $objExc) {
273: $objExc->IncrementOffset();
274: throw $objExc;
275: }
276:
277: // Copy certain attributes to the label styler when assigned since its part of the control.
278: case 'CssClass':
279: try {
280: parent::__set($strName, $mixValue);
281: $this->getCheckLabelStyler()->CssClass = $mixValue; // assign to both checkbox and label so they can be styled together using css
282: $this->blnModified = true;
283: break;
284: } catch (QInvalidCastException $objExc) {
285: $objExc->IncrementOffset();
286: throw $objExc;
287: }
288:
289: default:
290: try {
291: parent::__set($strName, $mixValue);
292: break;
293: } catch (QCallerException $objExc) {
294: $objExc->IncrementOffset();
295: throw $objExc;
296: }
297: }
298: }
299:
300: /**
301: * Returns an description of the options available to modify by the designer for the code generator.
302: *
303: * @return QModelConnectorParam[]
304: */
305: public static function GetModelConnectorParams() {
306: return array_merge(parent::GetModelConnectorParams(), array(
307: new QModelConnectorParam (get_called_class(), 'Text', 'Label on checkbox', QType::String),
308: new QModelConnectorParam (get_called_class(), 'TextAlign', 'Left or right alignment of label', QModelConnectorParam::SelectionList,
309: array ('QTextAlign::Right'=>'QTextAlign::Right',
310: 'QTextAlign::Left'=>'QTextAlign::Left'
311: )),
312: new QModelConnectorParam (get_called_class(), 'HtmlEntities', 'Whether to apply HTML entities on the label', QType::Boolean),
313: new QModelConnectorParam (get_called_class(), 'CssClass', 'The css class(es) to apply to the checkbox and label together', QType::String)
314: ));
315: }
316:
317:
318: }