results.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. (function ($, document, window, undefined) {
  2. var s2 = window.s2 = window.s2 || {};
  3. var util = s2.util;
  4. var assert = util.assert;
  5. s2.Dropdown = util.clazz(util.Observable, {
  6. construct: function (opts) {
  7. assert.isNotNull(opts, "opts parameter must be set");
  8. assert.isElement(opts.select, "opts.select must point to the select element");
  9. this.super();
  10. this.opts = opts;
  11. },
  12. bind: function (container, tag) {
  13. assert.isElement(container, "container parameter must be set");
  14. assert.isElement(tag, "tag parameter must be set");
  15. this.container = container;
  16. this.element = tag;
  17. this.element.addClass("s2-dropdown");
  18. this.element.detach();
  19. this.element.removeClass("s2-hidden");
  20. //util.detectPlatform(this.element);
  21. },
  22. show: function () {
  23. var self = this;
  24. self.opts.select.parent("body").append(this.element);
  25. self.position();
  26. self.container.addClass("s2-active");
  27. },
  28. hide: function () {
  29. var self = this;
  30. self.element.detach();
  31. self.container.removeClass("s2-active");
  32. },
  33. position: function () {
  34. var self = this,
  35. container = self.container;
  36. var
  37. offset = container.offset(),
  38. height = container.outerHeight(false),
  39. width = container.outerWidth(false),
  40. dropTop = offset.top + height,
  41. dropLeft = offset.left;
  42. self.element.css({ top: dropTop, left: dropLeft, width: width });
  43. }
  44. });
  45. s2.SearchField = util.clazz(util.Observable, {
  46. construct: function (element) {
  47. this.super();
  48. var self = this;
  49. this.value = element.val();
  50. this.element = element;
  51. this.element.on("keyup.s2", function () {
  52. self.onKeyUp.apply(self, arguments)
  53. });
  54. },
  55. onKeyUp: function (e) {
  56. var self = this;
  57. if (self.value !== self.element.val()) {
  58. self.trigger("valueChanged", { oldValue: self.value, value: self.element.val(), event: e});
  59. self.value = self.element.val();
  60. }
  61. },
  62. focus: function () {
  63. this.element.focus();
  64. },
  65. val: function () {
  66. return this.element.val();
  67. }
  68. });
  69. s2.ResultList = util.clazz(util.Observable, {
  70. construct: function (opts) {
  71. assert.isNotNull(opts, "opts argument must be set");
  72. assert.isElement(opts.select, "opts.select must point to the select element");
  73. this.super();
  74. this.opts = opts;
  75. this.tag = util.tag();
  76. this.queryParams = {};
  77. },
  78. render: function () {
  79. return new util.Markup("<div class='s2-results' id='", this.tag, "'></div>");
  80. },
  81. bind: function (container) {
  82. var self = this;
  83. this.container = container;
  84. this.element = container.find("#" + this.tag);
  85. assert.isElement(this.element, "Could not find result list element");
  86. this.container.attr("tabindex", "0");
  87. this.container.on("keydown", function (e) {
  88. self.onKeyDown(e);
  89. });
  90. this.container.on("focusout", function (e) {
  91. self.onBlur(e);
  92. });
  93. this.element.on("click", function () {
  94. self.onClick.apply(self, arguments);
  95. });
  96. //util.detectPlatform(this.element);
  97. },
  98. show: function () {
  99. var self = this;
  100. self.update();
  101. },
  102. update: function () {
  103. var self = this;
  104. var index = 0;
  105. self.data = [];
  106. self.element.find(".s2-options").remove();
  107. var options = $("<ul class='s2-options'></ul>");
  108. self.element.append(options);
  109. $.each(self.query(), function () {
  110. var option = $(["<li class='s2-option' data-s2-index='" + index, "'>", this.text, "</li>"].join(""));
  111. options.append(option);
  112. self.data.push(this);
  113. index++;
  114. });
  115. options.find("li").first().addClass("s2-highlighted");
  116. },
  117. query: function () {
  118. return this.opts.data.query(this.queryParams);
  119. },
  120. onClick: function (event) {
  121. var target = $(event.target);
  122. var option = target.is(".s2-option") ? target : target.parents(".s2-option").first();
  123. if (option.length > 0) {
  124. // option clicked
  125. this.trigger("select", { event: event, element: option, data: this.data[option.data("s2-index")] });
  126. }
  127. },
  128. focus: function () {
  129. var self = this;
  130. this.container.focus();
  131. },
  132. onBlur: function (event) {
  133. var self = this;
  134. window.setTimeout(function () {
  135. // done in a time out because we want the current focusout event processed so that
  136. // document.activeElement points to element that received the new focus
  137. //console.log("blur event", event);
  138. //console.log("blur container", self.container.get(0));
  139. //console.log("blur active", document.activeElement);
  140. //console.log("blur contains", $.contains(self.container.get(0), document.activeElement));
  141. if (!$.contains(self.container.get(0), document.activeElement) && self.container.get(0) !== document.activeElement) {
  142. self.trigger("close", {event: event});
  143. }
  144. }, 0);
  145. },
  146. onKeyDown: function (event) {
  147. if (event.which == util.key.DOWN) {
  148. this.moveHighlight({delta: 1, event: event});
  149. event.preventDefault();
  150. } else if (event.which === util.key.UP) {
  151. this.moveHighlight({delta: -1, event: event});
  152. event.preventDefault();
  153. } else if (event.which === util.key.ENTER) {
  154. this.selectHighlighted({event: event});
  155. event.preventDefault();
  156. }
  157. },
  158. selectHighlighted: function (param) {
  159. var option = this.element.find(".s2-highlighted").first();
  160. this.trigger("select", { event: param.event, element: option, data: this.data[option.data("s2-index")] });
  161. },
  162. moveHighlight: function (param) {
  163. var delta = param.delta;
  164. var current = this.element.find(".s2-highlighted");
  165. var next = null;
  166. if (delta === 1) {
  167. next = current.next();
  168. } else {
  169. next = current.prev();
  170. }
  171. current.removeClass("s2-highlighted");
  172. next.addClass("s2-highlighted");
  173. }
  174. });
  175. s2.ResultListWithSearch = util.clazz(Object, {
  176. render: function () {
  177. this.searchTag = util.tag();
  178. var markup = new util.Markup(
  179. "<div class='s2-search'>", //
  180. " <input type='text' id='", this.searchTag, "'/>", //
  181. " <a href='#' class='s2-test'>click me</a>", //
  182. " {{original}}", //
  183. "</div>");
  184. markup.replace("original", this.decorated());
  185. return markup;
  186. },
  187. bind: function (container) {
  188. this.decorated(container);
  189. var self = this;
  190. this.searchField = new s2.SearchField(container.find("#" + this.searchTag));
  191. this.searchField.on("valueChanged", function (params) {
  192. self.onSearch.apply(self, arguments);
  193. });
  194. },
  195. focus: function () {
  196. this.searchField.focus();
  197. },
  198. onSearch: function (params) {
  199. this.delegate.queryParams.term = this.searchField.val();
  200. this.delegate.update();
  201. }
  202. });
  203. })(jQuery, document, window);