Browse by Game as an Extension (Custom Module)

Jira Code: IBT-37

The browse by game section displays a list of games (custom record) which are fetched from NS and displayed in the website using the facet view of sca. When clicked any one of the game it will take us to another page with info and related products.

//Configuration

{
  "type": "object",

  "group": {
    "id": "browseByGame",
    "title": "Browse By Game",
    "description": "Browse By Game"
  },

  "subtab": {
    "id": "gamesResultDisplayOptions",
    "title": "Result Display Options",
    "description": "Result Display Options",
    "group": "browseByGame"
  },

  "properties": {

    "gamesDisplayOptions": {
      "group": "browseByGame",
      "subtab": "gamesResultDisplayOptions",
      "type": "array",
      "title": "Desktop",
      "description": "Available views for Browse By Game by selecting the templates",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "title": "id",
            "description": "The id for this display option",
            "mandatory": true
          },
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Label to use in the UI to reference this sort option.",
            "translate": true,
            "mandatory": true
          },
          "template": {
            "type": "string",
            "title": "template",
            "enum": ["browse_by_game_game.tpl", "browse_by_game_game_list_view_cell.tpl"],
            "description": "Template to use in the results of this option",
            "mandatory": true
          },
          "columns": {
            "type": "integer",
            "title": "columns",
            "description": "Number of columns to show in this result list",
            "mandatory": true
          },
          "icon": {
            "type": "string",
            "title": "icon",
            "description": "Icon to use in the UI for this option"
          },
          "isDefault": {
            "type": "boolean",
            "title": "Is default ?",
            "description": "Is default ? "
          }
        }
      },

      "default":[
        {
          "id": "list",
          "name": "List",
          "template": "browse_by_game_game_list_view_cell.tpl",
          "columns": 1,
          "icon": "icon-display-list"
        },
        {
          "id": "grid",
          "name": "Grid",
          "template": "browse_by_game_game.tpl",
          "columns": 4,
          "icon": "icon-display-grid",
          "isDefault": true
        }
      ]
    },
    "gamesDisplayOptionsPhone": {
      "group": "browseByGame",
      "subtab": "gamesResultDisplayOptions",
      "type": "array",
      "title": "Phone",
      "description": "Available views for Browse By Game by selecting the templates",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "title": "id",
            "description": "The id for this display option",
            "mandatory": true
          },
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Label to use in the UI to reference this sort option.",
            "translate": true,
            "mandatory": true
          },
          "template": {
            "type": "string",
            "title": "template",
            "enum": ["browse_by_game_game.tpl", "browse_by_game_game_list_view_cell.tpl"],
            "description": "Template to use in the results of this option",
            "mandatory": true
          },
          "columns": {
            "type": "integer",
            "title": "columns",
            "description": "Number of columns to show in this result list",
            "mandatory": true
          },
          "icon": {
            "type": "string",
            "title": "icon",
            "description": "Icon to use in the UI for this option"
          },
          "isDefault": {
            "type": "boolean",
            "title": "Is default ?",
            "description": "Is default ? "
          }
        }
      },

      "default":[
        {
          "id": "list",
          "name": "List",
          "template": "browse_by_game_game_list_view_cell.tpl",
          "columns": 1,
          "icon": "icon-display-list"
        },
        {
          "id": "grid",
          "name": "Grid",
          "template": "browse_by_game_game.tpl",
          "columns": 2,
          "icon": "icon-display-grid",
          "isDefault": true
        }
      ]
    },
    "gamesDisplayOptionsTablet": {
      "group": "browseByGame",
      "subtab": "gamesResultDisplayOptions",
      "type": "array",
      "title": "Tablet",
      "description": "Available views for Browse By Game by selecting the templates",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "title": "id",
            "description": "The id for this display option",
            "mandatory": true
          },
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Label to use in the UI to reference this sort option.",
            "translate": true,
            "mandatory": true
          },
          "template": {
            "type": "string",
            "title": "template",
            "enum": ["browse_by_game_game.tpl", "browse_by_game_game_list_view_cell.tpl"],
            "description": "Template to use in the results of this option",
            "mandatory": true
          },
          "columns": {
            "type": "integer",
            "title": "columns",
            "description": "Number of columns to show in this result list",
            "mandatory": true
          },
          "icon": {
            "type": "string",
            "title": "icon",
            "description": "Icon to use in the UI for this option"
          },
          "isDefault": {
            "type": "boolean",
            "title": "Is default ?",
            "description": "Is default ? "
          }
        }
      },

      "default":[
        {
          "id": "list",
          "name": "List",
          "template": "browse_by_game_game_list_view_cell.tpl",
          "columns": 1,
          "icon": "icon-display-list"
        },
        {
          "id": "grid",
          "name": "Grid",
          "template": "browse_by_game_game.tpl",
          "columns": 3,
          "icon": "icon-display-grid",
          "isDefault": true
        }
      ]
    }
  }
}
//JS

define(
    'BrowseByGame.Collection'
,   [
        'BrowseByGame.Model'
    ,   'Backbone.CachedCollection'
    ,	'underscore'
    ,	'Utils'
    ]
,   function BrowseByGameCollection (
        BrowseByGameModel
    ,   BackboneCachedCollection
    ,	_
    ,	Utils
    )
{
	'use strict';

    return BackboneCachedCollection.extend({
        url: function url () {
            return Utils.getAbsoluteUrl(getExtensionAssetsPath('services/BrowseByGame.Service.ss'));
        }

    ,   parse: function parse (response) {
            var games;

            games = response.records;

            this.page = parseInt(response.page, 10);
            this.recordsPerPage = parseInt(response.recordsPerPage, 10);
            this.totalRecordsFound = parseInt(response.totalRecordsFound, 10);

            return games || response;
        }

    ,   model: BrowseByGameModel
    });

});
//JS

