How to make an element for ZOO/JBZoo - additional possibilities

0.0/10 rating (0 votes)

Using AJAX in an element

There are often tasks where Ajax is just necessary. Fortunately, it’s not hard to add responsiveness to your element.

We will have to do several things:

  1. Register an action in the element constructor. Otherwise it will not be executed.
  2. Create a method with a name similar to the action name and add arguments to receive.
public function __construct()
    {
        parent::__construct();
        $this->registerCallback('myFirstAjax');
    }
    

Adding the method to our element.

//  We need to know the number of passed parameters in order to receive them.
    public function myFirstAjax($param1, $param2, $param3)
    {
        // We get the default text from the settings of the element.
        $default = $this->config->get('ajax', 'default text');
                return $this->app->jbajax->send(array(
                'default'    => $default,
                'param1'  => $param1,
                'param2'  => $param2,
                'param3'  => $param3,
            )
        );
    }
    

JBAjax helper and its element method will help us to create a correct link for a POST request.

$url = $this->app->jbrouter->element($this->identifier, $this->getItem()->id, 'myFirstAjax');

If we want to pass additional parameters, we need to prepare args array before sending the request. You can do it using js, for example.

<script type="text/javascript">
    jQuery(document).ready(function () {
        jQuery('.css selector’).on(‘click’, function(){
           // Our array with additional parameters
            var data = new Array('1',  '2', '3');
            jQuery.ajax({
                type: 'POST',
                data: 'args=' + data,
                url: '<?php echo $url; ?>',
                success: function(html){
                    console.log(html.param1);
                    console.log(html.param2);
                    console.log(html.param3);
                    console.log(html.default);
                }
            });
        });
    });
</script>

Or you can use php to pass an array as a fourth argument to the send method.

$data = array(‘1’, ‘2’, ‘3’);
$url    = $this->app->jbrouter->element($this->identifier, $this->getItem()->id, 'myFirstAjax', $data);

You can return the reply as JSON using send method of JBAjax helper. All that you need to do is to specify a key and its value like we did in the above example. Then we just need to receive the result in a js script and process it.

Import/Export in a custom element

Element is created. We can use it for item submission or make it repeatable. But what to do with an import if we need to fill our website with products?

Fortunately, this is also covered by JBZoo developers. File of the element should be placed in this folder:

/media/zoo/applications/jbuniversal/framework/elements/user/ . File name corresponds to the element name.

Creating jbint.php file

Class name should have a prefix - JBCSVItemUser and a postfix (the name of our element) - JBInt. It is inherited from JBCSVItem class.

2 methods should be redefined in our class:

  • toCSV - a method used during export.
  • fromCSV - a method used during import.

Parent class has two defined constants:

  • JBCSVItem::SEP_ROWS - used to separate repeatable fields.
  • JBCSVItem::SEP_CELL - used to separate different data within one element.
class JBCSVItemUserJBlist extends JBCSVItem 
{
    public function toCSV()
    {
        $result = array();
        $params = $this->app->jbuser->getParam('export-items', array());
        if (!empty($this->_value)) {
            foreach($this->_value as $jbint) {
                $result[] = $jbint['number'];
            }
        }
        // Should we merge repeatable fields?
        if ((int)$params->merge_repeatable) {
            return implode(JBCSVItem::SEP_ROWS, $result);
        } else {
            return $result;
        }
    }
   
     public function fromCSV()
    {
        $data = ($position == 1) ? array() : $this->_element->data();
        if (strpos($value, JBCSVItem::SEP_ROWS)) {
            foreach (explode(JBCSVItem::SEP_ROWS, $value) as $val) {
                $values[] = array(
                    'number'  => $val,
                );
            }
            $data = $values;
        } else {
            $data[] = array('number' => $value);
        }
        $this->_element->bindData($data);
        return $this->_item;
    }
}

A filter

In order for our element to have setting for a filter, we need to create an xml file and fill it.

Using creation of settings for a new element in a filter as an example, we’ll create a new template named number. It will have a unique input type - number. There is also will be a range search.

There are two steps needed to create a filter template for a new element:

  1. Create an xml file with the name of our element.
  2. Write the template class.

XML file with the name of our element should be created here:

/media/zoo/applications/jbuniversal/config/mod_jbzoo_search/jbint.xml . The name of our template file corresponds to the option name in a parameter - jbzoo_filter_render.

Adding our new template to the parameter:

