how to make a dynamic progress bar to show the percentage or status

8 followers

This wiki article has not been tagged with a corresponding Yii version yet.
Help us improve the wiki by updating the version information.

Yii have a CJuiProgressBar, but it is static. If we want a dynamic progress bar to show the percentage or status, we have to do more things. I make it successfully and am glad to share it with you.

There are 6 files changed or added (to get zip file or any question,mail me by hehbhehb#163.com)

  • 1 Component(or model) file

ProgressBar.php

<?php
 
class ProgressBar
{
    private $key;
 
    private $running;
    private $total;
    private $done;
 
    public function __construct($key)
    {
        $this->key = $key;
    }
 
    public function start($total)
    {
        $this->running = 1;
        $this->done = 0;
        $this->total = $total;
        $this->put();
    }
 
    public function stop()
    {
        $this->running = 0;
        $this->put();
    }
 
    public function inc($step=1)
    {
        $this->done += $step;
        $this->put();
    }
 
    public function put()
    {
        $ret = Yii::app()->cache->set($this->key, array('running'=>$this->running, 'total'=>$this->total, 'done'=>$this->done));
    }
 
    public static function get($key)
    {
        $test = 1;
        //$test = 0;
        if ($test)
        {
            $data = Yii::app()->cache->get($key);
            if($data === false) 
            {
                $data = array('running'=>1, 'total'=>119, 'done'=>0);
            }
 
            $data['done'] = $data['done'] + 10;
 
            if ($data['done'] > 119) 
            {
                $data['running'] = 0;
            }
 
            Yii::app()->cache->set($key, $data, 1*60);
            return $data;               
        }
 
        $data = Yii::app()->cache->get($key);
        if($data === false)
        {
            $data = array('running' =>1, 'total'=>100, 'done'=>0);
        }
        return $data;       
    }
 
 
}
  • 2 Controller files

MyController.php

<?php
 
class MyController extends Controller
{
    public function actions()
    {
        return array(
            'GetProgressBarData'=>array(
                'class'=>'ActionGetProgressBarData',
            ),
        );
    }
 
    public function actionBatchHandle()
    {
        ...
        if(isset($_POST))
        {                   
            $post = $_POST;
            $id = uniqid();
            $filename = Yii::app()->getRuntimePath().DIRECTORY_SEPARATOR."{$id}";                   
            file_put_contents($filename, json_encode($post));
            $command = 'php ' . Yii::app()->getBasePath().DIRECTORY_SEPARATOR.'yiic.php ' . "cli BatchHandle --id=$id > /dev/null 2>&1 &";
            exec($command);
        }               
        $this->render('form',array('model'=>$model));           
    }
 
}

ActionGetProgressBarData.php, which is also placed under /controllers directory

<?php
class ActionGetProgressBarData extends CAction 
{    
    public function run($key) 
    {
        $response = ProgressBar::get($key);
        echo json_encode($response);            
    }
 
}
 
?>
  • 2 View files

form.php

<div class="form">
    <?php $form=$this->beginWidget('CActiveForm', array(
        'id'=>'form_id',
    )); ?>
 
    ...
 
    <div class="row buttons">
        <?php echo CHtml::submitButton('Batch Process', array('name'=>'Batch')); ?>
        <?php echo CHtml::hiddenField('progress_key', uniqid(), array('id'=>'progress_key')); ?>        
    </div>
 
 
    <?php $this->endWidget(); ?>
</div>
 
<?php 
        $js_code=<<<EOD
jQuery('#form_id input[type=submit]').on('click', function() {
        $('#progress_key').val(uniqid());
        open_progress_bar();
        return true;
    });
 
EOD;
 
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.'form_id', $js_code);
 
 
?>
 
<?php 
    $this->widget('zii.widgets.jui.CJuiButton',array('name'=>'just_for_include_jqeuryui_css','htmlOptions'=>array('style'=>'display:none;')));
    $this->renderPartial('VProgressBar');    // include the progress bar here, should we wrap it into a CJuiWidget?
?>

VProgressBar.php

<script type="text/javascript">
 
