PageRenderTime 46ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/scripts/Works.js

https://bitbucket.org/aldaviva/portfolio
JavaScript | 242 lines | 211 code | 30 blank | 1 comment | 18 complexity | 7d4b103009428c6ca5d849d9ce49ab31 MD5 | raw file
  1. window.Works = function(){
  2. _.extend(this, Backbone.Events);
  3. this.models = {
  4. Piece: Backbone.Model.extend({
  5. defaults: {
  6. selected: false,
  7. index: -1
  8. }
  9. })
  10. };
  11. this.views = {
  12. listPanel: Backbone.View.extend({
  13. tagName: "li",
  14. initialize: function(options){
  15. _.bindAll(this, "render");
  16. this.model.bind('change', this.render);
  17. },
  18. events: {
  19. 'click .thumb': 'onThumbClick'
  20. },
  21. render: function(){
  22. $(this.el).html(this.template(this.model.toJSON()));
  23. this.$('.year').toggle(this.options.showYear);
  24. $(this.el).toggleClass("selected", this.model.get("selected"));
  25. return this;
  26. },
  27. onThumbClick: function(){
  28. window.location.hash = '#'+this.model.id;
  29. }
  30. }),
  31. selectedItemPanel: Backbone.View.extend({
  32. render: function(){
  33. $(this.el).html(this.template(this.model.toJSON()));
  34. if(this.model.get('link')){
  35. this.$('img').wrap("<a href='"+this.model.get('link')+"' target='_blank' />");
  36. }
  37. var previouslySelected = this.model.collection.find(function(item){
  38. return item.get("selected");
  39. });
  40. if(previouslySelected){
  41. previouslySelected.set({selected: false});
  42. }
  43. this.model.set({selected: true});
  44. return this;
  45. }
  46. })
  47. };
  48. this.initialize = function(){
  49. this.setUpTemplates();
  50. var pieces = this.pieces = new Backbone.Collection();
  51. pieces.url = 'portfolio/data/portfolio.json';
  52. pieces.model = this.models.Piece;
  53. pieces.comparator = function(piece){
  54. return -1 * piece.get("year")
  55. }
  56. pieces.bind('refresh', _.bind(function(){
  57. this.setUpList();
  58. this.setUpSelectedItem();
  59. this.setUpController();
  60. this.setUpKeyboardShortcuts();
  61. this.trigger('refresh');
  62. }, this));
  63. pieces.fetch();
  64. };
  65. this.setUpList = function(){
  66. var listPane = $('#listPanel');
  67. var lastYear;
  68. this.pieces.each(function(item, index){
  69. item.set({'index': index});
  70. var view = new this.views.listPanel({
  71. model: item,
  72. showYear: item.get("year") != lastYear,
  73. id: "listItem-" + item.id
  74. });
  75. listPane.append(view.render().el);
  76. lastYear = item.get("year");
  77. }, this);
  78. this.setUpListScrolling(listPane);
  79. };
  80. this.setUpSelectedItem = function(){
  81. var selectedItemPane = $('#selectedItemPanel');
  82. var item = this.pieces.first();
  83. this.selectedItemView = new this.views.selectedItemPanel({
  84. model: item
  85. });
  86. selectedItemPane.empty().append(this.selectedItemView.render().el);
  87. };
  88. this.setUpController = function(){
  89. this.controller = new Backbone.Controller();
  90. this.controller.route(":pieceId", "changeSelectedPiece", _.bind(function(pieceId){
  91. var piece = this.pieces.get(pieceId);
  92. if(typeof piece != "undefined"){
  93. this.selectedItemView.model = piece;
  94. }
  95. this.selectedItemView.render();
  96. this.preloadPiece(this.getPieceByOffset(1));
  97. window.scrollTo(0,0);
  98. }, this));
  99. Backbone.history.start();
  100. };
  101. this.setUpKeyboardShortcuts = function(){
  102. $(document).keydown(_.bind(function(event){
  103. var piece = null
  104. switch(event.which){
  105. case 39: //Right arrow key
  106. piece = this.getPieceByOffset(1);
  107. break;
  108. case 37: //Left arrow key
  109. piece = this.getPieceByOffset(-1);
  110. break;
  111. case 36: //Home
  112. piece = this.getPieceByIndex(0);
  113. break;
  114. case 35: //End
  115. piece = this.getPieceByIndex(this.pieces.length - 1);
  116. break;
  117. }
  118. if(piece){
  119. this.goToPiece(piece);
  120. event.preventDefault();
  121. _.defer(this.scrollIfNecessary);
  122. }
  123. }, this));
  124. };
  125. this.getPieceByOffset = function(offset){
  126. var currentIndex = this.selectedItemView.model.get('index');
  127. var desiredIndex = currentIndex + offset;
  128. return this.getPieceByIndex(desiredIndex);
  129. };
  130. this.getPieceByIndex = function(index){
  131. return this.pieces.find(function(piece){
  132. return piece.get("index") == index;
  133. });
  134. };
  135. this.goToPiece = function(piece){
  136. window.location.hash = piece.id;
  137. };
  138. this.preloadPiece = function(piece){
  139. if(piece){
  140. var domId = "preload";
  141. var preloadContainer = $('#'+domId);
  142. if(!preloadContainer.length){
  143. preloadContainer = $("<div />").attr({id: domId}).css({'position': 'absolute', 'width': '1px', 'height': '1px', 'top': '0px', 'opacity': '0'});
  144. $(document.body).append(preloadContainer);
  145. }
  146. preloadContainer.css('background-image', 'url("portfolio/artwork/'+piece.get('src')+'")');
  147. }
  148. };
  149. this.setUpTemplates = function(){
  150. var views = this.views;
  151. $('.template').each(function(index, element){
  152. element = $(element);
  153. views[element.parent()[0].id].prototype.template = _.template(decodeURIComponent(element.remove().html()));
  154. });
  155. };
  156. this.scrollIfNecessary = function(){
  157. var listPanel = $('#listPanel');
  158. var activeListItem = listPanel.find('li.selected');
  159. var listItemWidth = activeListItem.width();
  160. var listItemGutter = window.parseInt(activeListItem.css('margin-right'), 10);
  161. var isActiveItemPastLeftEdge = (activeListItem[0].offsetLeft - listItemGutter < listPanel[0].scrollLeft);
  162. var isActiveItemPastRightEdge = (activeListItem[0].offsetLeft + listItemWidth + listItemGutter > listPanel[0].offsetWidth + listPanel[0].scrollLeft);
  163. var newScrollLeft = null;
  164. if(isActiveItemPastLeftEdge){
  165. console.log("active item is past left edge.");
  166. newScrollLeft = activeListItem[0].offsetLeft - listItemGutter /*- listPanel[0].offsetWidth*/;
  167. } else if(isActiveItemPastRightEdge){
  168. console.log("active item is past right edge");
  169. newScrollLeft = activeListItem[0].offsetLeft + listItemWidth + listItemGutter - listPanel[0].offsetWidth;
  170. } else {
  171. console.log("active item is visible");
  172. }
  173. if(newScrollLeft != null){
  174. listPanel.animate({
  175. scrollLeft: newScrollLeft
  176. }, 150);
  177. }
  178. };
  179. this.setUpListScrolling = function(listPane){
  180. var isMouseDown = false;
  181. var wasScrolledSinceMouseDown = false;
  182. var mouseDownX = 0;
  183. var mouseDownPanelScrollOffset = 0;
  184. listPane.bind('mousedown', function(event){
  185. isMouseDown = true;
  186. wasScrolledSinceMouseDown = false;
  187. mouseDownX = event.clientX;
  188. mouseDownPanelScrollOffset = listPane[0].scrollLeft;
  189. });
  190. var body = $('body');
  191. body.bind('mouseup click', function(event){
  192. if(wasScrolledSinceMouseDown){
  193. //alert('trying to prevent default');
  194. event.preventDefault();
  195. wasScrolledSinceMouseDown = false;
  196. }
  197. isMouseDown = false;
  198. });
  199. body.bind('mousemove', function(event){
  200. if(isMouseDown){
  201. wasScrolledSinceMouseDown = true;
  202. var offsetFromMouseDown = event.clientX - mouseDownX;
  203. event.target.scrollLeft = mouseDownPanelScrollOffset - offsetFromMouseDown;
  204. }
  205. });
  206. listPane.bind('mousewheel DOMMouseScroll', function(event){
  207. event.preventDefault();
  208. listPane[0].scrollLeft -= 30 * ((((event.wheelDelta || event.detail) > 0) ^ $.browser.mozilla) ? 1 : -1);
  209. });
  210. };
  211. this.initialize();
  212. };