<param name="jbzoo_filter_render"
                type="list"
                label="JBZOO_ELEMENT_TEMPLATE"
                description="JBZOO_ELEMENT_TEMPLATE_DESC"
                default="_auto_"
                >
            <option value="_auto_">JBZOO_ELEMENT_TEMPLATE_AUTO</option>
            <option value="text">JBZOO_ELEMENT_TEMPLATE_TEXT</option>
            <option value="text-range">JBZOO_ELEMENT_TEMPLATE_TEXT_RANGE</option>
            <option value="checkbox">JBZOO_ELEMENT_TEMPLATE_CHECKBOX</option>
            <option value="jqueryui">JBZOO_ELEMENT_TEMPLATE_JQUERYUI</option>
            <option value="radio">JBZOO_ELEMENT_TEMPLATE_RADIO</option>
            <option value="select">JBZOO_ELEMENT_TEMPLATE_SELECT</option>
            <option value="select-chosen">JBZOO_ELEMENT_TEMPLATE_SELECT_CHOSEN</option>
            <option value="slider">JBZOO_ELEMENT_TEMPLATE_SLIDER</option>
    <!-- Name of the new template -->
            <option value="number">JBZOO_ELEMENT_TEMPLATE_NUMBER_RANGE</option>
    <!--  Name of the new template -->
            <option value="hidden">JBZOO_ELEMENT_TEMPLATE_HIDDEN</option>
        </param>

Now we need to create a file for the template

/media/zoo/applications/jbuniversal/framework/render/filter/element.<OPTION_ALIAS>.php

Name of the class should start with JBFilterElement and end with an alias of the chosen option, inherited from the JBFilterElement class.

  • html - output our class.
  • _getName - changing names of inputs. We’ll have two of them.
  • _getAttrs - getting attributes. Checking if an autocomplete option is enabled. If it does - including scripts.
  • _number - a skeleton of our template. We use method from our class in this example. In JBZoo practice JBHtml helper is used.
class JBFilterElementNumber extends JBFilterElement 
{
    /**
     * Render HTML
     * @return string|null
     */
    public function html()
    {
        $html = array();
        $values = array('', '');
        if (isset($this->_value['range'])) {
            if (!is_array($this->_value['range'])) {
                $values = explode('/', $this->_value['range']);
            } else if (is_array($this->_value['range'])) {
                $values = $this->_value['range'];
            }
        }
        $html[] = '<label for="' . $this->_getId('1') . '">' . JText::_('JBZOO_FROM') . '</label>';
        $html[] = $this->_number(
            $this->_getName('0'),
            $values[0],
            $this->_attrs,
            $this->_getId('1')
        );
        $html[] = '<br />';
        $html[] = '<label for="' . $this->_getId('2') . '">' . JText::_('JBZOO_TO') . '</label>';
        $html[] = $this->_number(
            $this->_getName('1'),
            $values[1],
            $this->_attrs,
            $this->_getId('2')
        );
        return implode("\n\r", $html);
    }
    /**
     * Get name
     * @param $postFix
     * @return string
     */
    protected function _getName($postFix = null)
    {
        return parent::_getName('range') . '[' . $postFix . ']';
    }
    /**
     *  Generates an HTML input type[number].
     * @param $name
     * @param null $value
     * @param null $attribs
     * @param null $idtag
     * @return string
     */
    protected function _number($name, $value = null, $attribs = null, $idtag = null)
    {
        if ($idtag && is_array($attribs)) {
            $attribs['id'] = $idtag;
        }
        $attribs = $this->app->jbhtml->buildAttrs($attribs);
        if (strpos($attribs, 'jsAutocomplete') !== false) {
            $this->app->jbassets->jqueryui();
            $this->app->jbassets->initAutocomplete();
        }
        return '<input type="number" name="'.$name.'" value="'.$value.'" '. $attribs.' />' ;
    }
    /**
     * Get main attrs
     * @param array $attrs
     * @return array
     */
    protected function _getAttrs(array $attrs)
    {
        $attrs = parent::_getAttrs($attrs);
        $attrs['maxlength'] = '255';
        $attrs['size']      = '60';
        if ((int)$this->_params->get('jbzoo_filter_autocomplete', 0)) {
            $attrs['class'][]     = 'jsAutocomplete';
            $attrs['placeholder'] = $this->_getPlaceholder();
        }
        return $attrs;
    }
}

If you encounter any obstacles or can’t make something, look at the neighboring files, maybe you’ll find an answer there.

ZOO/JBZoo system events

What are events for? By using events we can globally affect the components of ZOO/JBZoo - elements, categories, items.

Let’s examine several events which can be called for an element.

  • afterDisplay - is called after output.
  • beforeDisplay - is called before output.
  • download - an event that is called before download. Currently only for DownloadElement.
  • afterSubmissionDisplay - same as afterDisplay but during item submission.
  • beforeSubmissionDisplay - same as beforeDisplay but during item submission.
  • beforeEdit - an event that takes place before editing.

Let’s examine an example. Let’s wrap all elements in a div with the event class. afterDisplay event will help us here - we can get element contents from it.

 /**
     * On after element display
     * @param $event
     */
    public static function afterDisplay($event)
    {
        $params         = $event->getParameters();
        $params['html'] = '<div class="event">'.$params['html'].'</div>';
        $event->setReturnValue($params);
    }
    

You can find all events for an element in the JBEventElement class:

/media/zoo/applications/jbuniversal/framework/events/jbevent.element.php

API, Creating an element

Still gotta questions, who can help me?

Visit our special JBZoo tech support forum which is specifically meant for JBZoo so the priority of the response and its promptness are much better there than in any other place. With inactive account with a “Plus” sign in a tariff plan you can ask for support in one of these sections or use any of our contacts.