MootoolsEngineHelper.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @package Cake.View.Helper
  13. * @since CakePHP(tm) v 1.3
  14. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  15. */
  16. App::uses('JsBaseEngineHelper', 'View/Helper');
  17. /**
  18. * MooTools Engine Helper for JsHelper
  19. *
  20. * Provides MooTools specific Javascript for JsHelper.
  21. * Assumes that you have the following MooTools packages
  22. *
  23. * - Remote, Remote.HTML, Remote.JSON
  24. * - Fx, Fx.Tween, Fx.Morph
  25. * - Selectors, DomReady,
  26. * - Drag, Drag.Move
  27. *
  28. * @package Cake.View.Helper
  29. */
  30. class MootoolsEngineHelper extends JsBaseEngineHelper {
  31. /**
  32. * Option mappings for MooTools
  33. *
  34. * @var array
  35. */
  36. protected $_optionMap = array(
  37. 'request' => array(
  38. 'complete' => 'onComplete',
  39. 'success' => 'onSuccess',
  40. 'before' => 'onRequest',
  41. 'error' => 'onFailure'
  42. ),
  43. 'sortable' => array(
  44. 'distance' => 'snap',
  45. 'containment' => 'constrain',
  46. 'sort' => 'onSort',
  47. 'complete' => 'onComplete',
  48. 'start' => 'onStart',
  49. ),
  50. 'drag' => array(
  51. 'snapGrid' => 'snap',
  52. 'start' => 'onStart',
  53. 'drag' => 'onDrag',
  54. 'stop' => 'onComplete',
  55. ),
  56. 'drop' => array(
  57. 'drop' => 'onDrop',
  58. 'hover' => 'onEnter',
  59. 'leave' => 'onLeave',
  60. ),
  61. 'slider' => array(
  62. 'complete' => 'onComplete',
  63. 'change' => 'onChange',
  64. 'direction' => 'mode',
  65. 'step' => 'steps'
  66. )
  67. );
  68. /**
  69. * Contains a list of callback names -> default arguments.
  70. *
  71. * @var array
  72. */
  73. protected $_callbackArguments = array(
  74. 'slider' => array(
  75. 'onTick' => 'position',
  76. 'onChange' => 'step',
  77. 'onComplete' => 'event'
  78. ),
  79. 'request' => array(
  80. 'onRequest' => '',
  81. 'onComplete' => '',
  82. 'onCancel' => '',
  83. 'onSuccess' => 'responseText, responseXML',
  84. 'onFailure' => 'xhr',
  85. 'onException' => 'headerName, value',
  86. ),
  87. 'drag' => array(
  88. 'onBeforeStart' => 'element',
  89. 'onStart' => 'element',
  90. 'onSnap' => 'element',
  91. 'onDrag' => 'element, event',
  92. 'onComplete' => 'element, event',
  93. 'onCancel' => 'element',
  94. ),
  95. 'drop' => array(
  96. 'onBeforeStart' => 'element',
  97. 'onStart' => 'element',
  98. 'onSnap' => 'element',
  99. 'onDrag' => 'element, event',
  100. 'onComplete' => 'element, event',
  101. 'onCancel' => 'element',
  102. 'onDrop' => 'element, droppable, event',
  103. 'onLeave' => 'element, droppable',
  104. 'onEnter' => 'element, droppable',
  105. ),
  106. 'sortable' => array(
  107. 'onStart' => 'element, clone',
  108. 'onSort' => 'element, clone',
  109. 'onComplete' => 'element',
  110. )
  111. );
  112. /**
  113. * Create javascript selector for a CSS rule
  114. *
  115. * @param string $selector The selector that is targeted
  116. * @return MootoolsEngineHelper instance of $this. Allows chained methods.
  117. */
  118. public function get($selector) {
  119. $this->_multipleSelection = false;
  120. if ($selector === 'window' || $selector === 'document') {
  121. $this->selection = "$(" . $selector . ")";
  122. return $this;
  123. }
  124. if (preg_match('/^#[^\s.]+$/', $selector)) {
  125. $this->selection = '$("' . substr($selector, 1) . '")';
  126. return $this;
  127. }
  128. $this->_multipleSelection = true;
  129. $this->selection = '$$("' . $selector . '")';
  130. return $this;
  131. }
  132. /**
  133. * Add an event to the script cache. Operates on the currently selected elements.
  134. *
  135. * ### Options
  136. *
  137. * - 'wrap' - Whether you want the callback wrapped in an anonymous function. (defaults true)
  138. * - 'stop' - Whether you want the event to stopped. (defaults true)
  139. *
  140. * @param string $type Type of event to bind to the current dom id
  141. * @param string $callback The Javascript function you wish to trigger or the function literal
  142. * @param array $options Options for the event.
  143. * @return string completed event handler
  144. */
  145. public function event($type, $callback, $options = array()) {
  146. $defaults = array('wrap' => true, 'stop' => true);
  147. $options = array_merge($defaults, $options);
  148. $function = 'function (event) {%s}';
  149. if ($options['wrap'] && $options['stop']) {
  150. $callback = "event.stop();\n" . $callback;
  151. }
  152. if ($options['wrap']) {
  153. $callback = sprintf($function, $callback);
  154. }
  155. $out = $this->selection . ".addEvent(\"{$type}\", $callback);";
  156. return $out;
  157. }
  158. /**
  159. * Create a domReady event. This is a special event in many libraries
  160. *
  161. * @param string $functionBody The code to run on domReady
  162. * @return string completed domReady method
  163. */
  164. public function domReady($functionBody) {
  165. $this->selection = 'window';
  166. return $this->event('domready', $functionBody, array('stop' => false));
  167. }
  168. /**
  169. * Create an iteration over the current selection result.
  170. *
  171. * @param string $callback The function body you wish to apply during the iteration.
  172. * @return string completed iteration
  173. */
  174. public function each($callback) {
  175. return $this->selection . '.each(function (item, index) {' . $callback . '});';
  176. }
  177. /**
  178. * Trigger an Effect.
  179. *
  180. * @param string $name The name of the effect to trigger.
  181. * @param array $options Array of options for the effect.
  182. * @return string completed string with effect.
  183. * @see JsBaseEngineHelper::effect()
  184. */
  185. public function effect($name, $options = array()) {
  186. $speed = null;
  187. if (isset($options['speed']) && in_array($options['speed'], array('fast', 'slow'))) {
  188. if ($options['speed'] === 'fast') {
  189. $speed = '"short"';
  190. } elseif ($options['speed'] === 'slow') {
  191. $speed = '"long"';
  192. }
  193. }
  194. $effect = '';
  195. switch ($name) {
  196. case 'hide':
  197. $effect = 'setStyle("display", "none")';
  198. break;
  199. case 'show':
  200. $effect = 'setStyle("display", "")';
  201. break;
  202. case 'fadeIn':
  203. case 'fadeOut':
  204. case 'slideIn':
  205. case 'slideOut':
  206. list($effectName, $direction) = preg_split('/([A-Z][a-z]+)/', $name, -1, PREG_SPLIT_DELIM_CAPTURE);
  207. $direction = strtolower($direction);
  208. if ($speed) {
  209. $effect .= "set(\"$effectName\", {duration:$speed}).";
  210. }
  211. $effect .= "$effectName(\"$direction\")";
  212. break;
  213. }
  214. return $this->selection . '.' . $effect . ';';
  215. }
  216. /**
  217. * Create an new Request.
  218. *
  219. * Requires `Request`. If you wish to use 'update' key you must have ```Request.HTML```
  220. * if you wish to do Json requests you will need ```JSON``` and ```Request.JSON```.
  221. *
  222. * @param string|array $url
  223. * @param array $options
  224. * @return string The completed ajax call.
  225. */
  226. public function request($url, $options = array()) {
  227. $url = html_entity_decode($this->url($url), ENT_COMPAT, Configure::read('App.encoding'));
  228. $options = $this->_mapOptions('request', $options);
  229. $type = $data = null;
  230. if (isset($options['type']) || isset($options['update'])) {
  231. if (isset($options['type']) && strtolower($options['type']) === 'json') {
  232. $type = '.JSON';
  233. }
  234. if (isset($options['update'])) {
  235. $options['update'] = str_replace('#', '', $options['update']);
  236. $type = '.HTML';
  237. }
  238. unset($options['type']);
  239. }
  240. if (!empty($options['data'])) {
  241. $data = $options['data'];
  242. unset($options['data']);
  243. }
  244. $options['url'] = $url;
  245. $options = $this->_prepareCallbacks('request', $options);
  246. if (!empty($options['dataExpression'])) {
  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. public 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. public 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 addition 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. public function drop($options = array()) {
  295. if (empty($options['drag'])) {
  296. trigger_error(
  297. __d('cake_dev', '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. public 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. public 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. }