Я работаю над динамическим селектором моделей Model-> Submodel на веб-сайте электронной коммерции (ведущий BigCommerce). Я разработал структуру трафарета для создания страниц со своими «детьми». «Модели» отображаются с функцией щелчка, чтобы показать «подмодели» под ними в ряд. Мне помогал друг с сценарием, чтобы настроить способ отображения и организации подмоделей. Я хотел добавить функцию переключения, поэтому нажатие на ту же модель переключит / свернет секцию подмодели.

Добавление функции переключения к «const», если условие сработало, но я не могу заставить эффект «slideUp» сработать с ним. Я тестировал: "существующий Submodel.toggle (). SlideUp (400);" и "istingSubmodel.slideUp (400, () => {существующийSubmodel.toggle ();}); ". Ни один не работал для меня.

$().ready(() => {

  // Any time a model is clicked, do the following.
  $(".model").click((e) => {
    const existingSubmodel = $('.sub-models.active');
    if (existingSubmodel.get(0)) {
      //Finish any animations if there are some going on. 
      existingSubmodel.stop(true, true);
      // Wait until the submodels have finshed sliding up and then remove. 
      existingSubmodel.slideUp(400, () => {
        existingSubmodel.remove();
      });
      existingSubmodel.toggle();
    }
    addSubmodels(e);
  });
});

/**
 * Find the index of the model
 * Then find the position in the row (ie what column is it?)
 * Then find the index to insert at - this will be at the end of a row so that the submodels container will start on a new line. 
 * Create a clone of the submodel container and add an `.active` class to it. 
 * Append that submodel clone to the `indexToInsert`.
 * Slide it down. 
 */
function addSubmodels(e) {
  const parent = $(e.currentTarget);
  const parentId = parent.attr('id');
  const index = getIndexOfElement(parent);
  const position = getPositionInFlex(parent);
  const indexToInsert = index + getNumberOfElements() - position;

  const elementToAppendTo = $(".model").get(indexToInsert);
  const subModel = $("#submodel-" + parentId).clone(true);
  subModel.addClass('active');
  $(elementToAppendTo).after(subModel);
  $('.sub-models.active').slideDown(400);
}

function getIndexOfElement(element) {
  return $('.model').toArray().findIndex(e => {
    return e.id === element.attr('id');
  });
}

function getNumberOfElements() {
  return Math.floor($("#container").width() / $(".model").outerWidth(true));
}

function getPositionInFlex(element) {
  const numEl = getNumberOfElements();
  const index = getIndexOfElement(element) + 1;
  const position = index % numEl;
  return position === 0 ? numEl : position;
}
#container {
  width: 800px;
  height: auto;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  background-color: white;
}

.model {
  margin: 20px;
  cursor: pointer;
}

.model:hover {
  box-shadow: 2px 2px 10px #AAA;
}

.model-text {
  width: 200px;
  height: 100px;
  text-align: center;
  background-color: #AAA;
  font-size: 18px;
}

.sub-models {
  display: none;
  padding: 20px;
  background-color: pink;
  width: 100%;
  margin: 0 20px;
}

.sub-model-row {
  display: flex;
  flex-wrap: wrap;
}

.sub-model {
  width: 25%;
  height: auto;
}

