AjaxLink.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category ZendX
  16. * @package ZendX_JQuery
  17. * @subpackage View
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_View_Helper_HtmlElement
  24. */
  25. include_once "Zend/View/Helper/HtmlElement.php";
  26. /**
  27. * jQuery Accordion Pane, goes with Accordion Container
  28. *
  29. * @uses Zend_Json
  30. * @package ZendX_JQuery
  31. * @subpackage View
  32. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class ZendX_JQuery_View_Helper_AjaxLink extends Zend_View_Helper_HtmlElement
  36. {
  37. /**
  38. * Static because multiple instances accross views of AjaxLink could reset the counter and a
  39. * subcontainer because of this single private class variable seems too much overhead.
  40. *
  41. * @staticvar Integer
  42. */
  43. private static $currentLinkCallbackId = 1;
  44. /**
  45. * Create an anchor that enables ajax-based requests and handling of the response.
  46. *
  47. * This helper creates links that make XmlHttpRequests to the server. It allows to
  48. * inject the response into the DOM. Fancy effects going with the links can be enabled
  49. * via simple callback shortnames. The functionality is mostly controlled by the $options
  50. * array:
  51. *
  52. * $options
  53. * Key Behaviour
  54. * =================================================================================
  55. * 'update' Update a container with the content fetched from $url
  56. * 'method' Explicit Requesting method mimicing the jQuery functionality: GET, POST
  57. * 'inline' True or false, wheater to inline the javascript in onClick=""
  58. * atttribute or append it to jQuery onLoad Stack.
  59. * 'complete' String specifies javascript called after successful request or a
  60. * shortname of a jQuery effect that should be applied to the 'update' element.
  61. * 'beforeSend' String specifies javascript called before the request is sent, or a
  62. * shortname of a jQuery effect that should be applied to the link clicked.
  63. * 'noscript' True/false, include a noscript variant that directly requests
  64. * the given $url (make sure to check $request->isXmlHttpRequest())
  65. * 'dataType' What type of data is the response returning? text, html, json?
  66. * 'title' HTML Attribute title of the Anchor
  67. * 'class' HTML Attribute class of the Anchor
  68. * 'id' HTML Attribute id of the Anchor
  69. * 'attribs' Array of Key-Value pairs with HTML Attribute names and their content.
  70. *
  71. * BeforeSend Callback:
  72. * Can include shortcuts as a string assignment to fire of effects before sending of request.
  73. * Possible shortcuts are 'fadeOut', 'fadeOutSlow', 'hide', 'hideSlow', 'slideUp', 'flash',
  74. * @example $options = array('beforeSend' => 'hideSlow', 'complete' => 'show');
  75. *
  76. * @link http://docs.jquery.com/Ajax
  77. * @param String $label Urls Title
  78. * @param String $url Link to Point to
  79. * @param Array $options
  80. * @param Array $params Key Value Pairs of GET/POST Parameters
  81. * @return String
  82. */
  83. public function ajaxLink($label, $url, $options=null, $params=null)
  84. {
  85. $jquery = $this->view->jQuery();
  86. $jquery->enable();
  87. $jqHandler = (ZendX_JQuery_View_Helper_JQuery::getNoConflictMode()==true)?'$j':'$';
  88. $attribs = array();
  89. if(isset($options['attribs']) && is_array($options['attribs'])) {
  90. $attribs = $options['attribs'];
  91. }
  92. //
  93. // The next following 4 conditions check for html attributes that the link might need
  94. //
  95. if(empty($options['noscript']) || $options['noscript'] == false) {
  96. $attribs['href'] = "#";
  97. } else {
  98. $attribs['href'] = $url;
  99. }
  100. if(!empty($options['title'])) {
  101. $attribs['title'] = $options['title'];
  102. }
  103. // class value is an array because the jQuery CSS selector
  104. // click event needs its own classname later on
  105. if(!isset($attribs['class'])) {
  106. $attribs['class'] = array();
  107. } elseif(is_string($attribs['class'])) {
  108. $attribs['class'] = explode(" ", $attribs['class']);
  109. }
  110. if(!empty($options['class'])) {
  111. $attribs['class'][] = $options['class'];
  112. }
  113. if(!empty($options['id'])) {
  114. $attribs['id'] = $options['id'];
  115. }
  116. //
  117. // Execute Javascript inline?
  118. //
  119. $inline = false;
  120. if(!empty($options['inline']) && $options['inline'] == true) {
  121. $inline = true;
  122. }
  123. //
  124. // Detect the callbacks:
  125. // Just those two callbacks, beforeSend and complete can be defined for the $.get and $.post options.
  126. // Pick all the defined callbacks and put them on their respective stacks.
  127. //
  128. $callbacks = array('beforeSend' => null, 'complete' => null);
  129. if(isset($options['beforeSend'])) {
  130. $callbacks['beforeSend'] = $options['beforeSend'];
  131. }
  132. if(isset($options['complete'])) {
  133. $callbacks['complete'] = $options['complete'];
  134. }
  135. $updateContainer = false;
  136. if(!empty($options['update']) && is_string($options['update'])) {
  137. $updateContainer = $options['update'];
  138. // Additionally check if there is a callback complete that is a shortcut to be executed
  139. // on the specified update container
  140. if(!empty($callbacks['complete'])) {
  141. switch(strtolower($callbacks['complete'])) {
  142. case 'show':
  143. $callbacks['complete'] = sprintf('%s("%s").show();', $jqHandler, $updateContainer);
  144. break;
  145. case 'showslow':
  146. $callbacks['complete'] = sprintf('%s("%s").show("slow");', $jqHandler, $updateContainer);
  147. break;
  148. case 'shownormal':
  149. $callbacks['complete'] = sprintf('%s("%s").show("normal");', $jqHandler, $updateContainer);
  150. break;
  151. case 'showfast':
  152. $callbacks['complete'] = sprintf('%s("%s").show("fast");', $jqHandler, $updateContainer);
  153. break;
  154. case 'fadein':
  155. $callbacks['complete'] = sprintf('%s("%s").fadeIn("normal");', $jqHandler, $updateContainer);
  156. break;
  157. case 'fadeinslow':
  158. $callbacks['complete'] = sprintf('%s("%s").fadeIn("slow");', $jqHandler, $updateContainer);
  159. break;
  160. case 'fadeinfast':
  161. $callbacks['complete'] = sprintf('%s("%s").fadeIn("fast");', $jqHandler, $updateContainer);
  162. break;
  163. case 'slidedown':
  164. $callbacks['complete'] = sprintf('%s("%s").slideDown("normal");', $jqHandler, $updateContainer);
  165. break;
  166. case 'slidedownslow':
  167. $callbacks['complete'] = sprintf('%s("%s").slideDown("slow");', $jqHandler, $updateContainer);
  168. break;
  169. case 'slidedownfast':
  170. $callbacks['complete'] = sprintf('%s("%s").slideDown("fast");', $jqHandler, $updateContainer);
  171. break;
  172. }
  173. }
  174. }
  175. if(empty($options['dataType'])) {
  176. $options['dataType'] = "html";
  177. }
  178. $requestHandler = $this->_determineRequestHandler($options, (count($params)>0)?true:false);
  179. $callbackCompleteJs = array();
  180. if($updateContainer != false) {
  181. if($options['dataType'] == "text") {
  182. $callbackCompleteJs[] = sprintf('%s("%s").text(data);', $jqHandler, $updateContainer);
  183. } else {
  184. $callbackCompleteJs[] = sprintf('%s("%s").html(data);', $jqHandler, $updateContainer);
  185. }
  186. }
  187. if($callbacks['complete'] != null) {
  188. $callbackCompleteJs[] = $callbacks['complete'];
  189. }
  190. if(isset($params) && count($params) > 0) {
  191. $params = ZendX_JQuery::encodeJson($params);
  192. } else {
  193. $params = '{}';
  194. }
  195. $js = array();
  196. if($callbacks['beforeSend'] != null) {
  197. switch(strtolower($callbacks['beforeSend'])) {
  198. case 'fadeout':
  199. $js[] = sprintf('%s(this).fadeOut();', $jqHandler);
  200. break;
  201. case 'fadeoutslow':
  202. $js[] = sprintf('%s(this).fadeOut("slow");', $jqHandler);
  203. break;
  204. case 'fadeoutfast':
  205. $js[] = sprintf('%s(this).fadeOut("fast");', $jqHandler);
  206. break;
  207. case 'hide':
  208. $js[] = sprintf('%s(this).hide();', $jqHandler);
  209. break;
  210. case 'hideslow':
  211. $js[] = sprintf('%s(this).hide("slow");', $jqHandler);
  212. break;
  213. case 'hidefast':
  214. $js[] = sprintf('%s(this).hide("fast");', $jqHandler);
  215. break;
  216. case 'slideup':
  217. $js[] = sprintf('%s(this).slideUp(1000);', $jqHandler);
  218. break;
  219. default:
  220. $js[] = $callbacks['beforeSend'];
  221. break;
  222. }
  223. }
  224. switch($requestHandler) {
  225. case 'GET':
  226. $js[] = sprintf('%s.get("%s", %s, function(data, textStatus) { %s }, "%s");return false;',
  227. $jqHandler, $url, $params, implode(' ', $callbackCompleteJs), $options['dataType']);
  228. break;
  229. case 'POST':
  230. $js[] = sprintf('%s.post("%s", %s, function(data, textStatus) { %s }, "%s");return false;',
  231. $jqHandler, $url, $params, implode(' ', $callbackCompleteJs), $options['dataType']);
  232. break;
  233. }
  234. $js = implode($js);
  235. if($inline == true) {
  236. $attribs['onclick'] = $js;
  237. } else {
  238. if(!isset($attribs['id'])) {
  239. $clickClass = sprintf("ajaxLink%d", ZendX_JQuery_View_Helper_AjaxLink::$currentLinkCallbackId);
  240. ZendX_JQuery_View_Helper_AjaxLink::$currentLinkCallbackId++;
  241. $attribs['class'][] = $clickClass;
  242. $onLoad = sprintf('%s("a.%s").click(function() { %s });', $jqHandler, $clickClass, $js);
  243. } else {
  244. $onLoad = sprintf('%s("a#%s").click(function() { %s });', $jqHandler, $attribs['id'], $js);
  245. }
  246. $jquery->addOnLoad($onLoad);
  247. }
  248. if(count($attribs['class']) > 0) {
  249. $attribs['class'] = implode(" ", $attribs['class']);
  250. } else {
  251. unset($attribs['class']);
  252. }
  253. $html = '<a'
  254. . $this->_htmlAttribs($attribs)
  255. . '>'
  256. . $label
  257. . '</a>';
  258. return $html;
  259. }
  260. /**
  261. * Determine which request method (GET or POST) should be used.
  262. *
  263. * Normally the request method is determined implicitly by the rule,
  264. * if addiotional params are sent, POST, if not GET. You can overwrite
  265. * this behaviiour by implicitly setting $options['method'] = "POST|GET";
  266. *
  267. * @param Array $options
  268. * @param Boolean $hasParams
  269. * @return String
  270. */
  271. protected function _determineRequestHandler($options, $hasParams)
  272. {
  273. if(isset($options['method']) && in_array(strtoupper($options['method']), array('GET', 'POST'))) {
  274. return strtoupper($options['method']);
  275. }
  276. $requestHandler = "GET";
  277. if($hasParams == true) {
  278. $requestHandler = "POST";
  279. }
  280. return $requestHandler;
  281. }
  282. }