Skip to content
Snippets Groups Projects
class.dynamic_forms.php 38.8 KiB
Newer Older
Peter Rotich's avatar
Peter Rotich committed
            return null;

        $config = $this->getConfiguration();
Peter Rotich's avatar
Peter Rotich committed
        $choices = $this->getChoices();
        $selection = array();
        if ($value && is_array($value)) {
            foreach ($value as $k=>$v) {
                if (($i=$list->getItem((int) $k)))
Peter Rotich's avatar
Peter Rotich committed
                    $selection[$i->getId()] = $i->getValue();
                elseif (isset($choices[$v]))
                    $selection[$v] = $choices[$v];
            }
        }

        return $selection;
    }

    function to_database($value) {
        if (is_array($value)) {
            reset($value);
        }
Peter Rotich's avatar
Peter Rotich committed
        if ($value && is_array($value))
            $value = JsonDataEncoder::encode($value);

    function to_php($value, $id=false) {
        $value = ($value && !is_array($value))
Peter Rotich's avatar
Peter Rotich committed
            ? JsonDataParser::parse($value) : $value;
        if (!is_array($value)) {
            $choices = $this->getChoices();
            if (isset($choices[$value]))
                $value = $choices[$value];
        }
        // Don't set the ID here as multiselect prevents using exactly one
        // ID value. Instead, stick with the JSON value only.
    function hasSubFields() {
        return true;
    }
    function getSubFields() {
        return $this->getConfigurationForm()->getFields();
    }

Peter Rotich's avatar
Peter Rotich committed
    function toString($items) {
        return ($items && is_array($items))
            ? implode(', ', $items) : (string) $items;
Peter Rotich's avatar
Peter Rotich committed
    function validateEntry($entry) {
        parent::validateEntry($entry);
        if (!$this->errors()) {
            $config = $this->getConfiguration();
            if ($config['typeahead']
                    && ($entered = $this->getWidget()->getEnteredValue())
                    && !in_array($entered, $entry))
                $this->_errors[] = __('Select a value from the list');
Jared Hancock's avatar
Jared Hancock committed
    }

    function getConfigurationOptions() {
        return array(
Peter Rotich's avatar
Peter Rotich committed
            'widget' => new ChoiceField(array(
                'id'=>1, 'label'=>__('Widget'), 'required'=>false,
Peter Rotich's avatar
Peter Rotich committed
                'default' => 'dropdown',
                'choices'=>array(
                    'dropdown' => __('Drop Down'),
                    'typeahead' =>__('Typeahead'),
Peter Rotich's avatar
Peter Rotich committed
                ),
                'configuration'=>array(
                    'multiselect' => false,
                ),
                'hint'=>__('Typeahead will work better for large lists')
Peter Rotich's avatar
Peter Rotich committed
            'multiselect' => new BooleanField(array(
                'id'=>1, 'label'=>__(/* Type of widget allowing multiple selections */ 'Multiselect'),
                'required'=>false, 'default'=>false,
Peter Rotich's avatar
Peter Rotich committed
                'configuration'=>array(
                    'desc'=>__('Allow multiple selections')),
                'hint' => __('Dropdown only'),
Peter Rotich's avatar
Peter Rotich committed
            )),
            'prompt' => new TextboxField(array(
                'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'',
                'hint'=>__('Leading text shown before a value is selected'),
                'configuration'=>array('size'=>40, 'length'=>40),
            )),
Peter Rotich's avatar
Peter Rotich committed
    function getConfiguration() {

        $config = parent::getConfiguration();
        if ($config['widget'])
            $config['typeahead'] = $config['widget'] == 'typeahead';
Peter Rotich's avatar
Peter Rotich committed

        //Typeahed doesn't support multiselect for now  TODO: Add!
        if ($config['typeahead'])
            $config['multiselect'] = false;

        return $config;
    }

    function getChoices($verbose=false) {
        if (!$this->_choices || $verbose) {
            $this->_choices = array();
            foreach ($this->getList()->getItems() as $i)
Peter Rotich's avatar
Peter Rotich committed
                $this->_choices[$i->getId()] = $i->getValue();

            // Retired old selections
            $values = ($a=$this->getAnswer()) ? $a->getValue() : array();
            if ($values && is_array($values)) {
                foreach ($values as $k => $v) {
                    if (!isset($this->_choices[$k])) {
                        if ($verbose) $v .= ' '.__('(retired)');
Peter Rotich's avatar
Peter Rotich committed
                        $this->_choices[$k] = $v;
                    }
                }
        }
        return $this->_choices;
    }
    function getChoice($value) {
        $choices = $this->getChoices();
        if ($value && is_array($value)) {
            $selection = $value;
        } elseif (isset($choices[$value]))
            $selection[] = $choices[$value];
        elseif ($this->get('default'))
            $selection[] = $choices[$this->get('default')];

        return $selection;
    }

    function export($value) {
        if ($value && is_numeric($value)
                && ($item = DynamicListItem::lookup($value)))
            return $item->toString();
        return $value;
    }

    function getFilterData() {
        $data = array(parent::getFilterData());
        if (($v = $this->getClean()) instanceof DynamicListItem) {
            $data = array_merge($data, $v->getFilterData());
        }
        return $data;
    }
class TypeaheadSelectionWidget extends ChoicesWidget {
    function render($how) {
        if ($how == 'search')
            return parent::render($how);
        $name = $this->getEnteredValue();
        if (is_array($this->value)) {
            $name = $name ?: current($this->value);
            $value = key($this->value);
        $config = $this->field->getConfiguration();
Jared Hancock's avatar
Jared Hancock committed
        $source = array();
        foreach ($this->field->getList()->getItems() as $i)
            $source[] = array(
Peter Rotich's avatar
Peter Rotich committed
                'value' => $i->getValue(), 'id' => $i->getId(),
                'info' => sprintf('%s %s',
                    $i->getValue(),
                    (($extra= $i->getAbbrev()) ? "-- $extra" : '')),
Jared Hancock's avatar
Jared Hancock committed
        ?>
        <span style="display:inline-block">
        <input type="text" size="30" name="<?php echo $this->name; ?>_name"
            id="<?php echo $this->name; ?>" value="<?php echo Format::htmlchars($name); ?>"
            placeholder="<?php echo $config['prompt'];
            ?>" autocomplete="off" />
        <input type="hidden" name="<?php echo $this->name;
            ?>[<?php echo $value; ?>]" id="<?php echo $this->name;
            ?>_id" value="<?php echo Format::htmlchars($name); ?>"/>
Jared Hancock's avatar
Jared Hancock committed
        <script type="text/javascript">
        $(function() {
            $('input#<?php echo $this->name; ?>').typeahead({
Jared Hancock's avatar
Jared Hancock committed
                source: <?php echo JsonDataEncoder::encode($source); ?>,
                property: 'info',
Jared Hancock's avatar
Jared Hancock committed
                onselect: function(item) {
                    $('input#<?php echo $this->name; ?>_name').val(item['value'])
                    $('input#<?php echo $this->name; ?>_id')
                      .attr('name', '<?php echo $this->name; ?>[' + item['id'] + ']')
                      .val(item['value']);
Jared Hancock's avatar
Jared Hancock committed
                }
            });
        });
        </script>
        </span>
        <?php
    }
    function getValue() {
        $data = $this->field->getSource();
        if (isset($data[$this->name]))
            return $data[$this->name];
        return parent::getValue();
    }

    function getEnteredValue() {
        // Used to verify typeahead fields
        $data = $this->field->getSource();
        if (isset($data[$this->name.'_name']))
            return trim($data[$this->name.'_name']);
        return parent::getValue();
    }