function open_progress_bar() 
{
    my_title = 'Processing, please wait...';            
    $('#modalDivProgress').dialog({
        autoOpen: true,
        width: 800,
        height:150,
        modal: true,
        title: my_title
    });
    $("#progressbar").progressbar({value: 0});
    show_progress();    
}
 
function show_progress() 
{   
    var url = '<?php echo Yii::app()->controller->createUrl("GetProgressBarData"); ?>';
    var progress_key = $('#progress_key').val();
    $.getJSON(url + "&key=" + progress_key, function(data) {
        var done = parseInt(data.done);
        var total = parseInt(data.total);
        var percentage = Math.floor(100 * done / total);
        if (percentage > 100) 
            percentage = 100;
        $("#progressbar").progressbar( "value", percentage);
        var percentage_txt = percentage + "%" + " [" + done + "/" + total + "]";
        $("#percentage").text(percentage_txt);
        if (percentage == 100) {
            alert('Done');
            $("#progressbar").progressbar( "destroy");
            $("#modalDivProgress").dialog("close");
        } else {
            setTimeout("show_progress()", 5000);                    
        }
    });
}
 
function uniqid (prefix, more_entropy) {
  // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // +    revised by: Kankrelune (http://www.webfaktory.info/)
  // %        note 1: Uses an internal counter (in php_js global) to avoid collision
  // *     example 1: uniqid();
  // *     returns 1: 'a30285b160c14'
  // *     example 2: uniqid('foo');
  // *     returns 2: 'fooa30285b1cd361'
  // *     example 3: uniqid('bar', true);
  // *     returns 3: 'bara20285b23dfd1.31879087'
  if (typeof prefix === 'undefined') {
    prefix = "";
  }
 
  var retId;
  var formatSeed = function (seed, reqWidth) {
    seed = parseInt(seed, 10).toString(16); // to hex str
    if (reqWidth < seed.length) { // so long we split
      return seed.slice(seed.length - reqWidth);
    }
    if (reqWidth > seed.length) { // so short we pad
      return Array(1 + (reqWidth - seed.length)).join('0') + seed;
    }
    return seed;
  };
 
  // BEGIN REDUNDANT
  if (!this.php_js) {
    this.php_js = {};
  }
  // END REDUNDANT
  if (!this.php_js.uniqidSeed) { // init seed with big random int
    this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15);
  }
  this.php_js.uniqidSeed++;
 
  retId = prefix; // start with prefix, add current milliseconds hex string
  retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8);
  retId += formatSeed(this.php_js.uniqidSeed, 5); // add seed hex string
  if (more_entropy) {
    // for more entropy we add a float lower to 10
    retId += (Math.random() * 10).toFixed(8).toString();
  }
 
  return retId;
}
 
</script>
 
<div id="modalDivProgress" style="margin: 20px auto;">
    <div id="progressbar" style="width:780px;"></div>
    <div id="percentage" style="margin-top: -22px;margin-left:310px;"></div>
</div>
  • 1 Command file CliCommand.php
<?php
 
class CliCommand extends CConsoleCommand
{
 
    public function actionBatchHandle($id) 
    {
        set_time_limit(0);  
        $filename = Yii::app()->getRuntimePath().DIRECTORY_SEPARATOR."{$id}";
        $post = file_get_contents($filename);
        $post = json_decode($post, true);
 
        //$criteria = getCriteria($post);
        ...
 
        $total = Yii::app()->db->getCommandBuilder()->createCountCommand('table_name', $criteria)->queryScalar();
        $progress = new ProgressBar($post['progress_key']);
        $progress->start($total);
 
        $dataReader = Yii::app()->db->getCommandBuilder()->createFindCommand('table_name', $criteria)->query(); 
        while(($row=$dataReader->read())!==false) 
        {
            // process one record
            ...
            $progress->inc();   
        }   
        $progress->stop();  
 
        unlink($filename);
    }   
 
}

Total 1 comment

#14218 report it
VivekYii at 2013/07/27 08:00am
Too good but .....plz provide Video tutorial as well

I like this tutorial but video can make well for YII popularity issue.

Leave a comment

Please to leave your comment.

Write new article