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.

870 lines
28 KiB

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