define(
    'BrowseByGame.Game.Detailed.View'
,   [
        'BrowseByGame.Search.View'
    ,   'BrowseByGame.Collection'
    ,   'BrowseByGame.Items.Collection'
    ,   'Item.Model'
    ,   'Facets.ItemCell.View'

    ,   'browse_by_game_game_detailed.tpl'
    ,   'facets_item_cell_grid.tpl'
    ,	'facets_items_collection.tpl'
    ,	'facets_items_collection_view_cell.tpl'
    ,	'facets_items_collection_view_row.tpl'

    ,   'Backbone.CollectionView'
    ,   'AjaxRequestsKiller'
    ,   'Backbone'
    ,   'underscore'
    ,   'Utils'
    ]
,   function BrowseByGameGameDetailedView (
        BrowseByGameSearchView
    ,   BrowseByGameCollection
    ,   ItemCollection
    ,   ItemModel
    ,   FacetsItemCellView

    ,   browse_by_game_game_detailed_tpl
    ,   facets_item_cell_grid_tpl
    ,   facets_items_collection_tpl
    ,   facets_items_collection_view_cell_tpl
    ,   facets_items_collection_view_row_tpl

    ,   BackboneCollectionView
    ,   AjaxRequestsKiller
    ,   Backbone
    ,   _
) {
    'use strict';

    return Backbone.View.extend({
        template: browse_by_game_game_detailed_tpl

    ,   initialize: function initialize () {
            this.model = this.options.model;
            this.application = this.options.application;
            this.isLoading = true;

            this.items = [];
            this.organizationItems = [];
            this.componentsItems = [];
            this.accessoriesItems = [];
            this.otherItems = [];
            this.collectionPromise = new BrowseByGameCollection().fetch({
                data: {
                    paginate: 'F'
                }
            ,   killerId: AjaxRequestsKiller.getKillerId()
            });

            this.getGameItems();
        }

    ,   getTitle: function getTitle () {
            return this.model.get('name');
        }

    ,	getBreadcrumbPages: function () {
            return [
                {
                    text: _('Browse By Game').translate()
                ,	href: '/browse-by-game'
                }
            ,   {
                    text: this.model.get('name')
                ,   href: '/browse-by-game/' + this.model.get('id')
                }
            ]
        }

    ,   getGameItems: function getGameItems () {
            var itemIds
            ,   self = this;

            itemIds = _.pluck((this.model.get('items') || []), 'id').join(',');

            if (itemIds) {
                var itemCollection = new ItemCollection();

                itemCollection.ids = itemIds;

                itemCollection.fetch({
                    killerId: AjaxRequestsKiller.getKillerId()
                }).done(function done (response) {
                    self.items = response.items || [];

                    if (self.items.length) {
                        self.categorizeItems();
                    }

                    self.isLoading = false;
                    self.render();
                }).fail(function fail (e) {
                    console.log('error', e);

                    self.isLoading = false;
                    self.render();
                })
            } else {
                this.isLoading = false;
                this.render();
            }
        }

    ,   categorizeItems: function categorizeItems () {
            if (this.items.length) {
                _.each(this.items, function each (item) {
                    var itemModel
                    ,   productType;
                    itemModel = new ItemModel(item);

                    productType = itemModel.get('custitem_tbt_web_product_type');

                    if (productType) {
                        if (productType.toLowerCase() === 'organization') {
                            this.organizationItems.push(itemModel);
                        } else if (productType.toLowerCase() === 'components') {
                            this.componentsItems.push(itemModel);
                        } else if (productType.toLowerCase() === 'accessories') {
                            this.accessoriesItems.push(itemModel);
                        } else {
                            this.otherItems.push(itemModel);
                        }
                    } else {
                        this.otherItems.push(itemModel);
                    }
                }, this)
            }
        }

    ,   childViews: {
            'BrowseByGame.Search': function BrowseByGameSearch () {
                return new BrowseByGameSearchView({
                    collectionPromise: this.collectionPromise
                ,   application: this.application
                })
            }
        ,   'Component.Items.Collection': function ComponentItemsCollection () {
                return new BackboneCollectionView({
                    childTemplate: facets_item_cell_grid_tpl
                ,	childView: FacetsItemCellView
                ,	cellTemplate: facets_items_collection_view_cell_tpl
                ,	rowTemplate: facets_items_collection_view_row_tpl
                ,	template: facets_items_collection_tpl
                ,   viewsPerRow: 4
                ,	childViewOptions: {
                        application: this.application
                    ,   forceWebstoreName2: true
                    }
                ,	collection: this.componentsItems || []
                })
            }
        ,   'Organization.Items.Collection': function OrganizationItemsCollection () {
                return new BackboneCollectionView({
                    childTemplate: facets_item_cell_grid_tpl
                ,	childView: FacetsItemCellView
                ,	cellTemplate: facets_items_collection_view_cell_tpl
                ,	rowTemplate: facets_items_collection_view_row_tpl
                ,	template: facets_items_collection_tpl
                ,   viewsPerRow: 4
                ,	childViewOptions: {
                        application: this.application
                    ,   forceWebstoreName2: true
                    }
                ,	collection: this.organizationItems || []
                })
            }
        ,   'Accessories.Items.Collection': function AccessoriesItemsCollection () {
                return new BackboneCollectionView({
                    childTemplate: facets_item_cell_grid_tpl
                ,	cellTemplate: facets_items_collection_view_cell_tpl
                ,	rowTemplate: facets_items_collection_view_row_tpl
                ,	template: facets_items_collection_tpl
                ,	childView: FacetsItemCellView
                ,   viewsPerRow: 4
                ,	childViewOptions: {
                        application: this.application
                    ,   forceWebstoreName2: true
                    }
                ,	collection: this.accessoriesItems || []
                })
            }
        ,   'Others.Items.Collection': function OthersItemsCollection () {
                return new BackboneCollectionView({
                    childTemplate: facets_item_cell_grid_tpl
                ,	cellTemplate: facets_items_collection_view_cell_tpl
                ,	rowTemplate: facets_items_collection_view_row_tpl
                ,	template: facets_items_collection_tpl
                ,	childView: FacetsItemCellView
                ,   viewsPerRow: 4
                ,	childViewOptions: {
                        application: this.application
                    ,   forceWebstoreName2: true
                    }
                ,	collection: this.otherItems || []
                })
            }
        }

    ,   getContext: function getContext () {
            return {
                id: this.model.get('id')
            ,   name: this.model.get('name')
            ,   image: this.model.get('image')
            ,   age: this.model.get('age')
            ,   bbgUrl: this.model.get('bbgUrl')
            ,   players: this.model.get('players')
            ,   publishDate: this.model.get('publishDate')
            ,   publisher: this.model.get('publisher')
            ,   publisherUrl: this.model.get('publisherUrl')
            ,   time: this.model.get('time')
            ,   isLoading: this.isLoading
            ,   hasOrganizationItems: this.organizationItems.length > 0
            ,   hasComponentItems: this.componentsItems.length > 0
            ,   hasAccessoriesItems: this.accessoriesItems.length > 0
            ,   hasOtherItems: this.otherItems.length > 0
            };
        }
    });
});
//JS
define(
    'BrowseByGame.Game.View'
,   [
        'browse_by_game_game.tpl'

    ,   'Backbone'
    ,   'underscore'
    ,   'Utils'
    ]
,   function BrowseByGameGameView (
        browse_by_game_game_tpl

    ,   Backbone
    ,   _
    )
{
    'use strict';

    return Backbone.View.extend({
        template: browse_by_game_game_tpl

    ,   initialize: function initialize () {
            this.model = this.options.model;

            // Define data table view
            this.cellClass = this.options.cellClass || '';


        }

    ,	getBreadcrumbPages: function () {
            return {
                text: _('Credit Cards').translate()
                ,	href: '/creditcards'
            };
        }

    ,   getContext: function getContext () {
            return {
                name: this.model.get('name')
            ,   gameId: this.model.get('id')
            ,   imageSrc: this.model.get('image')
            ,   publisher: this.model.get('publisher')
            ,   publisherUrl: this.model.get('publisherUrl')
            ,   publishDate: this.model.get('publishDate')

            ,   cellClass: this.cellClass

            }
        }
    })
});
//JS
define(
    'BrowseByGame.Items.Collection'
,   [
        'Item.Collection'
    ,   'Profile.Model'
    ,   'Session'

    ,   'Backbone'
    ,   'underscore'
    ,   'Utils'
    ]
,   function BrowseByGameItemsCollection (
        ItemCollection
    ,   ProfileModel
    ,   Session

    ,   Backbone
    ,   _
    )
{
    'use strict';

    return ItemCollection.extend({
        url: function url () {
            var profile
            ,   apiUrl;

            profile = ProfileModel.getInstance();
            apiUrl = _.addParamsToUrl(
                profile.getSearchApiUrl()
            ,   _.extend({}, this.searchApiMasterOptions, Session.getSearchApiParams(), {
                    id: this.ids,
                    fieldset: 'search'
                })
            ,	profile.isAvoidingDoubleRedirect()
            );

            return apiUrl;
        }
    });
});
//JS
define(
    'BrowseByGame'
,	[
		'BrowseByGame.Router'
	]
,	function (
        BrowseByGameRouter
	)
{
	'use strict';

	return	{
	    mountToApp: function mountToApp (application) {
			return new BrowseByGameRouter(application);
		}
	};
});
//JS

