Responsive carousel with multiple items

I am in the process of developing a website that requires the implementation of a carousel feature. Since the website is based on AngularJS, I initially considered using Angular's Bootstrap Carousel. However, I encountered an issue where this carousel only displays one image at a time.

My specific requirement is to display 3 images at once on desktop, 2 images on tablets, and 1 image on mobile devices. Therefore, responsive design plays a crucial role in this project.

Does anyone have any experience with achieving this without relying on JQuery? While I am open to using JQuery, a senior team member suggested exploring alternative options.

This is what I attempted with Angular's Bootstrap:

$scope.getPromoURLs = function() {
    var subObj = myJSON.response.details.promotionalSpots;
    for( var keys in subObj ) {
        var value = subObj[keys].promotionUrl;
        $scope.slides.push( value );
    }
};
// Builds an array of promotional URLs from a JSON object to use as image sources
$scope.getPromoURLs();

$scope.addSlide = function () {
    // Test attempting to concatenate 3 images together - unsuccessful
    var newWidth = 600 + slides.length;
    slides.push({
       image: ''+slides[0]+''+slides[1] // etc
       // Attempted to combine images here 
    });
};

// TODO: should evaluate array length dynamically instead of hardcoding it to 4
for (var i = 0; i < 4; i++) {
    $scope.addSlide();
}

Answer №1

ui-bootstrap's carousel may not be the best option due to drawbacks like isolated scope on each slide. I prefer using https://github.com/revolunet/angular-carousel as it supports multiple items on each slide.

This directive is great for using ng-repeat. You can easily change your collection and use nested ng-repeat to display a different number of items in each slide.

<ul rn-carousel class="image">
  <li ng-repeat="images in imageCollection">
    <div ng-repeat="image in images" class="layer">{{ image }}</div>
  </li>
</ul>

With 3 breakpoints already defined, all we need to do is reconstruct the imageCollection array when the viewport size changes.

$window.on('resize', function() {
    var width = $window.width();
    if(width > 900) {
       // desktop
       rebuildSlide(3);
    } else if(width <= 900 && width > 480) {
       // tablet
       rebuildSlide(2);
    } else {
       // phone
       rebuildSlide(1);
    }
    // don't forget manually trigger $digest()
    $scope.$digest();
});

function rebuildSlide(n) {
   var imageCollection = [],
       slide = [],
       index;
   // values represent your actual data collection.
   for(index = 0; index < values.length; index++) {
       if(slide.length === n) {
           imageCollection.push(slide);
           slide = [];
       }
       slide.push(values[index]);
   }
   imageCollection.push(slide);
   $scope.imageCollection = imageCollection;
}

Answer №2

After experimenting with integrating the angularjs Carousel (ui.bootstrap.carousel) to support multiple items per animation, I also explored implementing [Detection for Responsive Websites using AngularJS].2

Check out the demo here: http://plnkr.co/edit/QhBQpG2nCAnfsb9mpTvj?p=preview

Results:

1 ) Single Item (Mobile Version) :

2 ) Double Items (Tablet Version) :

3 ) Triple Items (Desktop Version) :

PART 2: It can also detect the window resolution to determine whether it is tablet, mobile or desktop by following this tutorial... Experiment with these values: "mobile, tablet, desktop" to see the three different view versions.

Showcase of the tablet version:

var app = angular.module('myApp', ['ui.bootstrap', 'angular-responsive']);

app.controller('MainCtrl', function($scope) {
  $scope.displayMode = 'mobile'; // default value


  $scope.$watch('displayMode', function(value) {

    switch (value) {
      case 'mobile':
        // execute code for mobile mode
          console.log(value);
        break;
      case 'tablet':
        // perform tasks for tablet mode
          console.log(value);
        break;
    }
  });
});

