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

9 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
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 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
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
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 );