Ergebnis 1 bis 9 von 9

Thema: Mobiles Seitenlayout für Contao 4.8+

  1. #1
    Contao-Nutzer
    Registriert seit
    15.08.2009.
    Beiträge
    187

    Standard Mobiles Seitenlayout für Contao 4.8+

    Hallo zusamen,

    wir nutzen das Modul aktuell mit Contao 4.13.39. Die mobile Navigation hat unter 4.4.57 fehlerfrei funktioniert. Mir ist heute ein Kuriosum aufgefallen, wenn man auf die Seite kommt wird das Hamburger Menü mit der Haupt- und Subnavigation angezeigt. Klickt man eine Unterseite an, wird das Hamburger Menü nicht mehr angezeigt. Dreht man das Smartphone auf Querformat, wird es angezeigt. Danach wird es auch im Hochformat angezeigt. Klickt man dann eine andere Seite an, gleicher Fehler.

    Eigener JavaScript-Code im Seitenlayout:

    Code:
    <script src="files/theme_files/responsive_navigation/jquery.responsinav.min.js"></script>
    <script>
    $(function(){
        $(window).responsinav({ breakpoint: 1139 });
    });
    </script>
    <script type="text/javascript" src="files/theme_files/quicksand/jquery.quicksand.js"></script>
    <script type="text/javascript" src="files/theme_files/quicksand/quicksand.js"></script>

    jquery.quicksand.js
    Code:
    /*
    
    
    Quicksand 1.3
    
    Reorder and filter items with a nice shuffling animation.
    
    Copyright (c) 2010 Jacek Galanciak (razorjack.net) and agilope.com
    Big thanks for Piotr Petrus (riddle.pl) for deep code review and wonderful docs & demos.
    
    Dual licensed under the MIT and GPL version 2 licenses.
    http://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt
    http://github.com/jquery/jquery/blob/master/GPL-LICENSE.txt
    
    Project site: http://razorjack.net/quicksand
    Github site: http://github.com/razorjack/quicksand
    
     */
    
    (function($) {
      $.fn.quicksand = function(collection, customOptions) {
        var options = {
          duration : 750,
          easing : 'swing',
          attribute : 'data-id',        // attribute to recognize same items within source and dest
          adjustHeight : 'auto',        // 'dynamic' animates height during shuffling (slow), 'auto' adjusts it
                                        // before or after the animation, false leaves height constant
          adjustWidth : 'auto',         // 'dynamic' animates width during shuffling (slow), 
                                        // 'auto' adjusts it before or after the animation, false leaves width constant
          useScaling : false,           // enable it if you're using scaling effect
          enhancement : function(c) {}, // Visual enhacement (eg. font replacement) function for cloned elements
          selector : '> *',
          atomic : false,
          dx : 0,
          dy : 0,
          maxWidth : 0,
          retainExisting : true         // disable if you want the collection of items to be replaced completely by incoming items.
        };
        $.extend(options, customOptions);
    
        // Got IE and want scaling effect? Kiss my ass.
        if (navigator.userAgent.match(/msie/i) || (typeof ($.fn.scale) == 'undefined')) {
          options.useScaling = false;
        }
    
        var callbackFunction;
        if (typeof (arguments[1]) == 'function') {
          callbackFunction = arguments[1];
        } else if (typeof (arguments[2] == 'function')) {
          callbackFunction = arguments[2];
        }
    
        return this.each(function(i) {
          var val;
          var animationQueue = []; // used to store all the animation params before starting the animation;
          // solves initial animation slowdowns
          var $collection;
          if (typeof(options.attribute) == 'function') {
            $collection = $(collection);
          } else {
            $collection = $(collection).filter('[' + options.attribute + ']').clone(); // destination (target) collection
          }
          var $sourceParent = $(this); // source, the visible container of source collection
          var sourceHeight = $(this).css('height'); // used to keep height and document flow during the animation
          var sourceWidth = $(this).css('width'); // used to keep  width and document flow during the animation
          var destHeight, destWidth;
          var adjustHeightOnCallback = false;
          var adjustWidthOnCallback = false;
          var offset = $($sourceParent).offset(); // offset of visible container, used in animation calculations
          var offsets = []; // coordinates of every source collection item
          var $source = $(this).find(options.selector); // source collection items
          var width = $($source).innerWidth(); // need for the responsive design
    
          // Replace the collection and quit if IE6
          if (navigator.userAgent.match(/msie/i) && navigator.userAgent.match(/6/)) {
            $sourceParent.html('').append($collection);
            return;
          }
    
          // Gets called when any animation is finished
          var postCallbackPerformed = 0; // prevents the function from being called more than one time
          var postCallback = function() {
            $(this).css('margin', '').css('position', '').css('top', '').css('left', '').css('opacity', '');
            if (!postCallbackPerformed) {
              postCallbackPerformed = 1;
    
              if (!options.atomic) {
                // hack: used to be: $sourceParent.html($dest.html()); 
                // put target HTML into visible source container  
                // but new webkit builds cause flickering when replacing the collections
                var $toDelete = $sourceParent.find(options.selector);
                if (!options.retainExisting) {
                  $sourceParent.prepend($dest.find(options.selector));
                  $toDelete.remove();
                } else {
                  // Avoid replacing elements because we may have already altered items in significant
                  // ways and it would be bad to have to do it again. (i.e. lazy load images) 
                  // But $dest holds the correct ordering. So we must re-sequence items in $sourceParent to match.
                  var $keepElements = $([]);
                  $dest.find(options.selector).each(function(i) {
                    var $matchedElement = $([]);
                    if (typeof (options.attribute) == 'function') {
                      var val = options.attribute($(this));
                      $toDelete.each(function() {
                        if (options.attribute(this) == val) {
                          $matchedElement = $(this);
                          return false;
                        }
                      });
                    } else {
                      $matchedElement = $toDelete.filter(
                        '[' + options.attribute + '="'+ 
                        $(this).attr(options.attribute) + '"]');
                    }
                    if ($matchedElement.length > 0) {
                      // There is a matching element in the $toDelete list and in $dest
                      // list, so make sure it is in the right location within $sourceParent
                      // and put it in the list of elements we need to not delete.
                      $keepElements = $keepElements.add($matchedElement);
                      if (i === 0) {
                        $sourceParent.prepend($matchedElement);
                      } else {
                        $matchedElement.insertAfter($sourceParent.find(options.selector).get(i - 1));
                      }
                    }
                  });
                  // Remove whatever is remaining from the DOM
                  $toDelete.not($keepElements).remove();
                }
    
                if (adjustHeightOnCallback) {
                  $sourceParent.css('height', destHeight);
                }
                if (adjustWidthOnCallback) {
                  $sourceParent.css('width', sourceWidth);
                }
              }
              options.enhancement($sourceParent); // Perform custom visual enhancements on a newly replaced collection
              if (typeof callbackFunction == 'function') {
                callbackFunction.call(this);
              }
            }
    
            if (false === options.adjustHeight) {
              $sourceParent.css('height', 'auto');
            }
    
            if (false === options.adjustWidth) {
              $sourceParent.css('width', 'auto');
            }
          };
    
          // Position: relative situations
          var $correctionParent = $sourceParent.offsetParent();
          var correctionOffset = $correctionParent.offset();
          if ($correctionParent.css('position') == 'relative') {
            if ($correctionParent.get(0).nodeName.toLowerCase() != 'body') {
              correctionOffset.top += (parseFloat($correctionParent.css('border-top-width')) || 0);
              correctionOffset.left += (parseFloat($correctionParent.css('border-left-width')) || 0);
            }
          } else {
            correctionOffset.top -= (parseFloat($correctionParent.css('border-top-width')) || 0);
            correctionOffset.left -= (parseFloat($correctionParent.css('border-left-width')) || 0);
            correctionOffset.top -= (parseFloat($correctionParent.css('margin-top')) || 0);
            correctionOffset.left -= (parseFloat($correctionParent.css('margin-left')) || 0);
          }
    
          // perform custom corrections from options (use when Quicksand fails to detect proper correction)
          if (isNaN(correctionOffset.left)) {
            correctionOffset.left = 0;
          }
          if (isNaN(correctionOffset.top)) {
            correctionOffset.top = 0;
          }
    
          correctionOffset.left -= options.dx;
          correctionOffset.top -= options.dy;
    
          // keeps nodes after source container, holding their position
          $sourceParent.css('height', $(this).height());
          $sourceParent.css('width', $(this).width());
    
          // get positions of source collections
          $source.each(function(i) {
            offsets[i] = $(this).offset();
          });
    
          // stops previous animations on source container
          $(this).stop();
          var dx = 0;
          var dy = 0;
          $source.each(function(i) {
            $(this).stop(); // stop animation of collection items
            var rawObj = $(this).get(0);
            if (rawObj.style.position == 'absolute') {
              dx = -options.dx;
              dy = -options.dy;
            } else {
              dx = options.dx;
              dy = options.dy;
            }
    
            rawObj.style.position = 'absolute';
            rawObj.style.margin = '0';
    
            if (!options.adjustWidth) {
              rawObj.style.width = (width + 'px'); // sets the width to the current element
              // with even if it has been changed
              // by a responsive design
            }
    
            rawObj.style.top = (offsets[i].top- parseFloat(rawObj.style.marginTop) - correctionOffset.top + dy) + 'px';
            rawObj.style.left = (offsets[i].left- parseFloat(rawObj.style.marginLeft) - correctionOffset.left + dx) + 'px';
    
            if (options.maxWidth > 0 && offsets[i].left > options.maxWidth) {
              rawObj.style.display = 'none';
            }
          });
    
          // create temporary container with destination collection
          var $dest = $($sourceParent).clone();
          var rawDest = $dest.get(0);
          rawDest.innerHTML = '';
          rawDest.setAttribute('id', '');
          rawDest.style.height = 'auto';
          rawDest.style.width = $sourceParent.width() + 'px';
          $dest.append($collection);
          // Inserts node into HTML. Note that the node is under visible source container in the exactly same position
          // The browser render all the items without showing them (opacity: 0.0) No offset calculations are needed, 
          // the browser just extracts position from underlayered destination items and sets animation to destination positions.
          $dest.insertBefore($sourceParent);
          $dest.css('opacity', 0.0);
          rawDest.style.zIndex = -1;
    
          rawDest.style.margin = '0';
          rawDest.style.position = 'absolute';
          rawDest.style.top = offset.top - correctionOffset.top + 'px';
          rawDest.style.left = offset.left - correctionOffset.left + 'px';
    
          if (options.adjustHeight === 'dynamic') {
            // If destination container has different height than source container the height can be animated,
            // adjusting it to destination height
            $sourceParent.animate({ height : $dest.height() }, options.duration, options.easing);
          } else if (options.adjustHeight === 'auto') {
            destHeight = $dest.height();
            if (parseFloat(sourceHeight) < parseFloat(destHeight)) {
              // Adjust the height now so that the items don't move out of the container
              $sourceParent.css('height', destHeight);
            } else {
              // Adjust later, on callback
              adjustHeightOnCallback = true;
            }
          }
    
          if (options.adjustWidth === 'dynamic') {
            // If destination container has different width than source container the width can be animated, 
            // adjusting it to destination width
            $sourceParent.animate({ width : $dest.width() }, options.duration, options.easing);
          } else if (options.adjustWidth === 'auto') {
            destWidth = $dest.width();
            if (parseFloat(sourceWidth) < parseFloat(destWidth)) {
              // Adjust the height now so that the items don't move out of the container
              $sourceParent.css('width', destWidth);
            } else {
              // Adjust later, on callback
              adjustWidthOnCallback = true;
            }
          }
    
          // Now it's time to do shuffling animation. First of all, we need to identify same elements within
          // source and destination collections
          $source.each(function(i) {
            var destElement = [];
            if (typeof (options.attribute) == 'function') {
              val = options.attribute($(this));
              $collection.each(function() {
                if (options.attribute(this) == val) {
                  destElement = $(this);
                  return false;
                }
              });
            } else {
              destElement = $collection.filter('[' + options.attribute + '="' + $(this).attr(options.attribute) + '"]');
            }
            if (destElement.length) {
              // The item is both in source and destination collections. It it's under different position, let's move it
              if (!options.useScaling) {
                animationQueue.push({
                  element : $(this), dest : destElement,
                  style : {
                    top : $(this).offset().top,
                    left : $(this).offset().left,
                    opacity : ""
                  },
                  animation : {
                    top : destElement.offset().top - correctionOffset.top,
                    left : destElement.offset().left - correctionOffset.left,
                    opacity : 1.0
                  }
                });
              } else {
                animationQueue.push({
                  element : $(this), dest : destElement,
                  style : {
                    top : $(this).offset().top,
                    left : $(this).offset().left,
                    opacity : ""
                  },
                  animation : {
                    top : destElement.offset().top - correctionOffset.top,
                    left : destElement.offset().left - correctionOffset.left,
                    opacity : 1.0,
                    scale : '1.0'
                  }
                });
              }
            } else {
              // The item from source collection is not present in destination collections.  Let's remove it
              if (!options.useScaling) {
                animationQueue.push({
                  element : $(this),
                  style : {
                    top : $(this).offset().top,
                    left : $(this).offset().left,
                    opacity : ""
                  },
                  animation : {
                    opacity : '0.0'
                  }
                });
              } else {
                animationQueue.push({
                  element : $(this),
                  animation : {
                    opacity : '0.0',
                    style : {
                      top : $(this).offset().top,
                      left : $(this).offset().left,
                      opacity : ""
                    },
                    scale : '0.0'
                  }
                });
              }
            }
          });
    
          $collection.each(function(i) {
            // Grab all items from target collection not present in visible source collection
            var sourceElement = [];
            var destElement = [];
            if (typeof (options.attribute) == 'function') {
              val = options.attribute($(this));
              $source.each(function() {
                if (options.attribute(this) == val) {
                  sourceElement = $(this);
                  return false;
                }
              });
    
              $collection.each(function() {
                if (options.attribute(this) == val) {
                  destElement = $(this);
                  return false;
                }
              });
            } else {
              sourceElement = $source.filter('[' + options.attribute + '="' + $(this).attr(options.attribute) + '"]');
              destElement = $collection.filter('[' + options.attribute + '="' + $(this).attr(options.attribute) + '"]');
            }
    
            var animationOptions;
            if (sourceElement.length === 0 && destElement.length > 0) {
    
              // No such element in source collection...
              if (!options.useScaling) {
                animationOptions = {opacity : '1.0'};
              } else {
                animationOptions = {opacity : '1.0', scale : '1.0'};
              }
    
              // Let's create it
              var d = destElement.clone();
              var rawDestElement = d.get(0);
              rawDestElement.style.position = 'absolute';
              rawDestElement.style.margin = '0';
    
              if (!options.adjustWidth) {
                // sets the width to the current element with even if it has been changed by a responsive design
                rawDestElement.style.width = width + 'px'; 
              }
    
              rawDestElement.style.top = destElement.offset().top - correctionOffset.top + 'px';
              rawDestElement.style.left = destElement.offset().left - correctionOffset.left + 'px';
    
              d.css('opacity', 0.0); // IE
    
              if (options.useScaling) {
                d.css('transform', 'scale(0.0)');
              }
              d.appendTo($sourceParent);
    
              if (options.maxWidth === 0 || destElement.offset().left < options.maxWidth) {
                animationQueue.push({element : $(d), dest : destElement,animation : animationOptions});
              }
            }
          });
    
          $dest.remove();
          if (!options.atomic) {
            options.enhancement($sourceParent); // Perform custom visual enhancements during the animation
            for (i = 0; i < animationQueue.length; i++) {
              animationQueue[i].element.animate(animationQueue[i].animation, options.duration, options.easing, postCallback);
            }
          } else {
            $toDelete = $sourceParent.find(options.selector);
            $sourceParent.prepend($dest.find(options.selector));
            for (i = 0; i < animationQueue.length; i++) {
              if (animationQueue[i].dest && animationQueue[i].style) {
                var destElement = animationQueue[i].dest;
                var destOffset = destElement.offset();
    
                destElement.css({
                  position : 'relative',
                  top : (animationQueue[i].style.top - destOffset.top),
                  left : (animationQueue[i].style.left - destOffset.left)
                });
    
                destElement.animate({top : "0", left : "0"}, 
                                    options.duration, 
                                    options.easing, 
                                    postCallback);
              } else {
                animationQueue[i].element.animate(animationQueue[i].animation, 
                                                  options.duration, 
                                                  options.easing,
                                                  postCallback);
              }
            }
            $toDelete.remove();
          }
        });
      };
    })(jQuery);

    quicksand.js
    Code:
    $(document).ready(function(){
    	
    	var items = $('#container .mod_newslist li'),
    		itemsByTags = {};
    	
    	// Looping though all the li items:
    	
    	items.each(function(i){
    		var elem = $(this),
    			tags = elem.data('tags').split(',');
    		
    		// Adding a data-id attribute. Required by the Quicksand plugin:
    		elem.attr('data-id',i);
    		
    		$.each(tags,function(key,value){
    			
    			// Removing extra whitespace:
    			value = $.trim(value);
    			
    			if(!(value in itemsByTags)){
    				// Create an empty array to hold this item:
    				itemsByTags[value] = [];
    			}
    			
    			// Each item is added to one array per tag:
    			itemsByTags[value].push(elem);
    		});
    		
    	});
    
    	// Creating the "Everything" option in the menu:
    	createList('Everything',items);
    
    	// Looping though the arrays in itemsByTags:
    	$.each(itemsByTags,function(k,v){
    		createList(k,v);
    	});
    	
    	$('#portfolio_filter').on('click', 'a', function(e){
    		var link = $(this);
    		
    		link.addClass('active').siblings().removeClass('active');
    		
    		// Using the Quicksand plugin to animate the li items.
    		// It uses data('list') defined by our createList function:
    		
    		$('#container .mod_newslist').quicksand(link.data('list').find('li'));
    		e.preventDefault();
    	});
    	
    	$('#portfolio_filter a:first').click();
    	
    	function createList(text,items){
    		
    		// This is a helper function that takes the
    		// text of a menu button and array of li items
    		
    		// Creating an empty unordered list:
    		var ul = $('<ul>',{'class':'hidden'});
    		
    		$.each(items,function(){
    			// Creating a copy of each li item
    			// and adding it to the list:
    			
    			$(this).clone().appendTo(ul);
    		});
    
    		ul.appendTo('#container');
    
    		// Creating a menu item. The unordered list is added
    		// as a data parameter (available via .data('list'):
    		
    		var a = $('<a>',{
    			html: text,
    			href:'#',
    			data: {list:ul}
    		}).appendTo('#portfolio_filter');
    	}
    });
    Jemand eine Idee, woran das liegen könnte?
    Geändert von derolli (01.04.2024 um 10:05 Uhr)

  2. #2
    Contao-Fan
    Registriert seit
    24.02.2021.
    Beiträge
    459

    Standard

    Die Antwort ist 42.

    Du zeigst uns den Code einer Shuffle-Animation von irgendwelchen Items und fragst nach einer Lösung der Responsive-Navigation.
    Poste einmal diesen Code
    PHP-Code:
    <script src="files/theme_files/responsive_navigation/jquery.responsinav.min.js"></script> 

  3. #3
    Contao-Nutzer
    Registriert seit
    15.08.2009.
    Beiträge
    187

    Standard

    Code:
    (function($){$.fn.responsinav=function(o){var o=jQuery.extend({breakpoint:480},o);rn_mode=undefined;sub_nav_bind=false
    $(window).bind('load resize',function(){if($(window).width()<=o.breakpoint){if(rn_mode==0||rn_mode==undefined){nav.reset();nav.mobile();}}else{if(rn_mode==1||rn_mode==undefined){nav.reset();nav.full();}}});nav={reset:function(){$('.mainmenu>ul li').unbind('mouseenter mouseleave click');$('.mainmenu .sub_nav').unbind('click').remove();},full:function(){rn_mode=0;$('.mainmenu>ul').show();$('.mainmenu ul ul').hide();$(".mainmenu>ul li").hover(function(){var timeout=$(this).data("timeout");if(timeout)clearTimeout(timeout);$(this).children("ul").slideDown(300).css({'z-index':curz++});},function(){$(this).data("timeout",setTimeout($.proxy(function(){$(this).find("ul").slideUp(300);},this),300));});},mobile:function(){rn_mode=1;$('.mainmenu>ul').hide();if($('.mainmenu>a.mobile_handle').length==0){$('<a class="mobile_handle"><i class="icon-reorder"></i></a>').insertBefore('.mainmenu ul.level_1');}$('.mainmenu>a.mobile_handle').unbind('click');$('.mainmenu>a.mobile_handle').click(function(){$('.mainmenu>ul').slideToggle(300);});if($('.sub_nav').length==0){$('.mainmenu ul li').each(function(){if($(this).children('ul').length>0){$('<a class="sub_nav"><i class="icon-angle-down"></i></a>').appendTo(this);}});}if(sub_nav_bind==false){$('.mainmenu>ul').delegate('.sub_nav','click',function(e){$(this).siblings('ul').slideToggle(300);if($(this).children('i').hasClass('icon-angle-down')){$(this).children('i').attr('class','icon-angle-up');}else{$(this).children('i').attr('class','icon-angle-down');}});sub_nav_bind=true;}}};};})(jQuery);

  4. #4
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.126
    Partner-ID
    10107

    Standard

    Was genau meinst du mit "das Modul"?
    » sponsor me via GitHub or PayPal or Revolut

  5. #5
    Contao-Nutzer
    Registriert seit
    15.08.2009.
    Beiträge
    187

    Standard

    Verstehe die Frage nicht.

  6. #6
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.126
    Partner-ID
    10107

    Standard

    Du hast in deinem initialen Post geschrieben "wir nutzen das Modul", aber es ist nicht klar von welchem "Modul" du überhaupt sprichst.
    » sponsor me via GitHub or PayPal or Revolut

  7. #7
    Contao-Fan
    Registriert seit
    24.02.2021.
    Beiträge
    459

    Standard

    Zudem kenne ich gerade auch nur diese Erweiterung, die nutzt auch kein JQuery?
    https://extensions.contao.org/?q=mob...-layout-bundle

    Sprichst du hier von einer mobilen Navigation? Falls, ja, geht es hier nur um das jQuery?

    Das responsive_navigation/jquery.responsinav.min.js hat einen Breakpoint von 480, welchen du über deine Einstellung im HTML erweiterst, nicht überschreibst:
    HTML-Code:
    <script>....... var o = jQuery.extend({ breakpoint: 480 }, o);</script>
    <script>
    $(function(){
        $(window).responsinav({ breakpoint: 1139 });
    });
    </script>
    Schaue in die Browser-Konsole und lese die Errors aus. Hat sich die jQuery-Version geändert (Von 1 auf 3???).
    Musst du vielleicht eine ältere Version von jQuery einbinden?

    Falls es nur um das Script geht, dann ist das hier eher Offtopic und im Internet gibt es sicherlich mit einem existierenden Fehler der Browser-Konsole schon über 100+ Lösungen.

  8. #8
    Contao-Nutzer
    Registriert seit
    15.08.2009.
    Beiträge
    187

    Standard

    Achso. Steht im Titel. Mobiles Seitenlayout für Contao 4.8+.

  9. #9
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.126
    Partner-ID
    10107

    Standard

    Mit diesem Bundle kannst du abhängig vom User-Agent andere Seitenlayouts definieren. Das dürfte aber nichts mit deinem eigentlichen Problem zu tun haben? Das von dir erwähnte jQuery Plugin ist jedenfalls nicht Teil davon.
    » sponsor me via GitHub or PayPal or Revolut

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •