[jQuery]jsで生成したDOM要素にslick.jsを設定する

非表示・表示切り替えにも対応していく。

どういうことか

普通はhtmlなりphpなりでスライダー部を作って、それにslick.jsを付与する。

今回はjsでスライダー部を作って、slick.jsを付与する。

.append()なり何なりで出力したhtmlには.slick()が反映されない。
これはslickに限らない話で、出力と付与のタイミングが合わないとそうなる。

できないんじゃなくて、できる作り方があるよという話。
jsの仕様を理解した組み方が求められる。

やっていく

最終的にこんな感じにするとする。

<script>
$(function(){
    $('ul.slider').slick({
        dots: true,
        infinite: true,
        speed: 500,
    });
})
</script>

<div class="wrap">
    <ul class="slider" data-name="slider01">
        <li>***</li>
        <li>***</li>
        <li>***</li>
        ⋮
    </ul>
    <ul class="slider" data-name="slider02">
        <li>***</li>
        <li>***</li>
        <li>***</li>
        ⋮
    </ul>
    <ul class="slider" data-name="slider03">
        <li>***</li>
        <li>***</li>
        <li>***</li>
        ⋮
    </ul>
</div>

スライダーを複数設定して、1個だけ表示する。
ボタンとかで表示するスライダーを切り替える。
display:none;なスライダーは表示時にぶっ壊れる(jsが反応しない)ことは珍しくなく、slick.jsも同様。
それも対応する。

htmlはこんな感じにしておくとする。

<div class="wrap">
</div>

.wrapの中にjsでスライダーを突っ込む。

スライダーの生成・出力

直近で作った要素も混ぜつつ。
配列にまとめた内容を展開して作っていく。

$(function(){
    const slider01Ary = {sliderName:'slider01',slideName:['slider01_01','slider01_02','slider01_03','slider01_04','slider01_05',...]};
    const slider02Ary = {sliderName:'slider02',slideName:['slider02_01','slider02_02','slider02_03','slider02_04','slider02_05',...]};
    const slider03Ary = {sliderName:'slider03',slideName:['slider03_01','slider03_02','slider03_03','slider03_04','slider03_05',...]};
    const slider04Ary = {sliderName:'slider04',slideName:['slider04_01','slider04_02','slider04_03','slider04_04','slider04_05',...]};
    ⋮
    let sliderSet = '';

    const slider01Num = slider01Ary['slideName'].length;
    for(i=0;i<slider01Num;i++){
        if(i == 0){ sliderSet += '<ul class="slider" data-name="'+slider01Ary['sliderName']+'">'; }
        sliderSet += '<li>'+slider01Ary['slideName'][i]+'</li>';
        if(i == slider01Num - 1){ sliderSet += '</ul>'; }
    }

    const slider02Num = slider02Ary['slideName'].length;
    for(i=0;i<slider02Num;i++){
        if(i == 0){ sliderSet += '<ul class="slider" data-name="'+slider02Ary['sliderName']+'">'; }
        sliderSet += '<li>'+slider02Ary['slideName'][i]+'</li>';
        if(i == slider02Num - 1){ sliderSet += '</ul>'; }
    }

    ⋮

    $('.wrap').append(sliderSet);
    $('.wrap .slider').slick({
        dots: true,
        infinite: true,
        speed: 500,
    });
})

.slick()は生成のあとに書く。
手前に書くと詰む。

手前に書いた.slick()が出力したDOM要素に被ってなきゃいいんだけどね。

例えばスライドを1個だけhtml側で設置してあってjsで追加するみたいなことをした場合。
元々ある用に.slick()を書いて、上記のようなjsでスライドを出力してまた.slick()を書いてもダメ。
先に書いたほうが優先されて詰み。

.slick(‘setPosition’)を入れても意味がない。
setPositionを使うときは、表示が壊れててもとにかく.slick()があらかじめ適用されてることが前提になる。

はじめからこの形で組んでたらいいんだけど、追っかけでスライド追加をやっていくときに混乱すると思います。混乱しました。

表示の切り替えボタンを付ける

こんな感じで

<style>
ul.slider{ display:none;}
ul.slider:first-child{ display:block;}
</style>

<div class="wrap">
    <ul class="slider" data-name="slider01">
    </ul>
    <ul class="slider" data-name="slider02">
    </ul>
    <ul class="slider" data-name="slider03">
    </ul>
    ⋮
</div>
<div class="change">
    <button type="button" data-name="slider01">slider01</button>
    <button type="button" data-name="slider02">slider02</button>
    <button type="button" data-name="slider03">slider03</button>
    ⋮
</div>

切り替え部分のHTMLはこうだとして

<div class="change">
</div>

こう

$(function(){
    const slider01Ary = {sliderName:'slider01',slideName:['slider01_01','slider01_02','slider01_03','slider01_04','slider01_05',...]};
    const slider02Ary = {sliderName:'slider02',slideName:['slider02_01','slider02_02','slider02_03','slider02_04','slider02_05',...]};
    ⋮

    let changeSet = '';
    changeSet += '<button type="button" data-name="'+slider01Ary['sliderName']+'">'+slider01Ary['sliderName']+'</button>';
    changeSet += '<button type="button" data-name="'+slider02Ary['sliderName']+'">'+slider02Ary['sliderName']+'</button>';
    ⋮
    $('.change').append(changeSet);

    $(document).on('click','.change button',function(){
        $('.wrap ul.slider').hide();
        $('.wrap ul.slider[data-name="'+$(this).attr('data-name')+'"]').fadeIn(function(){
            $(this).slick('setPosition');
        });
    })
})

出力したbuttonとかを発火させる場合は$(document)から書き出したほうが楽。

setPositionを付けてるけど、なんかこれ、付けなくても良さげな動作をしたときもある。
なんだろうね、まあ書いたほうが無難ですかね。

コメント

タイトルとURLをコピーしました