define(
    'BrowseByGame.List.Wrapper.View'
,   [
        'browse_by_game_list_view_wrapper.tpl'

    ,   'Backbone'
    ,   'underscore'
    ,   'jQuery'
    ,   'Utils'
    ]
,   function BrowseByGameListWrapperView (
        browse_by_game_list_view_wrapper_tpl

    ,   Backbone
    ,   _
    ,   jQuery
    )
{
    'use strict';

    return Backbone.View.extend({
        template: browse_by_game_list_view_wrapper_tpl

    ,   initialize: function (options) {
            this.collection = options.collection;
            this.games = [];
            this.application = options.application;
            this.currentPage = 1;
            this.totalPages = Math.ceil(this.collection.totalRecordsFound / this.collection.recordsPerPage);
            this.isLoading = false;

            _.each(this.collection.models, function each (model) {
                this.games.push({
                    id: model.get('id')
                ,   name: model.get('name')
                ,   publisherUrl: model.get('publisherUrl')
                ,   publisher: model.get('publisher')
                ,   publishDate: model.get('publishDate')
                })
            }, this);

            jQuery(window).on('scroll.bbb', _.bind(this.handleScroll, this));
        }

    ,   handleScroll: function listenScroll () {
            if (this.isLoading) {
                return false;
            }

            var scrollTop = jQuery(document).scrollTop()
            ,   windowHeight = jQuery(window).height()
            ,   bodyHeight = jQuery(document).height() - windowHeight
            ,   scrollPercentage = (scrollTop / bodyHeight);

            if (scrollPercentage > 0.7) {
                this.getNextGames();
            }
        }

    ,   getNextGames: function getNextGames () {
            var self = this;

            if (this.currentPage === this.totalPages) {
                return;
            }

            this.isLoading = true;

            this.render();

            this.collection.fetch({
                data: {
                    paginate: 'T'
                ,   display: 'list'
                ,   resultsPerPage: 40
                ,   page: this.currentPage + 1
                }
            }).done(function done (data) {
                if (self.currentPage < self.totalPages) {
                    self.currentPage++;
                }

                self.games = _.union(self.games, data.records);
            }).always(function always () {
                self.isLoading = false;
                self.render();
            });
        }

    ,   destroy: function () {
            jQuery(window).off('scroll.bbb');
            this._destroy();
        }

    ,   getContext: function getContext () {
            return {
                games: this.games
            ,   isLoading: this.isLoading
            }
        }
    });
});
//JS
define(
    'BrowseByGame.Model'
,   [
        'Backbone'
    ,   'underscore'
    ,   'Utils'

    ]
,   function BrowseByGameModel (
        Backbone
    ,   _
    ,   Utils
    )
{
    'use strict';

    return Backbone.Model.extend({
        urlRoot: function urlRoot () {
            return Utils.getAbsoluteUrl(getExtensionAssetsPath('services/BrowseByGame.Service.ss'));
        }
    });
});
//JS
define(
    'BrowseByGame.Router'
,   [
        'BrowseByGame.View'
    ,   'BrowseByGame.Game.Detailed.View'
    ,   'BrowseByGame.Collection'
    ,   'BrowseByGame.Model'

    ,   'AjaxRequestsKiller'
    ,   'Backbone'
    ,   'Utils'
    ]
,   function BrowseByGameRouter (
        BrowseByGameView
    ,   BrowseByGameDetailedView
    ,   BrowseByGameCollection
    ,   BrowseByGameModel

    ,   AjaxRequestsKiller
    ,   Backbone
    ,   Utils
    )
{
    'use strict';

    return Backbone.Router.extend({
        routes: {
            'browse-by-game': 'browseByGame'
        ,   'browse-by-game?*options': 'browseByGame'
        ,   'browse-by-game/:id': 'browseGameDetail'
        }

    ,   initialize: function initialize(application) {
            this.application = application;
        }

    ,   browseByGame: function browseByGame (options) {
            var browseByGameView
            ,   browseByGameCollection
            ,   fetchData
            ,   self = this;

            browseByGameCollection = new BrowseByGameCollection();

            if (options) {
                options = Utils.parseUrlOptions(options);
            } else {
                options = { page: 1 };
            }

            fetchData = {
                paginate: 'T'
            ,   page: options.page
            };

            if (options && options.display && options.display === 'list') {
                fetchData.display = 'list';
                fetchData.resultsPerPage = 40;
            }

            browseByGameCollection.fetch({
                data: fetchData
            ,   killerId: AjaxRequestsKiller.getKillerId()
            }).done(function done () {
                browseByGameView = new BrowseByGameView({
                    application: self.application
                ,   collection: browseByGameCollection
                });

                browseByGameView.showContent();
            });
        }

    ,   browseGameDetail: function browseGameDetail (id) {
            var browseByGameModel
            ,   self = this;

            browseByGameModel = new BrowseByGameModel();

            browseByGameModel.fetch({
                data: {
                    internalid: id
                }
            ,   killerId: AjaxRequestsKiller.getKillerId()
            }).done(function done () {
                new BrowseByGameDetailedView({
                    application: self.application
                ,   model: browseByGameModel
                }).showContent();
            });
        }
    });
});
//JS
define(
    'BrowseByGame.Search.View'
,   [
        'browse_by_game_search.tpl'

    ,   'Backbone'
    ,   'underscore'
    ,   'jQuery'
    ]
,   function BrowseByGameSearchView (
        browse_by_game_search_tpl

    ,   Backbone
    ,   _
    ,   jQuery
    )
{
    'use strict';

    return Backbone.View.extend({
        template: browse_by_game_search_tpl

    ,   events: {
            'keyup .browse-by-game-search-box-input': 'filterGamesByName'
        ,   'click [data-type="games-search-reset"]': 'clearSearch'
        }

    ,   initialize: function initialize () {
            var self = this;

            this.games = [];
            this.filteredGames = [];
            this.clearSearch();

            this.options.collectionPromise.done(function done (games) {
                self.games = games.records || [];
                self.render();
            });
        }

    ,   filterGamesByName: function filterGamesByName (e) {
            e.preventDefault();

            var searchQuery;

            searchQuery = jQuery(e.currentTarget).val();

            if (!searchQuery) {
                return this.clearSearch();
            } else {
                this.$('.browse-by-game-search-search-icon').hide();
                this.$('[data-type="games-search-reset"]').show();
            }

            this.filteredGames = _.filter(this.games, function find (game) {
                return ~game.name.toLowerCase().indexOf(searchQuery.toLowerCase())
            }) || [];

            this.$('.browse-by-game-search-result').each(function each () {
                var $game;

                $game = jQuery(this);

                if (!~$game.data('name').toLowerCase().indexOf(searchQuery.toLowerCase())) {
                    $game.hide();
                } else {
                    $game.show();

                }
            })
        }

    ,   clearSearch: function clearSearch () {
            this.$('.browse-by-game-search-result').hide();
            this.$('[data-type="games-search-reset"]').hide();
            this.$('.browse-by-game-search-search-icon').show();
            this.$('.browse-by-game-search-box-input').val('');
        }

    ,   getContext: function getContext () {
        
            return {
                games: this.filteredGames.length > 0 || this.games
            }
        }
    })
});
//JS
define(
    'BrowseByGame.View'
,   [
        'BrowseByGame.Game.View'
    ,   'GlobalViews.Pagination.View'
    ,   'BrowseByGame.Collection'
    ,   'BrowseByGame.Search.View'
    ,   'BrowseByGame.List.Wrapper.View'

    ,	'SC.Configuration'

    ,   'browse_by_game.tpl'
    ,   'browse_by_game_game.tpl'
    ,   'browse_by_game_game_list_view_cell.tpl'
    ,   'browse_by_game_search_compact.tpl'
    ,   'browse_by_game_list_view_wrapper.tpl'
    ,	'backbone_collection_view_row.tpl'

    ,   'AjaxRequestsKiller'
    ,   'Backbone.CollectionView'
    ,   'Backbone'
    ,   'underscore'
    ,   'jQuery'
    ,   'Utils'
    ]
,   function BrowseByGameView (
        BrowseByGameGameView
    ,   GlobalViewsPaginationView
    ,   BrowseByGameCollection
    ,   BrowseByGameSearchView
    ,   BrowseByGameListWrapperView

    ,   Configuration

    ,   browse_by_game_tpl
    ,   browse_by_game_game_tpl
    ,   browse_by_game_game_list_view_cell_tpl
    ,   browse_by_game_search_compact_tpl
    ,   browse_by_game_list_view_wrapper_tpl

    ,	backbone_collection_view_row_tpl

    ,   AjaxRequestsKiller
    ,   BackboneCollectionView
    ,   Backbone
    ,   _
    ,   jQuery
    ,   Utils
    )
{
    'use strict';

    return Backbone.View.extend({
        template: browse_by_game_tpl

    ,   title: _('Browse By Game').translate()

    ,   events : {
            'click [data-display]': 'toggleListView'
        }

    ,   initialize: function initialize (options) {
            this.collection = options.collection;
            this.baseUrl = window.location.protocol + '//' + window.location.hostname + '/' + Backbone.history.fragment;
            this.queryOptions = Utils.parseUrlOptions(location.href);
            this.collectionPromise = new BrowseByGameCollection().fetch({
                data: {
                    paginate: 'F'
                }
            ,   killerId: AjaxRequestsKiller.getKillerId()
            });

            var self = this;

            var display_option_type = Utils.selectByViewportWidth({
                    phone: 'gamesDisplayOptionsPhone'
                ,	tablet: 'gamesDisplayOptionsTablet'
                ,	desktop: 'gamesDisplayOptions'
                }, 'gamesDisplayOptions')
            ,   display_option = _.find(this.options.application.getConfig(display_option_type), function (option) {
                    return option.id === (SC.Utils.getParameterByName(document.URL, 'display') || 'grid');
                });

            this.on('afterViewRender', function() {
                if (display_option.id === 'list') {
                    jQuery(window).off('resize.bbg');
                } else {
                    jQuery(window).on('resize.bbg', jQuery.proxy(self.onResizeThrottled, self));
                }
            });
        }

    ,   onResizeThrottled: _.throttle(function() {
            if(window.currentDevice != SC.Utils.getDeviceType()) {
                window.currentDevice = SC.Utils.getDeviceType();
                this.showContent(true);
            }

        }, 100)

    ,   destroy: function destroy () {
            jQuery(window).off('resize.bbg');

            this._destroy();
        }

    ,	getBreadcrumbPages: function () {
            return {
                text: _('Browse By Game').translate()
            ,	href: '/browse-by-game'
            };
        }

    ,   render: function render () {
            this.updateCannonicalLinks();

            this._render();
        }

    ,   updateCannonicalLinks: function updateCannonicalLinks () {
            var $head
            ,   previousPage
            ,   nextPage;

            $head = jQuery('head');
            previousPage = this.getRelPrev();
            nextPage = this.getRelNext();

            $head.find('link[rel="next"], link[rel="prev"]').remove();

            if (previousPage) {
                jQuery('<link/>', {
                    rel: 'prev'
                ,	href: previousPage
                }).appendTo($head);
            }

            if (nextPage) {
                jQuery('<link/>', {
                    rel: 'next'
                ,	href: nextPage
                }).appendTo($head);
            }
        }

    ,   getRelPrev: function getRelPrev () {
            var currentPage;

            currentPage = this.queryOptions && parseInt(this.queryOptions.page, 10) || 1;

            if (currentPage > 1) {
                if (currentPage === 2) {
                    return this.baseUrl;
                }

                if (currentPage > 2) {
                    return this.baseUrl + '?page=' + (currentPage - 1);
                }
            }

            return null;
        }

    ,	getRelNext: function getRelNext () {
            var currentPage;

            currentPage = this.queryOptions && parseInt(this.queryOptions.page, 10) || 1;

            if (currentPage < this.collection.totalRecordsFound) {
                var next;

                next = this.baseUrl += '?page='+ (currentPage + 1);

                return next;
            }

            return null;
        }

    ,   childViews: {
            'BrowseByGame.Collection': function BrowseByGameCollection () {
                var display_option_type = Utils.selectByViewportWidth({
                        phone: 'gamesDisplayOptionsPhone'
                    ,	tablet: 'gamesDisplayOptionsTablet'
                    ,	desktop: 'gamesDisplayOptions'
                    }, 'gamesDisplayOptions')
                ,   display_option = _.find(this.options.application.getConfig(display_option_type), function (option) {
                        return option.id === (SC.Utils.getParameterByName(document.URL, 'display') || 'grid');
                    });

                if (display_option.id === 'list') {
                    return new BrowseByGameListWrapperView({
                        collection: this.collection
                    ,   application: this.options.application
                    })
                } else {
                    return new BackboneCollectionView({
                        childView: BrowseByGameGameView
                    ,	childViewOptions: {
                            cellClass: display_option.id
                        }
                    ,	childTemplate: display_option.template
                    ,	rowTemplate: backbone_collection_view_row_tpl
                    ,   viewsPerRow: display_option.columns
                    ,   collection: this.collection
                    });
                }
            }

        ,   'GlobalViews.Pagination': function GlobalViewsPagination () {
                return new GlobalViewsPaginationView({
                    totalPages: Math.ceil(this.collection.totalRecordsFound / this.collection.recordsPerPage)
                }, Configuration.defaultPaginationSettings);
            }

        ,   'BrowseByGame.Search': function BrowseByGameSearch () {
                return new BrowseByGameSearchView({
                    collectionPromise: this.collectionPromise
                ,   application: this.application
                })
            }
        }

    ,   getContext: function getContext () {
            var display_option_type = Utils.selectByViewportWidth({
                phone: 'gamesDisplayOptionsPhone'
            ,	tablet: 'gamesDisplayOptionsTablet'
            ,	desktop: 'gamesDisplayOptions'
            }, 'gamesDisplayOptions')
            ,   display_option = _.find(this.options.application.getConfig(display_option_type), function (option) {
                    return option.id === (SC.Utils.getParameterByName(document.URL, 'display') || 'grid');
                })
            ,   isNotListView = display_option.id !== 'list';

            return {
                isNotListView: isNotListView
            }
        }
    });
});
//SASS
.browse-by-game-game-detailed-container {
    @extend .container;

    margin-top: 15px;
}

