MootoolsEngineHelper.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <?php
  2. /**
  3. * MooTools Engine Helper for JsHelper
  4. *
  5. * Provides MooTools specific Javascript for JsHelper.
  6. * Assumes that you have the following MooTools packages
  7. *
  8. * - Remote, Remote.HTML, Remote.JSON
  9. * - Fx, Fx.Tween, Fx.Morph
  10. * - Selectors, DomReady,
  11. * - Drag, Drag.Move
  12. *
  13. * PHP 5
  14. *
  15. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  16. * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  17. *
  18. * Licensed under The MIT License
  19. * Redistributions of files must retain the above copyright notice.
  20. *
  21. * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  22. * @link http://cakephp.org CakePHP(tm) Project
  23. * @package cake.libs.view.helpers
  24. * @since CakePHP(tm) v 1.3
  25. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  26. */
  27. App::uses('JsBaseEngineHelper', 'View/Helper');
  28. class MootoolsEngineHelper extends JsBaseEngineHelper {
  29. /**
  30. * Option mappings for MooTools
  31. *
  32. * @var array
  33. */
  34. protected $_optionMap = array(
  35. 'request' => array(
  36. 'complete' => 'onComplete',
  37. 'success' => 'onSuccess',
  38. 'before' => 'onRequest',
  39. 'error' => 'onFailure'
  40. ),
  41. 'sortable' => array(
  42. 'distance' => 'snap',
  43. 'containment' => 'constrain',
  44. 'sort' => 'onSort',
  45. 'complete' => 'onComplete',
  46. 'start' => 'onStart',
  47. ),
  48. 'drag' => array(
  49. 'snapGrid' => 'snap',
  50. 'start' => 'onStart',
  51. 'drag' => 'onDrag',
  52. 'stop' => 'onComplete',
  53. ),
  54. 'drop' => array(
  55. 'drop' => 'onDrop',
  56. 'hover' => 'onEnter',
  57. 'leave' => 'onLeave',
  58. ),
  59. 'slider' => array(
  60. 'complete' => 'onComplete',
  61. 'change' => 'onChange',
  62. 'direction' => 'mode',
  63. 'step' => 'steps'
  64. )
  65. );
  66. /**
  67. * Contains a list of callback names -> default arguments.
  68. *
  69. * @var array
  70. */
  71. protected $_callbackArguments = array(
  72. 'slider' => array(
  73. 'onTick' => 'position',
  74. 'onChange' => 'step',
  75. 'onComplete' => 'event'
  76. ),
  77. 'request' => array(
  78. 'onRequest' => '',
  79. 'onComplete' => '',
  80. 'onCancel' => '',
  81. 'onSuccess' => 'responseText, responseXML',
  82. 'onFailure' => 'xhr',
  83. 'onException' => 'headerName, value',
  84. ),
  85. 'drag' => array(
  86. 'onBeforeStart' => 'element',
  87. 'onStart' => 'element',
  88. 'onSnap' => 'element',
  89. 'onDrag' => 'element, event',
  90. 'onComplete' => 'element, event',
  91. 'onCancel' => 'element',
  92. ),
  93. 'drop' => array(
  94. 'onBeforeStart' => 'element',
  95. 'onStart' => 'element',
  96. 'onSnap' => 'element',
  97. 'onDrag' => 'element, event',
  98. 'onComplete' => 'element, event',
  99. 'onCancel' => 'element',
  100. 'onDrop' => 'element, droppable, event',
  101. 'onLeave' => 'element, droppable',
  102. 'onEnter' => 'element, droppable',
  103. ),
  104. 'sortable' => array(
  105. 'onStart' => 'element, clone',
  106. 'onSort' => 'element, clone',
  107. 'onComplete' => 'element',
  108. )
  109. );
  110. /**
  111. * Create javascript selector for a CSS rule
  112. *
  113. * @param string $selector The selector that is targeted
  114. * @return object instance of $this. Allows chained methods.
  115. */
  116. function get($selector) {
  117. $this->_multipleSelection = false;
  118. if ($selector == 'window' || $selector == 'document') {
  119. $this->selection = "$(" . $selector .")";
  120. return $this;
  121. }
  122. if (preg_match('/^#[^\s.]+$/', $selector)) {
  123. $this->selection = '$("' . substr($selector, 1) . '")';
  124. return $this;
  125. }
  126. $this->_multipleSelection = true;
  127. $this->selection = '$$("' . $selector . '")';
  128. return $this;
  129. }
  130. /**
  131. * Add an event to the script cache. Operates on the currently selected elements.
  132. *
  133. * ### Options
  134. *
  135. * - 'wrap' - Whether you want the callback wrapped in an anonymous function. (defaults true)
  136. * - 'stop' - Whether you want the event to stopped. (defaults true)
  137. *
  138. * @param string $type Type of event to bind to the current dom id
  139. * @param string $callback The Javascript function you wish to trigger or the function literal
  140. * @param array $options Options for the event.
  141. * @return string completed event handler
  142. */
  143. function event($type, $callback, $options = array()) {
  144. $defaults = array('wrap' => true, 'stop' => true);
  145. $options = array_merge($defaults, $options);
  146. $function = 'function (event) {%s}';
  147. if ($options['wrap'] && $options['stop']) {
  148. $callback = "event.stop();\n" . $callback;
  149. }
  150. if ($options['wrap']) {
  151. $callback = sprintf($function, $callback);
  152. }
  153. $out = $this->selection . ".addEvent(\"{$type}\", $callback);";
  154. return $out;
  155. }
  156. /**
  157. * Create a domReady event. This is a special event in many libraries
  158. *
  159. * @param string $functionBody The code to run on domReady
  160. * @return string completed domReady method
  161. */
  162. function domReady($functionBody) {
  163. $this->selection = 'window';
  164. return $this->event('domready', $functionBody, array('stop' => false));
  165. }
  166. /**
  167. * Create an iteration over the current selection result.
  168. *
  169. * @param string $method The method you want to apply to the selection
  170. * @param string $callback The function body you wish to apply during the iteration.
  171. * @return string completed iteration
  172. */
  173. function each($callback) {
  174. return $this->selection . '.each(function (item, index) {' . $callback . '});';
  175. }
  176. /**
  177. * Trigger an Effect.
  178. *
  179. * @param string $name The name of the effect to trigger.
  180. * @param array $options Array of options for the effect.
  181. * @return string completed string with effect.
  182. * @see JsBaseEngineHelper::effect()
  183. */
  184. function effect($name, $options = array()) {
  185. $speed = null;
  186. if (isset($options['speed']) && in_array($options['speed'], array('fast', 'slow'))) {
  187. if ($options['speed'] == 'fast') {
  188. $speed = '"short"';
  189. } elseif ($options['speed'] == 'slow') {
  190. $speed = '"long"';
  191. }
  192. }
  193. $effect = '';
  194. switch ($name) {
  195. case 'hide':
  196. $effect = 'setStyle("display", "none")';
  197. break;
  198. case 'show':
  199. $effect = 'setStyle("display", "")';
  200. break;
  201. case 'fadeIn':
  202. case 'fadeOut':
  203. case 'slideIn':
  204. case 'slideOut':
  205. list($effectName, $direction) = preg_split('/([A-Z][a-z]+)/', $name, -1, PREG_SPLIT_DELIM_CAPTURE);
  206. $direction = strtolower($direction);
  207. if ($speed) {
  208. $effect .= "set(\"$effectName\", {duration:$speed}).";
  209. }
  210. $effect .= "$effectName(\"$direction\")";
  211. break;
  212. }
  213. return $this->selection . '.' . $effect . ';';
  214. }
  215. /**
  216. * Create an new Request.
  217. *
  218. * Requires `Request`. If you wish to use 'update' key you must have ```Request.HTML```
  219. * if you wish to do Json requests you will need ```JSON``` and ```Request.JSON```.
  220. *
  221. * @param mixed $url
  222. * @param array $options
  223. * @return string The completed ajax call.
  224. */
  225. function request($url, $options = array()) {
  226. $url = $this->url($url);
  227. $options = $this->_mapOptions('request', $options);
  228. $type = $data = null;
  229. if (isset($options['type']) || isset($options['update'])) {
  230. if (isset($options['type']) && strtolower($options['type']) == 'json') {
  231. $type = '.JSON';
  232. }
  233. if (isset($options['update'])) {
  234. $options['update'] = str_replace('#', '', $options['update']);
  235. $type = '.HTML';
  236. }
  237. unset($options['type']);
  238. }
  239. if (!empty($options['data'])) {
  240. $data = $options['data'];
  241. unset($options['data']);
  242. }
  243. $options['url'] = $url;
  244. $options = $this->_prepareCallbacks('request', $options);
  245. if (!empty($options['dataExpression'])) {
  246. $callbacks[] = 'data';
  247. unset($options['dataExpression']);
  248. } elseif (!empty($data)) {
  249. $data = $this->object($data);
  250. }
  251. $options = $this->_parseOptions($options, array_keys($this->_callbackArguments['request']));
  252. return "var jsRequest = new Request$type({{$options}}).send($data);";
  253. }
  254. /**
  255. * Create a sortable element.
  256. *
  257. * Requires the `Sortables` plugin from MootoolsMore
  258. *
  259. * @param array $options Array of options for the sortable.
  260. * @return string Completed sortable script.
  261. * @see JsBaseEngineHelper::sortable() for options list.
  262. */
  263. function sortable($options = array()) {
  264. $options = $this->_processOptions('sortable', $options);
  265. return 'var jsSortable = new Sortables(' . $this->selection . ', {' . $options . '});';
  266. }
  267. /**
  268. * Create a Draggable element.
  269. *
  270. * Requires the `Drag` plugin from MootoolsMore
  271. *
  272. * @param array $options Array of options for the draggable.
  273. * @return string Completed draggable script.
  274. * @see JsHelper::drag() for options list.
  275. */
  276. function drag($options = array()) {
  277. $options = $this->_processOptions('drag', $options);
  278. return $this->selection . '.makeDraggable({' . $options . '});';
  279. }
  280. /**
  281. * Create a Droppable element.
  282. *
  283. * Requires the `Drag` and `Drag.Move` plugins from MootoolsMore
  284. *
  285. * Droppables in Mootools function differently from other libraries. Droppables
  286. * are implemented as an extension of Drag. So in addtion to making a get() selection for
  287. * the droppable element. You must also provide a selector rule to the draggable element. Furthermore,
  288. * Mootools droppables inherit all options from Drag.
  289. *
  290. * @param array $options Array of options for the droppable.
  291. * @return string Completed droppable script.
  292. * @see JsBaseEngineHelper::drop() for options list.
  293. */
  294. function drop($options = array()) {
  295. if (empty($options['drag'])) {
  296. trigger_error(
  297. __d('cake_error', 'MootoolsEngine::drop() requires a "drag" option to properly function'), E_USER_WARNING
  298. );
  299. return false;
  300. }
  301. $options['droppables'] = $this->selection;
  302. $this->get($options['drag']);
  303. unset($options['drag']);
  304. $options = $this->_mapOptions('drag', $this->_mapOptions('drop', $options));
  305. $options = $this->_prepareCallbacks('drop', $options);
  306. $safe = array_merge(array_keys($this->_callbackArguments['drop']), array('droppables'));
  307. $optionString = $this->_parseOptions($options, $safe);
  308. $out = $this->selection . '.makeDraggable({' . $optionString . '});';
  309. $this->selection = $options['droppables'];
  310. return $out;
  311. }
  312. /**
  313. * Create a slider control
  314. *
  315. * Requires `Slider` from MootoolsMore
  316. *
  317. * @param array $options Array of options for the slider.
  318. * @return string Completed slider script.
  319. * @see JsBaseEngineHelper::slider() for options list.
  320. */
  321. function slider($options = array()) {
  322. $slider = $this->selection;
  323. $this->get($options['handle']);
  324. unset($options['handle']);
  325. if (isset($options['min']) && isset($options['max'])) {
  326. $options['range'] = array($options['min'], $options['max']);
  327. unset($options['min'], $options['max']);
  328. }
  329. $optionString = $this->_processOptions('slider', $options);
  330. if (!empty($optionString)) {
  331. $optionString = ', {' . $optionString . '}';
  332. }
  333. $out = 'var jsSlider = new Slider(' . $slider . ', ' . $this->selection . $optionString . ');';
  334. $this->selection = $slider;
  335. return $out;
  336. }
  337. /**
  338. * Serialize the form attached to $selector.
  339. *
  340. * @param array $options Array of options.
  341. * @return string Completed serializeForm() snippet
  342. * @see JsBaseEngineHelper::serializeForm()
  343. */
  344. function serializeForm($options = array()) {
  345. $options = array_merge(array('isForm' => false, 'inline' => false), $options);
  346. $selection = $this->selection;
  347. if (!$options['isForm']) {
  348. $selection = '$(' . $this->selection . '.form)';
  349. }
  350. $method = '.toQueryString()';
  351. if (!$options['inline']) {
  352. $method .= ';';
  353. }
  354. return $selection . $method;
  355. }
  356. }