You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1000 lines
33 KiB

10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
  1. /*!
  2. * # Semantic UI 2.0.0 - API
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2015 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ( $, window, document, undefined ) {
  12. "use strict";
  13. $.api = $.fn.api = function(parameters) {
  14. var
  15. // use window context if none specified
  16. $allModules = $.isFunction(this)
  17. ? $(window)
  18. : $(this),
  19. moduleSelector = $allModules.selector || '',
  20. time = new Date().getTime(),
  21. performance = [],
  22. query = arguments[0],
  23. methodInvoked = (typeof query == 'string'),
  24. queryArguments = [].slice.call(arguments, 1),
  25. returnedValue
  26. ;
  27. $allModules
  28. .each(function() {
  29. var
  30. settings = ( $.isPlainObject(parameters) )
  31. ? $.extend(true, {}, $.fn.api.settings, parameters)
  32. : $.extend({}, $.fn.api.settings),
  33. // internal aliases
  34. namespace = settings.namespace,
  35. metadata = settings.metadata,
  36. selector = settings.selector,
  37. error = settings.error,
  38. className = settings.className,
  39. // define namespaces for modules
  40. eventNamespace = '.' + namespace,
  41. moduleNamespace = 'module-' + namespace,
  42. // element that creates request
  43. $module = $(this),
  44. $form = $module.closest(selector.form),
  45. // context used for state
  46. $context = (settings.stateContext)
  47. ? $(settings.stateContext)
  48. : $module,
  49. // request details
  50. ajaxSettings,
  51. requestSettings,
  52. url,
  53. data,
  54. requestStartTime,
  55. // standard module
  56. element = this,
  57. context = $context[0],
  58. instance = $module.data(moduleNamespace),
  59. module
  60. ;
  61. module = {
  62. initialize: function() {
  63. if(!methodInvoked) {
  64. module.create.cache();
  65. module.bind.events();
  66. }
  67. module.instantiate();
  68. },
  69. instantiate: function() {
  70. module.verbose('Storing instance of module', module);
  71. instance = module;
  72. $module
  73. .data(moduleNamespace, instance)
  74. ;
  75. },
  76. destroy: function() {
  77. module.verbose('Destroying previous module for', element);
  78. $module
  79. .removeData(moduleNamespace)
  80. .off(eventNamespace)
  81. ;
  82. },
  83. bind: {
  84. events: function() {
  85. var
  86. triggerEvent = module.get.event()
  87. ;
  88. if( triggerEvent ) {
  89. module.debug('Attaching API events to element', triggerEvent);
  90. $module
  91. .on(triggerEvent + eventNamespace, module.event.trigger)
  92. ;
  93. }
  94. else if(settings.on == 'now') {
  95. module.debug('Querying API now', triggerEvent);
  96. module.query();
  97. }
  98. }
  99. },
  100. read: {
  101. cachedResponse: function(url) {
  102. var
  103. response
  104. ;
  105. if(!module.cache) {
  106. module.create.cache();
  107. }
  108. response = (module.cache.response[url] !== undefined)
  109. ? module.cache.response[url]
  110. : false
  111. ;
  112. module.debug('Using cached response', url, response);
  113. return response;
  114. }
  115. },
  116. write: {
  117. cachedResponse: function(url, response) {
  118. if(!module.cache) {
  119. module.create.cache();
  120. }
  121. if(response && response === '') {
  122. module.debug('Response empty, not caching', response);
  123. return;
  124. }
  125. module.verbose('Storing cached response for url', url, response);
  126. module.cache.response[url] = response;
  127. }
  128. },
  129. query: function() {
  130. if(module.is.disabled()) {
  131. module.debug('Element is disabled API request aborted');
  132. return;
  133. }
  134. if(module.is.loading()) {
  135. if(settings.interruptRequests) {
  136. module.debug('Interrupting previous request');
  137. module.abort();
  138. }
  139. else {
  140. module.debug('Cancelling request, previous request is still pending');
  141. return;
  142. }
  143. }
  144. // pass element metadata to url (value, text)
  145. if(settings.defaultData) {
  146. $.extend(true, settings.urlData, module.get.defaultData());
  147. }
  148. // Add form content
  149. if(settings.serializeForm !== false || $context.is('form')) {
  150. if(settings.serializeForm == 'json') {
  151. $.extend(true, settings.data, module.get.formData());
  152. }
  153. else {
  154. settings.data = module.get.formData();
  155. }
  156. }
  157. // call beforesend and get any settings changes
  158. requestSettings = module.get.settings();
  159. // check if before send cancelled request
  160. if(requestSettings === false) {
  161. module.cancelled = true;
  162. module.error(error.beforeSend);
  163. return;
  164. }
  165. else {
  166. module.cancelled = false;
  167. }
  168. if(settings.url) {
  169. // override with url if specified
  170. module.debug('Using specified url', url);
  171. url = module.add.urlData( settings.url );
  172. }
  173. else {
  174. // otherwise find url from api endpoints
  175. url = module.add.urlData( module.get.templateURL() );
  176. module.debug('Added URL Data to url', url);
  177. }
  178. // exit conditions reached, missing url parameters
  179. if( !url && !module.is.mocked()) {
  180. if( module.is.form() ) {
  181. url = $module.attr('action') || '';
  182. module.debug('No url or action specified, defaulting to form action', url);
  183. }
  184. else {
  185. module.error(error.missingURL, settings.action);
  186. return;
  187. }
  188. }
  189. // look for jQuery ajax parameters in settings
  190. ajaxSettings = $.extend(true, {}, settings, {
  191. type : settings.method || settings.type,
  192. data : data,
  193. url : settings.base + url,
  194. beforeSend : settings.beforeXHR,
  195. success : function() {},
  196. failure : function() {},
  197. complete : function() {}
  198. });
  199. module.debug('Querying URL', ajaxSettings.url);
  200. module.verbose('Using AJAX settings', ajaxSettings);
  201. if(settings.cache === 'local' && module.read.cachedResponse(url)) {
  202. module.debug('Response returned from local cache');
  203. module.request = module.create.request();
  204. module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
  205. return;
  206. }
  207. if( !settings.throttle ) {
  208. module.debug('Sending data', data, ajaxSettings.method);
  209. module.send.request();
  210. }
  211. else {
  212. if(!settings.throttleFirstRequest && !module.timer) {
  213. module.debug('Sending data', data, ajaxSettings.method);
  214. module.send.request();
  215. module.timer = setTimeout(function(){}, settings.throttle);
  216. }
  217. else {
  218. module.debug('Throttling request', settings.throttle);
  219. clearTimeout(module.timer);
  220. module.timer = setTimeout(function() {
  221. if(module.timer) {
  222. delete module.timer;
  223. }
  224. module.debug('Sending throttled request', data, ajaxSettings.method);
  225. module.send.request();
  226. }, settings.throttle);
  227. }
  228. }
  229. },
  230. is: {
  231. disabled: function() {
  232. return ($module.filter(settings.filter).length > 0);
  233. },
  234. form: function() {
  235. return $module.is('form');
  236. },
  237. mocked: function() {
  238. return (settings.mockResponse || settings.mockResponseAsync);
  239. },
  240. input: function() {
  241. return $module.is('input');
  242. },
  243. loading: function() {
  244. return (module.request && module.request.state() == 'pending');
  245. }
  246. },
  247. was: {
  248. cancelled: function() {
  249. return (module.cancelled || false);
  250. },
  251. succesful: function() {
  252. return (module.request && module.request.state() == 'resolved');
  253. },
  254. failure: function() {
  255. return (module.request && module.request.state() == 'rejected');
  256. },
  257. complete: function() {
  258. return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
  259. }
  260. },
  261. add: {
  262. urlData: function(url, urlData) {
  263. var
  264. requiredVariables,
  265. optionalVariables
  266. ;
  267. if(url) {
  268. requiredVariables = url.match(settings.regExp.required);
  269. optionalVariables = url.match(settings.regExp.optional);
  270. urlData = urlData || settings.urlData;
  271. if(requiredVariables) {
  272. module.debug('Looking for required URL variables', requiredVariables);
  273. $.each(requiredVariables, function(index, templatedString) {
  274. var
  275. // allow legacy {$var} style
  276. variable = (templatedString.indexOf('$') !== -1)
  277. ? templatedString.substr(2, templatedString.length - 3)
  278. : templatedString.substr(1, templatedString.length - 2),
  279. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  280. ? urlData[variable]
  281. : ($module.data(variable) !== undefined)
  282. ? $module.data(variable)
  283. : ($context.data(variable) !== undefined)
  284. ? $context.data(variable)
  285. : urlData[variable]
  286. ;
  287. // remove value
  288. if(value === undefined) {
  289. module.error(error.requiredParameter, variable, url);
  290. url = false;
  291. return false;
  292. }
  293. else {
  294. module.verbose('Found required variable', variable, value);
  295. url = url.replace(templatedString, value);
  296. }
  297. });
  298. }
  299. if(optionalVariables) {
  300. module.debug('Looking for optional URL variables', requiredVariables);
  301. $.each(optionalVariables, function(index, templatedString) {
  302. var
  303. // allow legacy {/$var} style
  304. variable = (templatedString.indexOf('$') !== -1)
  305. ? templatedString.substr(3, templatedString.length - 4)
  306. : templatedString.substr(2, templatedString.length - 3),
  307. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  308. ? urlData[variable]
  309. : ($module.data(variable) !== undefined)
  310. ? $module.data(variable)
  311. : ($context.data(variable) !== undefined)
  312. ? $context.data(variable)
  313. : urlData[variable]
  314. ;
  315. // optional replacement
  316. if(value !== undefined) {
  317. module.verbose('Optional variable Found', variable, value);
  318. url = url.replace(templatedString, value);
  319. }
  320. else {
  321. module.verbose('Optional variable not found', variable);
  322. // remove preceding slash if set
  323. if(url.indexOf('/' + templatedString) !== -1) {
  324. url = url.replace('/' + templatedString, '');
  325. }
  326. else {
  327. url = url.replace(templatedString, '');
  328. }
  329. }
  330. });
  331. }
  332. }
  333. return url;
  334. }
  335. },
  336. send: {
  337. request: function() {
  338. module.set.loading();
  339. module.request = module.create.request();
  340. module.xhr = module.create.xhr();
  341. settings.onRequest.call(context, module.request, module.xhr);
  342. }
  343. },
  344. event: {
  345. trigger: function(event) {
  346. module.query();
  347. if(event.type == 'submit' || event.type == 'click') {
  348. event.preventDefault();
  349. }
  350. },
  351. xhr: {
  352. always: function() {
  353. // calculate if loading time was below minimum threshold
  354. },
  355. done: function(response) {
  356. var
  357. context = this,
  358. elapsedTime = (new Date().getTime() - requestStartTime),
  359. timeLeft = (settings.loadingDuration - elapsedTime)
  360. ;
  361. timeLeft = (timeLeft > 0)
  362. ? timeLeft
  363. : 0
  364. ;
  365. setTimeout(function() {
  366. module.request.resolveWith(context, [response]);
  367. }, timeLeft);
  368. },
  369. fail: function(xhr, status, httpMessage) {
  370. var
  371. context = this,
  372. elapsedTime = (new Date().getTime() - requestStartTime),
  373. timeLeft = (settings.loadingDuration - elapsedTime)
  374. ;
  375. timeLeft = (timeLeft > 0)
  376. ? timeLeft
  377. : 0
  378. ;
  379. // page triggers abort on navigation, dont show error
  380. setTimeout(function() {
  381. if(xhr.readyState !== undefined && xhr.readyState === 0) {
  382. module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
  383. }
  384. else {
  385. module.request.rejectWith(context, [xhr, status, httpMessage]);
  386. }
  387. }, timeLeft);
  388. }
  389. },
  390. request: {
  391. complete: function(response) {
  392. module.remove.loading();
  393. settings.onComplete.call(context, response, $module);
  394. },
  395. done: function(response) {
  396. var
  397. translatedResponse = ( $.isFunction(settings.onResponse) )
  398. ? settings.onResponse.call(context, $.extend(true, {}, response))
  399. : false
  400. ;
  401. module.debug('API Response Received', response);
  402. if(settings.cache === 'local' && url) {
  403. module.write.cachedResponse(url, response);
  404. module.debug('Adding url to local cache', module.cache);
  405. }
  406. if(translatedResponse) {
  407. module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
  408. response = translatedResponse;
  409. }
  410. if(settings.dataType == 'json') {
  411. if( $.isFunction(settings.successTest) ) {
  412. module.debug('Checking JSON returned success', settings.successTest, response);
  413. if( settings.successTest(response) ) {
  414. settings.onSuccess.call(context, response, $module);
  415. }
  416. else {
  417. module.debug('JSON test specified by user and response failed', response);
  418. settings.onFailure.call(context, response, $module);
  419. }
  420. }
  421. else {
  422. settings.onSuccess.call(context, response, $module);
  423. }
  424. }
  425. else {
  426. settings.onSuccess.call(context, response, $module);
  427. }
  428. },
  429. fail: function(xhr, status, httpMessage) {
  430. var
  431. errorMessage = (settings.error[status] !== undefined)
  432. ? settings.error[status]
  433. : httpMessage,
  434. response
  435. ;
  436. // request aborted, don't show error state
  437. if(status == 'aborted') {
  438. module.debug('Request Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
  439. module.reset();
  440. settings.onAbort.call(context, status, $module);
  441. return;
  442. }
  443. if(xhr !== undefined) {
  444. // if http status code returned and json returned error, look for it
  445. if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
  446. module.error(error.statusMessage + httpMessage, ajaxSettings.url);
  447. }
  448. else {
  449. if(status == 'error' && settings.dataType == 'json') {
  450. try {
  451. response = $.parseJSON(xhr.responseText);
  452. if(response && response.error !== undefined) {
  453. errorMessage = response.error;
  454. }
  455. }
  456. catch(e) {
  457. module.error(error.JSONParse);
  458. }
  459. }
  460. }
  461. module.remove.loading();
  462. // show error state if specified with length
  463. if(settings.errorDuration !== false) {
  464. module.set.error();
  465. setTimeout(module.remove.error, settings.errorDuration);
  466. }
  467. module.debug('API Request error:', errorMessage);
  468. settings.onError.call(context, errorMessage, $module);
  469. }
  470. }
  471. }
  472. },
  473. create: {
  474. cache: function() {
  475. module.verbose('Creating local response cache');
  476. module.cache = {
  477. response: {}
  478. };
  479. },
  480. // api promise
  481. request: function() {
  482. return $.Deferred()
  483. .always(module.event.request.complete)
  484. .done(module.event.request.done)
  485. .fail(module.event.request.fail)
  486. ;
  487. },
  488. // xhr promise
  489. xhr: function() {
  490. var
  491. callback
  492. ;
  493. if( module.is.mocked() ) {
  494. if(settings.mockResponse) {
  495. if($.isFunction(settings.mockResponse)) {
  496. module.debug('Using sync mocked response callback', settings.mockResponse);
  497. module.request.resolveWith(context, [ settings.mockResponse.call(context, settings) ]);
  498. }
  499. else {
  500. module.debug('Using mocked response', settings.mockResponse);
  501. module.request.resolveWith(context, [ settings.mockResponse ]);
  502. }
  503. }
  504. else if( $.isFunction(settings.mockResponseAsync) ) {
  505. callback = function(response) {
  506. module.verbose('Async callback returned response', response);
  507. module.request.resolveWith(context, [response]);
  508. };
  509. module.debug('Using async mocked response', settings.mockResponseAsync);
  510. settings.mockResponseAsync.call(context, settings, callback);
  511. }
  512. }
  513. else {
  514. return $.ajax(ajaxSettings)
  515. .always(module.event.xhr.always)
  516. .done(module.event.xhr.done)
  517. .fail(module.event.xhr.fail)
  518. ;
  519. }
  520. }
  521. },
  522. set: {
  523. error: function() {
  524. module.verbose('Adding error state to element', $context);
  525. $context.addClass(className.error);
  526. },
  527. loading: function() {
  528. module.verbose('Adding loading state to element', $context);
  529. $context.addClass(className.loading);
  530. requestStartTime = new Date().getTime();
  531. }
  532. },
  533. remove: {
  534. error: function() {
  535. module.verbose('Removing error state from element', $context);
  536. $context.removeClass(className.error);
  537. },
  538. loading: function() {
  539. module.verbose('Removing loading state from element', $context);
  540. $context.removeClass(className.loading);
  541. }
  542. },
  543. get: {
  544. request: function() {
  545. return module.request || false;
  546. },
  547. xhr: function() {
  548. return module.xhr || false;
  549. },
  550. settings: function() {
  551. var
  552. runSettings
  553. ;
  554. runSettings = settings.beforeSend.call(context, settings);
  555. if(runSettings) {
  556. if(runSettings.success !== undefined) {
  557. module.debug('Legacy success callback detected', runSettings);
  558. module.error(error.legacyParameters, runSettings.success);
  559. runSettings.onSuccess = runSettings.success;
  560. }
  561. if(runSettings.failure !== undefined) {
  562. module.debug('Legacy failure callback detected', runSettings);
  563. module.error(error.legacyParameters, runSettings.failure);
  564. runSettings.onFailure = runSettings.failure;
  565. }
  566. if(runSettings.complete !== undefined) {
  567. module.debug('Legacy complete callback detected', runSettings);
  568. module.error(error.legacyParameters, runSettings.complete);
  569. runSettings.onComplete = runSettings.complete;
  570. }
  571. }
  572. if(runSettings === undefined) {
  573. module.error(error.noReturnedValue);
  574. }
  575. return (runSettings !== undefined)
  576. ? runSettings
  577. : settings
  578. ;
  579. },
  580. defaultData: function() {
  581. var
  582. data = {}
  583. ;
  584. if( !$.isWindow(element) ) {
  585. if( module.is.input() ) {
  586. data.value = $module.val();
  587. }
  588. else if( !module.is.form() ) {
  589. }
  590. else {
  591. data.text = $module.text();
  592. }
  593. }
  594. return data;
  595. },
  596. event: function() {
  597. if( $.isWindow(element) || settings.on == 'now' ) {
  598. module.debug('API called without element, no events attached');
  599. return false;
  600. }
  601. else if(settings.on == 'auto') {
  602. if( $module.is('input') ) {
  603. return (element.oninput !== undefined)
  604. ? 'input'
  605. : (element.onpropertychange !== undefined)
  606. ? 'propertychange'
  607. : 'keyup'
  608. ;
  609. }
  610. else if( $module.is('form') ) {
  611. return 'submit';
  612. }
  613. else {
  614. return 'click';
  615. }
  616. }
  617. else {
  618. return settings.on;
  619. }
  620. },
  621. formData: function() {
  622. var
  623. formData
  624. ;
  625. if($module.serializeObject !== undefined) {
  626. formData = $form.serializeObject();
  627. }
  628. else {
  629. module.error(error.missingSerialize);
  630. formData = $form.serialize();
  631. }
  632. module.debug('Retrieved form data', formData);
  633. return formData;
  634. },
  635. templateURL: function(action) {
  636. var
  637. url
  638. ;
  639. action = action || $module.data(metadata.action) || settings.action || false;
  640. if(action) {
  641. module.debug('Looking up url for action', action, settings.api);
  642. if(settings.api[action] !== undefined) {
  643. url = settings.api[action];
  644. module.debug('Found template url', url);
  645. }
  646. else if( !module.is.form() && !module.is.mocked() ) {
  647. module.error(error.missingAction, settings.action, settings.api);
  648. }
  649. }
  650. return url;
  651. }
  652. },
  653. abort: function() {
  654. var
  655. xhr = module.get.xhr()
  656. ;
  657. if( xhr && xhr.state() !== 'resolved') {
  658. module.debug('Cancelling API request');
  659. xhr.abort();
  660. }
  661. },
  662. // reset state
  663. reset: function() {
  664. module.remove.error();
  665. module.remove.loading();
  666. },
  667. setting: function(name, value) {
  668. module.debug('Changing setting', name, value);
  669. if( $.isPlainObject(name) ) {
  670. $.extend(true, settings, name);
  671. }
  672. else if(value !== undefined) {
  673. settings[name] = value;
  674. }
  675. else {
  676. return settings[name];
  677. }
  678. },
  679. internal: function(name, value) {
  680. if( $.isPlainObject(name) ) {
  681. $.extend(true, module, name);
  682. }
  683. else if(value !== undefined) {
  684. module[name] = value;
  685. }
  686. else {
  687. return module[name];
  688. }
  689. },
  690. debug: function() {
  691. if(settings.debug) {
  692. if(settings.performance) {
  693. module.performance.log(arguments);
  694. }
  695. else {
  696. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  697. module.debug.apply(console, arguments);
  698. }
  699. }
  700. },
  701. verbose: function() {
  702. if(settings.verbose && settings.debug) {
  703. if(settings.performance) {
  704. module.performance.log(arguments);
  705. }
  706. else {
  707. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  708. module.verbose.apply(console, arguments);
  709. }
  710. }
  711. },
  712. error: function() {
  713. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  714. module.error.apply(console, arguments);
  715. },
  716. performance: {
  717. log: function(message) {
  718. var
  719. currentTime,
  720. executionTime,
  721. previousTime
  722. ;
  723. if(settings.performance) {
  724. currentTime = new Date().getTime();
  725. previousTime = time || currentTime;
  726. executionTime = currentTime - previousTime;
  727. time = currentTime;
  728. performance.push({
  729. 'Name' : message[0],
  730. 'Arguments' : [].slice.call(message, 1) || '',
  731. //'Element' : element,
  732. 'Execution Time' : executionTime
  733. });
  734. }
  735. clearTimeout(module.performance.timer);
  736. module.performance.timer = setTimeout(module.performance.display, 500);
  737. },
  738. display: function() {
  739. var
  740. title = settings.name + ':',
  741. totalTime = 0
  742. ;
  743. time = false;
  744. clearTimeout(module.performance.timer);
  745. $.each(performance, function(index, data) {
  746. totalTime += data['Execution Time'];
  747. });
  748. title += ' ' + totalTime + 'ms';
  749. if(moduleSelector) {
  750. title += ' \'' + moduleSelector + '\'';
  751. }
  752. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  753. console.groupCollapsed(title);
  754. if(console.table) {
  755. console.table(performance);
  756. }
  757. else {
  758. $.each(performance, function(index, data) {
  759. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  760. });
  761. }
  762. console.groupEnd();
  763. }
  764. performance = [];
  765. }
  766. },
  767. invoke: function(query, passedArguments, context) {
  768. var
  769. object = instance,
  770. maxDepth,
  771. found,
  772. response
  773. ;
  774. passedArguments = passedArguments || queryArguments;
  775. context = element || context;
  776. if(typeof query == 'string' && object !== undefined) {
  777. query = query.split(/[\. ]/);
  778. maxDepth = query.length - 1;
  779. $.each(query, function(depth, value) {
  780. var camelCaseValue = (depth != maxDepth)
  781. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  782. : query
  783. ;
  784. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  785. object = object[camelCaseValue];
  786. }
  787. else if( object[camelCaseValue] !== undefined ) {
  788. found = object[camelCaseValue];
  789. return false;
  790. }
  791. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  792. object = object[value];
  793. }
  794. else if( object[value] !== undefined ) {
  795. found = object[value];
  796. return false;
  797. }
  798. else {
  799. module.error(error.method, query);
  800. return false;
  801. }
  802. });
  803. }
  804. if ( $.isFunction( found ) ) {
  805. response = found.apply(context, passedArguments);
  806. }
  807. else if(found !== undefined) {
  808. response = found;
  809. }
  810. if($.isArray(returnedValue)) {
  811. returnedValue.push(response);
  812. }
  813. else if(returnedValue !== undefined) {
  814. returnedValue = [returnedValue, response];
  815. }
  816. else if(response !== undefined) {
  817. returnedValue = response;
  818. }
  819. return found;
  820. }
  821. };
  822. if(methodInvoked) {
  823. if(instance === undefined) {
  824. module.initialize();
  825. }
  826. module.invoke(query);
  827. }
  828. else {
  829. if(instance !== undefined) {
  830. instance.invoke('destroy');
  831. }
  832. module.initialize();
  833. }
  834. })
  835. ;
  836. return (returnedValue !== undefined)
  837. ? returnedValue
  838. : this
  839. ;
  840. };
  841. $.api.settings = {
  842. name : 'API',
  843. namespace : 'api',
  844. debug : true,
  845. verbose : false,
  846. performance : true,
  847. // cache
  848. cache : true,
  849. interruptRequests : true,
  850. // event binding
  851. on : 'auto',
  852. filter : '.disabled',
  853. stateContext : false,
  854. // state
  855. loadingDuration : 0,
  856. errorDuration : 2000,
  857. // templating
  858. action : false,
  859. url : false,
  860. base : '',
  861. // data
  862. urlData : {},
  863. // ui
  864. defaultData : true,
  865. serializeForm : false,
  866. throttle : 0,
  867. throttleFirstRequest : true,
  868. // jQ ajax
  869. method : 'get',
  870. data : {},
  871. dataType : 'json',
  872. // mock response
  873. mockResponse : false,
  874. mockResponseAsync : false,
  875. // callbacks before request
  876. beforeSend : function(settings) { return settings; },
  877. beforeXHR : function(xhr) {},
  878. onRequest : function(promise, xhr) {},
  879. // after request
  880. onResponse : false, // function(response) { },
  881. onSuccess : function(response, $module) {},
  882. onComplete : function(response, $module) {},
  883. onFailure : function(errorMessage, $module) {},
  884. onError : function(errorMessage, $module) {},
  885. onAbort : function(errorMessage, $module) {},
  886. successTest : false,
  887. // errors
  888. error : {
  889. beforeSend : 'The before send function has aborted the request',
  890. error : 'There was an error with your request',
  891. exitConditions : 'API Request Aborted. Exit conditions met',
  892. JSONParse : 'JSON could not be parsed during error handling',
  893. legacyParameters : 'You are using legacy API success callback names',
  894. method : 'The method you called is not defined',
  895. missingAction : 'API action used but no url was defined',
  896. missingSerialize : 'Required dependency jquery-serialize-object missing, using basic serialize',
  897. missingURL : 'No URL specified for api event',
  898. noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
  899. parseError : 'There was an error parsing your request',
  900. requiredParameter : 'Missing a required URL parameter: ',
  901. statusMessage : 'Server gave an error: ',
  902. timeout : 'Your request timed out'
  903. },
  904. regExp : {
  905. required : /\{\$*[A-z0-9]+\}/g,
  906. optional : /\{\/\$*[A-z0-9]+\}/g,
  907. },
  908. className: {
  909. loading : 'loading',
  910. error : 'error'
  911. },
  912. selector: {
  913. form: 'form'
  914. },
  915. metadata: {
  916. action : 'action'
  917. }
  918. };
  919. $.api.settings.api = {};
  920. })( jQuery, window , document );