.browse-by-game-game-detailed-left-sidebar {
    @extend .col-md-3;

    display: none;

    @media (min-width: $screen-md-min) {
        display: block;
    }
}

.browse-by-game-game-detailed {
    @extend .col-xs-12;
    @extend .col-md-9;

    a:hover {
        color: #252a30;
    }
    
}

.browse-by-game-game-detailed-header {
    @extend .row;
}

.browse-by-game-game-detailed-header-image-container {
    @extend .col-xs-3;
}

.browse-by-game-game-detailed-header-details {
    @extend .col-xs-9;
}

.browse-by-game-game-detailed-header-details-title {
    text-align: center;

    h1 {
        font-weight: 300;
        text-transform: uppercase;
        font-size: 28px;
        line-height: 28px;
    }
}

.browse-by-game-game-detailed-header-details-specs {
    margin-top: $sc-medium-margin;
}

.browse-by-game-game-detailed-header-details-specs-spec {
    margin-top: $sc-small-margin;
}

.browse-by-game-game-detailed-header-details-specs-game-play {
    @extend .clearfix;
}

.browse-by-game-game-detailed-header-details-specs-game-play-time,
.browse-by-game-game-detailed-header-details-specs-game-play-players,
.browse-by-game-game-detailed-header-details-specs-game-play-ages {
    float: left;
    height: 65px;
    background: #ececec;
    font-size: 11px;
    text-align: center;
    width: 120px;
    padding: 6px;

    i {
        font-size: 35px;
        display: block;
    }
}

