Yii 1.1: How to create a wrapper for a js library

23 followers

This wiki will explain how to include a javascript library in a widget.

We will use as example uploadify, a flash/javascript plugin for file uploading.

Our example: uploadify

Let's imagine we have a page with a file field, and we want to exchange it with uploadify.

The first step is to create a widget that will replace this file field.

Creating the widget

Let's create a file in components named ZUploadify:

<?php
 
class ZUploadify extends CInputWidget
{
    public function run()
    {
        echo CHtml::activeFileField($this->model, $this->attribute);
    }
}

We extend CInputWidget, the base widget for input field. This parent class gives us the attributes 'model' and 'attribute'.

Now, instead of the file field in our form we can place:

<?php $this->widget('ZUploadify', array('model'=>$model, 'attribute'=>'file')); ?>

Excellent! Now we have a widget which works exactly how CHtml::activeFileField() worked.

We can move forward to use uploadify.

Import uploadify

Following uploadify documentation, we have to download the package and import it on the web page.

Let's save the package in protected/components/assets for now.

Now we have to publish this directory and to include the files. All simple as:

public function run()
{
   $assetsFolder=Yii::app()->assetManager->publish(
      Yii::getPathOfAlias('application.components.assets.uploadify')
   );
   Yii::app()->clientScript->registerCssFile($assetsFolder.'/uploadify.css');
   Yii::app()->clientScript->registerScriptFile($assetsFolder.'/swfobject.js');
   Yii::app()->clientScript->registerScriptFile(
      $assetsFolder.'/jquery.uploadify.v2.1.4.min.js'
   );
   Yii::app()->clientScript->registerCoreScript('jquery');
 
   echo CHtml::activeFileField($this->model, $this->attribute);
}

The first instruction (assetsManger->publish) publishes the directory and returns the path created.

The other instructions publishes the script and css file. Please note that we are including the yii version of jquery, not the uploadify one to avoid conflicts.

Register the script

Our objective is to register the following js script, and to reserve us the possibility to customize it.

<script type="text/javascript">
$(document).ready(function() {
  $('#file_upload').uploadify({
    'uploader'  : '/uploadify/uploadify.swf',
    'script'    : '/uploadify/uploadify.php',
    'cancelImg' : '/uploadify/cancel.png',
    'folder'    : '/uploads',
    'auto'      : true
  });
});
</script>

Let's add a property options:

public $options;

And then we prepare the options like this:

$options= CJavaScript::encode(array_merge(
            array(
                'uploader'  => $assetsFolder.'/uploadify.swf',
                'script'    => $assetsFolder.'/uploadify.php',
                'cancelImg' => $assetsFolder.'/cancel.png',
                'folder'    => '/uploads',
                'auto'      => true
            ),
            $this->options
        ));

The options are made up by some default standard options (uploader, script ,cancelImg, folder and auto) that will be merged with the user defined options.

User defined options will take precedence (they are the second array in array_merge), so we will have the possibility of override the default ones.

This options will be encoded with Cjavascript::encode(), a magic function that allow to give javascript functions as parameters, we have just to write 'js:' at the beginning.

To register the script we need only the id, we can generate the id with CHtml, respecting any choice of the user:

if (isset ($htmlOptions['id']))
        $id= $htmlOptions['id'];
    else
        $id= CHtml::activeId($this->model, $this->attribute);

And finally register the script:

Yii::app()->clientScript->registerScript($id, "$(document).ready(function() { $('#$id').uploadify($options);});");

That's it, our uploadify widget is ready to be used.

Conclusion

In summary:

  • Create a widget
  • Download the library somewhere
  • Publish the library
  • Include needed script/css
  • Prepare options and register the script

Here is the complete result:

<?php
 
class ZUploadify extends CInputWidget
{
 
    public $options = array();
    public function run()
    {
 
        $assetsFolder= Yii::app()->assetManager->publish(Yii::getPathOfAlias('application.modules.administrator.components.assets.uploadify'));
        Yii::app()->clientScript->registerCssFile($assetsFolder.'/uploadify.css');
        Yii::app()->clientScript->registerScriptFile($assetsFolder.'/swfobject.js');
        Yii::app()->clientScript->registerScriptFile($assetsFolder.'/jquery.uploadify.v2.1.4.min.js');
        Yii::app()->clientScript->registerCoreScript('jquery');
 
        $options= CJavaScript::encode(array_merge(
            array(
                'uploader'  => $assetsFolder.'/uploadify.swf',
                'script'    => $assetsFolder.'/uploadify.php',
                'cancelImg' => $assetsFolder.'/cancel.png',
                'folder'    => '/uploads',
                'auto'      => true
            ),
            $this->options
        ));
 
        if (isset ($htmlOptions['id']))
            $id= $htmlOptions['id'];
        else
            $id= CHtml::activeId($this->model, $this->attribute);
 
 
        Yii::app()->clientScript->registerScript($id,   "$(document).ready(function() { $('#$id').uploadify($options);});");
        echo CHtml::activeFileField($this->model, $this->attribute, $this->htmlOptions);
    }
}

For any customization, follow the documentation of uploadify. The work of Yii framework is only to give a structure in which to include all needed file.

Total 2 comments

#11906 report it
Giancarlo at 2013/02/12 09:04am
How can I access to the value of the field?

The component use:

$id= CHtml::activeId($this->model, $this->attribute);

but i want use the value of field. $this->model->value_of_field

How can I do?

#4125 report it
zaccaria at 2011/06/08 08:37am
note

The aim of the widget is not using effectively uploadify (for this there is already the documentation of uploadify), but explain the technique and the functions needed for create a wrappar for a js library

Leave a comment

Please to leave your comment.

Write new article