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

You are viewing revision #8 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.

« previous (#7)next (#9) »

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 070 times
Version: Unknown (update)
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