function CarouselDemoCtrl($scope) {
  var whatDevice = $scope.nowDevice;
  $scope.myInterval = 7000;
  $scope.slides = [{
    image: 'http://placekitten.com/221/200',
    text: 'Kitten.'
  }, {
    image: 'http://placekitten.com/241/200',
    text: 'Kitty!'
  }, {
    image: 'http://placekitten.com/223/200',
    text: 'Cat.'
  }, {
    image: 'http://placekitten.com/224/200',
    text: 'Feline!'
  }, {
    image: 'http://placekitten.com/225/200',
    text: 'Cat.'
  }, {
    image: 'http://placekitten.com/226/200',
    text: 'Feline!'
  }, {
    image: 'http://placekitten.com/227/200',
    text: 'Cat.'
  }, {
    image: 'http://placekitten.com/228/200',
    text: 'Feline!'
  }, {
    image: 'http://placekitten.com/229/200',
    text: 'Cat.'
  }, {
    image: 'http://placekitten.com/230/200',
    text: 'Feline!'
  }];


    var i, first = [],
      second, third;
    var many = 1;

    //##################################################    
    //Need to be changed to update the carousel since the resolution changed
    $scope.displayMode = "tablet";
    //##################################################
    if ($scope.displayMode == "mobile") {many = 1;}
    else if ($scope.displayMode == "tablet") {many = 2;} 
    else {many = 3;}

    for (i = 0; i < $scope.slides.length; i += many) {
      second = {
        image1: $scope.slides[i]
      };
      if (many == 1) {}
      if ($scope.slides[i + 1] && (many == 2 || many == 3)) {
        second.image2 = $scope.slides[i + 1];

      }
      if ($scope.slides[i + (many - 1)] && many == 3) {
        second.image3 = $scope.slides[i + 2];
      }
      first.push(second);
    }
    $scope.groupedSlides = first;
}

app.directive('dnDisplayMode', function($window) {
  return {
    restrict: 'A',
    scope: {
      dnDisplayMode: '='
    },
    template: '<span class="mobile"></span><span class="tablet"></span><span class="tablet-landscape"></span><span class="desktop"></span>',
    link: function(scope, elem, attrs) {
      var markers = elem.find('span');

      function isVisible(element) {
        return element && element.style.display != 'none' && element.offsetWidth && element.offsetHeight;
      }

      function update() {
        angular.forEach(markers, function(element) {
          if (isVisible(element)) {
            scope.dnDisplayMode = element.className;
            return false;
          }
        });
      }

      var t;
      angular.element($window).bind('resize', function() {
        clearTimeout(t);
        t = setTimeout(function() {
          update();
          scope.$apply();
        }, 300);
      });

      update();
    }
  };
});

I trust this provides some valuable insight!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Eliminate the pull-to-refresh feature in Safari browser on React Native applications

Hi there! I recently created an app with react native. However, when using Safari browser and trying to pull the page down, a refresh loader appears. I would like to disable this feature in the Safari browser. Any suggestions on how to remove the pull to ...

Transmit an array of JavaScript objects using Email

Within the code layout provided with this post, I have executed various operations in JavaScript which resulted in an array of objects named MyObjects. Each object within MyObjects contains properties for Name and Phone, structured as follows: MyObject ...

Error Encountered When Updating cGridView in Yii: "TypeError: $.fn.yiiGridView is undefined"

I'm encountering an issue with updating the gridview TypeError: $.fn.yiiGridView is undefined; after using AjaxLink Click Button for Refresh <script> $(document).ready(function(){ $("#tombol_refresh").click(function(){ $.fn.yiiGridView ...

A static method written in Typescript within an abstract class for generating a new instance of the class itself

