Permalink
Browse files

An example for repeat elements, event callbacks for repeat JS

Frozen repeat no longer outputs Javascript
Repeat's constructor accepts prototype, setters return $this


git-svn-id: http://svn.php.net/repository/pear/packages/HTML_QuickForm2/trunk@325176 c90b9560-bf6c-de11-be94-00142212c4b1
  • Loading branch information...
sad-spirit committed Apr 14, 2012
1 parent ab31422 commit bf1aad61a742d52ce6710fd7a3db71326bdd7add
@@ -211,6 +211,25 @@ public function setValue($value)
throw new HTML_QuickForm2_Exception('Not implemented');
}
+ /**
+ * Class constructor
+ *
+ * Repeat element can understand the following keys in $data parameter:
+ * - 'prototype': a Container to be repeated. Passed to {@link setPrototype()}.
+ *
+ * @param string $name Element name
+ * @param string|array $attributes Attributes (either a string or an array)
+ * @param array $data Additional element data
+ */
+ public function __construct($name = null, $attributes = null, array $data = array())
+ {
+ if (!empty($data['prototype'])) {
+ $this->setPrototype($data['prototype']);
+ }
+ unset($data['prototype']);
+ parent::__construct($name, $attributes, $data);
+ }
+
/**
* Sets the Container that will be used as a prototype for repeating
*
@@ -316,11 +335,14 @@ protected function getDataSources()
* may be disabled are bad choices
*
* @param string $field field name
+ *
+ * @return HTML_QuickForm2_Container_Repeat
*/
public function setIndexField($field)
{
$this->indexField = $field;
$this->updateValue();
+ return $this;
}
/**
@@ -380,6 +402,8 @@ public function getIndexes()
* from data sources, so use this after all possible updates were done.
*
* @param array $indexes
+ *
+ * @return HTML_QuickForm2_Container_Repeat
*/
public function setIndexes(array $indexes)
{
@@ -390,6 +414,7 @@ public function setIndexes(array $indexes)
}
}
$this->itemIndexes = array_keys($hash);
+ return $this;
}
/**
@@ -682,9 +707,12 @@ public function render(HTML_QuickForm2_Renderer $renderer)
}
$this->restoreChildAttributes($backup);
- $jsBuilder->addLibrary('repeat', 'quickform-repeat.js');
- $jsBuilder->addElementJavascript($this->_generateInitScript($evalBuilder));
- $this->renderClientRules($jsBuilder);
+ // only add javascript if not frozen
+ if (!$this->toggleFrozen()) {
+ $jsBuilder->addLibrary('repeat', 'quickform-repeat.js');
+ $jsBuilder->addElementJavascript($this->_generateInitScript($evalBuilder));
+ $this->renderClientRules($jsBuilder);
+ }
$renderer->finishContainer($this);
$renderer->setOption('group_hiddens', $hiddens);

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -91,7 +91,7 @@ qf.Repeat.addHandler = function(event)
while (parent && !qf.classes.has(parent, 'repeat')) {
parent = parent.parentNode;
}
- if (parent && parent.repeat) {
+ if (parent && parent.repeat && parent.repeat.onBeforeAdd()) {
parent.repeat.add();
}
event.preventDefault();
@@ -114,7 +114,7 @@ qf.Repeat.removeHandler = function(event)
}
parent = parent.parentNode;
}
- if (parent && parent.repeat) {
+ if (parent && parent.repeat && parent.repeat.onBeforeRemove(item)) {
parent.repeat.remove(item);
}
event.preventDefault();
@@ -265,6 +265,7 @@ qf.Repeat.prototype = {
}
}
}
+ this.onChange();
},
/**
* Removes an item from repeat element
@@ -295,5 +296,35 @@ qf.Repeat.prototype = {
}
}
item.parentNode.removeChild(item);
+ this.onChange();
+ },
+ /**
+ * Called before adding a repeated item.
+ *
+ * If this method returns false, no item will be added
+ *
+ * @returns {Boolean}
+ */
+ onBeforeAdd: function()
+ {
+ return true;
+ },
+ /**
+ * Called before removing a repeated item.
+ *
+ * If this method returns false, the item will not be removed
+ *
+ * @param {Node} item
+ * @returns {Boolean}
+ */
+ onBeforeRemove: function(item)
+ {
+ return true;
+ },
+ /**
+ * Called after adding or deleting the item
+ */
+ onChange: function()
+ {
}
};
View
@@ -0,0 +1,188 @@
+<?php
+/**
+ * Usage example for HTML_QuickForm2 package: repeat element
+ *
+ * $Id$
+ */
+
+require_once 'HTML/QuickForm2.php';
+require_once 'HTML/QuickForm2/Renderer.php';
+
+$form = new HTML_QuickForm2('testRepeat');
+
+$form->addDataSource(new HTML_QuickForm2_DataSource_Array(array(
+ 'country' => array(4, 706, 180),
+ 'street' => array(
+ 'Secret Taliban caves',
+ 'Pirate hideout. Aaargh!',
+ 'Somewhere in the jungle'
+ ),
+ 'default' => array(true, false, false),
+
+ 'links' => array(
+ 'main' => 'yes_1',
+ 'title' => array('php.net', 'pear.php.net', 'google.com')
+ )
+)));
+
+/* @var $fsOne HTML_QuickForm2_Container_Fieldset */
+$fsOne = $form->addFieldset()->setLabel('Fieldset-based repeat element');
+
+/* @var $repeatFs HTML_QuickForm2_Container_Repeat */
+$repeatFs = $fsOne->addRepeat()
+ ->setPrototype(HTML_QuickForm2_Factory::createElement('fieldset'))
+ ->setId('repeat-fieldset')
+ ->setLabel('Shipping addresses');
+
+$countries = array(
+ '' => "-- please select --",
+ 4 => "Afghanistan",
+ 148 => "Chad",
+ 180 => "Congo, Democratic Republic of",
+ 368 => "Iraq",
+ 706 => "Somalia",
+ 736 => "Sudan",
+ 716 => "Zimbabwe"
+);
+
+$country = $repeatFs->addSelect('country')->loadOptions($countries)->setLabel('Country:');
+$repeatFs->addText('region', array('style' => 'width: 20em;'))->setLabel('Region:');
+$street = $repeatFs->addText('street', array('style' => 'width: 20em;'))->setLabel('Street address:');
+$repeatFs->addCheckbox('default')->setContent('default shipping address');
+// button to remove a repeated item from a repeat
+$repeatFs->addButton('remove', array('type' => 'button'))
+ ->setContent('remove this address')
+ ->addClass('repeatRemove');
+
+// setting rules for repeated elements, these will work properly server-side and client-side
+$country->addRule('required', 'Please select a country', null,
+ HTML_QuickForm2_Rule::ONBLUR_CLIENT_SERVER);
+$street->addRule('required', 'Please input street address', null,
+ HTML_QuickForm2_Rule::ONBLUR_CLIENT_SERVER);
+
+
+/* @var $fsTwo HTML_QuickForm2_Container_Fieldset */
+$fsTwo = $form->addFieldset()->setLabel('Group-based repeat element');
+/* @var $repeatGroup HTML_QuickForm2_Container_Repeat */
+$repeatGroup = $fsTwo->addRepeat(
+ null, array('id' => 'repeat-group'),
+ array('prototype' => HTML_QuickForm2_Factory::createElement('group', 'links')
+ ->setLabel('A link:')->setSeparator('&nbsp;'))
+ )->setIndexField('links[title]') // not strictly necessary, but doesn't hurt either
+ ->setLabel('Links');
+
+$repeatGroup->addText('title', array('style' => 'width: 15em;'));
+// specially crafted value attribute to prevent adding index to name
+$repeatGroup->addRadio('main', array('value' => 'yes_:idx:'))->setContent('main');
+// button to remove a repeated item from a repeat
+$repeatGroup->addButton('remove', array('type' => 'button'))
+ ->setContent('X')
+ ->addClass('repeatRemove');
+
+$form->addSubmit('submit', array('value' => 'Send this form'));
+
+$renderer = HTML_QuickForm2_Renderer::factory('default');
+$form->render($renderer);
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <style type="text/css">
+
+/* Set up custom font and form width */
+body {
+ margin-left: 10px;
+ font-family: Arial,sans-serif;
+ font-size: small;
+}
+
+.quickform {
+ min-width: 500px;
+ max-width: 600px;
+ width: 560px;
+}
+
+/* Use default styles included with the package */
+<?php
+if ('@data_dir@' != '@' . 'data_dir@') {
+ $filename = '@data_dir@/HTML_QuickForm2/quickform.css';
+} else {
+ $filename = dirname(dirname(dirname(__FILE__))) . '/data/quickform.css';
+}
+readfile($filename);
+?>
+
+/* http://www.quirksmode.org/css/clearing.html */
+#repeat-group .repeatItem { overflow: auto; width: 100%; }
+
+/* zebra table for group-based repeat */
+.quickform .repeat .odd { background-color: #FEE; }
+.quickform .repeat .even { background-color: #EEF; }
+
+ </style>
+<?php
+
+// Inline QuickForm's javascript libraries
+echo $renderer->getJavascriptBuilder()->getLibraries(true, true);
+
+?>
+ <title>HTML_QuickForm2 repeat element example</title>
+</head>
+<body>
+<?php
+
+if ($form->validate()) {
+ echo "<pre>\n";
+ var_dump($form->getValue());
+ echo "\n</pre><hr />";
+}
+
+echo $renderer;
+
+?>
+<script type="text/javascript">
+// <![CDATA[
+
+// add event handlers to repeats
+var repeatFs = document.getElementById('repeat-fieldset').repeat,
+ repeatGroup = document.getElementById('repeat-group').repeat;
+
+repeatFs.onBeforeAdd = function()
+{
+ var items = this.getElementsByClass('repeatItem', this.container);
+ // 5 visible items and 1 hidden prototype
+ if (items.length > 5) {
+ alert('5 addresses should be enough for everybody!');
+ return false;
+ }
+ return true;
+};
+
+repeatFs.onBeforeRemove = function(item)
+{
+ var items = this.getElementsByClass('repeatItem', this.container);
+ if (2 == items.length) {
+ alert('You cannot remove the last address');
+ return false;
+ }
+ return true;
+};
+
+repeatGroup.onChange = function()
+{
+ var items = this.getElementsByClass('repeatItem', this.container);
+ for (var i = 1, item; item = items[i]; i++) {
+ qf.classes.add(item, i % 2 ? 'odd' : 'even');
+ qf.classes.remove(item, i % 2 ? 'even' : 'odd');
+ }
+};
+
+// paint zebra for initial values
+repeatGroup.onChange();
+
+// ]]>
+</script>
+</body>
+</html>
Oops, something went wrong.

0 comments on commit bf1aad6

Please sign in to comment.