Thread: [Pieforms-commit] SF.net SVN: pieforms: [54] pieforms-php5/trunk/src/pieform.php
Status: Alpha
Brought to you by:
oracleshinoda
From: <ora...@us...> - 2006-11-20 13:04:21
|
Revision: 54 http://svn.sourceforge.net/pieforms/?rev=54&view=rev Author: oracleshinoda Date: 2006-11-20 05:04:21 -0800 (Mon, 20 Nov 2006) Log Message: ----------- Removed support for prefix and suffix, which should be handled by the renderers now Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-11-20 12:59:58 UTC (rev 53) +++ pieforms-php5/trunk/src/pieform.php 2006-11-20 13:04:21 UTC (rev 54) @@ -1250,16 +1250,11 @@ // @todo reverse order of parameters for consistency, a Form object first $builtelement = $function($element, $form); - // Prepare the prefix and suffix - // @tod REMOVE THIS: each renderer should support it seperately - $prefix = (isset($element['prefix'])) ? $element['prefix'] : ''; - $suffix = (isset($element['suffix'])) ? $element['suffix'] : ''; - // Remove the 'autofocus' class, because we only want it on the form input // itself, not the wrapping HTML $element['class'] = preg_replace('/\s?autofocus/', '', $element['class']); - return $prefix . $rendererfunction($form, $builtelement, $element) . $suffix; + return $rendererfunction($form, $builtelement, $element); } ?> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-11-20 13:05:54
|
Revision: 55 http://svn.sourceforge.net/pieforms/?rev=55&view=rev Author: oracleshinoda Date: 2006-11-20 05:05:53 -0800 (Mon, 20 Nov 2006) Log Message: ----------- Removed some commented out cruft Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-11-20 13:04:21 UTC (rev 54) +++ pieforms-php5/trunk/src/pieform.php 2006-11-20 13:05:53 UTC (rev 55) @@ -1224,12 +1224,6 @@ // Make sure that the function to render the element type is available $function = 'pieform_render_' . $element['type']; - //if (!function_exists($function)) { - // @include('pieform/elements/' . $element['type'] . '.php'); - // if (!function_exists($function)) { - // throw new PieformException('No such form element: ' . $element['type']); - // } - //} // Work out the renderer function required and make sure it exists if ($renderer = $form->get_renderer()) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-11-21 12:34:56
|
Revision: 59 http://svn.sourceforge.net/pieforms/?rev=59&view=rev Author: oracleshinoda Date: 2006-11-21 04:34:54 -0800 (Tue, 21 Nov 2006) Log Message: ----------- Allow the element name to be set in the element array itself. Compatibility with the future perl version Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-11-21 01:53:20 UTC (rev 58) +++ pieforms-php5/trunk/src/pieform.php 2006-11-21 12:34:54 UTC (rev 59) @@ -401,6 +401,10 @@ // Set some attributes for all elements $autofocusadded = false; foreach ($this->elements as $name => &$element) { + // The name can be in the element itself. This is compatibility for the perl version + if (isset($element['name'])) { + $name = $element['name']; + } if (count($element) == 0) { throw new PieformException('An element in form "' . $this->name . '" has no data'); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-11-21 20:51:55
|
Revision: 60 http://svn.sourceforge.net/pieforms/?rev=60&view=rev Author: oracleshinoda Date: 2006-11-21 12:51:45 -0800 (Tue, 21 Nov 2006) Log Message: ----------- Don't include markup values in form submission Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-11-21 12:34:54 UTC (rev 59) +++ pieforms-php5/trunk/src/pieform.php 2006-11-21 20:51:45 UTC (rev 60) @@ -784,7 +784,9 @@ $result = array(); $global = ($this->method == 'get') ? $_GET : $_POST; foreach ($this->get_elements() as $element) { - $result[$element['name']] = $this->get_value($element); + if ($element['type'] != 'markup') {j + $result[$element['name']] = $this->get_value($element); + } } return $result; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-11-21 20:53:23
|
Revision: 61 http://svn.sourceforge.net/pieforms/?rev=61&view=rev Author: oracleshinoda Date: 2006-11-21 12:53:11 -0800 (Tue, 21 Nov 2006) Log Message: ----------- Fixed typo parse error Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-11-21 20:51:45 UTC (rev 60) +++ pieforms-php5/trunk/src/pieform.php 2006-11-21 20:53:11 UTC (rev 61) @@ -784,7 +784,7 @@ $result = array(); $global = ($this->method == 'get') ? $_GET : $_POST; foreach ($this->get_elements() as $element) { - if ($element['type'] != 'markup') {j + if ($element['type'] != 'markup') { $result[$element['name']] = $this->get_value($element); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2007-12-31 02:00:10
|
Revision: 254 http://pieforms.svn.sourceforge.net/pieforms/?rev=254&view=rev Author: oracleshinoda Date: 2007-12-30 18:00:15 -0800 (Sun, 30 Dec 2007) Log Message: ----------- A new datastructure to speed up and simplify looping through elements. Added 'elementrefs' structure, containing references to all elements in the form, minus fieldsets. Changed calls to get_elements to use elementrefs. Simplified a bunch of code using this. For example, a whole bunch of duplicated checking in the constructor has been consolidated now that it's easier to loop through all elements without having to take fieldsets into account. Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2007-12-31 01:59:52 UTC (rev 253) +++ pieforms-php5/trunk/src/pieform.php 2007-12-31 02:00:15 UTC (rev 254) @@ -123,6 +123,15 @@ private $data = array(); /** + * A hash of references to the elements of the form, not including + * fieldsets (although including all elements inside any fieldsets. Used internally + * for simplifying looping over elements + * + * @var array + */ + private $elementrefs = array(); + + /** * Whether this form includes a file element. If so, the enctype attribute * for the form will be specified as "multipart/mixed" as required. This * is auto-detected by the Pieform class. @@ -328,165 +337,123 @@ throw new PieformException('Forms must have a list of elements'); } - // Rename all the keys to have nice compliant names - // @todo: - // - This isn't done for elements inside fieldsets - // - There's no easy way for other things do do all this preprocessing if they - // need. It should be a method so that other things (like multirecord) - // can use it. - $elements = array(); - foreach ($this->data['elements'] as $name => $element) { - $newname = preg_replace('/[^a-zA-Z0-9_]/', '_', $name); - if (isset($elements[$name])) { - throw new PieformException('Element "' . $name . '" has a dangerous name that interferes with another element'); + // Get references to all the elements in the form, excluding fieldsets + foreach ($this->data['elements'] as $name => &$_element) { + if (isset($_element['type']) && $_element['type'] == 'fieldset') { + // Load the fieldset plugin as we know this form has one now + $this->include_plugin('element', 'fieldset'); + if ($this->get_property('template')) { + self::info("Your form '$this->name' has a fieldset, but is using a template. Fieldsets make no sense when using templates"); + } + + foreach ($_element['elements'] as $subname => &$_subelement) { + $this->elementrefs[$subname] = &$_subelement; + } } - $elements[$newname] = $element; + else { + $this->elementrefs[$name] = &$_element; + } } - $this->data['elements'] = $elements; + // Check that all elements have names compliant to PHP's variable naming policy + // (otherwise things get messy later) + foreach (array_keys($this->elementrefs) as $name) { + if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $name)) { + throw new PieformException('Element "' . $name . '" is badly named (validity test: could you give a PHP variable the name?)'); + } + } + // Remove elements to ignore + // This can't be done using $this->elementrefs, because you can't unset + // an entry in there and have it unset the entry in $this->data['elements'] foreach ($this->data['elements'] as $name => $element) { if (isset($element['type']) && $element['type'] == 'fieldset') { foreach ($element['elements'] as $subname => $subelement) { if (!empty($subelement['ignore'])) { unset ($this->data['elements'][$name]['elements'][$subname]); + unset($this->elementrefs[$subname]); } } } else { if (!empty($element['ignore'])) { unset($this->data['elements'][$name]); + unset($this->elementrefs[$name]); } } } // Set some attributes for all elements $autofocusadded = false; - foreach ($this->data['elements'] as $name => &$element) { + foreach ($this->elementrefs as $name => &$element) { // @todo re-check ordering of this section - // The name can be in the element itself. This is compatibility for the perl version - if (isset($element['name'])) { - $name = $element['name']; - } if (count($element) == 0) { throw new PieformException('An element in form "' . $this->name . '" has no data (' . $name . ')'); } - if (!isset($element['type'])) { + + if (!isset($element['type']) || $element['type'] == 'markup') { $element['type'] = 'markup'; if (!isset($element['value'])) { throw new PieformException('The markup element "' . $name . '" has no value'); } } - if (!isset($element['title'])) { - $element['title'] = ''; - } - if ($element['type'] == 'file') { - $this->fileupload = true; - if ($this->data['method'] == 'get') { - $this->data['method'] = 'post'; - self::info("Your form '$this->name' had the method 'get' and also a file element - it has been converted to 'post'"); + else { + // Now we know what type the element is, we can load the plugin for it + $this->include_plugin('element', $element['type']); + + // The name can be in the element itself. This is compatibility for the perl version + if (isset($element['name'])) { + $name = $element['name']; } - } - if ($element['type'] == 'fieldset') { - if ($this->get_property('template')) { - self::info("Your form '$this->name' has a fieldset, but is using a template. Fieldsets make no sense when using templates"); + + // All elements should have at least the title key set + if (!isset($element['title'])) { + $element['title'] = ''; } - $this->include_plugin('element', 'fieldset'); - foreach ($element['elements'] as $subname => &$subelement) { - // The name can be in the element itself. This is compatibility for the perl version - if (isset($subelement['name'])) { - $subname = $subelement['name']; - } - if (count($subelement) == 0) { - throw new PieformException('An element in form "' . $this->name . '" has no data (' . $subname . ')'); - } - if (!isset($subelement['type'])) { - $subelement['type'] = 'markup'; - if (!isset($subelement['value'])) { - throw new PieformException('The markup element "' - . $name . '" has no value'); - } - } - // Configure some basics for real elements - if ($subelement['type'] != 'markup') { - // This function can be defined by the application using Pieforms, - // and applies to all elements of this type - $function = 'pieform_element_' . $subelement['type'] . '_configure'; - if (function_exists($function)) { - $subelement = $function($subelement); - } - - // This function is defined by the plugin itself, to set fields on - // the element that need to be set but should not be set by the - // application - $function = 'pieform_element_' . $subelement['type'] . '_set_attributes'; - $this->include_plugin('element', $subelement['type']); - if (function_exists($function)) { - $subelement = $function($subelement); - } - - // Add the autofocus flag to the element if required - if (!$autofocusadded && $this->data['autofocus'] === true && empty($element['nofocus'])) { - $subelement['autofocus'] = true; - $autofocusadded = true; - } - else if (!empty($this->data['autofocus']) && $this->data['autofocus'] !== true - && $subname == $this->data['autofocus']) { - $subelement['autofocus'] = true; - } - - // All elements should have some kind of title - if (!isset($subelement['title'])) { - $subelement['title'] = ''; - } - - // Force the form method to post if there is a file to upload. - if ($subelement['type'] == 'file') { - $this->fileupload = true; - if ($this->data['method'] == 'get') { - $this->data['method'] = 'post'; - self::info("Your form '$this->name' had the method 'get' and also a file element - it has been converted to 'post'"); - } - } - - // All elements inherit the form tabindex - $subelement['tabindex'] = $this->data['tabindex']; + // Force the form method to post if there is a file to upload + if ($element['type'] == 'file') { + $this->fileupload = true; + if ($this->data['method'] == 'get') { + $this->data['method'] = 'post'; + self::info("Your form '$this->name' had the method 'get' and also a file element - it has been converted to 'post'"); } - $subelement['name'] = $subname; + } + // This function can be defined by the application using Pieforms, + // and applies to all elements of this type + $function = 'pieform_element_' . $element['type'] . '_configure'; + if (function_exists($function)) { + $element = $function($element); } - } - else { - // Let each element set and override attributes if necessary - if ($element['type'] != 'markup') { - $function = 'pieform_element_' . $element['type'] . '_configure'; - if (function_exists($function)) { - $element = $function($element); - } - $function = 'pieform_element_' . $element['type'] . '_set_attributes'; - $this->include_plugin('element', $element['type']); - if (function_exists($function)) { - $element = $function($element); - } + // vvv --------------------------------------------------- vvv + // After this point Pieforms can set or override attributes + // without fear that the developer will be able to change them. - // Add the autofocus flag to the element if required - if (!$autofocusadded && $this->data['autofocus'] === true && empty($element['nofocus'])) { - $element['autofocus'] = true; - $autofocusadded = true; - } - elseif (!empty($this->data['autofocus']) && $this->data['autofocus'] !== true - && $name == $this->data['autofocus']) { - $element['autofocus'] = true; - } + // This function is defined by the plugin itself, to set + // fields on the element that need to be set but should not + // be set by the application + $function = 'pieform_element_' . $element['type'] . '_set_attributes'; + if (function_exists($function)) { + $element = $function($element); + } - $element['tabindex'] = $this->data['tabindex']; + // Add the autofocus flag to the element if required + if (!$autofocusadded && $this->data['autofocus'] === true && empty($element['nofocus'])) { + $element['autofocus'] = true; + $autofocusadded = true; } - $element['name'] = $name; - } + elseif (!empty($this->data['autofocus']) && $this->data['autofocus'] !== true + && $name == $this->data['autofocus']) { + $element['autofocus'] = true; + } + // All elements inherit the form tabindex + $element['tabindex'] = $this->data['tabindex']; + } + $element['name'] = $name; } // Check if the form was submitted, and if so, validate and process it @@ -528,7 +495,7 @@ // Submit the form if things went OK if ($this->data['submit'] && !$this->has_errors()) { $submitted = false; - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if (!empty($element['submitelement']) && isset($global[$element['name']])) { $function = "{$this->data['successcallback']}_{$element['name']}"; if (function_exists($function)) { @@ -543,10 +510,8 @@ // Call the user defined function for processing a submit // This function should really redirect/exit after it has // finished processing the form. - // @todo maybe it should do just that... call_user_func_array($function, array($this, $values)); if ($this->data['dieaftersubmit']) { - // This will only work if I can make the login_submit function stuff work in login_validate if ($this->data['jsform']) { $message = 'Your ' . $this->name . '_submit function should use $form->json_reply to send a response'; } @@ -565,6 +530,8 @@ } } + // If we get here, the form was submitted but failed validation + // Auto focus the first element with an error if required if ($this->data['autofocus'] !== false) { $this->auto_focus_first_error(); @@ -642,9 +609,10 @@ }/*}}}*/ /** - * Builds and returns the HTML for the form, respecting the chosen renderer. + * Builds and returns the HTML for the form, using the chosen renderer or + * template * - * Note that the "action" attribute for the form tag are NOT HTML escaped + * Note that the "action" attribute for the form tag is NOT HTML escaped * for you. This allows you to build your own URLs, should you require. On * the other hand, this means you must be careful about escaping the URL, * especially if it has data from an external source in it. @@ -675,7 +643,7 @@ // $elements is a convenience variable that contains all of the form elements (minus fieldsets and // hidden elements) $elements = array(); - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if ($element['type'] != 'hidden') { $elements[$element['name']] = $element; } @@ -684,7 +652,7 @@ // Hidden elements $this->include_plugin('element', 'hidden'); $hidden_elements = ''; - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if ($element['type'] == 'hidden') { $hidden_elements .= pieform_element_hidden($this, $element); } @@ -743,7 +711,7 @@ // Hidden elements $this->include_plugin('element', 'hidden'); - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if ($element['type'] == 'hidden') { $result .= pieform_element_hidden($this, $element); } @@ -828,7 +796,7 @@ } return $elements; }/*}}}*/ - + /** * Returns the element with the given name. Throws a PieformException if the * element cannot be found. @@ -841,11 +809,10 @@ * @throws PieformException If the element could not be found */ public function get_element($name) {/*{{{*/ - foreach ($this->get_elements() as $element) { - if ($element['name'] == $name) { - return $element; - } + if (isset($this->elementrefs[$name])) { + return $this->elementrefs[$name]; } + throw new PieformException('Element "' . $name . '" cannot be found'); }/*}}}*/ @@ -864,7 +831,7 @@ private function get_submitted_values() {/*{{{*/ $result = array(); $global = ($this->data['method'] == 'get') ? $_GET : $_POST; - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if ($element['type'] != 'markup') { if ( (empty($element['submitelement']) && empty($element['cancelelement'])) || @@ -900,7 +867,7 @@ } // Perform rule validation - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if (isset($element['rules']) && is_array($element['rules'])) { foreach ($element['rules'] as $rule => $data) { if (!$this->get_error($element['name'])) { @@ -936,7 +903,7 @@ $result = "var {$this->name}_btn = null;\n"; $connecteventadded = false; - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if (!empty($element['submitelement'])) { if (!$connecteventadded) { $result .= "addLoadEvent(function() {\n"; @@ -1244,7 +1211,7 @@ * @return bool Whether there are errors with the form */ public function has_errors() {/*{{{*/ - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if (isset($element['error'])) { return true; } @@ -1371,7 +1338,7 @@ */ public function get_errors() {/*{{{*/ $result = array(); - foreach ($this->get_elements() as $element) { + foreach ($this->elementrefs as $element) { if (isset($element['error'])) { $result[] = $element; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-11-22 00:39:23
|
Revision: 65 http://svn.sourceforge.net/pieforms/?rev=65&view=rev Author: oracleshinoda Date: 2006-11-21 16:39:23 -0800 (Tue, 21 Nov 2006) Log Message: ----------- Return value after validating the js callback. Added i18n for the regex rule Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-11-21 22:43:47 UTC (rev 64) +++ pieforms-php5/trunk/src/pieform.php 2006-11-22 00:39:23 UTC (rev 65) @@ -238,7 +238,8 @@ 'maxlength' => 'This field must be at most %d characters long', 'minlength' => 'This field must be at least %d characters long', 'integer' => 'The field must be an integer', - 'validateoptions' => 'The option "%s" is invalid' + 'validateoptions' => 'The option "%s" is invalid', + 'regex' => 'This field is not in valid form' ) ); @@ -1161,6 +1162,7 @@ if (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $name)) { throw new PieformException("'$name' is not a valid javascript callback name"); } + return $name; } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-11-22 20:54:10
|
Revision: 67 http://svn.sourceforge.net/pieforms/?rev=67&view=rev Author: oracleshinoda Date: 2006-11-22 12:54:03 -0800 (Wed, 22 Nov 2006) Log Message: ----------- Allow elements to have an 'ignore' parameter - if set, the element will not be output. Useful for keeping form definitions as one big array, instead of if statements and ['foo'] =... madness everywhere. Also copied a couple of checks to fieldset elements Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-11-22 00:40:42 UTC (rev 66) +++ pieforms-php5/trunk/src/pieform.php 2006-11-22 20:54:03 UTC (rev 67) @@ -402,12 +402,16 @@ // Set some attributes for all elements $autofocusadded = false; foreach ($this->elements as $name => &$element) { + if (!empty($element['ignore'])) { + unset($this->elements[$name]); + continue; + } // The name can be in the element itself. This is compatibility for the perl version if (isset($element['name'])) { $name = $element['name']; } if (count($element) == 0) { - throw new PieformException('An element in form "' . $this->name . '" has no data'); + throw new PieformException('An element in form "' . $this->name . '" has no data (' . $name . ')'); } if (!isset($element['type'])) { $element['type'] = 'markup'; @@ -428,6 +432,17 @@ } if ($element['type'] == 'fieldset') { foreach ($element['elements'] as $subname => &$subelement) { + if (!empty($subelement['ignore'])) { + unset($element['elements'][$subname]); + continue; + } + // The name can be in the element itself. This is compatibility for the perl version + if (isset($subelement['name'])) { + $subname = $subelement['name']; + } + if (count($subelement) == 0) { + throw new PieformException('An element in form "' . $this->name . '" has no data (' . $subname . ')'); + } if (!isset($subelement['type'])) { $subelement['type'] = 'markup'; if (!isset($subelement['value'])) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-11-23 10:41:27
|
Revision: 69 http://svn.sourceforge.net/pieforms/?rev=69&view=rev Author: oracleshinoda Date: 2006-11-23 02:41:27 -0800 (Thu, 23 Nov 2006) Log Message: ----------- Implemented ignoring properly, unsetting the elements while going around the default setting loop wasn't working properly Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-11-23 01:06:00 UTC (rev 68) +++ pieforms-php5/trunk/src/pieform.php 2006-11-23 10:41:27 UTC (rev 69) @@ -397,15 +397,28 @@ if (!is_array($data['elements']) || count($data['elements']) == 0) { throw new PieformException('Forms must have a list of elements'); } + + // Remove elements to ignore + foreach ($data['elements'] as $name => $element) { + if (isset($element['type']) && $element['type'] == 'fieldset') { + foreach ($element['elements'] as $subname => $subelement) { + if (!empty($subelement['ignore'])) { + unset ($data['elements'][$name]['elements'][$subname]); + } + } + } + else { + if (!empty($element['ignore'])) { + unset($data['elements'][$name]); + } + } + } + $this->elements = $data['elements']; // Set some attributes for all elements $autofocusadded = false; foreach ($this->elements as $name => &$element) { - if (!empty($element['ignore'])) { - unset($this->elements[$name]); - continue; - } // The name can be in the element itself. This is compatibility for the perl version if (isset($element['name'])) { $name = $element['name']; @@ -432,10 +445,6 @@ } if ($element['type'] == 'fieldset') { foreach ($element['elements'] as $subname => &$subelement) { - if (!empty($subelement['ignore'])) { - unset($element['elements'][$subname]); - continue; - } // The name can be in the element itself. This is compatibility for the perl version if (isset($subelement['name'])) { $subname = $subelement['name']; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-07 05:49:42
|
Revision: 83 http://svn.sourceforge.net/pieforms/?rev=83&view=rev Author: oracleshinoda Date: 2006-12-06 21:43:30 -0800 (Wed, 06 Dec 2006) Log Message: ----------- Did one of the TODO items - use MochiKit's connect() to handle the form submission. Made sure that elements have their 'id' attribute have the form name put on the front, so more than one form can be used on the same page successfully. Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-07 05:41:51 UTC (rev 82) +++ pieforms-php5/trunk/src/pieform.php 2006-12-07 05:43:30 UTC (rev 83) @@ -66,7 +66,6 @@ // // - more form element types (inc. types like autocomplete and date picker and wyswiyg) // - support processing of data before validation occurs (e.g. trim(), strtoupper()) - // - do onsubmit for ajax stuff by mochikit connect() // - Basic validation is possible as there's a callback function for checking, // but some helper functions could be written to make people's job validating // stuff much easier (form_validate_email, form_validate_date etc). @@ -328,7 +327,6 @@ $formdefaults = array( 'method' => 'get', 'action' => '', - 'onsubmit' => '', 'ajaxpost' => false, 'preajaxsubmitcallback' => '', 'postajaxsubmitcallback' => '', @@ -354,7 +352,6 @@ $this->action = $data['action']; $this->validate = $data['validate']; $this->submit = $data['submit']; - $this->onsubmit = $data['onsubmit']; $this->autofocus = $data['autofocus']; $this->language = $data['language']; @@ -683,9 +680,6 @@ if ($this->fileupload) { $result .= ' enctype="multipart/form-data"'; } - if ($this->ajaxpost) { - $result .= ' onsubmit="' . $this->name . '_submit(); return false;"'; - } $result .= ">\n"; // @todo masks attempts in pieform_render_element, including the error handling there @@ -871,7 +865,8 @@ private function submit_js() { // @todo nigel should disable all buttons on this form while the submit is happening $result = <<<EOF -function {$this->name}_submit() { + +connect($('{$this->name}'), 'onsubmit', function (e) { // eventually we should check input types for wysiwyg before doing this // Also should only save wysiwyg elements in the form, not all of them... if (typeof(tinyMCE) != 'undefined') { tinyMCE.triggerSave(); } @@ -961,8 +956,8 @@ $result .= <<<EOF }); {$this->name}_message('{$strprocessingform}', 'info'); - return false; -} + e.stop(); +}); EOF; @@ -1110,12 +1105,15 @@ * @param array $exclude Any attributes to explicitly exclude from adding * @return string The attributes for the element */ - public static function element_attributes($element, $exclude=array()) { + public function element_attributes($element, $exclude=array()) { static $attributes = array('accesskey', 'class', 'dir', 'id', 'lang', 'name', 'onclick', 'size', 'style', 'tabindex'); $elementattributes = array_diff($attributes, $exclude); $result = ''; foreach ($elementattributes as $attribute) { if (isset($element[$attribute]) && $element[$attribute] !== '') { + if ($attribute == 'id') { + $element[$attribute] = $this->name . '_' . $element[$attribute]; + } $result .= ' ' . $attribute . '="' . self::hsc($element[$attribute]) . '"'; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-08 02:11:56
|
Revision: 85 http://svn.sourceforge.net/pieforms/?rev=85&view=rev Author: oracleshinoda Date: 2006-12-07 18:11:55 -0800 (Thu, 07 Dec 2006) Log Message: ----------- Standardised how plugins are included Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-08 02:09:46 UTC (rev 84) +++ pieforms-php5/trunk/src/pieform.php 2006-12-08 02:11:55 UTC (rev 85) @@ -72,7 +72,6 @@ // - Collapsible js for fieldsets // - Grippie for textareas // - javascript validation - // - handle multiple submit buttons // - handle multipage forms? // - handle a tabbed interface type of form? // @@ -203,6 +202,13 @@ private $tabindex = 1; /** + * Directories to look for elements, renderers and rules + * + * @var array + */ + private $configdirs = array(); + + /** * Whether to autofocus fields in this form, and if so, optionally which * field to focus. * @@ -332,11 +338,12 @@ 'postajaxsubmitcallback' => '', 'ajaxsuccessfunction' => '', 'ajaxfailurefunction' => '', - 'autofocus' => false, - 'language' => 'en.utf8', - 'validate' => true, - 'submit' => true, - 'elements' => array(), + 'configdirs' => array(), + 'autofocus' => false, + 'language' => 'en.utf8', + 'validate' => true, + 'submit' => true, + 'elements' => array(), 'submitfunction' => '', 'validatefunction' => '', ); @@ -348,12 +355,15 @@ if ($data['method'] != 'post') { $data['method'] = 'get'; } - $this->method = $data['method']; - $this->action = $data['action']; - $this->validate = $data['validate']; - $this->submit = $data['submit']; - $this->autofocus = $data['autofocus']; - $this->language = $data['language']; + $this->method = $data['method']; + $this->action = $data['action']; + $this->validate = $data['validate']; + $this->submit = $data['submit']; + $this->configdirs = array_map( + create_function('$a', 'return substr($a, -1) == "/" ? substr($a, 0, -1) : $a;'), + (array) $data['configdirs']); + $this->autofocus = $data['autofocus']; + $this->language = $data['language']; if ($data['submitfunction']) { $this->submitfunction = $data['submitfunction']; @@ -480,7 +490,7 @@ // Let each element set and override attributes if necessary if ($subelement['type'] != 'markup') { $function = 'pieform_render_' . $subelement['type'] . '_set_attributes'; - require_once('pieform/elements/' . $subelement['type'] . '.php'); + $this->include_plugin('element', $subelement['type']); if (function_exists($function)) { $subelement = $function($subelement); } @@ -506,7 +516,7 @@ // @todo here, all elements are loaded that will be used, so no // need to include files for them later (like in pieform_render_element) // Also, don't use require_once so nicer errors can be thrown - require_once('pieform/elements/' . $element['type'] . '.php'); + $this->include_plugin('element', $element['type']); if (function_exists($function)) { $element = $function($element); } @@ -683,7 +693,7 @@ $result .= ">\n"; // @todo masks attempts in pieform_render_element, including the error handling there - @include_once('pieform/renderers/' . $this->renderer . '.php'); + $this->include_plugin('renderer', $this->renderer); // Form header $function = 'pieform_renderer_' . $this->renderer . '_header'; @@ -705,7 +715,7 @@ } // Hidden elements - require_once('pieform/elements/hidden.php'); + $this->include_plugin('element', 'hidden'); foreach ($this->get_elements() as $element) { if ($element['type'] == 'hidden') { $result .= pieform_render_hidden($element, $this); @@ -737,9 +747,6 @@ */ public function get_value($element) { $function = 'pieform_get_value_' . $element['type']; - if (!function_exists($function)) { - @include_once('pieform/elements/' . $element['type'] . '.php'); - } // @todo for consistency, reverse parameter order - always a Form object first if (function_exists($function)) { return $function($element, $this); @@ -843,7 +850,7 @@ // Get the rule $function = 'pieform_rule_' . $rule; if (!function_exists($function)) { - @include_once('pieform/rules/' . $rule . '.php'); + $this->include_plugin('rule', $rule); if (!function_exists($function)) { throw new PieformException('No such form rule "' . $rule . '"'); } @@ -963,7 +970,7 @@ $js_messages_function = 'pieform_renderer_' . $this->renderer . '_messages_js'; if (!function_exists($js_messages_function)) { - @include_once('pieform/renderers/' . $this->renderer . '.php'); + $this->include_plugin('renderer', $this->renderer); if (!function_exists($js_messages_function)) { throw new PieformException('No renderer message function "' . $js_messages_function . '"'); } @@ -1146,6 +1153,37 @@ } /** + * Includes a plugin file, checking any configured plugin directories. + * + * @param string $type The type of plugin to include: 'element', 'renderer' or 'rule' + * @param string $name The name of the plugin to include + * @throws PieformException If the given type or plugin could not be found + */ + public function include_plugin($type, $name) { + if (!in_array($type, array('element', 'renderer', 'rule'))) { + throw new PieformException("The type \"$type\" is not allowed for an include plugin"); + } + + // Check the configured include paths if they are specified + foreach ($this->configdirs as $directory) { + $file = "$directory/{$type}s/$name.php"; + if (is_readable($file)) { + include_once($file); + return; + } + } + + // Check the default include path + $file = dirname(__FILE__) . "/pieform/{$type}s/{$name}.php"; + if (is_readable($file)) { + include_once($file); + return; + } + + throw new PieformException("Could not find $type \"$name\""); + } + + /** * Return an internationalised string based on the passed input key * * Returns english by default. @@ -1272,7 +1310,7 @@ if ($renderer = $form->get_renderer()) { $rendererfunction = 'pieform_renderer_' . $renderer; if (!function_exists($rendererfunction)) { - include('pieform/renderers/' . $renderer . '.php'); + $form->include_plugin('pieform/renderers/' . $renderer . '.php'); if (!function_exists($rendererfunction)) { throw new PieformException('No such form renderer: "' . $renderer . '"'); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-10 10:59:29
|
Revision: 90 http://svn.sourceforge.net/pieforms/?rev=90&view=rev Author: oracleshinoda Date: 2006-12-10 02:59:26 -0800 (Sun, 10 Dec 2006) Log Message: ----------- Allowed each element to specify a function that returns an array of HTML items that should be used to set the object up. Useful for calendar/wysiwyg. Also allowed the user to define a function to configure the default form of any element type. Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-10 10:57:41 UTC (rev 89) +++ pieforms-php5/trunk/src/pieform.php 2006-12-10 10:59:26 UTC (rev 90) @@ -24,6 +24,8 @@ * */ +$GLOBALS['_PIEFORM_REGISTRY'] = array(); + /** * Builds, validates and processes a form. * @@ -310,6 +312,8 @@ * @param array $data The form description hash */ public function __construct($data) { + $GLOBALS['_PIEFORM_REGISTRY'][] = $this; + if (!isset($data['name']) || !preg_match('/^[a-z_][a-z0-9_]*$/', $data['name'])) { throw new PieformException('Forms must have a name, and that name must be valid (validity test: could you give a PHP function the name?)'); } @@ -489,6 +493,16 @@ // Let each element set and override attributes if necessary if ($subelement['type'] != 'markup') { + // This function can be defined by the application using Pieforms, + // and applies to all elements of this type + $function = 'pieform_configure_' . $subelement['type']; + if (function_exists($function)) { + $subelement = $function($subelement); + } + + // This function is defined by the plugin itself, to set fields on + // the element that need to be set but should not be set by the + // application $function = 'pieform_render_' . $subelement['type'] . '_set_attributes'; $this->include_plugin('element', $subelement['type']); if (function_exists($function)) { @@ -512,10 +526,12 @@ // Let each element set and override attributes if necessary if ($element['type'] != 'markup') { + $function = 'pieform_configure_' . $element['type']; + if (function_exists($function)) { + $element = $function($element); + } + $function = 'pieform_render_' . $element['type'] . '_set_attributes'; - // @todo here, all elements are loaded that will be used, so no - // need to include files for them later (like in pieform_render_element) - // Also, don't use require_once so nicer errors can be thrown $this->include_plugin('element', $element['type']); if (function_exists($function)) { $element = $function($element); @@ -1332,4 +1348,19 @@ return $rendererfunction($form, $builtelement, $element); } +function pieform_get_headdata() { + $htmlelements = array(); + foreach ($GLOBALS['_PIEFORM_REGISTRY'] as $form) { + foreach ($form->get_elements() as $element) { + $function = 'pieform_get_headdata_' . $element['type']; + if (function_exists($function)) { + $elems = $function($element); + $htmlelements = array_merge($htmlelements, $elems); + } + } + } + + return array_unique($htmlelements); +} + ?> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-15 01:30:15
|
Revision: 98 http://svn.sourceforge.net/pieforms/?rev=98&view=rev Author: oracleshinoda Date: 2006-12-14 17:30:15 -0800 (Thu, 14 Dec 2006) Log Message: ----------- Fixed support for multiple submit buttons with their own function (Alastair Pharo) Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-15 01:28:52 UTC (rev 97) +++ pieforms-php5/trunk/src/pieform.php 2006-12-15 01:30:15 UTC (rev 98) @@ -582,7 +582,7 @@ $submitted = false; foreach ($this->get_elements() as $element) { // @todo Rename 'ajaxmessages' to 'submitelement' - if (!empty($element['ajaxmessages']) == true && isset($values[$element['name']])) { + if (!empty($element['ajaxmessages']) == true && isset($global[$element['name']])) { $function = "{$this->name}_submit_{$element['name']}"; if (function_exists($function)) { $function($values); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-17 23:24:50
|
Revision: 99 http://svn.sourceforge.net/pieforms/?rev=99&view=rev Author: oracleshinoda Date: 2006-12-17 15:24:49 -0800 (Sun, 17 Dec 2006) Log Message: ----------- Be much smarter about which submit button is being sent through in ajax land. This prevents problems with all buttons being sent through and thus causing hiccups with the choice of submit function to call. It also conveniently makes sure that the status messages will always be displayed next to the correct button Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-15 01:30:15 UTC (rev 98) +++ pieforms-php5/trunk/src/pieform.php 2006-12-17 23:24:49 UTC (rev 99) @@ -889,6 +889,20 @@ // @todo nigel should disable all buttons on this form while the submit is happening $result = <<<EOF +var {$this->name}_btn = null; +// For each submit button, add a waffer thin flag +addLoadEvent(function () { + +EOF; + foreach ($this->get_elements() as $element) { + if (!empty($element['ajaxmessages'])) { + $result .= " connect($('{$this->name}_{$element['name']}'), 'onclick', function () { {$this->name}_btn = '{$element['name']}'; });\n"; + } + } + $result .= <<<EOF + +}); + connect($('{$this->name}'), 'onsubmit', function (e) { // eventually we should check input types for wysiwyg before doing this // Also should only save wysiwyg elements in the form, not all of them... @@ -904,24 +918,23 @@ EOF; // Get values for each element from the form via the DOM foreach ($this->get_elements() as $element) { - if ($element['type'] != 'markup') { - $function = 'pieform_get_value_js_' . $element['type']; - if (function_exists($function)) { - // @todo reverse parameter order for consistency, PieForm first - $result .= $function($element, $this); + // Submit elements will be handled later, as there could be more than one + if (empty($element['ajaxmessages'])) { + if ($element['type'] != 'markup') { + $function = 'pieform_get_value_js_' . $element['type']; + if (function_exists($function)) { + // @todo reverse parameter order for consistency, PieForm first + $result .= $function($element, $this); + } + else { + $result .= " data['" . $element['name'] . "'] = document.forms['$this->name'].elements['{$element['name']}'].value;\n"; + } } - else { - $result .= " data['" . $element['name'] . "'] = document.forms['$this->name'].elements['{$element['name']}'].value;\n"; - } - if (!empty($element['ajaxmessages'])) { - $messageelement = $element['name']; - } } } - if (!isset($messageelement)) { - throw new PieformException('At least one submit-type element is required for AJAX forms'); - } + // Add only the submit button that was clicked + $result .= " data['{$this->name}_' + {$this->name}_btn] = document.forms['$this->name'].elements['{$this->name}_' + {$this->name}_btn].value;\n"; // Add the hidden element for detecting form submission $result .= " data['pieform_{$this->name}'] = '';\n"; @@ -992,7 +1005,7 @@ } } - return $result . $js_messages_function($this->name, $messageelement); + return $result . $js_messages_function($this->name); } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-18 00:41:31
|
Revision: 102 http://svn.sourceforge.net/pieforms/?rev=102&view=rev Author: oracleshinoda Date: 2006-12-17 16:41:26 -0800 (Sun, 17 Dec 2006) Log Message: ----------- Allowed the form tag to be retrieved separately from the rest of the form, which allows more flexibility in how the form is built. Hopefully fix up the passing of the submit value for ajax calls now as well Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-17 23:27:39 UTC (rev 101) +++ pieforms-php5/trunk/src/pieform.php 2006-12-18 00:41:26 UTC (rev 102) @@ -679,6 +679,24 @@ } /** + * Returns the HTML for the <form...> tag + * + * @return string + */ + public function get_form_tag() { + $result = '<form'; + foreach (array('name', 'method', 'action') as $attribute) { + $result .= ' ' . $attribute . '="' . $this->{$attribute} . '"'; + } + $result .= ' id="' . $this->name . '"'; + if ($this->fileupload) { + $result .= ' enctype="multipart/form-data"'; + } + $result .= '>'; + return $result; + } + + /** * Returns whether the form has been submitted * * @return bool @@ -695,20 +713,15 @@ * the other hand, this means you must be careful about escaping the URL, * especially if it has data from an external source in it. * + * @param boolean Whether to include the <form...></form> tags in the output * @return string The form as HTML */ - public function build() { - $result = '<form'; - foreach (array('name', 'method', 'action') as $attribute) { - $result .= ' ' . $attribute . '="' . $this->{$attribute} . '"'; + public function build($outputformtags=true) { + $result = ''; + if ($outputformtags) { + $result = $this->get_form_tag() . "\n"; } - $result .= ' id="' . $this->name . '"'; - if ($this->fileupload) { - $result .= ' enctype="multipart/form-data"'; - } - $result .= ">\n"; - // @todo masks attempts in pieform_render_element, including the error handling there $this->include_plugin('renderer', $this->renderer); // Form header @@ -743,7 +756,9 @@ 'value' => '' ); $result .= pieform_render_hidden($element, $this); - $result .= "</form>\n"; + if ($outputformtags) { + $result .= "</form>\n"; + } if ($this->ajaxpost) { $result .= '<script language="javascript" type="text/javascript">'; @@ -768,6 +783,9 @@ return $function($element, $this); } $global = ($this->method == 'get') ? $_GET : $_POST; + if (!empty($element['ajaxmessages']) && isset($global[$element['name']])) { + return $element['value']; + } if (isset($element['value'])) { return $element['value']; } @@ -934,7 +952,7 @@ } // Add only the submit button that was clicked - $result .= " data['{$this->name}_' + {$this->name}_btn] = document.forms['$this->name'].elements['{$this->name}_' + {$this->name}_btn].value;\n"; + $result .= " data[{$this->name}_btn] = document.forms['$this->name'].elements['{$this->name}_' + {$this->name}_btn].value;\n"; // Add the hidden element for detecting form submission $result .= " data['pieform_{$this->name}'] = '';\n"; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-18 01:11:25
|
Revision: 103 http://svn.sourceforge.net/pieforms/?rev=103&view=rev Author: oracleshinoda Date: 2006-12-17 17:11:25 -0800 (Sun, 17 Dec 2006) Log Message: ----------- Actually make multiplebutton ajax submit work reasonably well now... Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-18 00:41:26 UTC (rev 102) +++ pieforms-php5/trunk/src/pieform.php 2006-12-18 01:11:25 UTC (rev 103) @@ -783,10 +783,13 @@ return $function($element, $this); } $global = ($this->method == 'get') ? $_GET : $_POST; - if (!empty($element['ajaxmessages']) && isset($global[$element['name']])) { + // If the element is a submit element and has its value in the request, return it + // Otherwise, we don't return the value if the form has been submitted, as they + // aren't normally returned using a standard form. + if (isset($element['value']) && !empty($element['ajaxmessages']) && isset($global[$element['name']])) { return $element['value']; } - if (isset($element['value'])) { + else if (isset($element['value']) && (!$this->is_submitted() || (empty($element['ajaxmessages'])))) { return $element['value']; } else if (isset($global[$element['name']]) && $element['type'] != 'submit') { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-23 03:36:12
|
Revision: 105 http://svn.sourceforge.net/pieforms/?rev=105&view=rev Author: oracleshinoda Date: 2006-12-22 19:36:11 -0800 (Fri, 22 Dec 2006) Log Message: ----------- * Updated the comment on the Pieform class to better reflect the API changes being made * Only include the JSON library when json_encode is first called * Moved all of the user-configurable flags for the class into one member variable, 'data'. * Renamed the ajaxsuccessfunction and ajaxfailurefunction to *callback for consistency * Made the cancel function optional * Made setting $element['goto'] actually work, for both normal forms and AJAX forms * Fixed all submit-based elements to have their value placed in the submit data if they are pressed. * AJAX submission is now no longer strictly AJAX - instead, data is submitted to a hidden iframe. This removes all of the mess around the pieform_get_value_js_[element] functions, and allows sending files (which works fine, even for more than one file). * Now all replies by JSON should be done using the $form->json_reply method, which understands how to reply to a hidden iframe. * Defined some constants for use with $form->json_reply * Full i18n is now built in. Each element can export its own strings, and the user can override them on a per element or per form basis (even for all forms in their application with the pieform_configure function). * API changes: - Renamed pieform_configure_[element] to pieform_element_[element]_configure - Submit functions now take the Pieform object as their first parameter (major BC break!) - pieform_render_element now takes its parameters in reverse order (although this function is largely an internal-only function) - Renamed pieform_get_value_[element] to pieform_element_[element]_get_value - Renamed pieform_render_[element] to pieform_element_[element] (major BC break!) - pieform_element_[element] functions now takes the Pieform object as their first parameter (major BC break!) Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-18 01:12:20 UTC (rev 104) +++ pieforms-php5/trunk/src/pieform.php 2006-12-23 03:36:11 UTC (rev 105) @@ -37,22 +37,22 @@ * <pre> * $form = array( * 'name' => 'myform', - * 'action' => '/myscript.php', + * 'action' => 'myscript.php', * 'method' => 'post', * 'elements' => array( * // definition of elements in the form * ) * ); * - * $smarty->assign('myform', form($form)); + * $smarty->assign('myform', pieform($form)); * - * function myform_validate($form, $values) { + * function myform_validate(Pieform $form, $values) { * // perform validation agains form elements here * // some types of validation are conveniently available already as * // as part of the form definition hash * } * - * function myform_submit($values) { + * function myform_submit(Pieform $form, $values) { * // perform action knowing that the values are valid, e.g. DB insert. * } * </pre> @@ -66,22 +66,22 @@ // // @todo stuff to do for forms: // - // - more form element types (inc. types like autocomplete and date picker and wyswiyg) + // - more form element types (inc. types like autocomplete and wyswiyg) // - support processing of data before validation occurs (e.g. trim(), strtoupper()) // - Basic validation is possible as there's a callback function for checking, // but some helper functions could be written to make people's job validating // stuff much easier (form_validate_email, form_validate_date etc). // - Collapsible js for fieldsets // - Grippie for textareas - // - javascript validation + // - javascript validation (probably won't be done as ajax validation is pretty good) // - handle multipage forms? // - handle a tabbed interface type of form? // } if (!function_exists('json_encode')) { + require_once 'JSON/JSON.php'; function json_encode($data) { - require_once 'JSON/JSON.php'; $json = new Services_JSON(); return $json->encode($data); } @@ -96,24 +96,16 @@ * Represents an HTML form. Forms created using this class have a lot of the * legwork for forms abstracted away. * - * The form API makes it really easy to build complex HTML forms, simply by + * Pieforms makes it really easy to build complex HTML forms, simply by * building a hash describing your form, and defining one or two callback * functions. * - * For more information on how the form API works, please see the documentation + * For more information on how Pieforms works, please see the documentation * at https://eduforge.org/wiki/wiki/mahara/wiki?pagename=FormAPI */ class Pieform { /** - * Data for the form - * - * @var array - * @todo move all of the member fields here into this field - */ - private $data = array(); - - /** * Maintains a tab index across all created forms, to make it easy for * people to forget about it and have it just work for all of their forms. * @@ -129,131 +121,16 @@ private $name = ''; /** - * The method that the form will be submitted by. Either 'get' or 'post'. + * Data for the form * - * @var string - */ - private $method = 'get'; - - /** - * The URL that the form will be submitted to. - * - * @var string - */ - private $action = ''; - - /** - * Whether the form should be validated. Forms that are not validated are - * also not submitted. This is useful if you just want to draw a form, and - * have no validation rules apply to it. - */ - private $validate = true; - - /** - * Whether the form should be checked for submission. Forms can have - * validate on and submit off in order to validate submitted data, but to - * not bother with the submit. - * - * @var bool - */ - private $submit = true; - - /** - * Whether to submit the form via ajax - * - * @todo rename this probably, because AJAX GET is supported too - * - * @var bool - */ - private $ajaxpost = false; - - /** - * A callback to call before submitting the form via AJAX - * - * @var string - */ - private $preajaxsubmitcallback = ''; - - /** - * A callback to call after submitting the form via AJAX, regardless of - * the result of the submission - * - * @var string - */ - private $postajaxsubmitcallback = ''; - - /** - * Name of a javascript function to call on successful ajax submission - * - * @var string - */ - private $ajaxsuccessfunction = ''; - - /** - * Name of a javascript function to call on failed ajax submission - * - * @var string - */ - private $ajaxfailurefunction = ''; - - /** - * The tab index for this particular form. - * - * @var int - */ - private $tabindex = 1; - - /** - * Directories to look for elements, renderers and rules - * * @var array */ - private $configdirs = array(); + private $data = array(); /** - * Whether to autofocus fields in this form, and if so, optionally which - * field to focus. - * - * @var mixed - */ - private $autofocus = false; - - /** - * The renderer used to build the HTML for the form that each element sits - * in. See the form/renderer package to find out the allowed types. - * - * @var string - */ - private $renderer = 'table'; - - /** - * The language used for form rule error messages. - * - * @var string - */ - private $language = 'en.utf8'; - - /** - * Language strings for rules - * - * @var array - */ - private $language_strings = array( - 'en.utf8' => array( - 'required' => 'This field is required', - 'email' => 'E-mail address is invalid', - 'maxlength' => 'This field must be at most %d characters long', - 'minlength' => 'This field must be at least %d characters long', - 'integer' => 'The field must be an integer', - 'validateoptions' => 'The option "%s" is invalid', - 'regex' => 'This field is not in valid form' - ) - ); - - /** * Whether this form includes a file element. If so, the enctype attribute * for the form will be specified as "multipart/mixed" as required. This - * is auto-detected by the Form class. + * is auto-detected by the Pieform class. * * @var bool */ @@ -268,30 +145,6 @@ private $submitted = false; /** - * Whether the form is cancellable or not - that is, whether sending a - * request to cancel the form will be honoured or not. This is useful for - * the transient login form, where it must pass on cancel requests from - * other forms sometimes. - * - * @var bool - */ - private $iscancellable = true; - - /** - * Name of validate function - * - * @var string - */ - private $validatefunction = ''; - - /** - * Name of submit function - * - * @var string - */ - private $submitfunction = ''; - - /** * Processes the form. Called by the {@link pieform} function. It simply * builds the form (processing it if it has been submitted), and returns * the HTML to display the form @@ -335,101 +188,81 @@ // Assign defaults for the form $formdefaults = array( - 'method' => 'get', - 'action' => '', - 'ajaxpost' => false, + 'method' => 'get', + 'action' => '', + 'elements' => array(), + 'renderer' => 'table', + 'ajaxform' => false, 'preajaxsubmitcallback' => '', 'postajaxsubmitcallback' => '', - 'ajaxsuccessfunction' => '', - 'ajaxfailurefunction' => '', - 'configdirs' => array(), - 'autofocus' => false, - 'language' => 'en.utf8', + 'ajaxsuccesscallback' => '', + 'ajaxfailurecallback' => '', 'validate' => true, 'submit' => true, - 'elements' => array(), - 'submitfunction' => '', - 'validatefunction' => '', + 'validatecallback' => '', + 'submitcallback' => '', + 'iscancellable' => true, + 'autofocus' => false, + 'configdirs' => array(), + 'language' => 'en.utf8', + 'rulei18n' => array(), + 'tabindex' => false ); $data = array_merge($formdefaults, $formconfig, $data); $this->data = $data; // Set the method - only get/post allowed - $data['method'] = strtolower($data['method']); - if ($data['method'] != 'post') { - $data['method'] = 'get'; + $this->data['method'] = strtolower($data['method']); + if ($this->data['method'] != 'post') { + $this->data['method'] = 'get'; } - $this->method = $data['method']; - $this->action = $data['action']; - $this->validate = $data['validate']; - $this->submit = $data['submit']; - $this->configdirs = array_map( - create_function('$a', 'return substr($a, -1) == "/" ? substr($a, 0, -1) : $a;'), - (array) $data['configdirs']); - $this->autofocus = $data['autofocus']; - $this->language = $data['language']; - - if ($data['submitfunction']) { - $this->submitfunction = $data['submitfunction']; - } - else { - $this->submitfunction = $this->name . '_submit'; - } - if ($data['validatefunction']) { - $this->validatefunction = $data['validatefunction']; + // Make sure that the javascript callbacks are valid + if ($this->data['ajaxform']) { + $this->validate_js_callbacks(); } - else { - $this->validatefunction = $this->name . '_validate'; - } - if ($data['ajaxpost']) { - $this->ajaxpost = true; - $this->preajaxsubmitcallback = self::validate_js_callback($data['preajaxsubmitcallback']); - $this->postajaxsubmitcallback = self::validate_js_callback($data['postajaxsubmitcallback']); - // @todo rename to *callback instead of *function for consistency - $this->ajaxsuccessfunction = self::validate_js_callback($data['ajaxsuccessfunction']); - $this->ajaxfailurefunction = self::validate_js_callback($data['ajaxfailurefunction']); + if (!$this->data['validatecallback']) { + $this->data['validatecallback'] = $this->name . '_validate'; } - if (isset($data['renderer'])) { - $this->renderer = $data['renderer']; + if (!$this->data['submitcallback']) { + $this->data['submitcallback'] = $this->name . '_submit'; } - if (isset($data['tabindex'])) { - $this->tabindex = intval($data['tabindex']); - } - else { - $this->tabindex = self::$formtabindex++; - } + $this->data['configdirs'] = array_map( + create_function('$a', 'return substr($a, -1) == "/" ? substr($a, 0, -1) : $a;'), + (array) $this->data['configdirs']); - $this->iscancellable = (isset($data['iscancellable']) && !$data['iscancellable']) ? false : true; - if (!is_array($data['elements']) || count($data['elements']) == 0) { + if (empty($this->data['tabindex'])) { + $this->data['tabindex'] = self::$formtabindex++; + } + + if (!is_array($this->data['elements']) || count($this->data['elements']) == 0) { throw new PieformException('Forms must have a list of elements'); } // Remove elements to ignore - foreach ($data['elements'] as $name => $element) { + foreach ($this->data['elements'] as $name => $element) { if (isset($element['type']) && $element['type'] == 'fieldset') { foreach ($element['elements'] as $subname => $subelement) { if (!empty($subelement['ignore'])) { - unset ($data['elements'][$name]['elements'][$subname]); + unset ($this->data['elements'][$name]['elements'][$subname]); } } } else { if (!empty($element['ignore'])) { - unset($data['elements'][$name]); + unset($this->data['elements'][$name]); } } } - $this->elements = $data['elements']; - // Set some attributes for all elements $autofocusadded = false; - foreach ($this->elements as $name => &$element) { + foreach ($this->data['elements'] as $name => &$element) { + // @todo re-check ordering of this section // The name can be in the element itself. This is compatibility for the perl version if (isset($element['name'])) { $name = $element['name']; @@ -449,12 +282,13 @@ } if ($element['type'] == 'file') { $this->fileupload = true; - if ($this->method == 'get') { - $this->method = 'post'; + if ($this->data['method'] == 'get') { + $this->data['method'] = 'post'; self::info("Your form '$this->name' had the method 'get' and also a file element - it has been converted to 'post'"); } } if ($element['type'] == 'fieldset') { + $this->include_plugin('element', 'fieldset'); foreach ($element['elements'] as $subname => &$subelement) { // The name can be in the element itself. This is compatibility for the perl version if (isset($subelement['name'])) { @@ -470,32 +304,12 @@ . $name . '" has no value'); } } - if (!isset($subelement['title'])) { - $subelement['title'] = ''; - } - if ($subelement['type'] == 'file') { - $this->fileupload = true; - if ($this->method == 'get') { - $this->method = 'post'; - self::info("Your form '$this->name' had the method 'get' and also a file element - it has been converted to 'post'"); - } - } - if (!$autofocusadded && $this->autofocus === true) { - $subelement['autofocus'] = true; - $autofocusadded = true; - } - else if (!empty($this->autofocus) && $this->autofocus !== true - && $subname == $this->autofocus) { - $subelement['autofocus'] = true; - } - $subelement['name'] = $subname; - $subelement['tabindex'] = $this->tabindex; - // Let each element set and override attributes if necessary + // Configure some basics for real elements if ($subelement['type'] != 'markup') { // This function can be defined by the application using Pieforms, // and applies to all elements of this type - $function = 'pieform_configure_' . $subelement['type']; + $function = 'pieform_element_' . $subelement['type'] . '_configure'; if (function_exists($function)) { $subelement = $function($subelement); } @@ -503,65 +317,100 @@ // This function is defined by the plugin itself, to set fields on // the element that need to be set but should not be set by the // application - $function = 'pieform_render_' . $subelement['type'] . '_set_attributes'; + $function = 'pieform_element_' . $subelement['type'] . '_set_attributes'; $this->include_plugin('element', $subelement['type']); if (function_exists($function)) { $subelement = $function($subelement); } + + // Add the autofocus flag to the element if required + if (!$autofocusadded && $this->data['autofocus'] === true && empty($element['nofocus'])) { + $subelement['autofocus'] = true; + $autofocusadded = true; + } + else if (!empty($this->data['autofocus']) && $this->data['autofocus'] !== true + && $subname == $this->data['autofocus']) { + $subelement['autofocus'] = true; + } + + // All elements should have some kind of title + if (!isset($subelement['title'])) { + $subelement['title'] = ''; + } + + // Force the form method to post if there is a file to upload. + if ($subelement['type'] == 'file') { + $this->fileupload = true; + if ($this->data['method'] == 'get') { + $this->data['method'] = 'post'; + self::info("Your form '$this->name' had the method 'get' and also a file element - it has been converted to 'post'"); + } + } + + // All elements inherit the form tabindex + $subelement['tabindex'] = $this->data['tabindex']; } + $subelement['name'] = $subname; + } } else { - if (!$autofocusadded && $this->autofocus === true) { - $element['autofocus'] = true; - $autofocusadded = true; - } - elseif (!empty($this->autofocus) && $this->autofocus !== true - && $name == $this->autofocus) { - $element['autofocus'] = true; - } - $element['name'] = $name; - $element['tabindex'] = $this->tabindex; - } + // Let each element set and override attributes if necessary + if ($element['type'] != 'markup') { + $function = 'pieform_element_' . $element['type'] . '_configure'; + if (function_exists($function)) { + $element = $function($element); + } - // Let each element set and override attributes if necessary - if ($element['type'] != 'markup') { - $function = 'pieform_configure_' . $element['type']; - if (function_exists($function)) { - $element = $function($element); - } + $function = 'pieform_element_' . $element['type'] . '_set_attributes'; + $this->include_plugin('element', $element['type']); + if (function_exists($function)) { + $element = $function($element); + } - $function = 'pieform_render_' . $element['type'] . '_set_attributes'; - $this->include_plugin('element', $element['type']); - if (function_exists($function)) { - $element = $function($element); + // Add the autofocus flag to the element if required + if (!$autofocusadded && $this->data['autofocus'] === true && empty($element['nofocus'])) { + $element['autofocus'] = true; + $autofocusadded = true; + } + elseif (!empty($this->data['autofocus']) && $this->data['autofocus'] !== true + && $name == $this->data['autofocus']) { + $element['autofocus'] = true; + } + + $element['tabindex'] = $this->data['tabindex']; } + $element['name'] = $name; } + } // Check if the form was submitted, and if so, validate and process it - $global = ($this->method == 'get') ? $_GET: $_POST; - if ($this->validate && isset($global['pieform_' . $this->name] )) { - if ($this->submit) { + $global = ($this->data['method'] == 'get') ? $_GET: $_POST; + if ($this->data['validate'] && isset($global['pieform_' . $this->name] )) { + if ($this->data['submit']) { $this->submitted = true; // Check if the form has been cancelled - if ($this->iscancellable) { + if ($this->data['iscancellable']) { foreach ($global as $key => $value) { if (substr($key, 0, 7) == 'cancel_') { - // Check for and call the cancel function handler - // @todo<nigel>: it might be that this function could be optional + // Check for and call the cancel function handler, if defined $function = $this->name . '_' . $key; - if (!function_exists($function)) { - throw new PieformException('Form "' . $this->name . '" does not have a cancel function handler for "' . substr($key, 7) . '"'); + if (function_exists($function)) { + $function($this); } - $function(); + + // Redirect the user to where they should go, if the cancel handler didn't already $element = $this->get_element(substr($key, 7)); if (!isset($element['goto'])) { throw new PieformException('Cancel element "' . $element['name'] . '" has no page to go to'); } - // @todo what happens in the case of ajax post? - redirect($element['goto']); - return; + if ($this->data['ajaxform']) { + $this->json_reply(PIEFORM_CANCEL, $element['goto']); + } + header('HTTP/1.1 303 See Other'); + header('Location:' . $element['goto']); + exit; } } } @@ -572,32 +421,32 @@ // Perform general validation first $this->validate($values); // Then user specific validation if a function is available for that - if (function_exists($this->validatefunction)) { - $function = $this->validatefunction; + $function = $this->data['validatecallback']; + if (function_exists($function)) { $function($this, $values); } // Submit the form if things went OK - if ($this->submit && !$this->has_errors()) { + if ($this->data['submit'] && !$this->has_errors()) { $submitted = false; foreach ($this->get_elements() as $element) { // @todo Rename 'ajaxmessages' to 'submitelement' if (!empty($element['ajaxmessages']) == true && isset($global[$element['name']])) { $function = "{$this->name}_submit_{$element['name']}"; if (function_exists($function)) { - $function($values); + $function($this, $values); $submitted = true; break; } } } - if (!$submitted && function_exists($this->submitfunction)) { - $function = $this->submitfunction; + $function = $this->data['submitcallback']; + if (!$submitted && function_exists($function)) { // Call the user defined function for processing a submit // This function should really redirect/exit after it has // finished processing the form. // @todo maybe it should do just that... - $function($values); + $function($this, $values); // This will only work if I can make the login_submit function stuff work in login_validate //if ($this->ajaxpost) { // $message = 'Your ' . $this->name . '_submit function should output some json and exit'; @@ -613,19 +462,18 @@ } // Auto focus the first element with an error if required - if ($this->autofocus !== false) { + if ($this->data['autofocus'] !== false) { $this->auto_focus_first_error(); } // If the form has been submitted by ajax, return ajax - if ($this->ajaxpost) { + if ($this->data['ajaxform']) { $errors = $this->get_errors(); $json = array(); foreach ($errors as $element) { $json[$element['name']] = $element['error']; } - echo json_encode(array('error' => 'local', 'message' => '@todo allow forms to specify a local error message', 'errors' => $json)); - exit; + $this->json_reply(PIEFORM_ERR, '@todo allow forms to specify a local error message', $json); } } } @@ -652,33 +500,15 @@ } /** - * Returns the form submission method + * Returns whether the form has been submitted * - * @return string - */ - public function get_method() { - return $this->method; - } - - /** - * Is the form being submitted by ajax? - * * @return bool */ - public function get_ajaxpost() { - return $this->ajaxpost; + public function is_submitted() { + return $this->submitted; } /** - * Returns the renderer used on to render the form - * - * @return string - */ - public function get_renderer() { - return $this->renderer; - } - - /** * Returns the HTML for the <form...> tag * * @return string @@ -686,7 +516,7 @@ public function get_form_tag() { $result = '<form'; foreach (array('name', 'method', 'action') as $attribute) { - $result .= ' ' . $attribute . '="' . $this->{$attribute} . '"'; + $result .= ' ' . $attribute . '="' . $this->data[$attribute] . '"'; } $result .= ' id="' . $this->name . '"'; if ($this->fileupload) { @@ -697,15 +527,6 @@ } /** - * Returns whether the form has been submitted - * - * @return bool - */ - public function is_submitted() { - return $this->submitted; - } - - /** * Builds and returns the HTML for the form, respecting the chosen renderer. * * Note that the "action" attribute for the form tag are NOT HTML escaped @@ -722,23 +543,23 @@ $result = $this->get_form_tag() . "\n"; } - $this->include_plugin('renderer', $this->renderer); + $this->include_plugin('renderer', $this->data['renderer']); // Form header - $function = 'pieform_renderer_' . $this->renderer . '_header'; + $function = 'pieform_renderer_' . $this->data['renderer'] . '_header'; if (function_exists($function)) { $result .= $function(); } // Render each element - foreach ($this->elements as $name => $elem) { + foreach ($this->data['elements'] as $name => $elem) { if ($elem['type'] != 'hidden') { - $result .= pieform_render_element($elem, $this); + $result .= pieform_render_element($this, $elem); } } // Form footer - $function = 'pieform_renderer_' . $this->renderer . '_footer'; + $function = 'pieform_renderer_' . $this->data['renderer'] . '_footer'; if (function_exists($function)) { $result .= $function(); } @@ -747,7 +568,7 @@ $this->include_plugin('element', 'hidden'); foreach ($this->get_elements() as $element) { if ($element['type'] == 'hidden') { - $result .= pieform_render_hidden($element, $this); + $result .= pieform_element_hidden($element, $this); } } $element = array( @@ -755,15 +576,15 @@ 'name' => 'pieform_' . $this->name, 'value' => '' ); - $result .= pieform_render_hidden($element, $this); + $result .= pieform_element_hidden($element, $this); if ($outputformtags) { $result .= "</form>\n"; } - if ($this->ajaxpost) { - $result .= '<script language="javascript" type="text/javascript">'; - $result .= $this->submit_js(); - $result .= "</script>\n"; + if ($this->data['ajaxform']) { + $result .= '<script type="text/javascript">'; + $result .= "\n" . $this->submit_js(); + $result .= "\n</script>\n"; } return $result; @@ -777,21 +598,17 @@ * is available for the element. */ public function get_value($element) { - $function = 'pieform_get_value_' . $element['type']; - // @todo for consistency, reverse parameter order - always a Form object first + $function = 'pieform_element_' . $element['type'] . '_get_value'; if (function_exists($function)) { - return $function($element, $this); + return $function($this, $element); } - $global = ($this->method == 'get') ? $_GET : $_POST; + $global = ($this->data['method'] == 'get') ? $_GET : $_POST; // If the element is a submit element and has its value in the request, return it // Otherwise, we don't return the value if the form has been submitted, as they // aren't normally returned using a standard form. - if (isset($element['value']) && !empty($element['ajaxmessages']) && isset($global[$element['name']])) { + if (isset($element['value'])) { return $element['value']; } - else if (isset($element['value']) && (!$this->is_submitted() || (empty($element['ajaxmessages'])))) { - return $element['value']; - } else if (isset($global[$element['name']]) && $element['type'] != 'submit') { return $global[$element['name']]; } @@ -810,7 +627,7 @@ */ public function get_elements() { $elements = array(); - foreach ($this->elements as $name => $element) { + foreach ($this->data['elements'] as $name => $element) { if ($element['type'] == 'fieldset') { foreach ($element['elements'] as $subelement) { $elements[] = $subelement; @@ -844,7 +661,7 @@ } /** - * Retrieves submitted values from POST for the elements of this form. + * Retrieves submitted values from the request for the elements of this form. * * This takes into account that some elements may not even have been set, * for example if they were check boxes that were not checked upon @@ -857,10 +674,14 @@ */ private function get_submitted_values() { $result = array(); - $global = ($this->method == 'get') ? $_GET : $_POST; + $global = ($this->data['method'] == 'get') ? $_GET : $_POST; + log_debug($global); foreach ($this->get_elements() as $element) { if ($element['type'] != 'markup') { - $result[$element['name']] = $this->get_value($element); + if (empty($element['ajaxmessages']) || + !empty($element['ajaxmessages']) && isset($global[$element['name']])) { + $result[$element['name']] = $this->get_value($element); + } } } return $result; @@ -901,132 +722,123 @@ } } - /** - * Returns a js function to submit an ajax form - * Expects formname_message() to be defined by the renderer, - * and formname_validate() to be defined. - */ private function submit_js() { - // @todo nigel should disable all buttons on this form while the submit is happening - $result = <<<EOF + $strprocessingform = get_string('processingform'); -var {$this->name}_btn = null; -// For each submit button, add a waffer thin flag -addLoadEvent(function () { + $result = "var {$this->name}_btn = null;\n"; -EOF; + $connecteventadded = false; foreach ($this->get_elements() as $element) { if (!empty($element['ajaxmessages'])) { - $result .= " connect($('{$this->name}_{$element['name']}'), 'onclick', function () { {$this->name}_btn = '{$element['name']}'; });\n"; + if (!$connecteventadded) { + $result .= "addLoadEvent(function() {\n"; + $connecteventadded = true; + } + $result .= " connect($('{$this->name}_{$element['name']}'), 'onclick', function() { {$this->name}_btn = '{$element['name']}'; });\n"; } } + if ($connecteventadded) { + $result .= "});\n"; + } + $result .= <<<EOF +connect($('{$this->name}'), 'onsubmit', function(e) { + if (typeof(tinyMCE) != 'undefined') { tinyMCE.triggerSave(); } -}); - -connect($('{$this->name}'), 'onsubmit', function (e) { - // eventually we should check input types for wysiwyg before doing this - // Also should only save wysiwyg elements in the form, not all of them... - if (typeof(tinyMCE) != 'undefined') { tinyMCE.triggerSave(); } - EOF; - if (!empty($this->preajaxsubmitcallback)) { - $result .= " $this->preajaxsubmitcallback();\n"; + if (!empty($this->data['preajaxsubmitcallback'])) { + $result .= " {$this->data['preajaxsubmitcallback']}();\n"; } $result .= <<<EOF - var data = {}; + var iframe = $('{$this->name}_iframe'); + $('{$this->name}').target = '{$this->name}_iframe'; + if (!iframe) { + iframe = createDOM('iframe', { + 'name': '{$this->name}_iframe', + 'id' : '{$this->name}_iframe' + }); + hideElement(iframe); + insertSiblingNodesAfter($('{$this->name}'), iframe); + + window.pieformHandler_{$this->name} = function(data) { + {$this->name}_remove_all_errors(); + evalJSONRequest(data); + if (data.returnCode == 0) { + // The request completed successfully + {$this->name}_message(data.message, 'ok'); + EOF; - // Get values for each element from the form via the DOM - foreach ($this->get_elements() as $element) { - // Submit elements will be handled later, as there could be more than one - if (empty($element['ajaxmessages'])) { - if ($element['type'] != 'markup') { - $function = 'pieform_get_value_js_' . $element['type']; - if (function_exists($function)) { - // @todo reverse parameter order for consistency, PieForm first - $result .= $function($element, $this); - } - else { - $result .= " data['" . $element['name'] . "'] = document.forms['$this->name'].elements['{$element['name']}'].value;\n"; - } - } - } + + if (!empty($this->data['ajaxsuccesscallback'])) { + $result .= " {$this->data['ajaxsuccesscallback']}(data);\n"; } - // Add only the submit button that was clicked - $result .= " data[{$this->name}_btn] = document.forms['$this->name'].elements['{$this->name}_' + {$this->name}_btn].value;\n"; - // Add the hidden element for detecting form submission - $result .= " data['pieform_{$this->name}'] = '';\n"; - - $action = ($this->action) ? $this->action : basename($_SERVER['PHP_SELF']); - $method = ($this->get_method() == 'get') ? 'GET' : 'POST'; $result .= <<<EOF - var req = getXMLHttpRequest(); - req.open('{$method}', '{$action}'); - req.setRequestHeader('Content-type','application/x-www-form-urlencoded'); - var d = sendXMLHttpRequest(req,queryString(data)); - d.addCallbacks( - function (result) { - {$this->name}_remove_all_errors(); - var data = evalJSONRequest(result); - if (data.error) { - {$this->name}_message(data.message, 'error'); - for (error in data.errors) { - {$this->name}_set_error(data.errors[error], error); } + else if (data.returnCode == 1) { + // The request failed validation + {$this->name}_message(data.message, 'error'); + for (error in data.errors) { + {$this->name}_set_error(data.errors[error], error); + } EOF; - if (!empty($this->ajaxfailurefunction)) { - $result .= " {$this->ajaxfailurefunction}(data);\n"; + if (!empty($this->data['ajaxfailurecallback'])) { + $result .= " {$this->data['ajaxfailurecallback']}(data);\n"; } $result .= <<<EOF - } - else { - {$this->name}_message(data.message, 'ok'); + } + else if (data.returnCode == 2) { + window.location = data.message; + } + else { + // A return code we don't know about + // @todo call some predefined function passing the data + alert('an unknown error occured (if you are a mahara dev, see Nigel)'); + } EOF; - - if (!empty($this->ajaxsuccessfunction)) { - $result .= " {$this->ajaxsuccessfunction}(data);\n"; + if (!empty($this->data['postajaxsubmitcallback'])) { + $result .= " {$this->data['postajaxsubmitcallback']}();\n"; } - $result .= " {$this->name}_remove_all_errors();\n"; - $result .= " }\n"; - if (!empty($this->postajaxsubmitcallback)) { - $result .= " $this->postajaxsubmitcallback();\n"; + $result .= <<<EOF } + } - $strunknownerror = $this->i18n('ajaxunknownerror'); - $strprocessingform = $this->i18n('processingform'); - $result .= <<<EOF - }, - function() { - {$this->name}_message('{$strunknownerror}', 'error'); + if ({$this->name}_btn) { + {$this->name}_message('{$strprocessingform}', 'info'); + } +}); + EOF; - if (!empty($this->postajaxsubmitcallback)) { - $result .= " $this->postajaxsubmitcallback();\n"; + $function = 'pieform_renderer_' . $this->data['renderer'] . '_messages_js'; + if (!function_exists($function)) { + throw new PieformException('No renderer message function "' . $function . '"'); } - $result .= <<<EOF - }); - {$this->name}_message('{$strprocessingform}', 'info'); - e.stop(); -}); -EOF; - - $js_messages_function = 'pieform_renderer_' . $this->renderer . '_messages_js'; - if (!function_exists($js_messages_function)) { - $this->include_plugin('renderer', $this->renderer); - if (!function_exists($js_messages_function)) { - throw new PieformException('No renderer message function "' . $js_messages_function . '"'); - } + return $result . $function($this->name); + } + + public function json_reply($returncode, $message=null, $errors=null) { + $data = array( + 'returnCode' => intval($returncode), + 'message' => $message + ); + if ($errors) { + $data['errors'] = $errors; } + $result = json_encode($data); + log_debug($result); - return $result . $js_messages_function($this->name); + echo <<<EOF +<html><head><script type="text/javascript">function sendResult() { parent.pieformHandler_{$this->name}($result); }</script></head><body onload="sendResult(); "></body></html> +EOF; + exit; } /** @@ -1066,7 +878,7 @@ * @throws PieformException If the element could not be found */ public function set_error($name, $message) { - foreach ($this->elements as &$element) { + foreach ($this->data['elements'] as &$element) { if ($element['type'] == 'fieldset') { foreach ($element['elements'] as &$subelement) { if ($subelement['name'] == $name) { @@ -1215,7 +1027,7 @@ } // Check the configured include paths if they are specified - foreach ($this->configdirs as $directory) { + foreach ($this->data['configdirs'] as $directory) { $file = "$directory/{$type}s/$name.php"; if (is_readable($file)) { include_once($file); @@ -1238,17 +1050,37 @@ * * Returns english by default. * - * @param string $key The language key to look up - * @return string The internationalised string + * @param string $plugin The type of plugin (element, renderer, rule) + * @param string $pluginname The name of the plugin to get the language + * strings for + * @param string $key The language key to look up + * @param array $element The element to get the string for. Elements + * can specify there own i18n strings for rules + * @return string The internationalised string */ - public function i18n($key) { - $function = 'pieform_' . $key . '_i18n'; - if (function_exists($function)) { - return $function($this->language); + public function i18n($plugin, $pluginname, $key, $element) { + if (!in_array($plugin, array('element', 'renderer', 'rule'))) { + throw new PieformException("Invalid plugin name '$plugin'"); } - if (isset($this->language_strings[$this->language][$key])) { - return $this->language_strings[$this->language][$key]; + + // Check the element itself for the language string + if ($plugin == 'rule' && isset($element['rulei18n'][$key])) { + return $element['rulei18n'][$key]; } + + // Check to see if a default was configured for the form + if ($plugin == 'rule' && isset($this->data['rulei18n'][$key])) { + return $this->data['rulei18n'][$key]; + } + + // Fall back to the default string + $function = 'pieform_' . $plugin . '_' . $pluginname . '_i18n'; + if (function_exists($function)) { + $strings = $function(); + return $strings[$this->data['language']][$key]; + } + + // We don't recognise this string return '[[' . $key . ']]'; } @@ -1277,14 +1109,16 @@ } } - private static function validate_js_callback($name) { - if ($name == '') { - return ''; + /** + * Makes sure that the ajax callbacks for this form are valid javascript + * function names. + */ + private function validate_js_callbacks() { + foreach (array('preajaxsubmitcallback', 'postajaxsubmitcallback', 'ajaxsuccesscallback', 'ajaxfailurecallback') as $callback) { + if ($this->data[$callback] != '' && !preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $this->data[$callback])) { + throw new PieformException("'{$this->data[$callback]}' is not a valid javascript callback name for callback '$callback'"); + } } - if (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $name)) { - throw new PieformException("'$name' is not a valid javascript callback name"); - } - return $name; } /** @@ -1308,7 +1142,7 @@ * an error on it */ private function auto_focus_first_error() { - foreach ($this->elements as &$element) { + foreach ($this->data['elements'] as &$element) { if ($element['type'] == 'fieldset') { foreach ($element['elements'] as &$subelement) { if (isset($subelement['error'])) { @@ -1343,37 +1177,27 @@ * {@internal This is separate so that child element types can nest other * elements inside them (like the fieldset element does for example).}} * - * @param array $element The element to render * @param Pieform $form The form to render the element for + * @param array $element The element to render * @return string The rendered element */ -function pieform_render_element($element, Pieform $form) { +function pieform_render_element(Pieform $form, $element) { // If the element is pure markup, don't pass it to the renderer if ($element['type'] == 'markup') { return $element['value'] . "\n"; } // Make sure that the function to render the element type is available - $function = 'pieform_render_' . $element['type']; + $function = 'pieform_element_' . $element['type']; - // Work out the renderer function required and make sure it exists - if ($renderer = $form->get_renderer()) { - $rendererfunction = 'pieform_renderer_' . $renderer; - if (!function_exists($rendererfunction)) { - $form->include_plugin('pieform/renderers/' . $renderer . '.php'); - if (!function_exists($rendererfunction)) { - throw new PieformException('No such form renderer: "' . $renderer . '"'); - } - } + $rendererfunction = 'pieform_renderer_' . $form->get_property('renderer'); + if (!function_exists($rendererfunction)) { + throw new PieformException('No such form renderer function: "' . $rendererfunction . '"'); } - else { - throw new PieformException('No form renderer specified for form "' . $form->get_name() . '"'); - } $element['id'] = Pieform::make_id($element); $element['class'] = Pieform::make_class($element); - // @todo reverse order of parameters for consistency, a Form object first - $builtelement = $function($element, $form); + $builtelement = $function($form, $element); // Remove the 'autofocus' class, because we only want it on the form input // itself, not the wrapping HTML @@ -1386,7 +1210,7 @@ $htmlelements = array(); foreach ($GLOBALS['_PIEFORM_REGISTRY'] as $form) { foreach ($form->get_elements() as $element) { - $function = 'pieform_get_headdata_' . $element['type']; + $function = 'pieform_element_' . $element['type'] . '_get_headdata'; if (function_exists($function)) { $elems = $function($element); $htmlelements = array_merge($htmlelements, $elems); @@ -1397,4 +1221,8 @@ return array_unique($htmlelements); } +define('PIEFORM_OK', 0); +define('PIEFORM_ERR', 1); +define('PIEFORM_CANCEL', 2); + ?> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-23 05:03:38
|
Revision: 127 http://svn.sourceforge.net/pieforms/?rev=127&view=rev Author: oracleshinoda Date: 2006-12-22 21:03:37 -0800 (Fri, 22 Dec 2006) Log Message: ----------- Added a new flag, 'cancelelement', so that erraneous javascript is not added for them, and their value can still be quashed when the post data is sent. Also, allow elements to specify a function that describes how a rule applies to them, which can be very useful when the way that the rule works is 'almost' right, but you don't want to make a new rule Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-23 04:35:31 UTC (rev 126) +++ pieforms-php5/trunk/src/pieform.php 2006-12-23 05:03:37 UTC (rev 127) @@ -677,8 +677,13 @@ log_debug($global); foreach ($this->get_elements() as $element) { if ($element['type'] != 'markup') { - if (empty($element['submitelement']) || - !empty($element['submitelement']) && isset($global[$element['name']])) { + if ( + (empty($element['submitelement']) && empty($element['cancelelement'])) || + ( + (!empty($element['submitelement']) || !empty($element['cancelelement'])) + && isset($global[$element['name']]) + ) + ) { $result[$element['name']] = $this->get_value($element); } } @@ -704,12 +709,17 @@ if (isset($element['rules']) && is_array($element['rules'])) { foreach ($element['rules'] as $rule => $data) { if (!$this->get_error($element['name'])) { - // Get the rule - $function = 'pieform_rule_' . $rule; + // See if this element has a function that describes + // how this rule should apply to it + $function = 'pieform_element_' . $element['name'] . '_rule_' . $rule; if (!function_exists($function)) { - $this->include_plugin('rule', $rule); + // Try instead the default rule function + $function = 'pieform_rule_' . $rule; if (!function_exists($function)) { - throw new PieformException('No such form rule "' . $rule . '"'); + $this->include_plugin('rule', $rule); + if (!function_exists($function)) { + throw new PieformException('No such form rule "' . $rule . '"'); + } } } if ($error = $function($this, $values[$element['name']], $element, $data)) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-23 05:13:18
|
Revision: 133 http://svn.sourceforge.net/pieforms/?rev=133&view=rev Author: oracleshinoda Date: 2006-12-22 21:13:18 -0800 (Fri, 22 Dec 2006) Log Message: ----------- Removed mahara-isms that would have prevented anyone else from using it from svnhead Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-23 05:10:44 UTC (rev 132) +++ pieforms-php5/trunk/src/pieform.php 2006-12-23 05:13:18 UTC (rev 133) @@ -674,7 +674,6 @@ private function get_submitted_values() { $result = array(); $global = ($this->data['method'] == 'get') ? $_GET : $_POST; - log_debug($global); foreach ($this->get_elements() as $element) { if ($element['type'] != 'markup') { if ( @@ -842,7 +841,6 @@ $data['errors'] = $errors; } $result = json_encode($data); - log_debug($result); echo <<<EOF <html><head><script type="text/javascript">function sendResult() { parent.pieformHandler_{$this->name}($result); }</script></head><body onload="sendResult(); "></body></html> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-23 13:23:23
|
Revision: 135 http://svn.sourceforge.net/pieforms/?rev=135&view=rev Author: oracleshinoda Date: 2006-12-23 05:23:23 -0800 (Sat, 23 Dec 2006) Log Message: ----------- * You can now have a javascript presubmit function non javascript forms. * A bunch of the callbacks have had their names changed for yet more consistency. * Forms that use a hidden iframe to submit to are now known as 'javascript forms' or 'jsforms', not AJAX forms, because they're not using AJAX. A bunch of the callbacks have been renamed based on this. * Support has been added for a PHP callback if a form fails to validate, and a javascript callback if the returnCode is not recognised. * Some function calls were changed to use call_user_func_array, which allows the possibility that they're not just strings (i.e. they could be class/method array pairs) * Reduced the number of parameters for json_reply to two, now the 'errors' index of the 'message' data holds any errors specific to form elements. * The errors sent back will now be set for any nonzero return code. * Broke out the javascript for detecting which button was pressed last into its own method. * Unset the detected last pressed submit button just before the form callback finishes, which prevents randomness when pressing cancel buttons later * Made the get_errors method public, someone else may want access to it. Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-23 13:13:02 UTC (rev 134) +++ pieforms-php5/trunk/src/pieform.php 2006-12-23 13:23:23 UTC (rev 135) @@ -73,7 +73,6 @@ // stuff much easier (form_validate_email, form_validate_date etc). // - Collapsible js for fieldsets // - Grippie for textareas - // - javascript validation (probably won't be done as ajax validation is pretty good) // - handle multipage forms? // - handle a tabbed interface type of form? // @@ -188,24 +187,86 @@ // Assign defaults for the form $formdefaults = array( - 'method' => 'get', - 'action' => '', - 'elements' => array(), - 'renderer' => 'table', - 'ajaxform' => false, - 'preajaxsubmitcallback' => '', - 'postajaxsubmitcallback' => '', - 'ajaxsuccesscallback' => '', - 'ajaxfailurecallback' => '', - 'validate' => true, - 'submit' => true, + // The method used to submit the form, should always be 'get' or 'post' + 'method' => 'get', + + // The form target. The vast majority of the time this should be blank, + // as the functions that handle the submit should be in the same script + // as the form definition + 'action' => '', + + // The form elements + 'elements' => array(), + + // The form renderer (see the pieform/renderers directory) + 'renderer' => 'table', + + // Whether to validate the form. Non validated forms have none of the + // validate, success or error callbacks called on them + 'validate' => true, + + // Whether to process the submission of this form. The form will still + // be validated. Handy if the code handling the submission is elsewhere + 'submit' => true, + + // The PHP callback called to validate the form. Optional 'validatecallback' => '', - 'submitcallback' => '', - 'iscancellable' => true, + + // The PHP callback called to process the submission of the form. + // Required, unless a success function is provided for each submit + // button in the form + 'successcallback' => '', + + // The PHP callback called if there is any validation error. Optional + 'errorcallback' => '', + + // Whether this form should submit to a hidden iframe and use DOM + // manipulation to insert error messages (faster than a normal submit, + // supported in less browsers. Most modern browsers should be fine) + 'jsform' => false, + + // The javascript function called before submission of a form + // (regardless of whether the form is a jsform) + 'presubmitcallback' => '', + + // The javascript function called after submission of a form. As non-js + // forms will trigger a page load on submit, this has no effect for them. + 'postsubmitcallback' => '', + + // The javascript function called if the form submission was successful + 'jssuccesscallback' => '', + + // The javascript function called if the form submission was unsuccessful + 'jserrorcallback' => '', + + // The javascript function called if the form submission returned an + // unknown error code + 'globaljserrorcallback' => '', + + // Whether this form can be cancelled, regardless of the presence of + // 'cancel' buttons or form inputs mischeviously named as to behave + // like cancel buttons + 'iscancellable' => true, + + // Whether to auto-focus either the first field (if the value is true, + // or the named field (if the value is a string) when the form is + // displayed. If this has any value other than false and the form has + // been submitted with an error, the first field with an error will + // be focussed. 'autofocus' => false, + + // The directories to search for additional elements, renderers and + // rules 'configdirs' => array(), + + // The language to use for any form strings, such as those found in + // rules. 'language' => 'en.utf8', + + // Any overriding language strings for rules 'rulei18n' => array(), + + // The tabindex for the form (managed automatically by Pieforms) 'tabindex' => false ); $data = array_merge($formdefaults, $formconfig, $data); @@ -218,7 +279,7 @@ } // Make sure that the javascript callbacks are valid - if ($this->data['ajaxform']) { + if ($this->data['jsform']) { $this->validate_js_callbacks(); } @@ -226,8 +287,8 @@ $this->data['validatecallback'] = $this->name . '_validate'; } - if (!$this->data['submitcallback']) { - $this->data['submitcallback'] = $this->name . '_submit'; + if (!$this->data['successcallback']) { + $this->data['successcallback'] = $this->name . '_submit'; } $this->data['configdirs'] = array_map( @@ -405,7 +466,7 @@ if (!isset($element['goto'])) { throw new PieformException('Cancel element "' . $element['name'] . '" has no page to go to'); } - if ($this->data['ajaxform']) { + if ($this->data['jsform']) { $this->json_reply(PIEFORM_CANCEL, $element['goto']); } header('HTTP/1.1 303 See Other'); @@ -422,15 +483,15 @@ $this->validate($values); // Then user specific validation if a function is available for that $function = $this->data['validatecallback']; - if (function_exists($function)) { - $function($this, $values); + if (is_callable($function)) { + call_user_func_array($function, array($this, $values)); } // Submit the form if things went OK if ($this->data['submit'] && !$this->has_errors()) { $submitted = false; foreach ($this->get_elements() as $element) { - if (!empty($element['submitelement']) == true && isset($global[$element['name']])) { + if (!empty($element['submitelement']) && isset($global[$element['name']])) { $function = "{$this->name}_submit_{$element['name']}"; if (function_exists($function)) { $function($this, $values); @@ -439,13 +500,13 @@ } } } - $function = $this->data['submitcallback']; - if (!$submitted && function_exists($function)) { + $function = $this->data['successcallback']; + if (!$submitted && is_callable($function)) { // Call the user defined function for processing a submit // This function should really redirect/exit after it has // finished processing the form. // @todo maybe it should do just that... - $function($this, $values); + call_user_func_array($function, array($this, $values)); // This will only work if I can make the login_submit function stuff work in login_validate //if ($this->ajaxpost) { // $message = 'Your ' . $this->name . '_submit function should output some json and exit'; @@ -464,15 +525,21 @@ if ($this->data['autofocus'] !== false) { $this->auto_focus_first_error(); } + + // Call the user-defined PHP error function, if it exists + $function = $this->data['errorcallback']; + if (is_callable($function)) { + call_user_func_array($function, array($this)); + } - // If the form has been submitted by ajax, return ajax - if ($this->data['ajaxform']) { + // If the form has been submitted by javascript, return json + if ($this->data['jsform']) { $errors = $this->get_errors(); $json = array(); foreach ($errors as $element) { $json[$element['name']] = $element['error']; } - $this->json_reply(PIEFORM_ERR, '@todo allow forms to specify a local error message', $json); + $this->json_reply(PIEFORM_ERR, array('errors' => $json)); } } } @@ -580,9 +647,18 @@ $result .= "</form>\n"; } - if ($this->data['ajaxform']) { + if ($this->data['jsform'] || $this->data['presubmitcallback']) { $result .= '<script type="text/javascript">'; - $result .= "\n" . $this->submit_js(); + $result .= "\n" . $this->whichbutton_js(); + } + if ($this->data['jsform']) { + $result .= $this->submit_js(); + } + else if ($this->data['presubmitcallback']) { + $result .= 'connect(\'' . $this->name . '\', \'onsubmit\', ' + . 'function() { ' . $this->data['presubmitcallback'] . "('{$this->name}', {$this->name}_btn); });"; + } + if ($this->data['jsform'] || $this->data['presubmitcallback']) { $result .= "\n</script>\n"; } @@ -730,9 +806,7 @@ } } - private function submit_js() { - $strprocessingform = get_string('processingform'); - + private function whichbutton_js() { $result = "var {$this->name}_btn = null;\n"; $connecteventadded = false; @@ -742,20 +816,32 @@ $result .= "addLoadEvent(function() {\n"; $connecteventadded = true; } - $result .= " connect($('{$this->name}_{$element['name']}'), 'onclick', function() { {$this->name}_btn = '{$element['name']}'; });\n"; + if (!empty($element['cancelelement'])) { + $cancelstr = 'cancel_'; + } + else { + $cancelstr = ''; + } + $result .= " connect($('{$cancelstr}{$this->name}_{$element['name']}'), 'onclick', function() { {$this->name}_btn = '{$cancelstr}{$this->name}_{$element['name']}'; });\n"; } } if ($connecteventadded) { $result .= "});\n"; } - $result .= <<<EOF + return $result; + } + + private function submit_js() { + $strprocessingform = get_string('processingform'); + + $result = <<<EOF connect($('{$this->name}'), 'onsubmit', function(e) { if (typeof(tinyMCE) != 'undefined') { tinyMCE.triggerSave(); } EOF; - if (!empty($this->data['preajaxsubmitcallback'])) { - $result .= " {$this->data['preajaxsubmitcallback']}();\n"; + if (!empty($this->data['presubmitcallback'])) { + $result .= " {$this->data['presubmitcallback']}('{$this->name}', {$this->name}_btn);\n"; } $result .= <<<EOF @@ -770,60 +856,78 @@ insertSiblingNodesAfter($('{$this->name}'), iframe); window.pieformHandler_{$this->name} = function(data) { - {$this->name}_remove_all_errors(); + +EOF; + if (isset($this->data['processingstopcallback'])) { + $result .= " {$this->data['processingstopcallback']}('{$this->name}', {$this->name}_btn);\n"; + } + + $result .= <<<EOF evalJSONRequest(data); if (data.returnCode == 0) { + {$this->name}_remove_all_errors(); // The request completed successfully - {$this->name}_message(data.message, 'ok'); EOF; - - if (!empty($this->data['ajaxsuccesscallback'])) { - $result .= " {$this->data['ajaxsuccesscallback']}(data);\n"; + if (!empty($this->data['jssuccesscallback'])) { + $result .= " {$this->data['jssuccesscallback']}('{$this->name}', data);\n"; } - $result .= <<<EOF } - else if (data.returnCode == 1) { - // The request failed validation - {$this->name}_message(data.message, 'error'); - for (error in data.errors) { - {$this->name}_set_error(data.errors[error], error); + else { + // Redirect if the form is being cancelled + if (data.returnCode == 2) { + window.location = data.message; + return; } + + // Set errors if there are any + {$this->name}_remove_all_errors(); + if (data.message.errors) { + for (error in data.message.errors) { + {$this->name}_set_error(data.message.errors[error], error); + } + } + if (data.returnCode == 1) { + // The request failed validation + EOF; - if (!empty($this->data['ajaxfailurecallback'])) { - $result .= " {$this->data['ajaxfailurecallback']}(data);\n"; + // @todo: renumber the PIEFORM_* flags to be 0, -1, -2 to allow users to have the positive numbers to themselves + if (!empty($this->data['jserrorcallback'])) { + $result .= " {$this->data['jserrorcallback']}('{$this->name}', data);\n"; } $result .= <<<EOF + } + else { + // A return code we don't know about + +EOF; + if (!empty($this->data['globaljserrorcallback'])) { + $result .= " {$this->data['globaljserrorcallback']}('{$this->name}', data);\n"; + } + else { + $result .= " alert('Developer: got error code ' + data.returnCode + + ', either fix your form to not use this code or define a global js error handler');\n"; + } + $result .= <<<EOF + } } - else if (data.returnCode == 2) { - window.location = data.message; - } - else { - // A return code we don't know about - // @todo call some predefined function passing the data - alert('an unknown error occured (if you are a mahara dev, see Nigel)'); - } EOF; - if (!empty($this->data['postajaxsubmitcallback'])) { - $result .= " {$this->data['postajaxsubmitcallback']}();\n"; + if (!empty($this->data['postsubmitcallback'])) { + $result .= " {$this->data['postsubmitcallback']}('{$this->name}', {$this->name}_btn);\n"; } $result .= <<<EOF + {$this->name}_btn = null; } } - if ({$this->name}_btn) { - {$this->name}_message('{$strprocessingform}', 'info'); - } -}); - - EOF; + $result .= "});\n\n"; $function = 'pieform_renderer_' . $this->data['renderer'] . '_messages_js'; if (!function_exists($function)) { throw new PieformException('No renderer message function "' . $function . '"'); @@ -832,14 +936,11 @@ return $result . $function($this->name); } - public function json_reply($returncode, $message=null, $errors=null) { + public function json_reply($returncode, $message=null) { $data = array( 'returnCode' => intval($returncode), 'message' => $message ); - if ($errors) { - $data['errors'] = $errors; - } $result = json_encode($data); echo <<<EOF @@ -1117,11 +1218,12 @@ } /** - * Makes sure that the ajax callbacks for this form are valid javascript + * Makes sure that the javascript callbacks for this form are valid javascript * function names. */ private function validate_js_callbacks() { - foreach (array('preajaxsubmitcallback', 'postajaxsubmitcallback', 'ajaxsuccesscallback', 'ajaxfailurecallback') as $callback) { + foreach (array('presubmitcallback', 'postsubmitcallback', 'jssuccesscallback', + 'jserrorcallback', 'globaljserrorcallback') as $callback) { if ($this->data[$callback] != '' && !preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $this->data[$callback])) { throw new PieformException("'{$this->data[$callback]}' is not a valid javascript callback name for callback '$callback'"); } @@ -1134,7 +1236,7 @@ * @return array An array of elements with errors on them, the empty array * in the result of no errors. */ - private function get_errors() { + public function get_errors() { $result = array(); foreach ($this->get_elements() as $element) { if (isset($element['error'])) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-24 06:29:28
|
Revision: 143 http://svn.sourceforge.net/pieforms/?rev=143&view=rev Author: oracleshinoda Date: 2006-12-23 22:29:24 -0800 (Sat, 23 Dec 2006) Log Message: ----------- Renumbered response constants to be negative numbers, to allow application developers to use the positive numbers Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-24 05:12:32 UTC (rev 142) +++ pieforms-php5/trunk/src/pieform.php 2006-12-24 06:29:24 UTC (rev 143) @@ -26,6 +26,13 @@ $GLOBALS['_PIEFORM_REGISTRY'] = array(); +/** The form was processed successfully */ +define('PIEFORM_OK', 0); +/** The form failed processing/validating */ +define('PIEFORM_ERR', -1); +/** A cancel button was pressed */ +define('PIEFORM_CANCEL', -2); + /** * Builds, validates and processes a form. * @@ -877,7 +884,7 @@ } else { // Redirect if the form is being cancelled - if (data.returnCode == 2) { + if (data.returnCode == -2) { window.location = data.message; return; } @@ -890,7 +897,7 @@ } } - if (data.returnCode == 1) { + if (data.returnCode == -1) { // The request failed validation EOF; @@ -1330,8 +1337,4 @@ return array_unique($htmlelements); } -define('PIEFORM_OK', 0); -define('PIEFORM_ERR', 1); -define('PIEFORM_CANCEL', 2); - ?> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-25 23:45:27
|
Revision: 144 http://svn.sourceforge.net/pieforms/?rev=144&view=rev Author: oracleshinoda Date: 2006-12-25 15:45:25 -0800 (Mon, 25 Dec 2006) Log Message: ----------- Forms will now die if execution is continuing after the submit function is called, however this behaviour can be turned off if necessary (the transient login page in Mahara requires it to be off) Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-24 06:29:24 UTC (rev 143) +++ pieforms-php5/trunk/src/pieform.php 2006-12-25 23:45:25 UTC (rev 144) @@ -255,6 +255,12 @@ // like cancel buttons 'iscancellable' => true, + // Whether Pieforms should die after calling a submit function. Generally + // this is a good idea, as it forces the user to reply to the form + // submission. However, there are occasions where you might want to let + // it continue, so this behaviour can be turned off + 'dieaftersubmit' => true, + // Whether to auto-focus either the first field (if the value is true, // or the named field (if the value is a string) when the form is // displayed. If this has any value other than false and the form has @@ -514,14 +520,20 @@ // finished processing the form. // @todo maybe it should do just that... call_user_func_array($function, array($this, $values)); - // This will only work if I can make the login_submit function stuff work in login_validate - //if ($this->ajaxpost) { - // $message = 'Your ' . $this->name . '_submit function should output some json and exit'; - //} - //else { - // $message = 'Your ' . $this->name . '_submit function should redirect when it is finished'; - //} - //throw new PieformException($message); + if ($this->data['dieaftersubmit']) { + // This will only work if I can make the login_submit function stuff work in login_validate + if ($this->data['jsform']) { + $message = 'Your ' . $this->name . '_submit function should use $form->json_reply to send a response'; + } + else { + $message = 'Your ' . $this->name . '_submit function should redirect or exit when it is done'; + } + throw new PieformException($message); + } + else { + // Successful submission, and the user doesn't care about replying, so... + return; + } } else if (!$submitted) { throw new PieformException('No function registered to handle form submission for form "' . $this->name . '"'); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-27 05:37:33
|
Revision: 150 http://svn.sourceforge.net/pieforms/?rev=150&view=rev Author: oracleshinoda Date: 2006-12-26 21:37:33 -0800 (Tue, 26 Dec 2006) Log Message: ----------- Removed some comments from the javascript output for jsform submissions, comments aren't needed (later on this stuff might be packed). Added a bit of code to handle expanding a fieldset if it contains elements with errors in them. Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-27 05:27:58 UTC (rev 149) +++ pieforms-php5/trunk/src/pieform.php 2006-12-27 05:37:33 UTC (rev 150) @@ -895,33 +895,33 @@ $result .= <<<EOF } else { - // Redirect if the form is being cancelled if (data.returnCode == -2) { window.location = data.message; return; } - // Set errors if there are any {$this->name}_remove_all_errors(); if (data.message.errors) { for (error in data.message.errors) { {$this->name}_set_error(data.message.errors[error], error); } + // @todo only output when fieldsets are present + forEach(getElementsByTagAndClassName('fieldset', 'collapsed', '{$this->name}'), function(fieldset) { + if (getFirstElementByTagAndClassName(null, 'error', fieldset)) { + removeElementClass(fieldset, 'collapsed'); + } + }); } if (data.returnCode == -1) { - // The request failed validation EOF; - - // @todo: renumber the PIEFORM_* flags to be 0, -1, -2 to allow users to have the positive numbers to themselves if (!empty($this->data['jserrorcallback'])) { $result .= " {$this->data['jserrorcallback']}('{$this->name}', data);\n"; } $result .= <<<EOF } else { - // A return code we don't know about EOF; if (!empty($this->data['globaljserrorcallback'])) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2006-12-27 12:54:11
|
Revision: 156 http://svn.sourceforge.net/pieforms/?rev=156&view=rev Author: oracleshinoda Date: 2006-12-27 04:54:07 -0800 (Wed, 27 Dec 2006) Log Message: ----------- Allow forms to specify an error message for jsforms. This is a small helper that stops the need to define a _error function if you want to send an error back. The message is completely optional Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2006-12-27 12:49:27 UTC (rev 155) +++ pieforms-php5/trunk/src/pieform.php 2006-12-27 12:54:07 UTC (rev 156) @@ -250,6 +250,11 @@ // unknown error code 'globaljserrorcallback' => '', + // The message to pass back as a reason for the form submission failing + // if the form is a jsform. This can be used by your application however + // you choose. + 'jserrormessage' => '', + // Whether this form can be cancelled, regardless of the presence of // 'cancel' buttons or form inputs mischeviously named as to behave // like cancel buttons @@ -558,7 +563,8 @@ foreach ($errors as $element) { $json[$element['name']] = $element['error']; } - $this->json_reply(PIEFORM_ERR, array('errors' => $json)); + $message = $this->get_property('jserrormessage'); + $this->json_reply(PIEFORM_ERR, array('message' => $message, 'errors' => $json)); } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ora...@us...> - 2007-01-07 11:31:28
|
Revision: 161 http://svn.sourceforge.net/pieforms/?rev=161&view=rev Author: oracleshinoda Date: 2007-01-07 03:31:25 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Whitespace change Modified Paths: -------------- pieforms-php5/trunk/src/pieform.php Modified: pieforms-php5/trunk/src/pieform.php =================================================================== --- pieforms-php5/trunk/src/pieform.php 2007-01-02 11:06:04 UTC (rev 160) +++ pieforms-php5/trunk/src/pieform.php 2007-01-07 11:31:25 UTC (rev 161) @@ -488,8 +488,7 @@ $this->json_reply(PIEFORM_CANCEL, $element['goto']); } header('HTTP/1.1 303 See Other'); - header('Location:' . $element['goto']); - exit; + header('Location:' . $element['goto']); exit; } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |