PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/atk4/lib/jQuery/Chain.php

https://github.com/mahimarathore/mahi
PHP | 245 lines | 207 code | 3 blank | 35 comment | 6 complexity | 5dbb95a9008b7fa430b840204cfa6d0e MD5 | raw file
Possible License(s): AGPL-3.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /***********************************************************
  3. jQuery chain proxy. Returned by view->js(). Calls to this
  4. class will be converted into jQuery calls.
  5. Feel free to call _XX functions in this class
  6. Reference:
  7. http://agiletoolkit.org/doc/ref
  8. ==ATK4===================================================
  9. This file is part of Agile Toolkit 4
  10. http://agiletoolkit.org/
  11. (c) 2008-2013 Agile Toolkit Limited <info@agiletoolkit.org>
  12. Distributed under Affero General Public License v3 and
  13. commercial license.
  14. See LICENSE or LICENSE_COM for more information
  15. =====================================================ATK4=*/
  16. /*
  17. This class represents sequentall calls to one jQuery object
  18. */
  19. class jQuery_Chain extends AbstractModel {
  20. public $str='';
  21. public $prepend='';
  22. public $selector=null;
  23. public $enclose=false;
  24. public $preventDefault=false;
  25. public $base='';
  26. function __call($name,$arguments){
  27. if($arguments){
  28. $a2=$this->_flattern_objects($arguments,true);
  29. $this->str.=".$name(".$a2.")";
  30. }else{
  31. $this->str.=".$name()";
  32. }
  33. return $this;
  34. }
  35. /* convert reserved words or used methods into js calls, such as "execute" */
  36. function _fn($name,$arguments=array()){
  37. // Wrapper for functons which use reserved words
  38. return $this->__call($name,$arguments);
  39. }
  40. /* converting this object into string will produce JavaScript code */
  41. function __toString(){
  42. return $this->_render();
  43. }
  44. /* Some methods shouldn't be special! */
  45. function each(){
  46. return $this->__call('each',func_get_args());
  47. }
  48. /* Chain binds to parent object by default. Use this to use other selector $('selector') */
  49. function _selector($selector=null){
  50. $this->selector=$selector;
  51. return $this;
  52. }
  53. /* Use this to bind chain to document $(document)... */
  54. function _selectorDocument(){
  55. $this->selector='__atk_selector_document';
  56. return $this;
  57. }
  58. /* Use this to bind chain to window $(window)... */
  59. function _selectorWindow(){
  60. $this->selector='__atk_selector_window';
  61. return $this;
  62. }
  63. /* Use this to bind chain to "this" $(this)... */
  64. function _selectorThis(){
  65. $this->selector='__atk_selector_this';
  66. return $this;
  67. }
  68. /* Use this to bind chain to "region" $(region). Region is defined by ATK when reloading */
  69. function _selectorRegion(){
  70. $this->selector='__atk_selector_region';
  71. return $this;
  72. }
  73. /* Execute more JavaScript code before chain. Avoid using. */
  74. function _prepend($code){
  75. if(is_array($code)){
  76. $code=join(';',$code);
  77. }
  78. $this->prepend=$code.';'.$this->prepend;
  79. return $this;
  80. }
  81. function debug(){
  82. $this->debug=true;
  83. return $this;
  84. }
  85. /* Send chain in response to form submit, button click or ajaxec() function for AJAX control output */
  86. function execute(){
  87. if(isset($_POST['ajax_submit']) || $_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest'){
  88. //if($this->api->jquery)$this->api->jquery->getJS($this->owner);
  89. $x=$this->api->template->get('document_ready');
  90. if(is_array($x))$x=join('',$x);
  91. echo $this->_render();
  92. $this->api->hook('post-js-execute');
  93. exit;
  94. }else return $this;
  95. }
  96. /* [private] used by custom json_encoding */
  97. function _safe_js_string($str) {
  98. $l=strlen($str);
  99. $ret="";
  100. for($i=0;$i<$l;++$i) {
  101. switch($str[$i]) {
  102. case "\r": $ret.="\\r"; break;
  103. case "\n": $ret.="\\n"; break;
  104. case "\"": case "'": case "<": case ">": case "&": case "\\":
  105. $ret.='\x'.dechex( ord($str[$i] ) );
  106. break;
  107. default:
  108. $ret.=$str[$i];
  109. break;
  110. }
  111. }
  112. return $ret;
  113. }
  114. /* [private] custom json_encoding. called on function arguments. */
  115. protected function _flattern_objects($arg,$return_comma_list=false){
  116. /*
  117. * This function is very similar to json_encode, however it will traverse array
  118. * before encoding in search of objects based on AbstractObject. Those would
  119. * be replaced with their json representation if function exists, otherwise
  120. * with string representation
  121. */
  122. if(is_object($arg)){
  123. if($arg instanceof jQuery_Chain){
  124. $r=$arg->_render();
  125. if(substr($r,-1)==';')$r=substr($r,0,-1);
  126. return $r;
  127. }elseif($arg instanceof AbstractView){
  128. return "'#".str_replace('/','_',$arg->name)."'";
  129. }else{
  130. return "'".$this->_safe_js_string((string)$arg)."'"; // indirectly call toString();
  131. }
  132. }elseif(is_array($arg)){
  133. $a2=array();
  134. // is array associative? (hash)
  135. $assoc=$arg!=array_values($arg);
  136. foreach($arg as $key=>$value){
  137. $value=$this->_flattern_objects($value);
  138. $key=$this->_flattern_objects($key);
  139. if(!$assoc || $return_comma_list){
  140. $a2[]=$value;
  141. }else{
  142. $a2[]=$key.':'.$value;
  143. }
  144. }
  145. if($return_comma_list){
  146. $s=join(',',$a2);
  147. }elseif($assoc){
  148. $s='{'.join(',',$a2).'}';
  149. }else{
  150. $s='['.join(',',$a2).']';
  151. }
  152. }elseif(is_string($arg)){
  153. $s="'".$this->_safe_js_string($arg)."'";
  154. }elseif(is_bool($arg)){
  155. $s=json_encode($arg);
  156. }elseif(is_numeric($arg)){
  157. $s=json_encode($arg);
  158. }elseif(is_null($arg)){
  159. $s=json_encode($arg);
  160. }else{
  161. throw $this->exception('Unable to encode value for jQuery Chain - unknown type')
  162. ->addMoreInfo('arg',$arg);
  163. }
  164. return $s;
  165. }
  166. /* Calls real redirect (from univ), but accepts page name. Use url() for 1st argument manually anyway. */
  167. function redirect($page=null,$arg=null){
  168. $url=$this->api->url($page,$arg);
  169. return $this->_fn('redirect',array($url));
  170. }
  171. /* Reload object. You can bind this to custom event and trigger it if object is not directly accessible. */
  172. function reload($arguments=array(),$fn=null,$url=null){
  173. if($fn)$fn->_enclose();
  174. $id=$this->owner;
  175. if(!$url)$url=$this->api->url(null,array('cut_object'=>$id->name));
  176. return $this->_fn('atk4_reload',array($url,$arguments,$fn));
  177. }
  178. /* Chain will not be called but will return callable function instead. */
  179. function _enclose($fn=null,$preventDefault=false){
  180. // builds structure $('obj').$fn(function(){ $('obj').XX; });
  181. if($fn===null)$fn=true;
  182. $this->enclose=$fn;
  183. $this->preventDefault=$preventDefault;
  184. return $this;
  185. }
  186. function _render(){
  187. $ret='';
  188. $ret.=$this->prepend;
  189. if($this->selector===false){
  190. $ret.="$";
  191. }elseif($this->selector==='__atk_selector_this'){
  192. $ret.="$(this)";
  193. }elseif($this->selector==='__atk_selector_document'){
  194. $ret.="$(document)";
  195. }elseif($this->selector==='__atk_selector_window'){
  196. $ret.="$(window)";
  197. }elseif($this->selector==='__atk_selector_region'){
  198. $ret.="$(region)";
  199. }else{
  200. if($this->str)$ret.="$('".($this->selector?$this->selector:'#'.str_replace('/','_',$this->owner->name))."')";
  201. }
  202. $ret.=$this->str;
  203. if($this->enclose===true){
  204. if($this->preventDefault){
  205. $ret="function(ev){ev.preventDefault();ev.stopPropagation(); ".$ret." }";
  206. }else{
  207. $ret="function(){ ".$ret." }";
  208. }
  209. }elseif($this->enclose){
  210. $ret="$('".($this->selector?$this->selector:'#'.$this->owner->name)."')".
  211. ".bind('".$this->enclose."',function(ev){ ev.preventDefault();ev.stopPropagation(); ".$ret." })";
  212. }
  213. if(@$this->debug){
  214. echo "<font color='blue'>".htmlspecialchars($ret).";</font><br/>";
  215. $this->debug=false;
  216. }
  217. return $ret;
  218. }
  219. /* Returns HTML for a link with text $text. When clicked will execute this chain. */
  220. function getLink($text){
  221. return '<a href="javascript:void(0)" onclick="'.$this->getString().'">'.$text.'</a>';
  222. }
  223. function getString(){
  224. return $this->_render();
  225. }
  226. /* Specify requirement for stylesheet. Will load dynamically. */
  227. function _css($file){
  228. $this->api->jquery->addStylesheet($file);
  229. return $this;
  230. }
  231. /* Specify requirement for extra javascript include. Will load dynamically. */
  232. function _load($file){
  233. $this->api->jquery->addInclude($file);
  234. return $this;
  235. }
  236. }