ws-ui-parts.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. "use strict";
  2. (function($) {
  3. $(document).ready(function() {
  4. console.log('ws: init UI parts');
  5. /**
  6. * Initialize an empty object to be populated as follows:
  7. * - key is an UI element's id
  8. * - value associated is an obj containing: tmpl (the template) and $elem (jQueried target element)
  9. */
  10. _ws.ui = {};
  11. /**
  12. * Generic template-based rendering function
  13. */
  14. function viewDefaultRender(data) {
  15. if(! data) {
  16. console.log('WARNING! You should provide data for #' + elemId + "'s render()");
  17. }
  18. this.$elem.empty();
  19. this.$elem.html( Mustache.render( this.tmpl, data ) );
  20. this.$elem.show();
  21. this.bindEvents();
  22. }
  23. /**
  24. * Wrapper around provided render function (show elem after render)
  25. */
  26. function viewRenderWrapper(data) {
  27. this._render(data);
  28. this.$elem.show();
  29. }
  30. /**
  31. * Bind events
  32. */
  33. function viewBindEvents() {
  34. var events = this.props.events;
  35. for(var descriptor in events) {
  36. var handler = events[descriptor];
  37. var bits = descriptor.split(' ');
  38. var evtName = bits.shift();
  39. var selector = bits.join(' ');
  40. var target = selector === '' ? this.$elem : this.$elem.find(selector);
  41. console.log('#### bind', descriptor, 'e:' + evtName, 's:[' + selector + '], target:', target);
  42. target.on(evtName, handler.bind(this));
  43. }
  44. }
  45. /**
  46. * Bind events: nop
  47. */
  48. function viewBindEventsNop() {
  49. console.log(this.partName, 'bindEvents:nop');
  50. }
  51. /**
  52. * Show view element
  53. */
  54. function viewElemShow() {
  55. this.$elem.show();
  56. }
  57. /**
  58. * Hide view element
  59. */
  60. function hideElemShow() {
  61. this.$elem.hide();
  62. }
  63. /**
  64. * Build a view
  65. */
  66. _ws.makeView = function(elemId, props) {
  67. console.log('** makeView', elemId);
  68. var v = {};
  69. v.props = props || {};
  70. v.$elem = $('#' + elemId);
  71. v.partName = _.camelCase(elemId);
  72. console.log('adding', elemId, v.partName);
  73. _ws.ui[v.partName] = v;
  74. // Bind the provided render function
  75. if(v.props.render) {
  76. v._render = props.render.bind(v);
  77. v.render = viewRenderWrapper.bind(v);
  78. }
  79. // Otherwise assign the default render function
  80. else {
  81. var $tmplEl = $('script[data-tmpl-for="' + elemId + '"]');
  82. v.tmpl = $tmplEl.html();
  83. v.render = viewDefaultRender.bind(v);
  84. }
  85. // Set event handlers
  86. if(v.props.events) {
  87. v.bindEvents = viewBindEvents.bind(v);
  88. v.bindEvents();
  89. }
  90. else {
  91. v.bindEvents = viewBindEventsNop.bind(v);
  92. }
  93. // Pass arbitrary properties
  94. for(var p in props) {
  95. if(['render', 'events'].indexOf(p) !== -1) {
  96. // console.log('pass props: ignore', p);
  97. continue;
  98. }
  99. v[p] = props[p];
  100. console.log('pass props: added', p, v[p]);
  101. }
  102. v.show = viewElemShow.bind(v);
  103. v.hide = hideElemShow.bind(v);
  104. };
  105. });
  106. })(jQuery);