Skip to content

Instantly share code, notes, and snippets.

@jdavidbakr
Last active October 27, 2016 00:00
Show Gist options
  • Save jdavidbakr/4662ae1ea7b0b7725485 to your computer and use it in GitHub Desktop.
Save jdavidbakr/4662ae1ea7b0b7725485 to your computer and use it in GitHub Desktop.
Laravel: AjaxFormBuilder
<?php
namespace App\Services;
use Collective\Html\FormBuilder;
class AjaxFormBuilder extends FormBuilder {
protected $form_id;
protected $readonly = false;
public function readonly($value=true)
{
$this->readonly = $value;
}
public function input($type, $name, $value = null, $options = [])
{
if($this->readonly) {
$options['disabled'] = true;
}
return parent::input($type, $name, $value, $options);
}
public function textarea($name, $value = null, $options = [])
{
if($this->readonly) {
$options['disabled'] = true;
}
return parent::textarea($name, $value, $options);
}
public function countdown_textarea($name, $value = null, $options = [])
{
if($this->readonly) {
$html = $this->textarea($name, $value, $options);
} else {
$id = 'count-'.str_random(5);
$options['onkeyup'] = 'TextCountdown.Update(this, "'.$id.'");';
$html = $this->textarea($name, $value, $options);
$html .= '<div class="countdown_text">Remaining characters: <span id="'.$id.'">'.$options['maxlength'].'</span></div>';
}
return $html;
}
public function select($name, $list = [], $selected = null, $options = [])
{
if($this->readonly) {
$options['disabled'] = true;
}
return parent::select($name, $list, $selected, $options);
}
/**
* Opens a new form, attaching the onsubmit attribute
* @param array $options
* @return string
*/
public function open(array $options = array()) {
if (!empty($options['id'])) {
$this->form_id = $options['id'];
} else {
$this->form_id = str_random(10);
$options['id'] = $this->form_id;
}
if(empty($options['no-warning'])) {
$options['onchange'] = 'PageChangeWarning.change_made();';
}
$options['onsubmit'] = 'AjaxForm.submit(this);return false;';
return parent::open($options);
}
/**
* Creates a submit button with the "button" class, as well as a hidden submit button so the form submits on enter
* @param string $value
* @param array $attributes
* @return string
*/
public function submit($value = null, $attributes = array()) {
if($this->readonly) {
// No submit button on a read-only form
return;
}
if (!empty($attributes['class'])) {
$classes = explode(" ", $attributes['class']);
} else {
$classes = array();
}
$classes[] = 'button';
$attributes['class'] = implode(" ", $classes);
$attributes['onclick'] = "AjaxForm.submit_button_click('{$this->form_id}')";
$attributes = $this->html->attributes($attributes);
return '<input type="submit" class="hidden" id="submitbtn" name="Submit" /><a' . $attributes . '>' . htmlspecialchars(!empty($value) ? $value : 'Submit') . '</a>';
}
/**
* Hidden Subform select
* @param string $name
* @param array $list List of options
* @param array $option_attributes List of attributes for the option elements - keyed with their keys
* @param bool $selected
* @param array $options The select element's attributes
* @return string
*/
public function hs_select($name, $list = array(), $option_attributes = array(), $selected = null, $options = array()) {
// When building a select box the "value" attribute is really the selected one
// so we will use that when checking the model or session for a value which
// should provide a convenient method of re-populating the forms on post.
$selected = $this->getValueAttribute($name, $selected);
if($this->readonly) {
$options['disabled'] = true;
}
$options['id'] = $this->getIdAttribute($name, $options);
if (!isset($options['name'])) {
$options['name'] = $name;
}
$options['onchange'] = 'HiddenSubform.update(this)';
// We will simply loop through the options and build an HTML value for each of
// them until we have an array of HTML declarations. Then we will join them
// all together into one single HTML element that can be put on the form.
$html = array();
$id = str_random(10);
$options['id'] = $id;
foreach ($list as $value => $display) {
$html[] = $this->hs_getSelectOption($display,
$option_attributes,
$value,
$selected);
}
// Once we have all of this HTML, we can join this into a single element after
// formatting the attributes into an HTML "attributes" string, then we will
// build out a final select statement, which will contain all the values.
$options = $this->html->attributes($options);
$list = implode('', $html);
$select = "<select{$options}>{$list}</select>";
$script = "<script>document.addEventListener('DOMContentLoaded', function(event) { document.getElementById('{$id}').onchange() })</script>";
return $select . $script;
}
public function hs_getSelectOption($display, $option_attributes, $value, $selected)
{
if(is_array($display)) {
return $this->hs_optionGroup($display, $option_attributes, $value, $selected);
}
return $this->hs_option($display, $option_attributes, $value, $selected);
}
public function hs_optionGroup($list, $option_attributes, $label, $selected)
{
$html = [];
foreach($list as $value => $display)
{
$html[] = $this->hs_option($display, $option_attributes, $value, $selected);
}
return '<optgroup label="' . e($label) . '">' . implode('', $html) . '</optgroup>';
}
public function hs_option($display, $option_attributes, $value, $selected)
{
$sel = $this->getSelectedValue($value, $selected);
$option_options = [
'value' => e($value),
'selected' => $sel
];
if(!empty($option_attributes[$value])) {
$option_options = array_merge($option_options, $option_attributes[$value]);
}
return '<option' . $this->html->attributes($option_options) . '>' . e($display) . '</option>';
}
public function hs_checkbox($name, $value = 1, $checked = null, $options = [])
{
$id = str_random(10);
$options['id'] = $id;
$options['onchange'] = 'HiddenSubform.update(this)';
$checkbox = $this->checkable('checkbox', $name, $value, $checked, $options);
$script = "<script>document.addEventListener('DOMContentLoaded', function(event) { document.getElementById('{$id}').onchange() })</script>";
return $checkbox . $script;
}
/**
* Creates a calendar object that manages the popup calendar
* @param string $name
* @param string $default
* @param array $options Additional attributes for the input element (not the visible one)
* @return string
*/
public function calendar($name, $default = null, $options = array())
{
if ( ! isset($options['name'])) $options['name'] = $name;
$options['type'] = 'text';
$options['style'] = 'display: none;';
// We will get the appropriate value for the given field. We will look for the
// value in the session for the value in the old input data then we'll look
// in the model instance if one is set. Otherwise we will just use empty.
$id = $this->getIdAttribute($name, $options);
$value = $this->getValueAttribute($name, $default);
// Once we have the type, value, and ID we can merge them into the rest of the
// attributes array so we can convert them into their HTML attribute format
// when creating the HTML element. Then, we will return the entire input.
$merge = compact('type', 'value', 'id');
$options = array_merge($options, $merge);
// Create the picker options
$picker_options = array();
$picker_options['onclick'] = 'return datepicker.activate(event, this)';
$picker_options['onfocus'] = 'this.blur(); return datepicker.activate(event, this)';
$picker_options['rel'] = $id;
if($value) {
$picker_options['value'] = date("n/d/Y", strtotime($value));
}
return '<input'.$this->html->attributes($options).'><input'.$this->html->attributes($picker_options).'>';
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment