10

I am trying to use jQuery to scroll to a particular thumbnail (inside a modal) when right/left arrows have been pressed (modal should pop up when user clicks on a image). I was able to make the scroll working when user clicks on a thumbnail but I could not trigger a click when variable current2 changes. Any help would be appreciated.

I am new in Angular.js so if there are other suggestions to improve the code, it would be appreciated.

jsbin link

<body ng-app="mediaGallery" class="ng-cloak" ng-controller="mediaGalleryCtrl">

    <div class="row">
        <div class="small-8 columns">
            <div class="small-3 columns">
                <div ng-repeat="obj in array">
                    <div ng-if="$index < 4">
                        <img ng-click="changeMainMedia($index, 'current1')" class="thumbnail" ng-src="{{obj.src}}" />
                    </div>
                    <div ng-if="$index == 4">
                        <div class="thumbnail" data-open="media-gallery">
                            <label class="text-right success label">{{array.length - 3}} +</label>
                        </div>
                    </div>
                </div>

            </div>

            <div class="small-9 columns">
                <img data-open="media-gallery" class="main-gallery" ng-src="{{array[current1].src}}" />
            </div>
        </div>
    </div>



    <div ng-keydown="key($event)" id="media-gallery" class="small reveal text-center media-gallery" data-reveal>
        <div class="modal-body">
            <div class="main-media">
                <img class="main-gallery media-gallery-main" ng-src="{{array[current2].src}}" />
                <hr>

                <div class="nested-media" scroll-thumbnail>
                    <img ng-click="changeMainMedia($index, 'current2')" ng-repeat="obj in array" class="thumbnail media-gallery-thumbnail" ng-src="{{obj.src}}" />
                </div>
            </div>

            <button class="close-button" data-close aria-label="Close reveal" type="button">
           <span aria-hidden="true">x</span>
        </button>
        </div>
    </div>

    <script>
        var app = angular.module("mediaGallery", []);
        app.controller("mediaGalleryCtrl", ['$scope', function(scope) {
            var array = [{
                src: "https://placeimg.com/640/480/any"
            }, {
                src: "https://placeimg.com/640/480/tech"
            }, {
                src: "https://placeimg.com/640/480/animals"
            }, {
                src: "https://placeimg.com/640/480/nature"
            }, {
                src: "https://placeimg.com/640/480/arch"
            }, {
                src: "https://placeimg.com/640/480/people"
            }];

            scope.array = array;
            scope.current1 = 0
            scope.current2 = 0;

            scope.changeMainMedia = function(index, key) {
                scope[key] = index;
            }

            scope.key = function($event) {
                var previous = -1;
                var current = scope.current2;

                if ($event.keyCode == "39") {
                    previous = current;
                    current = (current + 1) % array.length;
                } else if ($event.keyCode == "37") {
                    previous = current;
                    current = (current - 1) % array.length;
                }
                current = current < 0 ? (array.length + current) : current;

                scope.current2 = current;
            }
        }]);

        app.directive('scrollThumbnail', function() {
            return {
                link: function(scope, elem, attrs) {
                    elem.on("click", function(event) {
                        $(this).animate({
                            scrollLeft: $(event.target).position().left
                        }, "slow");
                    });
                }
            };
        });

        $(document).foundation()
    </script>

</body>
Node.JS
  • 1,042
  • 6
  • 44
  • 114
  • 1
    what's confusing is that the title and body of your question talk about using jquery but the bounty states you do not want to use jquery – Serg Chernata Jan 08 '17 at 21:38
  • @SergChernata I don't want to use DOM selector with a specific DOM id – Node.JS Jan 08 '17 at 21:40
  • @SergChernata I don't have much experience with Angular, but I am looking for an answer that uses Angular's built in method (angular way) instead of pure jQuery to search through DOM – Node.JS Jan 08 '17 at 21:43
  • @SergChernata Thank you for pointing that out. – Node.JS Jan 08 '17 at 21:43
  • Hi! Could you please attach snapshot of both your modal and screen since what I feel that event is not getting called when variable 'current2' gets updated. So, in such scenario you could try to make use of "jQuery triggers" where you can try to call your event whenever variable current2 gets updated. Please try with trigger once if not please share snapshots of your modal and page. – Ashraf.Shk786 Jan 10 '17 at 13:41

1 Answers1

1

This is a solution which does not need jQuery. I commented the changes that I have made to your code.

<!DOCTYPE HTML>

<html>

<head>
    <title>index</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta name="description" />
    <meta name="author">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.0/css/foundation.css" />

    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.6/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.0/js/foundation.js"></script>

    <style>
        .media-gallery .media-gallery-thumbnail {
            max-height: 5em;
            display: inline-block
        }

        .media-gallery .media-gallery-main {
            height: auto;
            width: auto;
            max-height: 20em;
        }

        .media-gallery .nested-media {
            overflow-x: scroll;
            white-space: nowrap;
        }

        .media-gallery .media-gallery-main {
            max-width: 100%;
            -moz-transition: all 0.3s;
            -webkit-transition: all 0.3s;
            transition: all 0.3s;
        }

        .media-gallery .media-gallery-main:hover {
            -moz-transform: scale(1.5);
            -webkit-transform: scale(1.5);
            transform: scale(1.5);
        }

        [ng\:cloak],
        [ng-cloak],
        [data-ng-cloak],
        [x-ng-cloak],
        .ng-cloak,
        .x-ng-cloak {
            display: none !important;
        }
    </style>
