ajax-functions.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /*· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
  2. · ·
  3. · ·
  4. · Q V I T T E R ·
  5. · ·
  6. · ·
  7. · <o) ·
  8. · /_//// ·
  9. · (____/ ·
  10. · (o< ·
  11. · o> \\\\_\ ·
  12. · \\) \____) ·
  13. · ·
  14. · ·
  15. · @licstart The following is the entire license notice for the ·
  16. · JavaScript code in this page. ·
  17. · ·
  18. · Copyright (C) 2015 Hannes Mannerheim and other contributors ·
  19. · ·
  20. · ·
  21. · This program is free software: you can redistribute it and/or modify ·
  22. · it under the terms of the GNU Affero General Public License as ·
  23. · published by the Free Software Foundation, either version 3 of the ·
  24. · License, or (at your option) any later version. ·
  25. · ·
  26. · This program is distributed in the hope that it will be useful, ·
  27. · but WITHOUT ANY WARRANTY; without even the implied warranty of ·
  28. · MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ·
  29. · GNU Affero General Public License for more details. ·
  30. · ·
  31. · You should have received a copy of the GNU Affero General Public License ·
  32. · along with this program. If not, see <http://www.gnu.org/licenses/>. ·
  33. · ·
  34. · @licend The above is the entire license notice ·
  35. · for the JavaScript code in this page. ·
  36. · ·
  37. · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
  38. /* ·
  39. ·
  40. · Current time in milliseconds, to send with each request to make sure
  41. · we're not getting 304 responses.
  42. ·
  43. ·
  44. · · · · · · · · · · · · · */
  45. function timeNow() {
  46. return new Date().getTime();
  47. }
  48. /* ·
  49. ·
  50. · Get a document and replace strings
  51. ·
  52. · @param doc: the name of the document
  53. · @param actionOnSuccess: callback function to run on success
  54. ·
  55. · · · · · · · · · · · · · */
  56. function getDoc(doc, actionOnSuccess) {
  57. var timeNow = new Date().getTime();
  58. $.ajax({ url: window.fullUrlToThisQvitterApp + 'doc/' + window.selectedLanguage + '/' + doc + '.html',
  59. cache: false,
  60. type: "GET",
  61. success: function(data) {
  62. actionOnSuccess(renderDoc(data));
  63. },
  64. error: function() {
  65. // default to english if we can't find the doc in selected language
  66. $.ajax({ url: window.fullUrlToThisQvitterApp + 'doc/en/' + doc + '.html',
  67. cache: false,
  68. type: "GET",
  69. success: function(data) {
  70. actionOnSuccess(renderDoc(data));
  71. }
  72. });
  73. }
  74. });
  75. }
  76. function renderDoc(docHtml) {
  77. docHtml = docHtml.replace(/{instance-name}/g,window.siteTitle);
  78. docHtml = docHtml.replace(/{instance-url}/g,window.siteRootDomain);
  79. docHtml = docHtml.replace(/{instance-url-with-protocol}/g,window.siteInstanceURL);
  80. docHtml = docHtml.replace(/{nickname}/g,window.loggedIn.screen_name);
  81. docHtml = docHtml.replace(/{instance-email}/g,window.siteEmail);
  82. docHtml = docHtml.replace(/{instance-license-title}/g,window.siteLicenseTitle);
  83. docHtml = docHtml.replace(/{instance-license-url}/g,window.siteLicenseURL);
  84. return docHtml;
  85. }
  86. /* ·
  87. ·
  88. · Check login credentials with http basic auth
  89. ·
  90. · @param username: users screen name
  91. · @param password: users password
  92. · @param actionOnSuccess: callback function on log in success
  93. ·
  94. · · · · · · · · · */
  95. function checkLogin(username,password,actionOnSuccess) {
  96. $.ajax({ url: window.apiRoot + 'qvitter/checklogin.json',
  97. cache: false,
  98. type: 'POST',
  99. data: {
  100. username: username,
  101. password: password
  102. },
  103. dataType: 'json',
  104. error: function(data) {
  105. shakeLoginBox();
  106. if(data.status === 403) {
  107. showErrorMessage(window.sL.silenced);
  108. }
  109. },
  110. success: function(data) {
  111. if(typeof data.error == 'undefined' && data !== false) {
  112. actionOnSuccess(data);
  113. }
  114. else {
  115. shakeLoginBox();
  116. }
  117. }
  118. });
  119. }
  120. /* ·
  121. ·
  122. · Generic API GET request
  123. ·
  124. · @param stream: any api get-request e.g. 'statuses/favs/111111.json'
  125. · @param actionOnSuccess: callback function
  126. ·
  127. · · · · · · · · · · · · · */
  128. function getFromAPI(stream, actionOnSuccess) {
  129. var url = window.apiRoot + stream;
  130. $.ajax({ url: url,
  131. cache: false,
  132. type: "GET",
  133. dataType: 'json',
  134. statusCode: {
  135. 401:function() {
  136. location.reload(); // we may have been logged out in another tab, reload page
  137. }
  138. },
  139. success: function(data, textStatus, request) {
  140. // if there's no Qvitter-Notifications header, it means we're logged out
  141. // so if it's missing and Qvitter still thinks we're logged in, reload page
  142. // we've probably been logged out in another tab or something
  143. if(request.getResponseHeader('Qvitter-Notifications') === null && window.loggedIn !== false) {
  144. location.reload();
  145. return;
  146. }
  147. displayOrHideUnreadNotifications(request.getResponseHeader('Qvitter-Notifications'));
  148. // parse and cache any user arrays in header
  149. var userArray = false;
  150. if(request.getResponseHeader('Qvitter-User-Array') !== null) {
  151. var qvitterUserArrayHeader = request.getResponseHeader('Qvitter-User-Array');
  152. // quitter.se fix
  153. if(window.thisSiteThinksItIsHttpButIsActuallyHttps) {
  154. qvitterUserArrayHeader = qvitterUserArrayHeader.replace(new RegExp('http:\\\\/\\\\/' + window.siteRootDomain, 'g'), 'https:\/\/' + window.siteRootDomain);
  155. }
  156. userArray = iterateRecursiveReplaceHtmlSpecialChars($.parseJSON(qvitterUserArrayHeader));
  157. userArrayCacheStore(userArray);
  158. }
  159. data = convertEmptyObjectToEmptyArray(data);
  160. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  161. searchForUserDataToCache(data);
  162. updateUserDataInStream();
  163. searchForUpdatedNoticeData(data);
  164. actionOnSuccess(data, userArray, request, url);
  165. },
  166. error: function(data, textStatus, errorThrown) {
  167. data.textStatus = textStatus;
  168. data.errorThrown = errorThrown;
  169. actionOnSuccess(false, false, data, url);
  170. remove_spinner();
  171. }
  172. });
  173. }
  174. /* ·
  175. ·
  176. · Hello to the API! When saying hello you will e.g. also get headers
  177. · with up-to-date unread notifications count to update etc
  178. ·
  179. · @param callback: function to invoke when done
  180. ·
  181. · · · · · · · · · · · · · */
  182. function helloAPI(callback) {
  183. getFromAPI('qvitter/hello.json',function(){
  184. if(typeof callback == 'function') {
  185. callback();
  186. }
  187. });
  188. }
  189. /* ·
  190. ·
  191. · Get all people we follow, all groups we're in and everyone we've blocked
  192. · Store in global objects
  193. ·
  194. · @param callback: function to invoke when done
  195. ·
  196. · · · · · · · · · · · · · */
  197. function getAllFollowsMembershipsAndBlocks(callback) {
  198. if(window.loggedIn === false) {
  199. return;
  200. }
  201. window.following = new Object();
  202. window.groupMemberships = new Object();
  203. window.groupNicknamesAndLocalAliases = new Array();
  204. window.allBlocking = new Array();
  205. getFromAPI('qvitter/allfollowing/' + window.loggedIn.screen_name + '.json',function(data){
  206. if(data.users) {
  207. $.each(data.users,function(k,v){
  208. if(v[2] === false) { var avatar = window.defaultAvatarStreamSize; }
  209. else { var avatar = v[2]; }
  210. if(v[3]) {
  211. // extract server base url
  212. v[3] = v[3].substring(v[3].indexOf('://')+3,v[3].lastIndexOf(v[1])-1);
  213. }
  214. v[0] = v[0] || v[1]; // if name is null we go with username there too
  215. window.following[k] = { 'id': k,'name': v[0], 'username': v[1],'avatar': avatar, 'url':v[3] };
  216. });
  217. }
  218. if(data.groups) {
  219. $.each(data.groups,function(k,v){
  220. if(v[2] === false || v[2] === null) { var avatar = window.defaultAvatarStreamSize; }
  221. else { var avatar = v[2]; }
  222. if(v[3]) {
  223. // extract server base url
  224. v[3] = v[3].substring(v[3].indexOf('://')+3);
  225. v[3] = v[3].substring(0, v[3].indexOf('/'));
  226. }
  227. v[0] = v[0] || v[1]; // if name is null we go with username there too
  228. window.groupMemberships[k] = { 'id': k,'name': v[0], 'username': v[1],'avatar': avatar, 'url':v[3] };
  229. window.groupNicknamesAndLocalAliases[k] = v[1];
  230. });
  231. }
  232. if(data.blocks) {
  233. window.allBlocking = data.blocks;
  234. markAllNoticesFromBlockedUsersAsBlockedInJQueryObject($('body'));
  235. }
  236. if(typeof callback == 'function') {
  237. callback();
  238. }
  239. });
  240. }
  241. /* ·
  242. ·
  243. · Get user nickname by user id
  244. ·
  245. · @param id: local user id
  246. · @param callback: function to invoke when done
  247. ·
  248. · · · · · · · · · · · · · */
  249. function getNicknameByUserIdFromAPI(id, callback) {
  250. display_spinner();
  251. getFromAPI('users/show.json?id=' + id, function(data){
  252. remove_spinner();
  253. if(data && typeof data.screen_name != 'undefined') {
  254. callback(data.screen_name);
  255. }
  256. else {
  257. callback(false);
  258. }
  259. });
  260. }
  261. /* ·
  262. ·
  263. · Get group nickname by group id
  264. ·
  265. · @param id: local group id
  266. · @param callback: function to invoke when done
  267. ·
  268. · · · · · · · · · · · · · */
  269. function getNicknameByGroupIdFromAPI(id, callback) {
  270. display_spinner();
  271. getFromAPI('statusnet/groups/show/' + id + '.json', function(data){
  272. remove_spinner();
  273. if(data && typeof data.nickname != 'undefined') {
  274. callback(data.nickname);
  275. }
  276. else {
  277. callback(false);
  278. }
  279. });
  280. }
  281. /* ·
  282. ·
  283. · Update the bookmarks
  284. ·
  285. · @param newBookmarks: the new bookmarks object to save
  286. ·
  287. · · · · · · · · · · · · · */
  288. function postUpdateBookmarks(newBookmarks) {
  289. var bookmarksString = JSON.stringify(newBookmarks);
  290. $.ajax({ url: window.apiRoot + 'qvitter/update_bookmarks.json',
  291. cache: false,
  292. type: "POST",
  293. beforeSend: function (xhr) {
  294. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  295. },
  296. data: {
  297. bookmarks: bookmarksString
  298. },
  299. dataType:"json",
  300. error: function(data){ console.log('error updating bookmarks'); },
  301. success: function(data) {
  302. // console.log('bookmarks updated successfully');
  303. }
  304. });
  305. }
  306. /* ·
  307. ·
  308. · Post new link color
  309. ·
  310. · @param newLinkColor: the new link color in hex without #
  311. ·
  312. · · · · · · · · · · · · · */
  313. function postNewLinkColor(newLinkColor) {
  314. $.ajax({ url: window.apiRoot + 'qvitter/update_link_color.json',
  315. cache: false,
  316. type: "POST",
  317. beforeSend: function (xhr) {
  318. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  319. },
  320. data: {
  321. linkcolor: newLinkColor
  322. },
  323. dataType:"json",
  324. error: function(data){ console.log(data); },
  325. success: function(data) {
  326. window.userLinkColor = newLinkColor;
  327. }
  328. });
  329. }
  330. /* ·
  331. ·
  332. · Post new background color
  333. ·
  334. · @param newBackgroundColor: the new background color in hex without #
  335. ·
  336. · · · · · · · · · · · · · */
  337. function postNewBackgroundColor(newBackgroundColor) {
  338. $.ajax({ url: window.apiRoot + 'qvitter/update_background_color.json',
  339. cache: false,
  340. type: "POST",
  341. beforeSend: function (xhr) {
  342. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  343. },
  344. data: {
  345. backgroundcolor: newBackgroundColor
  346. },
  347. dataType:"json",
  348. error: function(data){ console.log(data); },
  349. success: function(data) {
  350. // unset background image and set new color
  351. window.loggedIn.background_image = false;
  352. changeDesign({backgroundimage:false,backgroundcolor:newBackgroundColor});
  353. }
  354. });
  355. }
  356. /* ·
  357. ·
  358. · Set a profile pref
  359. ·
  360. · @param namespace: the namespace field in the db table, should be 'qvitter'
  361. · @param topic: the topic field in the db table,
  362. · @param data: the data to set
  363. · @param callback: function to run when finished
  364. ·
  365. · · · · · · · · · · · · · */
  366. function postSetProfilePref(namespace, topic, data, callback) {
  367. $.ajax({ url: window.apiRoot + 'qvitter/set_profile_pref.json',
  368. cache: false,
  369. type: "POST",
  370. beforeSend: function (xhr) {
  371. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  372. },
  373. data: {
  374. namespace: namespace,
  375. topic: topic,
  376. data: data
  377. },
  378. dataType:"json",
  379. error: function(data){ callback(false); },
  380. success: function(data) {
  381. callback(data); }
  382. });
  383. }
  384. /* ·
  385. ·
  386. · Post follow or unfollow user request
  387. ·
  388. · @param followOrUnfollow: either 'follow' or 'unfollow'
  389. · @param user_id: the user id of the user we want to follow
  390. · @param actionOnSuccess: callback function, false on error, data on success
  391. ·
  392. · · · · · · · · · · · · · */
  393. function APIFollowOrUnfollowUser(followOrUnfollow,user_id,this_element,actionOnSuccess) {
  394. if(followOrUnfollow == 'follow') {
  395. var postRequest = 'friendships/create.json';
  396. }
  397. else if (followOrUnfollow == 'unfollow') {
  398. var postRequest = 'friendships/destroy.json';
  399. }
  400. $.ajax({ url: window.apiRoot + postRequest,
  401. cache: false,
  402. type: "POST",
  403. beforeSend: function (xhr) {
  404. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  405. },
  406. data: {
  407. user_id: user_id
  408. },
  409. dataType:"json",
  410. error: function(data){ actionOnSuccess(false,this_element); console.log(data); },
  411. success: function(data) {
  412. data = convertEmptyObjectToEmptyArray(data);
  413. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  414. searchForUserDataToCache(data);
  415. updateUserDataInStream();
  416. actionOnSuccess(data,this_element);
  417. }
  418. });
  419. }
  420. /* ·
  421. ·
  422. · Post block or unblock user request
  423. ·
  424. · @param blockOrUnblock: either 'block' or 'unblock'
  425. · @param user_id: the user id of the user we want to block/unblock
  426. · @param actionOnSuccess: callback function, false on error, data on success
  427. ·
  428. · · · · · · · · · · · · · */
  429. function APIBlockOrUnblockUser(blockOrUnblock,user_id,actionOnSuccess) {
  430. if(blockOrUnblock == 'block') {
  431. var postRequest = 'blocks/create.json';
  432. }
  433. else if (blockOrUnblock == 'unblock') {
  434. var postRequest = 'blocks/destroy.json';
  435. }
  436. $.ajax({ url: window.apiRoot + postRequest,
  437. cache: false,
  438. type: "POST",
  439. beforeSend: function (xhr) {
  440. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  441. },
  442. data: {
  443. id: user_id
  444. },
  445. dataType:"json",
  446. error: function(data){ actionOnSuccess(false); console.log(data); },
  447. success: function(data) {
  448. data = convertEmptyObjectToEmptyArray(data);
  449. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  450. searchForUserDataToCache(data);
  451. updateUserDataInStream();
  452. actionOnSuccess(data);
  453. }
  454. });
  455. }
  456. /* ·
  457. ·
  458. · Post sandbox or unsandbox user request
  459. ·
  460. · @param createOrDestroy: either 'create' or 'destroy'
  461. · @param userId: the user id of the user we want to sandbox/unsandbox
  462. · @param actionOnSuccess: callback function, false on error, data on success
  463. ·
  464. · · · · · · · · · · · · · */
  465. function APISandboxCreateOrDestroy(createOrDestroy,userId,actionOnSuccess) {
  466. $.ajax({ url: window.apiRoot + 'qvitter/sandbox/' + createOrDestroy + '.json',
  467. cache: false,
  468. type: "POST",
  469. beforeSend: function (xhr) {
  470. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  471. },
  472. data: {
  473. id: userId
  474. },
  475. dataType:"json",
  476. error: function(data){ actionOnSuccess(false); console.log('sandbox error'); console.log(data); },
  477. success: function(data) {
  478. data = convertEmptyObjectToEmptyArray(data);
  479. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  480. searchForUserDataToCache(data);
  481. updateUserDataInStream();
  482. rememberStreamStateInLocalStorage();
  483. actionOnSuccess(data);
  484. }
  485. });
  486. }
  487. /* ·
  488. ·
  489. · Post silence or unsilence user request
  490. ·
  491. · @param createOrDestroy: either 'create' or 'destroy'
  492. · @param userId: the user id of the user we want to silence/unsilence
  493. · @param actionOnSuccess: callback function, false on error, data on success
  494. ·
  495. · · · · · · · · · · · · · */
  496. function APISilenceCreateOrDestroy(createOrDestroy,userId,actionOnSuccess) {
  497. $.ajax({ url: window.apiRoot + 'qvitter/silence/' + createOrDestroy + '.json',
  498. cache: false,
  499. type: "POST",
  500. beforeSend: function (xhr) {
  501. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  502. },
  503. data: {
  504. id: userId
  505. },
  506. dataType:"json",
  507. error: function(data){ actionOnSuccess(false); console.log('silence error'); console.log(data); },
  508. success: function(data) {
  509. data = convertEmptyObjectToEmptyArray(data);
  510. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  511. searchForUserDataToCache(data);
  512. updateUserDataInStream();
  513. rememberStreamStateInLocalStorage();
  514. actionOnSuccess(data);
  515. }
  516. });
  517. }
  518. /* ·
  519. ·
  520. · Post join or leave group request
  521. ·
  522. · @param joinOrLeave: either 'join' or 'leave'
  523. · @param group_id: group's id
  524. · @param actionOnSuccess: callback function, false on error, data on success
  525. ·
  526. · · · · · · · · · · · · · */
  527. function APIJoinOrLeaveGroup(joinOrLeave,group_id,this_element,actionOnSuccess) {
  528. $.ajax({ url: window.apiRoot + 'statusnet/groups/' + joinOrLeave + '.json',
  529. cache: false,
  530. type: "POST",
  531. beforeSend: function (xhr) {
  532. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  533. },
  534. data: {
  535. id: group_id
  536. },
  537. dataType:"json",
  538. error: function(data){ actionOnSuccess(false,this_element); console.log(data); },
  539. success: function(data) {
  540. data = convertEmptyObjectToEmptyArray(data);
  541. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  542. searchForUserDataToCache(data);
  543. updateUserDataInStream();
  544. actionOnSuccess(data,this_element);
  545. }
  546. });
  547. }
  548. /* ·
  549. ·
  550. · Post queet
  551. ·
  552. · @param queetText_txt: the text to post
  553. · @param in_reply_to_status_id: the local id for the queet to reply to
  554. · @param postToGroups: post the queet in these groups, string of ids separated by colon expected, e.g. 5:2:4
  555. · @param actionOnSuccess: callback function, false on error, data on success
  556. ·
  557. · · · · · · · · · · · · · */
  558. function postQueetToAPI(queetText_txt, in_reply_to_status_id, postToGroups, actionOnSuccess) {
  559. $.ajax({ url: window.apiRoot + 'qvitter/statuses/update.json',
  560. cache: false,
  561. type: "POST",
  562. beforeSend: function (xhr) {
  563. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  564. },
  565. data: {
  566. status: queetText_txt,
  567. source: 'Qvitter',
  568. in_reply_to_status_id: in_reply_to_status_id,
  569. post_to_groups: postToGroups
  570. },
  571. dataType:"json",
  572. error: function(data){ actionOnSuccess(false); console.log(data); },
  573. success: function(data) {
  574. data = convertEmptyObjectToEmptyArray(data);
  575. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  576. searchForUserDataToCache(data);
  577. updateUserDataInStream();
  578. searchForUpdatedNoticeData(data);
  579. actionOnSuccess(data);
  580. }
  581. });
  582. }
  583. /* ·
  584. ·
  585. · Generic POST-action
  586. ·
  587. · @param action: the api action, e.q. 'statuses/retweet/1.json'
  588. · @param actionOnSuccess: callback function, false on error, data on success
  589. ·
  590. · · · · · · · · · · · · · */
  591. function postActionToAPI(action, actionOnSuccess) {
  592. $.ajax({ url: window.apiRoot + action,
  593. cache: false,
  594. type: "POST",
  595. beforeSend: function (xhr) {
  596. xhr.setRequestHeader('X-Qvitter-CSRF', getCookieValue('Qvitter-CSRF'));
  597. },
  598. data: {
  599. source: 'Qvitter'
  600. },
  601. dataType:"json",
  602. error: function(data){ actionOnSuccess(false); console.log(data); },
  603. success: function(data) {
  604. data = convertEmptyObjectToEmptyArray(data);
  605. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  606. searchForUserDataToCache(data);
  607. updateUserDataInStream();
  608. searchForUpdatedNoticeData(data);
  609. actionOnSuccess(data);
  610. }
  611. });
  612. }
  613. /* ·
  614. ·
  615. · Gets favs or requeets for a queet from api
  616. ·
  617. · @param q: stream item object
  618. · @param qid: the queet id
  619. ·
  620. · · · · · · · · · */
  621. function getFavsAndRequeetsForQueet(q,qid) {
  622. // get immediately from localstorage cache
  623. var cacheData = localStorageObjectCache_GET('favsAndRequeets',qid);
  624. if(cacheData) {
  625. showFavsAndRequeetsInQueet(q, cacheData);
  626. }
  627. $.ajax({ url: window.apiRoot + "qvitter/favs_and_repeats/" + qid + ".json",
  628. cache: false,
  629. type: "GET",
  630. dataType: 'json',
  631. success: function(data) {
  632. data = iterateRecursiveReplaceHtmlSpecialChars(data);
  633. if(data.favs.length > 0 || data.repeats.length > 0) {
  634. localStorageObjectCache_STORE('favsAndRequeets',qid, data); // cache response
  635. }
  636. else {
  637. // remove from cache and DOM if all favs and repeats are deleted
  638. localStorageObjectCache_STORE('favsAndRequeets',qid, false);
  639. }
  640. showFavsAndRequeetsInQueet(q,data);
  641. },
  642. error: function(data) {
  643. remove_spinner();
  644. console.log(data);
  645. }
  646. });
  647. }