Commits

christiansalazar committed 7f4445a

version 1.0

Comments (0)

Files changed (6)

EFilterWidget.php

+<?php
+/**
+ * EFilterWidget 
+ *
+ *	Please refer to README about details.
+ *
+ *
+ * @uses CWidget
+ * @version 1.0 
+ * @author Christian Salazar <christiansalazarh@gmail.com> 
+ * @license FREE BSD
+ */
+class EFilterWidget extends CWidget {
+
+	public $id;					// HTML MAIN DIV ID
+	public $findButtonLabel;	// "Find >>"
+	public $okButtonLabel;		// "OK"
+	public $pleaseSelectText;	// "-please select-"
+	public $fields;				// array. see doc.
+	public $action;				// action array URL
+	
+	// WAW1: using an ID as receptor for selected value uppon user clicks "OK"
+	public $receptorId; 
+	// WAY2: using onSuccess event handler fired when user clicks "OK"
+	public $onSuccess;			// successfull user selection handler
+	// onError will always be called on any error.
+	public $onError;			// error handler
+	public $backgroundColor;	// widget bg color. default none.
+
+
+	private $_baseUrl;
+	public $debug;
+
+	public function init(){
+		parent::init();
+		if($this->pleaseSelectText == null)
+			$this->pleaseSelectText = '-please select-';
+		if($this->okButtonLabel==null)
+			$this->okButtonLabel='OK';
+		if($this->findButtonLabel==null)
+			$this->findButtonLabel='Find>>';
+		if($this->onSuccess == null)
+			$this->onSuccess = "function(){}";
+		if($this->onError == null)
+			$this->onError = "function(){}";
+		if($this->backgroundColor == null)
+			$this->backgroundColor = '';
+	}
+
+	public function run(){
+		$this->_prepareAssets();
+
+		$keys = array();
+		$html = "<ul class='efilterwidget-ul'>";
+		foreach($this->fields as $key=>$field){
+			$keys[] = $key;
+			$html .= $this->_buildFieldUI(
+				$key,
+				$field['ui'], 
+				$field['label'], 
+				$field['value'],
+				isset($field['options']) ? $field['options'] : array(),
+				isset($field['size']) ? $field['size'] : ""
+			);
+		}
+		$html .= "</ul>";
+
+		$findid = $this->id."-find";
+		$findsel = $this->id."-sel";
+		$findok = $this->id."-ok";
+		$imgloading=$this->id."-loading";
+		$loading = $this->_baseUrl . '/loading.gif';
+
+		$ss="";
+		if($this->backgroundColor != '')
+			$ss = "style='background-color: ".$this->backgroundColor.";'";
+
+		// main html layout for this UI component
+		//
+		echo 
+"
+<!-- efilterwidget extension by: christiansalazarh@gmail.com -->
+<div id={$this->id} class='efilterwidget' {$ss}>
+	{$html}
+	<div class='finder'>
+		<input id='{$findid}' type='button' value='"
+			.CHtml::encode($this->findButtonLabel)."'>
+		<select id='{$findsel}' class='efilterwidget-results'></select>
+		<input id='{$findok}' class='okbutton' type='button' value='"
+			.CHtml::encode($this->okButtonLabel)."'>
+		<img src='{$loading}' style='display: none;' id='{$imgloading}'>
+	</div>
+</div>
+";
+
+		// options passed by to main jQuery script
+		//
+		
+		$options = CJavaScript::encode(array(
+			'action'=>CHtml::normalizeUrl($this->action),
+			'id'=>$this->id,
+			'keys'=>$keys,
+			'findid'=>$findid,
+			'sel'=>$findsel,
+			'findok'=>$findok,
+			'loading'=>$imgloading,
+			'pleaseSelect'=>$this->pleaseSelectText,
+			'receptorId'=>$this->receptorId,
+			'onSuccess'=>new CJavaScriptExpression($this->onSuccess),
+			'onError'=>new CJavaScriptExpression($this->onError),
+		));
+		Yii::app()->getClientScript()->registerScript("efilterwidget_script"
+				,"new EFilterWidget({$options})");
+		
+	}// end run()
+
+	public function _prepareAssets(){
+		$localAssetsDir = dirname(__FILE__) . '/assets';
+		$this->_baseUrl = Yii::app()->getAssetManager()->publish(
+				$localAssetsDir);
+
+		if($this->debug == true)
+		$this->_baseUrl = 'protected/extensions/efilterwidget/assets';
+
+        $cs = Yii::app()->getClientScript();
+        $cs->registerCoreScript('jquery');
+		foreach(scandir($localAssetsDir) as $f){
+			$_f = strtolower($f);
+			if(strstr($_f,".swp"))
+				continue;
+			if(strstr($_f,".js"))
+				$cs->registerScriptFile($this->_baseUrl."/".$_f);
+			if(strstr($_f,".css"))
+				$cs->registerCssFile($this->_baseUrl."/".$_f);
+		}
+	}
+
+
+	private function _buildFieldUI($key,$ui, $label, $value, $options, $size){
+		if($ui == 'text'){
+			return $this->_buildTextUI($key,$label, $value, $size);
+		}elseif($ui == 'list'){
+			return $this->_buildListUI($key,$label, $value, $options, $size);
+		}
+		else
+			throw new Exception("Invalid argument value for UI."
+					." must be 'text' or 'list'");
+	}
+
+	private function _buildTextUI($key, $label, $value, $size){
+		$ss=''; if($size != '') $ss = "size={$size}";
+		return 
+"
+<li class='efilterwidget-ui-text' id='{$key}'>
+   <div>{$label}</div>
+   <input type='text' class='efilterwidget-value' {$ss} value='{$value}'>
+</li>
+";	
+	}
+
+	private function _buildListUI($key, $label, $value,$options, $size){
+		$list = CHtml::dropDownList($key.'-list',$value,$options,
+			array('class'=>'efilterwidget-value'));
+		return
+"
+<li class='efilterwidget-ui-list' id='{$key}'>
+   <div>{$label}</div>
+   {$list}
+</li>
+";	
+	}
+
+}
+EFilterWidget
+=============
+
+author: Christian Salazar <christiansalazarh@gmail.com>
+
+licence: NEW BSD
+
+EN
+--
+This widget presents a form containing a set of fields defined on the widget 
+arguments, when user press the 'Find' button an ajax action will be fired,
+in response the client must select an option obtained from your remote query.
+
+ES
+--
+
+Este widget presenta un formulario al cliente, el cual dispara una consulta 
+ajax con los parametros configurados, devolviendo al cliente una lista de 
+opciones para seleccionar cuando este presiona el boton "Buscar"(Find).
+
+Example Widget:
+---------------
+
+~~~
+<?php                                                                          
+    $this->widget('ext.efilterwidget.EFilterWidget'
+	,array(
+    	'id'=>'efilterwidget1',
+    	'findButtonLabel'=>'Find>>',
+    	'okButtonLabel'=>'OK',
+    	'fields'=>array(
+    		'year'=>array(
+    				'ui'=>'text',
+    				'label'=>'Year:',
+    				'value'=>'',
+    				'size'=>10,
+    			),
+    		'month'=>array(
+    				'ui'=>'list',
+    				'label'=>'Months:',
+    				'value'=>'FEB',
+    				'size'=>10,
+    				'options'=>array(''=>'??','JAN'=>'Enero','FEB'=>'Febrero'),
+    			),
+    	),
+    	'action'=>array('site/efilterwidgetsample'),
+    	'receptorId'=>'testValue',
+    	'onSuccess'=>"function(data){ $('#logger').html(data); }",
+    	'onError'=>"function(err){ $('#logger').html('error: '+err);  }",
+    	'backgroundColor'=>'#ccffee',
+    ));
+?>	
+<div id='logger'></div>
+<?php 
+    echo "Example text field receptor:";
+    echo CHtml::textField('testValue','');
+?>
+~~~
+
+Your Action:
+------------
+
+~~~
+<?php
+// in any controller, please be consistent with 'action' parameter on widget.
+//
+public function actionEFilterWidgetSample(){
+	// 'keys' is an argument sent by EFilterWidget who informs about
+	// 	each key present in URL argument. is a helper.
+	//	is a comma-separated key names string.	
+	$keys = explode(",",$_GET['keys']);
+	// sample array filtered by argument passed by URL
+	//	example:  
+	//	Person::model()->findByAttributes(array('uid'=>$_GET['uid']));
+	//	available keys: $_GET['keys'], will return: "uid,firstname" (ie). 
+	$sample = array(
+		 array('userid'=>'U1', 'name'=>'christian')
+		,array('userid'=>'U2', 'name'=>'anahi')
+		,array('userid'=>'U3', 'name'=>'pedro')
+		,array('userid'=>'U4', 'name'=>'lisbeth')
+	);
+	// 	IMPORTANT:
+	// 	The widget requires JSON data
+	//	please return a value generated by CHtml::listData
+	//	and converted to json using: CJSON::encode(...)
+	header("Content-type: application/json");
+	echo CJSON::encode(CHtml::listData($sample, 'userid', 'name'));
+}
+?>
+~~~

