我想我已经成功创建了一个滑块(请执行说出你对它的评论),我能够在我的项目中实现它。问题是,当我尝试嵌套滑块时。
嵌套滑块未完全显示。显示的唯一部分是标签。内容未显示。当我检查控制台时,它显示嵌套的simSliderOuterWrapper's
宽度为0。
我做错了什么,我怎样才能使其完全正常运作?
function simSlider(parentElem, config) {
/* ----------------------------------- */
/* -------- Variable Creation -------- */
/* ----------------------------------- */
var currentThis = this,
personalID = parentElem.id,
outerWrapper = document.createElement('div'),
innerWrapper = document.createElement('div'),
labelWrapper = document.createElement('div'),
tabUnderliner = document.createElement('div'),
content = parentElem.children,
radiosArray = [],
contentsHeight = [],
contentWidth = parentElem.offsetWidth,
selectedIndex = prevIndex = 0;
/* ---------------------------------- */
/* ------- Configure Settings ------- */
/* ---------------------------------- */
if (config === undefined) config = {};
currentThis.config = {
// Class Names
outerWrapperClassName: config.outerWrapperClassName,
innerWrapperClassName: config.innerWrapperClassName,
labelWrapperClassName: config.labelWrapperClassName,
labelsClassName: config.labelsClassName,
tabUnderlinerClassName: config.tabUnderlinerClassName,
// CSS Styles
background: config.background || 'blue',
tabUnderlinerColor: config.tabUnderlinerColor || 'orange',
tabTitles: config.tabTitles,
animation: config.animation || '0.7s cubic-bezier(0.45, 0.05, 0.55, 0.95)',
// Callbacks
beforeInit: config.beforeInit || emptyFunction,
endInit: config.endInit || emptyFunction,
beforeSlide: config.beforeSlide || emptyFunction,
slide: config.slide || emptyFunction,
endSlide: config.endSlide || emptyFunction
};
function emptyFunction() {}
/* ------------------------------------------ */
/* ----- Handle Slider Change/Animation ----- */
/* ------------------------------------------ */
function changeFunction(e) {
selectedIndex = radiosArray.indexOf(e.target);
currentThis.config.beforeSlide(selectedIndex, content[selectedIndex]);
var amount = '-' + contentWidth + 'px';
content[selectedIndex].style.width = contentWidth + 'px';
if (selectedIndex < prevIndex) {
innerWrapper.style.transform = 'translateX(' + amount + ')';
amount = '0';
}
setTimeout(function() {
innerWrapper.style.transition = 'transform ' + currentThis.config.animation;
innerWrapper.style.transform = 'translateX(' + amount + ')';
outerWrapper.style.height = contentsHeight[selectedIndex] + 'px';
tabUnderliner.style.transform = 'translateX(' + (selectedIndex * 100) + '%)';
currentThis.config.slide(selectedIndex, content[selectedIndex]);
});
}
function transitionCallback(e) {
// http://stackoverflow.com/q/36274519/4861207
if (e.target !== innerWrapper) return;
innerWrapper.style.transition = 'none';
innerWrapper.style.transform = 'translateX(0)';
content[prevIndex].style.width = 0;
prevIndex = selectedIndex;
currentThis.config.endSlide(selectedIndex, content[selectedIndex]);
}
/* ---------------------------------- */
/* ------ Initialize simSlider ------ */
/* ---------------------------------- */
function initSimSlider() {
// beforeInit Callback
currentThis.config.beforeInit;
// Move contents (slides) to 'innerWrapper'
while (content.length) {
contentsHeight.push(content[0].offsetHeight);
content[0].style.width = 0;
innerWrapper.appendChild(content[0]);
}
content = innerWrapper.children;
// Create and Style Tabs
for (var i = 0; i < content.length; i++) {
var radio = document.createElement('input'),
label = document.createElement('label');
manipulateAttributes(radio, {
type: 'radio',
checked: i === 0,
name: 'simSlider' + personalID,
id: 'simSlider' + personalID + i,
class: 'simSliderTab',
style: {
display: 'none'
}
});
manipulateAttributes(label, {
htmlFor: 'simSlider' + personalID + i,
html: currentThis.config.tabTitles ? currentThis.config.tabTitles[i] : i,
style: {
display: 'inline-block',
width: 'calc(100% / ' + content.length + ')'
}
});
if (currentThis.config.labelsClassName) label.className = currentThis.config.labelsClassName;
radio.addEventListener('change', changeFunction);
radiosArray.push(radio);
labelWrapper.appendChild(label);
parentElem.appendChild(radio);
}
// Add eventListener
if ('transition' in document.documentElement.style) innerWrapper.addEventListener('transitionend', transitionCallback);
// Add CSS Style
content[selectedIndex].style.width = contentWidth + 'px';
tabUnderliner.style.transition = 'transform ' + currentThis.config.animation;
manipulateAttributes(outerWrapper, {
className: 'simSliderOuterWrapper',
style: {
width: contentWidth + 'px',
height: contentsHeight[selectedIndex] + 'px',
transition: 'height ' + currentThis.config.animation,
background: currentThis.config.background,
overflow: 'hidden'
}
});
manipulateAttributes(innerWrapper, {
className: 'simSliderInnerWrapper',
style: {
width: (contentWidth * 2) + 'px',
display: 'flex'
}
});
manipulateAttributes(labelWrapper, {
className: 'simSliderLabelWrapper',
style: {
background: 'brown'
}
});
manipulateAttributes(tabUnderliner, {
className: 'simSliderTabUnderliner',
style: {
background: currentThis.config.tabUnderlinerColor,
height: '3px',
width: 'calc(100% / ' + content.length + ')'
}
});
// Add Class Names
if (currentThis.config.outerWrapperClassName) outerWrapper.className += ' ' + currentThis.config.outerWrapperClassName;
if (currentThis.config.innerWrapperClassName) innerWrapper.className += ' ' + currentThis.config.innerWrapperClassName;
if (currentThis.config.labelWrapperClassName) labelWrapper.className += ' ' + currentThis.config.labelWrapperClassName;
if (currentThis.config.tabUnderlinerClassName) tabUnderliner.className += ' ' + currentThis.config.tabUnderlinerClassName;
// Append Elements
outerWrapper.appendChild(innerWrapper);
parentElem.appendChild(labelWrapper);
parentElem.appendChild(tabUnderliner);
parentElem.appendChild(outerWrapper);
// endInit Callback
currentThis.config.endInit;
}
/* ---------------------------------- */
/* -------- Inital Rendering -------- */
/* ---------------------------------- */
initSimSlider();
function manipulateAttributes(element, attr) {
function recursiveSet(at, set) {
for (var prop in at) {
/* check if object and not a dom node or array */
if (typeof at[prop] == 'object' && at[prop].dataset == null && at[prop][0] == null) {
recursiveSet(at[prop], set [prop]);
} else if (prop == 'html') {
element.innerHTML = at[prop];
} else {
set [prop] = at[prop];
}
}
}
recursiveSet(attr, element);
}
function hasClass(ele, cls) {
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += " " + cls;
}
}
var mySlider = document.getElementById('mySlider'),
slider = new simSlider(mySlider);
.tabGroup {
width: 500px;
}
.menu {
background-color: brown;
}
.content {} #rad1:checked ~ #outerWrapper > #innerWrapper > #first,
#rad2:checked ~ #outerWrapper > #innerWrapper > #second,
#rad3:checked ~ #outerWrapper > #innerWrapper > #third {} .simSliderTabUnderliner {} .simSliderOuterWrapper {
background-color: blue;
}
#first {
width: 500px;
height: 386px;
}
#second {
width: 300px;
height: 600px;
background-color: lightgreen;
}
#third {
width: 500px;
height: 500px;
}
img {
max-width: 100%;
max-height: 100%;
}
<div class="tabGroup">
<div id="mySlider">
<div class="content" id="first">
<img src="http://www.hdwallpapery.com/static/images/creativity_water_spray_drops_flower_rose_desktop_images_TVIdSpG.jpg" />
</div>
<div class="content" id="second">
<img src="http://www.hdwallpapery.com/static/images/images_1_JbTP6rz.jpg" />
</div>
<div class="content" id="third">
<img src="https://www.planwallpaper.com/static/images/Winter-Tiger-Wild-Cat-Images.jpg" />
</div>
</div>
</div>
function simSlider(parentElem, config) {
/* ----------------------------------- */
/* -------- Variable Creation -------- */
/* ----------------------------------- */
var currentThis = this,
personalID = parentElem.id,
outerWrapper = document.createElement('div'),
innerWrapper = document.createElement('div'),
labelWrapper = document.createElement('div'),
tabUnderliner = document.createElement('div'),
content = parentElem.children,
radiosArray = [],
contentsHeight = [],
contentWidth = parentElem.offsetWidth,
selectedIndex = prevIndex = 0;
/* ---------------------------------- */
/* ------- Configure Settings ------- */
/* ---------------------------------- */
if (config === undefined) config = {};
currentThis.config = {
// Class Names
outerWrapperClassName: config.outerWrapperClassName,
innerWrapperClassName: config.innerWrapperClassName,
labelWrapperClassName: config.labelWrapperClassName,
labelsClassName: config.labelsClassName,
tabUnderlinerClassName: config.tabUnderlinerClassName,
// CSS Styles
background: config.background || 'blue',
tabUnderlinerColor: config.tabUnderlinerColor || 'orange',
tabTitles: config.tabTitles,
animation: config.animation || '0.7s cubic-bezier(0.45, 0.05, 0.55, 0.95)',
// Callbacks
beforeInit: config.beforeInit || emptyFunction,
endInit: config.endInit || emptyFunction,
beforeSlide: config.beforeSlide || emptyFunction,
slide: config.slide || emptyFunction,
endSlide: config.endSlide || emptyFunction
};
function emptyFunction() {}
/* ------------------------------------------ */
/* ----- Handle Slider Change/Animation ----- */
/* ------------------------------------------ */
function changeFunction(e) {
selectedIndex = radiosArray.indexOf(e.target);
currentThis.config.beforeSlide(selectedIndex, content[selectedIndex]);
var amount = '-' + contentWidth + 'px';
content[selectedIndex].style.width = contentWidth + 'px';
if (selectedIndex < prevIndex) {
innerWrapper.style.transform = 'translateX(' + amount + ')';
amount = '0';
}
setTimeout(function() {
innerWrapper.style.transition = 'transform ' + currentThis.config.animation;
innerWrapper.style.transform = 'translateX(' + amount + ')';
outerWrapper.style.height = contentsHeight[selectedIndex] + 'px';
tabUnderliner.style.transform = 'translateX(' + (selectedIndex * 100) + '%)';
currentThis.config.slide(selectedIndex, content[selectedIndex]);
});
}
function transitionCallback(e) {
// http://stackoverflow.com/q/36274519/4861207
if (e.target !== innerWrapper) return;
innerWrapper.style.transition = 'none';
innerWrapper.style.transform = 'translateX(0)';
content[prevIndex].style.width = 0;
prevIndex = selectedIndex;
currentThis.config.endSlide(selectedIndex, content[selectedIndex]);
}
/* ---------------------------------- */
/* ------ Initialize simSlider ------ */
/* ---------------------------------- */
function initSimSlider() {
// beforeInit Callback
currentThis.config.beforeInit;
// Move contents (slides) to 'innerWrapper'
while (content.length) {
contentsHeight.push(content[0].offsetHeight);
content[0].style.width = 0;
innerWrapper.appendChild(content[0]);
}
content = innerWrapper.children;
// Create and Style Tabs
for (var i = 0; i < content.length; i++) {
var radio = document.createElement('input'),
label = document.createElement('label');
manipulateAttributes(radio, {
type: 'radio',
checked: i === 0,
name: 'simSlider' + personalID,
id: 'simSlider' + personalID + i,
class: 'simSliderTab',
style: {
display: 'none'
}
});
manipulateAttributes(label, {
htmlFor: 'simSlider' + personalID + i,
html: currentThis.config.tabTitles ? currentThis.config.tabTitles[i] : i,
style: {
display: 'inline-block',
width: 'calc(100% / ' + content.length + ')'
}
});
if (currentThis.config.labelsClassName) label.className = currentThis.config.labelsClassName;
radio.addEventListener('change', changeFunction);
radiosArray.push(radio);
labelWrapper.appendChild(label);
parentElem.appendChild(radio);
}
// Add eventListener
if ('transition' in document.documentElement.style) innerWrapper.addEventListener('transitionend', transitionCallback);
// Add CSS Style
content[selectedIndex].style.width = contentWidth + 'px';
tabUnderliner.style.transition = 'transform ' + currentThis.config.animation;
manipulateAttributes(outerWrapper, {
className: 'simSliderOuterWrapper',
style: {
width: contentWidth + 'px',
height: contentsHeight[selectedIndex] + 'px',
transition: 'height ' + currentThis.config.animation,
background: currentThis.config.background,
overflow: 'hidden'
}
});
manipulateAttributes(innerWrapper, {
className: 'simSliderInnerWrapper',
style: {
width: (contentWidth * 2) + 'px',
display: 'flex'
}
});
manipulateAttributes(labelWrapper, {
className: 'simSliderLabelWrapper',
style: {
background: 'brown'
}
});
manipulateAttributes(tabUnderliner, {
className: 'simSliderTabUnderliner',
style: {
background: currentThis.config.tabUnderlinerColor,
height: '3px',
width: 'calc(100% / ' + content.length + ')'
}
});
// Add Class Names
if (currentThis.config.outerWrapperClassName) outerWrapper.className += ' ' + currentThis.config.outerWrapperClassName;
if (currentThis.config.innerWrapperClassName) innerWrapper.className += ' ' + currentThis.config.innerWrapperClassName;
if (currentThis.config.labelWrapperClassName) labelWrapper.className += ' ' + currentThis.config.labelWrapperClassName;
if (currentThis.config.tabUnderlinerClassName) tabUnderliner.className += ' ' + currentThis.config.tabUnderlinerClassName;
// Append Elements
outerWrapper.appendChild(innerWrapper);
parentElem.appendChild(labelWrapper);
parentElem.appendChild(tabUnderliner);
parentElem.appendChild(outerWrapper);
// endInit Callback
currentThis.config.endInit;
}
/* ---------------------------------- */
/* -------- Inital Rendering -------- */
/* ---------------------------------- */
initSimSlider();
function manipulateAttributes(element, attr) {
function recursiveSet(at, set) {
for (var prop in at) {
/* check if object and not a dom node or array */
if (typeof at[prop] == 'object' && at[prop].dataset == null && at[prop][0] == null) {
recursiveSet(at[prop], set [prop]);
} else if (prop == 'html') {
element.innerHTML = at[prop];
} else {
set [prop] = at[prop];
}
}
}
recursiveSet(attr, element);
}
function hasClass(ele, cls) {
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += " " + cls;
}
}
var mySlider = document.getElementById('mySlider'),
slider = new simSlider(mySlider);
var mySlider2 = document.getElementById('second'),
slider2 = new simSlider(mySlider2);
#mySlider {
width: 500px;
}
.menu {
background-color: brown;
}
.simSliderOuterWrapper {
background-color: blue;
}
#first {
width: 500px;
height: 386px;
}
#second {
width: 500px;
height: 600px;
background-color: lightgreen;
}
#third {
width: 500px;
height: 500px;
}
#first2 {
width: 500px;
height: 500px;
}
#second2 {
width: 500px;
height: 600px;
background-color: lightgreen;
}
#third2 {
width: 500px;
height: 700px;
}
img {
max-width: 100%;
max-height: 100%;
}
<div id="mySlider">
<div class="content" id="first">
<img src="http://www.hdwallpapery.com/static/images/creativity_water_spray_drops_flower_rose_desktop_images_TVIdSpG.jpg" />
</div>
<div class="content" id="second">
<div id="first2">
<img src="https://rfranksblog.files.wordpress.com/2013/02/keep-calm-and-find-the-syntax-error-copy.jpg" />
</div>
<div id="second2">
<img src="http://aquinashub.co.uk/wp-content/uploads/2015/04/shutterstock_computer_programming.jpg" />
</div>
<div id="third2">
<img src="http://datavizion.biz/wp-content/uploads/2011/04/23689689.jpg" />
</div>
</div>
<div class="content" id="third">
<img src="https://www.planwallpaper.com/static/images/Winter-Tiger-Wild-Cat-Images.jpg" />
</div>
</div>
答案 0 :(得分:1)
第二个滑块的宽度为0的原因,第一个滑块使所有子节点(恰好是嵌套滑块)的宽度为0.
然后,内部滑块获得其子宽度(如上所述)为0.因此第二个滑块中的所有内容的宽度均为0.
对此的解决方法(这不是一个完全修复,因为它会产生另一个问题,但它确实回答了文字问题),是先初始化第二个滑块然后再初始化外部滑块。像这样:
var mySlider2 = document.getElementById('second'),
slider2 = new simSlider(mySlider2);
var mySlider = document.getElementById('mySlider'),
slider = new simSlider(mySlider);
答案 1 :(得分:0)
我一直在玩这个。宽度问题发生在initSimSlider
的第一次运行期间,即主要滑块mySlider
。除content
外,子content[0]
DIV的宽度更改为零。 second
DIV也是content[1]
mySlider
,宽度为零,因此offsetWidth
变为零,用于设置second
'的宽度儿童DIV。 (您可以通过将内滑块放在第一个位置,使其成为content[0]
来演示此功能,而不会缩小为零。)
另一种解决方案是使用scrollWidth
而不是offsetWidth
,这将是父DIV中最宽子项的宽度。如果content
DIV的宽度相等,则不应影响布局。这消除了对首先初始化simSlider
的顺序的依赖性。
这是一个JSFiddle demo,其他一些调整。 HTH。