diff --git a/app/index.html b/app/index.html index 2ef899f..6d485e4 100755 --- a/app/index.html +++ b/app/index.html @@ -25,9 +25,9 @@
-
-
- +
+
+
+ @@ -72,7 +73,9 @@ + + diff --git a/app/scripts/app.js b/app/scripts/app.js index fe9e91d..a94bcf3 100755 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -52,7 +52,7 @@ angular * Return the target movie {*}. */ var gettingSelectedMovie = function(moviesData, $stateParams, $filter){ - var selectedMovie = $filter('filter')(moviesData, {urlAlias: $stateParams.name}); + var selectedMovie = $filter('filter')(moviesData.movies, {urlAlias: $stateParams.name}); return selectedMovie[0]; }; @@ -106,6 +106,11 @@ angular moviesData: function(Movies){ return Movies.gettingMovies(); } + }, + // Example of adding custom data (hardcoded) for applying + // conditional css class. + data: { + fixedPosition: true } }) @@ -132,13 +137,33 @@ angular } }, resolve: { - moviesData: function(Bookmarks){ - return Bookmarks.getMovies(); + moviesData: function(Bookmarks, $stateParams){ + // The resolve object automatically resolved it self as a "promise". + // Usually you will call a function that just returns a "promise" + // object, But on this case we want to add extra logic before we + // resolve. That's why it's done manually. + return Bookmarks.getMovies().then(function(movies) { + $stateParams.moviesCount = movies.length; + return movies; + }); } + }, + // Callback function been executed immediately after a successful + // "state" transition. In this example we make sure we are scrolling to + // the top of the page. + onEnter: function($document) { + var element = angular.element(document.getElementById('myApp')); + $document.scrollToElementAnimated(element); + }, + // Example of adding custom data (hardcoded) for applying + // conditional css class. + data: { + fixedPosition: true, + numberOfMoviesToCompare: 3 } }) - // Movies state. + // Movie state. .state('main.movie',{ url: 'movie/{name}?originBookmark', abstract: true, @@ -162,12 +187,11 @@ angular } } }) - // Single movie state. .state('main.movie.movieInfo',{ // The "^" character excludes the parent prefix url // ("movie/{name}?originBookmark") format from this child state url, it - // will become only as "movie/info/{name}?originBookmark". + // will transform to "movie/info/{name}?originBookmark". url: '^/movie/info/{name}?originBookmark', views: { 'content@': { @@ -211,7 +235,7 @@ angular } }) }]) - .run([ '$rootScope', '$state', '$stateParams', 'localStorageService', 'Bookmarks', function ($rootScope, $state, $stateParams, localStorageService, Bookmarks) { + .run([ '$rootScope', '$state', '$stateParams', 'localStorageService', function ($rootScope, $state, $stateParams, localStorageService) { // It's very handy to add references to $state and $stateParams to the // $rootScope so that you can access them from any scope within your // applications. @@ -224,6 +248,9 @@ angular return console.log(data); }; + //Debug variable + $rootScope.debug = false; + // Access local storage service from any scope. $rootScope.localStorageService = localStorageService; }]) diff --git a/app/scripts/controllers/movie.js b/app/scripts/controllers/movie.js index dbc24ed..764cc4f 100755 --- a/app/scripts/controllers/movie.js +++ b/app/scripts/controllers/movie.js @@ -13,7 +13,7 @@ angular.module('myApp') var self = this; // Array of movies. - self.movies = moviesData; + self.movies = moviesData.movies; // Bookmarks service object. self.bookmarksService = Bookmarks; @@ -24,4 +24,11 @@ angular.module('myApp') // Movie trailer. self.movieTrailerUrl = Movies.gettingMovieTrailerUrl(self.selectedMovie.trackName, $state.current.data.trailer); + // filter params. + self.filterParams = {}; + self.filterParams.RelatedMoviesByGenre = { + primaryGenreName: self.selectedMovie.primaryGenreName, + id: '!' + self.selectedMovie.id + }; + }]); diff --git a/app/scripts/controllers/movies.js b/app/scripts/controllers/movies.js index b6b6159..2b6068d 100755 --- a/app/scripts/controllers/movies.js +++ b/app/scripts/controllers/movies.js @@ -13,7 +13,13 @@ angular.module('myApp') var self = this; // Movies data. - self.data = moviesData; + self.data = moviesData.movies; + + // Movies data. + self.filterByGenre = '!All'; + + // Movies genres. + self.genres = moviesData.genres; // Bookmarks service object. self.bookmarksService = Bookmarks; diff --git a/app/scripts/directives/scrollBar.js b/app/scripts/directives/scrollBar.js index fea49e0..8363e8d 100644 --- a/app/scripts/directives/scrollBar.js +++ b/app/scripts/directives/scrollBar.js @@ -6,7 +6,6 @@ angular.module('myApp') restrict: 'EA', link: function(scope, element) { - // Adding scrollbar js library. element.mCustomScrollbar({ setHeight: 75, diff --git a/app/scripts/directives/scrollToMovie.js b/app/scripts/directives/scrollToMovie.js new file mode 100644 index 0000000..6b6377e --- /dev/null +++ b/app/scripts/directives/scrollToMovie.js @@ -0,0 +1,19 @@ +'use strict'; +angular.module('myApp') + .directive('scrollToMovie', ['$document', function ($document) { + return { + restrict: 'EA', + scope: { + itemId: '@' + }, + link: function (scope, element) { + + var scrollToMovie = function(id) { + var element = angular.element(document.getElementById(id)); + $document.scrollToElementAnimated(element) + } + + element.bind('click', scrollToMovie(scope.itemId)); + } + }; + }]); diff --git a/app/scripts/filters/alterCollection.js b/app/scripts/filters/alterCollection.js new file mode 100644 index 0000000..316be74 --- /dev/null +++ b/app/scripts/filters/alterCollection.js @@ -0,0 +1,19 @@ +angular.module('myApp').filter('alterCollection', function($window, $filter) { + return function(collection, params) { + console.log(params); + console.log(collection); + + + // Exclude self movie and movies from different genres. + return $filter('filter')(collection, params.config).slice(0,6); + + var newCollection = new Array(); + angular.copy(collection, newCollection); + // Shuffle the collection. + newCollection = $window.shuffle(newCollection); +// newCollection = ; + +// var newCollection = ; + return newCollection + }; +}); diff --git a/app/scripts/services/bookmarks.js b/app/scripts/services/bookmarks.js index dd5ff44..942bac2 100644 --- a/app/scripts/services/bookmarks.js +++ b/app/scripts/services/bookmarks.js @@ -4,9 +4,26 @@ angular.module('myApp') .factory('Bookmarks', ['localStorageService', '$filter', '$q', function (localStorageService, $filter, $q) { // Private data array of movies. - var data =[]; - data = localStorageService.get('bookmarks'); - data = data != null ? data : new Array(); + var data = { + movies: localStorageService.get('bookmarks') || new Array(), + genres: {} + }; + + /** + * Get all of the existing genres and a counter for each one. + * + * @param movies + * Movies array. + * @returns {*} + * Array of genres names and counter for each genre. + */ + function getMoviesGenres(movies) { + var genres = {'All': movies.length}; + angular.forEach(movies, function(movie) { + angular.isDefined(genres[movie.primaryGenreName]) ? genres[movie.primaryGenreName]++ : genres[movie.primaryGenreName] = 1; + }); + return genres; + } return { @@ -28,7 +45,7 @@ angular.module('myApp') angular.copy(movie, movieCopy); // Get array of movies. - var movies = data; + var movies = data.movies; // Adding a flag to the movie object to reference it's relationship // to the bookmark type movie. @@ -72,7 +89,7 @@ angular.module('myApp') var deferred = $q.defer(); // Get array of movies. - var movies = data; + var movies = data.movies; // Find the target movie from with in the movies array. var targetMovie = $filter('filter')(movies, {id: movie.id}); @@ -90,15 +107,14 @@ angular.module('myApp') // In case of success. if (deleted) { - // On success un-mark the movie as bookmarked. movie.isBookmarked = false; - deferred.resolve({"deleted": deleted, "error": false}); + deferred.resolve({"error": false}); } // In case of error. else { - deferred.reject({"deleted": deleted, "error": true}); + deferred.reject({"error": true}); } // Return promise object. @@ -113,6 +129,9 @@ angular.module('myApp') */ getMovies: function() { var deferred = $q.defer(); + data.genres = getMoviesGenres(data.movies); + // count numbers of movies that are returned. + data.count = data.length; deferred.resolve(data); // Return promise object. return deferred.promise; @@ -128,7 +147,7 @@ angular.module('myApp') * @returns bool */ isMovieBookmarked: function(movieId) { - var movies = data; + var movies = data.movies; // Find the target movie from with in the movies array. var targetMovie = $filter('filter')(movies, {id: movieId}); return targetMovie.length ? true : false; diff --git a/app/scripts/services/movies.js b/app/scripts/services/movies.js index b3b0a11..0499dfd 100644 --- a/app/scripts/services/movies.js +++ b/app/scripts/services/movies.js @@ -1,10 +1,10 @@ 'use strict'; angular.module('myApp') - .factory('Movies', ['$http', '$q', '$sce', 'Bookmarks', function ($http, $q, $sce, Bookmarks) { + .factory('Movies', ['$http', '$q', '$sce', '$filter', 'Bookmarks', function ($http, $q, $sce, $filter, Bookmarks) { /** - * Return the promise {*} with the list of top movies Ids amount by moviesCount. + * Return the movies IDs from the list of "top movies". * * @param moviesCount * Number of movies to return. @@ -78,8 +78,27 @@ angular.module('myApp') return deferred.promise; } - // Public API here + /** + * Get all of the existing genres and a counter for each one. + * + * @param movies + * Movies array. + * @returns {*} + * Array of genres names and counter for each genre. + */ + function getMoviesGenres (movies) { + var genres = {'All': movies.length}; + angular.forEach(movies, function(movie) { + angular.isDefined(genres[movie.primaryGenreName]) ? genres[movie.primaryGenreName]++ : genres[movie.primaryGenreName] = 1; + }); + return genres; + } + + // Public API here. return { + + self: this, + /** * Return a promise object of the list of Movies. * @@ -88,12 +107,17 @@ angular.module('myApp') gettingMovies: function(moviesCount) { var deferred = $q.defer(); - moviesCount = angular.isDefined(moviesCount) ? moviesCount : 60; + moviesCount = angular.isDefined(moviesCount) ? moviesCount : 99; // Get the top movies ids. requestTopMoviesIds(moviesCount).then(function(moviesIds) { requestMoviesById(moviesIds).then(function(movies) { - deferred.resolve(movies); + + var data = { + movies: movies, + genres: getMoviesGenres(movies) + }; + deferred.resolve(data); }) }); diff --git a/app/styles/main.scss b/app/styles/main.scss index 8e564c8..3e03aea 100755 --- a/app/styles/main.scss +++ b/app/styles/main.scss @@ -26,10 +26,6 @@ body { #main { - @include phone-only { - padding: 0px 30px; - } - #movies { .movies-notification { margin: 8px 0px; @@ -42,6 +38,17 @@ body { #main-header, #main-footer { + &.fixed { + position: fixed; + left: 0; + right: 0; + z-index: 5; + margin: 0 auto; + box-shadow: 0 2px 5px 0 rgba(0,0,0,0.26); + background: black; + @include responsive-width(); + } + .top, .bottom { margin: 0px; @@ -54,11 +61,17 @@ body { #main-header { color: $gray; text-transform: uppercase; + top: 0; + padding-top: 20px; - .top { - margin-top: 15px; - @include border-top-left-radius(6px); - @include border-top-right-radius(6px); + &.fixed { + padding-bottom: 4px; + } + + .menu { + @include phone-only { + padding: 0px 30px; + } } .navbar { @@ -151,7 +164,26 @@ body { } } + #main-content { + &.fixed { + margin-top: 140px; + margin-bottom: 54px; + } + + &.slim { + overflow-y: hidden; + height: 570px; + } + } + #main-footer { + bottom: 0; + padding-bottom: 20px; + + &.slim { + bottom: 339px; + width: inherit; + } .bottom { @include border-bottom-left-radius(6px); @@ -225,6 +257,84 @@ body { } } + #genre-menu-wrapper { + position: fixed; + top: 80px; + left: 0; + right: 0; + z-index: 5; + margin: 0 auto; + background: black; + @include responsive-width(); + + button { + width: 100%; + color: $gray-light; + outline: none; + border: none; + padding: 10px 0px; + margin: 13px auto 0px auto; + background: #000000; + + span { + color: $blue; + } + + @include borders(1px); + + &:hover { + color: $blue; + } + } + + #genre-menu { + position: relative; + overflow-x: hidden; + + &:after { + content: ""; + width: 100%; + position: absolute; + left: 0px; + @include border(1px); + } + + &:after { + bottom: 0px; + } + + ul { + text-align: center; + list-style: none; + padding: 0px; + margin: 9px auto 13px auto; + + li { + margin: 4px; + padding: 5px; + display: inline-block; + @include border-radius(5px); + color: rgba(51, 122, 183, 1); + background: rgba(51, 122, 183, 0.14); + cursor: pointer; + + &:hover { + color: white; + } + + .count { + color: rgba(255, 255, 255, 0.46); + } + } + } + + .top { + margin: 13px auto 0px auto; + width: inherit; + } + } + } + .movies-wrapper { @include large-desktop-only { @@ -245,18 +355,18 @@ body { .preview { cursor: pointer; - @include transition(opacity 0.5s ease-in-out); img { width: 100%; + @include transition(opacity 0.5s ease-in-out); @include exclude-phone-only { @include img-responsive; } - } - &:hover { - @include opacity(0.6); + &:hover { + @include opacity(0.6); + } } } @@ -305,14 +415,11 @@ body { content: ""; width: 100%; position: absolute; + top: 0px; left: 0px; @include border(1px); } - &:after { - top: 0px; - } - span { color: $lightGray; } @@ -333,7 +440,6 @@ body { @include borders(2px); } - .info-container, .image-container { padding-bottom: 30px; } @@ -526,7 +632,59 @@ body { } } } + + #related-movies-by-genre { + position: relative; + padding-bottom: 14px; + margin-bottom: 15px; + + &:after { + content: ""; + width: 100%; + position: absolute; + left: 0px; + bottom: 0px; + @include border(1px); + } + + .title { + color: white; + padding: 8px; + @include borders(1px); + } + + article { + position: relative; + margin-top: 15px; + @include transition(opacity 0.5s ease-in-out); + + &:hover { + @include opacity(0.6); + } + + &:not(:last-child):after { + content: ""; + width: 100%; + position: absolute; + right: 0px; + top: 0px; + height: 100%; + width: 5%; + background: #000000; + } + } + } } + + .top { + margin: 0px; + height: 15px; + text-align: center; + background: $darkGray; + margin-top: 15px; + @include border-top-left-radius(6px); + @include border-top-right-radius(6px); + } } .trailer { @@ -689,6 +847,11 @@ body { top: 0px; } + a { + color: white; + text-decoration: none; + } + .title { margin: 0px; font-size: 12px; @@ -698,6 +861,10 @@ body { &:hover { color: $blue; + + a{ + color: $blue; + } } &.add:hover { diff --git a/app/styles/mixin.scss b/app/styles/mixin.scss index 6d93368..46a42cc 100644 --- a/app/styles/mixin.scss +++ b/app/styles/mixin.scss @@ -59,6 +59,27 @@ $effect: ease-in; @include transition-timing-function($effect); } +// Color change transition +@mixin responsive-width { + width: $container-lg; + + @include medium-desktop-only { + width: $container-md; + } + + @include tablet-only { + width: $container-sm; + } + + @include mobile-only { + width: $ContainerPhone; + } + + @include phone-only { + width: 100%; + } +} + // Color change transition @mixin border($height) { background: $blue; @@ -156,6 +177,13 @@ $effect: ease-in; } } +// Not for phone to mobile width only. +@mixin phone-to-tablet-only { + @media (max-width: $screen-sm-max) { + @content; + } +} + // Not for phone to mobile width only. @mixin phone-to-mobile-only { @media (max-width: $screen-is-max) { diff --git a/app/views/includes/debug-responsive.html b/app/views/includes/debug-responsive.html new file mode 100644 index 0000000..724d3f2 --- /dev/null +++ b/app/views/includes/debug-responsive.html @@ -0,0 +1,7 @@ +
+
LG
+
MD
+
SM
+
IS
+
XS
+
diff --git a/app/views/includes/menu-genre-groups.html b/app/views/includes/menu-genre-groups.html new file mode 100644 index 0000000..85791a9 --- /dev/null +++ b/app/views/includes/menu-genre-groups.html @@ -0,0 +1,9 @@ + +
+ +
+
diff --git a/app/views/main/header.html b/app/views/main/header.html index 5941df0..e5aaaa0 100755 --- a/app/views/main/header.html +++ b/app/views/main/header.html @@ -1,20 +1,25 @@ +
-
-