assets/efilter.css

+div.efilterwidget {
+	border: 1px dotted #aaa;
+	border-radius: 5px;
+	width: 200px;
+	padding: 10px;
+	display: block;
+}
+
+div.efilterwidget ul {
+	list-style: none;
+	margin: 3px;
+	padding: 0px;
+}
+
+div.efilterwidget .finder {
+	border: 1px solid #ccc;
+	border-radius: 5px;
+	background-color: #cceeff;
+	padding: 5px;
+}
+
+div.efilterwidget input.okbutton {
+	display: block;
+}

assets/efilter.js

+// el codigo JS del widget
+//
+var EFilterWidget = function(options){
+
+	var divMayor = $('#'+options.id);
+	
+	var ajaxcmd = function(action,postdata,callback){
+		var result=false;
+		var nocache=function(){
+			var dateObject = new Date();
+			var uuid = dateObject.getTime();
+			return "&nocache="+uuid;
+		}
+		jQuery.ajax({
+			url: action+nocache(),
+			type: 'post',
+			async: false,
+			contentType: "application/json",
+			data: postdata,
+			success: function(data, textStatus, jqXHR){
+				result = data;
+				if(callback != null)
+					callback(true, data);
+			},
+			error: function(jqXHR, textStatus, errorThrown){
+				callback(false, jqXHR.responseText);
+				return false;
+			},
+		});
+		return result;
+	}
+
+	$('#'+options.findid).click(function(){
+		var urlArgs='';
+		var kk='';
+		var c='';
+		$.each(options.keys, function(index,key){
+			var value = $('#'+key).find('.efilterwidget-value').val();
+			urlArgs += '&'+key+'='+value;
+			kk += c+key;
+			c=',';
+		});		
+	    // plus special argument: keys
+		urlArgs += '&keys='+kk;
+		
+		var loading = $('#'+options.loading);
+		var find = $('#'+options.findid);
+		var ok = $('#'+options.findok);
+		var sel = $('#'+options.sel);
+		loading.show();
+		ok.attr('disabled','disabled');
+		find.attr('disabled','disabled');
+		sel.attr('disabled','disabled');
+		sel.find('option').each(function(){ $(this).remove(); });
+
+		ajaxcmd(options.action+urlArgs,'',function(result, data){
+			find.attr('disabled',null);
+			sel.attr('disabled',null);
+			ok.attr('disabled',null);
+			loading.hide();
+			if(result == true){
+				// data comming from server, fill select options
+				// and wait for user interaction
+				//
+				// DATA EXPECTED HERE:  JSON ARRAY, key=>value
+				var opts="<option value=''>"+options.pleaseSelect+"</option>";
+				$.each(data,function(value,text){
+					opts += "<option value='"+value+"'>"+text+"</option>";					
+				});
+				sel.html(opts);
+			}else{
+				options.onError(data);
+			}
+		});
+	});
+
+	$('#'+options.findok).click(function(){
+		var value = $('#'+options.sel).val();
+		if(value != ''){
+			if(options.receptorId != '')
+				$('#'+options.receptorId).val(value);
+			options.onSuccess(value);
+		}
+	});
+
+};

assets/loading.gif

Added
New image

screenshot.jpg

Added
New image