quick-view-douban

see douban book movie music in every webpage by selecting text

  1. // ==UserScript==
  2. // @name quick-view-douban
  3. // @namespace http://vivyli.com
  4. // @modified ywzhaiqi
  5. // @include *
  6. // @version 2.1
  7. // @description see douban book movie music in every webpage by selecting text
  8. // @description 修正电影搜索,增加图片显示
  9. // @grant GM_xmlhttpRequest
  10. // ==/UserScript==
  11.  
  12. var apikey = '0c088077ba8a630f241981672f9f292d';
  13.  
  14. var imgDouban;
  15. var txtSelection;
  16. var isBookClicked = false;
  17. var isMovieClicked = false;
  18. var isMusicClicked = false;
  19. var q = null;
  20. var userAgent = 'known';
  21. initialize();
  22.  
  23. document.addEventListener('mousedown', clean, false);
  24. document.addEventListener('mouseup', showIcon, false);
  25.  
  26. function clean(event) {
  27. var divInfo = getId('divInfo');
  28. var divSearch = getId('divSearch');
  29.  
  30. if (divInfo) {
  31. if (!clickedInsideID(event.target, 'divInfo'))
  32. divInfo.parentNode.removeChild(divInfo);
  33. }
  34.  
  35. if (divSearch)
  36. divSearch.parentNode.removeChild(divSearch);
  37. }
  38.  
  39. function showIcon(event) {
  40. var divInfo = getId('divInfo');
  41. var divSearch = getId('divSearch');
  42.  
  43. if (!clickedInsideID(event.target, 'divInfo'))
  44. txtSelection = getSelection(event);
  45. else
  46. return;
  47. if (txtSelection == '') {
  48. return;
  49. } else {
  50. q = txtSelection;
  51. }
  52. divSearch = createElement('div', {
  53. id: 'divSearch',
  54. style: 'top:' + (event.clientY + window.pageYOffset + 10) + 'px; left:' + (event.clientX + window.pageXOffset + 10) + 'px;'
  55. });
  56. divSearch.appendChild(imgDouban.cloneNode(false));
  57. divSearch.addEventListener('mouseover', showDouban, false);
  58. document.body.appendChild(divSearch);
  59. }
  60.  
  61. function showDouban(event) {
  62. var divResult = null;
  63. var divInfo = getId('divInfo');
  64. var divSearch = getId('divSearch');
  65. var top = divSearch.style.top;
  66. var left = divSearch.style.left;
  67.  
  68. divInfo = createElement('div', {
  69. id: 'divInfo'
  70. });
  71. divInfo.style.top = top;
  72. divInfo.style.left = left;
  73. document.body.appendChild(divInfo);
  74.  
  75. var bookDiv = createElement('div', {
  76. id: 'bookDiv',
  77. title: 'book'
  78. }, null, null);
  79. var bookClickDiv = createElement('div', {
  80. id: 'bookClickDiv'
  81. }, 'mouseup showDoubanBook false', '+豆瓣读书');
  82. bookDiv.appendChild(bookClickDiv);
  83. divInfo.appendChild(bookDiv);
  84.  
  85. var movieDiv = createElement('div', {
  86. id: 'movieDiv',
  87. title: 'movie'
  88. }, null, null);
  89. var movieClickDiv = createElement('div', {
  90. id: 'movieClickDiv'
  91. }, 'mouseup showDoubanMovie false', '+豆瓣电影');
  92. movieDiv.appendChild(movieClickDiv);
  93. divInfo.appendChild(movieDiv);
  94.  
  95. var musicDiv = createElement('div', {
  96. id: 'musicDiv',
  97. title: 'music'
  98. }, null, null);
  99. var musicClickDiv = createElement('div', {
  100. id: 'musicClickDiv'
  101. }, 'mouseup showDoubanMusic false', '+豆瓣音乐');
  102. musicDiv.appendChild(musicClickDiv);
  103. divInfo.appendChild(musicDiv);
  104.  
  105. }
  106.  
  107. function showDoubanBook(event) {
  108. if (isBookClicked == false) {
  109. getId('bookClickDiv').innerHTML = '-豆瓣读书 loading...';
  110. isBookClicked = true;
  111. showBookInfo();
  112. } else if (isBookClicked == true) {
  113. getId('bookClickDiv').innerHTML = '+豆瓣读书';
  114. cleanBook();
  115. //getId('bookDiv')
  116. isBookClicked = false;
  117. }
  118. }
  119.  
  120. function cleanBook() {
  121. var bookInfo = getId('bookInfo');
  122. var morebooks = getId('morebooks');
  123. if (bookInfo != null)
  124. bookInfo.parentNode.removeChild(bookInfo);
  125. if (morebooks != null)
  126. morebooks.parentNode.removeChild(morebooks);
  127. }
  128.  
  129. function showBookInfo() {
  130. var bookurl = 'http://api.douban.com/book/subjects?q=' + q + '&apikey=' + apikey;
  131. var moreurl = 'http://book.douban.com/subject_search?search_text=' + q + '&cat=1001';
  132. GM_xmlhttpRequest({
  133. method: 'GET',
  134. url: bookurl,
  135. onload: function(resp) {
  136. var book = parseBook(resp.responseText);
  137. var bookInfo = createElement('div', {
  138. id: 'bookInfo'
  139. }, null, book);
  140. getId('bookDiv').appendChild(bookInfo);
  141. var more = createElement('div', {
  142. id: 'more'
  143. }, null, null);
  144. getId('bookDiv').appendChild(more);
  145. more.appendChild(createElement('a', {
  146. id: 'morebooks',
  147. href: moreurl,
  148. target: '_blank'
  149. }, null, '--更多书籍--'));
  150. getId('bookClickDiv').innerHTML = '-豆瓣读书';
  151. }
  152. });
  153. }
  154.  
  155. function parseBook(text) {
  156. return parse(text, 'Book');
  157. }
  158. // Douban Movie
  159.  
  160. function showDoubanMovie(event) {
  161. if (isMovieClicked == false) {
  162. getId('movieClickDiv').innerHTML = '-豆瓣电影 loading...';
  163. isMovieClicked = true;
  164. // showMovieInfo();
  165. showMovieInfo2();
  166. } else if (isMovieClicked == true) {
  167. getId('movieClickDiv').innerHTML = '+豆瓣电影';
  168. cleanMovie();
  169. //getId('bookDiv')
  170. isMovieClicked = false;
  171. }
  172. }
  173.  
  174. function cleanMovie() {
  175. var movieInfo = getId('movieInfo');
  176. var moremovies = getId('moremovies');
  177. if (movieInfo != null)
  178. movieInfo.parentNode.removeChild(movieInfo);
  179. if (moremovies != null)
  180. moremovies.parentNode.removeChild(moremovies);
  181. }
  182.  
  183. // version 2
  184. function showMovieInfo2() {
  185. var movieurl = 'https://api.douban.com/v2/movie/search?q=' + q;
  186. var moreurl = 'http://movie.douban.com/subject_search?search_text=' + q + '&cat=1002';
  187. GM_xmlhttpRequest({
  188. method: 'GET',
  189. url: movieurl,
  190. onload: function(res) {
  191. var obj = JSON.parse(res.responseText);
  192. var movie = obj.subjects[0];
  193. var html;
  194. if(movie){
  195. movie.subtype = (movie.subtype == 'tv') ? "电视剧" : "电影";
  196. movie.original_title = (movie.original_title == movie.title) ? "" : movie.original_title;
  197.  
  198. var template = '\
  199. <img src="{images.small}" alt={alt} align="right"/>\
  200. {subtype}: <a id = "turl" href="{alt}" target="_blank">{title}</a><br/>\
  201. 原名: {original_title}<br/>\
  202. 时间: {year}<br/>\
  203. <span class="_allstar{rating.stars}"></span>\
  204. <span>{rating.average}</span>\
  205. <span>({collect_count}评价)</span>\
  206. ';
  207. html = nano(template, movie);
  208. }else{
  209. html = "对不起,找不到相关的电影";
  210. }
  211.  
  212. var movieInfo = createElement('div', {
  213. id: 'movieInfo'
  214. }, null, html);
  215. getId('movieDiv').appendChild(movieInfo);
  216. var more = createElement('div', {
  217. id: 'more'
  218. }, null, null);
  219. getId('movieDiv').appendChild(more);
  220. more.appendChild(createElement('a', {
  221. id: 'moremovies',
  222. href: moreurl,
  223. target: '_blank'
  224. }, null, '--更多电影--'));
  225. getId('movieClickDiv').innerHTML = '-豆瓣电影';
  226. }
  227. });
  228. }
  229.  
  230. function showMovieInfo() {
  231. //alert(q);
  232. var movieurl = 'http://api.douban.com/movie/subjects?q=' + q + '&apikey=' + apikey;
  233. var moreurl = 'http://movie.douban.com/subject_search?search_text=' + q + '&cat=1002';
  234. GM_xmlhttpRequest({
  235. method: 'GET',
  236. url: movieurl,
  237. onload: function(resp) {
  238. var movie = parseMovie(resp.responseText);
  239. var movieInfo = createElement('div', {
  240. id: 'movieInfo'
  241. }, null, movie);
  242. getId('movieDiv').appendChild(movieInfo);
  243. var more = createElement('div', {
  244. id: 'more'
  245. }, null, null);
  246. getId('movieDiv').appendChild(more);
  247. more.appendChild(createElement('a', {
  248. id: 'moremovies',
  249. href: moreurl,
  250. target: '_blank'
  251. }, null, '--更多电影--'));
  252. getId('movieClickDiv').innerHTML = '-豆瓣电影';
  253. }
  254. });
  255. }
  256.  
  257. function parseMovie(text) {
  258. return parse(text, 'Movie');
  259. }
  260. //Douban Music
  261.  
  262. function showDoubanMusic(event) {
  263. if (isMusicClicked == false) {
  264. getId('musicClickDiv').innerHTML = '-豆瓣音乐 loading...';
  265. isMusicClicked = true;
  266. showMusicInfo();
  267. } else if (isMusicClicked == true) {
  268. getId('musicClickDiv').innerHTML = '+豆瓣音乐';
  269. cleanMusic();
  270. //getId('bookDiv')
  271. isMusicClicked = false;
  272. }
  273. }
  274.  
  275. function cleanMusic() {
  276. var musicInfo = getId('musicInfo');
  277. var moremusics = getId('moremusics');
  278. if (musicInfo != null)
  279. musicInfo.parentNode.removeChild(musicInfo);
  280. if (moremusics != null)
  281. moremusics.parentNode.removeChild(moremusics);
  282. }
  283.  
  284. function showMusicInfo() {
  285. var musicurl = 'http://api.douban.com/music/subjects?q=' + q + '&apikey=' + apikey;
  286. var moreurl = 'http://music.douban.com/subject_search?search_text=' + q + '&cat=1003';
  287. GM_xmlhttpRequest({
  288. method: 'GET',
  289. url: musicurl,
  290. onload: function(resp) {
  291. var music = parseMusic(resp.responseText);
  292. var musicInfo = createElement('div', {
  293. id: 'musicInfo'
  294. }, null, music);
  295. getId('musicDiv').appendChild(musicInfo);
  296. var more = createElement('div', {
  297. id: 'more'
  298. }, null, null);
  299. getId('musicDiv').appendChild(more);
  300. more.appendChild(createElement('a', {
  301. id: 'moremusics',
  302. href: moreurl,
  303. target: '_blank'
  304. }, null, '--更多音乐--'));
  305. getId('musicClickDiv').innerHTML = '-豆瓣音乐';
  306. }
  307. });
  308. }
  309.  
  310. function parseMusic(text) {
  311. return parse(text, 'Music');
  312. }
  313.  
  314. function parse(text, category) {
  315. var cat = category;
  316. if (category == 'Book')
  317. cat = '书籍';
  318. else if (category == 'Music')
  319. cat = '音乐';
  320. else if (category == 'Movie')
  321. cat = '电影';
  322.  
  323. var ratingTag = 'rating';
  324. var attributeTag = 'attribute';
  325. if (userAgent == 'Firefox') {
  326. ratingTag = 'gd:' + ratingTag;
  327. attributeTag = 'db:' + attributeTag;
  328. }
  329. var res = '';
  330.  
  331. var parser = new DOMParser();
  332. var dom = parser.parseFromString(text, "text/xml");
  333. var entities = dom.getElementsByTagName("entry");
  334.  
  335. if (entities.length > 0) {
  336.  
  337. var entry = entities[0];
  338.  
  339. var id = entry.getElementsByTagName("id")[0].textContent;
  340. var title = entry.getElementsByTagName("title")[0].textContent;
  341. var rate = entry.getElementsByTagName(ratingTag)[0].getAttribute('average');
  342. var total = entry.getElementsByTagName(ratingTag)[0].getAttribute('numRaters');
  343.  
  344. var attrs = entry.getElementsByTagName(attributeTag);
  345. var links = entry.getElementsByTagName('link');
  346. if (category == 'Book') {
  347. var author = '';
  348. var price = '';
  349. var publisher = '';
  350. var pubdate = '';
  351. for (var i = 0; i < attrs.length; i++) {
  352. var name = attrs[i].getAttribute('name').toString();
  353.  
  354. if (name == "author") {
  355. if (author == '')
  356. author = attrs[i].textContent;
  357. else author += ', ' + attrs[i].textContent;
  358. } else if (name == 'price') {
  359. price = attrs[i].textContent;
  360. } else if (name == 'publisher') {
  361. publisher = attrs[i].textContent;
  362. } else if (name == 'pubdate') {
  363. pubdate = attrs[i].textContent;
  364. }
  365.  
  366. }
  367. var url = '';
  368. if (links.length > 0) {
  369. for (var i = links.length - 1; i >= 0; i--) {
  370. var rel = links[i].getAttribute('rel').toString();
  371. if (rel == 'alternate') {
  372. url = links[i].getAttribute('href').toString();
  373. break;
  374. }
  375. };
  376. }
  377.  
  378. var imgSrc = entry.querySelector('link[rel="image"]').getAttribute('href');
  379.  
  380. res = '<img src="' + imgSrc + '" align="right"/>' +
  381. '书籍: <a id = "turl" href = "' + url + '" target = "_blank">' + title + '</a><br/>' +
  382. '作者: ' + author + '<br/>' +
  383. '价格: ' + price + '<br/>' +
  384. '发行: ' + publisher + '<br/>' +
  385. '时间: ' + pubdate + '<br/>' +
  386. '评分: ' + rate + '(共' + total + ' 条评价)';
  387.  
  388. } else if (category == 'Music') {
  389. var singer = '';
  390. var pubdate = '';
  391. var publisher = '';
  392.  
  393. for (var i = 0; i < attrs.length; i++) {
  394. var name = attrs[i].getAttribute('name');
  395. if (name == 'singer') {
  396. if (singer == '')
  397. singer = attrs[i].textContent;
  398. else singer += ', ' + attrs[i].textContent;
  399. } else if (name == 'pubdate') {
  400. pubdate = attrs[i].textContent;
  401. } else if (name == 'publisher') {
  402. publisher = attrs[i].textContent;
  403. }
  404.  
  405. }
  406. var url = '';
  407. if (links.length > 0) {
  408. for (var i = links.length - 1; i >= 0; i--) {
  409. var rel = links[i].getAttribute('rel').toString();
  410. if (rel == 'alternate') {
  411. url = links[i].getAttribute('href').toString();
  412. break;
  413. }
  414. };
  415. }
  416. res = cat + ': <a id = "turl" href = "' + url + '" target = "_blank">' + title + '</a><br/>' +
  417. '歌手: ' + singer + '<br/>' +
  418. '时间: ' + pubdate + '<br/>' +
  419. '发行: ' + publisher + '<br/>' +
  420. '评分: ' + rate + '(共' + total + ' 条评价)';
  421.  
  422. } else if (category == 'Movie') {
  423. var country = '';
  424. var director = '';
  425. var pubdate = '';
  426. var lang = '';
  427. var cast = '';
  428. for (var i = 0; i < attrs.length; i++) {
  429. var name = attrs[i].getAttribute('name');
  430. if (name == 'country') {
  431. if (country == '')
  432. country = attrs[i].textContent;
  433. else country += ', ' + attrs[i].textContent;
  434. } else if (name == 'director') {
  435. if (director == '')
  436. director = attrs[i].textContent;
  437. else director += ', ' + attrs[i].textContent;
  438. } else if (name == 'pubdate') {
  439. pubdate = attrs[i].textContent;
  440. } else if (name == 'language') {
  441. if (lang == '')
  442. lang = attrs[i].textContent;
  443. else lang += ', ' + attrs[i].textContent;
  444. } else if (name == 'cast') {
  445. if (cast == '')
  446. cast = attrs[i].textContent;
  447. else cast += ', ' + attrs[i].textContent;
  448. }
  449.  
  450. }
  451. var url = '';
  452. if (links.length > 0) {
  453. for (var i = links.length - 1; i >= 0; i--) {
  454. var rel = links[i].getAttribute('rel').toString();
  455. if (rel == 'alternate') {
  456. url = links[i].getAttribute('href').toString();
  457. break;
  458. }
  459. };
  460. }
  461. res = cat + ': <a id = "turl" href = "' + url + '" target = "_blank">' + title + '</a><br/>' +
  462. '导演: ' + director + '<br/>' +
  463. '主演: ' + cast + '<br/>' +
  464. '国家: ' + country + '<br/>' +
  465. '时间: ' + pubdate + '<br/>' +
  466. '评分: ' + rate + '(共' + total + ' 条评价)';
  467. }
  468.  
  469. return res;
  470. }
  471. return '对不起,找不到相关的' + cat;
  472. }
  473.  
  474. function getSelection(event) {
  475. var txt = null;
  476.  
  477. if (event && event.target.nodeName == 'TextArea') {
  478. txt = event.target.value.substr(event.target.selectionStart, event.target.selectionEnd - event.target.selectionStart);
  479. } else if (window.getSelection) {
  480. txt = window.getSelection();
  481. } else if (document.getSelection) {
  482. txt = window.getSelection();
  483. } else if (document.selection) {
  484. txt = document.selection.createRange().text;
  485. }
  486. return txt.toString();
  487.  
  488. }
  489.  
  490. function getId(id, parent) {
  491. if (!parent)
  492. return document.getElementById(id);
  493. return parent.getElementById(id);
  494. }
  495.  
  496. function createElement(type, attrArray, evtListener, html) {
  497. var node = document.createElement(type);
  498.  
  499. for (var attr in attrArray)
  500. if (attrArray.hasOwnProperty(attr)) {
  501. node.setAttribute(attr, attrArray[attr]);
  502. }
  503.  
  504. if (evtListener) {
  505. var a = evtListener.split(' ');
  506. node.addEventListener(a[0], eval(a[1]), eval(a[2]));
  507. }
  508.  
  509. if (html)
  510. node.innerHTML = html;
  511.  
  512. return node;
  513. }
  514.  
  515. function getTag(name, parent) {
  516. if (!parent)
  517. return document.getElementsByTagName(name);
  518. return parent.getElementsByTagName(name);
  519. }
  520.  
  521. function clickedInsideID(target, id) {
  522.  
  523. if (target.getAttribute('id') == id)
  524. return getId(id);
  525.  
  526. if (target.parentNode) {
  527. while (target = target.parentNode) {
  528. try {
  529. if (target.getAttribute('id') == id)
  530. return getId(id);
  531. } catch (e) {}
  532. }
  533. }
  534.  
  535. return null;
  536. }
  537.  
  538. // initialize
  539.  
  540. function initialize() {
  541. images();
  542. css();
  543. checkUserAgent();
  544. }
  545.  
  546. function checkUserAgent() {
  547. if (navigator["userAgent"].indexOf('Firefox') != -1)
  548. userAgent = 'Firefox';
  549. else if (navigator['userAgent'].indexOf('Chrome') != -1)
  550. userAgent = 'Chrome';
  551. }
  552.  
  553. function css() {
  554.  
  555. var style = createElement('style', {
  556. id: 'douban-view',
  557. type: "text/css"
  558. }, null, "" +
  559. '#bookClickDiv {cursor : pointer; color: #FFFFFF;}' +
  560. '#musicClickDiv {cursor : pointer;color: #FFFFFF;}' +
  561. '#movieClickDiv {cursor: pointer;color: #FFFFFF;}' +
  562. '#bookInfo {color: #FFFFFF;}' +
  563. '#musicInfo {color: #FFFFFF;}' +
  564. '#movieInfo {color: #FFFFFF;}' +
  565. '#divSearch { background-color:#FFFFFF; color:#000000; position:absolute; padding:3px; z-index:999999999; -moz-border-radius:3px; }' +
  566. '#divInfo { background-color:#000000; color:#FFFFFF !important; filter: Alpha(opacity=10);opacity:0.75; position:absolute; min-width:250px; min-height:50px; max-width:100%; padding:7px; font-size:small; text-align:left; z-index:999999999; -moz-border-radius:3px; }' +
  567. '#more{ text-align: right;}' +
  568. '#morebooks{color: #FFAA00}' +
  569. '#moremusics{color: #FFAA00}' +
  570. '#moremovies{color: #FFAA00}' +
  571. '#turl{color: #FFAA00}' +
  572. '._allstar50, ._allstar45, ._allstar40, ._allstar35, ._allstar30, ._allstar25, ._allstar20, ._allstar15, ._allstar10, ._allstar05 {\
  573. background: url("http://www.douban.com/pics/movie/midstars.gif") no-repeat scroll 0 0 transparent;\
  574. display: inline-block;\
  575. height: 11px;\
  576. margin: 0 3px 0 0;\
  577. overflow: hidden;\
  578. width: 55px;\
  579. }'
  580. );
  581. getTag('head')[0].appendChild(style);
  582. }
  583.  
  584. function images() {
  585. imgDouban = createElement('img', {
  586. border: 0
  587. });
  588. imgDouban.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAARCAYAAADUryzEAAADHmlDQ1BJQ0MgUHJvZmlsZQAAeAGFVN9r01AU/tplnbDhizpnEQk+aJFuZFN0Q5y2a1e6zVrqNrchSJumbVyaxiTtfrAH2YtvOsV38Qc++QcM2YNve5INxhRh+KyIIkz2IrOemzRNJ1MDufe73/nuOSfn5F6g+XFa0xQvDxRVU0/FwvzE5BTf8gFeHEMr/GhNi4YWSiZHQA/Tsnnvs/MOHsZsdO5v36v+Y9WalQwR8BwgvpQ1xCLhWaBpXNR0E+DWie+dMTXCzUxzWKcECR9nOG9jgeGMjSOWZjQ1QJoJwgfFQjpLuEA4mGng8w3YzoEU5CcmqZIuizyrRVIv5WRFsgz28B9zg/JfsKiU6Zut5xCNbZoZTtF8it4fOX1wjOYA1cE/Xxi9QbidcFg246M1fkLNJK4RJr3n7nRpmO1lmpdZKRIlHCS8YlSuM2xp5gsDiZrm0+30UJKwnzS/NDNZ8+PtUJUE6zHF9fZLRvS6vdfbkZMH4zU+pynWf0D+vff1corleZLw67QejdX0W5I6Vtvb5M2mI8PEd1E/A0hCgo4cZCjgkUIMYZpjxKr4TBYZIkqk0ml0VHmyONY7KJOW7RxHeMlfDrheFvVbsrj24Pue3SXXjrwVhcW3o9hR7bWB6bqyE5obf3VhpaNu4Te55ZsbbasLCFH+iuWxSF5lyk+CUdd1NuaQU5f8dQvPMpTuJXYSWAy6rPBe+CpsCk+FF8KXv9TIzt6tEcuAcSw+q55TzcbsJdJM0utkuL+K9ULGGPmQMUNanb4kTZyKOfLaUAsnBneC6+biXC/XB567zF3h+rkIrS5yI47CF/VFfCHwvjO+Pl+3b4hhp9u+02TrozFa67vTkbqisXqUj9sn9j2OqhMZsrG+sX5WCCu0omNqSrN0TwADJW1Ol/MFk+8RhAt8iK4tiY+rYleQTysKb5kMXpcMSa9I2S6wO4/tA7ZT1l3maV9zOfMqcOkb/cPrLjdVBl4ZwNFzLhegM3XkCbB8XizrFdsfPJ63gJE722OtPW1huos+VqvbdC5bHgG7D6vVn8+q1d3n5H8LeKP8BqkjCtbCoV8yAAACAUlEQVQ4EZVTz0sbQRh9+0tTbf0RFRWprawGEbQgDa5NcpP2Iu3BlmqN/4v/gCBePIiIKBEvHooULAEvEUSxtqJio1ZLwepajJqou0k2cWY3WbNJhTjLzM735r038307y0S1WNK3PIvAzhJCV+fIp5UXl8Hd7MIn6SO4hteOwflvX6DElHy0Oodyg393oWgqOLtUNajGo3mLM4knoWPwl0pYxzzkSO/auzPX753vy78w6h8D1fJp1tafbezLB1CjKsCk0ax3EhB4HnFNMxdMg7OrEED625fdeFZZTwi5LhHlEnMrn3FxfZFrQJE6ex16ne8xuTQNlRQo2+SDswdHZydY2Pj6fwOe4yCH/xGC3yRkTl48bYUgmIfWlyyRRnKrfGwHLehNTAXLGGkkQR6Sv1glYvd4L9PzrogUPQ2fYmHTD0ns0EkcxxpkItYSCQTlINYOvxtYarScQI1FMRXw4U1bFw7kQwRTu9mEQgx4vBhfnEAimbAYpLawYHhUWAS3w2WCjpomPK+ozxFTgmnAMiwKeEHvO0c/oZGd0rHkkLD++4cZUzzdmJ6RPpIh4HX3QawWDZzkS0GGNfxrS6oRuj6HEqefFoioEQzND+tzvsT2RL+S04EZHXjIQLWsp8XzEI2F625+Bd7b2Ys4+RuX91YtV9TCzApKi0ohNTox4OrHLRsAtvjqiOggAAAAAElFTkSuQmCC';
  589. }
  590.  
  591.  
  592. var _regex = /\{([\w\.]*)\}/g;
  593. function nano(template, data) {
  594. return template.replace(this._regex, function(str, key) {
  595. var keys = key.split('.'),
  596. value = data[keys.shift()];
  597. keys.forEach(function(key) {
  598. value = value[key];
  599. });
  600. return (value === null || value === undefined) ? '' : value;
  601. });
  602. }