share.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /**
  2. * @fileOverview
  3. *
  4. * 分享功能交互
  5. *
  6. * @author: techird
  7. * @copyright: Baidu FEX, 2014
  8. */
  9. KityMinder.registerUI('menu/share/share', function(minder) {
  10. var $share_menu = minder.getUI('menu/menu').createSubMenu('share');
  11. var $create_menu = $($share_menu.createSub('createshare'));
  12. var $manage_menu = $($share_menu.createSub('manageshare'));
  13. var $share_list = $('<ul>')
  14. .attr('id', 'manage-share-list')
  15. .appendTo($manage_menu);
  16. var $doc = minder.getUI('doc');
  17. var notice = minder.getUI('widget/notice');
  18. var finder = minder.getUI('widget/netdiskfinder');
  19. var BACKEND_URL = 'http://naotu.baidu.com/share.php';
  20. if (window.location.host == 'local.host') {
  21. //BACKEND_URL = '/naotu/share.php'; // 测试环境
  22. }
  23. var currentShare = null;
  24. var shareList = [];
  25. renderCreatePanel().then(bindCreatePanelEvent);
  26. renderManagePanel();
  27. var shareListLoaded = loadShareList();
  28. shareListLoaded.then(renderShareList);
  29. shareListLoaded.then(bindManageActions);
  30. minder.on('uiready', function() {
  31. minder.getUI('topbar/user').requireLogin($manage_menu);
  32. });
  33. $doc.on('docload', function(doc) {
  34. if (doc.source != 'netdisk') {
  35. currentShare = null;
  36. setShareType('none');
  37. }
  38. shareListLoaded.then(function() {
  39. var shared = getShareByPath(doc.path);
  40. setCurrentShare(shared);
  41. });
  42. });
  43. $doc.on('docsave', function(doc) {
  44. if (doc.source != 'netdisk') return;
  45. var shared = getShareByPath(doc.path);
  46. if (shared) {
  47. fio.user.check().then(function(user) {
  48. $.pajax({
  49. url: BACKEND_URL,
  50. type: 'POST',
  51. data: {
  52. action: 'update',
  53. ak: user.access_token,
  54. id: shared.id || shared.shareMinder.id,
  55. record: doc.json
  56. }
  57. }).then(function() {
  58. //notice.info(minder.getLang('ui.share_sync_success', doc.title));
  59. })['catch'](function(e) {
  60. notice.error('err_share_sync_fail', e);
  61. });
  62. });
  63. }
  64. });
  65. finder.on('mv', trackFileMove);
  66. function trackFileMove(from, to) {
  67. var fromPath = from.split('/');
  68. var toPath = to.split('/');
  69. function preCommonLength(a, b) {
  70. var i = 0;
  71. while ((i in a) && (i in b) && a[i] == b[i]) i++;
  72. return (i in b) ? 0 : i;
  73. }
  74. shareListLoaded.then(function(list) {
  75. var userChecked = fio.user.check();
  76. list.forEach(function(item) {
  77. var originPath = item.path.split('/');
  78. var clen = preCommonLength(originPath, fromPath);
  79. if (clen) {
  80. var movedPath = toPath.concat(originPath.slice(clen));
  81. userChecked.then(function(user) {
  82. $.pajax({
  83. url: BACKEND_URL,
  84. type: 'POST',
  85. data: {
  86. action: 'move',
  87. ak: user.access_token,
  88. id: item.id || item.shareMinder.id,
  89. path: movedPath.join('/')
  90. }
  91. }).then(function() {
  92. notice.info(minder.getLang('ui.share_sync_success', item.title));
  93. })['catch'](function(e) {
  94. notice.error('err_share_sync_failed', e);
  95. });
  96. });
  97. item.path = movedPath.join('/');
  98. }
  99. });
  100. renderShareList(list);
  101. });
  102. }
  103. function loadShareFile() {
  104. var pattern = /(?:shareId|share_id)=(\w+)([&#]|$)/;
  105. var match = pattern.exec(window.location) || pattern.exec(document.referrer);
  106. if (!match) return Promise.resolve(null);
  107. var shareId = match[1];
  108. $(minder.getRenderTarget()).addClass('loading');
  109. shareListLoaded.then(function(list) {
  110. for (var i = 0; i < list.length; i++) {
  111. var id = list[i].id || (list[i].shareMinder && list[i].shareMinder.id);
  112. if (id == shareId && list[i].path) {
  113. return loadOriginFile(list[i]);
  114. }
  115. }
  116. return loadShare(shareId);
  117. });
  118. }
  119. function loadOriginFile(share) {
  120. var $netdisk = minder.getUI('menu/open/netdisk');
  121. notice.info(minder.getLang('ui.load_share_for_edit', share.title));
  122. return $netdisk.open(share.path, function() {
  123. // 网盘加载失败
  124. return loadShare(share);
  125. });
  126. }
  127. function loadShare(shareId) {
  128. function renderShareData(data) {
  129. if (data.error) {
  130. notice.error('err_share_data', data.error);
  131. return;
  132. }
  133. var content = data.shareMinder.data;
  134. return $doc.load({
  135. source: 'share',
  136. content: content,
  137. protocol: 'json',
  138. saved: true,
  139. ownerId: data.uid,
  140. ownerName: data.uname
  141. });
  142. }
  143. var $container = $(minder.getRenderTarget()).addClass('loading');
  144. return $.pajax({
  145. url: 'http://naotu.baidu.com/share.php',
  146. data: {
  147. action: 'find',
  148. id: shareId
  149. },
  150. dataType: 'json'
  151. }).then(renderShareData)['catch'](function(e) {
  152. notice.error('err_share_data', e);
  153. }).then(function() {
  154. $container.removeClass('loading');
  155. });
  156. }
  157. function getShareByPath(path) {
  158. if (!path || !shareList) return null;
  159. var i = shareList.length;
  160. while (i--) {
  161. if (shareList[i].path == path) return shareList[i];
  162. }
  163. return null;
  164. }
  165. function setCurrentShare(share) {
  166. currentShare = share;
  167. if (share)
  168. renderPublicShare(share);
  169. else
  170. setShareType('none');
  171. }
  172. function renderCreatePanel() {
  173. // render template
  174. return $.pajax({ url: 'static/pages/createshare.html' }).then(function(html) {
  175. /* global jhtmls: true */
  176. var render = jhtmls.render(html);
  177. $create_menu.html(render({
  178. lang: minder.getLang('ui'),
  179. minder: minder
  180. }));
  181. setTimeout(zeroCopy, 10);
  182. return $create_menu;
  183. });
  184. }
  185. function renderManagePanel() {
  186. $manage_menu.append($('<h2>')
  187. .text(minder.getLang('ui.manage_share'))
  188. .attr('id', 'manage-share-header'));
  189. }
  190. function bindCreatePanelEvent($panel) {
  191. $panel.delegate('input[name=sharetype]', 'click', function(e) {
  192. var actions = {
  193. 'none': removeCurrentShare,
  194. 'public': createPublicShare
  195. };
  196. actions[e.target.value]();
  197. });
  198. $panel.delegate('input#share-url', 'dblclick', function() {
  199. this.select();
  200. });
  201. $panel.delegate('#copy-share-url', 'click', function() {
  202. if (kity.Browser.safari && kity.Browser.safari < 8) {
  203. var input = $('#share-url');
  204. input.focus();
  205. input.select();
  206. window.alert(minder.getLang('ui.clipboardunsupported'));
  207. }
  208. });
  209. }
  210. function bindManageActions() {
  211. $manage_menu.delegate('.share-item a', 'click', function(e) {
  212. var $target = $(e.target);
  213. var $li = $target.closest('.share-item');
  214. var share = $li.data('share');
  215. switch (true) {
  216. case $target.hasClass('view-action'):
  217. window.open(buildShareUrl(share.id || share.shareMinder.id), '_blank');
  218. return;
  219. case $target.hasClass('remove-action'):
  220. $li.addClass('loading');
  221. removeShare(share).then(function(result) {
  222. if (result && result.deleted) {
  223. shareList.splice(shareList.indexOf(share), 1);
  224. $li.slideUp(function() {
  225. $li.remove();
  226. });
  227. if (share == currentShare) {
  228. removeCurrentShareSelect();
  229. }
  230. }
  231. }).then(function() {
  232. $li.removeClass('loading');
  233. });
  234. return;
  235. case $target.hasClass('edit-action'):
  236. loadOriginFile(share);
  237. return;
  238. }
  239. });
  240. }
  241. function removeShare(share) {
  242. return fio.user.check().then(function(user) {
  243. return $.pajax(BACKEND_URL, {
  244. type: 'POST',
  245. data: {
  246. action: 'remove',
  247. ak: user && user.access_token,
  248. id: share.id || share.shareMinder.id
  249. },
  250. dataType: 'json'
  251. })['catch'](function(e) {
  252. var notice = minder.getUI('widget/notice');
  253. notice.error('err_remove_share', e);
  254. });
  255. });
  256. }
  257. function removeCurrentShare() {
  258. if (!currentShare) return;
  259. $create_menu.addClass('loading');
  260. return removeShare(currentShare).then(function(result) {
  261. if (result && result.deleted) {
  262. removeCurrentShareSelect();
  263. }
  264. $create_menu.removeClass('loading');
  265. });
  266. }
  267. function removeCurrentShareSelect() {
  268. if (currentShare.$listItem) {
  269. currentShare.$listItem.remove();
  270. }
  271. currentShare = null;
  272. setShareType('none');
  273. }
  274. function uuid() {
  275. // 最多使用 1e7,否则 IE toString() 会出来指数表示法
  276. var timeLead = 1e6;
  277. return ((+new Date() * timeLead) + (Math.random() * --timeLead)).toString(36);
  278. }
  279. function createPublicShare(user) {
  280. if (currentShare) return;
  281. $create_menu.addClass('loading');
  282. return fio.user.check().then(function(user) {
  283. var record = {
  284. shareMinder: {
  285. id: uuid(),
  286. data: JSON.stringify(minder.exportJson())
  287. }
  288. };
  289. var currentDoc = $doc.current();
  290. if (currentDoc.source == 'netdisk') {
  291. record.path = currentDoc.path;
  292. }
  293. return $.pajax(BACKEND_URL, {
  294. type: 'POST',
  295. data: {
  296. action: 'insert',
  297. record: JSON.stringify(record),
  298. ak: user && user.access_token
  299. },
  300. dataType: 'json'
  301. }).then(function(result) {
  302. if (result.error) {
  303. throw new Error(result.error);
  304. }
  305. return result;
  306. })['catch'](function(e) {
  307. var notice = minder.getUI('widget/notice');
  308. notice.error('err_create_share', e);
  309. });
  310. })
  311. .then(function(shared) {
  312. if (shared) {
  313. setCurrentShare(shared);
  314. shareListLoaded.then(function() {
  315. shareList.unshift(shared);
  316. $('#manage-share-list').prepend(currentShare.$listItem = buildShareItem(shared));
  317. });
  318. }
  319. $create_menu.removeClass('loading');
  320. });
  321. }
  322. function buildShareUrl(id) {
  323. var baseUrl = /^(.*?)(\?|\#|$)/.exec(window.location.href)[1];
  324. baseUrl = baseUrl.split('edit.html')[0];
  325. return baseUrl + 'viewshare.html?shareId=' + id;
  326. }
  327. function setShareType(value) {
  328. var $sbody = $('#public-share .share-body', $create_menu);
  329. if (value == 'public') {
  330. $sbody.show();
  331. } else {
  332. $sbody.hide();
  333. }
  334. $('#share-select input[name=sharetype][value=' + value + ']', $create_menu)
  335. .prop('checked', true);
  336. }
  337. function renderPublicShare(shared) {
  338. var $sbody = $('#public-share .share-body', $create_menu);
  339. var shareUrl = buildShareUrl(shared.id || shared.shareMinder.id);
  340. $('#share-url', $sbody).val(shareUrl)[0].select();
  341. // qr code
  342. var $qrcontainer = $sbody.find('.share-qr-code').empty();
  343. new window.QRCode($qrcontainer[0], {
  344. text: shareUrl,
  345. width: 128,
  346. height: 128,
  347. correctLevel : window.QRCode.CorrectLevel.M
  348. });
  349. var shareConfig = window._bd_share_config && window._bd_share_config.common,
  350. resetShare = window._bd_share_main && window._bd_share_main.init;
  351. if (shareConfig && resetShare) {
  352. shareConfig.bdTitle = shareConfig.bdText = minder.getMinderTitle();
  353. shareConfig.bdDesc = shareConfig.bdText = minder.getLang('ui.sns_share_text',
  354. minder.getMinderTitle(), shareUrl);
  355. shareConfig.bdUrl = shareUrl;
  356. resetShare();
  357. }
  358. setShareType('public');
  359. }
  360. function loadShareList() {
  361. return fio.user.check().then(function(user) {
  362. if (!user) return;
  363. return $.pajax(BACKEND_URL, {
  364. type: 'GET',
  365. data: {
  366. action: 'list',
  367. ak: user && user.access_token
  368. },
  369. dataType: 'json'
  370. }).then(function(result) {
  371. return (shareList = result.list || []);
  372. });
  373. });
  374. }
  375. function renderShareList(list) {
  376. var frdTime = minder.getUI('widget/friendlytimespan');
  377. if (!list) return;
  378. $share_list.empty();
  379. list.forEach(function(share) {
  380. $share_list.append(share.$listItem = buildShareItem(share));
  381. });
  382. }
  383. function buildShareItem(share) {
  384. var id = share.id || (share.shareMinder && share.shareMinder.id);
  385. if (!id) return;
  386. var $li = $('<li>')
  387. .addClass('share-item')
  388. .data('share', share);
  389. $('<span>')
  390. .addClass('title')
  391. .text(share.title)
  392. .appendTo($li);
  393. $('<span>')
  394. .addClass('url')
  395. .text(share.path ?
  396. share.path.replace('/apps/kityminder', minder.getLang('ui.mydocument')) :
  397. buildShareUrl(id))
  398. .appendTo($li);
  399. if (share.ctime) {
  400. $('<span>')
  401. .addClass('ctime')
  402. .displayFriendlyTime(+share.ctime)
  403. .appendTo($li);
  404. }
  405. $('<a>')
  406. .addClass('remove-action')
  407. .text(minder.getLang('ui.share_remove_action'))
  408. .attr('title', minder.getLang('ui.share_remove_action'))
  409. .appendTo($li);
  410. $('<a>')
  411. .addClass('view-action')
  412. .text(minder.getLang('ui.share_view_action'))
  413. .attr('title', minder.getLang('ui.share_view_action'))
  414. .appendTo($li);
  415. if (share.path)
  416. $('<a>')
  417. .addClass('edit-action')
  418. .text(minder.getLang('ui.share_edit_action'))
  419. .attr('title', minder.getLang('ui.share_edit_action'))
  420. .appendTo($li);
  421. return $li;
  422. }
  423. function clearShareList() {
  424. shareList = [];
  425. }
  426. function shareRedirect() {
  427. var pattern = /(?:shareId|share_id)=(\w+)([&#]|$)/;
  428. var match = pattern.exec(window.location) || pattern.exec(document.referrer);
  429. if (match) {
  430. window.location.href = 'viewshare.html?shareId=' + match[1];
  431. }
  432. }
  433. function zeroCopy() {
  434. /* global ZeroClipboard:true */
  435. var $copy_url_btn = $('#copy-share-url', $create_menu);
  436. if (window.ZeroClipboard) {
  437. ZeroClipboard.config({
  438. swfPath: 'lib/ZeroClipboard.swf',
  439. hoverClass: 'hover',
  440. activeClass: 'active'
  441. });
  442. var clip = new window.ZeroClipboard($copy_url_btn);
  443. clip.on('ready', function() {
  444. clip.on('aftercopy', function() {
  445. $copy_url_btn.text(minder.getLang('ui.copied')).attr('disabled', 'disabled');
  446. setTimeout(function() {
  447. $copy_url_btn
  448. .text(minder.getLang('ui.copy'))
  449. .removeAttr('disabled');
  450. }, 3000);
  451. });
  452. });
  453. }
  454. }
  455. return {
  456. $menu: $share_menu,
  457. loadShareFile: loadShareFile
  458. };
  459. });