MootoolsEngineHelper.php 11 KB

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