.browse-by-game-game-detailed-header-details-specs-game-play-time-icon {
    @extend .icon-clock;
}

.browse-by-game-game-detailed-header-details-specs-game-play-players-icon {
    @extend .icon-users;
}

.browse-by-game-game-detailed-header-details-specs-game-play-ages-icon {
    @extend .icon-plus;
}

.browse-by-game-game-detailed-loading-message {
    margin-top: $sc-medium-margin;
    text-align: center;
}

.browse-by-game-game-detailed-items {
    margin-top: $sc-large-margin;

    [class^="facets-items-collection-view-cell-"] {
        height: 316px;
        max-height: 316px;
    }

    .facets-item-cell-grid-image {
        max-height: 100px;
    }
}

.browse-by-game-game-detailed-items-categories-title {
    border-bottom: 1px solid black;
    margin-bottom: 10px;

    h2 {
        font-weight: 300;
        text-transform: uppercase;
        font-size: 28px;
        line-height: 38px;
    }
}
//SASS

.browse-by-game-list-view-wrapper-table {
    @extend .table;
    @extend .table-striped;
}

.browse-by-game-list-view-wrapper-loader {
    text-align: center;
    height: 80px;
    margin-bottom: 20px;
}
//SASS

.browse-by-game-game-container {
    margin-top: $sc-small-margin;
    text-align: center;

    a:hover {
        color: #252a30;
    }

    @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
        margin-top: 0;

        &:nth-child(1n+4) {
            margin-top: $sc-small-margin;
        }
    }

    @media (min-width: $screen-md-min) {
        margin-top: 0;

        &:nth-child(1n+5) {
            margin-top: $sc-small-margin;
        }
    }
}

.browse-by-game-game-container-grid{

}

.browse-by-game-game-container-table{

}

.browse-by-game-game-container-list{
    padding: 15px;

    .browse-by-game-game-image{
        @extend .col-xs-4;
        @extend .col-md-3;
        text-align: center;
    }

    .browse-by-game-game-detail{
        @extend .col-xs-8;
        @extend .col-md-9;

        .browse-by-game-game-link-name{
            font-weight: 300;
            text-transform: uppercase;
            font-size: 16px;
            line-height: 24px;
            height: auto;
            
            @media (min-width: $screen-sm-min) {
                font-size: 26px;
                line-height: 28px;
                height: 70px;
            }
        }
    }

    a:hover{
        color: #252a30;
    }
}


.browse-by-game-game-link {
    display: block;
    text-align: center;

    .browse-by-game-game-container-list & {
        text-align: left;
    }
}

.browse-by-game-game-link-image {
    max-height: 175px;
    height: 175px;

    .browse-by-game-game-container-list & {
        height: auto;
    }

    img {
        max-height: 175px;
    }
}

.browse-by-game-game-link-name {
    max-height: 70px;
    height: 70px;
}

.browse-by-game-search-box-title {
    padding-bottom: 10px;

    h2 {
       display: none;
        font-family: 'Roboto Condensed', Helvetica, Times New Roman, sans-serif;
    @media (min-width: $screen-md-min) {
        font-weight: normal;
        text-align: left;
        display: block;
        padding: $sc-base-padding * 3;
        margin-top: 0;
        padding: 12px 20px;
        font-size: 18px;
        text-transform: uppercase;
        color: #ffb400 !important;
        background: #252a2f;
    }
    }
}

.browse-by-game-search-results {
    padding: 10px 0;

    .browse-by-game-search-compact & {
        position: absolute;
        z-index: 100;
        width: 100%;
        padding-top: 0;
    }
}

.browse-by-game-search-result {
  color: #252a2f;
    font-size: 14px;
    text-transform: uppercase;
    position: relative;
    display: block;
    padding: 10px 15px;
    background-color: #fff;
    border: 1px solid #ddd;

    &:not(:last-child) {
        margin-bottom: -1px;
    }
    display: none;
}

    

//SASS

.browse-by-game {
    @extend .container;

    margin-top: 15px;

    a:hover {
        color: #252a30;
    }
}

.browse-by-game-pagination-container,
.browse-by-game-collection {
    @extend .clearfix;
}

.browse-by-game-search-compact {
    width: 100%;
    display: block;
    margin-top: -25px;
    margin-bottom: 25px;
    float: left;

    &.browse-by-game-search-compact-list {
        margin-top: 10px;
        margin-bottom: 30px;
    }

    @media (min-width: $screen-sm-min) {
        width: 40%;
        margin: 0;

        &.browse-by-game-search-compact-list {
            margin-top: 0;
            margin-bottom: 30px;
        }
    }
}

.browse-by-game-pagination {
    @extend .panel;
    @extend .panel-smart;

    padding: 0 !important;
    float: right;
    margin-bottom: $sc-large-margin;
}

.browse-by-game-display-view{
    @extend .pull-right;

    margin-right: 5px;

    .facets-item-list-display-selector  {
        margin-right: 5px;
        display: inline-block;
    }
}