.hide {
  opacity: .5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>
  Select From The Following Models
</h1>
<!-- Grandparent -->
<div id="container">
  <div id="1" class="model">

    <div class="model-text">
      Model 1
    </div>

  </div>
  <div id="2" class="model">
    <div class="model-text">
      Model 2
    </div>
  </div>
  <div id="3" class="model">
    <div class="model-text">
      Model 3
    </div>
  </div>
  <div id="4" class="model">
    <div class="model-text">
      Model 4
    </div>
  </div>
  <div id="5" class="model">
    <div class="model-text">
      Model 5
    </div>
  </div>
  <div id="6" class="model">
    <div class="model-text">
      Model 6
    </div>

  </div>


  <div id="submodel-1" class="sub-models">
    <div class="sub-model-row">
      <div class="sub-model">
        Model 1 SubModel 1
      </div>
      <div class="sub-model">
        Model 1 SubModel 2
      </div>
      <div class="sub-model">
        Model 1 SubModel 3
      </div>
    </div>
  </div>

  <div id="submodel-2" class="sub-models">
    <div class="sub-model-row">
      <div class="sub-model">
        Model 2 SubModel 1
      </div>
      <div class="sub-model">
        Model 2 SubModel 2
      </div>
      <div class="sub-model">
        Model 2 SubModel 3
      </div>
    </div>
  </div>
  <div id="submodel-3" class="sub-models">
    <div class="sub-model-row">
      <div class="sub-model">
        Model 3 SubModel 1
      </div>
      <div class="sub-model">
        Model 3 SubModel 2
      </div>
      <div class="sub-model">
        Model 3 SubModel 3
      </div>
    </div>
  </div>
  <div id="submodel-4" class="sub-models">
    <div class="sub-model-row">
      <div class="sub-model">
        Model 1 SubModel 1
      </div>
      <div class="sub-model">
        Model 1 SubModel 2
      </div>
      <div class="sub-model">
        Model 1 SubModel 3
      </div>
    </div>
  </div>
  <div id="submodel-5" class="sub-models">
    <div class="sub-model-row">
      <div class="sub-model">
        Model 1 SubModel 1
      </div>
      <div class="sub-model">
        Model 1 SubModel 2
      </div>
      <div class="sub-model">
        Model 1 SubModel 3
      </div>
    </div>
  </div>
  <div id="submodel-6" class="sub-models">
    <div class="sub-model-row">
      <div class="sub-model">
        Model 1 SubModel 1
      </div>
      <div class="sub-model">
        Model 1 SubModel 2
      </div>
      <div class="sub-model">
        Model 1 SubModel 3
      </div>
    </div>
  </div>
</div>

Мне просто нужна функция переключения для анимации с эффектом slideUp. Было бы замечательно, если бы переключение секций «Submodel» также вызывало анимацию скольжения (что происходит, если вы удаляете код существующего «Submodel.toggle ();» из строки 13 JS). Любая помощь будет оценена, поскольку я все еще изучаю jQuery и мой JS так себе.

Вы также можете поиграть с ним здесь: JSfiddle

2
Mark Dorman 27 Авг 2019 в 21:46

2 ответа

Лучший ответ

Если ваша основная цель состоит в том, чтобы убедиться, что подмодель переключается при нажатии на модель, под которой она находится, то вы можете удалить функцию toggle() или slideToggle(), как она существует здесь. Вместо этого вы можете сделать что-то подобное после блока if (existingSubmodel.get(0)):

// Add .activemodel class to each model-text that gets clicked. 
// If the model-text has the activemodel class already, just remove it and do nothing else. 
// Otherwise, add the new submodel in there, AND get rid of all .activemodel classes, 
// and just add a new .activemodel class on the the model that is now active.  


if ($(e.target).hasClass('activemodel')) {
    $(e.target).removeClass('activemodel');
} else {
    addSubmodels(e);
    $('.activemodel').removeClass('activemodel');
    $(e.target).addClass('activemodel');
}

Я заметил, что это также не удастся, если последняя строка не заполнена, это, вероятно, незначительный недосмотр вашего друга - indexToInsert вычисляется так, как будто строка заполнена. Если он не полный, то elementToAppendTo фактически не будет существовать, поэтому вы не можете добавить его. Я думаю, что достойным решением здесь было бы сброс indexToInsert к последнему индексу $('.models'), если он окажется длиннее этого последнего индекса. Это может выглядеть примерно так:

// after setting const position
const models = $(".model");
let indexToInsert = index + getNumberOfElements() - position;
if (indexToInsert > models.length-1) { indexToInsert = models.length-1}

const elementToAppendTo = models.get(indexToInsert);
0
mcheah 27 Авг 2019 в 23:46

ОБНОВЛЕНО

После игры с этим в скрипке я мог видеть, чего вы на самом деле пытались достичь. slideUp - действительно нужный вам метод, но вам нужно указать правильный элемент в дереве dom, потому что вы клонируете элемент: existingSubmodel[0].slideUp(); Здесь мы указываем первый элемент в дереве dom, потому что вы добавляете клон

  // Any time a model is clicked, do the following.
  $(".model").click((e) => {
    const existingSubmodel = $('.sub-models.active');
    if (existingSubmodel.get(0)) {
        //Finish any animations if there are some going on. 
        existingSubmodel.stop(true,true);
        // Wait until the submodels have finshed sliding up and then remove. 
        existingSubmodel.slideUp(400, () => {
           existingSubmodel.remove(); 
        });
        existingSubmodel[0].slideUp(); 
    }
    addSubmodels(e);
  });

А остальная часть вашего кода хороша. На самом деле все, что я изменил, было строкой 13.

Рабочая скрипка: https://jsfiddle.net/mcpdnyaz/1/#&togoti

Надеюсь это поможет.

0
kenef 27 Авг 2019 в 22:10