- Itunes top 60 movies - My bookmarks - - {{ $state.current.data.breadcrumbs }} -

-
-
- +
+ +
+
@@ -27,12 +32,7 @@

In order to use this feature you must enable your browser - local storage capability.

-
- - Bookmarked movies are stored on your browser local storage. - -
-
+
diff --git a/app/views/pages/movie/movieInfo.html b/app/views/pages/movie/movieInfo.html index 63164ef..099a910 100644 --- a/app/views/pages/movie/movieInfo.html +++ b/app/views/pages/movie/movieInfo.html @@ -6,9 +6,9 @@
-

{{ movie.selectedMovie.trackName }}

- {{ movie.selectedMovie.trackName }}-poster image -
{{ movie.selectedMovie.index }}
+

{{ ::movie.selectedMovie.trackName }}

+ {{ ::movie.selectedMovie.trackName }}-poster image +
{{ ::movie.selectedMovie.index }}
@@ -19,40 +19,40 @@

{{ movie.selectedMovie.trackName }}

- -
{{ movie.selectedMovie.longDescription }}
+ +
{{ ::movie.selectedMovie.longDescription }}
  • -
    {{ movie.selectedMovie.releaseDate | date:'longDate' }}
    +
    {{ ::movie.selectedMovie.releaseDate | date:'longDate' }}
  • -
    {{ movie.selectedMovie.primaryGenreName }}
    +
    {{ ::movie.selectedMovie.primaryGenreName }}
  • -
    {{ movie.selectedMovie.artistName }}
    +
    {{ ::movie.selectedMovie.artistName }}
  • - HD: {{ movie.selectedMovie.collectionHdPrice }}$ + HD: {{ ::movie.selectedMovie.collectionHdPrice }}$ | - Rental HD: {{ movie.selectedMovie.trackHdRentalPrice }}$ + Rental HD: {{ ::movie.selectedMovie.trackHdRentalPrice }}$
  • -
    {{ movie.selectedMovie.contentAdvisoryRating }}
    +
    {{ ::movie.selectedMovie.contentAdvisoryRating }}
  • - +
  • @@ -77,4 +77,13 @@
+
+ diff --git a/app/views/pages/movies/movie.preview.html b/app/views/pages/movies/movie.preview.html index ed7a312..8c7ec37 100644 --- a/app/views/pages/movies/movie.preview.html +++ b/app/views/pages/movies/movie.preview.html @@ -1,7 +1,7 @@ - + diff --git a/app/views/pages/movies/movie.summary.html b/app/views/pages/movies/movie.summary.html index 899f610..f91b8d4 100644 --- a/app/views/pages/movies/movie.summary.html +++ b/app/views/pages/movies/movie.summary.html @@ -1,26 +1,26 @@
-

{{ movie.trackName }}

+

{{ ::movie.trackName }}

- {{ movie.index }} + {{ ::movie.index }}
| Release Date:
- {{ movie.releaseDate | date:'longDate' }} + {{ ::movie.releaseDate | date:'longDate' }}
| Primary genre:
- {{ movie.primaryGenreName }} + {{ ::movie.primaryGenreName }}