简体   繁体   中英

How would I give CSS property to a cloned element as Javascript?

I'm trying to give translateX() property to cloned element which is called this.firstClone as javascript. The problem is this.firstClone doesn't refer to the cloned element even the value itself makes the clone in the code.

constructor($el) {
  this.$el = $el; // 0
  this.myCards = this.$el.find('a'); // 1
  this.myCount = 1; // 2
  this.myLength = this.myCards.length; // 3
  this.firstClone = this.myCards.first().before(this.myCards.last().clone().addClass('cloned')); // 4 this makes the clone.
  this.lastClone = this.myCards.last().after(this.myCards.first().clone().addClass('cloned'));
}

Above there, this.firstClone makes the clone of the last image to the first in the set. And also when I remove that, the cloned element is gone. There's no problem to make, set or remove the cloned image.

But when I console.log it, it refers second element which has translateX(1%) in DOM. The property is also going to set to the second element when I do like this: this.firstClone.style.transform = "translateX(" + (-1) + "%)";

Is this a glitch of javascript? or do I just misunderstanding about .first() and .clone() method?

My goal is to give the css properties each of the cloned elements, but I stuck in here w/o no clues.

Full Code:

 'use strict'; (function ($, window, undefined) { $.fn.cardSlider = function(options) { return this.each(function() { const $el = $(this); var thatCards = new Card($el, options); thatCards.scrolling($el); }) } class Card { constructor($el) { this.$el = $el; // 0 this.myCards = this.$el.find('a'); // 1 this.myCount = 1; // 2 this.myLength = this.myCards.length; // 3 this.firstClone = this.myCards.first().before(this.myCards.last().clone().addClass('cloned')); // 4 this makes the clone. this.lastClone = this.myCards.last().after(this.myCards.first().clone().addClass('cloned')); } scrolling($el) { console.log(this.firstClone); this.firstClone.style.transform = "translateX(" + (-1) + "%)"; // Browser fires an error. Cannot set property 'transform' of undefined this.firstClone.css({ paddingBottom: 200 + 'px' }); // An example for proving that the css property doesn't refer to the real clone. for (var i = 0; i < this.myLength; i++) { this.myCards[i].style.transform = "translateX(" + Math.pow(2, i) + "%)"; } } } }(jQuery)); $('.outer').cardSlider(); 
 .outer { margin: 0 auto; width: 70%; overflow: hidden; } .film { display: flex; flex-flow: row; justify-content: center; left: 90%; } .images { position: relative; display: block; width: 90%; flex-shrink: 0; padding-bottom: 74%; background-color: blue; } .images:first-child, .images:last-child { background-color: orange; opacity: .4; } 
  <div class="outer"> <div class="film"> <a class="images" href="#" draggable="false"></a> <a class="images" href="#" draggable="false"></a> <a class="images" href="#" draggable="false"></a> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 

*I tested this code in Codepen and here but both didn't work. You probably have to make the new files to test this.

Your code is quite messy, but I think one problem you have is that you assign the wrong element to firstClone and lastClone . You propably want those variables to be references to the new clones, but that's not what your code does.

Let's look at this line:

this.firstClone = this.myCards.first().before(this.myCards.last().clone().addClass('cloned'));

  • First, you clone the last card and add the class cloned ( this.myCards.last().clone().addClass('cloned') )

  • Then, you pass that clone to the function before of the first card ( this.myCards.first().before(...) )

  • Finally, you assign whatever the function before returns to the variable this.firstClone

The problem is that the expression a.before(b) inserts b before a and then returns a . What you want to save, though, is a reference to b , not a .

You have to use the function insertBefore instead. It does exactly the same as before , but the other way around: b.insertBefore(a) also inserts b before a , but this returns b .

(See the difference here: https://www.mkyong.com/jquery/jquery-before-and-insertbefore-example/ )

So the line we looked at should be:

this.firstClone = this.myCards.last().clone().addClass('cloned').insertBefore(this.myCards.first());

This way, your variable this.firstClone holds a reference to the newly created clone and not the (previously) first element. The same holds for the line after that:

this.lastClone = this.myCards.first().clone().addClass('cloned').insertAfter(this.myCards.last());

I hope this solves your problem.

Used in context:

 'use strict'; (function ($, window, undefined) { $.fn.cardSlider = function(options) { return this.each(function() { const $el = $(this); var thatCards = new Card($el, options); thatCards.scrolling($el); }) } class Card { constructor($el) { this.$el = $el; // 0 this.myCards = this.$el.find('a'); // 1 this.myCount = 1; // 2 this.myLength = this.myCards.length; // 3 this.firstClone = this.myCards.last().clone().addClass('cloned').insertBefore(this.myCards.first()); // 4 this makes the clone. this.lastClone = this.myCards.first().clone().addClass('cloned').insertAfter(this.myCards.last()); } scrolling($el) { console.log(this.myCards[1]); // Both refers the same element this.firstClone.css({ paddingBottom: 200 + 'px' }); for (var i = 0; i < this.myLength; i++) { this.myCards[i].style.transform = "translateX(" + Math.pow(2, i) + "%)"; } } } }(jQuery)); $('.outer').cardSlider(); 
 .outer { margin: 0 auto; width: 70%; overflow: hidden; } .film { display: flex; flex-flow: row; justify-content: center; left: 90%; } .images { position: relative; display: block; width: 90%; flex-shrink: 0; padding-bottom: 74%; background-color: blue; } .images:first-child, .images:last-child { background-color: orange; opacity: .4; } 
  <div class="outer"> <div class="film"> <a class="images" href="#" draggable="false"></a> <a class="images" href="#" draggable="false"></a> <a class="images" href="#" draggable="false"></a> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 

The problem is that this.firstClone is a jQuery object, not a DOM element. But style is a DOM property. In jQuery you use the .css() function to add styles, so it should be:

this.firstClone.css("transform", "translateX(-1%)");

or you can put it as part of the following:

  this.firstClone.css({
    paddingBottom: 200 + 'px',
    transform: "translateX(-1%)"
  });

Your code works in the for loop because when you index a jQuery collection, it returns the corresponding DOM element (to get the jQuery object, you use .eq(i) ). So you could also write the above as:

this.firstClone[0].style.transform = "translateX(-1%)";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM