PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/share/spice/octopart/spice.js

https://github.com/aembleton/zeroclickinfo-spice
JavaScript | 211 lines | 142 code | 25 blank | 44 comment | 25 complexity | bca360a159b4e0ec45046e2ff680bc4f MD5 | raw file
  1. // `ddg_spice_octopart` is a callback function that gets
  2. // called when people search for electronic parts. Example
  3. // triggers are "atmega specs" or "microprocessor datasheet."
  4. // Some example 'datasheet' queries:
  5. //
  6. // - ne555 datasheet
  7. // - atmel avr datasheet
  8. // - datasheet arduino uno
  9. // - UWX1V100MCL1GB datasheet
  10. // - UWX1V100 datasheet
  11. // - blue led datasheet
  12. // - stm32 adc dac ethernet datasheet
  13. // - zigbee transceiver freescale datasheet
  14. //
  15. // Extra info the Octopart API response that could be parsed and displayed
  16. //
  17. // - rohs and lead-free attributes
  18. // - product lifecycle status (obsolete, pre-production, active)
  19. // - categorization (aka, type of component)
  20. // - direct free sample links (for some parts)
  21. //
  22. // Another possibility is to trigger on distributor name and SKU (eg, "newark
  23. // 68T2515") and show part information and a direct link to the distributor's buy
  24. // now page.
  25. // This anonymous function is used to prevent helper
  26. // functions from becoming global functions. We only expose
  27. // `ddg_spice_octopart` so we attach it to the variable `root`.
  28. (function(root) {
  29. "use strict";
  30. // This function is responsible for calling other functions that
  31. // process data and display the plugin.
  32. root.ddg_spice_octopart = function(response) {
  33. if(response && response.hits > 0) {
  34. var parts = response.results,
  35. collection = [],
  36. snippets = [],
  37. part;
  38. // Our goal is to make multiple entries in the plugin.
  39. for(var i = 0, length = parts.length; i < length; i += 1) {
  40. snippets = [];
  41. part = parts[i].item;
  42. // Skip a product that isn't relevant.
  43. if(!DDG.isRelevant(part.short_description, {specs: 1, datasheet: 1, octopart: 1})) {
  44. continue;
  45. }
  46. // Filter out stubs.
  47. if(/^BAD: RFQ Only/.test(part.market_status) && part.images.length === 0) {
  48. continue;
  49. }
  50. getDescription(part, snippets);
  51. getPrice(part, snippets);
  52. getMarketStatus(part, snippets);
  53. collection.push({
  54. heading: getHeading(part),
  55. datasheet_url: getDatasheetURL(part),
  56. manufacturer_url: getManufacturerURL(part),
  57. part: part,
  58. snippets: snippets,
  59. image: getImage(part)
  60. });
  61. }
  62. display(collection);
  63. }
  64. };
  65. // Returns the URL of the image. If it doesn't exist, it returns an empty string.
  66. function getImage(part) {
  67. return part.images.length ? part.images[0].url_55px : "";
  68. }
  69. // Links to the manufacturer's website e.g. Atmel.
  70. function getManufacturerURL(part) {
  71. return part.hyperlinks.manufacturer ||
  72. part.manufacturer.homepage_url;
  73. }
  74. // Returns a link to the PDF document.
  75. function getDatasheetURL(part) {
  76. if (part.datasheets.length) {
  77. return part.datasheets[0].url;
  78. } else {
  79. return "No Datasheet";
  80. }
  81. }
  82. // Check the availability of this part.
  83. function getMarketStatus(part, snippets) {
  84. if (part.num_authsuppliers === 0) {
  85. snippets.push(part.market_status.replace(/^BAD:/, ''));
  86. }
  87. }
  88. // Format the cost of the part.
  89. function getPrice(part, snippets) {
  90. var s = 'Avg Price: ';
  91. if (part.avg_price && (part.avg_price[0] !== null || part.avg_price[0] !== undefined)) {
  92. if (part.avg_price < 0.01) {
  93. s += 'below $0.01/each';
  94. } else {
  95. s += '$' + part.avg_price[0].toFixed(2) + '/each';
  96. }
  97. snippets.push(s);
  98. }
  99. }
  100. // Gets the description used in the plugin.
  101. function getDescription(part, snippets) {
  102. if(part.short_description) {
  103. snippets.push(specsHTML(html_escape(part.short_description.replace(/[,;]$/, ''))));
  104. }
  105. }
  106. // Returns an array containing the title of the plugin.
  107. function getHeading(part) {
  108. return [html_escape(part.manufacturer.displayname), html_escape(part.mpn)];
  109. }
  110. function html_escape(s) {
  111. return s.replace(/&/g, "&amp;")
  112. .replace(/</g, "&lt;")
  113. .replace(/>/g,"&gt;");
  114. }
  115. // Adds an emphasis on the text.
  116. function specsHTML(text) {
  117. return "Specs: <i>" + text + "</i>";
  118. }
  119. // Use this function to create the HTML and call the `nra` function.
  120. function display(collection) {
  121. var items = [],
  122. links = [],
  123. content = "";
  124. // `datasheetHTML`, `linkHTML`, and `distributorsHTML` all create links.
  125. // In the future, it's better to generalize these functions.
  126. function datasheetHTML(collection, links) {
  127. if(collection.part.datasheets.length) {
  128. links.push('<a href="' + collection.datasheet_url + '" ' +
  129. 'style="white-space:nowrap;">' +
  130. '<img src="' + 'https://icons.duckduckgo.com/i/www.adobe.com.ico' +
  131. '" style="' +
  132. 'display:inline;margin-right:3px;height:12px;"/>' +
  133. 'Datasheet</a>');
  134. } else {
  135. links.push("No Datasheet");
  136. }
  137. }
  138. function linkHTML(collection, links) {
  139. if(collection.manufacturer_url) {
  140. links.push('<a href="' + collection.manufacturer_url + '">Manufacturer</a>');
  141. }
  142. }
  143. function distributorsHTML(part, links) {
  144. if (/^GOOD|WARNING:/.test(part.market_status)) {
  145. var s = '<a href="' + part.detail_url + '#compare_suppliers' +
  146. '" style="white-space:nowrap;">from ';
  147. if (part.num_authsuppliers === 0) {
  148. s += "secondary sources";
  149. } else {
  150. s += part.num_authsuppliers;
  151. if (part.num_suppliers > part.num_authsuppliers) {
  152. s += "+";
  153. }
  154. s += " suppliers";
  155. }
  156. s += "</a>";
  157. links.push(s);
  158. }
  159. }
  160. // Loop through each value of collection, append HTML, and then pass it to `nra`.
  161. for(var i = 0, length = collection.length; i < length; i += 1) {
  162. links = [];
  163. datasheetHTML(collection[i], links);
  164. linkHTML(collection[i], links);
  165. distributorsHTML(collection[i].part, links);
  166. content = "";
  167. if(collection[i].snippets.length) {
  168. content += collection[i].snippets.join('; ') + ' ';
  169. }
  170. if(links.length) {
  171. content += '[' + links.join('] [') + '] ';
  172. }
  173. content += '<div style="clear:both;"></div>';
  174. items[i] = {
  175. h: "Octopart - " + collection[i].heading.join(" "),
  176. a: content,
  177. i: collection[i].image,
  178. s: 'Octopart',
  179. u: collection[i].part.detail_url,
  180. t: collection[i].heading.join(" "),
  181. force_big_header: true
  182. };
  183. }
  184. nra(items);
  185. }
  186. }(this));