Imagine I have abstract class Foo { } class Bar1 extends Foo { constructor(someVar) { ... } } class Bar2 extends Foo { constructor(someVar) { ... } } I want to create a static method that generates an instance of the final class (all construct ...

Troubleshooting the pushstate back function in HTML5 and jQuery

In my code, I have implemented an ajax call to load content dynamically. I am now looking to add a deeplinking effect, and after researching, I discovered that only raw coding can achieve this. Here is what I have implemented so far: jQuery("#sw_layered_c ...

Adding an element to a blank array using Angular

When attempting to add a new item to an empty array, I encounter an error: $scope.array.push is not a function. However, when the array is not empty, the push operation works flawlessly and updates my scope correctly. Just so you know, my array is initia ...

Image placed as background for registration form

In my Vue project, I am trying to create a login form with an image as the background. However, I am facing an issue where the image is not displaying on the page. Can someone guide me on how to add a picture behind the form? HTML: Below is the HTML code ...

Is it possible to bypass preflighting when using $http requests?

My current setup involves nginx on the remote server, but unfortunately there is no support for the OPTIONS method. This has led to a frustrating situation where the server and angular are unable to communicate effectively. All I want to do is send a basi ...

An Issue with Ionic Modal Dismissing

During the development of a small app, I encountered an interesting "bug" that I believe is worth mentioning here. The issue revolves around a modal that contains a simple login form. Upon submitting the form data, it triggers the login() method as shown i ...

Angular application with Material Design integration

I've been struggling to implement material design into my angular app, but I'm facing some challenges. After installing material design and adding all the necessary modules to the app.moduel.ts file, the components are not displaying correctly. ...

Emergence of content missing on initial slide in a jQuery carousel

I am currently working on a website that includes a jQuery image slider. However, I have encountered an issue where in IE7, the text of the first slide does not show up until just before the script starts to change slides. After that, it displays correctl ...

Leveraging Javascript/Jquery for numbering items in a list

This is a snippet of HTML code that I am working with: <ul> <li data-slide-to="0" data-target="#myCarousel" class="appendLi"></li> <li data-slide-to="0" data-target="#myCarousel" class="appendLi"></li> <li data ...

What is a more dynamic way to assign attributes to elements without directly embedding them in the HTML code?

For my unique scenario, my goal is to assign the attribute target = "_blank" to all <a> elements within a specific div in order to open them in new tabs. This concept could potentially be applied to any element and any attribute. I am curious if the ...

When clicking, the drop-down feature is malfunctioning as all the menus are dropping down simultaneously

I have been trying to implement a dropdown on click feature for my website, but it is not functioning as intended. () When I click on button 1, button 2 also drops down unexpectedly. This behavior is not desired. Below is the code snippet from the page: ...

Error Message in Three.js: "Function is not defined in Perspective Camera"

My program was functioning well, but now I'm encountering the "undefined is not a function" error within the three.js file. The problematic line is 10466 in the uncompressed library, specifically within the declaration of THREE.PerspectiveCamera. Wher ...

Using jqGrid to load additional JSON data after the initial local data has already been populated in the

I encountered a specific issue: I have a compact form with four choices. Users can choose to fill them out or not, and upon clicking 'Ok', a jqGrid is loaded with data based on those selections. To accommodate dynamic column formatting, my servle ...

Using Java Script to adjust dimensions in a webpage

As a newcomer to JS, I encountered my first simple problem that I can't seem to solve. Currently working on a basic website using an online editor, I decided to add a shoutbox from shoutbox.com In order to use the shoutbox, I embedded it in an HTML ...

Synchronization Issue between Ionic Popover templateURL and Angular ng-model

In my project utilizing the Ionic framework, I encountered an issue with the code snippet below: $scope.loginCountryCode; $scope.loginPhone; // Code continues... <div class="container"> <label class="item item-input&quo ...

Customizing the starting number of rows per page in TablePagination from material-ui

As a newcomer to using materials, I am looking to customize the table pagination to show 'n' number of rows, for example 10, and remove the "Rows per page" dropdown. <TablePagination rowsPerPageOptions={[]} component="div" ...

How can you organize an array into rows and columns for easier viewing?

Hopefully everything is clear. I am open to making changes if needed to address any important points. In one of my components, the array items are displayed within cards as shown below: <b-card-group deck class="mb-3"> <b-card border-variant ...