6

Stackoverflow helped me too much with current version, but currently I am completely lost as I don't know how to solve one issue. I will be really thankful for any advice.

I have product container with parameters. They show up on mouse :hover (done with css). Problem is that if somebody will tap on mobile, it will fire both events: click and mouseover. But I need different behavior for mobile devices. So I used solution from stackoverflow where I can check if browser knows touchstart event. It works fine until somebody will come with touchable screen, but using mouse. So this user will click on container and parameters will show up without redirecting to product detail. But it is wrong for mouse behavior.

What I need is that if somebody will tap on image, it will first show up parameters and on second tap it will redirect to product detail (different behavior is only on tap on button which automatically redirects user to product detail). But if somebody will use mouse, we have :hover effect, so even first click on image can redirect user to product detail page.

Current javascript code is commented so there is workaround what works fine on desktop and mobiles. But it doesn't work on hybrid devices with touchable screen with mouse. Commented code is how I thought about solution as I added there workaround with mouseenter/mouseleave functions. This doesn't work for mobile devices as they also fire those events. Same problem is with touchstart/touchend events.

Can anybody help, please?

/*var usedMouse = false;

$('.products-grid .container:not(.over)').mouseenter(function() {
  usedMouse = true;
});*/

$('.products-grid .container:not(.over)').tap(function(e) {
  if (!!('ontouchstart' in window)/* && !usedMouse*/) {
    // location change if already hovered or tap target is button
    if ($(this).hasClass('over') || $(e.target).hasClass('button')) {
      $(this).addClass('detail'); // add detail - disable hover effect on actual container
      return true;
    }

    e.preventDefault();
    e.stopPropagation();

    $('.products-grid .container').removeClass('over'); // remove all over effects
    $(this).addClass('over'); // add over effect to actual container
    return false; // do nothing because script made over effect
  }
});

/*$('.products-grid .container:not(.over)').mouseleave(function() {
  usedMouse = false;
});*/
.products-grid {
  width: 100%;
  text-align: center;
}
.products-grid .row,
.std .products-grid .row {
  margin: 0 0 0 -22px;
  text-align: left;
}
.products-grid .row > .leftcolumn {
  float: left;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  width: 33.33%;
  margin: 0;
  padding: 0 0 0 22px;
}
.products-grid .row .product-image {
  overflow: hidden;
  display: block;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  width: 100%;
  height: auto;
  border: 1px solid #c9d5d8;
}
.products-grid .row .product-image img {
  display: block;
  width: 100% !important;
  height: auto !important;
  margin: 0;
}
.products-grid .clear,
.std .products-grid .clear {
  clear: both;
  margin: 0;
}
.products-grid .container {
  position: relative;
  margin: 0 0 50px;
}
.products-grid .options-wrapper {
  position: relative;
  overflow: hidden;
  width: 100%;
  margin: 0;
  padding-top: 5px;
}
.products-grid .parameters,
.products-grid .container.detail > .options-wrapper > .parameters,
.products-grid .container.detail:hover > .options-wrapper > .parameters {
  position: absolute;
  left: 0;
  right: 0;
  -webkit-transition: all 250ms linear;
  -moz-transition: all 250ms linear;
  -ms-transition: all 250ms linear;
  -o-transition: all 250ms linear;
  transition: all 250ms linear;
  -webkit-transform: translateX(-100%);
  -moz-transform: translateX(-100%);
  -ms-transform: translateX(-100%);
  -o-transform: translateX(-100%);
  transform: translateX(-100%);
  margin-top: -5px;
  padding-top: 66px;
  background: #eff9ff;
}
.products-grid .container:hover > .options-wrapper > .parameters,
.products-grid .container.over > .options-wrapper > .parameters {
  -webkit-transform: translateX(0%);
  -moz-transform: translateX(0%);
  -ms-transform: translateX(0%);
  -o-transform: translateX(0%);
  transform: translateX(0%);
}
.products-grid .parameters .size-wrapper {
  height: auto;
  border-bottom: 0 none;
}
.products-grid .parameters span {
  overflow: hidden;
  float: left;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  width: 50%;
  height: 33px;
  border-bottom: 1px solid #bdccd4;
  padding-left: 10px;
  white-space: nowrap;
  font-size: 13px;
  color: #5f727c;
  line-height: 30px;
}
.products-grid .name-box,
.std .products-grid .name-box {
  position: relative;
  margin: 0;
}
.products-grid h3,
.std .products-grid h3 {
  overflow: hidden;
  height: 42px;
  margin: 15px 12px 18px;
  white-space: normal;
  font-size: 18px;
  font-weight: 700;
  color: #000;
  line-height: 21px;
}
.products-grid h3 a {
  text-decoration: none;
  font-weight: bold;
  color: #000;
}
.products-grid h3 a:hover {
  text-decoration: none;
}
.products-grid .description {
  overflow: hidden;
  height: 40px;
  margin: 0 12px 11px;
  font-size: 14px;
  font-weight: 400;
  color: #81929c;
  line-height: 20px;
}
.products-grid .description p {
  margin: 0;
  padding: 0;
}
.price_wrapper,
.std .price_wrapper {
    margin: 0;
    border-top: 1px solid #bdccd4;
    border-bottom: 1px solid #bdccd4;
    padding: 9px 8px 10px;
}
.price_wrapper:after {
    content: ' ';
    clear: both;
    display: block;
}
.price_wrapper .addToCart {
  float: right;
}
.price_wrapper a.button {
  float: right;
  width: 136px;
  height: 39px;
  background-color: #a5c82d;
  text-align: center;
  text-decoration: none;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  line-height: 39px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.5/jquery.mobile.min.js"></script>
<div class="products-grid">
  <div class="row">
    <div class="leftcolumn">
      <div class="container">
        <a class="product-image" href="#">
          <img src="http://dummyimage.com/316x210/eee/333333.png" alt="product name" title="Product Name">
        </a>
        <div class="options-wrapper">
          <div class="parameters">
            <div class="size-wrapper">
              <span class="height">Height 95.2 cm</span>
              <span class="width">Width 210.5 cm</span>
              <span class="length">Length 187.5 cm</span>
              <span class="color"></span>
            </div>
          </div>

          <div class="name-box">
            <h3 class="product-name"><a href="#" title="Product Name">Product Name</a></h3>
          </div>

          <div class="description">Description</div>
        </div>
        <div class="price_wrapper">
          <a class="button" href="#">Detail</a>
        </div>
      </div>
    </div>
  </div>
</div>
Maju
  • 616
  • 4
  • 9
  • 2
    Hi, I don't think you should use mouseenter/mouseleave events Take a look at this thread (modernizr answer) : http://stackoverflow.com/questions/11406285/determine-and-bind-click-or-touch-event In my opinion, you should detect was that a click or touch first, then count the number of touches / do what you like – Benji Sep 05 '16 at 09:18
  • Thanks for your advice. It helped me to create own solution - so I didn't use modernizr. Tested today and it works fine. – Maju Sep 07 '16 at 10:33

1 Answers1

0

This solution helped me to solve my issue (thanks to @booboos):

    // mark as mobile clicked
    $('.products-grid .container:not(.over)').touchstart(function() {
        this.mobileClick = true;
    });

    // unmark mobile click
    $('.products-grid .container:not(.over)').touchmove(function() {
        this.mobileClick = false;
    });

    // if mobile click is unmarked - delete mark property
    $('.products-grid .container:not(.over)').touchend(function() {
        if (this.mobileClick === false)
            delete this.mobileClick;
    });

    // check if there was mobile click and create new behavior for screen taps
    $('.products-grid .container:not(.over)').tap(function(e) {

        if (typeof this.mobileClick === 'undefined')
            return true;

        e.preventDefault();

        if (this.mobileClick === true) {
            if ($(this).hasClass('over') || $(e.target).hasClass('button')) {
                $(this).addClass('detail'); // add detail - disable hover effect on actual container
                window.location.href = $(this).find('.button').attr('href');
            }

            $('.products-grid .container').removeClass('over'); // remove all over effects
            $(this).addClass('over'); // add over effect to actual container

            delete this.mobileClick;
        }
    });
  1. touchstart creates property mobileClick on touched container element
  2. touchmove will disable the property
  3. touchend event just remove property if there was touchmove event before
  4. tap on container will check if there is active mobileClick property on element and if it is there - script will first add class "over" to the container element and if the container has over class then next time it will redirect user to detail page. This event also removes mobileClick property at the end. So I can be sure that next time touch is really touch.
Maju
  • 616
  • 4
  • 9