PageRenderTime 77ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/jFormer/jformer.php

https://bitbucket.org/izubizarreta/https-bitbucket.org-bityvip
PHP | 4168 lines | 2973 code | 625 blank | 570 comment | 670 complexity | 9ceca5f435dbf0586b5ea75a08240d39 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.0, JSON, GPL-2.0, BSD-3-Clause, LGPL-2.1, MIT
  1. <?php
  2. class JFormElement {
  3. private $type;
  4. private $unaryTagArray = array('input', 'img', 'hr', 'br', 'meta', 'link');
  5. private $attributeArray;
  6. private $innerHtml;
  7. /**
  8. * Constructor
  9. *
  10. * @param <type> $type
  11. * @param <type> $attributeArray
  12. * @param <type> $unaryTagArray
  13. */
  14. public function __construct($type, $attributeArray = array()) {
  15. $this->type = strtolower($type);
  16. foreach ($attributeArray as $attribute => $value) {
  17. $this->setAttribute($attribute, $value);
  18. }
  19. return $this;
  20. }
  21. /**
  22. * Set an array, can pass an array or a key, value combination
  23. *
  24. * @param <type> $attribute
  25. * @param <type> $value
  26. */
  27. public function getAttribute($attribute) {
  28. return $this->attributeArray[$attribute];
  29. }
  30. function setAttribute($attribute, $value = '') {
  31. if (!is_array($attribute)) {
  32. $this->attributeArray[$attribute] = $value;
  33. } else {
  34. $this->attributeArray = array_merge($this->attributeArray, $attribute);
  35. }
  36. return $this;
  37. }
  38. function addToAttribute($attribute, $value = '') {
  39. if (isset($this->attributeArray[$attribute])) {
  40. $currentValue = $this->attributeArray[$attribute];
  41. } else {
  42. $currentValue = '';
  43. }
  44. $this->attributeArray[$attribute] = $currentValue . $value;
  45. return $this;
  46. }
  47. function addClassName($className) {
  48. $currentClasses = $this->getAttribute('class');
  49. // Check to see if the class is already added
  50. if (!strstr($currentClasses, $className)) {
  51. $newClasses = $currentClasses . ' ' . $className;
  52. $this->setAttribute('class', $newClasses);
  53. }
  54. }
  55. /**
  56. * Insert an element into the current element
  57. *
  58. * @param <type> $object
  59. */
  60. function insert($object) {
  61. if (@get_class($object) == __class__) {
  62. $this->innerHtml .= $object->build();
  63. } else {
  64. $this->innerHtml .= $object;
  65. }
  66. return $this;
  67. }
  68. /**
  69. * Set the innerHtml of an element
  70. *
  71. * @param <type> $object
  72. * @return <type>
  73. */
  74. function update($object) {
  75. $this->innerHtml = $object;
  76. return $this;
  77. }
  78. /**
  79. * Builds the element
  80. *
  81. * @return <type>
  82. */
  83. function build() {
  84. // Start the tag
  85. $element = '<' . $this->type;
  86. // Add attributes
  87. if (count($this->attributeArray)) {
  88. foreach ($this->attributeArray as $key => $value) {
  89. $element .= ' ' . $key . '="' . $value . '"';
  90. }
  91. }
  92. // Close the element
  93. if (!in_array($this->type, $this->unaryTagArray)) {
  94. $element.= '>' . $this->innerHtml . '</' . $this->type . '>';
  95. } else {
  96. $element.= ' />';
  97. }
  98. // Don't format the XML string, saves time
  99. //return $this->formatXmlString($element);
  100. return $element;
  101. }
  102. /**
  103. * Echoes out the element
  104. *
  105. * @return <type>
  106. */
  107. function __toString() {
  108. return $this->build();
  109. }
  110. }
  111. /**
  112. * A Form object
  113. */
  114. class JFormer {
  115. // General settings
  116. var $id;
  117. var $class = 'jFormer';
  118. var $action;
  119. var $style;
  120. var $jFormPageArray = array();
  121. var $jFormerId;
  122. var $onSubmitFunctionServerSide = 'onSubmit';
  123. var $disableAnalytics = false;
  124. var $setupPageScroller = true;
  125. var $data;
  126. // Title, description, and submission button
  127. var $title = '';
  128. var $titleClass = 'jFormerTitle';
  129. var $description = '';
  130. var $descriptionClass = 'jFormerDescription';
  131. var $submitButtonText = 'Submit';
  132. var $submitProcessingButtonText = 'Processing...';
  133. var $afterControl = '';
  134. // Form options
  135. var $alertsEnabled = true;
  136. var $clientSideValidation = true;
  137. var $debugMode = false;
  138. var $validationTips = true;
  139. // Page navigator
  140. var $pageNavigatorEnabled = false;
  141. var $pageNavigator = array();
  142. // Progress bar
  143. var $progressBar = false;
  144. // Splash page
  145. var $splashPageEnabled = false;
  146. var $splashPage = array();
  147. // Save state options
  148. var $saveStateEnabled = false;
  149. var $saveState = array();
  150. // Animations
  151. var $animationOptions = null;
  152. // Custom script execution before form submission
  153. var $onSubmitStartClientSide = '';
  154. var $onSubmitFinishClientSide = '';
  155. // Security options
  156. var $requireSsl = false; // Not implemented yet
  157. // Essential class variables
  158. var $status = array('status' => 'processing', 'response' => 'Form initialized.');
  159. // Validation
  160. var $jValidator;
  161. var $validationResponse = array();
  162. var $validationPassed = null;
  163. /**
  164. * Constructor
  165. */
  166. function __construct($id, $optionArray = array(), $jFormPageArray = array()) {
  167. // Set the id
  168. $this->id = $id;
  169. // Set the action dynamically
  170. $callingFile = debug_backtrace();
  171. $callingFile = $callingFile[0]['file'];
  172. $this->action = str_replace($_SERVER['DOCUMENT_ROOT'], '', $callingFile);
  173. // Use the options array to update the form variables
  174. if (is_array($optionArray)) {
  175. foreach ($optionArray as $option => $value) {
  176. $this->{$option} = $value;
  177. }
  178. }
  179. // Set defaults for the page navigator
  180. if (!empty($this->pageNavigator)) {
  181. $this->pageNavigatorEnabled = true;
  182. } else if ($this->pageNavigator == true) {
  183. $this->pageNavigator = array(
  184. 'position' => 'top'
  185. );
  186. }
  187. // Set defaults for the save state
  188. if (!empty($this->saveState)) {
  189. $this->saveStateEnabled = true;
  190. if (empty($this->saveState['showSavingAlert'])) {
  191. $this->saveState['showSavingAlert'] = true;
  192. }
  193. } else {
  194. $this->saveState = array(
  195. 'interval' => 30,
  196. 'showSavingAlert' => true,
  197. );
  198. }
  199. // Set defaults for the splash page
  200. if (!empty($this->splashPage)) {
  201. $this->splashPageEnabled = true;
  202. } else if ($this->saveStateEnabled == true) {
  203. $this->splashPage = array(
  204. 'content' => '',
  205. 'splashButtonText' => 'Begin'
  206. );
  207. }
  208. // Add the pages from the constructor
  209. foreach ($jFormPageArray as $jFormPage) {
  210. $this->addJFormPage($jFormPage);
  211. }
  212. return $this;
  213. }
  214. function addJFormPage($jFormPage) {
  215. $jFormPage->jFormer = $this;
  216. $this->jFormPageArray[$jFormPage->id] = $jFormPage;
  217. return $this;
  218. }
  219. function addJFormPages($jFormPages) {
  220. if (is_array($jFormPages)) {
  221. foreach ($jFormPages as $jFormPage) {
  222. $jFormPage->jFormer = $this;
  223. $this->jFormPageArray[$jFormPage->id] = $jFormPage;
  224. }
  225. }
  226. $jFormPage->jFormer = $this;
  227. $this->jFormPageArray[$jFormPage->id] = $jFormPage;
  228. return $this;
  229. }
  230. // Convenience method, no need to create a page or section to get components on the form
  231. function addJFormComponent($jFormComponent) {
  232. // Create an anonymous page if necessary
  233. if (empty($this->jFormPageArray)) {
  234. $this->addJFormPage(new JFormPage($this->id . '_page1', array('anonymous' => true)));
  235. }
  236. // Get the first page in the jFormPageArray
  237. $currentJFormPage = current($this->jFormPageArray);
  238. // Get the last section in the page
  239. $lastJFormSection = end($currentJFormPage->jFormSectionArray);
  240. // If the last section exists and is anonymous, add the component to it
  241. if (!empty($lastJFormSection) && $lastJFormSection->anonymous) {
  242. $lastJFormSection->addJFormComponent($jFormComponent);
  243. }
  244. // If the last section in the page does not exist or is not anonymous, add a new anonymous section and add the component to it
  245. else {
  246. // Create an anonymous section
  247. $anonymousSection = new JFormSection($currentJFormPage->id . '_section' . (sizeof($currentJFormPage->jFormSectionArray) + 1), array('anonymous' => true));
  248. // Add the anonymous section to the page
  249. $currentJFormPage->addJFormSection($anonymousSection->addJFormComponent($jFormComponent));
  250. }
  251. return $this;
  252. }
  253. function addJFormComponentArray($jFormComponentArray) {
  254. foreach ($jFormComponentArray as $jFormComponent) {
  255. $this->addJFormComponent($jFormComponent);
  256. }
  257. return $this;
  258. }
  259. // Convenience method, no need to create a to get a section on the form
  260. function addJFormSection($jFormSection) {
  261. // Create an anonymous page if necessary
  262. if (empty($this->jFormPageArray)) {
  263. $this->addJFormPage(new JFormPage($this->id . '_page1', array('anonymous' => true)));
  264. }
  265. // Get the first page in the jFormPageArray
  266. $currentJFormPage = current($this->jFormPageArray);
  267. // Add the section to the first page
  268. $currentJFormPage->addJFormSection($jFormSection);
  269. return $this;
  270. }
  271. function setStatus($status, $response) {
  272. $this->status = array('status' => $status, 'response' => $response);
  273. return $this->status;
  274. }
  275. function resetStatus() {
  276. $this->status = array('status' => 'processing', 'response' => 'Form status reset.');
  277. return $this->status;
  278. }
  279. function getStatus() {
  280. return $this->status;
  281. }
  282. function validate() {
  283. // Update the form status
  284. $this->setStatus('processing', 'Validating component values.');
  285. // Clear the validation response
  286. $this->validationResponse = array();
  287. // Validate each page
  288. foreach ($this->jFormPageArray as $jFormPage) {
  289. $this->validationResponse[$jFormPage->id] = $jFormPage->validate();
  290. }
  291. // Walk through all of the pages to see if there are any errors
  292. $this->validationPassed = true;
  293. foreach ($this->validationResponse as $jFormPageKey => $jFormPage) {
  294. foreach ($jFormPage as $jFormSectionKey => $jFormSection) {
  295. // If there are section instances
  296. if ($jFormSection != null && array_key_exists(0, $jFormSection) && is_array($jFormSection[0])) {
  297. foreach ($jFormSection as $jFormSectionInstanceIndex => $jFormSectionInstance) {
  298. foreach ($jFormSectionInstance as $jFormComponentKey => $jFormComponentErrorMessageArray) {
  299. // If there are component instances
  300. if ($jFormComponentErrorMessageArray != null && array_key_exists(0, $jFormComponentErrorMessageArray) && is_array($jFormComponentErrorMessageArray[0])) {
  301. foreach ($jFormComponentErrorMessageArray as $jFormComponentInstanceErrorMessageArray) {
  302. // If the first value is not empty, the component did not pass validation
  303. if (!empty($jFormComponentInstanceErrorMessageArray[0]) || sizeof($jFormComponentInstanceErrorMessageArray) > 1) {
  304. $this->validationPassed = false;
  305. }
  306. }
  307. } else {
  308. if (!empty($jFormComponentErrorMessageArray)) {
  309. $this->validationPassed = false;
  310. }
  311. }
  312. }
  313. }
  314. }
  315. // No section instances
  316. else {
  317. foreach ($jFormSection as $jFormComponentErrorMessageArray) {
  318. // Component instances
  319. if ($jFormComponentErrorMessageArray != null && array_key_exists(0, $jFormComponentErrorMessageArray) && is_array($jFormComponentErrorMessageArray[0])) {
  320. foreach ($jFormComponentErrorMessageArray as $jFormComponentInstanceErrorMessageArray) {
  321. // If the first value is not empty, the component did not pass validation
  322. if (!empty($jFormComponentInstanceErrorMessageArray[0]) || sizeof($jFormComponentInstanceErrorMessageArray) > 1) {
  323. $this->validationPassed = false;
  324. }
  325. }
  326. } else {
  327. if (!empty($jFormComponentErrorMessageArray)) {
  328. $this->validationPassed = false;
  329. }
  330. }
  331. }
  332. }
  333. }
  334. }
  335. // Update the form status
  336. $this->setStatus('processing', 'Validation complete.');
  337. return $this->validationResponse;
  338. }
  339. function getData() {
  340. $this->data = array();
  341. foreach ($this->jFormPageArray as $jFormPageKey => $jFormPage) {
  342. if (!$jFormPage->anonymous) {
  343. $this->data[$jFormPageKey] = $jFormPage->getData();
  344. } else {
  345. foreach ($jFormPage->jFormSectionArray as $jFormSectionKey => $jFormSection) {
  346. if (!$jFormSection->anonymous) {
  347. $this->data[$jFormSectionKey] = $jFormSection->getData();
  348. } else {
  349. foreach ($jFormSection->jFormComponentArray as $jFormComponentKey => $jFormComponent) {
  350. if (get_class($jFormComponent) != 'JFormComponentHtml') { // Don't include HTML components
  351. $this->data[$jFormComponentKey] = $jFormComponent->getValue();
  352. }
  353. }
  354. }
  355. }
  356. }
  357. }
  358. return json_decode(json_encode($this->data));
  359. }
  360. function setData($data, $fileArray = array()) {
  361. // Get the form data as an object, handle apache auto-add slashes on post requests
  362. $jFormerData = json_decode(urldecode($data));
  363. if (!is_object($jFormerData)) {
  364. $jFormerData = json_decode(urldecode(stripslashes($data)));
  365. }
  366. // Clear all of the component values
  367. $this->clearData();
  368. //print_r($jFormerData); exit();
  369. //print_r($fileArray);
  370. // Update the form status
  371. $this->setStatus('processing', 'Setting component values.');
  372. // Assign all of the received JSON values to the form
  373. foreach ($jFormerData as $jFormPageKey => $jFormPageData) {
  374. $this->jFormPageArray[$jFormPageKey]->setData($jFormPageData);
  375. }
  376. // Handle files
  377. if (!empty($fileArray)) {
  378. foreach ($fileArray as $jFormComponentId => $fileDataArray) {
  379. preg_match('/(-section([0-9])+)?(-instance([0-9])+)?:([A-Za-z0-9_-]+):([A-Za-z0-9_-]+)/', $jFormComponentId, $fileIdInfo);
  380. $jFormComponentId = str_replace($fileIdInfo[0], '', $jFormComponentId);
  381. $jFormPageId = $fileIdInfo[5];
  382. $jFormSectionId = $fileIdInfo[6];
  383. // Inside section instances
  384. if ($fileIdInfo[1] != null || ($fileIdInfo[1] == null && array_key_exists(0, $this->jFormPageArray[$jFormPageId]->jFormSectionArray[$jFormSectionId]->jFormComponentArray))) {
  385. // section instance
  386. // set the instance index
  387. if ($fileIdInfo[1] != null) {
  388. $jFormSectionInstanceIndex = $fileIdInfo[2] - 1;
  389. } else {
  390. // prime instance
  391. $jFormSectionInstanceIndex = 0;
  392. }
  393. // check to see if there is a component instance
  394. if ($fileIdInfo[3] != null || ($fileIdInfo[3] == null && is_array($this->jFormPageArray[$jFormPageId]->jFormSectionArray[$jFormSectionId]->jFormComponentArray[$jFormSectionInstanceIndex][$jFormComponentId]->value))) {
  395. // set the component instance index inside of a section instance
  396. if ($fileIdInfo[3] == null) {
  397. $jFormComponentInstanceIndex = 0;
  398. } else {
  399. $jFormComponentInstanceIndex = $fileIdInfo[4] - 1;
  400. }
  401. // set the value with a section and a component instance
  402. $this->jFormPageArray[$jFormPageId]->jFormSectionArray[$jFormSectionId]->jFormComponentArray[$jFormSectionInstanceIndex][$jFormComponentId]->value[$jFormComponentInstanceIndex] = $fileDataArray;
  403. } else {
  404. // set the value with a section instance
  405. $this->jFormPageArray[$jFormPageId]->jFormSectionArray[$jFormSectionId]->jFormComponentArray[$jFormSectionInstanceIndex][$jFormComponentId]->value = $fileDataArray;
  406. }
  407. }
  408. // Not section instances
  409. else {
  410. // has component instances
  411. if ($fileIdInfo[3] != null || ($fileIdInfo[3] == null && is_array($this->jFormPageArray[$jFormPageId]->jFormSectionArray[$jFormSectionId]->jFormComponentArray[$jFormComponentId]->value))) {
  412. // set component instance index
  413. if ($fileIdInfo[3] == null) {
  414. $jFormComponentInstanceIndex = 0;
  415. } else {
  416. $jFormComponentInstanceIndex = $fileIdInfo[4] - 1;
  417. }
  418. $this->jFormPageArray[$jFormPageId]->jFormSectionArray[$jFormSectionId]->jFormComponentArray[$jFormComponentId]->value[$jFormComponentInstanceIndex] = $fileDataArray;
  419. } else {
  420. // no instances
  421. $this->jFormPageArray[$jFormPageId]->jFormSectionArray[$jFormSectionId]->jFormComponentArray[$jFormComponentId]->value = $fileDataArray;
  422. }
  423. }
  424. }
  425. }
  426. return $this;
  427. }
  428. function clearData() {
  429. foreach ($this->jFormPageArray as $jFormPage) {
  430. $jFormPage->clearData();
  431. }
  432. $this->data = null;
  433. }
  434. function clearAllComponentValues() {
  435. // Clear all of the components in the form
  436. foreach ($this->jFormPageArray as $jFormPage) {
  437. foreach ($jFormPage->jFormSectionArray as $jFormSection) {
  438. foreach ($jFormSection->jFormComponentArray as $jFormComponent) {
  439. $jFormComponent->value = null;
  440. }
  441. }
  442. }
  443. }
  444. function selectJFormComponent($jFormComponentId) {
  445. foreach ($this->jFormPageArray as $jFormPageKey => $jFormPage) {
  446. foreach ($jFormPage->jFormSectionArray as $jFormSectionKey => $jFormSection) {
  447. foreach ($jFormSection->jFormComponentArray as $jFormComponentKey => $jFormComponent) {
  448. if ($jFormComponentId == $jFormComponentKey) {
  449. return $jFormComponent;
  450. }
  451. }
  452. }
  453. }
  454. return false;
  455. }
  456. public function initializeSaveState($username, $password, $formState, $formData) {
  457. // Make sure we have a table to work with
  458. $this->createSaveStateTable();
  459. $_SESSION[$this->id]['saveState']['username'] = $username;
  460. $_SESSION[$this->id]['saveState']['password'] = $password;
  461. // Either create a new form or resume an old one
  462. if ($formState == 'newForm') {
  463. // Check to see if the form state exists already
  464. $response = $this->getSavedState();
  465. if ($response['status'] == 'failure') {
  466. $response = $this->createSaveState($formData);
  467. } else {
  468. $response['status'] = 'exists';
  469. $response['response'] = array('failureNoticeHtml' => 'Form already exists. Either choose to resume the form, or enter a different password to create a new form.');
  470. }
  471. } else if ($formState == 'resumeForm') {
  472. $response = $this->getSavedState();
  473. }
  474. return $response;
  475. }
  476. public function createSaveState($formData) {
  477. // Make sure we have a table to work with
  478. $this->createSaveStateTable();
  479. // Connect to the database using the form settings
  480. $mysqli = new mysqli($this->saveState['database']['host'], $this->saveState['database']['username'], $this->saveState['database']['password'], $this->saveState['database']['database']);
  481. $sql = 'INSERT INTO `' . $this->saveState['database']['table'] . '` (`username`, `password`, `form`, `time_added`) VALUES (\'' . $_SESSION[$this->id]['saveState']['username'] . '\', MD5(\'' . $_SESSION[$this->id]['saveState']['password'] . '\'), \'' . $formData . '\', NOW())';
  482. $query = $mysqli->prepare($sql);
  483. if (is_object($query)) {
  484. $query->execute();
  485. } else {
  486. $debug = debug_backtrace();
  487. die("Error when preparing statement. Call came from {$debug[1]['function']} on line {$debug[1]['line']} in {$debug[1]['file']}.\n<br /><br />{$mysqli->error}:\n<br /><br />" . $sql);
  488. }
  489. if ($query->errno) {
  490. $response = array("status" => "failure", "response" => $query->error, "sql" => $sql);
  491. } else {
  492. // Send a save state link
  493. $this->sendSaveStateLink();
  494. $response = array('status' => 'success', "response" => 'Successfully created a new form state.');
  495. }
  496. return $response;
  497. }
  498. public function sendSaveStateLink() {
  499. // Short circuit if they don't have the e-mail options set
  500. if (!isset($this->saveState['email'])) {
  501. return false;
  502. }
  503. // Set the form headers
  504. $headers = 'From: ' . $this->saveState['email']['fromName'] . ' <' . $this->saveState['email']['fromEmail'] . '>' . "\r\n" . 'X-Mailer: PHP/' . phpversion();
  505. // Set the subject
  506. $subject = $this->saveState['email']['subject'];
  507. // Set the e-mail and replace [formUrl] with the real form URL
  508. $message = str_replace('[formUrl]', $this->saveState['email']['formUrl'], $this->saveState['email']['message']);
  509. // Send the message
  510. if (mail($_SESSION[$this->id]['saveState']['username'], $subject, $message, $headers)) {
  511. return true;
  512. } else {
  513. return false;
  514. }
  515. }
  516. public function saveState($formData) {
  517. // Make sure we have a table to work with
  518. $this->createSaveStateTable();
  519. // Connect to the database using the form settings
  520. $mysqli = new mysqli($this->saveState['database']['host'], $this->saveState['database']['username'], $this->saveState['database']['password'], $this->saveState['database']['database']);
  521. $sql = 'UPDATE `' . $this->saveState['database']['table'] . '` SET `form` = \'' . $formData . '\', `time_updated` = NOW() WHERE `username` = \'' . $_SESSION[$this->id]['saveState']['username'] . '\' AND `password` = MD5(\'' . $_SESSION[$this->id]['saveState']['password'] . '\')';
  522. $query = $mysqli->prepare($sql);
  523. if (is_object($query)) {
  524. $query->execute();
  525. } else {
  526. $debug = debug_backtrace();
  527. die("Error when preparing statement. Call came from {$debug[1]['function']} on line {$debug[1]['line']} in {$debug[1]['file']}.\n<br /><br />{$mysqli->error}:\n<br /><br />" . $sql);
  528. }
  529. if ($query->errno) {
  530. $response = array("status" => "failure", "response" => $query->error, "sql" => $sql);
  531. } else {
  532. $response = array('status' => 'success', "response" => 'Successfully updated the form state.');
  533. }
  534. return $response;
  535. }
  536. public function getSavedState() {
  537. // Connect to the database
  538. $mysqli = new mysqli($this->saveState['database']['host'], $this->saveState['database']['username'], $this->saveState['database']['password'], $this->saveState['database']['database']);
  539. // Get the saved state from the appropriate table
  540. $sql = 'SELECT * FROM `' . $this->saveState['database']['table'] . '` WHERE `username` = \'' . $_SESSION[$this->id]['saveState']['username'] . '\' AND `password` = MD5(\'' . $_SESSION[$this->id]['saveState']['password'] . '\')';
  541. $query = $mysqli->prepare($sql);
  542. if (is_object($query)) {
  543. $query->execute();
  544. } else {
  545. $debug = debug_backtrace();
  546. die("Error when preparing statement. Call came from {$debug[1]['function']} on line {$debug[1]['line']} in {$debug[1]['file']}.\n<br /><br />{$mysqli->error}:\n<br /><br />" . $sql);
  547. }
  548. $query->store_result();
  549. if ($query->errno) {
  550. $response = array("status" => "failure", "response" => $query->error, "sql" => $sql);
  551. } else if ($query->num_rows == 0) {
  552. $response = array("status" => "failure", "response" => array('failureNoticeHtml' => 'No form exists for that username and password combination. Try again or start a new form.'));
  553. } else {
  554. $resultArray = array();
  555. for ($i = 0; $i < $query->num_rows(); $i++) {
  556. $resultArray[$i] = array();
  557. $boundedVariables = array();
  558. $meta = $query->result_metadata();
  559. while ($column = $meta->fetch_field()) {
  560. $resultArray[$i][$column->name] = null;
  561. $boundedVariables[] = &$resultArray[$i][$column->name];
  562. }
  563. call_user_func_array(array($query, 'bind_result'), $boundedVariables);
  564. $query->fetch();
  565. }
  566. foreach ($resultArray as &$result) {
  567. foreach ($result as &$value) {
  568. if (Utility::isJson($value)) {
  569. $value = json_decode($value);
  570. } else if (Utility::isJson(urldecode($value))) {
  571. $value = json_decode(urldecode($value));
  572. }
  573. }
  574. $result = json_decode(json_encode($result));
  575. }
  576. //print_r($result);
  577. $response = array("status" => "success", "response" => $result->form);
  578. }
  579. return $response;
  580. }
  581. public function createSaveStateTable() {
  582. $mysqli = new mysqli($this->saveState['database']['host'], $this->saveState['database']['username'], $this->saveState['database']['password'], $this->saveState['database']['database']);
  583. $sql = '
  584. CREATE TABLE IF NOT EXISTS `' . $this->saveState['database']['table'] . '` (
  585. `id` int(11) NOT NULL AUTO_INCREMENT,
  586. `username` varchar(64) NOT NULL,
  587. `password` varchar(32) NOT NULL,
  588. `form` text,
  589. `time_updated` datetime,
  590. `time_added` datetime,
  591. PRIMARY KEY(`id`),
  592. INDEX `' . $this->saveState['database']['table'] . '_index`(`id`, `username`, `password`)
  593. )
  594. ENGINE=MYISAM
  595. ROW_FORMAT=default
  596. ';
  597. $query = $mysqli->prepare($sql);
  598. if (is_object($query)) {
  599. $query->execute();
  600. } else {
  601. $debug = debug_backtrace();
  602. die("Error when preparing statement. Call came from {$debug[1]['function']} on line {$debug[1]['line']} in {$debug[1]['file']}.\n<br /><br />{$mysqli->error}:\n<br /><br />" . $sql);
  603. }
  604. $query->store_result();
  605. if ($query->errno) {
  606. $response = array("status" => "failure", "response" => $query->error, "sql" => $sql);
  607. } else {
  608. $response = array("status" => "success", "response" => 'Table `' . $this->saveState['database']['table'] . '` created successfully.');
  609. }
  610. return $response;
  611. }
  612. function saveToSession($callbackFunctionName) {
  613. // Patch the callback function into $this
  614. $this->jFormerId = $this->id . uniqid();
  615. $_SESSION[$this->jFormerId] = $this;
  616. return $this;
  617. }
  618. function processRequest($silent = false) {
  619. // Are they trying to post a file that is too large?
  620. if (isset($_SERVER['CONTENT_LENGTH']) && empty($_POST)) {
  621. $this->setStatus('success', array('failureNoticeHtml' => 'Your request (' . round($_SERVER['CONTENT_LENGTH'] / 1024 / 1024, 1) . 'M) was too large for the server to handle. ' . ini_get('post_max_size') . ' is the maximum request size.'));
  622. echo '
  623. <script type="text/javascript" language="javascript">
  624. parent.' . $this->id . 'Object.handleFormSubmissionResponse(' . json_encode($this->getStatus()) . ');
  625. </script>
  626. ';
  627. exit();
  628. }
  629. // Are they trying to post something to the form?
  630. if (isset($_POST['jFormer']) && $this->id == $_POST['jFormerId'] || isset($_POST['jFormerTask'])) {
  631. // Process the form, get the form state, or display the form
  632. if (isset($_POST['jFormer'])) {
  633. //echo json_encode($_POST);
  634. $onSubmitErrorMessageArray = array();
  635. // Set the form components and validate the form
  636. $this->setData($_POST['jFormer'], $_FILES);
  637. //print_r($this->getData());
  638. // Run validation
  639. $this->validate();
  640. if (!$this->validationPassed) {
  641. $this->setStatus('failure', array('validationFailed' => $this->validationResponse));
  642. } else {
  643. try {
  644. $onSubmitResponse = call_user_func($this->onSubmitFunctionServerSide, $this->getData());
  645. } catch (Exception $exception) {
  646. $onSubmitErrorMessageArray[] = $exception->getTraceAsString();
  647. }
  648. // Make sure you actually get a callback response
  649. if (empty($onSubmitResponse)) {
  650. $onSubmitErrorMessageArray[] = '<p>The function <b>' . $this->onSubmitFunctionServerSide . '</b> did not return a valid response.</p>';
  651. }
  652. // If there are no errors, it is a successful response
  653. if (empty($onSubmitErrorMessageArray)) {
  654. $this->setStatus('success', $onSubmitResponse);
  655. } else {
  656. $this->setStatus('failure', array('failureHtml' => $onSubmitErrorMessageArray));
  657. }
  658. }
  659. echo '
  660. <script type="text/javascript" language="javascript">
  661. parent.' . $this->id . 'Object.handleFormSubmissionResponse(' . json_encode($this->getStatus()) . ');
  662. </script>
  663. ';
  664. //echo json_encode($this->getValues());
  665. exit();
  666. }
  667. // Get the form's status
  668. else if (isset($_POST['jFormerTask']) && $_POST['jFormerTask'] == 'getFormStatus') {
  669. $onSubmitResponse = $this->getStatus();
  670. echo json_encode($onSubmitResponse);
  671. $this->resetStatus();
  672. exit();
  673. }
  674. // Set the save state username and password
  675. else if (isset($_POST['jFormerTask']) && $_POST['jFormerTask'] == 'initializeSaveState') {
  676. echo json_encode($this->initializeSaveState($_POST['identifier'], $_POST['password'], $_POST['formState'], $_POST['formData']));
  677. exit();
  678. }
  679. // Get the saved state
  680. else if (isset($_POST['jFormerTask']) && $_POST['jFormerTask'] == 'getSavedState') {
  681. echo json_encode($this->getSavedState($this->saveState['identifier'], $this->saveState['password']));
  682. exit();
  683. }
  684. // Save the current form state
  685. else if (isset($_POST['jFormerTask']) && $_POST['jFormerTask'] == 'saveState') {
  686. echo json_encode($this->saveState($_POST['formData']));
  687. exit();
  688. }
  689. }
  690. // If they aren't trying to post something to the form
  691. else if (!$silent) {
  692. $this->outputHtml();
  693. }
  694. }
  695. function getOptions() {
  696. $options = array();
  697. $options['options'] = array();
  698. $options['jFormPages'] = array();
  699. // Get all of the pages
  700. foreach ($this->jFormPageArray as $jFormPage) {
  701. $options['jFormPages'][$jFormPage->id] = $jFormPage->getOptions();
  702. }
  703. // Set form options
  704. if (!$this->clientSideValidation) {
  705. $options['options']['clientSideValidation'] = $this->clientSideValidation;
  706. }
  707. if ($this->debugMode) {
  708. $options['options']['debugMode'] = $this->debugMode;
  709. }
  710. if (!$this->validationTips) {
  711. $options['options']['validationTips'] = $this->validationTips;
  712. }
  713. if ($this->disableAnalytics) {
  714. $options['options']['disableAnalytics'] = $this->disableAnalytics;
  715. }
  716. if (!$this->setupPageScroller) {
  717. $options['options']['setupPageScroller'] = $this->setupPageScroller;
  718. }
  719. if ($this->animationOptions !== null) {
  720. $options['options']['animationOptions'] = $this->animationOptions;
  721. }
  722. if ($this->pageNavigatorEnabled) {
  723. $options['options']['pageNavigator'] = $this->pageNavigator;
  724. }
  725. if ($this->saveStateEnabled) {
  726. $options['options']['saveState'] = $this->saveState;
  727. // Don't give your database login out in the options
  728. unset($options['options']['saveState']['database']);
  729. }
  730. if ($this->splashPageEnabled) {
  731. $options['options']['splashPage'] = $this->splashPage;
  732. unset($options['options']['splashPage']['content']);
  733. }
  734. if (!empty($this->onSubmitStartClientSide)) {
  735. $options['options']['onSubmitStart'] = $this->onSubmitStartClientSide;
  736. }
  737. if (!empty($this->onSubmitFinishClientSide)) {
  738. $options['options']['onSubmitFinish'] = $this->onSubmitFinishClientSide;
  739. }
  740. if (!$this->alertsEnabled) {
  741. $options['options']['alertsEnabled'] = false;
  742. }
  743. if ($this->submitButtonText != 'Submit') {
  744. $options['options']['submitButtonText'] = $this->submitButtonText;
  745. }
  746. if ($this->submitProcessingButtonText != 'Processing...') {
  747. $options['options']['submitProcessingButtonText'] = $this->submitProcessingButtonText;
  748. }
  749. if ($this->progressBar) {
  750. $options['options']['progressBar'] = $this->progressBar;
  751. }
  752. if (empty($options['options'])) {
  753. unset($options['options']);
  754. }
  755. return $options;
  756. }
  757. function outputHtml() {
  758. echo $this->getHtml();
  759. }
  760. function __toString() {
  761. $element = $this->getHtml();
  762. return $element->__toString();
  763. }
  764. function getHtml() {
  765. // Create the form
  766. $formElement = new JFormElement('form', array(
  767. 'id' => $this->id,
  768. 'target' => $this->id . '-iframe',
  769. 'enctype' => 'multipart/form-data',
  770. 'method' => 'post',
  771. 'class' => $this->class,
  772. 'action' => $this->action,
  773. ));
  774. // Set the style
  775. if (!empty($this->style)) {
  776. $formElement->addToAttribute('style', $this->style);
  777. }
  778. // Global messages
  779. if ($this->alertsEnabled) {
  780. $jFormerAlertWrapperDiv = new JFormElement('div', array(
  781. 'class' => 'jFormerAlertWrapper',
  782. 'style' => 'display: none;',
  783. ));
  784. $alertDiv = new JFormElement('div', array(
  785. 'class' => 'jFormerAlert',
  786. ));
  787. $jFormerAlertWrapperDiv->insert($alertDiv);
  788. $formElement->insert($jFormerAlertWrapperDiv);
  789. }
  790. // If a splash is enabled
  791. if ($this->splashPageEnabled || $this->saveStateEnabled) {
  792. // Create a splash page div
  793. $splashPageDiv = new JFormElement('div', array(
  794. 'id' => $this->id . '-splash-page',
  795. 'class' => 'jFormerSplashPage jFormPage',
  796. ));
  797. // Set defaults if they aren't set
  798. if (!isset($this->splashPage['content'])) {
  799. $this->splashPage['content'] = '';
  800. }
  801. if (!isset($this->splashPage['splashButtonText'])) {
  802. $this->splashPage['splashButtonText'] = 'Begin';
  803. }
  804. $splashPageDiv->insert('<div class="jFormerSplashPageContent">' . $this->splashPage['content'] . '</div>');
  805. // If the form can be saved, show the necessary components
  806. if ($this->saveStateEnabled) {
  807. $saveStateIdentifier = new jFormComponentSingleLineText('saveStateIdentifier', 'E-mail address:', array(
  808. 'tip' => '<p>We will send form results to this e-mail address.</p>',
  809. 'validationOptions' => array('required', 'email'),
  810. ));
  811. $saveStateStatus = new jFormComponentMultipleChoice('saveStateStatus', 'Starting a new form?',
  812. array(
  813. array('value' => 'newForm', 'label' => 'Yes, let me start a new form', 'checked' => true),
  814. array('value' => 'resumeForm', 'label' => 'No, I want to continue a previous form'),
  815. ),
  816. array(
  817. 'multipleChoiceType' => 'radio',
  818. 'validationOptions' => array('required'),
  819. )
  820. );
  821. $saveStatePassword = new jFormComponentSingleLineText('saveStatePassword', 'Create password:', array(
  822. 'type' => 'password',
  823. 'tip' => '<p>Use this to come back and resume your form.</p>',
  824. 'showPasswordStrength' => true,
  825. 'validationOptions' => array('required', 'password'),
  826. ));
  827. // Add the components to the class save state variable
  828. $this->saveState['components'] = array($saveStateIdentifier->id => $saveStateIdentifier->getOptions(), $saveStateStatus->id => $saveStateStatus->getOptions(), $saveStatePassword->id => $saveStatePassword->getOptions());
  829. $splashPageDiv->insert($saveStateIdentifier->__toString() . $saveStateStatus->__toString() . $saveStatePassword->__toString());
  830. }
  831. // Create a splash button if there is no custom button ID
  832. if (!isset($this->splashPage['customButtonId'])) {
  833. $splashLi = new JFormElement('li', array('class' => 'splashLi'));
  834. $splashButton = new JFormElement('button', array('class' => 'splashButton'));
  835. $splashButton->update($this->splashPage['splashButtonText']);
  836. $splashLi->insert($splashButton);
  837. }
  838. }
  839. // Add a title to the form
  840. if (!empty($this->title)) {
  841. $title = new JFormElement('div', array(
  842. 'class' => $this->titleClass
  843. ));
  844. $title->update($this->title);
  845. $formElement->insert($title);
  846. }
  847. // Add a description to the form
  848. if (!empty($this->description)) {
  849. $description = new JFormElement('div', array(
  850. 'class' => $this->descriptionClass
  851. ));
  852. $description->update($this->description);
  853. $formElement->insert($description);
  854. }
  855. // Add the page navigator if enabled
  856. if ($this->pageNavigatorEnabled) {
  857. $pageNavigatorDiv = new JFormElement('div', array(
  858. 'class' => 'jFormPageNavigator',
  859. ));
  860. if (isset($this->pageNavigator['position']) && $this->pageNavigator['position'] == 'right') {
  861. $pageNavigatorDiv->addToAttribute('class', ' jFormPageNavigatorRight');
  862. } else {
  863. $pageNavigatorDiv->addToAttribute('class', ' jFormPageNavigatorTop');
  864. }
  865. $pageNavigatorUl = new JFormElement('ul', array(
  866. ));
  867. $jFormPageArrayCount = 0;
  868. foreach ($this->jFormPageArray as $jFormPageKey => $jFormPage) {
  869. $jFormPageArrayCount++;
  870. $pageNavigatorLabel = new JFormElement('li', array(
  871. 'id' => 'navigatePage' . $jFormPageArrayCount,
  872. 'class' => 'jFormPageNavigatorLink',
  873. ));
  874. // If the label is numeric
  875. if (isset($this->pageNavigator['label']) && $this->pageNavigator['label'] == 'numeric') {
  876. $pageNavigatorLabelText = 'Page ' . $jFormPageArrayCount;
  877. } else {
  878. // Add a link prefix if there is a title
  879. if (!empty($jFormPage->title)) {
  880. $pageNavigatorLabelText = '<span class="jFormNavigatorLinkPrefix">' . $jFormPageArrayCount . '</span> ' . strip_tags($jFormPage->title);
  881. } else {
  882. $pageNavigatorLabelText = 'Page ' . $jFormPageArrayCount;
  883. }
  884. }
  885. $pageNavigatorLabel->update($pageNavigatorLabelText);
  886. if ($jFormPageArrayCount != 1) {
  887. $pageNavigatorLabel->addToAttribute('class', ' jFormPageNavigatorLinkLocked');
  888. } else {
  889. $pageNavigatorLabel->addToAttribute('class', ' jFormPageNavigatorLinkUnlocked jFormPageNavigatorLinkActive');
  890. }
  891. $pageNavigatorUl->insert($pageNavigatorLabel);
  892. }
  893. // Add the page navigator ul to the div
  894. $pageNavigatorDiv->insert($pageNavigatorUl);
  895. // Add the progress bar if it is enabled
  896. if ($this->progressBar) {
  897. $pageNavigatorDiv->insert('<div class="jFormerProgress"><div class="jFormerProgressBar"></div></div>');
  898. }
  899. // Hide the progress bar if there is a splash page
  900. if ($this->splashPageEnabled) {
  901. $pageNavigatorDiv->addToAttribute('style', 'display: none;');
  902. }
  903. $formElement->insert($pageNavigatorDiv);
  904. }
  905. // Add the jFormerControl UL
  906. $jFormerControlUl = new JFormElement('ul', array(
  907. 'class' => 'jFormerControl',
  908. ));
  909. // Create the previous button
  910. $previousButtonLi = new JFormElement('li', array('class' => 'previousLi', 'style' => 'display: none;'));
  911. $previousButton = new JFormElement('button', array('class' => 'previousButton'));
  912. $previousButton->update('Previous');
  913. $previousButtonLi->insert($previousButton);
  914. // Create the next button
  915. $nextButtonLi = new JFormElement('li', array('class' => 'nextLi'));
  916. $nextButton = new JFormElement('button', array('class' => 'nextButton'));
  917. $nextButton->update($this->submitButtonText);
  918. // Don't show the next button
  919. if ($this->splashPageEnabled || $this->saveStateEnabled) {
  920. $nextButtonLi->setAttribute('style', 'display: none;');
  921. }
  922. $nextButtonLi->insert($nextButton);
  923. // Add a splash page button if it exists
  924. if (isset($splashLi)) {
  925. $jFormerControlUl->insert($splashLi);
  926. }
  927. // Add the previous and next buttons
  928. $jFormerControlUl->insert($previousButtonLi . $nextButtonLi);
  929. // Create the page wrapper and scrollers
  930. $jFormPageWrapper = new JFormElement('div', array('class' => 'jFormPageWrapper'));
  931. $jFormPageScroller = new JFormElement('div', array('class' => 'jFormPageScroller'));
  932. // Add a splash page if it exists
  933. if (isset($splashPageDiv)) {
  934. $jFormPageScroller->insert($splashPageDiv);
  935. }
  936. // Add the form pages to the form
  937. $jFormPageCount = 0;
  938. foreach ($this->jFormPageArray as $jFormPage) {
  939. // Hide everything but the first page
  940. if ($jFormPageCount != 0 || ($jFormPageCount == 0 && ($this->splashPageEnabled || $this->saveStateEnabled))) {
  941. $jFormPage->style .= 'display: none;';
  942. }
  943. $jFormPageScroller->insert($jFormPage);
  944. $jFormPageCount++;
  945. }
  946. // Page wrapper wrapper
  947. $pageWrapperContainer = new JFormElement('div', array('class' => 'jFormWrapperContainer'));
  948. // Insert the page wrapper and the jFormerControl UL to the form
  949. $formElement->insert($pageWrapperContainer->insert($jFormPageWrapper->insert($jFormPageScroller) . $jFormerControlUl));
  950. // Create a script tag to initialize jFormer JavaScript
  951. $script = new JFormElement('script', array(
  952. 'type' => 'text/javascript',
  953. 'language' => 'javascript'
  954. ));
  955. // Update the script tag
  956. $script->update('$(document).ready(function () { ' . $this->id . 'Object = new JFormer(\'' . $this->id . '\', ' . json_encode($this->getOptions()) . '); });');
  957. $formElement->insert($script);
  958. // Add a hidden iframe to handle the form posts
  959. $iframe = new JFormElement('iframe', array(
  960. 'id' => $this->id . '-iframe',
  961. 'name' => $this->id . '-iframe',
  962. 'class' => 'jFormerIFrame',
  963. 'frameborder' => 0,
  964. 'src' => '/empty.html',
  965. //'src' => str_replace($_SERVER['DOCUMENT_ROOT'], '', __FILE__).'?iframe=true',
  966. ));
  967. if ($this->debugMode) {
  968. $iframe->addToAttribute('style', 'display:block;');
  969. }
  970. $formElement->insert($iframe);
  971. // After control
  972. if (!empty($this->afterControl)) {
  973. $subSubmitInstructions = new JFormElement('div', array('class' => 'jFormerAfterControl'));
  974. $subSubmitInstructions->update($this->afterControl);
  975. $formElement->insert($subSubmitInstructions);
  976. }
  977. return $formElement;
  978. }
  979. static function formValuesToHtml($formValues) {
  980. $div = new JFormElement('div', array(
  981. 'style' => 'font-family: Arial, san-serif;'
  982. ));
  983. foreach ($formValues as $pageKey => $section) {
  984. $div->insert('<h1>' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($pageKey)) . '</h1>');
  985. foreach ($section as $sectionKey => $sectionValue) {
  986. // If the sectionValue is an array (instances)
  987. if (is_array($sectionValue)) {
  988. $div->insert('<h2>' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($sectionKey)) . ' (' . sizeof($sectionValue) . ' total)</h2>');
  989. foreach ($sectionValue as $sectionInstanceIndex => $section) {
  990. $div->insert('<h2>(' . ($sectionInstanceIndex + 1) . ') ' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($sectionKey)) . '</h2>');
  991. $div->insert(JFormer::sectionFormValuesToHtml($section));
  992. }
  993. } else {
  994. $div->insert('<h2>' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($sectionKey)) . '</h2>');
  995. $div->insert(JFormer::sectionFormValuesToHtml($sectionValue));
  996. }
  997. }
  998. }
  999. return $div;
  1000. }
  1001. static function sectionFormValuesToHtml($sectionFormValues) {
  1002. $div = new JFormElement('div');
  1003. foreach ($sectionFormValues as $componentKey => $componentValue) {
  1004. if (is_object($componentValue) || is_array($componentValue)) {
  1005. // If the component value is an array (instances)
  1006. if (is_array($componentValue)) {
  1007. $div->insert('<h4>' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($componentKey)) . ' (' . sizeof($componentValue) . ' total)</h4>');
  1008. } else {
  1009. $div->insert('<h4>' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($componentKey)) . '</h4>');
  1010. }
  1011. foreach ($componentValue as $componentValueKey => $componentValueValue) {
  1012. if (is_int($componentValueKey)) {
  1013. if (is_object($componentValueValue)) {
  1014. foreach ($componentValueValue as $instanceKey => $instanceValue) {
  1015. $div->insert('<p>(' . ($componentValueKey + 1) . ') ' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($instanceKey)) . ': <b>' . $instanceValue . '</b></p>');
  1016. }
  1017. } else {
  1018. $div->insert('<p><b>' . $componentValueValue . '</b></p>');
  1019. }
  1020. } else {
  1021. $div->insert('<p>' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($componentValueKey)) . ': <b>' . $componentValueValue . '</b></p>');
  1022. }
  1023. }
  1024. } else {
  1025. $div->insert('<p>' . Utility::stringToTitle(Utility::fromCamelCaseToSpaces($componentKey)) . ': <b>' . $componentValue . '</b></p>');
  1026. }
  1027. }
  1028. return $div;
  1029. }
  1030. }
  1031. // Handle any requests that come to this file
  1032. if (isset($_GET['iframe'])) {
  1033. echo '';
  1034. }
  1035. /**
  1036. * A FormPage object contains FormSection objects and belongs to a Form object
  1037. */
  1038. class JFormPage {
  1039. // General settings
  1040. var $id;
  1041. var $class = 'jFormPage';
  1042. var $style = '';
  1043. var $jFormer;
  1044. var $jFormSectionArray = array();
  1045. var $onBeforeScrollTo; // array('function', 'notificationHtml')
  1046. var $data;
  1047. var $anonymous = false;
  1048. // Title, description, submit instructions
  1049. var $title = '';
  1050. var $titleClass = 'jFormPageTitle';
  1051. var $description = '';
  1052. var $descriptionClass = 'jFormPageDescription';
  1053. var $submitInstructions = '';
  1054. var $submitInstructionsClass = 'jFormPageSubmitInstructions';
  1055. // Validation
  1056. var $errorMessageArray = array();
  1057. // Options
  1058. var $dependencyOptions = null;
  1059. /*
  1060. * Constructor
  1061. */
  1062. function __construct($id, $optionArray = array(), $jFormSectionArray = array()) {
  1063. // Set the id
  1064. $this->id = $id;
  1065. // Use the options hash to update object variables
  1066. if (is_array($optionArray)) {
  1067. foreach ($optionArray as $option => $value) {
  1068. $this->{$option} = $value;
  1069. }
  1070. }
  1071. // Add the sections from the constructor
  1072. foreach ($jFormSectionArray as $jFormSection) {
  1073. $this->addJFormSection($jFormSection);
  1074. }
  1075. return $this;
  1076. }
  1077. function addJFormSection($jFormSection) {
  1078. $jFormSection->parentJFormPage = $this;
  1079. $this->jFormSectionArray[$jFormSection->id] = $jFormSection;
  1080. return $this;
  1081. }
  1082. function addJFormSections($jFormSections) {
  1083. if (is_array($jFormSections)) {
  1084. foreach ($jFormSections as $jFormSection) {
  1085. $jFormSection->parentJFormPage = $this;
  1086. $this->jFormSectionArray[$jFormSection->id] = $jFormSection;
  1087. }
  1088. }
  1089. $jFormSection->parentJFormPage = $this;
  1090. $this->jFormSectionArray[$jFormSection->id] = $jFormSection;
  1091. return $this;
  1092. }
  1093. // Convenience method, no need to create a section to get components on the page
  1094. function addJFormComponent($jFormComponent) {
  1095. // Create an anonymous section if necessary
  1096. if (empty($this->jFormSectionArray)) {
  1097. $this->addJFormSection(new JFormSection($this->id . '_section1', array('anonymous' => true)));
  1098. }
  1099. // Get the last section in the page
  1100. $lastJFormSection = end($this->jFormSectionArray);
  1101. // If the last section exists and is anonymous, add the component to it
  1102. if (!empty($lastJFormSection) && $lastJFormSection->anonymous) {
  1103. $lastJFormSection->addJFormComponent($jFormComponent);
  1104. }
  1105. // If the last section in the page does not exist or is not anonymous, add a new anonymous section and add the component to it
  1106. else {
  1107. // Create an anonymous section
  1108. $anonymousSection = new JFormSection($this->id . '_section' . (sizeof($this->jFormSectionArray) + 1), array('anonymous' => true));
  1109. // Add the anonymous section to the page
  1110. $this->addJFormSection($anonymousSection->addJFormComponent($jFormComponent));
  1111. }
  1112. return $this;
  1113. }
  1114. function addJFormComponentArray($jFormComponentArray) {
  1115. foreach ($jFormComponentArray as $jFormComponent) {
  1116. $this->addJFormComponent($jFormComponent);
  1117. }
  1118. return $this;
  1119. }
  1120. function getData() {
  1121. $this->data = array();
  1122. foreach ($this->jFormSectionArray as $jFormSectionKey => $jFormSection) {
  1123. $this->data[$jFormSectionKey] = $jFormSection->getData();
  1124. }
  1125. return $this->data;
  1126. }
  1127. function setData($jFormPageData) {
  1128. foreach ($jFormPageData as $jFormSectionKey => $jFormSectionData) {
  1129. $this->jFormSectionArray[$jFormSectionKey]->setData($jFormSectionData);
  1130. }
  1131. }
  1132. function clearData() {
  1133. foreach ($this->jFormSectionArray as $jFormSection) {
  1134. $jFormSection->clearData();
  1135. }
  1136. $this->data = null;
  1137. }
  1138. function validate() {
  1139. // Clear the error message array
  1140. $this->errorMessageArray = array();
  1141. // Validate each section
  1142. foreach ($this->jFormSectionArray as $jFormSection) {
  1143. $this->errorMessageArray[$jFormSection->id] = $jFormSection->validate();
  1144. }
  1145. return $this->errorMessageArray;
  1146. }
  1147. function getOptions() {
  1148. $options = array();
  1149. $options['options'] = array();
  1150. $options['jFormSections'] = array();
  1151. foreach ($this->jFormSectionArray as $jFormSection) {
  1152. $options['jFormSections'][$jFormSection->id] = $jFormSection->getOptions();
  1153. }
  1154. if (!empty($this->onScrollTo)) {
  1155. $options['options']['onScrollTo'] = $this->onScrollTo;
  1156. }
  1157. // Dependencies
  1158. if (!empty($this->dependencyOptions)) {
  1159. // Make sure the dependentOn key is tied to an array
  1160. if (isset($this->dependencyOptions['dependentOn']) && !is_array($this->dependencyOptions['dependentOn'])) {
  1161. $this->dependencyOptions['dependentOn'] = array($this->dependencyOptions['dependentOn']);
  1162. }
  1163. $options['options']['dependencyOptions'] = $this->dependencyOptions;
  1164. }
  1165. if (empty($options['options'])) {
  1166. unset($options['options']);
  1167. }
  1168. return $options;
  1169. }
  1170. /**
  1171. *
  1172. * @return string
  1173. */
  1174. function __toString() {
  1175. // Page div
  1176. $jFormPageDiv = new JFormElement('div', array(
  1177. 'id' => $this->id,
  1178. 'class' => $this->class
  1179. ));
  1180. // Set the styile
  1181. if (!empty($this->style)) {
  1182. $jFormPageDiv->addToAttribute('style', $this->style);
  1183. }
  1184. // Add a title to the page
  1185. if (!empty($this->title)) {
  1186. $title = new JFormElement('div', array(
  1187. 'class' => $this->titleClass
  1188. ));
  1189. $title->update($this->title);
  1190. $jFormPageDiv->insert($title);
  1191. }
  1192. // Add a description to the page
  1193. if (!empty($this->description)) {
  1194. $description = new JFormElement('div', array(
  1195. 'class' => $this->descriptionClass
  1196. ));
  1197. $description->update($this->description);
  1198. $jFormPageDiv->insert($description);
  1199. }
  1200. // Add the form sections to the page
  1201. foreach ($this->jFormSectionArray as $jFormSection) {
  1202. $jFormPageDiv->insert($jFormSection);
  1203. }
  1204. // Submit instructions
  1205. if (!empty($this->submitInstructions)) {
  1206. $submitInstruction = new JFormElement('div', array(
  1207. 'class' => $this->submitInstructionsClass
  1208. ));
  1209. $submitInstruction->update($this->submitInstructions);
  1210. $jFormPageDiv->insert($submitInstruction);
  1211. }
  1212. return $jFormPageDiv->__toString();
  1213. }
  1214. }
  1215. /**
  1216. * A FormSection object contains FormComponent objects and belongs to a FormPage object
  1217. */
  1218. class JFormSection {
  1219. // General settings
  1220. var $id;
  1221. var $class = 'jFormSection';
  1222. var $style = '';
  1223. var $parentJFormPage;
  1224. var $jFormComponentArray = array();
  1225. var $data;
  1226. var $anonymous = false;
  1227. // Title, description, submit instructions
  1228. var $title = '';
  1229. var $titleClass = 'jFormSectionTitle';
  1230. var $description = '';
  1231. var $descriptionClass = 'jFormSectionDescription';
  1232. // Options
  1233. var $instanceOptions = null;
  1234. var $dependencyOptions = null;
  1235. // Validation
  1236. var $errorMessageArray = array();
  1237. /*
  1238. * Constructor
  1239. */
  1240. function __construct($id, $optionArray = array(), $jFormComponentArray = array()) {
  1241. // Set the id
  1242. $this->id = $id;
  1243. // Use the options hash to update object variables
  1244. if (is_array($optionArray)) {
  1245. foreach ($optionArray as $option => $value) {
  1246. $this->{$option} = $value;
  1247. }
  1248. }
  1249. // Add the components from the constructor
  1250. $this->addJFormComponentArray($jFormComponentArray);
  1251. return $this;
  1252. }
  1253. function addJFormComponent($jFormComponent) {
  1254. $jFormComponent->parentJFormSection = $this;
  1255. $this->jFormComponentArray[$jFormComponent->id] = $jFormComponent;
  1256. return $this;
  1257. }
  1258. function addJFormComponents($jFormComponents) {
  1259. if (is_array($jFormComponents)) {
  1260. foreach ($jFormComponentArray as $jFormComponent) {
  1261. $jFormComponent->parentJFormSection = $this;
  1262. $this->addJFormComponent($jFormComponent);
  1263. }
  1264. } else {
  1265. $jFormComponent->parentJFormSection = $this;
  1266. $this->jFormComponentArray[$jFormComponent->id] = $jFormComponent;
  1267. }
  1268. return $this;
  1269. }
  1270. function addJFormComponentArray($jFormComponentArray) {
  1271. foreach ($jFormComponentArray as $jFormComponent) {
  1272. $this->addJFormComponent($jFormComponent);
  1273. }
  1274. return $this;
  1275. }
  1276. function getData() {
  1277. $this->data = array();
  1278. // Check to see if jFormComponent array contains instances
  1279. if (array_key_exists(0, $this->jFormComponentArray) && is_array($this->jFormComponentArray[0])) {
  1280. foreach ($this->jFormComponentArray as $jFormComponentArrayInstanceIndex => $jFormComponentArrayInstance) {
  1281. foreach ($jFormComponentArrayInstance as $jFormComponentKey => $jFormComponent) {
  1282. if (get_class($jFormComponent) != 'JFormComponentHtml') { // Don't include HTML components
  1283. $this->data[$jFormComponentArrayInstanceIndex][$jFormComponentKey] = $jFormComponent->getValue();
  1284. }
  1285. }
  1286. }
  1287. }
  1288. // If the section does not have instances
  1289. else {
  1290. foreach ($this->jFormComponentArray as $jFormComponentKey => $jFormComponent) {
  1291. if (get_class($jFormComponent) != 'JFormComponentHtml') { // Don't include HTML components
  1292. $this->data[$jFormComponentKey] = $jFormComponent->getValue();
  1293. }
  1294. }
  1295. }
  1296. return $this->data;
  1297. }
  1298. function setData($jFormSectionData) {
  1299. // Handle multiple instances
  1300. if (is_array($jFormSectionData)) {
  1301. $newJFormComponentArray = array();
  1302. // Go through each section instance
  1303. foreach ($jFormSectionData as $jFormSectionIndex => $jFormSection) {
  1304. // Create a clone of the jFormComponentArray
  1305. $newJFormComponentArray[$jFormSectionIndex] = unserialize(serialize($this->jFormComponentArray));
  1306. // Go through each component in the instanced section
  1307. foreach ($jFormSection as $jFormComponentKey => $jFormComponentValue) {
  1308. // Set the value of the clone
  1309. $newJFormComponentArray[$jFormSectionIndex][$jFormComponentKey]->setValue($jFormComponentValue);
  1310. }
  1311. }
  1312. $this->jFormComponentArray = $newJFormComponentArray;
  1313. }
  1314. // Single instance
  1315. else {
  1316. // Go through each component
  1317. foreach ($jFormSectionData as $jFormComponentKey => $jFormComponentValue) {
  1318. $this->jFormComponentArray[$jFormComponentKey]->setValue($jFormComponentValue);
  1319. }
  1320. }
  1321. }
  1322. function clearData() {
  1323. // Check to see if jFormComponent array contains instances
  1324. if (array_key_exists(0, $this->jFormComponentArray) && is_array($this->jFormComponentArray[0])) {
  1325. foreach ($this->jFormComponentArray as $jFormComponentArrayInstanceIndex => $jFormComponentArrayInstance) {
  1326. foreach ($jFormComponentArrayInstance as $jFormComponentKey => $jFormComponent) {
  1327. $jFormComponent->clearValue();
  1328. }
  1329. }
  1330. }
  1331. // If the section does not have instances
  1332. else {
  1333. foreach ($this->jFormComponentArray as $jFormComponent) {
  1334. $jFormComponent->clearValue();
  1335. }
  1336. }
  1337. $this->data = null;
  1338. }
  1339. function validate() {
  1340. // Clear the error message array
  1341. $this->errorMessageArray = array();
  1342. // If we have instances, return an array
  1343. if (array_key_exists(0, $this->jFormComponentArray) && is_array($this->jFormComponentArray[0])) {
  1344. foreach ($this->jFormComponentArray as $jFormComponentArrayInstanceIndex => $jFormComponentArrayInstance) {
  1345. foreach ($jFormComponentArrayInstance as $jFormComponentKey => $jFormComponent) {
  1346. $this->errorMessageArray[$jFormComponentArrayInstanceIndex][$jFormComponent->id] = $jFormComponent->validate();
  1347. }
  1348. }
  1349. }
  1350. // If the section does not have instances, return an single dimension array
  1351. else {
  1352. foreach ($this->jFormComponentArray as $jFormComponent) {
  1353. $this->errorMessageArray[$jFormComponent->id] = $jFormComponent->validate();
  1354. }
  1355. }
  1356. return $this->errorMessageArray;
  1357. }
  1358. function getOptions() {
  1359. $options = array();
  1360. $options['options'] = array();
  1361. $options['jFormComponents'] = array();
  1362. // Instances
  1363. if (!empty($this->instanceOptions)) {
  1364. $options['options']['instanceOptions'] = $this->instanceOptions;
  1365. if (!isset($options['options']['instanceOptions']['addButtonText'])) {
  1366. $options['options']['instanceOptions']['addButtonText'] = 'Add Another';
  1367. }
  1368. if (!isset($options['options']['instanceOptions']['removeButtonText'])) {
  1369. $options['options']['instanceOptions']['removeButtonText'] = 'Remove';
  1370. }
  1371. }
  1372. // Dependencies
  1373. if (!empty($this->dependencyOptions)) {
  1374. // Make sure the dependentOn key is tied to an array
  1375. if (isset($this->dependencyOptions['dependentOn']) && !is_array($this->dependencyOptions['dependentOn'])) {
  1376. $this->dependencyOptions['dependentOn'] = array($this->dependencyOptions['dependentOn']);
  1377. }
  1378. $options['options']['dependencyOptions'] = $this->dependencyOptions;
  1379. }
  1380. // Get options for each of the jFormComponents
  1381. foreach ($this->jFormComponentArray as $jFormComponent) {
  1382. // Don't get options for JFormComponentHtml objects
  1383. if (get_class($jFormComponent) != 'JFormComponentHtml') {
  1384. $options['jFormComponents'][$jFormComponent->id] = $jFormComponent->getOptions();
  1385. }
  1386. }
  1387. if (empty($options['options'])) {
  1388. unset($options['options']);
  1389. }
  1390. return $options;
  1391. }
  1392. /**
  1393. *
  1394. * @return string
  1395. */
  1396. function __toString() {
  1397. // Section fieldset
  1398. $jFormSectionDiv = new JFormElement('div', array(
  1399. 'id' => $this->id,
  1400. 'class' => $this->class
  1401. ));
  1402. // This causes issues with things that are dependent and should display by default
  1403. // If the section has dependencies and the display type is hidden, hide by default
  1404. //if($this->dependencyOptions !== null && isset($this->dependencyOptions['display']) && $this->dependencyOptions['display'] == 'hide') {
  1405. // $jFormSectionDiv->setAttribute('style', 'display: none;');
  1406. //}
  1407. // Set the style
  1408. if (!empty($this->style)) {
  1409. $jFormSectionDiv->addToAttribute('style', $this->style);
  1410. }
  1411. // Add a title to the page
  1412. if (!empty($this->title)) {
  1413. $title = new JFormElement('div', array(
  1414. 'class' => $this->titleClass
  1415. ));
  1416. $title->update($this->title);
  1417. $jFormSectionDiv->insert($title);
  1418. }
  1419. // Add a description to the page
  1420. if (!empty($this->description)) {
  1421. $description = new JFormElement('div', array(
  1422. 'class' => $this->descriptionClass
  1423. ));
  1424. $description->update($this->description);
  1425. $jFormSectionDiv->insert($description);
  1426. }
  1427. // Add the form sections to the page
  1428. foreach ($this->jFormComponentArray as $jFormComponentArray) {
  1429. $jFormSectionDiv->insert($jFormComponentArray);
  1430. }
  1431. return $jFormSectionDiv->__toString();
  1432. }
  1433. }
  1434. /**
  1435. * An abstract FormComponent object, cannot be instantiated
  1436. */
  1437. abstract class JFormComponent {
  1438. // General settings
  1439. var $id;
  1440. var $class = null;
  1441. var $value = null;
  1442. var $style = null;
  1443. var $parentJFormSection;
  1444. var $anonymous = false;
  1445. // Label
  1446. var $label = null; // Must be implemented by child class
  1447. var $labelClass = 'jFormComponentLabel';
  1448. var $labelRequiredStarClass = 'jFormComponentLabelRequiredStar';
  1449. // Helpers
  1450. var $tip = null;
  1451. var $tipClass = 'jFormComponentTip';
  1452. var $description = null;
  1453. var $descriptionClass = 'jFormComponentDescription';
  1454. // Options
  1455. var $instanceOptions = null;
  1456. var $triggerFunction = null;
  1457. var $enterSubmits = false;
  1458. // Dependencies
  1459. var $dependencyOptions = null;
  1460. // Validation
  1461. var $validationOptions = array();
  1462. var $errorMessageArray = null;
  1463. var $passedValidation = null;
  1464. var $showErrorTipOnce = false;
  1465. /**
  1466. * Initialize
  1467. */
  1468. function initialize($optionArray = array()) {
  1469. // Use the options hash to update object variables
  1470. if (is_array($optionArray)) {
  1471. foreach ($optionArray as $option => $value) {
  1472. $this->{$option} = $value;
  1473. }
  1474. }
  1475. // Allow users to pass a string into validation options
  1476. if (is_string($this->validationOptions)) {
  1477. $this->validationOptions = array($this->validationOptions);
  1478. }
  1479. return $this;
  1480. }
  1481. function getValue() {
  1482. return $this->value;
  1483. }
  1484. function setValue($value) {
  1485. $this->value = $value;
  1486. }
  1487. function clearValue() {
  1488. $this->value = null;
  1489. }
  1490. function validate() {
  1491. // Clear the error message array
  1492. $this->errorMessageArray = array();
  1493. // Only validate if the value isn't null - this is so dependencies aren't validated before they are unlocked
  1494. if ($this->value !== null) {
  1495. // Perform the validation
  1496. $this->reformValidations();
  1497. // If you have instance values
  1498. if ($this->hasInstanceValues()) {
  1499. // Walk through each of the instance values
  1500. foreach ($this->value as $instanceKey => $instanceValue) {
  1501. foreach ($this->validationOptions as $validationType => $validationOptions) {
  1502. $validationOptions['value'] = $instanceValue;
  1503. // Get the validation response
  1504. $validationResponse = $this->$validationType($validationOptions);
  1505. // Make sure you have an array to work with
  1506. if (!isset($this->errorMessageArray[$instanceKey])) {
  1507. $this->errorMessageArray[$instanceKey] = array();
  1508. }
  1509. if ($validationResponse != 'success') {
  1510. $this->passedValidation = false;
  1511. if (is_array($validationResponse)) {
  1512. $this->errorMessageArray[$instanceKey] = array_merge($this->errorMessageArray[$instanceKey], $validationResponse);
  1513. } else {
  1514. if (is_string($validationResponse)) {
  1515. $this->errorMessageArray[$instanceKey] = array_merge($this->errorMessageArray[$instanceKey], array($validationResponse));
  1516. } else {
  1517. $this->errorMessageArray[$instanceKey] = array_merge($this->errorMessageArray[$instanceKey], array('There was a problem validating this component on the server.'));
  1518. }
  1519. }
  1520. }
  1521. // Use an empty array as a placeholder for instances that have passed validation
  1522. else {
  1523. if (sizeof($this->errorMessageArray[$instanceKey]) == 0) {
  1524. $this->errorMessageArray[$instanceKey] = array('');
  1525. }
  1526. }
  1527. }
  1528. }
  1529. }
  1530. // If there are no instance values
  1531. else {
  1532. foreach ($this->validationOptions as $validationType => $validationOptions) {
  1533. $validationOptions['value'] = $this->value;
  1534. // Get the validation response
  1535. $validationResponse = $this->$validationType($validationOptions);
  1536. if ($validationResponse != 'success') {
  1537. $this->passedValidation = false;
  1538. if (is_array($validationResponse)) {
  1539. $this->errorMessageArray = array_merge($validationResponse, $this->errorMessageArray);
  1540. } else {
  1541. if (is_string($validationResponse)) {
  1542. $this->errorMessageArray = array_merge(array($validationResponse), $this->errorMessageArray);
  1543. } else {
  1544. $this->errorMessageArray = array_merge(array('There was a problem validating this component on the server.'), $this->errorMessageArray);
  1545. }
  1546. }
  1547. }
  1548. }
  1549. }
  1550. return $this->errorMessageArray;
  1551. }
  1552. }
  1553. function reformValidations() {
  1554. $reformedValidations = array();
  1555. foreach ($this->validationOptions as $validationType => $validationOptions) {
  1556. // Check to see if the name of the function is actually an array index
  1557. if (is_int($validationType)) {
  1558. // The function is not an index, it becomes the name of the option with the value of an empty object
  1559. $reformedValidations[$validationOptions] = array();
  1560. }
  1561. // If the validationOptions is a string
  1562. else if (!is_array($validationOptions)) {
  1563. $reformedValidations[$validationType] = array();
  1564. $reformedValidations[$validationType][$validationType] = $validationOptions;
  1565. }
  1566. // If validationOptions is an object
  1567. else if (is_array($validationOptions)) {
  1568. if (isset($validationOptions[0])) {
  1569. $reformedValidations[$validationType] = array();
  1570. $reformedValidations[$validationType][$validationType] = $validationOptions;
  1571. } else {
  1572. $reformedValidations[$validationType] = $validationOptions;
  1573. }
  1574. }
  1575. }
  1576. $this->validationOptions = $reformedValidations;
  1577. }
  1578. function getOptions() {
  1579. $options = array();
  1580. $options['options'] = array();
  1581. $options['type'] = get_class($this);
  1582. // Validation options
  1583. if (!empty($this->validationOptions)) {
  1584. $options['options']['validationOptions'] = $this->validationOptions;
  1585. }
  1586. if ($this->showErrorTipOnce) {
  1587. $options['options']['showErrorTipOnce'] = $this->showErrorTipOnce;
  1588. }
  1589. // Instances
  1590. if (!empty($this->instanceOptions)) {
  1591. $options['options']['instanceOptions'] = $this->instanceOptions;
  1592. if (!isset($options['options']['instanceOptions']['addButtonText'])) {
  1593. $options['options']['instanceOptions']['addButtonText'] = 'Add Another';
  1594. }
  1595. if (!isset($options['options']['instanceOptions']['removeButtonText'])) {
  1596. $options['options']['instanceOptions']['removeButtonText'] = 'Remove';
  1597. }
  1598. }
  1599. // Trigger
  1600. if (!empty($this->triggerFunction)) {
  1601. $options['options']['triggerFunction'] = $this->triggerFunction;
  1602. }
  1603. // Dependencies
  1604. if (!empty($this->dependencyOptions)) {
  1605. // Make sure the dependentOn key is tied to an array
  1606. if (isset($this->dependencyOptions['dependentOn']) && !is_array($this->dependencyOptions['dependentOn'])) {
  1607. $this->dependencyOptions['dependentOn'] = array($this->dependencyOptions['dependentOn']);
  1608. }
  1609. $options['options']['dependencyOptions'] = $this->dependencyOptions;
  1610. }
  1611. // Clear the options key if there is nothing in it
  1612. if (empty($options['options'])) {
  1613. unset($options['options']);
  1614. }
  1615. return $options;
  1616. }
  1617. /**
  1618. * Generates the HTML for the FormComponent
  1619. * @return string
  1620. */
  1621. abstract function __toString();
  1622. function hasInstanceValues() {
  1623. return is_array($this->value);
  1624. }
  1625. function generateComponentDiv($includeLabel = true) {
  1626. // Div tag contains everything about the component
  1627. $componentDiv = new JFormElement('div', array(
  1628. 'id' => $this->id . '-wrapper',
  1629. 'class' => 'jFormComponent ' . $this->class,
  1630. ));
  1631. // This causes issues with things that are dependent and should display by default
  1632. // If the component has dependencies and the display type is hidden, hide by default
  1633. //if($this->dependencyOptions !== null && isset($this->dependencyOptions['display']) && $this->dependencyOptions['display'] == 'hide') {
  1634. // $componentDiv->setAttribute('style', 'display: none;');
  1635. //}
  1636. // Style
  1637. if (!empty($this->style)) {
  1638. $componentDiv->addToAttribute('style', $this->style);
  1639. }
  1640. // Label tag
  1641. if ($includeLabel) {
  1642. $label = $this->generateComponentLabel();
  1643. $componentDiv->insert($label);
  1644. }
  1645. return $componentDiv;
  1646. }
  1647. function generateComponentLabel() {
  1648. if (empty($this->label)) {
  1649. return '';
  1650. }
  1651. $label = new JFormElement('label', array(
  1652. 'id' => $this->id . '-label',
  1653. 'for' => $this->id,
  1654. 'class' => $this->labelClass
  1655. ));
  1656. $label->update($this->label);
  1657. // Add the required star to the label
  1658. if (in_array('required', $this->validationOptions)) {
  1659. $labelRequiredStarSpan = new JFormElement('span', array(
  1660. 'class' => $this->labelRequiredStarClass
  1661. ));
  1662. $labelRequiredStarSpan->update(' *');
  1663. $label->insert($labelRequiredStarSpan);
  1664. }
  1665. return $label;
  1666. }
  1667. function insertComponentDescription($div) {
  1668. // Description
  1669. if (!empty($this->description)) {
  1670. $description = new JFormElement('div', array(
  1671. 'id' => $this->id . '-description',
  1672. 'class' => $this->descriptionClass
  1673. ));
  1674. $description->update($this->description);
  1675. $div->insert($description);
  1676. }
  1677. return $div;
  1678. }
  1679. function insertComponentTip($div) {
  1680. // Create the tip div if not empty
  1681. if (!empty($this->tip)) {
  1682. $tipDiv = new JFormElement('div', array(
  1683. 'id' => $this->id . '-tip',
  1684. 'style' => 'display: none;',
  1685. 'class' => $this->tipClass,
  1686. ));
  1687. $tipDiv->update($this->tip);
  1688. $div->insert($tipDiv);
  1689. }
  1690. return $div;
  1691. }
  1692. // Generic validations
  1693. public function required($options) { // Just override this if necessary
  1694. $messageArray = array('Required.');
  1695. //return empty($options['value']) ? 'success' : $messageArray; // Break validation on purpose
  1696. return!empty($options['value']) || $options['value'] == '0' ? 'success' : $messageArray;
  1697. }
  1698. }
  1699. class JFormComponentAddress extends JFormComponent {
  1700. var $selectedCountry = null;
  1701. var $selectedState = null;
  1702. var $stateDropDown = false;
  1703. var $emptyValues = null;
  1704. var $showSublabels = true;
  1705. var $unitedStatesOnly = false;
  1706. var $addressLine2Hidden = false;
  1707. /*
  1708. * Constructor
  1709. */
  1710. function __construct($id, $label, $optionArray = array()) {
  1711. // Class variables
  1712. $this->id = $id;
  1713. $this->name = $this->id;
  1714. $this->label = $label;
  1715. $this->class = 'jFormComponentAddress';
  1716. // Initialize the abstract FormComponent object
  1717. $this->initialize($optionArray);
  1718. // Set the empty values with a boolean
  1719. if ($this->emptyValues === true) {
  1720. $this->emptyValues = array('addressLine1' => 'Street Address', 'addressLine2' => 'Address Line 2', 'city' => 'City', 'state' => 'State / Province / Region', 'zip' => 'Postal / Zip Code');
  1721. }
  1722. // United States only switch
  1723. if ($this->unitedStatesOnly) {
  1724. $this->stateDropDown = true;
  1725. $this->selectedCountry = 'US';
  1726. }
  1727. }
  1728. function getOption($optionValue, $optionLabel, $optionSelected, $optionDisabled) {
  1729. $option = new JFormElement('option', array('value' => $optionValue));
  1730. $option->update($optionLabel);
  1731. if ($optionSelected) {
  1732. $option->setAttribute('selected', 'selected');
  1733. }
  1734. if ($optionDisabled) {
  1735. $option->setAttribute('disabled', 'disabled');
  1736. }
  1737. return $option;
  1738. }
  1739. function getOptions() {
  1740. $options = parent::getOptions();
  1741. if (!empty($this->emptyValues)) {
  1742. $options['options']['emptyValue'] = $this->emptyValues;
  1743. }
  1744. if ($this->stateDropDown) {
  1745. $options['options']['stateDropDown'] = true;
  1746. }
  1747. if (empty($options['options'])) {
  1748. unset($options['options']);
  1749. }
  1750. return $options;
  1751. }
  1752. /**
  1753. *
  1754. * @return string
  1755. */
  1756. function __toString() {
  1757. // Generate the component div
  1758. $componentDiv = $this->generateComponentDiv();
  1759. // Add the Address Line 1 input tag
  1760. $addressLine1Div = new JFormElement('div', array(
  1761. 'class' => 'addressLine1Div',
  1762. ));
  1763. $addressLine1 = new JFormElement('input', array(
  1764. 'type' => 'text',
  1765. 'id' => $this->id . '-addressLine1',
  1766. 'name' => $this->name . '-addressLine1',
  1767. 'class' => 'addressLine1',
  1768. ));
  1769. $addressLine1Div->insert($addressLine1);
  1770. // Add the Address Line 2 input tag
  1771. $addressLine2Div = new JFormElement('div', array(
  1772. 'class' => 'addressLine2Div',
  1773. ));
  1774. $addressLine2 = new JFormElement('input', array(
  1775. 'type' => 'text',
  1776. 'id' => $this->id . '-addressLine2',
  1777. 'name' => $this->name . '-addressLine2',
  1778. 'class' => 'addressLine2',
  1779. ));
  1780. $addressLine2Div->insert($addressLine2);
  1781. // Add the city input tag
  1782. $cityDiv = new JFormElement('div', array(
  1783. 'class' => 'cityDiv',
  1784. ));
  1785. $city = new JFormElement('input', array(
  1786. 'type' => 'text',
  1787. 'id' => $this->id . '-city',
  1788. 'name' => $this->name . '-city',
  1789. 'class' => 'city',
  1790. 'maxlength' => '15',
  1791. ));
  1792. $cityDiv->insert($city);
  1793. // Add the State input tag
  1794. $stateDiv = new JFormElement('div', array(
  1795. 'class' => 'stateDiv',
  1796. ));
  1797. if ($this->stateDropDown) {
  1798. $state = new JFormElement('select', array(
  1799. 'id' => $this->id . '-state',
  1800. 'name' => $this->name . '-state',
  1801. 'class' => 'state',
  1802. ));
  1803. // Add any options that are not in an opt group to the select
  1804. foreach (JFormComponentDropDown::getStateArray($this->selectedState) as $dropDownOption) {
  1805. $optionValue = isset($dropDownOption['value']) ? $dropDownOption['value'] : '';
  1806. $optionLabel = isset($dropDownOption['label']) ? $dropDownOption['label'] : '';
  1807. $optionSelected = isset($dropDownOption['selected']) ? $dropDownOption['selected'] : false;
  1808. $optionDisabled = isset($dropDownOption['disabled']) ? $dropDownOption['disabled'] : false;
  1809. $optionOptGroup = isset($dropDownOption['optGroup']) ? $dropDownOption['optGroup'] : '';
  1810. $state->insert($this->getOption($optionValue, $optionLabel, $optionSelected, $optionDisabled));
  1811. }
  1812. } else {
  1813. $state = new JFormElement('input', array(
  1814. 'type' => 'text',
  1815. 'id' => $this->id . '-state',
  1816. 'name' => $this->name . '-state',
  1817. 'class' => 'state',
  1818. ));
  1819. }
  1820. $stateDiv->insert($state);
  1821. // Add the Zip input tag
  1822. $zipDiv = new JFormElement('div', array(
  1823. 'class' => 'zipDiv',
  1824. ));
  1825. $zip = new JFormElement('input', array(
  1826. 'type' => 'text',
  1827. 'id' => $this->id . '-zip',
  1828. 'name' => $this->name . '-zip',
  1829. 'class' => 'zip',
  1830. 'maxlength' => '5',
  1831. ));
  1832. $zipDiv->insert($zip);
  1833. // Add the country input tag
  1834. $countryDiv = new JFormElement('div', array(
  1835. 'class' => 'countryDiv',
  1836. ));
  1837. // Don't built a select list if you are United States only
  1838. if ($this->unitedStatesOnly) {
  1839. $country = new JFormElement('input', array(
  1840. 'type' => 'hidden',
  1841. 'id' => $this->id . '-country',
  1842. 'name' => $this->name . '-country',
  1843. 'class' => 'country',
  1844. 'value' => 'US',
  1845. 'style' => 'display: none;',
  1846. ));
  1847. } else {
  1848. $country = new JFormElement('select', array(
  1849. 'id' => $this->id . '-country',
  1850. 'name' => $this->name . '-country',
  1851. 'class' => 'country',
  1852. ));
  1853. // Add any options that are not in an opt group to the select
  1854. foreach (JFormComponentDropDown::getCountryArray($this->selectedCountry) as $dropDownOption) {
  1855. $optionValue = isset($dropDownOption['value']) ? $dropDownOption['value'] : '';
  1856. $optionLabel = isset($dropDownOption['label']) ? $dropDownOption['label'] : '';
  1857. $optionSelected = isset($dropDownOption['selected']) ? $dropDownOption['selected'] : false;
  1858. $optionDisabled = isset($dropDownOption['disabled']) ? $dropDownOption['disabled'] : false;
  1859. $optionOptGroup = isset($dropDownOption['optGroup']) ? $dropDownOption['optGroup'] : '';
  1860. $country->insert($this->getOption($optionValue, $optionLabel, $optionSelected, $optionDisabled));
  1861. }
  1862. }
  1863. $countryDiv->insert($country);
  1864. // Set the empty values if they are enabled
  1865. if (!empty($this->emptyValues)) {
  1866. foreach ($this->emptyValues as $empyValueKey => $emptyValue) {
  1867. if ($empyValueKey == 'addressLine1') {
  1868. $addressLine1->setAttribute('value', $emptyValue);
  1869. $addressLine1->addClassName('defaultValue');
  1870. }
  1871. if ($empyValueKey == 'addressLine2') {
  1872. $addressLine2->setAttribute('value', $emptyValue);
  1873. $addressLine2->addClassName('defaultValue');
  1874. }
  1875. if ($empyValueKey == 'city') {
  1876. $city->setAttribute('value', $emptyValue);
  1877. $city->addClassName('defaultValue');
  1878. }
  1879. if ($empyValueKey == 'state' && !$this->stateDropDown) {
  1880. $state->setAttribute('value', $emptyValue);
  1881. $state->addClassName('defaultValue');
  1882. }
  1883. if ($empyValueKey == 'zip') {
  1884. $zip->setAttribute('value', $emptyValue);
  1885. $zip->addClassName('defaultValue');
  1886. }
  1887. }
  1888. }
  1889. // Put the sublabels in if the option allows for it
  1890. if ($this->showSublabels) {
  1891. $addressLine1Div->insert('<div class="jFormComponentSublabel"><p>Street Address</p></div>');
  1892. $addressLine2Div->insert('<div class="jFormComponentSublabel"><p>Address Line 2</p></div>');
  1893. $cityDiv->insert('<div class="jFormComponentSublabel"><p>City</p></div>');
  1894. if ($this->unitedStatesOnly) {
  1895. $stateDiv->insert('<div class="jFormComponentSublabel"><p>State</p></div>');
  1896. } else {
  1897. $stateDiv->insert('<div class="jFormComponentSublabel"><p>State / Province / Region</p></div>');
  1898. }
  1899. if ($this->unitedStatesOnly) {
  1900. $zipDiv->insert('<div class="jFormComponentSublabel"><p>Zip Code</p></div>');
  1901. } else {
  1902. $zipDiv->insert('<div class="jFormComponentSublabel"><p>Postal / Zip Code</p></div>');
  1903. }
  1904. $countryDiv->insert('<div class="jFormComponentSublabel"><p>Country</p></div>');
  1905. }
  1906. // United States only switch
  1907. if ($this->unitedStatesOnly) {
  1908. $countryDiv->setAttribute('style', 'display: none;');
  1909. }
  1910. // Hide address line 2
  1911. if ($this->addressLine2Hidden) {
  1912. $addressLine2Div->setAttribute('style', 'display: none;');
  1913. }
  1914. // Insert the address components
  1915. $componentDiv->insert($addressLine1Div);
  1916. $componentDiv->insert($addressLine2Div);
  1917. $componentDiv->insert($cityDiv);
  1918. $componentDiv->insert($stateDiv);
  1919. $componentDiv->insert($zipDiv);
  1920. $componentDiv->insert($countryDiv);
  1921. // Add any description (optional)
  1922. $componentDiv = $this->insertComponentDescription($componentDiv);
  1923. // Add a tip (optional)
  1924. $componentDiv = $this->insertComponentTip($componentDiv);
  1925. return $componentDiv->__toString();
  1926. }
  1927. // Address validations
  1928. public function required($options) {
  1929. $errorMessageArray = array();
  1930. if ($options['value']->addressLine1 == '') {
  1931. array_push($errorMessageArray, array('Street Address is required.'));
  1932. }
  1933. if ($options['value']->city == '') {
  1934. array_push($errorMessageArray, array('City is required.'));
  1935. }
  1936. if ($options['value']->state == '') {
  1937. array_push($errorMessageArray, array('State is required.'));
  1938. }
  1939. if ($options['value']->zip == '') {
  1940. array_push($errorMessageArray, array('Zip is required.'));
  1941. }
  1942. if ($options['value']->country == '') {
  1943. array_push($errorMessageArray, array('Country is required.'));
  1944. }
  1945. return sizeof($errorMessageArray) < 1 ? 'success' : $errorMessageArray;
  1946. }
  1947. }
  1948. class JFormComponentCreditCard extends JFormComponent {
  1949. var $emptyValues = null; // cardNumber, securityCode
  1950. var $showSublabels = true;
  1951. var $showCardType = true;
  1952. var $showSecurityCode = true;
  1953. var $creditCardProviders = array('visa' => 'Visa', 'masterCard' => 'MasterCard', 'americanExpress' => 'American Express', 'discover' => 'Discover');
  1954. var $showMonthName = true;
  1955. var $showLongYear = true;
  1956. /*
  1957. * Constructor
  1958. */
  1959. function __construct($id, $label, $optionArray = array()) {
  1960. // Class variables
  1961. $this->id = $id;
  1962. $this->name = $this->id;
  1963. $this->label = $label;
  1964. $this->class = 'jFormComponentCreditCard';
  1965. // Initialize the abstract FormComponent object
  1966. $this->initialize($optionArray);
  1967. // Set the empty values with a boolean
  1968. if ($this->emptyValues === true) {
  1969. $this->emptyValues = array('cardNumber' => 'Card Number', 'securityCode' => 'CSC/CVV');
  1970. }
  1971. }
  1972. function getOption($optionValue, $optionLabel, $optionSelected, $optionDisabled) {
  1973. $option = new JFormElement('option', array('value' => $optionValue));
  1974. $option->update($optionLabel);
  1975. if ($optionSelected) {
  1976. $option->setAttribute('selected', 'selected');
  1977. }
  1978. if ($optionDisabled) {
  1979. $option->setAttribute('disabled', 'disabled');
  1980. }
  1981. return $option;
  1982. }
  1983. function getOptions() {
  1984. $options = parent::getOptions();
  1985. if (!empty($this->emptyValues)) {
  1986. $options['options']['emptyValues'] = $this->emptyValues;
  1987. }
  1988. if (empty($options['options'])) {
  1989. unset($options['options']);
  1990. }
  1991. return $options;
  1992. }
  1993. /**
  1994. *
  1995. * @return string
  1996. */
  1997. function __toString() {
  1998. // Generate the component div
  1999. $componentDiv = $this->generateComponentDiv();
  2000. // Add the card type select tag
  2001. if ($this->showCardType) {
  2002. $cardTypeDiv = new JFormElement('div', array(
  2003. 'class' => 'cardTypeDiv',
  2004. ));
  2005. $cardType = new JFormElement('select', array(
  2006. 'id' => $this->id . '-cardType',
  2007. 'name' => $this->name . '-cardType',
  2008. 'class' => 'cardType',
  2009. ));
  2010. // Have a default value the drop down list if there isn't a sublabel
  2011. if ($this->showSublabels == false) {
  2012. $cardType->insert($this->getOption('', 'Card Type', true, true));
  2013. }
  2014. // Add the card types
  2015. foreach ($this->creditCardProviders as $key => $value) {
  2016. $cardType->insert($this->getOption($key, $value, false, false));
  2017. }
  2018. $cardTypeDiv->insert($cardType);
  2019. }
  2020. // Add the card number input tag
  2021. $cardNumberDiv = new JFormElement('div', array(
  2022. 'class' => 'cardNumberDiv',
  2023. ));
  2024. $cardNumber = new JFormElement('input', array(
  2025. 'type' => 'text',
  2026. 'id' => $this->id . '-cardNumber',
  2027. 'name' => $this->name . '-cardNumber',
  2028. 'class' => 'cardNumber',
  2029. 'maxlength' => '16',
  2030. ));
  2031. $cardNumberDiv->insert($cardNumber);
  2032. // Add the expiration month select tag
  2033. $expirationDateDiv = new JFormElement('div', array(
  2034. 'class' => 'expirationDateDiv',
  2035. ));
  2036. $expirationMonth = new JFormElement('select', array(
  2037. 'id' => $this->id . '-expirationMonth',
  2038. 'name' => $this->name . '-expirationMonth',
  2039. 'class' => 'expirationMonth',
  2040. ));
  2041. // Have a default value the drop down list if there isn't a sublabel
  2042. if ($this->showSublabels == false) {
  2043. $expirationMonth->insert($this->getOption('', 'Month', true, true));
  2044. }
  2045. // Add the months
  2046. foreach (JFormComponentDropDown::getMonthArray() as $dropDownOption) {
  2047. $optionValue = isset($dropDownOption['value']) ? $dropDownOption['value'] : '';
  2048. $optionLabel = isset($dropDownOption['label']) ? $dropDownOption['label'] : '';
  2049. $optionSelected = isset($dropDownOption['selected']) ? $dropDownOption['selected'] : false;
  2050. $optionDisabled = isset($dropDownOption['disabled']) ? $dropDownOption['disabled'] : false;
  2051. $optionOptGroup = isset($dropDownOption['optGroup']) ? $dropDownOption['optGroup'] : '';
  2052. if ($this->showMonthName) {
  2053. $expirationMonth->insert($this->getOption($optionValue, $optionValue . ' - ' . $optionLabel, $optionSelected, $optionDisabled));
  2054. $expirationMonth->addClassName('long');
  2055. } else {
  2056. $expirationMonth->insert($this->getOption($optionValue, $optionValue, $optionSelected, $optionDisabled));
  2057. }
  2058. }
  2059. $expirationDateDiv->insert($expirationMonth);
  2060. // Add the expiration year select tag
  2061. $expirationYear = new JFormElement('select', array(
  2062. 'id' => $this->id . '-expirationYear',
  2063. 'name' => $this->name . '-expirationYear',
  2064. 'class' => 'expirationYear',
  2065. ));
  2066. // Add years
  2067. if ($this->showLongYear) {
  2068. $startYear = Date('Y');
  2069. $expirationYear->addClassName('long');
  2070. } else {
  2071. $startYear = Date('y');
  2072. if (!$this->showMonthName) {
  2073. $expirationDateDiv->insert('<span class="expirationDateSeparator">/</span>');
  2074. }
  2075. }
  2076. if ($this->showSublabels == false) {
  2077. $expirationYear->insert($this->getOption('', 'Year', true, true));
  2078. }
  2079. foreach (range($startYear, $startYear + 6) as $year) {
  2080. $expirationYear->insert($this->getOption($year, $year, false, false));
  2081. }
  2082. $expirationDateDiv->insert($expirationYear);
  2083. // Add the security code input tag
  2084. $securityCodeDiv = new JFormElement('div', array(
  2085. 'class' => 'securityCodeDiv',
  2086. ));
  2087. $securityCode = new JFormElement('input', array(
  2088. 'type' => 'text',
  2089. 'id' => $this->id . '-securityCode',
  2090. 'name' => $this->name . '-securityCode',
  2091. 'class' => 'securityCode',
  2092. 'maxlength' => '4',
  2093. ));
  2094. $securityCodeDiv->insert($securityCode);
  2095. // Set the empty values if they are enabled
  2096. if (!empty($this->emptyValues)) {
  2097. foreach ($this->emptyValues as $emptyValueKey => $emptyValue) {
  2098. if ($emptyValueKey == 'cardNumber') {
  2099. $cardNumber->setAttribute('value', $emptyValue);
  2100. $cardNumber->addClassName('defaultValue');
  2101. }
  2102. if ($emptyValueKey == 'securityCode') {
  2103. $securityCode->setAttribute('value', $emptyValue);
  2104. $securityCode->addClassName('defaultValue');
  2105. }
  2106. }
  2107. }
  2108. // Put the sublabels in if the option allows for it
  2109. if ($this->showSublabels) {
  2110. if ($this->showCardType) {
  2111. $cardTypeDiv->insert('<div class="jFormComponentSublabel"><p>Card Type</p></div>');
  2112. }
  2113. $cardNumberDiv->insert('<div class="jFormComponentSublabel"><p>Card Number</p></div>');
  2114. $expirationDateDiv->insert('<div class="jFormComponentSublabel"><p>Expiration Date</p></div>');
  2115. if ($this->showSecurityCode) {
  2116. $securityCodeDiv->insert('<div class="jFormComponentSublabel"><p>Security Code</p></div>');
  2117. }
  2118. }
  2119. // Insert the components
  2120. if ($this->showCardType) {
  2121. $componentDiv->insert($cardTypeDiv);
  2122. }
  2123. $componentDiv->insert($cardNumberDiv);
  2124. $componentDiv->insert($expirationDateDiv);
  2125. if ($this->showSecurityCode) {
  2126. $componentDiv->insert($securityCodeDiv);
  2127. }
  2128. // Add any description (optional)
  2129. $componentDiv = $this->insertComponentDescription($componentDiv);
  2130. // Add a tip (optional)
  2131. $componentDiv = $this->insertComponentTip($componentDiv);
  2132. return $componentDiv->__toString();
  2133. }
  2134. // Credit card validations
  2135. public function required($options) {
  2136. $errorMessageArray = array();
  2137. if ($this->showCardType && empty($options['value']->cardType)) {
  2138. array_push($errorMessageArray, array('Card type is required.'));
  2139. }
  2140. if (empty($options['value']->cardNumber)) {
  2141. array_push($errorMessageArray, array('Card number is required.'));
  2142. } else {
  2143. if (preg_match('/[^\d]/', $options['value']->cardNumber)) {
  2144. array_push($errorMessageArray, array('Card number may only contain numbers.'));
  2145. }
  2146. if (strlen($options['value']->cardNumber) > 16 || strlen($options['value']->cardNumber) < 13) {
  2147. array_push($errorMessageArray, array('Card number must contain 13 to 16 digits.'));
  2148. }
  2149. }
  2150. if (empty($options['value']->expirationMonth)) {
  2151. array_push($errorMessageArray, array('Expiration month is required.'));
  2152. }
  2153. if (empty($options['value']->expirationYear)) {
  2154. array_push($errorMessageArray, array('Expiration year is required.'));
  2155. }
  2156. if ($this->showSecurityCode && empty($options['value']->securityCode)) {
  2157. array_push($errorMessageArray, array('Security code is required.'));
  2158. } else if ($this->showSecurityCode) {
  2159. if (preg_match('/[^\d]/', $options['value']->securityCode)) {
  2160. array_push($errorMessageArray, array('Security code may only contain numbers.'));
  2161. }
  2162. if (strlen($options['value']->securityCode) > 4 || strlen($options['value']->securityCode) < 3) {
  2163. array_push($errorMessageArray, array('Security code must contain 3 or 4 digits.'));
  2164. }
  2165. }
  2166. return sizeof($errorMessageArray) < 1 ? 'success' : $errorMessageArray;
  2167. }
  2168. }
  2169. class JFormComponentDate extends JFormComponentSingleLineText {
  2170. /*
  2171. * Constructor
  2172. */
  2173. function __construct($id, $label, $optionArray = array()) {
  2174. // Class variables
  2175. $this->id = $id;
  2176. $this->name = $this->id;
  2177. $this->label = $label;
  2178. $this->class = 'jFormComponentDate';
  2179. // Input options
  2180. $this->initialValue = '';
  2181. $this->type = 'text';
  2182. $this->disabled = false;
  2183. $this->readOnly = false;
  2184. $this->maxLength = '';
  2185. $this->styleWidth = '';
  2186. $this->mask = '9?9/9?9/9999';
  2187. $this->emptyValue = '';
  2188. // Initialize the abstract FormComponent object
  2189. $this->initialize($optionArray);
  2190. }
  2191. /**
  2192. *
  2193. * @return string
  2194. */
  2195. function __toString() {
  2196. // Generate the component div
  2197. $div = parent::__toString();
  2198. return $div;
  2199. }
  2200. // Date validations
  2201. public function required($options) {
  2202. $errorMessageArray = array();
  2203. if ($options['value']->month == '' || $options['value']->day == '' || $options['value']->year == '' || $options['value'] == null) {
  2204. array_push($errorMessageArray, 'Required.');
  2205. return $errorMessageArray;
  2206. }
  2207. $month = intval($options['value']->month);
  2208. $day = intval($options['value']->day);
  2209. $year = intval($options['value']->year);
  2210. $badDay = false;
  2211. if ($options['value']->month == '' || $options['value']->day == '' || $options['value']->year == '') {
  2212. return true;
  2213. }
  2214. if (!preg_match('/[\d]{4}/', $year)) {
  2215. array_push($errorMessageArray, 'You must enter a valid year.');
  2216. }
  2217. if ($month < 1 || $month > 12) {
  2218. array_push($errorMessageArray, 'You must enter a valid month.');
  2219. }
  2220. if ($month == 4 || $month == 6 || $month == 9 || $month == 11) {
  2221. if ($day > 30) {
  2222. $badDay = true;
  2223. }
  2224. } else if ($month == 2) {
  2225. $days = (($year % 4 == 0) && ( (!($year % 100 == 0)) || ($year % 400 == 0))) ? 29 : 28;
  2226. if ($day > $days) {
  2227. $badDay = true;
  2228. }
  2229. }
  2230. if ($day > 31 || $day < 1) {
  2231. $badDay = true;
  2232. }
  2233. if ($badDay) {
  2234. array_push($errorMessageArray, 'You must enter a valid day.');
  2235. }
  2236. return sizeof($errorMessageArray) < 1 ? 'success' : $errorMessageArray;
  2237. }
  2238. public function minDate($options) {
  2239. $errorMessageArray = array();
  2240. $month = intval($options['value']->month);
  2241. $day = intval($options['value']->day);
  2242. $year = intval($options['value']->year);
  2243. $error = false;
  2244. if (!empty($year) && !empty($month) && !empty($day)) {
  2245. if (strtotime($year . '-' . $month . '-' . $day) < strtotime($options['minDate'])) {
  2246. $error = true;
  2247. }
  2248. }
  2249. // If they did not provide a date, validate true
  2250. else {
  2251. return 'success';
  2252. }
  2253. if ($error) {
  2254. array_push($errorMessageArray, 'Date must be on or after ' . date('F j, Y', strtotime($options['minDate'])) . '.');
  2255. }
  2256. return sizeof($errorMessageArray) < 1 ? 'success' : $errorMessageArray;
  2257. }
  2258. public function maxDate($options) {
  2259. $errorMessageArray = array();
  2260. $month = intval($options['value']->month);
  2261. $day = intval($options['value']->day);
  2262. $year = intval($options['value']->year);
  2263. $error = false;
  2264. if (!empty($year) && !empty($month) && !empty($day)) {
  2265. if (strtotime($year . '-' . $month . '-' . $day) > strtotime($options['maxDate'])) {
  2266. $error = true;
  2267. }
  2268. }
  2269. // If they did not provide a date, validate true
  2270. else {
  2271. return 'success';
  2272. }
  2273. if ($error) {
  2274. array_push($errorMessageArray, 'Date must be on or before ' . date('F j, Y', strtotime($options['maxDate'])) . '.');
  2275. }
  2276. return sizeof($errorMessageArray) < 1 ? 'success' : $errorMessageArray;
  2277. }
  2278. public function teenager($options) {
  2279. if ($this->date($options) == 'success') {
  2280. $oldEnough = strtotime($options['value']->day . '/' . $options['value']->month . '/' . $options['value']->year) - strtotime('-13 years');
  2281. } else {
  2282. return false;
  2283. }
  2284. return $oldEnough >= 0 ? 'success' : $messageArray;
  2285. }
  2286. }
  2287. class JFormComponentDropDown extends JFormComponent {
  2288. var $dropDownOptionArray = array();
  2289. var $disabled = false;
  2290. var $multiple = false;
  2291. var $size = null;
  2292. var $width = null;
  2293. /**
  2294. * Constructor
  2295. */
  2296. function __construct($id, $label, $dropDownOptionArray, $optionArray = array()) {
  2297. // General settings
  2298. $this->id = $id;
  2299. $this->name = $this->id;
  2300. $this->class = 'jFormComponentDropDown';
  2301. $this->label = $label;
  2302. $this->dropDownOptionArray = $dropDownOptionArray;
  2303. // Initialize the abstract FormComponent object
  2304. $this->initialize($optionArray);
  2305. }
  2306. function getOption($optionValue, $optionLabel, $optionSelected, $optionDisabled) {
  2307. $option = new JFormElement('option', array('value' => $optionValue));
  2308. $option->update($optionLabel);
  2309. if ($optionSelected) {
  2310. $option->setAttribute('selected', 'selected');
  2311. }
  2312. if ($optionDisabled) {
  2313. $option->setAttribute('disabled', 'disabled');
  2314. }
  2315. return $option;
  2316. }
  2317. public static function getCountryArray($selectedCountry = null) {
  2318. $countryArray = array(array('value' => '', 'label' => 'Select a Country', 'disabled' => true), array('value' => 'US', 'label' => 'United States of America'), array('value' => 'AF', 'label' => 'Afghanistan'), array('value' => 'AL', 'label' => 'Albania'), array('value' => 'DZ', 'label' => 'Algeria'), array('value' => 'AS', 'label' => 'American Samoa'), array('value' => 'AD', 'label' => 'Andorra'), array('value' => 'AO', 'label' => 'Angola'), array('value' => 'AI', 'label' => 'Anguilla'), array('value' => 'AQ', 'label' => 'Antarctica'), array('value' => 'AG', 'label' => 'Antigua and Barbuda'), array('value' => 'AR', 'label' => 'Argentina'), array('value' => 'AM', 'label' => 'Armenia'), array('value' => 'AW', 'label' => 'Aruba'), array('value' => 'AU', 'label' => 'Australia'), array('value' => 'AT', 'label' => 'Austria'), array('value' => 'AZ', 'label' => 'Azerbaijan'), array('value' => 'BS', 'label' => 'Bahamas'), array('value' => 'BH', 'label' => 'Bahrain'), array('value' => 'BD', 'label' => 'Bangladesh'), array('value' => 'BB', 'label' => 'Barbados'), array('value' => 'BY', 'label' => 'Belarus'), array('value' => 'BE', 'label' => 'Belgium'), array('value' => 'BZ', 'label' => 'Belize'), array('value' => 'BJ', 'label' => 'Benin'), array('value' => 'BM', 'label' => 'Bermuda'), array('value' => 'BT', 'label' => 'Bhutan'), array('value' => 'BO', 'label' => 'Bolivia'), array('value' => 'BA', 'label' => 'Bosnia and Herzegovina'), array('value' => 'BW', 'label' => 'Botswana'), array('value' => 'BV', 'label' => 'Bouvet Island'), array('value' => 'BR', 'label' => 'Brazil'), array('value' => 'IO', 'label' => 'British Indian Ocean Territory'), array('value' => 'BN', 'label' => 'Brunei'), array('value' => 'BG', 'label' => 'Bulgaria'), array('value' => 'BF', 'label' => 'Burkina Faso'), array('value' => 'BI', 'label' => 'Burundi'), array('value' => 'KH', 'label' => 'Cambodia'), array('value' => 'CM', 'label' => 'Cameroon'), array('value' => 'CA', 'label' => 'Canada'), array('value' => 'CV', 'label' => 'Cape Verde'), array('value' => 'KY', 'label' => 'Cayman Islands'), array('value' => 'CF', 'label' => 'Central African Republic'), array('value' => 'TD', 'label' => 'Chad'), array('value' => 'CL', 'label' => 'Chile'), array('value' => 'CN', 'label' => 'China'), array('value' => 'CX', 'label' => 'Christmas Island'), array('value' => 'CC', 'label' => 'Cocos (Keeling) Islands'), array('value' => 'CO', 'label' => 'Columbia'), array('value' => 'KM', 'label' => 'Comoros'), array('value' => 'CG', 'label' => 'Congo'), array('value' => 'CK', 'label' => 'Cook Islands'), array('value' => 'CR', 'label' => 'Costa Rica'), array('value' => 'CI', 'label' => 'Cote D\'Ivorie (Ivory Coast)'), array('value' => 'HR', 'label' => 'Croatia (Hrvatska)'), array('value' => 'CU', 'label' => 'Cuba'), array('value' => 'CY', 'label' => 'Cyprus'), array('value' => 'CZ', 'label' => 'Czech Republic'), array('value' => 'CD', 'label' => 'Democratic Republic of Congo (Zaire)'), array('value' => 'DK', 'label' => 'Denmark'), array('value' => 'DJ', 'label' => 'Djibouti'), array('value' => 'DM', 'label' => 'Dominica'), array('value' => 'DO', 'label' => 'Dominican Republic'), array('value' => 'TP', 'label' => 'East Timor'), array('value' => 'EC', 'label' => 'Ecuador'), array('value' => 'EG', 'label' => 'Egypt'), array('value' => 'SV', 'label' => 'El Salvador'), array('value' => 'GQ', 'label' => 'Equatorial Guinea'), array('value' => 'ER', 'label' => 'Eritrea'), array('value' => 'EE', 'label' => 'Estonia'), array('value' => 'ET', 'label' => 'Ethiopia'), array('value' => 'FK', 'label' => 'Falkland Islands (Malvinas)'), array('value' => 'FO', 'label' => 'Faroe Islands'), array('value' => 'FJ', 'label' => 'Fiji'), array('value' => 'FI', 'label' => 'Finland'), array('value' => 'FR', 'label' => 'France'), array('value' => 'FX', 'label' => 'France), Metropolitanarray('), array('value' => 'GF', 'label' => 'French Guinea'), array('value' => 'PF', 'label' => 'French Polynesia'), array('value' => 'TF', 'label' => 'French Southern Territories'), array('value' => 'GA', 'label' => 'Gabon'), array('value' => 'GM', 'label' => 'Gambia'), array('value' => 'GE', 'label' => 'Georgia'), array('value' => 'DE', 'label' => 'Germany'), array('value' => 'GH', 'label' => 'Ghana'), array('value' => 'GI', 'label' => 'Gibraltar'), array('value' => 'GR', 'label' => 'Greece'), array('value' => 'GL', 'label' => 'Greenland'), array('value' => 'GD', 'label' => 'Grenada'), array('value' => 'GP', 'label' => 'Guadeloupe'), array('value' => 'GU', 'label' => 'Guam'), array('value' => 'GT', 'label' => 'Guatemala'), array('value' => 'GN', 'label' => 'Guinea'), array('value' => 'GW', 'label' => 'Guinea-Bissau'), array('value' => 'GY', 'label' => 'Guyana'), array('value' => 'HT', 'label' => 'Haiti'), array('value' => 'HM', 'label' => 'Heard and McDonald Islands'), array('value' => 'HN', 'label' => 'Honduras'), array('value' => 'HK', 'label' => 'Hong Kong'), array('value' => 'HU', 'label' => 'Hungary'), array('value' => 'IS', 'label' => 'Iceland'), array('value' => 'IN', 'label' => 'India'), array('value' => 'ID', 'label' => 'Indonesia'), array('value' => 'IR', 'label' => 'Iran'), array('value' => 'IQ', 'label' => 'Iraq'), array('value' => 'IE', 'label' => 'Ireland'), array('value' => 'IL', 'label' => 'Israel'), array('value' => 'IT', 'label' => 'Italy'), array('value' => 'JM', 'label' => 'Jamaica'), array('value' => 'JP', 'label' => 'Japan'), array('value' => 'JO', 'label' => 'Jordan'), array('value' => 'KZ', 'label' => 'Kazakhstan'), array('value' => 'KE', 'label' => 'Kenya'), array('value' => 'KI', 'label' => 'Kiribati'), array('value' => 'KW', 'label' => 'Kuwait'), array('value' => 'KG', 'label' => 'Kyrgyzstan'), array('value' => 'LA', 'label' => 'Laos'), array('value' => 'LV', 'label' => 'Latvia'), array('value' => 'LB', 'label' => 'Lebanon'), array('value' => 'LS', 'label' => 'Lesotho'), array('value' => 'LR', 'label' => 'Liberia'), array('value' => 'LY', 'label' => 'Libya'), array('value' => 'LI', 'label' => 'Liechtenstein'), array('value' => 'LT', 'label' => 'Lithuania'), array('value' => 'LU', 'label' => 'Luxembourg'), array('value' => 'MO', 'label' => 'Macau'), array('value' => 'MK', 'label' => 'Macedonia'), array('value' => 'MG', 'label' => 'Madagascar'), array('value' => 'MW', 'label' => 'Malawi'), array('value' => 'MY', 'label' => 'Malaysia'), array('value' => 'MV', 'label' => 'Maldives'), array('value' => 'ML', 'label' => 'Mali'), array('value' => 'MT', 'label' => 'Malta'), array('value' => 'MH', 'label' => 'Marshall Islands'), array('value' => 'MQ', 'label' => 'Martinique'), array('value' => 'MR', 'label' => 'Mauritania'), array('value' => 'MU', 'label' => 'Mauritius'), array('value' => 'YT', 'label' => 'Mayotte'), array('value' => 'MX', 'label' => 'Mexico'), array('value' => 'FM', 'label' => 'Micronesia'), array('value' => 'MD', 'label' => 'Moldova'), array('value' => 'MC', 'label' => 'Monaco'), array('value' => 'MN', 'label' => 'Mongolia'), array('value' => 'MS', 'label' => 'Montserrat'), array('value' => 'MA', 'label' => 'Morocco'), array('value' => 'MZ', 'label' => 'Mozambique'), array('value' => 'MM', 'label' => 'Myanmar (Burma)'), array('value' => 'NA', 'label' => 'Namibia'), array('value' => 'NR', 'label' => 'Nauru'), array('value' => 'NP', 'label' => 'Nepal'), array('value' => 'NL', 'label' => 'Netherlands'), array('value' => 'AN', 'label' => 'Netherlands Antilles'), array('value' => 'NC', 'label' => 'New Caledonia'), array('value' => 'NZ', 'label' => 'New Zealand'), array('value' => 'NI', 'label' => 'Nicaragua'), array('value' => 'NE', 'label' => 'Niger'), array('value' => 'NG', 'label' => 'Nigeria'), array('value' => 'NU', 'label' => 'Niue'), array('value' => 'NF', 'label' => 'Norfolk Island'), array('value' => 'KP', 'label' => 'North Korea'), array('value' => 'MP', 'label' => 'Northern Mariana Islands'), array('value' => 'NO', 'label' => 'Norway'), array('value' => 'OM', 'label' => 'Oman'), array('value' => 'PK', 'label' => 'Pakistan'), array('value' => 'PW', 'label' => 'Palau'), array('value' => 'PA', 'label' => 'Panama'), array('value' => 'PG', 'label' => 'Papua New Guinea'), array('value' => 'PY', 'label' => 'Paraguay'), array('value' => 'PE', 'label' => 'Peru'), array('value' => 'PH', 'label' => 'Philippines'), array('value' => 'PN', 'label' => 'Pitcairn'), array('value' => 'PL', 'label' => 'Poland'), array('value' => 'PT', 'label' => 'Portugal'), array('value' => 'PR', 'label' => 'Puerto Rico'), array('value' => 'QA', 'label' => 'Qatar'), array('value' => 'RE', 'label' => 'Reunion'), array('value' => 'RO', 'label' => 'Romania'), array('value' => 'RU', 'label' => 'Russia'), array('value' => 'RW', 'label' => 'Rwanda'), array('value' => 'SH', 'label' => 'Saint Helena'), array('value' => 'KN', 'label' => 'Saint Kitts and Nevis'), array('value' => 'LC', 'label' => 'Saint Lucia'), array('value' => 'PM', 'label' => 'Saint Pierre and Miquelon'), array('value' => 'VC', 'label' => 'Saint Vincent and The Grenadines'), array('value' => 'SM', 'label' => 'San Marino'), array('value' => 'ST', 'label' => 'Sao Tome and Principe'), array('value' => 'SA', 'label' => 'Saudi Arabia'), array('value' => 'SN', 'label' => 'Senegal'), array('value' => 'SC', 'label' => 'Seychelles'), array('value' => 'SL', 'label' => 'Sierra Leone'), array('value' => 'SG', 'label' => 'Singapore'), array('value' => 'SK', 'label' => 'Slovak Republic'), array('value' => 'SI', 'label' => 'Slovenia'), array('value' => 'SB', 'label' => 'Solomon Islands'), array('value' => 'SO', 'label' => 'Somalia'), array('value' => 'ZA', 'label' => 'South Africa'), array('value' => 'GS', 'label' => 'South Georgia'), array('value' => 'KR', 'label' => 'South Korea'), array('value' => 'ES', 'label' => 'Spain'), array('value' => 'LK', 'label' => 'Sri Lanka'), array('value' => 'SD', 'label' => 'Sudan'), array('value' => 'SR', 'label' => 'Suriname'), array('value' => 'SJ', 'label' => 'Svalbard and Jan Mayen'), array('value' => 'SZ', 'label' => 'Swaziland'), array('value' => 'SE', 'label' => 'Sweden'), array('value' => 'CH', 'label' => 'Switzerland'), array('value' => 'SY', 'label' => 'Syria'), array('value' => 'TW', 'label' => 'Taiwan'), array('value' => 'TJ', 'label' => 'Tajikistan'), array('value' => 'TZ', 'label' => 'Tanzania'), array('value' => 'TH', 'label' => 'Thailand'), array('value' => 'TG', 'label' => 'Togo'), array('value' => 'TK', 'label' => 'Tokelau'), array('value' => 'TO', 'label' => 'Tonga'), array('value' => 'TT', 'label' => 'Trinidad and Tobago'), array('value' => 'TN', 'label' => 'Tunisia'), array('value' => 'TR', 'label' => 'Turkey'), array('value' => 'TM', 'label' => 'Turkmenistan'), array('value' => 'TC', 'label' => 'Turks and Caicos Islands'), array('value' => 'TV', 'label' => 'Tuvalu'), array('value' => 'UG', 'label' => 'Uganda'), array('value' => 'UA', 'label' => 'Ukraine'), array('value' => 'AE', 'label' => 'United Arab Emirates'), array('value' => 'UK', 'label' => 'United Kingdom'), array('value' => 'US', 'label' => 'United States of America'), array('value' => 'UM', 'label' => 'United States Minor Outlying Islands'), array('value' => 'UY', 'label' => 'Uruguay'), array('value' => 'UZ', 'label' => 'Uzbekistan'), array('value' => 'VU', 'label' => 'Vanuatu'), array('value' => 'VA', 'label' => 'Vatican City (Holy See)'), array('value' => 'VE', 'label' => 'Venezuela'), array('value' => 'VN', 'label' => 'Vietnam'), array('value' => 'VG', 'label' => 'Virgin Islands (British)'), array('value' => 'VI', 'label' => 'Virgin Islands (US)'), array('value' => 'WF', 'label' => 'Wallis and Futuna Islands'), array('value' => 'EH', 'label' => 'Western Sahara'), array('value' => 'WS', 'label' => 'Western Samoa'), array('value' => 'YE', 'label' => 'Yemen'), array('value' => 'YU', 'label' => 'Yugoslavia'), array('value' => 'ZM', 'label' => 'Zambia'), array('value' => 'ZW', 'label' => 'Zimbabwe'));
  2319. if (!empty($selectedCountry)) {
  2320. foreach ($countryArray as &$countryOption) {
  2321. if ($countryOption['value'] == $selectedCountry) {
  2322. $countryOption['selected'] = true;
  2323. break;
  2324. }
  2325. }
  2326. } else {
  2327. $countryArray[0]['selected'] = true;
  2328. }
  2329. return $countryArray;
  2330. }
  2331. public static function getStateArray($selectedState = null) {
  2332. $stateArray = array(array('value' => '', 'label' => 'Select a State', 'disabled' => true), array('value' => 'AL', 'label' => 'Alabama'), array('value' => 'AK', 'label' => 'Alaska'), array('value' => 'AZ', 'label' => 'Arizona'), array('value' => 'AR', 'label' => 'Arkansas'), array('value' => 'CA', 'label' => 'California'), array('value' => 'CO', 'label' => 'Colorado'), array('value' => 'CT', 'label' => 'Connecticut'), array('value' => 'DE', 'label' => 'Delaware'), array('value' => 'DC', 'label' => 'District of Columbia'), array('value' => 'FL', 'label' => 'Florida'), array('value' => 'GA', 'label' => 'Georgia'), array('value' => 'HI', 'label' => 'Hawaii'), array('value' => 'ID', 'label' => 'Idaho'), array('value' => 'IL', 'label' => 'Illinois'), array('value' => 'IN', 'label' => 'Indiana'), array('value' => 'IA', 'label' => 'Iowa'), array('value' => 'KS', 'label' => 'Kansas'), array('value' => 'KY', 'label' => 'Kentucky'), array('value' => 'LA', 'label' => 'Louisiana'), array('value' => 'ME', 'label' => 'Maine'), array('value' => 'MD', 'label' => 'Maryland'), array('value' => 'MA', 'label' => 'Massachusetts'), array('value' => 'MI', 'label' => 'Michigan'), array('value' => 'MN', 'label' => 'Minnesota'), array('value' => 'MS', 'label' => 'Mississippi'), array('value' => 'MO', 'label' => 'Missouri'), array('value' => 'MT', 'label' => 'Montana'), array('value' => 'NE', 'label' => 'Nebraska'), array('value' => 'NV', 'label' => 'Nevada'), array('value' => 'NH', 'label' => 'New Hampshire'), array('value' => 'NJ', 'label' => 'New Jersey'), array('value' => 'NM', 'label' => 'New Mexico'), array('value' => 'NY', 'label' => 'New York'), array('value' => 'NC', 'label' => 'North Carolina'), array('value' => 'ND', 'label' => 'North Dakota'), array('value' => 'OH', 'label' => 'Ohio'), array('value' => 'OK', 'label' => 'Oklahoma'), array('value' => 'OR', 'label' => 'Oregon'), array('value' => 'PA', 'label' => 'Pennsylvania'), array('value' => 'RI', 'label' => 'Rhode Island'), array('value' => 'SC', 'label' => 'South Carolina'), array('value' => 'SD', 'label' => 'South Dakota'), array('value' => 'TN', 'label' => 'Tennessee'), array('value' => 'TX', 'label' => 'Texas'), array('value' => 'UT', 'label' => 'Utah'), array('value' => 'VT', 'label' => 'Vermont'), array('value' => 'VA', 'label' => 'Virginia'), array('value' => 'WA', 'label' => 'Washington'), array('value' => 'WV', 'label' => 'West Virginia'), array('value' => 'WI', 'label' => 'Wisconsin'), array('value' => 'WY', 'label' => 'Wyoming'));
  2333. if (!empty($selectedState)) {
  2334. foreach ($stateArray as &$stateOption) {
  2335. if ($stateOption['value'] == $selectedState) {
  2336. $stateOption['selected'] = true;
  2337. break;
  2338. }
  2339. }
  2340. } else {
  2341. $stateArray[0]['selected'] = true;
  2342. }
  2343. return $stateArray;
  2344. }
  2345. public static function getMonthArray() {
  2346. return array(array('value' => '01', 'label' => 'January'), array('value' => '02', 'label' => 'February'), array('value' => '03', 'label' => 'March'), array('value' => '04', 'label' => 'April'), array('value' => '05', 'label' => 'May'), array('value' => '06', 'label' => 'June'), array('value' => '07', 'label' => 'July'), array('value' => '08', 'label' => 'August'), array('value' => '09', 'label' => 'September'), array('value' => '10', 'label' => 'October'), array('value' => '11', 'label' => 'November'), array('value' => '12', 'label' => 'December'));
  2347. }
  2348. public static function getYearArray($minYear, $maxYear) {
  2349. $yearArray = array();
  2350. for ($i = $maxYear - $minYear; $i > 0; $i--) {
  2351. $yearArray[] = array('value' => $i + $minYear, 'label' => $i + $minYear);
  2352. }
  2353. return $yearArray;
  2354. }
  2355. /**
  2356. *
  2357. * @return string
  2358. */
  2359. function __toString() {
  2360. // Div tag contains everything about the component
  2361. $div = parent::generateComponentDiv();
  2362. // Select tag
  2363. $select = new JFormElement('select', array(
  2364. 'id' => $this->id,
  2365. 'name' => $this->name,
  2366. 'class' => $this->class,
  2367. ));
  2368. // Only use if disabled is set, otherwise will throw an error
  2369. if ($this->disabled) {
  2370. $select->setAttribute('disabled', 'disabled');
  2371. }
  2372. if ($this->multiple) {
  2373. $select->setAttribute('multiple', 'multiple');
  2374. }
  2375. if ($this->size != null) {
  2376. $select->setAttribute('size', $this->size);
  2377. }
  2378. if ($this->width != null) {
  2379. $select->setAttribute('style', 'width:' . $this->width);
  2380. }
  2381. // Check for any opt groups
  2382. $optGroupArray = array();
  2383. foreach ($this->dropDownOptionArray as $dropDownOption) {
  2384. if (isset($dropDownOption['optGroup']) && !empty($dropDownOption['optGroup'])) {
  2385. $optGroupArray[] = $dropDownOption['optGroup'];
  2386. }
  2387. }
  2388. $optGroupArray = array_unique($optGroupArray);
  2389. // Create the optgroup elements
  2390. foreach ($optGroupArray as $optGroup) {
  2391. ${$optGroup} = new JFormElement('optgroup', array('label' => $optGroup));
  2392. }
  2393. // Add any options to their appropriate optgroup
  2394. foreach ($this->dropDownOptionArray as $dropDownOption) {
  2395. if (isset($dropDownOption['optGroup']) && !empty($dropDownOption['optGroup'])) {
  2396. $optionValue = isset($dropDownOption['value']) ? $dropDownOption['value'] : '';
  2397. $optionLabel = isset($dropDownOption['label']) ? $dropDownOption['label'] : '';
  2398. $optionSelected = isset($dropDownOption['selected']) ? $dropDownOption['selected'] : false;
  2399. $optionDisabled = isset($dropDownOption['disabled']) ? $dropDownOption['disabled'] : false;
  2400. $optionOptGroup = isset($dropDownOption['optGroup']) ? $dropDownOption['optGroup'] : '';
  2401. ${$dropDownOption['optGroup']}->insert($this->getOption($optionValue, $optionLabel, $optionSelected, $optionDisabled));
  2402. }
  2403. }
  2404. // Add any options that are not in an opt group to the select
  2405. foreach ($this->dropDownOptionArray as $dropDownOption) {
  2406. // Handle optgroup addition - only add the group if you haven't seen it yet
  2407. if (isset($dropDownOption['optGroup']) && !empty($dropDownOption['optGroup']) && !isset(${$dropDownOption['optGroup'] . 'Added'})) {
  2408. $select->insert(${$dropDownOption['optGroup']});
  2409. ${$dropDownOption['optGroup'] . 'Added'} = true;
  2410. }
  2411. // Add any other elements
  2412. else if (!isset($dropDownOption['optGroup'])) {
  2413. $optionValue = isset($dropDownOption['value']) ? $dropDownOption['value'] : '';
  2414. $optionLabel = isset($dropDownOption['label']) ? $dropDownOption['label'] : '';
  2415. $optionSelected = isset($dropDownOption['selected']) ? $dropDownOption['selected'] : false;
  2416. $optionDisabled = isset($dropDownOption['disabled']) ? $dropDownOption['disabled'] : false;
  2417. $optionOptGroup = isset($dropDownOption['optGroup']) ? $dropDownOption['optGroup'] : '';
  2418. $select->insert($this->getOption($optionValue, $optionLabel, $optionSelected, $optionDisabled));
  2419. }
  2420. }
  2421. // Add the select box to the div
  2422. $div->insert($select);
  2423. // Add any description (optional)
  2424. $div = $this->insertComponentDescription($div);
  2425. // Add a tip (optional)
  2426. $div = $this->insertComponentTip($div, $this->id . '-div');
  2427. return $div->__toString();
  2428. }
  2429. }
  2430. class JFormComponentFile extends JFormComponent {
  2431. /*
  2432. * Constructor
  2433. */
  2434. function __construct($id, $label, $optionArray = array()) {
  2435. // Class variables
  2436. $this->id = $id;
  2437. $this->name = $this->id;
  2438. $this->class = 'jFormComponentFile';
  2439. $this->label = $label;
  2440. $this->inputClass = 'file';
  2441. //style hacking
  2442. $this->customStyle = true;
  2443. // Input options
  2444. $this->type = 'file';
  2445. $this->disabled = false;
  2446. $this->maxLength = '';
  2447. $this->styleWidth = '';
  2448. // Initialize the abstract FormComponent object
  2449. $this->initialize($optionArray);
  2450. }
  2451. function hasInstanceValues() {
  2452. return isset($this->value[0]);
  2453. }
  2454. function getOptions() {
  2455. $options = parent::getOptions();
  2456. if ($this->customStyle) {
  2457. $options['options']['customStyle'] = true;
  2458. }
  2459. return $options;
  2460. }
  2461. /**
  2462. *
  2463. * @return string
  2464. */
  2465. function __toString() {
  2466. // Generate the component div
  2467. $div = $this->generateComponentDiv();
  2468. // Add the input tag
  2469. $pseudoFileWrapper = new JFormElement('div', array(
  2470. 'class' => 'pseudoFile',
  2471. 'style' => 'position:absolute;'
  2472. ));
  2473. $pseudoFileInput = new JFormElement('input', array(
  2474. 'type' => 'text',
  2475. 'disabled' => 'disabled',
  2476. ));
  2477. $pseudoFileButton = new JFormElement('button', array(
  2478. 'onclick' => 'return false;',
  2479. 'disabled' => 'disabled'
  2480. ));
  2481. $pseudoFileButton->update('Browse...');
  2482. $pseudoFileWrapper->insert($pseudoFileInput);
  2483. $pseudoFileWrapper->insert($pseudoFileButton);
  2484. $input = new JFormElement('input', array(
  2485. 'type' => $this->type,
  2486. 'id' => $this->id,
  2487. 'name' => $this->name,
  2488. 'class' => $this->inputClass,
  2489. 'size' => 15,
  2490. ));
  2491. if (!empty($this->styleWidth)) {
  2492. $input->setAttribute('style', 'width: ' . $this->styleWidth . ';');
  2493. }
  2494. if (!empty($this->maxLength)) {
  2495. $input->setAttribute('maxlength', $this->maxLength);
  2496. }
  2497. if ($this->disabled) {
  2498. $input->setAttribute('disabled', 'disabled');
  2499. }
  2500. if ($this->customStyle) {
  2501. $input->addClassName('hidden');
  2502. $div->insert($pseudoFileWrapper);
  2503. }
  2504. $div->insert($input);
  2505. // Add any description (optional)
  2506. $div = $this->insertComponentDescription($div);
  2507. // Add a tip (optional)
  2508. $div = $this->insertComponentTip($div);
  2509. return $div->__toString();
  2510. }
  2511. public function required($options) {
  2512. $messageArray = array('Required.');
  2513. return!empty($options['value']) ? 'success' : $messageArray;
  2514. }
  2515. public function extension($options) {
  2516. $messageArray = array('Must have the .' . $options->extension . ' extension.');
  2517. $extensionRegex = '/\.' . options . extension . '$/';
  2518. return $options['value']['name'] == '' || preg_match($extensionRegex, $options['value']['name']) ? 'success' : $messageArray;
  2519. }
  2520. public function extensionType($options) {
  2521. $extensionType;
  2522. $messageArray = array('Incorrect file type.');
  2523. if (is_array($options['extensionType'])) {
  2524. $extensionType = '/\.(' . implode('|', $options['extensionType']) . ')/';
  2525. } else {
  2526. $extensionObject = new stdClass();
  2527. $extensionObject->image = '/\.(bmp|gif|jpg|png|psd|psp|thm|tif)$/i';
  2528. $extensionObject->document = '/\.(doc|docx|log|msg|pages|rtf|txt|wpd|wps)$/i';
  2529. $extensionObject->audio = '/\.(aac|aif|iff|m3u|mid|midi|mp3|mpa|ra|wav|wma)$/i';
  2530. $extensionObject->video = '/\.(3g2|3gp|asf|asx|avi|flv|mov|mp4|mpg|rm|swf|vob|wmv)$/i';
  2531. $extensionObject->web = '/\.(asp|css|htm|html|js|jsp|php|rss|xhtml)$/i';
  2532. $extensionType = $extensionObject->$options['extensionType'];
  2533. $messageArray = array('Must be an ' . $options['extensionType'] . ' file type.');
  2534. }
  2535. return empty($options['value']) || preg_match($extensionType, $options['value']['name']) ? 'success' : $messageArray;
  2536. }
  2537. public function size($options) {
  2538. if (empty($options['value'])) {
  2539. return 'success';
  2540. }
  2541. // they will give filesize in kb
  2542. $fileSizeInKb = $this->value['size'] / 1024;
  2543. return $fileSizeInKb <= $options['size'] ? 'success' : array('File must be smaller then ' . $options['size'] . 'kb. File is ' . round($fileSizeInKb, 2) . 'kb.');
  2544. }
  2545. public function imageDimensions($options) {
  2546. if (empty($options['value'])) {
  2547. return 'success';
  2548. }
  2549. $imageInfo = getimagesize($this->value['tmp_name']);
  2550. // Check to see if the file is an image
  2551. if (!$imageInfo) {
  2552. return array("File is not a valid image file.");
  2553. } else {
  2554. $errorMessageArray = array();
  2555. $width = $imageInfo[0];
  2556. $height = $imageInfo[1];
  2557. if ($width > $options['width']) {
  2558. $errorMessageArray[] = array('The image must be less then ' . $options['width'] . 'px wide. File is ' . $width . 'px.');
  2559. }
  2560. if ($height > $options['height']) {
  2561. $errorMessageArray[] = array('The image must be less then ' . $options['height'] . 'px tall. File is ' . $height . 'px.');
  2562. }
  2563. }
  2564. return empty($errorMessageArray) ? 'success' : $errorMessageArray;
  2565. }
  2566. public function minImageDimensions($options) {
  2567. if (empty($options['value'])) {
  2568. return 'success';
  2569. }
  2570. $imageInfo = getimagesize($this->value['tmp_name']);
  2571. // Check to see if the file is an image
  2572. if (!$imageInfo) {
  2573. return array("File is not a valid image file.");
  2574. } else {
  2575. $errorMessageArray = array();
  2576. $width = $imageInfo[0];
  2577. $height = $imageInfo[1];
  2578. if ($width < $options['width']) {
  2579. $errorMessageArray[] = array('The image must at least then ' . $options['width'] . 'px wide. File is ' . $width . 'px.');
  2580. }
  2581. if ($height < $options['height']) {
  2582. $errorMessageArray[] = array('The image must at least then ' . $options['height'] . 'px tall. File is ' . $height . 'px.');
  2583. }
  2584. }
  2585. return empty($errorMessageArray) ? 'success' : $errorMessageArray;
  2586. }
  2587. }
  2588. class JFormComponentHidden extends JFormComponent {
  2589. /*
  2590. * Constructor
  2591. */
  2592. function __construct($id, $value, $optionArray = array()) {
  2593. // Class variables
  2594. $this->id = $id;
  2595. $this->name = $this->id;
  2596. $this->class = 'jFormComponentHidden';
  2597. // Initialize the abstract FormComponent object
  2598. $this->initialize($optionArray);
  2599. // Prevent the value from being overwritten
  2600. $this->value = $value;
  2601. }
  2602. /**
  2603. *
  2604. * @return string
  2605. */
  2606. function __toString() {
  2607. // Generate the component div without a label
  2608. $div = $this->generateComponentDiv(false);
  2609. $div->addToAttribute('style', 'display: none;');
  2610. // Input tag
  2611. $input = new JFormElement('input', array(
  2612. 'type' => 'hidden',
  2613. 'id' => $this->id,
  2614. 'name' => $this->name,
  2615. 'value' => $this->value,
  2616. ));
  2617. $div->insert($input);
  2618. return $div->__toString();
  2619. }
  2620. }
  2621. class JFormComponentHtml {
  2622. var $html;
  2623. function __construct($html) {
  2624. $this->id = uniqid();
  2625. $this->html = $html;
  2626. }
  2627. function getOptions() {
  2628. return null;
  2629. }
  2630. function clearValue() {
  2631. return null;
  2632. }
  2633. function validate() {
  2634. return null;
  2635. }
  2636. function getValue() {
  2637. return null;
  2638. }
  2639. function __toString() {
  2640. return $this->html;
  2641. }
  2642. }
  2643. class JFormComponentLikert extends JFormComponent {
  2644. var $choiceArray = array();
  2645. var $statementArray = array();
  2646. var $showTableHeading = true;
  2647. var $collapseLabelIntoTableHeading = false;
  2648. /**
  2649. * Constructor
  2650. */
  2651. function __construct($id, $label, $choiceArray, $statementArray, $optionsArray) {
  2652. // General settings
  2653. $this->id = $id;
  2654. $this->name = $this->id;
  2655. $this->class = 'jFormComponentLikert';
  2656. $this->label = $label;
  2657. $this->choiceArray = $choiceArray;
  2658. $this->statementArray = $statementArray;
  2659. // Initialize the abstract FormComponent object
  2660. $this->initialize($optionsArray);
  2661. }
  2662. function getOptions() {
  2663. $options = parent::getOptions();
  2664. $statementArray = array();
  2665. foreach ($this->statementArray as $statement) {
  2666. $statementArray[$statement['name']] = array();
  2667. if (!empty($statement['validationOptions'])) {
  2668. $statementArray[$statement['name']]['validationOptions'] = $statement['validationOptions'];
  2669. }
  2670. if (!empty($statement['triggerFunction'])) {
  2671. $statementArray[$statement['name']]['triggerFunction'] = $statement['triggerFunction'];
  2672. }
  2673. }
  2674. $options['options']['statementArray'] = $statementArray;
  2675. // Make sure you have an options array to manipulate
  2676. if (!isset($options['options'])) {
  2677. $options['options'] = array();
  2678. }
  2679. return $options;
  2680. }
  2681. /**
  2682. *
  2683. * @return string
  2684. */
  2685. function __toString() {
  2686. // Generate the component div
  2687. $componentDiv = parent::generateComponentDiv(!$this->collapseLabelIntoTableHeading);
  2688. // Create the table
  2689. $table = new JFormElement('table', array('class' => 'jFormComponentLikertTable'));
  2690. // Generate the first row
  2691. if ($this->showTableHeading) {
  2692. $tableHeadingRow = new JFormElement('tr', array('class' => 'jFormComponentLikertTableHeading'));
  2693. $tableHeading = new JFormElement('th', array(
  2694. 'class' => 'jFormComponentLikertStatementColumn',
  2695. ));
  2696. // Collapse the label into the heading if the option is set
  2697. if ($this->collapseLabelIntoTableHeading) {
  2698. $tableHeadingLabel = new JFormElement('label', array(
  2699. 'class' => 'jFormComponentLikertStatementLabel',
  2700. ));
  2701. $tableHeadingLabel->update($this->label);
  2702. // Add the required star to the label
  2703. if (in_array('required', $this->validationOptions)) {
  2704. $labelRequiredStarSpan = new JFormElement('span', array(
  2705. 'class' => $this->labelRequiredStarClass
  2706. ));
  2707. $labelRequiredStarSpan->update(' *');
  2708. $tableHeadingLabel->insert($labelRequiredStarSpan);
  2709. }
  2710. $tableHeading->insert($tableHeadingLabel);
  2711. }
  2712. $tableHeadingRow->insert($tableHeading);
  2713. foreach ($this->choiceArray as $choice) {
  2714. $tableHeadingRow->insert('<th>' . $choice['label'] . '</th>');
  2715. }
  2716. $table->insert($tableHeadingRow);
  2717. }
  2718. // Insert each of the statements
  2719. $statementCount = 0;
  2720. foreach ($this->statementArray as $statement) {
  2721. // Set the row style
  2722. if ($statementCount % 2 == 0) {
  2723. $statementRowClass = 'jFormComponentLikertTableRowEven';
  2724. } else {
  2725. $statementRowClass = 'jFormComponentLikertTableRowOdd';
  2726. }
  2727. // Set the statement
  2728. $statementRow = new JFormElement('tr', array('class' => $statementRowClass));
  2729. $statementColumn = new JFormElement('td', array('class' => 'jFormComponentLikertStatementColumn'));
  2730. $statementLabel = new JFormElement('label', array(
  2731. 'class' => 'jFormComponentLikertStatementLabel',
  2732. 'for' => $statement['name'] . '-choice1',
  2733. ));
  2734. $statementColumn->insert($statementLabel->insert($statement['statement']));
  2735. // Set the statement description (optional)
  2736. if (!empty($statement['description'])) {
  2737. $statementDescription = new JFormElement('div', array(
  2738. 'class' => 'jFormComponentLikertStatementDescription',
  2739. ));
  2740. $statementColumn->insert($statementDescription->update($statement['description']));
  2741. }
  2742. // Insert a tip (optional)
  2743. if (!empty($statement['tip'])) {
  2744. $statementTip = new JFormElement('div', array(
  2745. 'class' => 'jFormComponentLikertStatementTip',
  2746. 'style' => 'display: none;',
  2747. ));
  2748. $statementColumn->insert($statementTip->update($statement['tip']));
  2749. }
  2750. $statementRow->insert($statementColumn);
  2751. $choiceCount = 1;
  2752. foreach ($this->choiceArray as $choice) {
  2753. $choiceColumn = new JFormElement('td');
  2754. $choiceInput = new JFormElement('input', array(
  2755. 'id' => $statement['name'] . '-choice' . $choiceCount,
  2756. 'type' => 'radio',
  2757. 'value' => $choice['value'],
  2758. 'name' => $statement['name'],
  2759. ));
  2760. // Set a selected value if defined
  2761. if (!empty($statement['selected'])) {
  2762. if ($statement['selected'] == $choice['value']) {
  2763. $choiceInput->setAttribute('checked', 'checked');
  2764. }
  2765. }
  2766. $choiceColumn->insert($choiceInput);
  2767. // Choice sub labels
  2768. if (!empty($choice['sublabel'])) {
  2769. $choiceSublabel = new JFormElement('label', array(
  2770. 'class' => 'jFormComponentLikertSublabel',
  2771. 'for' => $statement['name'] . '-choice' . $choiceCount,
  2772. ));
  2773. $choiceSublabel->update($choice['sublabel']);
  2774. $choiceColumn->insert($choiceSublabel);
  2775. }
  2776. $statementRow->insert($choiceColumn);
  2777. $choiceCount++;
  2778. }
  2779. $statementCount++;
  2780. $table->insert($statementRow);
  2781. }
  2782. $componentDiv->insert($table);
  2783. // Add any description (optional)
  2784. $componentDiv = $this->insertComponentDescription($componentDiv);
  2785. // Add a tip (optional)
  2786. $componentDiv = $this->insertComponentTip($componentDiv, $this->id . '-div');
  2787. return $componentDiv->__toString();
  2788. }
  2789. // Validation
  2790. public function required($options) {
  2791. $errorMessageArray = array();
  2792. foreach ($options['value'] as $key => $statement) {
  2793. if (empty($statement)) {
  2794. //print_r($key);
  2795. //print_r($statement);
  2796. array_push($errorMessageArray, array($key => 'Required.'));
  2797. }
  2798. }
  2799. return sizeof($errorMessageArray) == 0 ? 'success' : $errorMessageArray;
  2800. }
  2801. }
  2802. class JFormComponentLikertStatement extends JFormComponent {
  2803. /**
  2804. * Constructor
  2805. */
  2806. function __construct($id, $label, $choiceArray, $statementArray, $optionsArray) {
  2807. // General settings
  2808. $this->id = $id;
  2809. $this->name = $this->id;
  2810. $this->class = 'jFormComponentLikertStatement';
  2811. $this->label = $label;
  2812. // Initialize the abstract FormComponent object
  2813. $this->initialize($optionsArray);
  2814. }
  2815. function __toString() {
  2816. return;
  2817. }
  2818. }
  2819. class JFormComponentMultipleChoice extends JFormComponent {
  2820. var $multipleChoiceType = 'checkbox'; // radio, checkbox
  2821. var $multipleChoiceClass = 'choice';
  2822. var $multipleChoiceLabelClass = 'choiceLabel';
  2823. var $multipleChoiceArray = array();
  2824. var $showMultipleChoiceTipIcons = true;
  2825. /**
  2826. * Constructor
  2827. */
  2828. function __construct($id, $label, $multipleChoiceArray, $optionArray = array()) {
  2829. // General settings
  2830. $this->id = $id;
  2831. $this->name = $this->id;
  2832. $this->class = 'jFormComponentMultipleChoice';
  2833. $this->label = $label;
  2834. $this->multipleChoiceArray = $multipleChoiceArray;
  2835. // Initialize the abstract FormComponent object
  2836. $this->initialize($optionArray);
  2837. }
  2838. function hasInstanceValues() {
  2839. if ($this->multipleChoiceType == 'radio') {
  2840. return is_array($this->value);
  2841. } else {
  2842. if (!empty($this->value)) {
  2843. return is_array($this->value[0]);
  2844. }
  2845. }
  2846. return false;
  2847. }
  2848. /**
  2849. * MultipleChoice Specific Instance Handling for validation
  2850. *
  2851. */
  2852. function validateComponent() {
  2853. $this->passedValidation = true;
  2854. $this->errorMessageArray = array();
  2855. if (is_array($this->value[0])) {
  2856. foreach ($this->value as $value) {
  2857. $this->errorMessageArray[] = $this->validate($value);
  2858. }
  2859. } else {
  2860. $this->errorMessageArray = $this->validate($this->value);
  2861. }
  2862. }
  2863. function getOptions() {
  2864. $options = parent::getOptions();
  2865. // Make sure you have an options array to manipulate
  2866. if (!isset($options['options'])) {
  2867. $options['options'] = array();
  2868. }
  2869. // Set the multiple choice type
  2870. $options['options']['multipleChoiceType'] = $this->multipleChoiceType;
  2871. return $options;
  2872. }
  2873. /**
  2874. *
  2875. * @return string
  2876. */
  2877. function __toString() {
  2878. // Generate the component div
  2879. if (sizeof($this->multipleChoiceArray) > 1) {
  2880. $div = parent::generateComponentDiv();
  2881. } else {
  2882. $div = parent::generateComponentDiv(false);
  2883. }
  2884. // Case
  2885. // array(array('value' => 'option1', 'label' => 'Option 1', 'checked' => 'checked', 'tip' => 'This is a tip'))
  2886. $multipleChoiceCount = 0;
  2887. foreach ($this->multipleChoiceArray as $multipleChoice) {
  2888. $multipleChoiceValue = isset($multipleChoice['value']) ? $multipleChoice['value'] : '';
  2889. $multipleChoiceLabel = isset($multipleChoice['label']) ? $multipleChoice['label'] : '';
  2890. $multipleChoiceChecked = isset($multipleChoice['checked']) ? $multipleChoice['checked'] : false;
  2891. $multipleChoiceTip = isset($multipleChoice['tip']) ? $multipleChoice['tip'] : '';
  2892. $multipleChoiceDisabled = isset($multipleChoice['disabled']) ? $multipleChoice['disabled'] : '';
  2893. $multipleChoiceInputHidden = isset($multipleChoice['inputHidden']) ? $multipleChoice['inputHidden'] : '';
  2894. $multipleChoiceCount++;
  2895. $div->insert($this->getMultipleChoiceWrapper($multipleChoiceValue, $multipleChoiceLabel, $multipleChoiceChecked, $multipleChoiceTip, $multipleChoiceDisabled, $multipleChoiceInputHidden, $multipleChoiceCount));
  2896. }
  2897. // Add any description (optional)
  2898. $div = $this->insertComponentDescription($div);
  2899. // Add a tip (optional)
  2900. $div = $this->insertComponentTip($div, $this->id . '-div');
  2901. return $div->__toString();
  2902. }
  2903. //function to insert tips onto the wrappers
  2904. function getMultipleChoiceWrapper($multipleChoiceValue, $multipleChoiceLabel, $multipleChoiceChecked, $multipleChoiceTip, $multipleChoiceDisabled, $multipleChoiceInputHidden, $multipleChoiceCount) {
  2905. // Make a wrapper div for the input and label
  2906. $multipleChoiceWrapperDiv = new JFormElement('div', array(
  2907. 'id' => $this->id . '-choice' . $multipleChoiceCount . '-wrapper',
  2908. 'class' => $this->multipleChoiceClass . 'Wrapper',
  2909. ));
  2910. // Input tag
  2911. $input = new JFormElement('input', array(
  2912. 'type' => $this->multipleChoiceType,
  2913. 'id' => $this->id . '-choice' . $multipleChoiceCount,
  2914. 'name' => $this->name,
  2915. 'value' => $multipleChoiceValue,
  2916. 'class' => $this->multipleChoiceClass,
  2917. 'style' => 'display: inline;',
  2918. ));
  2919. if ($multipleChoiceChecked == 'checked') {
  2920. $input->setAttribute('checked', 'checked');
  2921. }
  2922. if ($multipleChoiceDisabled) {
  2923. $input->setAttribute('disabled', 'disabled');
  2924. }
  2925. if ($multipleChoiceInputHidden) {
  2926. $input->setAttribute('style', 'display: none;');
  2927. }
  2928. $multipleChoiceWrapperDiv->insert($input);
  2929. // Multiple choice label
  2930. $multipleChoiceLabelElement = new JFormElement('label', array(
  2931. 'for' => $this->id . '-choice' . $multipleChoiceCount,
  2932. 'class' => $this->multipleChoiceLabelClass,
  2933. 'style' => 'display: inline;',
  2934. ));
  2935. // Add an image to the label if there is a tip
  2936. if (!empty($multipleChoiceTip) && $this->showMultipleChoiceTipIcons) {
  2937. $multipleChoiceLabelElement->update($multipleChoiceLabel . ' <span class="jFormComponentMultipleChoiceTipIcon">&nbsp;</span>');
  2938. } else {
  2939. $multipleChoiceLabelElement->update($multipleChoiceLabel);
  2940. }
  2941. // Add a required star if there is only one multiple choice option and it is required
  2942. if (sizeof($this->multipleChoiceArray) == 1) {
  2943. // Add the required star to the label
  2944. if (in_array('required', $this->validationOptions)) {
  2945. $labelRequiredStarSpan = new JFormElement('span', array(
  2946. 'class' => $this->labelRequiredStarClass
  2947. ));
  2948. $labelRequiredStarSpan->update(' *');
  2949. $multipleChoiceLabelElement->insert($labelRequiredStarSpan);
  2950. }
  2951. }
  2952. $multipleChoiceWrapperDiv->insert($multipleChoiceLabelElement);
  2953. // Multiple choice tip
  2954. if (!empty($multipleChoiceTip)) {
  2955. $multipleChoiceTipDiv = new JFormElement('div', array(
  2956. 'id' => $this->id . '-' . $multipleChoiceValue . '-tip',
  2957. 'style' => 'display: none;',
  2958. 'class' => 'jFormComponentMultipleChoiceTip'
  2959. ));
  2960. $multipleChoiceTipDiv->update($multipleChoiceTip);
  2961. $multipleChoiceWrapperDiv->insert($multipleChoiceTipDiv);
  2962. }
  2963. return $multipleChoiceWrapperDiv;
  2964. }
  2965. // Validations
  2966. public function required($options) {
  2967. $errorMessageArray = array('Required.');
  2968. return sizeof($options['value']) > 0 ? 'success' : $errorMessageArray;
  2969. }
  2970. public function minOptions($options) {
  2971. $errorMessageArray = array('You must select more than ' . $options['minOptions'] . ' options');
  2972. return sizeof($options['value']) == 0 || sizeof($options['value']) > $options['minOptions'] ? 'success' : $errorMessageArray;
  2973. }
  2974. public function maxOptions($options) {
  2975. $errorMessageArray = array('You may select up to ' . $options['maxOptions'] . ' options. You have selected ' . sizeof($options['value']) . '.');
  2976. return sizeof($options['value']) == 0 || sizeof($options['value']) <= $options['maxOptions'] ? 'success' : $errorMessageArray;
  2977. }
  2978. }
  2979. class JFormComponentName extends JFormComponent {
  2980. var $middleInitialHidden = false;
  2981. var $emptyValues = null;
  2982. var $showSublabels = true;
  2983. /*
  2984. * Constructor
  2985. */
  2986. function __construct($id, $label, $optionArray = array()) {
  2987. // Class variables
  2988. $this->id = $id;
  2989. $this->name = $this->id;
  2990. $this->label = $label;
  2991. $this->class = 'jFormComponentName';
  2992. // Input options
  2993. $this->initialValues = array('firstName' => '', 'middleInitial' => '', 'lastName' => '');
  2994. if ($this->emptyValues === true) {
  2995. $this->emptyValues = array('firstName' => 'First Name', 'middleInitial' => 'M', 'lastName' => 'Last Name');
  2996. }
  2997. //$this->mask = '';
  2998. // Initialize the abstract FormComponent object
  2999. $this->initialize($optionArray);
  3000. }
  3001. function hasInstanceValues() {
  3002. return is_array($this->value);
  3003. }
  3004. function getOptions() {
  3005. $options = parent::getOptions();
  3006. if (!empty($this->emptyValues)) {
  3007. $options['options']['emptyValue'] = $this->emptyValues;
  3008. }
  3009. if (empty($options['options'])) {
  3010. unset($options['options']);
  3011. }
  3012. return $options;
  3013. }
  3014. /**
  3015. *
  3016. * @return string
  3017. */
  3018. function __toString() {
  3019. // Generate the component div
  3020. $div = $this->generateComponentDiv();
  3021. $firstNameDiv = new JFormElement('div', array(
  3022. 'class' => 'firstNameDiv',
  3023. ));
  3024. // Add the first name input tag
  3025. $firstName = new JFormElement('input', array(
  3026. 'type' => 'text',
  3027. 'id' => $this->id . '-firstName',
  3028. 'name' => $this->name . '-firstName',
  3029. 'class' => 'firstName singleLineText',
  3030. 'value' => $this->initialValues['firstName'],
  3031. ));
  3032. $firstNameDiv->insert($firstName);
  3033. // Add the middle initial input tag
  3034. $middleInitialDiv = new JFormElement('div', array(
  3035. 'class' => 'middleInitialDiv',
  3036. ));
  3037. $middleInitial = new JFormElement('input', array(
  3038. 'type' => 'text',
  3039. 'id' => $this->id . '-middleInitial',
  3040. 'name' => $this->name . '-middleInitial',
  3041. 'class' => 'middleInitial singleLineText',
  3042. 'maxlength' => '1',
  3043. 'value' => $this->initialValues['middleInitial'],
  3044. ));
  3045. if ($this->middleInitialHidden) {
  3046. $middleInitial->setAttribute('style', 'display: none;');
  3047. $middleInitialDiv->setAttribute('style', 'display: none;');
  3048. }
  3049. $middleInitialDiv->insert($middleInitial);
  3050. // Add the last name input tag
  3051. $lastNameDiv = new JFormElement('div', array(
  3052. 'class' => 'lastNameDiv',
  3053. ));
  3054. $lastName = new JFormElement('input', array(
  3055. 'type' => 'text',
  3056. 'id' => $this->id . '-lastName',
  3057. 'name' => $this->name . '-lastName',
  3058. 'class' => 'lastName singleLineText',
  3059. 'value' => $this->initialValues['lastName'],
  3060. ));
  3061. $lastNameDiv->insert($lastName);
  3062. if (!empty($this->emptyValues)) {
  3063. $this->emptyValues = array('firstName' => 'First Name', 'middleInitial' => 'M', 'lastName' => 'Last Name');
  3064. foreach ($this->emptyValues as $key => $value) {
  3065. if ($key == 'firstName') {
  3066. $firstName->setAttribute('value', $value);
  3067. $firstName->addClassName('defaultValue');
  3068. }
  3069. if ($key == 'middleInitial') {
  3070. $middleInitial->setAttribute('value', $value);
  3071. $middleInitial->addClassName('defaultValue');
  3072. }
  3073. if ($key == 'lastName') {
  3074. $lastName->setAttribute('value', $value);
  3075. $lastName->addClassName('defaultValue');
  3076. }
  3077. }
  3078. }
  3079. if ($this->showSublabels) {
  3080. $firstNameDiv->insert('<div class="jFormComponentSublabel"><p>First Name</p></div>');
  3081. $middleInitialDiv->insert('<div class="jFormComponentSublabel"><p>MI</p></div>');
  3082. $lastNameDiv->insert('<div class="jFormComponentSublabel"><p>Last Name</p></div>');
  3083. }
  3084. $div->insert($firstNameDiv);
  3085. $div->insert($middleInitialDiv);
  3086. $div->insert($lastNameDiv);
  3087. // Add any description (optional)
  3088. $div = $this->insertComponentDescription($div);
  3089. // Add a tip (optional)
  3090. $div = $this->insertComponentTip($div);
  3091. return $div->__toString();
  3092. }
  3093. public function required($options) {
  3094. $errorMessageArray = array();
  3095. if ($options['value']->firstName == '') {
  3096. array_push($errorMessageArray, array('First name is required.'));
  3097. }
  3098. if ($options['value']->lastName == '') {
  3099. array_push($errorMessageArray, array('Last name is required.'));
  3100. }
  3101. return sizeof($errorMessageArray) == 0 ? 'success' : $errorMessageArray;
  3102. }
  3103. }
  3104. class JFormComponentSingleLineText extends JFormComponent {
  3105. var $sublabel;
  3106. /*
  3107. * Constructor
  3108. */
  3109. function __construct($id, $label, $optionArray = array()) {
  3110. // Class variables
  3111. $this->id = $id;
  3112. $this->name = $this->id;
  3113. $this->label = $label;
  3114. $this->class = 'jFormComponentSingleLineText';
  3115. $this->widthArray = array('shortest' => '2em', 'short' => '6em', 'mediumShort' => '9em', 'medium' => '12em', 'mediumLong' => '15em', 'long' => '18em', 'longest' => '24em');
  3116. // Input options
  3117. $this->initialValue = '';
  3118. $this->type = 'text'; // text, password, hidden
  3119. $this->disabled = false;
  3120. $this->readOnly = false;
  3121. $this->maxLength = '';
  3122. $this->width = '';
  3123. $this->mask = '';
  3124. $this->emptyValue = '';
  3125. // Initialize the abstract FormComponent object
  3126. $this->initialize($optionArray);
  3127. }
  3128. function hasInstanceValues() {
  3129. return is_array($this->value);
  3130. }
  3131. function getOptions() {
  3132. $options = parent::getOptions();
  3133. // Make sure you have an options array to manipulate
  3134. if (!isset($options['options'])) {
  3135. $options['options'] = array();
  3136. }
  3137. // Mask
  3138. if (!empty($this->mask)) {
  3139. $options['options']['mask'] = $this->mask;
  3140. }
  3141. // Empty value
  3142. if (!empty($this->emptyValue)) {
  3143. $options['options']['emptyValue'] = $this->emptyValue;
  3144. }
  3145. // Clear the options key if there is nothing in it
  3146. if (empty($options['options'])) {
  3147. unset($options['options']);
  3148. }
  3149. return $options;
  3150. }
  3151. /**
  3152. *
  3153. * @return string
  3154. */
  3155. function __toString() {
  3156. // Generate the component div
  3157. $div = $this->generateComponentDiv();
  3158. // Add the input tag
  3159. $input = new JFormElement('input', array(
  3160. 'type' => $this->type,
  3161. 'id' => $this->id,
  3162. 'name' => $this->name,
  3163. ));
  3164. if (!empty($this->width)) {
  3165. if (array_key_exists($this->width, $this->widthArray)) {
  3166. $input->setAttribute('style', 'width: ' . $this->widthArray[$this->width] . ';');
  3167. } else {
  3168. $input->setAttribute('style', 'width: ' . $this->width . ';');
  3169. }
  3170. }
  3171. if (!empty($this->initialValue)) {
  3172. $input->setAttribute('value', $this->initialValue);
  3173. }
  3174. if (!empty($this->maxLength)) {
  3175. $input->setAttribute('maxlength', $this->maxLength);
  3176. }
  3177. if (!empty($this->mask)) {
  3178. $this->formComponentMeta['options']['mask'] = $this->mask;
  3179. }
  3180. if ($this->disabled) {
  3181. $input->setAttribute('disabled', 'disabled');
  3182. }
  3183. if ($this->readOnly) {
  3184. $input->setAttribute('readonly', 'readonly');
  3185. }
  3186. if ($this->enterSubmits) {
  3187. $input->addToAttribute('class', ' jFormComponentEnterSubmits');
  3188. }
  3189. $div->insert($input);
  3190. if (!empty($this->sublabel)) {
  3191. $div->insert('<div class="jFormComponentSublabel">' . $this->sublabel . '</div>');
  3192. }
  3193. // Add any description (optional)
  3194. $div = $this->insertComponentDescription($div);
  3195. // Add a tip (optional)
  3196. $div = $this->insertComponentTip($div);
  3197. return $div->__toString();
  3198. }
  3199. // Validations
  3200. public function alpha($options) {
  3201. $messageArray = array('Must only contain letters.');
  3202. return preg_match('/^[a-z_\s]+$/i', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3203. }
  3204. public function alphaDecimal($options) {
  3205. $messageArray = array('Must only contain letters, numbers, or periods.');
  3206. return preg_match('/^\w+$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3207. }
  3208. public function alphaNumeric($options) {
  3209. $messageArray = array('Must only contain letters or numbers.');
  3210. return preg_match('/^[a-z0-9_\s]+$/i', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3211. }
  3212. public function blank($options) {
  3213. $messageArray = array('Must be blank.');
  3214. return strlen(trim($options['value'])) == 0 ? 'success' : $messageArray;
  3215. }
  3216. public function canadianPostal($options) {
  3217. $messageArray = array('Must be a valid Canadian postal code.');
  3218. return preg_match('/^[ABCEGHJKLMNPRSTVXY][0-9][A-Z] [0-9][A-Z][0-9]$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3219. }
  3220. public function date($options) {
  3221. $messageArray = array('Must be a date in the mm/dd/yyyy format.');
  3222. return preg_match('/^(0?[1-9]|1[012])[\- \/.](0?[1-9]|[12][0-9]|3[01])[\- \/.](19|20)[0-9]{2}$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3223. }
  3224. public function dateTime($options) {
  3225. $messageArray = array('Must be a date in the mm/dd/yyyy hh:mm:ss tt format. ss and tt are optional.');
  3226. return preg_match('/^(0?[1-9]|1[012])[\- \/.](0?[1-9]|[12][0-9]|3[01])[\- \/.](19|20)?[0-9]{2} [0-2]?\d:[0-5]\d(:[0-5]\d)?( ?(a|p)m)?$/i', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3227. }
  3228. public function decimal($options) {
  3229. // Can be negative and have a decimal value
  3230. // Do not accept commas in value as the DB does not accept them
  3231. $messageArray = array('Must be a number without any commas. Decimal is optional.');
  3232. return preg_match('/^-?((\d+(\.\d+)?)|(\.\d+))$/', $options['value']) ? 'success' : $messageArray;
  3233. }
  3234. public function decimalNegative($options) {
  3235. // Must be negative and have a decimal value
  3236. $messageArray = array('Must be a negative number without any commas. Decimal is optional.');
  3237. //isDecimal = self.validations.decimal($options);
  3238. return ($isDecimal == 'success' && (floatval($options['value']) < 0)) ? 'success' : $messageArray;
  3239. }
  3240. public function decimalPositive($options) {
  3241. // Must be positive and have a decimal value
  3242. $messageArray = array('Must be a positive number without any commas. Decimal is optional.');
  3243. //isDecimal = self.validations.decimal($options);
  3244. return ($isDecimal == 'success' && (floatval($options['value']) > 0)) ? 'success' : $messageArray;
  3245. }
  3246. public function decimalZeroNegative($options) {
  3247. // Must be negative and have a decimal value
  3248. $messageArray = array('Must be zero or a negative number without any commas. Decimal is optional.');
  3249. //isDecimal = self.validations.decimal($options);
  3250. return ($isDecimal == 'success' && (floatval($options['value']) <= 0)) ? 'success' : $messageArray;
  3251. }
  3252. public function decimalZeroPositive($options) {
  3253. // Must be positive and have a decimal value
  3254. $messageArray = array('Must be zero or a positive number without any commas. Decimal is optional.');
  3255. //isDecimal = self.validations.decimal($options);
  3256. return ($isDecimal == 'success' && (floatval($options['value']) >= 0)) ? 'success' : $messageArray;
  3257. }
  3258. public function email($options) {
  3259. $messageArray = array('Must be a valid e-mail address.');
  3260. return preg_match('/^[A-Z0-9._%-\+]+@(?:[A-Z0-9\-]+\.)+[A-Z]{2,4}$/i', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3261. }
  3262. public function integer($options) {
  3263. $messageArray = array('Must be a whole number.');
  3264. return preg_match('/^-?\d+$/', $options['value']) ? 'success' : $messageArray;
  3265. }
  3266. public function integerNegative($options) {
  3267. $messageArray = array('Must be a negative whole number.');
  3268. //isInteger = preg_match('/^-?\d+$/', $options['value']);
  3269. return ($isInteger && (intval($options['value'], 10) < 0)) ? 'success' : $messageArray;
  3270. }
  3271. public function integerPositive($options) {
  3272. $messageArray = array('Must be a positive whole number.');
  3273. //isInteger = preg_match('/^-?\d+$/', $options['value']);
  3274. return ($isInteger && (intval($options['value'], 10) > 0)) ? 'success' : $messageArray;
  3275. }
  3276. public function integerZeroNegative($options) {
  3277. $messageArray = array('Must be zero or a negative whole number.');
  3278. //isInteger = preg_match('/^-?\d+$/', $options['value']);
  3279. return ($isInteger && (intval($options['value'], 10) <= 0)) ? 'success' : $messageArray;
  3280. }
  3281. public function integerZeroPositive($options) {
  3282. $messageArray = array('Must be zero or a positive whole number.');
  3283. //isInteger = preg_match('/^-?\d+$/', $options['value']);
  3284. return ($isInteger && (intval($options['value'], 10) >= 0)) ? 'success' : $messageArray;
  3285. }
  3286. public function isbn($options) {
  3287. //Match an ISBN
  3288. $errorMessageArray = array('Must be a valid ISBN and consist of either ten or thirteen characters.');
  3289. //For ISBN-10
  3290. if (preg_match('/^(?=.{13}$)\d{1,5}([\- ])\d{1,7}\1\d{1,6}\1(\d|X)$/', $options['value'])) {
  3291. $errorMessageArray = 'sucess';
  3292. }
  3293. if (preg_match('/^\d{9}(\d|X)$/', $options['value'])) {
  3294. $errorMessageArray = 'sucess';
  3295. }
  3296. //For ISBN-13
  3297. if (preg_match('/^(?=.{17}$)\d{3}([\- ])\d{1,5}\1\d{1,7}\1\d{1,6}\1(\d|X)$/', $options['value'])) {
  3298. $errorMessageArray = 'sucess';
  3299. }
  3300. if (preg_match('/^\d{3}[\- ]\d{9}(\d|X)$/', $options['value'])) {
  3301. $errorMessageArray = 'sucess';
  3302. }
  3303. //ISBN-13 without starting delimiter (Not a valid ISBN but less strict validation was requested)
  3304. if (preg_match('/^\d{12}(\d|X)$/', $options['value'])) {
  3305. $errorMessageArray = 'sucess';
  3306. }
  3307. return $errorMessageArray;
  3308. }
  3309. public function length($options) {
  3310. $messageArray = array('Must be exactly ' . $options['length'] . ' characters long. Current value is ' . strlen($options['value']) . ' characters.');
  3311. return strlen($options['value']) == $options['length'] || $options['value'] == '' ? 'success' : $messageArray;
  3312. }
  3313. public function matches($options) {
  3314. $componentToMatch = $this->parentJFormSection->parentJFormPage->jFormer->selectJFormComponent($options['matches']);
  3315. if ($componentToMatch && $componentToMatch->value == $options['value']) {
  3316. return 'success';
  3317. } else {
  3318. return array('Does not match.');
  3319. }
  3320. }
  3321. public function maxLength($options) {
  3322. $messageArray = array('Must be less than ' . $options['maxLength'] . ' characters long. Current value is ' . strlen($options['value']) . ' characters.');
  3323. return strlen($options['value']) <= $options['maxLength'] || $options['value'] == '' ? 'success' : $messageArray;
  3324. }
  3325. public function maxFloat($options) {
  3326. $messageArray = array('Must be numeric and cannot have more than ' . $options['maxFloat'] . ' decimal place(s).');
  3327. return preg_match('^-?((\\d+(\\.\\d{0,' + $options['maxFloat'] + '})?)|(\\.\\d{0,' . $options['maxFloat'] . '}))$', $options['value']) ? 'success' : $messageArray;
  3328. }
  3329. public function maxValue($options) {
  3330. $messageArray = array('Must be numeric with a maximum value of ' . $options['maxValue'] . '.');
  3331. return $options['maxValue'] >= $options['value'] ? 'success' : $messageArray;
  3332. }
  3333. public function minLength($options) {
  3334. $messageArray = array('Must be at least ' . $options['minLength'] . ' characters long. Current value is ' . strlen($options['value']) . ' characters.');
  3335. return strlen($options['value']) >= $options['minLength'] || $options['value'] == '' ? 'success' : $messageArray;
  3336. }
  3337. public function minValue($options) {
  3338. $messageArray = array('Must be numeric with a minimum value of ' . $options['minValue'] . '.');
  3339. return $options['minValue'] <= $options['value'] ? 'success' : $messageArray;
  3340. }
  3341. public function money($options) {
  3342. $messageArray = array('Must be a valid dollar value.');
  3343. return preg_match('/^\$?[1-9][0-9]{0,2}(,?[0-9]{3})*(\.[0-9]{2})?$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3344. }
  3345. public function moneyNegative($options) {
  3346. $messageArray = array('Must be a valid negative dollar value.');
  3347. return preg_match('/^((-?\$)|(\$-?)|(-))?((\d+(\.\d{2})?)|(\.\d{2}))$/', $options['value'], $matches) && $matches[0] < 0 || $options['value'] == '' ? 'success' : $messageArray;
  3348. }
  3349. public function moneyPositive($options) {
  3350. $messageArray = array('Must be a valid positive dollar value.');
  3351. return preg_match('/^((-?\$)|(\$-?)|(-))?((\d+(\.\d{2})?)|(\.\d{2}))$/', $options['value'], $matches) && $matches[0] > 0 || $options['value'] == '' ? 'success' : $messageArray;
  3352. }
  3353. public function moneyZeroNegative($options) {
  3354. $messageArray = array('Must be zero or a valid negative dollar value.');
  3355. return preg_match('/^((-?\$)|(\$-?)|(-))?((\d+(\.\d{2})?)|(\.\d{2}))$/', $options['value'], $matches) && $matches[0] <= 0 ? 'success' : $messageArray;
  3356. }
  3357. public function moneyZeroPositive($options) {
  3358. $messageArray = array('Must be zero or a valid positive dollar value.');
  3359. return preg_match('/^((-?\$)|(\$-?)|(-))?((\d+(\.\d{2})?)|(\.\d{2}))$/', $options['value'], $matches) && $matches[0] = 0 || $options['value'] == '' ? 'success' : $messageArray;
  3360. }
  3361. public function password($options) {
  3362. $messageArray = array('Must be between 4 and 32 characters.');
  3363. return preg_match('/^.{4,32}$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3364. }
  3365. public function phone($options) {
  3366. $messageArray = array('Must be a 10 digit phone number.');
  3367. return preg_match('/^(1[\-. ]?)?\(?[0-9]{3}\)?[\-. ]?[0-9]{3}[\-. ]?[0-9]{4}$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3368. }
  3369. public function postalZip($options) {
  3370. $messageArray = array('Must be a valid United States zip code, Canadian postal code, or United Kingdom postal code.');
  3371. $postal = false;
  3372. if (this . zip($options) == 'success') {
  3373. $postal = true;
  3374. }
  3375. if (this . canadianPostal($options) == 'success') {
  3376. $postal = true;
  3377. }
  3378. if (this . ukPostal($options) == 'success') {
  3379. $postal = true;
  3380. }
  3381. return postal ? 'success' : $messageArray;
  3382. }
  3383. public function required($options) {
  3384. $messageArray = array('Required.');
  3385. //return empty($options['value']) ? 'success' : $messageArray; // Break validation on purpose
  3386. return!empty($options['value']) || $options['value'] == '0' ? 'success' : $messageArray;
  3387. }
  3388. public function serverSide($options) {
  3389. // Handle empty values
  3390. if (empty($options['value'])) {
  3391. return 'success';
  3392. }
  3393. $messageArray = array();
  3394. // Perform the server side check with a scrape
  3395. $serverSideResponse = Network::getUrlContent($options['url'] . '&value=' . $options['value']);
  3396. // Can't read the URL
  3397. if ($serverSideResponse['status'] != 'success') {
  3398. $messageArray[] = 'This component could not be validated.';
  3399. }
  3400. // Read the URL
  3401. else {
  3402. $serverSideResponse = json_decode($serverSideResponse['response']);
  3403. if ($serverSideResponse->status == 'success') {
  3404. $messageArray == 'success';
  3405. } else {
  3406. $messageArray = $serverSideResponse->response;
  3407. }
  3408. }
  3409. return $messageArray;
  3410. }
  3411. public function ssn($options) {
  3412. $messageArray = array('Must be a valid United States social security number.');
  3413. return preg_match('/^\d{3}-?\d{2}-?\d{4}$/i', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3414. }
  3415. public function teenager($options) {
  3416. $messageArray = array('Must be at least 13 years old.');
  3417. if ($this->date($options) == 'success') {
  3418. $oldEnough = strtotime($options['value']) - strtotime('-13 years');
  3419. } else {
  3420. return false;
  3421. }
  3422. return $oldEnough >= 0 ? 'success' : $messageArray;
  3423. }
  3424. public function time($options) {
  3425. $messageArray = array('Must be a time in the hh:mm:ss tt format. ss and tt are optional.');
  3426. return preg_match('/^[0-2]?\d:[0-5]\d(:[0-5]\d)?( ?(a|p)m)?$/i', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3427. }
  3428. public function ukPostal($options) {
  3429. $messageArray = array('Must be a valid United Kingdom postal code.');
  3430. return preg_match('/^[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3431. }
  3432. public function url($options) {
  3433. $messageArray = array('Must be a valid Internet address.');
  3434. return preg_match('/^((ht|f)tp(s)?:\/\/|www\.)?([\-A-Z0-9.]+)(\.[a-zA-Z]{2,4})(\/[\-A-Z0-9+&@#\/%=~_|!:,.;]*)?(\?[\-A-Z0-9+&@#\/%=~_|!:,.;]*)?$/i', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3435. }
  3436. public function username($options) {
  3437. $messageArray = array('Must use 4 to 32 characters and start with a letter.');
  3438. return preg_match('/^[A-Za-z](?=[A-Za-z0-9_.]{3,31}$)[a-zA-Z0-9_]*\.?[a-zA-Z0-9_]*$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3439. }
  3440. public function zip($options) {
  3441. $messageArray = array('Must be a valid United States zip code.');
  3442. return preg_match('/^[0-9]{5}(?:-[0-9]{4})?$/', $options['value']) || $options['value'] == '' ? 'success' : $messageArray;
  3443. }
  3444. }
  3445. class JFormComponentTextArea extends JFormComponent {
  3446. /*
  3447. * Constructor
  3448. */
  3449. function __construct($id, $label, $optionArray = array()) {
  3450. // Class variables
  3451. $this->id = $id;
  3452. $this->name = $this->id;
  3453. $this->label = $label;
  3454. $this->class = 'jFormComponentTextArea';
  3455. $this->inputClass = 'textArea';
  3456. $this->widthArray = array('shortest' => '5em', 'short' => '10em', 'medium' => '20em', 'long' => '30em', 'longest' => '40em');
  3457. $this->heightArray = array('short' => '6em', 'medium' => '12em', 'tall' => '18em');
  3458. // Input options
  3459. $this->initialValue = '';
  3460. $this->disabled = false;
  3461. $this->readOnly = false;
  3462. $this->wrap = ''; // hard, off
  3463. $this->width = '';
  3464. $this->height = '';
  3465. $this->style = '';
  3466. $this->allowTabbing = false;
  3467. $this->emptyValue = '';
  3468. $this->autoGrow = false;
  3469. // Initialize the abstract FormComponent object
  3470. $this->initialize($optionArray);
  3471. }
  3472. function hasInstanceValues() {
  3473. return is_array($this->value);
  3474. }
  3475. function getOptions() {
  3476. $options = parent::getOptions();
  3477. // Tabbing
  3478. if ($this->allowTabbing) {
  3479. $options['options']['allowTabbing'] = true;
  3480. }
  3481. // Empty value
  3482. if (!empty($this->emptyValue)) {
  3483. $options['options']['emptyValue'] = $this->emptyValue;
  3484. }
  3485. // Auto grow
  3486. if ($this->autoGrow) {
  3487. $options['options']['autoGrow'] = $this->autoGrow;
  3488. }
  3489. return $options;
  3490. }
  3491. /**
  3492. *
  3493. * @return string
  3494. */
  3495. function __toString() {
  3496. // Generate the component div
  3497. $div = $this->generateComponentDiv();
  3498. // Add the input tag
  3499. $textArea = new JFormElement('textarea', array(
  3500. 'id' => $this->id,
  3501. 'name' => $this->name,
  3502. 'class' => $this->inputClass,
  3503. ));
  3504. if (!empty($this->width)) {
  3505. if (array_key_exists($this->width, $this->widthArray)) {
  3506. $textArea->setAttribute('style', 'width: ' . $this->widthArray[$this->width] . ';');
  3507. } else {
  3508. $textArea->setAttribute('style', 'width: ' . $this->width . ';');
  3509. }
  3510. }
  3511. if (!empty($this->height)) {
  3512. if (array_key_exists($this->height, $this->heightArray)) {
  3513. $textArea->addToAttribute('style', 'height: ' . $this->heightArray[$this->height] . ';');
  3514. } else {
  3515. $textArea->addToAttribute('style', 'height: ' . $this->height . ';');
  3516. }
  3517. }
  3518. if (!empty($this->style)) {
  3519. $textArea->addToAttribute('style', $this->style);
  3520. }
  3521. if ($this->disabled) {
  3522. $textArea->setAttribute('disabled', 'disabled');
  3523. }
  3524. if ($this->readOnly) {
  3525. $textArea->setAttribute('readonly', 'readonly');
  3526. }
  3527. if ($this->wrap) {
  3528. $textArea->setAttribute('wrap', $this->wrap);
  3529. }
  3530. if (!empty($this->initialValue)) {
  3531. $textArea->update($this->initialValue);
  3532. }
  3533. $div->insert($textArea);
  3534. // Add any description (optional)
  3535. $div = $this->insertComponentDescription($div);
  3536. // Add a tip (optional)
  3537. $div = $this->insertComponentTip($div);
  3538. return $div->__toString();
  3539. }
  3540. }
  3541. ?>