.browse-by-game-collection {

    .backbone-collection-view-cell-span2 {
        @extend .col-sm-2;
        @extend .col-xs-6;
    }

    .backbone-collection-view-cell-span3 {
        @extend .col-sm-3;
        @extend .col-xs-6;
    }

    .backbone-collection-view-cell-span4 {
        @extend .col-sm-4;
        @extend .col-xs-6;
    }

    .backbone-collection-view-cell-span5 {
        @extend .col-sm-5;
        @extend .col-xs-6;
    }

    .backbone-collection-view-cell-span6 {
        @extend .col-sm-6;
        @extend .col-xs-6;
    }

    .backbone-collection-view-cell-span7 {
        @extend .col-sm-7;
        @extend .col-xs-12;
    }

    .backbone-collection-view-cell-span8 {
        @extend .col-sm-8;
        @extend .col-xs-12;
    }

    .backbone-collection-view-cell-span9 {
        @extend .col-sm-9;
        @extend .col-xs-12;
    }

    .backbone-collection-view-cell-span10 {
        @extend .col-sm-10;
        @extend .col-xs-12;
    }

    .backbone-collection-view-cell-span11 {
        @extend .col-sm-11;
        @extend .col-xs-12;
    }

    .backbone-collection-view-cell-span12 {
        @extend .col-xs-12;
    }
}
//SUITESCRIPT
define(
    'BrowseByGame.Models'
,	[
        'SC.Model'
    ,   'JJ.BrowseByGame.BrowseByGame.ServiceController'
    ,   'Application'
    ,	'Configuration'
    ,   'underscore'
    ]
,	function BrowseByGameModel (
        SCModel
    ,   BrowseByGameServiceController
    ,   Application
    ,   Configuration
    ,   _
)
{
    'use strict';

    return SCModel.extend({
        name: 'BrowseByGame'
    ,   record: {
            type: 'customrecord_tbt_game'
        ,   fieldsets: {
                list: {
                    internalid: 'internalid'
                ,   name: 'name'
                ,   image: 'custrecord_tbt_game_image'
                ,   publisher: 'custrecord_tbt_game_publisher'
                ,   publisherUrl: 'custrecord_tbt_game_publisher_url'
                ,   publishDate: 'custrecord_tbt_game_publish_date'
                }
            ,   detailed: {
                    internalid: 'internalid'
                ,   name: 'name'
                ,   publisher: 'custrecord_tbt_game_publisher'
                ,   publisherUrl: 'custrecord_tbt_game_publisher_url'
                ,   publishDate: 'custrecord_tbt_game_publish_date'
                ,   time: 'custrecord_tbt_game_time'
                ,   players: 'custrecord_tbt_game_players'
                ,   age: 'custrecord_tbt_game_age'
                ,   image: 'custrecord_tbt_game_image'
                ,   bbgUrl: 'custrecord_bgg_url'
                }
            }
        }

    ,	get: function (id) {
            var searchFilters
            ,   gameDataSearchResult
            ,   gameDataAssociatedItems;

            searchFilters = [
                new nlobjSearchFilter('isinactive', null, 'is', 'F')
            ,   new nlobjSearchFilter('internalid', null, 'is', id)
            ];

            gameDataSearchResult = Application.getAllSearchResults(this.record.type, searchFilters, this.getColumnsArray(this.record.fieldsets.detailed));

            if (!gameDataSearchResult || !gameDataSearchResult.length) {
                throw notFoundError;
            }

            gameDataAssociatedItems = this.getGameDataItems(id);

            return this.wrapGameData(gameDataSearchResult[0], gameDataAssociatedItems, true);
        }

    ,	list: function (paginate, page, display, resultsPerPage) {
            var searchFilters
            ,   gameDataSearchResults
            ,   wrappedRecords
            ,   fetchImage
            ,   self = this;

            searchFilters = [
                new nlobjSearchFilter('isinactive', null, 'is', 'F')
            ];

            fetchImage = !display || display !== 'list';

            if (paginate) {
                gameDataSearchResults = Application.getPaginatedSearchResults({
                    record_type: this.record.type
                ,	filters: searchFilters
                ,	columns: this.getColumnsArray(this.record.fieldsets.list)
                ,	page: page || 1
                ,	results_per_page : +resultsPerPage && +resultsPerPage > 0 ? +resultsPerPage : Configuration.suitescriptResultsPerPage
                });

                nlapiLogExecution('ERROR', 'this.record.fieldsets.list', JSON.stringify(this.record.fieldsets.list));
            } else {
                var noImageFieldset;

                noImageFieldset = _.extend({}, this.record.fieldsets.list);
                delete noImageFieldset.image;

                gameDataSearchResults = Application.getAllSearchResults(this.record.type, searchFilters, this.getColumnsArray(noImageFieldset));

                fetchImage = false;
            }

            wrappedRecords = _.map((paginate ? gameDataSearchResults.records : gameDataSearchResults), function map (gameDataSearchResult) {
                return self.wrapGameData(gameDataSearchResult, null, fetchImage);
            });

            if (paginate) {
                gameDataSearchResults.records = wrappedRecords;
            } else {
                gameDataSearchResults = {};
                gameDataSearchResults.records = wrappedRecords;
            }

            return gameDataSearchResults;
        }

    ,   getItemCompability: function getItemCompability (itemId) {
            var searchFilters
            ,   searchColumns
            ,   itemGameDataSearchResults
            ,   wrappedRecords
            ,   gameCompatibilityResults;

            searchFilters = [
                new nlobjSearchFilter('internalid', null, 'is', itemId)
            ];

            searchColumns = [
                new nlobjSearchColumn('name', 'custitem_tbt_gamedata')
            ,   new nlobjSearchColumn('internalid', 'custitem_tbt_gamedata')
            ];

            itemGameDataSearchResults = Application.getAllSearchResults('item', searchFilters, searchColumns);

            nlapiLogExecution('ERROR','LOG 1', JSON.stringify(itemGameDataSearchResults));

            itemGameDataSearchResults = _.isArray(itemGameDataSearchResults) ? itemGameDataSearchResults : [itemGameDataSearchResults];

            nlapiLogExecution('ERROR','LOG 1.5', JSON.stringify(itemGameDataSearchResults));

            itemGameDataSearchResults = _.compact(itemGameDataSearchResults) && JSON.parse(JSON.stringify(itemGameDataSearchResults));

            nlapiLogExecution('ERROR','LOG 2', JSON.stringify(itemGameDataSearchResults));

            wrappedRecords = _.compact(_.map(itemGameDataSearchResults, function map (itemGameDataSearchResult) {

                nlapiLogExecution('ERROR','GAME RESULT ***', JSON.stringify(itemGameDataSearchResult));

                if (!_.isEmpty(itemGameDataSearchResult) && !_.isEmpty(itemGameDataSearchResult.columns)) {
                    return {
                        name: itemGameDataSearchResult.columns.name
                    ,   id: itemGameDataSearchResult.columns.internalid.internalid
                    }
                }
            }));

            nlapiLogExecution('ERROR','WRAPPED RECORDS', JSON.stringify(wrappedRecords));

            gameCompatibilityResults = {};
            gameCompatibilityResults.records = wrappedRecords;

            return gameCompatibilityResults;
        }

    ,   getColumnsArray: function getColumnsArray (fieldset) {
            var columns;

            columns = [];

            _.each(_.keys(fieldset), function each (key) {
                columns.push(new nlobjSearchColumn(fieldset[key]));
            }, this);

            return columns;
        }

    ,   getGameDataItems: function getGameDataItems (gameDataId) {
            var searchFilters
            ,   searchColumns
            ,   itemsSearchResults;

            searchFilters = [
                new nlobjSearchFilter('isinactive', null, 'is', 'F')
            ,   new nlobjSearchFilter('isonline', null, 'is', 'T')
            ,   new nlobjSearchFilter('custitem_tbt_gamedata', null, 'anyof', gameDataId)
            ];

            searchColumns = [
                new nlobjSearchColumn('internalid')
            ];

            itemsSearchResults = Application.getAllSearchResults('item', searchFilters, searchColumns);

            return itemsSearchResults;
        }

    ,   wrapGameData: function (gameData, associatedItems, fetchImage) {
            var wrappedGameData
            ,   imageRecordId;

            wrappedGameData = {};

            wrappedGameData.id = gameData.getValue(this.record.fieldsets.list.internalid);
            wrappedGameData.name = gameData.getValue(this.record.fieldsets.list.name);
            wrappedGameData.publisher = gameData.getText(this.record.fieldsets.detailed.publisher);
            wrappedGameData.publisherUrl = gameData.getValue(this.record.fieldsets.detailed.publisherUrl);
            wrappedGameData.publishDate = gameData.getValue(this.record.fieldsets.detailed.publishDate);
            
            if (fetchImage) {
                imageRecordId = gameData.getValue(this.record.fieldsets.detailed.image);

                if (imageRecordId) {
                    var imagePath;

                    try {
                        imagePath = this.getImagePath(imageRecordId);

                        if (imagePath) {
                            wrappedGameData.image = this.getImagePath(imageRecordId);
                        }
                    }
                    catch (e) {
                        nlapiLogExecution('ERROR', 'GAME DATA IMAGE getImagePath ERROR', JSON.stringify(e));
                    }
                }
            }

            if (associatedItems) {
                wrappedGameData.time = gameData.getValue(this.record.fieldsets.detailed.time);
                wrappedGameData.players = gameData.getValue(this.record.fieldsets.detailed.players);
                wrappedGameData.age = gameData.getValue(this.record.fieldsets.detailed.age);
                wrappedGameData.bbgUrl = gameData.getValue(this.record.fieldsets.detailed.bbgUrl);
                wrappedGameData.items = associatedItems;
            }

            return wrappedGameData;
        }

    ,   getImagePath: function getImagePath (imageRecordId) {
            var file;

            file = nlapiLoadFile(imageRecordId);

            if (file) {
                return file.getURL();
            }

            return null;
        }

    ,	notFoundError: {
            status: 404
        ,	code: 'ERR_RECORD_NOT_FOUND'
        ,	message: 'Not found'
        }
    });
});
//SUITESCRIPT: SERVICECONTROLLER

