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.

975 lines
32 KiB

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