main.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. require.config({
  2. paths: {
  3. bootstrap: './vendor/bootstrap.min',
  4. diffMatchPatch: './vendor/diff_match_patch.min',
  5. handlebars: './vendor/handlebars.min',
  6. handlebarsExtended: './utils/handlebars_helper',
  7. jquery: './vendor/jquery.min',
  8. locales: './locales/locale',
  9. lodash: './vendor/lodash.custom.min',
  10. pathToRegexp: './vendor/path-to-regexp/index',
  11. prettify: './vendor/prettify/prettify',
  12. semver: './vendor/semver.min',
  13. utilsSampleRequest: './utils/send_sample_request',
  14. webfontloader: './vendor/webfontloader',
  15. list: './vendor/list.min'
  16. },
  17. shim: {
  18. bootstrap: {
  19. deps: ['jquery']
  20. },
  21. diffMatchPatch: {
  22. exports: 'diff_match_patch'
  23. },
  24. handlebars: {
  25. exports: 'Handlebars'
  26. },
  27. handlebarsExtended: {
  28. deps: ['jquery', 'handlebars'],
  29. exports: 'Handlebars'
  30. },
  31. prettify: {
  32. exports: 'prettyPrint'
  33. }
  34. },
  35. urlArgs: 'v=' + (new Date()).getTime(),
  36. waitSeconds: 15
  37. });
  38. require([
  39. 'jquery',
  40. 'lodash',
  41. 'locales',
  42. 'handlebarsExtended',
  43. './api_project.js',
  44. './api_data.js',
  45. 'prettify',
  46. 'utilsSampleRequest',
  47. 'semver',
  48. 'webfontloader',
  49. 'bootstrap',
  50. 'pathToRegexp',
  51. 'list'
  52. ], function($, _, locale, Handlebars, apiProject, apiData, prettyPrint, sampleRequest, semver, WebFont) {
  53. // load google web fonts
  54. loadGoogleFontCss();
  55. var api = apiData.api;
  56. //
  57. // Templates
  58. //
  59. var templateHeader = Handlebars.compile( $('#template-header').html() );
  60. var templateFooter = Handlebars.compile( $('#template-footer').html() );
  61. var templateArticle = Handlebars.compile( $('#template-article').html() );
  62. var templateCompareArticle = Handlebars.compile( $('#template-compare-article').html() );
  63. var templateGenerator = Handlebars.compile( $('#template-generator').html() );
  64. var templateProject = Handlebars.compile( $('#template-project').html() );
  65. var templateSections = Handlebars.compile( $('#template-sections').html() );
  66. var templateSidenav = Handlebars.compile( $('#template-sidenav').html() );
  67. //
  68. // apiProject defaults
  69. //
  70. if ( ! apiProject.template)
  71. apiProject.template = {};
  72. if (apiProject.template.withCompare == null)
  73. apiProject.template.withCompare = true;
  74. if (apiProject.template.withGenerator == null)
  75. apiProject.template.withGenerator = true;
  76. if (apiProject.template.forceLanguage)
  77. locale.setLanguage(apiProject.template.forceLanguage);
  78. // Setup jQuery Ajax
  79. $.ajaxSetup(apiProject.template.jQueryAjaxSetup);
  80. //
  81. // Data transform
  82. //
  83. // grouped by group
  84. var apiByGroup = _.groupBy(api, function(entry) {
  85. return entry.group;
  86. });
  87. // grouped by group and name
  88. var apiByGroupAndName = {};
  89. $.each(apiByGroup, function(index, entries) {
  90. apiByGroupAndName[index] = _.groupBy(entries, function(entry) {
  91. return entry.name;
  92. });
  93. });
  94. //
  95. // sort api within a group by title ASC and custom order
  96. //
  97. var newList = [];
  98. var umlauts = { 'ä': 'ae', 'ü': 'ue', 'ö': 'oe', 'ß': 'ss' }; // TODO: remove in version 1.0
  99. $.each (apiByGroupAndName, function(index, groupEntries) {
  100. // get titles from the first entry of group[].name[] (name has versioning)
  101. var titles = [];
  102. $.each (groupEntries, function(titleName, entries) {
  103. var title = entries[0].title;
  104. if(title !== undefined) {
  105. title.toLowerCase().replace(/[äöüß]/g, function($0) { return umlauts[$0]; });
  106. titles.push(title + '#~#' + titleName); // '#~#' keep reference to titleName after sorting
  107. }
  108. });
  109. // sort by name ASC
  110. titles.sort();
  111. // custom order
  112. if (apiProject.order)
  113. titles = sortByOrder(titles, apiProject.order, '#~#');
  114. // add single elements to the new list
  115. titles.forEach(function(name) {
  116. var values = name.split('#~#');
  117. var key = values[1];
  118. groupEntries[key].forEach(function(entry) {
  119. newList.push(entry);
  120. });
  121. });
  122. });
  123. // api overwrite with ordered list
  124. api = newList;
  125. //
  126. // Group- and Versionlists
  127. //
  128. var apiGroups = {};
  129. var apiGroupTitles = {};
  130. var apiVersions = {};
  131. apiVersions[apiProject.version] = 1;
  132. $.each(api, function(index, entry) {
  133. apiGroups[entry.group] = 1;
  134. apiGroupTitles[entry.group] = entry.groupTitle || entry.group;
  135. apiVersions[entry.version] = 1;
  136. });
  137. // sort groups
  138. apiGroups = Object.keys(apiGroups);
  139. apiGroups.sort();
  140. // custom order
  141. if (apiProject.order)
  142. apiGroups = sortByOrder(apiGroups, apiProject.order);
  143. // sort versions DESC
  144. apiVersions = Object.keys(apiVersions);
  145. apiVersions.sort(semver.compare);
  146. apiVersions.reverse();
  147. //
  148. // create Navigationlist
  149. //
  150. var nav = [];
  151. apiGroups.forEach(function(group) {
  152. // Mainmenu entry
  153. nav.push({
  154. group: group,
  155. isHeader: true,
  156. title: apiGroupTitles[group]
  157. });
  158. // Submenu
  159. var oldName = '';
  160. api.forEach(function(entry) {
  161. if (entry.group === group) {
  162. if (oldName !== entry.name) {
  163. nav.push({
  164. title: entry.title,
  165. group: group,
  166. name: entry.name,
  167. type: entry.type,
  168. version: entry.version
  169. });
  170. } else {
  171. nav.push({
  172. title: entry.title,
  173. group: group,
  174. hidden: true,
  175. name: entry.name,
  176. type: entry.type,
  177. version: entry.version
  178. });
  179. }
  180. oldName = entry.name;
  181. }
  182. });
  183. });
  184. /**
  185. * Add navigation items by analyzing the HTML content and searching for h1 and h2 tags
  186. * @param nav Object the navigation array
  187. * @param content string the compiled HTML content
  188. * @param index where to insert items
  189. * @return boolean true if any good-looking (i.e. with a group identifier) <h1> tag was found
  190. */
  191. function add_nav(nav, content, index) {
  192. var found_level1 = false;
  193. if ( ! content) {
  194. return found_level1;
  195. }
  196. var topics = content.match(/<h(1|2).*?>(.+?)<\/h(1|2)>/gi);
  197. if ( topics ) {
  198. topics.forEach(function(entry) {
  199. var level = entry.substring(2,3);
  200. var title = entry.replace(/<.+?>/g, ''); // Remove all HTML tags for the title
  201. var entry_tags = entry.match(/id="api-([^\-]+)(?:-(.+))?"/); // Find the group and name in the id property
  202. var group = (entry_tags ? entry_tags[1] : null);
  203. var name = (entry_tags ? entry_tags[2] : null);
  204. if (level==1 && title && group) {
  205. nav.splice(index, 0, {
  206. group: group,
  207. isHeader: true,
  208. title: title,
  209. isFixed: true
  210. });
  211. index++;
  212. found_level1 = true;
  213. }
  214. if (level==2 && title && group && name) {
  215. nav.splice(index, 0, {
  216. group: group,
  217. name: name,
  218. isHeader: false,
  219. title: title,
  220. isFixed: false,
  221. version: '1.0'
  222. });
  223. index++;
  224. }
  225. });
  226. }
  227. return found_level1;
  228. }
  229. // Mainmenu Header entry
  230. if (apiProject.header) {
  231. var found_level1 = add_nav(nav, apiProject.header.content, 0); // Add level 1 and 2 titles
  232. if (!found_level1) { // If no Level 1 tags were found, make a title
  233. nav.unshift({
  234. group: '_',
  235. isHeader: true,
  236. title: (apiProject.header.title == null) ? locale.__('General') : apiProject.header.title,
  237. isFixed: true
  238. });
  239. }
  240. }
  241. // Mainmenu Footer entry
  242. if (apiProject.footer) {
  243. var last_nav_index = nav.length;
  244. var found_level1 = add_nav(nav, apiProject.footer.content, nav.length); // Add level 1 and 2 titles
  245. if (!found_level1 && apiProject.footer.title != null) { // If no Level 1 tags were found, make a title
  246. nav.splice(last_nav_index, 0, {
  247. group: '_footer',
  248. isHeader: true,
  249. title: apiProject.footer.title,
  250. isFixed: true
  251. });
  252. }
  253. }
  254. // render pagetitle
  255. var title = apiProject.title ? apiProject.title : 'apiDoc: ' + apiProject.name + ' - ' + apiProject.version;
  256. $(document).attr('title', title);
  257. // remove loader
  258. $('#loader').remove();
  259. // render sidenav
  260. var fields = {
  261. nav: nav
  262. };
  263. $('#sidenav').append( templateSidenav(fields) );
  264. // render Generator
  265. $('#generator').append( templateGenerator(apiProject) );
  266. // render Project
  267. _.extend(apiProject, { versions: apiVersions});
  268. $('#project').append( templateProject(apiProject) );
  269. // render apiDoc, header/footer documentation
  270. if (apiProject.header)
  271. $('#header').append( templateHeader(apiProject.header) );
  272. if (apiProject.footer)
  273. $('#footer').append( templateFooter(apiProject.footer) );
  274. //
  275. // Render Sections and Articles
  276. //
  277. var articleVersions = {};
  278. var content = '';
  279. apiGroups.forEach(function(groupEntry) {
  280. var articles = [];
  281. var oldName = '';
  282. var fields = {};
  283. var title = groupEntry;
  284. var description = '';
  285. articleVersions[groupEntry] = {};
  286. // render all articles of a group
  287. api.forEach(function(entry) {
  288. if(groupEntry === entry.group) {
  289. if (oldName !== entry.name) {
  290. // determine versions
  291. api.forEach(function(versionEntry) {
  292. if (groupEntry === versionEntry.group && entry.name === versionEntry.name) {
  293. if ( ! articleVersions[entry.group].hasOwnProperty(entry.name) ) {
  294. articleVersions[entry.group][entry.name] = [];
  295. }
  296. articleVersions[entry.group][entry.name].push(versionEntry.version);
  297. }
  298. });
  299. fields = {
  300. article: entry,
  301. versions: articleVersions[entry.group][entry.name]
  302. };
  303. } else {
  304. fields = {
  305. article: entry,
  306. hidden: true,
  307. versions: articleVersions[entry.group][entry.name]
  308. };
  309. }
  310. // add prefix URL for endpoint
  311. if (apiProject.url)
  312. fields.article.url = apiProject.url + fields.article.url;
  313. addArticleSettings(fields, entry);
  314. if (entry.groupTitle)
  315. title = entry.groupTitle;
  316. // TODO: make groupDescription compareable with older versions (not important for the moment)
  317. if (entry.groupDescription)
  318. description = entry.groupDescription;
  319. articles.push({
  320. article: templateArticle(fields),
  321. group: entry.group,
  322. name: entry.name
  323. });
  324. oldName = entry.name;
  325. }
  326. });
  327. // render Section with Articles
  328. var fields = {
  329. group: groupEntry,
  330. title: title,
  331. description: description,
  332. articles: articles
  333. };
  334. content += templateSections(fields);
  335. });
  336. $('#sections').append( content );
  337. // Bootstrap Scrollspy
  338. $(this).scrollspy({ target: '#scrollingNav', offset: 18 });
  339. // Content-Scroll on Navigation click.
  340. $('.sidenav').find('a').on('click', function(e) {
  341. e.preventDefault();
  342. var id = $(this).attr('href');
  343. if ($(id).length > 0)
  344. $('html,body').animate({ scrollTop: parseInt($(id).offset().top) }, 400);
  345. window.location.hash = $(this).attr('href');
  346. });
  347. // Quickjump on Pageload to hash position.
  348. if(window.location.hash) {
  349. var id = window.location.hash;
  350. if ($(id).length > 0)
  351. $('html,body').animate({ scrollTop: parseInt($(id).offset().top) }, 0);
  352. }
  353. /**
  354. * Check if Parameter (sub) List has a type Field.
  355. * Example: @apiSuccess varname1 No type.
  356. * @apiSuccess {String} varname2 With type.
  357. *
  358. * @param {Object} fields
  359. */
  360. function _hasTypeInFields(fields) {
  361. var result = false;
  362. $.each(fields, function(name) {
  363. result = result || _.some(fields[name], function(item) { return item.type; });
  364. });
  365. return result;
  366. }
  367. /**
  368. * On Template changes, recall plugins.
  369. */
  370. function initDynamic() {
  371. // Bootstrap popover
  372. $('button[data-toggle="popover"]').popover().click(function(e) {
  373. e.preventDefault();
  374. });
  375. var version = $('#version strong').html();
  376. $('#sidenav li').removeClass('is-new');
  377. if (apiProject.template.withCompare) {
  378. $('#sidenav li[data-version=\'' + version + '\']').each(function(){
  379. var group = $(this).data('group');
  380. var name = $(this).data('name');
  381. var length = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').length;
  382. var index = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').index($(this));
  383. if (length === 1 || index === (length - 1))
  384. $(this).addClass('is-new');
  385. });
  386. }
  387. // tabs
  388. $('.nav-tabs-examples a').click(function (e) {
  389. e.preventDefault();
  390. $(this).tab('show');
  391. });
  392. $('.nav-tabs-examples').find('a:first').tab('show');
  393. // sample request switch
  394. $('.sample-request-switch').click(function (e) {
  395. var name = '.' + $(this).attr('name') + '-fields';
  396. $(name).addClass('hide');
  397. $(this).parent().next(name).removeClass('hide');
  398. });
  399. // call scrollspy refresh method
  400. $(window).scrollspy('refresh');
  401. // init modules
  402. sampleRequest.initDynamic();
  403. }
  404. initDynamic();
  405. // Pre- / Code-Format
  406. prettyPrint();
  407. //
  408. // HTML-Template specific jQuery-Functions
  409. //
  410. // Change Main Version
  411. $('#versions li.version a').on('click', function(e) {
  412. e.preventDefault();
  413. var selectedVersion = $(this).html();
  414. $('#version strong').html(selectedVersion);
  415. // hide all
  416. $('article').addClass('hide');
  417. $('#sidenav li:not(.nav-fixed)').addClass('hide');
  418. // show 1st equal or lower Version of each entry
  419. $('article[data-version]').each(function(index) {
  420. var group = $(this).data('group');
  421. var name = $(this).data('name');
  422. var version = $(this).data('version');
  423. if (semver.lte(version, selectedVersion)) {
  424. if ($('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible').length === 0) {
  425. // enable Article
  426. $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide');
  427. // enable Navigation
  428. $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide');
  429. $('#sidenav li.nav-header[data-group=\'' + group + '\']').removeClass('hide');
  430. }
  431. }
  432. });
  433. // show 1st equal or lower Version of each entry
  434. $('article[data-version]').each(function(index) {
  435. var group = $(this).data('group');
  436. $('section#api-' + group).removeClass('hide');
  437. if ($('section#api-' + group + ' article:visible').length === 0) {
  438. $('section#api-' + group).addClass('hide');
  439. } else {
  440. $('section#api-' + group).removeClass('hide');
  441. }
  442. });
  443. initDynamic();
  444. return;
  445. });
  446. // compare all article with their predecessor
  447. $('#compareAllWithPredecessor').on('click', changeAllVersionCompareTo);
  448. // change version of an article
  449. $('article .versions li.version a').on('click', changeVersionCompareTo);
  450. // compare url-parameter
  451. $.urlParam = function(name) {
  452. var results = new RegExp('[\\?&amp;]' + name + '=([^&amp;#]*)').exec(window.location.href);
  453. return (results && results[1]) ? results[1] : null;
  454. };
  455. if ($.urlParam('compare')) {
  456. // URL Paramter ?compare=1 is set
  457. $('#compareAllWithPredecessor').trigger('click');
  458. if (window.location.hash) {
  459. var id = window.location.hash;
  460. $('html,body').animate({ scrollTop: parseInt($(id).offset().top) - 18 }, 0);
  461. }
  462. }
  463. /**
  464. * Initialize search
  465. */
  466. var options = {
  467. valueNames: [ 'nav-list-item' ]
  468. };
  469. var endpointsList = new List('scrollingNav', options);
  470. /**
  471. * Set initial focus to search input
  472. */
  473. $('#scrollingNav .sidenav-search input.search').focus();
  474. /**
  475. * Detect ESC key to reset search
  476. */
  477. $(document).keyup(function(e) {
  478. if (e.keyCode === 27) $('span.search-reset').click();
  479. });
  480. /**
  481. * Search reset
  482. */
  483. $('span.search-reset').on('click', function() {
  484. $('#scrollingNav .sidenav-search input.search')
  485. .val("")
  486. .focus()
  487. ;
  488. endpointsList.search();
  489. });
  490. /**
  491. * Change version of an article to compare it to an other version.
  492. */
  493. function changeVersionCompareTo(e) {
  494. e.preventDefault();
  495. var $root = $(this).parents('article');
  496. var selectedVersion = $(this).html();
  497. var $button = $root.find('.version');
  498. var currentVersion = $button.find('strong').html();
  499. $button.find('strong').html(selectedVersion);
  500. var group = $root.data('group');
  501. var name = $root.data('name');
  502. var version = $root.data('version');
  503. var compareVersion = $root.data('compare-version');
  504. if (compareVersion === selectedVersion)
  505. return;
  506. if ( ! compareVersion && version == selectedVersion)
  507. return;
  508. if (compareVersion && articleVersions[group][name][0] === selectedVersion || version === selectedVersion) {
  509. // the version of the entry is set to the highest version (reset)
  510. resetArticle(group, name, version);
  511. } else {
  512. var $compareToArticle = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + selectedVersion + '\']');
  513. var sourceEntry = {};
  514. var compareEntry = {};
  515. $.each(apiByGroupAndName[group][name], function(index, entry) {
  516. if (entry.version === version)
  517. sourceEntry = entry;
  518. if (entry.version === selectedVersion)
  519. compareEntry = entry;
  520. });
  521. var fields = {
  522. article: sourceEntry,
  523. compare: compareEntry,
  524. versions: articleVersions[group][name]
  525. };
  526. // add unique id
  527. // TODO: replace all group-name-version in template with id.
  528. fields.article.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version;
  529. fields.article.id = fields.article.id.replace(/\./g, '_');
  530. fields.compare.id = fields.compare.group + '-' + fields.compare.name + '-' + fields.compare.version;
  531. fields.compare.id = fields.compare.id.replace(/\./g, '_');
  532. var entry = sourceEntry;
  533. if (entry.parameter && entry.parameter.fields)
  534. fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields);
  535. if (entry.error && entry.error.fields)
  536. fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields);
  537. if (entry.success && entry.success.fields)
  538. fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields);
  539. if (entry.info && entry.info.fields)
  540. fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields);
  541. var entry = compareEntry;
  542. if (fields._hasTypeInParameterFields !== true && entry.parameter && entry.parameter.fields)
  543. fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields);
  544. if (fields._hasTypeInErrorFields !== true && entry.error && entry.error.fields)
  545. fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields);
  546. if (fields._hasTypeInSuccessFields !== true && entry.success && entry.success.fields)
  547. fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields);
  548. if (fields._hasTypeInInfoFields !== true && entry.info && entry.info.fields)
  549. fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields);
  550. var content = templateCompareArticle(fields);
  551. $root.after(content);
  552. var $content = $root.next();
  553. // Event on.click re-assign
  554. $content.find('.versions li.version a').on('click', changeVersionCompareTo);
  555. // select navigation
  556. $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + currentVersion + '\']').addClass('has-modifications');
  557. $root.remove();
  558. // TODO: on change main version or select the highest version re-render
  559. }
  560. initDynamic();
  561. }
  562. /**
  563. * Compare all currently selected Versions with their predecessor.
  564. */
  565. function changeAllVersionCompareTo(e) {
  566. e.preventDefault();
  567. $('article:visible .versions').each(function(){
  568. var $root = $(this).parents('article');
  569. var currentVersion = $root.data('version');
  570. var $foundElement = null;
  571. $(this).find('li.version a').each(function() {
  572. var selectVersion = $(this).html();
  573. if (selectVersion < currentVersion && ! $foundElement)
  574. $foundElement = $(this);
  575. });
  576. if($foundElement)
  577. $foundElement.trigger('click');
  578. });
  579. initDynamic();
  580. }
  581. /**
  582. * Sort the fields.
  583. */
  584. function sortFields(fields_object) {
  585. $.each(fields_object, function (key, fields) {
  586. var reversed = fields.slice().reverse()
  587. var max_dot_count = Math.max.apply(null, reversed.map(function (item) {
  588. return item.field.split(".").length - 1;
  589. }))
  590. for (var dot_count = 1; dot_count <= max_dot_count; dot_count++) {
  591. reversed.forEach(function (item, index) {
  592. var parts = item.field.split(".");
  593. if (parts.length - 1 == dot_count) {
  594. var fields_names = fields.map(function (item) { return item.field; });
  595. if (parts.slice(1).length >= 1) {
  596. var prefix = parts.slice(0, parts.length - 1).join(".");
  597. var prefix_index = fields_names.indexOf(prefix);
  598. if (prefix_index > -1) {
  599. fields.splice(fields_names.indexOf(item.field), 1);
  600. fields.splice(prefix_index + 1, 0, item);
  601. }
  602. }
  603. }
  604. });
  605. }
  606. });
  607. }
  608. /**
  609. * Add article settings.
  610. */
  611. function addArticleSettings(fields, entry) {
  612. // add unique id
  613. // TODO: replace all group-name-version in template with id.
  614. fields.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version;
  615. fields.id = fields.id.replace(/\./g, '_');
  616. if (entry.header && entry.header.fields) {
  617. sortFields(entry.header.fields);
  618. fields._hasTypeInHeaderFields = _hasTypeInFields(entry.header.fields);
  619. }
  620. if (entry.parameter && entry.parameter.fields) {
  621. sortFields(entry.parameter.fields);
  622. fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields);
  623. }
  624. if (entry.error && entry.error.fields) {
  625. sortFields(entry.error.fields);
  626. fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields);
  627. }
  628. if (entry.success && entry.success.fields) {
  629. sortFields(entry.success.fields);
  630. fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields);
  631. }
  632. if (entry.info && entry.info.fields) {
  633. sortFields(entry.info.fields);
  634. fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields);
  635. }
  636. // add template settings
  637. fields.template = apiProject.template;
  638. }
  639. /**
  640. * Render Article.
  641. */
  642. function renderArticle(group, name, version) {
  643. var entry = {};
  644. $.each(apiByGroupAndName[group][name], function(index, currentEntry) {
  645. if (currentEntry.version === version)
  646. entry = currentEntry;
  647. });
  648. var fields = {
  649. article: entry,
  650. versions: articleVersions[group][name]
  651. };
  652. addArticleSettings(fields, entry);
  653. return templateArticle(fields);
  654. }
  655. /**
  656. * Render original Article and remove the current visible Article.
  657. */
  658. function resetArticle(group, name, version) {
  659. var $root = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible');
  660. var content = renderArticle(group, name, version);
  661. $root.after(content);
  662. var $content = $root.next();
  663. // Event on.click muss neu zugewiesen werden (sollte eigentlich mit on automatisch funktionieren... sollte)
  664. $content.find('.versions li.version a').on('click', changeVersionCompareTo);
  665. $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('has-modifications');
  666. $root.remove();
  667. return;
  668. }
  669. /**
  670. * Load google fonts.
  671. */
  672. function loadGoogleFontCss() {
  673. WebFont.load({
  674. active: function() {
  675. // Update scrollspy
  676. $(window).scrollspy('refresh')
  677. },
  678. google: {
  679. families: ['Source Code Pro', 'Source Sans Pro:n4,n6,n7']
  680. }
  681. });
  682. }
  683. /**
  684. * Return ordered entries by custom order and append not defined entries to the end.
  685. * @param {String[]} elements
  686. * @param {String[]} order
  687. * @param {String} splitBy
  688. * @return {String[]} Custom ordered list.
  689. */
  690. function sortByOrder(elements, order, splitBy) {
  691. var results = [];
  692. order.forEach (function(name) {
  693. if (splitBy)
  694. elements.forEach (function(element) {
  695. var parts = element.split(splitBy);
  696. var key = parts[1]; // reference keep for sorting
  697. if (key == name)
  698. results.push(element);
  699. });
  700. else
  701. elements.forEach (function(key) {
  702. if (key == name)
  703. results.push(name);
  704. });
  705. });
  706. // Append all other entries that ar not defined in order
  707. elements.forEach(function(element) {
  708. if (results.indexOf(element) === -1)
  709. results.push(element);
  710. });
  711. return results;
  712. }
  713. });