define(
    'JJ.BrowseByGame.BrowseByGame.ServiceController'
,	[
        'ServiceController'
    ,	'Application'
    ,	'Configuration'
    ,	'BrowseByGame.Models'
    ]
,	function BrowseByGameServiceController (
        ServiceController
    ,	Application
    ,   Configuration
    ,	BrowseByGameModel
    )
{
    'use strict';

    return ServiceController.extend({
        name:'JJ.BrowseByGame.BrowseByGame.ServiceController'

    ,	get: function get () {
            var id
            ,   iteminternalid
            ,   display
            ,   paginate
            ,   page
            ,   resultsPerPage
            ,   results;

            try {
                iteminternalid = this.request.getParameter('iteminternalid');

                if (iteminternalid) {
                    results = BrowseByGameModel.getItemCompability(iteminternalid);
                } else {
                    id = this.request.getParameter('internalid');
                    paginate = this.request.getParameter('paginate') && this.request.getParameter('paginate') === 'T' || false;
                    page = this.request.getParameter('page');
                    display = this.request.getParameter('display') || 'grid';
                    resultsPerPage = this.request.getParameter('resultsPerPage') || Configuration.suitescriptResultsPerPage;

                    results = id ? BrowseByGameModel.get(id) : (BrowseByGameModel.list(paginate, page, display, resultsPerPage) || []);
                }

                this.sendContent(results, { cache: response.CACHE_DURATION_LONG });
            } catch (e) {
                console.warn('BrowseByGame.Service.ss::' + e.name, e);
                this.sendError(e);
            }
        }
    });
});
<!--TEMPLATE:: browse_by_game.tpl-->
<div class="browse-by-game">
    <section class="browse-by-game-pagination-container browse-by-game-pagination-top">
        {{#if isNotListView}}
            <div class="browse-by-game-pagination" data-view="GlobalViews.Pagination"></div>
        {{/if}}
        <div class="browse-by-game-display-view">
            <a data-display="list" href="browse-by-game?display=list" class="facets-item-list-display-selector" title="List">
                <i class="icon-display-list"></i>
            </a>
            <a data-display="grid" href="browse-by-game?display=grid" class="facets-item-list-display-selector   facets-item-list-display-selector-grid " title="Grid">
                <i class="icon-display-grid"></i>
            </a>
        </div>

        <div data-view="BrowseByGame.Search" data-template="browse_by_game_search_compact" class="browse-by-game-search-compact {{#unless isNotListView}}browse-by-game-search-compact-list{{/unless}}"></div>
    </section>
    <div class="browse-by-game-collection" data-view="BrowseByGame.Collection"></div>
    {{#if isNotListView}}
        <section class="browse-by-game-pagination-container browse-by-game-pagination-bottom">
            <div class="browse-by-game-pagination" data-view="GlobalViews.Pagination"></div>
        </section>
    {{/if}}
</div>
<!--TEMPLATE:: browse_by_game_game.tpl-->
<div class="backbone-collection-view-cell-span3">
<div class="browse-by-game-game-container-{{cellClass}}">
    <div class="browse-by-game-game">
        <a class="browse-by-game-game-link" data-touchpoint="home" data-hashtag="browse-by-game/{{gameId}}">
            <img class="browse-by-game-game-link-image" src="{{resizeImage imageSrc 'thumbnail'}}" alt="{{name}}">
            <div class="browse-by-game-game-link-name">
                {{name}}
            </div>
        </a>
    </div>
</div>
</div>
<!--TEMPLATE:: browse_by_game_game_detailed.tpl-->

<div class="browse-by-game-game-detailed-container">
    <aside class="browse-by-game-game-detailed-left-sidebar">
        <div class="browse-by-game-game-detailed-left-sidebar-search">
            <div data-view="BrowseByGame.Search"></div>
        </div>
    </aside>
    <section class="browse-by-game-game-detailed">
        <div class="browse-by-game-game-detailed-header">
            <div class="browse-by-game-game-detailed-header-image-container">
                <img src="{{image}}" alt="{{name}}">
            </div>
            <div class="browse-by-game-game-detailed-header-details">
                <div class="browse-by-game-game-detailed-header-details-title">
                    <h1>{{name}}</h1>
                </div>
                <div class="browse-by-game-game-detailed-header-details-specs">
                    <div class="browse-by-game-game-detailed-header-details-specs-spec browse-by-game-game-detailed-header-details-specs-publisher">
                        <span>
                            {{translate 'Publisher:'}}
                            <a class="browse-by-game-game-detailed-header-details-specs-link" target="_blank" href="{{publisherUrl}}">
                                {{publisher}}
                            </a>
                        </span>
                    </div>
                    <div class="browse-by-game-game-detailed-header-details-specs-spec browse-by-game-game-detailed-header-details-specs-published">
                        <span>{{translate 'Published:'}} {{publishDate}}</span>
                    </div>
                    <div class="browse-by-game-game-detailed-header-details-specs-spec browse-by-game-game-detailed-header-details-specs-community">
                        <span>
                            {{translate 'Community:'}}
                            <a class="browse-by-game-game-detailed-header-details-specs-link" target="_blank" href="{{bbgUrl}}">
                                BoardGameGeek
                            </a>
                        </span>
                    </div>
                    <!--<div class="browse-by-game-game-detailed-header-details-specs-spec browse-by-game-game-detailed-header-details-specs-learn">-->
                        <!--<span>-->
                            <!--{{translate 'Learn to Play:'}}-->
                            <!--<a class="browse-by-game-game-detailed-header-details-specs-link" target="_blank">-->
                                <!--Link??-->
                            <!--</a>-->
                        <!--</span>-->
                    <!--</div>-->
                    <div class="browse-by-game-game-detailed-header-details-specs-spec browse-by-game-game-detailed-header-details-specs-game-play">
                        <div class="browse-by-game-game-detailed-header-details-specs-game-play-time">
                            <i class="browse-by-game-game-detailed-header-details-specs-game-play-time-icon"></i>
                            <span>{{time}}</span>
                        </div>
                        <div class="browse-by-game-game-detailed-header-details-specs-game-play-players">
                            <i class="browse-by-game-game-detailed-header-details-specs-game-play-players-icon"></i>
                            <span>{{players}}</span>
                        </div>
                        <div class="browse-by-game-game-detailed-header-details-specs-game-play-ages">
                            <i class="browse-by-game-game-detailed-header-details-specs-game-play-ages-icon"></i>
                            <span>{{age}}</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        {{#if isLoading}}
            <div class="browse-by-game-game-detailed-loading-message">
                {{translate 'Loading...'}}
            </div>
        {{else}}
            <div class="browse-by-game-game-detailed-items">
                <div class="browse-by-game-game-detailed-items-categories">
                    {{#if hasOrganizationItems}}
                        <div class="browse-by-game-game-detailed-items-categories-organization">
                            <div class="browse-by-game-game-detailed-items-categories-title browse-by-game-game-detailed-items-categories-organization-title">
                                <h2>{{translate 'Organization'}}</h2>
                            </div>
                            <div class="browse-by-game-game-detailed-items-categories-organization-items">
                                <div data-view="Organization.Items.Collection"></div>
                            </div>
                        </div>
                    {{/if}}
                    {{#if hasComponentItems}}
                        <div class="browse-by-game-game-detailed-items-categories-components">
                            <div class="browse-by-game-game-detailed-items-categories-title browse-by-game-game-detailed-items-categories-components-title">
                                <h2>{{translate 'Components'}}</h2>
                            </div>
                            <div class="browse-by-game-game-detailed-items-categories-components-items">
                                <div data-view="Component.Items.Collection"></div>
                            </div>
                        </div>
                    {{/if}}
                    {{#if hasAccessoriesItems}}
                        <div class="browse-by-game-game-detailed-items-categories-accessories">
                            <div class="browse-by-game-game-detailed-items-categories-title browse-by-game-game-detailed-items-categories-accessories-title">
                                <h2>{{translate 'Accessories'}}</h2>
                            </div>
                            <div class="browse-by-game-game-detailed-items-categories-accessories-items">
                                <div data-view="Accessories.Items.Collection"></div>
                            </div>
                        </div>
                    {{/if}}
                    {{#if hasOtherItems}}
                        <div class="browse-by-game-game-detailed-items-categories-others">
                            <div class="browse-by-game-game-detailed-items-categories-title browse-by-game-game-detailed-items-categories-others-title">
                                <h2>{{translate 'Others'}}</h2>
                            </div>
                            <div class="browse-by-game-game-detailed-items-categories-others-items">
                                <div data-view="Others.Items.Collection"></div>
                            </div>
                        </div>
                    {{/if}}
                </div>
            </div>
        {{/if}}
    </section>
</div>
<!--TEMPLATE:: browse_by_game_game_list_view_cell.tpl-->

<div class="browse-by-game-game-container-{{cellClass}}">
    <div class="browse-by-game-game-image">
        <a class="browse-by-game-game-link" data-touchpoint="home" data-hashtag="browse-by-game/{{gameId}}">
            <img class="browse-by-game-game-link-image" src="{{resizeImage imageSrc 'thumbnail'}}" alt="{{name}}">
        </a>
    </div>
    <div class="browse-by-game-game-detail">
        <a class="browse-by-game-game-link" data-touchpoint="home" data-hashtag="browse-by-game/{{gameId}}">
            <div class="browse-by-game-game-link-name">
                {{name}}
            </div>
        </a>
        <div class="browse-by-game-game-detailed-header-details-specs-spec browse-by-game-game-detailed-header-details-specs-publisher">
            <span>
                {{translate 'Publisher:'}}
                <a class="browse-by-game-game-detailed-header-details-specs-link" target="_blank" href="{{publisherUrl}}">
                    {{publisher}}
                </a>
            </span>
        </div>
        <div class="browse-by-game-game-detailed-header-details-specs-spec browse-by-game-game-detailed-header-details-specs-published">
            <span>{{translate 'Published:'}} {{publishDate}}</span>
        </div>
    </div>
</div>

<!--TEMPLATE:: browse_by_game_list_view_wrapper.tpl-->

<div class="browse-by-game-list-view-wrapper">
    <div class="browse-by-game-list-view-wrapper-table-wrapper">
        <table class="browse-by-game-list-view-wrapper-table table table-striped">
            <tbody>
                {{#each games}}
                    <tr>
                        <td><a href="/browse-by-game/{{this.id}}">{{this.name}}</a></td>
                        <td><a href="{{this.publisherUrl}}" target="_blank">{{this.publisher}}</a></td>
                        <td>{{this.publishDate}}</td>
                    </tr>
                {{/each}}
            </tbody>
        </table>
    </div>
    {{#if isLoading}}
        <div class="browse-by-game-list-view-wrapper-loader">
            <svg width="80px"  height="80px"  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-eclipse" style="background: none;">
                <path ng-attr-d="{{config.pathCmd}}" ng-attr-fill="{{config.color}}" stroke="none" d="M10 50A40 40 0 0 0 90 50A40 42 0 0 1 10 50" fill="#ff8b03" transform="rotate(90 50 51)">
                    <animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 51;360 50 51" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform>
                </path>
            </svg>
        </div>
    {{/if}}
</div>
<!--TEMPLATE:: browse_by_game_search.tpl-->
<div class="browse-by-game-search">
    <div class="browse-by-game-search-box">
        <div class="browse-by-game-search-box-title">
            <h2>{{translate 'Browse By Game'}}</h2>
        </div>
        <div class="browse-by-game-search-box-searcher">
            <input type="text" class="browse-by-game-search-box-input" placeholder="{{translate 'Search by name...'}}">
        </div>
    </div>
    <div class="browse-by-game-search-results">
        <ul class="browse-by-game-search-results-list">
            {{#each games}}
                <li class="browse-by-game-search-result" data-id="{{id}}" data-name="{{name}}">
                    <a class="browse-by-game-search-result-link" href="/browse-by-game/{{id}}">
                        {{name}}
                    </a>
                </li>
            {{/each}}
        </ul>
    </div>
</div>
<!--TEMPLATE:: browse_by_game_search_compact.tpl-->

<div class="browse-by-game-search">
    <div class="browse-by-game-search-box">
        <div class="browse-by-game-search-box-searcher">
            <input type="text" class="browse-by-game-search-box-input" placeholder="{{translate 'Search for games...'}}">
            <a class="browse-by-game-search-reset" data-type="games-search-reset">
                <i class="browse-by-game-search-reset-icon"></i>
            </a>
            <i class="browse-by-game-search-search-icon"></i>
        </div>
    </div>
    <div class="browse-by-game-search-results">
        <ul class="browse-by-game-search-results-list">
            {{#each games}}
                <li class="browse-by-game-search-result" data-id="{{id}}" data-name="{{name}}">
                    <a class="browse-by-game-search-result-link" href="/browse-by-game/{{id}}">
                        {{name}}
                    </a>
                </li>
            {{/each}}
        </ul>
    </div>
</div>

Leave a comment

Your email address will not be published. Required fields are marked *