PageRenderTime 27ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/sites/web/packages/stock/stock.js

https://bitbucket.org/aswinvk28/smartpan-stock-drupal
JavaScript | 428 lines | 307 code | 49 blank | 72 comment | 28 complexity | 4be818d688b30224ca910a594c3b2ee1 MD5 | raw file
Possible License(s): LGPL-2.1
  1. (function(Backbone, $, _) {
  2. 'use strict';
  3. var Stock = Stock || {},
  4. Collection = {},
  5. Workspace = Workspace || {},
  6. latestStock = function(symbol) {
  7. return new Stock.StockData({
  8. url: "http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20from%20yahoo.finance.quoteslist%20where%20symbol%20%3D%20'" + symbol + "'&format=json&diagnostics=false&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback="
  9. });
  10. },
  11. escape = function(namespace) {
  12. var that = this;
  13. if (this.isShown) {
  14. $(document).on('keyup', function ( e ) {
  15. e.which == 27 && that.hide()
  16. });
  17. } else if (!this.isShown) {
  18. $(document).off('keyup');
  19. }
  20. },
  21. historicalSTock = function(symbol, startDate, endDate) {
  22. return new Stock.StockData({
  23. url: "http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20from%20yahoo.finance.historicaldata%20where%20symbol%20%3D%20'" + symbol + "'%20and%20startDate='" + startDate + "'%20andendDate='" + endDate + "'&format=json&diagnostics=false&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback="
  24. });
  25. },
  26. BootstrapAlert = Backbone.View.extend({
  27. initialize: function(options) {
  28. var view = this;
  29. $(this.el).html(view.render({
  30. message: options.message,
  31. type: options.type
  32. }));
  33. return this;
  34. },
  35. tagName: 'div',
  36. className: 'alert clearfix column_small decolumn_small',
  37. template: '<button type="button" class="close" data-dismiss="alert">&times;</button><strong><%= type %>!</strong> <%= message %>',
  38. render: function(options) {
  39. var func = _.template(this.template);
  40. return func(options);
  41. }
  42. }),
  43. common = {
  44. error: function() {
  45. var bootstrapAlert = new BootstrapAlert({
  46. message : 'Requested Resource Not Found',
  47. type: 'Warning'
  48. });
  49. $('.status-messages').html(bootstrapAlert.el).show();
  50. }
  51. },
  52. execute = function() {
  53. var context = this;
  54. var object = {
  55. success: function(collection, response) {
  56. Collection.fetchData.call(context, collection, response);
  57. },
  58. error: function(xhr, textStatus, errorThrown) {
  59. common.error();
  60. return this;
  61. },
  62. complete: function() {
  63. }
  64. };
  65. return object;
  66. };
  67. Stock.BASE_URI = 'http://query.yahooapis.com/v1/public/yql?';
  68. Stock.ENV_PARAM = "store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
  69. Stock.FORMAT = 'json';
  70. Stock.PARAMS = function(options) {
  71. var context = this;
  72. var object = {
  73. q: options.query,
  74. diagnostics: context.diagnostics,
  75. env: Stock.ENV_PARAM,
  76. format: Stock.FORMAT
  77. };
  78. return object;
  79. };
  80. Collection.fetchData = function(collection, response) {
  81. this.fetched++;
  82. if(!response) {
  83. this.errorPage();
  84. }
  85. return this;
  86. };
  87. Stock.toQueryString = function(obj) {
  88. var parts = [];
  89. for(var each in obj) if (obj.hasOwnProperty(each)) {
  90. parts.push(encodeURIComponent(each) + '=' + encodeURIComponent(obj[each]));
  91. }
  92. return Stock.BASE_URI + parts.join('&');
  93. };
  94. // Stock.StockData = Backbone.Collection.extend({
  95. // url: null,
  96. // diagnostics: false,
  97. // urlGenerator: function(options) {
  98. // this.url = options.url || Stock.toQueryString(Stock.PARAMS.call(this, options));
  99. // },
  100. // initialize: function(options) {
  101. // this.urlGenerator(options);
  102. // this.fetched = 0;
  103. // this.fetch(execute.apply(this));
  104. // return this;
  105. // },
  106. // errorPage: common.errorPage
  107. // });
  108. //
  109. // Stock.StockPriceCollection = Backbone.Collection.extend({
  110. // sync: Backbone.localforage.sync('Stock.StockPriceCollection'),
  111. // initialize: function(options) {
  112. //
  113. // }
  114. // });
  115. //
  116. // Stock.StockVolumeCollection = Backbone.Collection.extend({
  117. // sync: Backbone.localforage.sync('Stock.StockVolumeCollection'),
  118. // initialize: function(options) {
  119. //
  120. // }
  121. // });
  122. //
  123. // Stock.WidgetView = Backbone.View.extend({
  124. // render: function(options) {
  125. // var func = _.template(this.template);
  126. // return func(options);
  127. // },
  128. // template: function() {
  129. // return $('#script.widget-view').html()
  130. // },
  131. // initialize: function() {
  132. // var view = this;
  133. // $(this.el).html(view.render(view.model)); /*{
  134. // message: options.message,
  135. // type: options.type
  136. // }*/
  137. // return this;
  138. // }
  139. // });
  140. //
  141. // Stock.PriceWidgetContent = Backbone.View.extend({
  142. // render: function(options) {
  143. // var func = _.template(this.template);
  144. // return func(options);
  145. // },
  146. // template: function() {
  147. // return '<span class="fx-large clearfix"><%=price%></span><span class="raphael-ui-component clearfix"><%=price_change%></span>';
  148. // },
  149. // initialize: function(options) {
  150. // var view = this;
  151. // this.price = options.price;
  152. // $(this.el).html(view.render(view.model));
  153. // /*{
  154. // price: options.price,
  155. // price_change: options.price_change
  156. // }*/
  157. // return this;
  158. // }
  159. // });
  160. var StockChoice = Backbone.Model.extend({
  161. symbol: function() {
  162. return this.get("symbol");
  163. },
  164. label: function() {
  165. return this.symbol();
  166. }
  167. });
  168. var StockChoiceList = Backbone.Collection.extend({
  169. model: StockChoice,
  170. url: "http://smartpan.financial:9999/stock",
  171. initialize: function(options) {
  172. this.fetched = 0;
  173. return this;
  174. }
  175. });
  176. var stockChoiceList = new StockChoiceList();
  177. Stock.StockSymbolInput = Backbone.Model.extend({
  178. stock_symbol: null,
  179. changeStockSymbol: function(model, view) {
  180. var attr = $(view.el).data('action');
  181. var value = model.symbol() + '/' + model.get('id');
  182. $(view.el).attr('action', attr[attr.length - 1] === '/' ? attr + value : attr + '/' + value);
  183. },
  184. initialize: function() {
  185. this.on('change:stock_symbol', function(model, value, options) {
  186. model.changeStockSymbol(value, options.view);
  187. });
  188. }
  189. });
  190. var stockInputModel = new Stock.StockSymbolInput();
  191. Stock.StockInputFormView = Backbone.View.extend({
  192. model: stockInputModel,
  193. initialize: function(options) {
  194. this.input = $(this.el).find('#stock-symbol');
  195. },
  196. submit: function() {
  197. var callbacks = execute.apply(this);
  198. var success = callbacks.success;
  199. var promise = _.extend({}, callbacks);
  200. promise.success = function(collection, response) {
  201. success(collection, response);
  202. this.loadResult(this.colection.models);
  203. };
  204. this.collection.fetch(promise);
  205. },
  206. render: function() {
  207. },
  208. loadResult: function(models) {
  209. if (models.length) {
  210. _.forEach(models, this.targetElement.addItem, this);
  211. }
  212. }
  213. });
  214. Workspace.RaphaelDOMWrapper = Backbone.View.extend({
  215. initialize: function(options) {
  216. this.raphaelDOM = options.dom;
  217. $(this.el).append(this.raphaelDOM);
  218. return this;
  219. }
  220. });
  221. var AutoCompleteItemView = Backbone.View.extend({
  222. tagName: "li",
  223. template: _.template('<a href="#" data-stock-id="<%= id %>" data-stock-symbol="<%= symbol %>"><%= symbol %></a>'),
  224. events: {
  225. "click": "select"
  226. },
  227. initialize: function(options) {
  228. this.options = options;
  229. },
  230. render: function () {
  231. this.$el.html(this.template({
  232. "id": this.model.get('id'),
  233. "symbol": this.model.symbol()
  234. }));
  235. return this;
  236. },
  237. select: function () {
  238. this.options.parent.hide().select(this.model);
  239. return false;
  240. }
  241. });
  242. var AutoCompleteView = Backbone.View.extend({
  243. tagName: "ul",
  244. className: "autocomplete",
  245. wait: 300,
  246. queryParameter: "symbol",
  247. minKeywordLength: 1,
  248. currentText: "",
  249. itemView: AutoCompleteItemView,
  250. formView: new Stock.StockInputFormView({
  251. el: $('#stock-symbol').parents('form.form-search').first()
  252. }),
  253. initialize: function (options) {
  254. _.extend(this, options);
  255. this.filter = _.debounce(this.filter, this.wait);
  256. },
  257. render: function () {
  258. // disable the native auto complete functionality
  259. this.input.attr("autocomplete", "off");
  260. this.$el.width(this.input.outerWidth());
  261. this.input
  262. .keyup(_.bind(this.keyup, this))
  263. .keydown(_.bind(this.keydown, this))
  264. .after(this.$el);
  265. return this;
  266. },
  267. keydown: function (event) {
  268. if (event.keyCode == 38) return this.move(-1);
  269. if (event.keyCode == 40) return this.move(+1);
  270. if (event.keyCode == 13) return this.onEnter();
  271. if (event.keyCode == 27) return this.hide();
  272. },
  273. keyup: function () {
  274. var keyword = this.input.val();
  275. if (this.isChanged(keyword)) {
  276. if (this.isValid(keyword)) {
  277. this.filter(keyword);
  278. } else {
  279. this.hide()
  280. }
  281. }
  282. },
  283. filter: function (keyword) {
  284. if (this.model.url) {
  285. var parameters = {};
  286. var view = this;
  287. parameters[this.queryParameter] = keyword;
  288. var callbacks = execute.apply(this);
  289. var success = callbacks.success;
  290. var promise = _.extend({}, callbacks);
  291. promise.success = function(collection, response) {
  292. success(collection, response);
  293. view.loadResult(collection.models, keyword);
  294. };
  295. promise.data = parameters;
  296. console.log(this.model.sync('create', this.model, promise));
  297. } else {
  298. this.loadResult(this.model.filter(function (model) {
  299. return model.label().toLowerCase().indexOf(keyword) !== -1
  300. }), keyword);
  301. }
  302. },
  303. isValid: function (keyword) {
  304. return keyword.length > this.minKeywordLength
  305. },
  306. isChanged: function (keyword) {
  307. return this.currentText != keyword;
  308. },
  309. move: function (position) {
  310. var current = this.$el.children(".active"),
  311. siblings = this.$el.children(),
  312. index = current.index() + position;
  313. if (siblings.eq(index).length) {
  314. current.removeClass("active");
  315. siblings.eq(index).addClass("active");
  316. }
  317. return false;
  318. },
  319. onEnter: function () {
  320. this.$el.children(".active").click();
  321. return false;
  322. },
  323. loadResult: function (model, keyword) {
  324. this.currentText = keyword;
  325. this.show().reset();
  326. if (model.length) {
  327. _.forEach(model, this.addItem, this);
  328. this.show();
  329. } else {
  330. this.hide();
  331. }
  332. },
  333. addItem: function (model) {
  334. this.$el.append(new this.itemView({
  335. model: model,
  336. parent: this
  337. }).render().$el);
  338. },
  339. select: function (model) {
  340. var label = model.label();
  341. this.input.val(label);
  342. this.currentText = label;
  343. this.onSelect(model);
  344. },
  345. reset: function () {
  346. this.$el.empty();
  347. return this;
  348. },
  349. hide: function () {
  350. this.isShown = false;
  351. escape.call(this);
  352. this.$el.hide();
  353. return this;
  354. },
  355. show: function () {
  356. this.isShown = true;
  357. escape.call(this);
  358. this.$el.show();
  359. return this;
  360. },
  361. // callback definitions
  362. onSelect: function (model) {
  363. var value = $(this.el).val();
  364. this.modelBind.set('stock_symbol', model, {
  365. silent: false,
  366. view: this.formView
  367. });
  368. // var options = {
  369. // symbol: value
  370. // };
  371. // var stockData = new Stock.StockData(options);
  372. }
  373. });
  374. new AutoCompleteView({
  375. input: $("#stock-symbol"),
  376. model: stockChoiceList,
  377. modelBind: stockInputModel
  378. }).render();
  379. })(window.Backbone, window.jQuery, window._);