WEBLOG
JavaScript > vanilla.js
OLDOFFICEの標準設置JavaScript、コンテンツの開閉を紹介。
vanilla.js で 記述しclassでバージョン管理しています。
各プロジェクトでは、標準設置のスクリプトをwebpackでバンドルと圧縮し、各ページにdata属性を記述するだけで動作します。
htmlマークアップで下記のように記述するだけで動作します。
ラッパーに「data-openclose=”wrap”」。ハンドルに「data-openclose=”handle”」。開閉コンテンツに「data-openclose=”target”」を付与すると開閉します。
ハンドルにクラス「plus」を付与すると初期に閉じた状態になり、「minus」を付与すると開いた状態になります。
<div data-openclose="wrap">
<p class="plus" data-openclose="handle">Handle</p>
<div data-openclose="target">
<p>Open_contents</p>
</div>
</div>
openclose(selector, config = {}) {
const opt = ooutil.setting(
{
def: 'hide',
},
config
),
nodes = document.querySelectorAll(selector);
let status, $target;
if (nodes.length === 0) return;
/* func */
const getTarget = ($_handle) => {
let $tgt, $wrap;
if ($_handle.closest('[data-openclose="wrap"]').length) {
$wrap = $_handle.closest('[data-openclose="wrap"]');
} else {
$wrap = $_handle.parentNode;
}
$tgt = null;
if ($_handle.getAttribute('data-target')) {
$tgt = document.getElementById($_handle.getAttribute('data-target'));
}
if ($tgt === null && $_handle.getAttribute('data-target_class')) {
$tgt = $wrap.querySelector('.' + $_handle.getAttribute('data-target_class'));
}
if ($tgt === null && $wrap.querySelector('[data-openclose="target"]')) {
$tgt = $wrap.querySelector('[data-openclose="target"]');
}
if ($tgt === null) {
$tgt = $_handle.nextElementSibling;
}
return $tgt;
};
const core = ($_handle) => {
let $textWrap, isTextChange, texts;
if (status === 'open') {
$_handle.classList.add('minus');
$_handle.classList.remove('plus');
} else if (status === 'close') {
$_handle.classList.add('plus');
$_handle.classList.remove('minus');
}
if ($_handle.querySelector('[data-openclose_text]') !== null) {
$textWrap = $_handle.querySelector('[data-openclose_text]');
isTextChange = true;
} else if ($_handle.getAttribute('data-openclose_text') !== null) {
$textWrap = $_handle;
isTextChange = true;
} else {
isTextChange = false;
}
if (isTextChange) {
texts = $textWrap.getAttribute('data-openclose_text').split(',');
if (status === 'close') {
$textWrap.textContent = texts[0];
} else if (status === 'open') {
$textWrap.textContent = texts[1];
}
}
};
Array.from(nodes, ($handle) => {
/* event */
$handle.addEventListener('click', (e) => {
$target = getTarget(e.currentTarget);
status = ooutil.isHidden($target) ? 'open' : 'close';
this.slideToggle($target);
core(e.currentTarget);
});
/* init */
$target = getTarget($handle);
if ($handle.classList.contains('plus')) {
status = 'close';
$target.style.display = 'none';
} else if ($handle.classList.contains('minus')) {
status = 'open';
$target.style.display = 'block';
} else if (opt.def == 'hide') {
status = 'open';
$target.style.display = 'none';
} else if (opt.def == 'show') {
status = 'close';
$target.style.display = 'block';
} else {
status = 'close';
$target.style.display = 'block';
}
});
}