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

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);
	}	

}



3 0
7 followers
Viewed: 85 059 times
Version: 1.1
Category: How-tos
Written by: hehbhehb
Last updated by: Boaz
Created on: Jul 23, 2013
Last updated: 10 years ago
Update Article

Revisions

View all history

Related Articles