Thanx voor het programmatje om te kunnen inspecteren op de iPad.
Als voorbeeld neem ik de selectbox op de volgende pagina van mijn website:
http://www.devoetbalscout.nl/competitiezoeken.php
Dit is wat er gebeurd:
A: Desktop:
Als ik de geparsde html-code van de selectbox genaamd "zoekmanier" inspecteer op de desktop, dan krijg ik initieel het volgende:
<div class="customSelect custom" id="select-zoekmanier" style="width: 280px; z-index: 100;">
<select id="zoekmanier" class="custom"> ... met hierin de options & css: display="none" ... </select>
<div class="selectValueWrap"> ... met selected value ... </div>
<div class="selectList"> ... de lijst met options ... </div>
</div>
Na klikken op de selectbox wordt de html-code:
<div class="customSelect custom select-open" id="select-zoekmanier" style="width: 280px; z-index: 101;">
<select id="zoekmanier" class="custom"> ... met hierin de options & css: display="none" ... </select>
<div class="selectValueWrap"> ... met selected value ... </div>
<div class="selectList"> ... de lijst met options ... </div>
</div>
Kortom: de class "select-open" wordt toegevoegd aan de buitenste div en de z-index van deze div wordt verhoogd van 100 naar 101. Gevolg is dat de selectList zichtbaar wordt.
B: iPad:
Als ik de geparsde html-code van de selectbox genaamd "zoekmanier" inspecteer op de iPad, dan krijg ik initieel het volgende:
<div class="customSelect custom use-default" id="select-zoekmanier" style="width: 280px; z-index: 100;">
<select id="zoekmanier" class="custom"> ... met hierin de options & css: display="none" ... </select>
<div class="selectValueWrap"> ... met selected value ... </div>
<div class="selectList"> ... de lijst met options ... </div>
</div>
Na drukken op de selectbox verandert de html-code op de iPad niet en de class "select-open" wordt ook niet toegevoegd. De selectList is dus ook niet zichtbaar. Het enige dat er gebeurd is dat de selectbox heel kort grijs wordt en daarna weer terug verandert.
Iemand een idee wat hier mis gaat en hoe ik dit kan oplossen?
[size=xsmall]
Toevoeging op 06/02/2018 20:08:01:[/size]
Extra info:
De HTML-code van de selectbox:
<select id="zoekmanier" class="custom">
<option value="normaal" default="default" selected="selected">normaal zoeken</option>
<option value="normaal">normaal zoeken</option>
<option value="uitgebreid">uitgebreid zoeken</option>
</select>
De customselect wordt 'geactiveerd' met volgende code:
$(document).ready(function(){
$("select#zoekmanier.custom").each(function() {
var sb = new SelectBox({
selectbox: $(this),
height: 290,
width: 280,
changeCallback: function(val) {
var manier = val;
.. etc ...
}
});
});
});
Verder denk ik onderstaand bestandje van belang is (en vraag ik me af of ik scrollpane.js eigenlijk wel gebruik... ) aangezien daar de "select-open" class wordt toegevoegd.
(zie
http://www.roblaplaca.com/docs/custom-selectbox/ )
"SelectBox.js"
/**
* @classDescription Custom selectbox with the option to use jScrollPane
* for a custom scrollbar. Hides the original selectbox off
* screen so that it will still get picked up as a form element.
*
* @version 1.1.0
*
* @author Rob LaPlaca - [email protected]
* @date 04/05/2010
* @lastUpdate 03/09/2014
* @dependency jScrollPane.js optional
* jquery.mousewheel.js optional
*
* @param {DOMElement} options.selectbox the selectbox that is being customized, REQUIRED (default undefined)
* @param {Boolean} options.customScrollbar whether or not to use jScrollPane to restyle system scrollbar (default false)
* @param {Number} options.zIndex The default z-index of the selectbox. (default 100)
* @param {Function} options.changeCallback Function that gets executed on change of the selectbox (default empty function)
* @param {Function} options.manager Optional reference to a class that manages all instances of the selectbox
* @param {Object} options.scrollOptions jScrollPane options, refer to jscrollpane documentation for possible options
* http://www.kelvinluck.com/assets/jquery/jScrollPane/scripts/jScrollPane.js
*/
(function($){
window.SelectBoxManager = function(options){
var sbs = [],
self = this;
$(document).click(function(e) {
if($(e.target).parents(".customSelect").size() === 0) {
self.close();
}
});
this.add = function(sb) {
sbs.push(sb);
};
this.close = function() {
$(sbs).each(function() {
this.close();
});
};
};
var sb_manager = new SelectBoxManager();
window.SelectBox = function(options){
var self = this,
cfg = $.extend(true, {
manager: sb_manager,
customScrollbar: true,
zIndex: 100,
changeCallback: function(val) { },
truncate: function(str) {return str;},
scrollOptions: {}
}, options);
var $customSelect, $selectedValue, $selectValueWrap, $selectList, $dl, $options,
FOCUSED_CLASS = "focused",
SELECTED_CLASS = "selected",
SELECT_OPEN_CLASS = "select-open",
DISABLED_CLASS = "disabled",
HOVERED_CLASS = "hovered",
_useDefaultBehavior = false,
_isOpen = false,
_isEnabled = true,
_isFocused = false,
_selectedValue = "";
/**
* @constructor
*/
function init() {
// TODO: don't use userAgent matching to detect defaulting to device specific behavior
_useDefaultBehavior = navigator.userAgent.match(/iPad|iPhone|Android|IEMobile|BlackBerry/i) ? true : false;
if( _useDefaultBehavior ) {
cfg.selectbox.addClass("use-default");
}
var selectId = "",
selectedClass = cfg.selectbox.attr("class");
if(typeof cfg.selectbox.attr("id") !== "undefined") {
selectId = 'id="select-'+cfg.selectbox.attr("id")+'"';
}
cfg.selectbox.wrap('<div class="customSelect '+selectedClass+'" '+selectId+' />');
$customSelect = cfg.selectbox.parents(".customSelect");
$options = cfg.selectbox.find("option");
var selectListHTML = ['<div class="selectList"><div class="selectListOuterWrap"><div class="selectListInnerWrap"><div class="selectListTop"></div><dl>'];
selectListHTML.push(_renderOptions());
selectListHTML.push('</dl><div class="selectListBottom"></div></div></div></div>');
$customSelect.append('<div class="selectValueWrap"><div class="selectedValue">'+_selectedValue+'</div> <span class="caret"><img src="images/Icoontjes/selectarrowdown.jpg" class="arrowselectbox"></span></div>' + selectListHTML.join(""));
$dl = $customSelect.find("dl");
$selectedValue = $customSelect.find(".selectedValue");
$selectValueWrap = $customSelect.find(".selectValueWrap");
$selectList = $customSelect.find(".selectList");
$customSelect.width(cfg.width);
$dl.width(cfg.width - 2);
_bindEvents();
sb_manager.add(self);
}
/**
* @private
*/
function _bindEvents() {
$selectValueWrap.click(function() {
if(_isOpen) {
cfg.selectbox.focus();
self.close();
} else if(_isEnabled) {
if( _useDefaultBehavior ) {
cfg.selectbox.focus();
} else {
self.open();
//NIEUW:
$(".itm-0").remove();
//if ( $(".itm-0").parents.parents("#main-nav").length == 1 ) {
// // YES, the child element is inside the parent
//} else {
// // NO, it is not inside
//}
}
}
});
// delegated events
$dl.click(function(e) {
var $target = $(e.target);
if($target.is("dd") || $target.parents("dd")) {
if(e.target.tagName.toLowerCase() != "dd") {
$target = $target.parents("dd");
}
if(!$target.hasClass(DISABLED_CLASS) && $target.get(0)) {
self.jumpToIndex($target.get(0).className.split(" ")[0].split("-")[1]);
self.close();
if( ! _useDefaultBehavior ) {
cfg.selectbox.focus();
}
}
}
});
cfg.selectbox.focus(function(e) {
_isFocused = true;
$customSelect.addClass(FOCUSED_CLASS);
}).blur(function(e){
_isFocused = false;
$customSelect.removeClass(FOCUSED_CLASS);
});
if( _useDefaultBehavior ) {
cfg.selectbox.change(function(e) {
_updateValue( $(this).find("option:selected").html() );
});
}
cfg.selectbox.keyup(function(e){
self.close();
$options.each(function(i, itm){
if(itm.selected) {
self.jumpToIndex(i);
return false;
}
});
});
_bindHover();
}
/**
* @private
*/
function _bindHover() {
var $dds = $(".customSelect dd");
$dds.off("mouseover");
$dds.off("mouseout");
$dds.on("mouseover", function(e) {
var $target = $(e.target);
if(e.target.tagName.toLowerCase() != "dd") {
$target = $target.parents("dd");
}
$target.addClass(HOVERED_CLASS);
});
$dds.on("mouseout", function(e) {
var $target = $(e.target);
if(e.target.tagName.toLowerCase() != "dd") {
$target = $target.parents("dd");
}
$target.removeClass(HOVERED_CLASS);
});
}
/**
* @param {String} val
* @private
*/
function _updateValue(val) {
if($selectedValue.html() != val) {
$selectedValue.html(_truncate(val));
cfg.changeCallback(cfg.selectbox.val());
}
}
/**
* @returns {String} HTML generated after processing options
* @private
*/
function _renderOptions() {
var optionHTML = [];
$options.each(function(i, itm) {
var $this = $(this),
optgroup = $this.parents('optgroup'),
addlOptClasses = "",
iconMarkup = "";
// render optgroups if present in original select
if (optgroup.length > 0 && $this.prev().length === 0){
optionHTML.push('<dt>'+optgroup.attr('label')+'</dt>');
}
// if option has a classname add that to custom select as well
if(itm.className !== "") {
$(itm.className.split(" ")).each(function() {
iconMarkup += '<span class="' + this + '"></span>';
});
}
// add selected class to whatever option is currently active
if(itm.selected && !itm.disabled) {
_selectedValue = iconMarkup + _truncate($(itm).html());
addlOptClasses = " " + SELECTED_CLASS;
}
// Check for disabled options
if( itm.disabled ) {
addlOptClasses += " " + DISABLED_CLASS;
}
optionHTML.push('<dd class="itm-'+i+' ' + addlOptClasses + '">' + iconMarkup + itm.innerHTML + '</dd>');
});
if($selectedValue && $selectedValue.get(0) !== null) {
$selectedValue.html(_selectedValue);
}
return optionHTML.join("");
}
/**
* @private
*/
function _setupScrollbar() {
$dl.css("height","auto");
if(cfg.height && $dl.height() > cfg.height) {
$dl.css("height", cfg.height);
if(cfg.customScrollbar) {
self.scrollpane = $dl.jScrollPane($.extend({
contentWidth: 200
}, cfg.scrollOptions));
} else {
$dl.addClass("defaultScrollbar");
}
} else {
$dl.css({overflow: "hidden"});
}
}
/**
* @param {String} str
* @returns truncated display string
* @private
*/
function _truncate(str) {
var arr = str.split("</span>");
var valToTrunc = arr[arr.length - 1];
arr[arr.length - 1] = "";
var spans = arr.join("</SPAN>");
return spans + cfg.truncate(valToTrunc);
}
/**
* @public
*/
this.sync = function() {
$options = cfg.selectbox.find("option");
$dl.html(_renderOptions());
_bindHover();
_setupScrollbar();
};
/**
* @public
*/
this.disable = function() {
_isEnabled = false;
$customSelect.addClass(DISABLED_CLASS);
cfg.selectbox.attr("disabled", "disabled");
};
/**
* @public
*/
this.enable = function() {
_isEnabled = true;
$customSelect.removeClass(DISABLED_CLASS);
cfg.selectbox.removeAttr("disabled");
};
/**
* @public
*/
this.close = function() {
$customSelect.removeClass(SELECT_OPEN_CLASS);
$customSelect.css({"z-index": cfg.zIndex});
_isOpen = false;
};
/**
* @public
*/
this.open = function() {
_setupScrollbar();
if(cfg.manager) {
cfg.manager.close();
}
$customSelect.addClass(SELECT_OPEN_CLASS);
if(self.scrollpane) {
self.scrollpane.data('jsp').scrollToY($customSelect.find(".selected").position().top);
}
$customSelect.css({"z-index": cfg.zIndex + 1});
_isOpen = true;
};
/**
* @param {Number} index
* @public
*/
this.jumpToIndex = function(index) {
cfg.selectbox.get(0).selectedIndex = index;
$customSelect.find(".selected").removeClass(SELECTED_CLASS);
$customSelect.find(".itm-" + index).addClass(SELECTED_CLASS);
_updateValue($customSelect.find(".itm-" + index).html());
};
/**
* @param {String} value
* @returns {Number} index of the value
* @public
*/
this.jumpToValue = function(value) {
var index = -1;
$options.each(function(i) {
if (this.innerHTML==value){
index = i;
return false;
}
});
if (index!=-1){
self.jumpToIndex(index);
}
return index;
};
init();
};
})(jQuery);
[size=xsmall]
Toevoeging op 07/02/2018 10:49:25:[/size]
Dit issue kan gesloten worden...
Gisterennacht een hoop gezocht en nu blijkt dat bij deze versie (SelectBox.js v1.1) van Rob LaPlaca het niet openen van selectboxen op iOS een known problem is.
(zie:
https://github.com/roblaplaca/jQuery-Custom-Selectbox/issues/12 )
Rob LaPlaca heeft hier zelf het issue geclassificeerd als major bug en er is sinds 2014 geen nieuwere versie uitgekomen. Opvallend is dat bij versie 1.0 de selectboxen wel werken op de iPad (dit kun je testen door de volgende pagina te openen op de iPad:
http://www.roblaplaca.com/docs/custom-selectbox/ .
Dus ik heb gezocht naar versie 1.0 en een beetje een mix document gemaakt van 1.0 en 1.1 en nnu werken de selectboxen zowel op de desktop als op de iPad.
Mocht iemand met hetzelfde probleem zitten, dit is de code van mijn mix-bestandje:
/**
* @classDescription Custom selectbox with the option to use jScrollPane
* for a custom scrollbar. Hides the original selectbox off
* screen so that it will still get picked up as a form element.
*
* @version 1.0.0 - let op: aangepast met enkele elementen van v1.1.0
*
* @author Rob LaPlaca - [email protected] - let op: aangepast met enkele elementen van v1.1.0
* @date 04/05/2010
* @lastUpdate 07/02/2018
* @dependency jScrollPane.js optional
* jquery.mousewheel.js optional
*
* @param {DOMElement} options.selectbox the selectbox that is being customized, REQUIRED (default undefined)
* @param {Boolean} options.customScrollbar whether or not to use jScrollPane to restyle system scrollbar (default false)
* @param {Number} options.zIndex The default z-index of the selectbox. (default 100)
* @param {Function} options.changeCallback Function that gets executed on change of the selectbox (default empty function)
* @param {Function} options.manager Optional reference to a class that manages all instances of the selectbox
* @param {Object} options.scrollOptions jScrollPane options, refer to jscrollpane documentation for possible options
* http://www.kelvinluck.com/assets/jquery/jScrollPane/scripts/jScrollPane.js
*/
(function($){
/*
// v1.0:
var undefined;
$.SelectBoxManager = function(options){
var sbs = [],
self = this;
$(document).click(function(e) {
if($(e.target).parents(".customSelect").get(0) == null) {
self.close();
}
});
this.add = function(sb) {
sbs.push(sb);
};
this.close = function() {
$(sbs).each(function() {
this.close();
});
};
};
*/
/*
// v1.verder:
window.SelectBoxManager = function(options){
var sbs = [],
self = this;
$(document).click(function(e) {
if($(e.target).parents(".customSelect").size() === 0) {
self.close();
}
});
this.add = function(sb) {
sbs.push(sb);
};
this.close = function() {
$(sbs).each(function() {
this.close();
});
};
};
*/
// /*
// mix:
window.SelectBoxManager = function(options){
var sbs = [],
self = this;
$(document).click(function(e) {
if($(e.target).parents(".customSelect").get(0) == null) {
self.close();
}
});
this.add = function(sb) {
sbs.push(sb);
};
this.close = function() {
$(sbs).each(function() {
this.close();
});
};
};
// */
/* // v1.0:
$.SelectBox = function(options){
var self = this,
cfg = $.extend(true, {
customScrollbar: false,
zIndex: 100,
changeCallback: function(val) { },
truncate: function(str) {return str;},
scrollOptions: {}
}, options);
var $customSelect, $selectedValue, $selectValueWrap, $selectList, $dl, $options,
_isOpen = false,
_isEnabled = true,
_isFocused = false,
_selectedValue = "";
*/
/*
// v1.verder:
var sb_manager = new SelectBoxManager();
window.SelectBox = function(options){
var self = this,
cfg = $.extend(true, {
manager: sb_manager,
customScrollbar: true,
zIndex: 100,
changeCallback: function(val) { },
truncate: function(str) {return str;},
scrollOptions: {}
}, options);
var $customSelect, $selectedValue, $selectValueWrap, $selectList, $dl, $options,
FOCUSED_CLASS = "focused",
SELECTED_CLASS = "selected",
SELECT_OPEN_CLASS = "select-open",
DISABLED_CLASS = "disabled",
HOVERED_CLASS = "hovered",
_useDefaultBehavior = false,
_isOpen = false,
_isEnabled = true,
_isFocused = false,
_selectedValue = "";
*/
// /*
// mix:
var sb_manager = new SelectBoxManager();
window.SelectBox = function(options){
var self = this,
cfg = $.extend(true, {
customScrollbar: false,
zIndex: 100,
changeCallback: function(val) { },
truncate: function(str) {return str;},
scrollOptions: {}
}, options);
var $customSelect, $selectedValue, $selectValueWrap, $selectList, $dl, $options,
_isOpen = false,
_isEnabled = true,
_isFocused = false,
_selectedValue = "";
// */
// versie 1.0:
function init(){
var selectId = "";
if(cfg.selectbox.attr("id") != "") {
selectId = 'id="select-'+cfg.selectbox.attr("id")+'"';
}
cfg.selectbox.wrap('<div class="customSelect" '+selectId+' />');
$customSelect = cfg.selectbox.parents(".customSelect");
$options = cfg.selectbox.find("option");
var selectListHTML = ['<div class="selectList"><div class="selectListOuterWrap"><div class="selectListInnerWrap"><div class="selectListTop"></div><dl>'];
selectListHTML.push(_renderOptions());
selectListHTML.push('</dl><div class="selectListBottom"></div></div></div></div>');
$customSelect.append('<div class="selectValueWrap"><div class="selectedValue">'+_selectedValue+'</div></div>' + selectListHTML.join(""));
$dl = $customSelect.find("dl");
$selectedValue = $customSelect.find(".selectedValue");
$selectValueWrap = $customSelect.find(".selectValueWrap");
$selectList = $customSelect.find(".selectList");
$customSelect.width(cfg.width);
$dl.width(cfg.width);
_bindEvents();
}
// versie 1.0:
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
* start:private
* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
function _bindEvents() {
$selectValueWrap.click(function() {
if(_isOpen) {
cfg.selectbox.focus();
self.close();
} else if(_isEnabled) {
self.open();
}
});
// delegated events
$dl.click(function(e) {
var $target = $(e.target);
if($target.is("dd") || $target.parents("dd")) {
if(e.target.tagName.toLowerCase() != "dd") {
$target = $target.parents("dd");
}
if($target.get(0)) {
self.jumpToIndex($target.get(0).className.split(" ")[0].split("-")[1]);
self.close();
cfg.selectbox.focus();
}
}
});
cfg.selectbox.focus(function(e){
_isFocused = true;
$customSelect.addClass("focused");
}).blur(function(e){
_isFocused = false;
$customSelect.removeClass("focused");
});
cfg.selectbox.keyup(function(e){
self.close();
$options.each(function(i, itm){
if(itm.selected) {
self.jumpToIndex(i);
return false;
}
});
});
_bindHover();
}
/*
// versie 1.0:
function _bindHover() {
var $dds = $(".customSelect dd");
$dds.die("mouseover");
$dds.die("mouseout");
$dds.live("mouseover", function(e) {
var $target = $(e.target);
if(e.target.tagName.toLowerCase() != "dd") {
$target = $target.parents("dd");
}
$target.addClass("hovered");
});
$dds.live("mouseout", function(e) {
var $target = $(e.target);
if(e.target.tagName.toLowerCase() != "dd") {
$target = $target.parents("dd");
}
$target.removeClass("hovered");
});
}
*/
// versie 1.1:
function _bindHover() {
var $dds = $(".customSelect dd");
$dds.off("mouseover");
$dds.off("mouseout");
$dds.on("mouseover", function(e) {
var $target = $(e.target);
if(e.target.tagName.toLowerCase() != "dd") {
$target = $target.parents("dd");
}
$target.addClass(HOVERED_CLASS);
});
$dds.on("mouseout", function(e) {
var $target = $(e.target);
if(e.target.tagName.toLowerCase() != "dd") {
$target = $target.parents("dd");
}
$target.removeClass(HOVERED_CLASS);
});
}
// versie 1.0:
function _updateValue(val) {
if($selectedValue.html() != val) {
$selectedValue.html(_truncate(val));
cfg.changeCallback(cfg.selectbox.val());
}
}
// versie 1.0:
function _renderOptions() {
var optionHTML = [];
$options.each(function(i, itm) {
var $this = $(this);
var optgroup = $this.parents('optgroup');
if (optgroup.length > 0 && $this.prev().length === 0){
optionHTML.push('<dt>'+optgroup.attr('label')+'</dt>');
}
var iconMarkup = "";
if(itm.className != "") {
$(itm.className.split(" ")).each(function() {
iconMarkup += '<span class="' + this + '"></span>';
});
}
if(itm.selected) {
_selectedValue = iconMarkup + _truncate($(itm).html());
optionHTML.push('<dd class="itm-'+i+' selected">' + iconMarkup + itm.innerHTML + '</dd>');
} else {
optionHTML.push('<dd class="itm-'+i+'">' + iconMarkup + itm.innerHTML + '</dd>');
}
});
if($selectedValue && $selectedValue.get(0) != null) {
$selectedValue.html(_selectedValue);
}
return optionHTML.join("");
}
// versie 1.0:
function _setupScrollbar() {
$dl.css("height","auto");
if(cfg.height && $dl.height() > cfg.height) {
$dl.css("height", cfg.height);
if(cfg.customScrollbar) {
self.scrollpane = $dl.jScrollPane($.extend({tabIndex: -1, scrollbarMargin: 0}, cfg.scrollOptions));
} else {
$dl.addClass("defaultScrollbar");
}
} else {
$dl.css({overflow: "hidden"});
}
}
// versie 1.0:
function _truncate(str) {
var arr = str.split("</span>");
var valToTrunc = arr[arr.length - 1];
arr[arr.length - 1] = "";
var spans = arr.join("</SPAN>");
return spans + cfg.truncate(valToTrunc);
}
// end:private
// versie 1.0:
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
* start:public
* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
this.sync = function() {
$options = cfg.selectbox.find("option");
$dl.html(_renderOptions());
$dl.jScrollPaneRemove();
_bindHover();
_setupScrollbar();
};
this.disable = function() {
_isEnabled = false;
$customSelect.addClass("disabled");
cfg.selectbox.attr("disabled", "disabled");
};
this.enable = function() {
_isEnabled = true;
$customSelect.removeClass("disabled");
cfg.selectbox.removeAttr("disabled");
};
this.close = function() {
$customSelect.removeClass("select-open");
$customSelect.css({"z-index": cfg.zIndex});
_isOpen = false;
};
this.open = function() {
_setupScrollbar();
if(cfg.manager) {
cfg.manager.close();
}
$customSelect.addClass("select-open");
if(self.scrollpane) {
self.scrollpane[0].scrollTo($customSelect.find(".selected").position().top);
}
$customSelect.css({"z-index": cfg.zIndex + 1});
_isOpen = true;
};
this.jumpToIndex = function(index) {
cfg.selectbox.get(0).selectedIndex = index;
$customSelect.find(".selected").removeClass("selected");
$customSelect.find(".itm-" + index).addClass("selected");
_updateValue($customSelect.find(".itm-" + index).html());
};
this.jumpToValue = function(value) {
var index = -1;
$options.each(function(i){
if (this.innerHTML==value){
index = i;
return false;
}
});
if (index!=-1){
self.jumpToIndex(index);
}
return index;
};
// end:public
init();
};
})(jQuery);