</head>

<body ng-app="mediaGallery" class="ng-cloak" ng-controller="mediaGalleryCtrl">

    <div class="row">
        <div class="small-8 columns">
            <div class="small-3 columns">
                <div ng-repeat="obj in array">
                    <div ng-if="$index < 4">
                        <img ng-click="changeMainMedia($index, 'current1', $event)" class="thumbnail" ng-src="{{obj.src}}" />
                    </div>
                    <div ng-if="$index == 4">
                        <div class="thumbnail" data-open="media-gallery">
                            <label class="text-right success label">{{array.length - 3}} +</label>
                        </div>
                    </div> 
                </div>

            </div>

            <div class="small-9 columns">
                <img data-open="media-gallery" class="main-gallery" ng-src="{{array[current1].src}}" />
            </div>
        </div>
    </div>



    <div ng-keydown="key($event)" id="media-gallery" class="small reveal text-center media-gallery" data-reveal>
        <div class="modal-body">
            <div class="main-media">
                <img class="main-gallery media-gallery-main" ng-src="{{array[current2].src}}" />
                <hr>

                <div class="nested-media" scroll-thumbnail>
                    <img ng-click="changeMainMedia($index, 'current2', $event)" ng-repeat="obj in array" class="thumbnail media-gallery-thumbnail" ng-src="{{obj.src}}" />
                </div>
            </div>

            <button class="close-button" data-close aria-label="Close reveal" type="button">
           <span aria-hidden="true">x</span>
        </button>
        </div>
    </div>

    <script>
      var app = angular.module("mediaGallery", []);

      app.controller("mediaGalleryCtrl", ['$scope', function (scope) {
                  var array = [{
                          src : "https://placeimg.com/640/480/any"
                      }, {
                          src : "https://placeimg.com/640/480/tech"
                      }, {
                          src : "https://placeimg.com/640/480/animals"
                      }, {
                          src : "https://placeimg.com/640/480/nature"
                      }, {
                          src : "https://placeimg.com/640/480/arch"
                      }, {
                          src : "https://placeimg.com/640/480/people"
                      }
                  ];

                  scope.array = array;
                  scope.current1 = 0
                      scope.current2 = 0;

                  scope.changeMainMedia = function (index, key, $event) {
                      scope[key] = index;

                     // Use scroll function to scroll to element after click
                     // $event parameter is added to retrieve the node value
                     scope.scroll($event.target);
                  }

                  // Animate scrolling
                  // Midified from: http://stackoverflow.com/a/8918062/529024
                  scope.scrollTo = function (element, to, duration) {

                      if (duration <= 0)
                          return;
                      var difference = to - element.scrollLeft;
                      var perTick = difference / duration * 10;

                      setTimeout(function () {
                          element.scrollLeft = element.scrollLeft + perTick;
                          if (element.scrollLeft === to)
                              return;
                          scope.scrollTo(element, to, duration - 10);
                      }, 10);
                  }

                  // calculate scroll position and starting scroll animation
                  scope.scroll = function (element) {
                      // Get center of parent
                      var left = element.offsetLeft;

                      var scroll = left - element.parentElement.scrollLeft;

                      // Start scroll
                      scope.scrollTo(element.parentElement, scroll, 300);

                  }

                  scope.key = function ($event) {
                      var previous = -1;
                      var current = scope.current2;

                      if ($event.keyCode == "39") {
                          previous = current;
                          current = (current + 1) % array.length;
                      } else if ($event.keyCode == "37") {
                          previous = current;
                          current = (current - 1) % array.length;
                      }
                      current = current < 0 ? (array.length + current) : current;

                      scope.current2 = current;

                    // Scroll to element
                      scope.scroll(scope.getElement());
                  }

                  // get the element that is matching current2 value
                  scope.getElement = function () {
                      var parent = scope.parentElement;
                      var children = parent.children();

                      return children.eq(scope.current2)[0];
                  }

                  // This function is used by directive scrollThumbnail to set the parent element
                  // and use it to get element sibilings
                  scope.setElement = function (element) {
                      scope.parentElement = element;
                  }
              }
          ]);

      app.directive('scrollThumbnail', function () {
          return {
              scope : true,
              link : function (scope, elem, attrs) {
                // set element to scope.parentElement.
                  scope.setElement(elem);
              }
          };
      });

      $(document).foundation()
    </script>
</body>
</html>

And this a JSBin link: https://jsbin.com/ruzikilexe/1/edit?html,output

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Kalimah
  • 11,217
  • 11
  • 43
  • 80