CStarRating.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. /**
  3. * CStarRating class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CStarRating displays a star rating control that can collect user rating input.
  12. *
  13. * CStarRating is based on {@link http://www.fyneworks.com/jquery/star-rating/ jQuery Star Rating Plugin}.
  14. * It displays a list of stars indicating the rating values. Users can toggle these stars
  15. * to indicate their rating input. On the server side, when the rating input is submitted,
  16. * the value can be retrieved in the same way as working with a normal HTML input.
  17. * For example, using
  18. * <pre>
  19. * $this->widget('CStarRating',array('name'=>'rating'));
  20. * </pre>
  21. * we can retrieve the rating value via <code>$_POST['rating']</code>.
  22. *
  23. * CStarRating allows customization of its appearance. It also supports empty rating as well as read-only rating.
  24. *
  25. * @author Qiang Xue <qiang.xue@gmail.com>
  26. * @package system.web.widgets
  27. * @since 1.0
  28. */
  29. class CStarRating extends CInputWidget
  30. {
  31. /**
  32. * @var integer the number of stars. Defaults to 5.
  33. */
  34. public $starCount=5;
  35. /**
  36. * @var mixed the minimum rating allowed. This can be either an integer or a float value. Defaults to 1.
  37. */
  38. public $minRating=1;
  39. /**
  40. * @var mixed the maximum rating allowed. This can be either an integer or a float value. Defaults to 10.
  41. */
  42. public $maxRating=10;
  43. /**
  44. * @var mixed the step size of rating. This is the minimum difference between two rating values. Defaults to 1.
  45. */
  46. public $ratingStepSize=1;
  47. /**
  48. * @var mixed the CSS file used for the widget. Defaults to null, meaning
  49. * using the default CSS file included together with the widget.
  50. * If false, no CSS file will be used. Otherwise, the specified CSS file
  51. * will be included when using this widget.
  52. */
  53. public $cssFile;
  54. /**
  55. * @var array the titles associated with the rating options. The keys are ratings and the values are the corresponding titles.
  56. * Defaults to null, meaning using the rating value as the title.
  57. */
  58. public $titles;
  59. /**
  60. * @var string the hint text for the reset button. Defaults to null, meaning using the system-defined text (which is 'Cancel Rating').
  61. */
  62. public $resetText;
  63. /**
  64. * @var string the value taken when the rating is cleared. Defaults to null, meaning using the system-defined value (which is '').
  65. */
  66. public $resetValue;
  67. /**
  68. * @var boolean whether the rating value can be empty (not set). Defaults to true.
  69. * When this is true, a reset button will be displayed in front of stars.
  70. */
  71. public $allowEmpty;
  72. /**
  73. * @var integer the width of star image. Defaults to null, meaning using the system-defined value (which is 16).
  74. */
  75. public $starWidth;
  76. /**
  77. * @var boolean whether the rating value is read-only or not. Defaults to false.
  78. * When this is true, the rating cannot be changed.
  79. */
  80. public $readOnly;
  81. /**
  82. * @var string Callback when the stars are focused.
  83. */
  84. public $focus;
  85. /**
  86. * @var string Callback when the stars are not focused.
  87. */
  88. public $blur;
  89. /**
  90. * @var string Callback when the stars are clicked.
  91. */
  92. public $callback;
  93. /**
  94. * Executes the widget.
  95. * This method registers all needed client scripts and renders
  96. * the text field.
  97. */
  98. public function run()
  99. {
  100. list($name,$id)=$this->resolveNameID();
  101. if(isset($this->htmlOptions['id']))
  102. $id=$this->htmlOptions['id'];
  103. else
  104. $this->htmlOptions['id']=$id;
  105. if(isset($this->htmlOptions['name']))
  106. $name=$this->htmlOptions['name'];
  107. $this->registerClientScript($id);
  108. echo CHtml::openTag('span',$this->htmlOptions)."\n";
  109. $this->renderStars($id,$name);
  110. echo "</span>";
  111. }
  112. /**
  113. * Registers the necessary javascript and css scripts.
  114. * @param string $id the ID of the container
  115. */
  116. public function registerClientScript($id)
  117. {
  118. $jsOptions=$this->getClientOptions();
  119. $jsOptions=empty($jsOptions) ? '' : CJavaScript::encode($jsOptions);
  120. $js="jQuery('#{$id} > input').rating({$jsOptions});";
  121. $cs=Yii::app()->getClientScript();
  122. $cs->registerCoreScript('rating');
  123. $cs->registerScript('Yii.CStarRating#'.$id,$js);
  124. if($this->cssFile!==false)
  125. self::registerCssFile($this->cssFile);
  126. }
  127. /**
  128. * Registers the needed CSS file.
  129. * @param string $url the CSS URL. If null, a default CSS URL will be used.
  130. */
  131. public static function registerCssFile($url=null)
  132. {
  133. $cs=Yii::app()->getClientScript();
  134. if($url===null)
  135. $url=$cs->getCoreScriptUrl().'/rating/jquery.rating.css';
  136. $cs->registerCssFile($url);
  137. }
  138. /**
  139. * Renders the stars.
  140. * @param string $id the ID of the container
  141. * @param string $name the name of the input
  142. */
  143. protected function renderStars($id,$name)
  144. {
  145. $inputCount=(int)(($this->maxRating-$this->minRating)/$this->ratingStepSize+1);
  146. $starSplit=(int)($inputCount/$this->starCount);
  147. if($this->hasModel())
  148. {
  149. $attr=$this->attribute;
  150. CHtml::resolveName($this->model,$attr);
  151. $selection=$this->model->$attr;
  152. }
  153. else
  154. $selection=$this->value;
  155. $options=$starSplit>1 ? array('class'=>"{split:{$starSplit}}") : array();
  156. for($value=$this->minRating, $i=0;$i<$inputCount; ++$i, $value+=$this->ratingStepSize)
  157. {
  158. $options['id']=$id.'_'.$i;
  159. $options['value']=$value;
  160. if(isset($this->titles[$value]))
  161. $options['title']=$this->titles[$value];
  162. else
  163. unset($options['title']);
  164. echo CHtml::radioButton($name,!strcmp($value,$selection),$options) . "\n";
  165. }
  166. }
  167. /**
  168. * @return array the javascript options for the star rating
  169. */
  170. protected function getClientOptions()
  171. {
  172. $options=array();
  173. if($this->resetText!==null)
  174. $options['cancel']=$this->resetText;
  175. if($this->resetValue!==null)
  176. $options['cancelValue']=$this->resetValue;
  177. if($this->allowEmpty===false)
  178. $options['required']=true;
  179. if($this->starWidth!==null)
  180. $options['starWidth']=$this->starWidth;
  181. if($this->readOnly===true)
  182. $options['readOnly']=true;
  183. foreach(array('focus', 'blur', 'callback') as $event)
  184. {
  185. if($this->$event!==null)
  186. {
  187. if($this->$event instanceof CJavaScriptExpression)
  188. $options[$event]=$this->$event;
  189. else
  190. $options[$event]=new CJavaScriptExpression($this->$event);
  191. }
  192. }
  193. return $options;
  194. }
  195. }