I am attempting to create a listview control in jquery-mobile that has the ability for certain list items to expand and show child items. My goal is that this list is filterable, and the jquery-mobile data-filter="true" attribute is sufficient. Unfortunately, it seems to be inherited by < u l > and < o l > elements inside, and I end up with multiple filter controls. Is there a best practice for preventing this type of inheritence in jquery? Using jquery to remove extraneous form tags is a hack that works, but I'd rather do it as designed.
Here is a quick example:
<div data-role="content">
<div class="choice_list">
<h2>Select an item</h2><br />
<ul data-role="listview" data-inset="true" data-filter="true">
<li><a>Item</a></li>
<li data-role="collapsible">
<h3>Super Item</h3>
<ul data-role="listview" data-inset="true">
<li><a>Sub Item</a></li>
</ul>
</li>
</ul>
</div>
</div>
Please take a look at this JSFiddle for an example: http://jsfiddle.net/harlomic/SsJjS/3/.
You could use CSS to hide two of the three filter inputs:
/*hide all of the search filter forms*/
#test .choice_list form.ui-listview-filter {
display : none;
}
/*show just the first search filter form*/
#test .choice_list form.ui-listview-filter:nth-child(-n+3) {
display : block;
}
Here is a demo: http://jsfiddle.net/SsJjS/5/
Note that test is the ID of the page on which the list-views are found and choice_list is the class of the container element to your list-views.
I have also ran into this same problem with nested lists in JQM.
I messed around with it and if you remove data-role="listview" from your extra < ul >'s that will solve your problem, however, you will lose your JQM styling and that is not what you're looking for. We all want the slick layout and styling from JQM.
JQM should fix this as I also feel this could be a bug as I haven't found anything in the docs about this.
Related
I have a menu on the site in two places. One is made by text, and the other by pictures. You can click on both.
I want that when you hover over a specific item in a text menu (for example, under number 2), the picture with the same number changes (for example, under 2).
Code for text menu:
<ul>
<li class="page_item">
Test 1
</li>
<li class="page_item">
Test 2
</li>
</ul>
Code for Pictures menu:
<div class="project__card project__card-design">
<div class="project__card-design-bigelem">
</div>
<div class="project__card-design-bigelem">
</div>
<div class="project__card-design-bigelem">
</div>
</div>
Screen shot with Picture and text menu:
Screen shot with Picture and text menu
I will be grateful for any help!
Since I was looking for solutions that could identify the element with which number was highlighted. But so far I don’t even have ideas on how to do this.
All thanks in advance for any help!
If you like for this behaviour you can do this
hover: nav1 > imageNav1 ect...
You can get the index of the hover item and match that to the image nav item. Sorry for the markup, it's just to show you how you can implement it. You can also choose to do whatever after the matching is made in the mouseenter
$(".js-hover").on("mouseenter", function () {
const hoverIndex = $(this).index();
const $imageListItems = $(".image-list > li");
$imageListItems.removeClass("image-list__item--selected");
$imageListItems.eq(hoverIndex).addClass("image-list__item--selected");
});
.image-list__item--selected {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="list">
<li class="js-hover">text</li>
<li class="js-hover">text</li>
<li class="js-hover">text</li>
<li class="js-hover">text</li>
</ul>
<ul class="image-list">
<li>image1</li>
<li>image2</li>
<li>image3</li>
<li>image4</li>
</ul>
Here's a solution with pure js, works for elements that are not parents using ids.
html
<li id="child1" onmouseenter="customHover(event)" onmouseleave="handlemouseleave(event)"></li>
<div id="parent1"> </div>
<li id="child2" onmouseenter="customHover(event)" onmouseleave="handlemouseleave(event)"></li>
<div id="parent2"> </div>
<li id="child3" onmouseenter="customHover(event)" onmouseleave="handlemouseleave(event)"></li>
<div id="parent3"> </div>
and heres the js
function customHover(e){
let id = e.target.id;
let idNumber = id.slice(id.length - 1);
document.getElementById(`parent${idNumber}`).style.border = '1px solid red';
}
function handleMouseLeave(e){
let id = e.target.id;
let idNumber = id.slice(id.length - 1);
document.getElementById(`parent${idNumber}`).style.border = 'unset';//or whatever you need to change the styles back to the original
}
there are many solutions , with an without using libraries. I think you may use some jquery if possible , and if not you should search for addeventlistener (the advanced way)
https://api.jquery.com/hover/
is a good example of doing what you are trying todo .
var pageitemcount=0;
$( ".page_item" ).hover(function() {
pageitemcount++;
$.post("/mypageitemcounter.php",{pageitemcount:pageitemcount});
$(this).parent().append( $( "<span>"+pageitemcount+"</span>" ) );
});
The above part is for php , still can be used in a plugin.
If you are in wordpress environment , you have to dig into how to write wp plugins also. Trying to achieve this in an environment , and then applying the same to your custom wp plugin is the way to go. Do not change the existing plugins, or themes if possible. This may cause headaches after an update.. In wp environment, writing a custom plugin is the way to go. You should tag your question as wp-plugin if possible.
I'm working on a combobox, and in doing so, I want to use the new :focus-within pseudo selector to manage displaying the expandable listbox that's associated with the combobox.
:focus-within is a great solution and works like a charm. The only problem I'm having is figuring out how to keep the aria-expanded attribute on the listbox updated. Because all of the hide/show functionality is happening in browser-land due to the pseudo-selector, I'm unsure of a hook I can use in Javascript to determine when the item is visible or not in order to update that property.
Is there an elegant solution anyone knows about? I'd hate to have to replicate the logic for focus/blur that :focus-within is handling right now just to update this attribute. I'm also concerned they may get out of sync. There any way to spy on an element with :focus-within or something like that?
.list {
display: none;
}
.combobox-container:focus-within .list {
display: block;
}
<section class="combobox-container">
<div role="combobox" aria-expanded="false" aria-owns="listbox" aria-haspopup="listbox">
<label> Foo
<input type="text" aria-autocomplete="list" aria-controls="listbox" />
</label>
</div>
<ul class="list" id="listbox" role="listbox" tabindex="0" aria-multiselectable="true">
<!-- items for autocomplete. focusable anchors inside li tags. -->
<li>Javascript</li>
<li>HTML</li>
<li>CSS</li>
</ul>
</section>
Accessibility guidelines for a combobox
focus-within only has 84% browser coverage
For this reason that instantly makes your solution inaccessible as a lot of screen reader users still use JAWs with Internet Explorer.
Additionally you have the problem that while this works as a demo, in the real world an auto-complete list will be populated via AJAX or via a preloaded list that is filtered.
This means that the list will always be shown the second you focus the <input>, even when nothing has been typed into the combobox (which is not expected behaviour).
This is one of the few circumstances where relying solely on JavaScript is acceptable (with a fallback that the form can still be submitted without JavaScript).
Instead of trying to use :focus-within you can instead use JavaScript to toggle aria-expanded="true" when you return some suggestions and then use standard CSS3 selectors to show and hide the results.
The below example shows the CSS to achieve this. The + operator is the key, it is the Adjacent Sibling Combinator that selects the next sibling within a parent element.
CSS: .combobox-container div[aria-expanded="true"]+.list
For the example below I have made it so that once you type more than 1 character into the box it will change the aria-expanded attribute to true (and back again if the input is empty) - this makes it feel more like a 'real world' example.
Side note: You do not need to add a tabindex to the <ul>, the expected behaviour is to tab directly to the first suggested item, I have removed that in the example below.
//ignore this, this is my standard jQuery replacement for snippets
if(typeof $=="undefined"){!function(b,c,d,e,f){f=b['add'+e]
function i(a,d,i){for(d=(a&&a.nodeType?[a]:''+a===a?b.querySelectorAll(a):c),i=d.length;i--;c.unshift.call(this,d[i]));}
$=function(a){return /^f/.test(typeof a)?/in/.test(b.readyState)?setTimeout(function(){$(a);},9):a():new i(a);};$[d]=i[d]={on:function(a,b){return this.each(function(c){f?c['add'+e](a,b,false):c.attachEvent('on'+a,b)})},off:function(a,b){return this.each(function(c){f?c['remove'+e](a,b):c.detachEvent('on'+a,b)})},each:function(a,b){for(var c=this,d=0,e=c.length;d<e;++d){a.call(b||c[d],c[d],d,c)}
return c},splice:c.splice}}(document,[],'prototype','EventListener');var props=['add','remove','toggle','has'],maps=['add','remove','toggle','contains'];props.forEach(function(prop,index){$.prototype[prop+'Class']=function(a){return this.each(function(b){if(a){b.classList[maps[index]](a);}});};});$.prototype.hasClass=function(a){return this[0].classList.contains(a);};}
$.prototype.find=function(selector){return $(selector,this);};$.prototype.parent=function(){return(this.length==1)?$(this[0].parentNode):[];};$.prototype.findWithin=function(a){console.log("THIS IS",this[0],a);return this[0].getElementsByClassName(a);};$.prototype.first=function(){return $(this[0]);};$.prototype.focus=function(){return this[0].focus();};$.prototype.css=function(a,b){if(typeof(a)==='object'){for(var prop in a){this.each(function(c){c.style[prop]=a[prop];});}
return this;}else{return b===[]._?this[0].style[a]:this.each(function(c){c.style[a]=b;});}};$.prototype.text=function(a){return a===[]._?this[0].textContent:this.each(function(b){b.textContent=a;});};$.prototype.html=function(a){return a===[]._?this[0].innerHTML:this.each(function(b){b.innerHTML=a;});};$.prototype.attr=function(a,b){return b===[]._?this[0].getAttribute(a):this.each(function(c){c.setAttribute(a,b);});};$.param=function(obj,prefix){var str=[];for(var p in obj){var k=prefix?prefix+"["+p+"]":p,v=obj[p];str.push(typeof v=="object"?$.param(v,k):encodeURIComponent(k)+"="+encodeURIComponent(v));}
return str.join("&");};$.prototype.append=function(a){return this.each(function(b){b.appendChild(a[0]);});};$.ajax=function(a,b,c,d){var xhr=new XMLHttpRequest();var type=(typeof(b)==='object')?1:0;var gp=['GET','POST'];xhr.open(gp[type],a,true);if(type==1){xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");}
xhr.responseType=(typeof(c)==='string')?c:'';var cb=(!type)?b:c;xhr.onerror=function(){cb(this,true);};xhr.onreadystatechange=function(){if(this.readyState===4){if(this.status>=200&&this.status<400){cb(this,false);}else{cb(this,true);}}};if(type){xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');xhr.send($.param(b));}else{xhr.send();}
xhr=null;};
//only part of the demo, not for production use
$('input').on('keyup', function(e){
if($(this)[0].value.length > 0){
$('div[role=combobox]').attr('aria-expanded', true);
return;
}
$('div[role=combobox]').attr('aria-expanded', false);
return;
});
.list {
display: none;
}
.combobox-container div[aria-expanded="true"]+.list{
display: block;
border:2px solid #333;
}
<section class="combobox-container">
<div role="combobox" aria-expanded="false" aria-owns="listbox" aria-haspopup="listbox">
<label> Foo
<input type="text" aria-autocomplete="list" aria-controls="listbox" />
</label>
</div>
<ul class="list" id="listbox" role="listbox" aria-multiselectable="true">
<!-- items for autocomplete. focusable anchors inside li tags. -->
<li>Javascript</li>
<li>HTML</li>
<li>CSS</li>
</ul>
</section>
I'm currently using a service for autocompleting my search boxes. However, for all the autocompleted results that show up, there's always a <div> ad on the bottom following the <li>s. Something like this:
<ul>
<li class="menu-item""></li>
<li class="menu-item""></li>
<li class="menu-item""></li>
<div style="text-align:center;border-top:1px solid black;"></div>
ad
</ul>
However, this is loaded dynamically using JS so I don't know how I would write jQuery to hide() it. Is there a way I could dynamically hide it when someone does a search?
You could do something like this in your CSS:
ul>* {display:none}
ul>li {display:block}
After all, it is only valid for <ul> elements to have <li> children, so you should be able to hide everything else as invalid.
If you are sure of the structure, you can always address it in jquery as
$("ul").find("a,div").hide()
Best would be of course css, as Kolink answered.
I don't know if I'm in the right place to ask this question.
I'm looking for examples or tutorials of vertical or side tabbed content where contents appear on the side. Like normal tabbed contents but this time sideways (preferably tabs on the left). But it seems that there's not a single thing about it online even using Google. Therefore I'm lost.
Or maybe I don't know the name of this technique.
Also I don't want to use jquery ui for this.
Can someone show me the way please?
Many thanks
Without jQueryUI you could do something very easy and clean like this (demo => http://jsfiddle.net/steweb/zwaBx/)
Markup:
<ul id="tabs-titles">
<li class="current"> <!-- default (on page load), first one is currently displayed -->
first
</li>
<li>
second
</li>
<li>
third
</li>
</ul>
<ul id="tabs-contents">
<li>
<div class="content">first content first content first content</div>
</li>
<li>
<div class="content">second content</div>
</li>
<li>
<div class="content">third content</div>
</li>
</ul>
CSS:
#tabs-titles{
float:left;
margin-right:10px;
}
#tabs-titles li{
cursor:pointer;
}
#tabs-titles li.current{
font-weight:bolder;
}
#tabs-contents{
background:#F2F2F2;
margin-left:100px;
padding:5px;
}
#tabs-contents li{
display:none;
}
#tabs-contents li:first-child{
display:block; /* first one content displayed by default */
}
JS: (simple jQuery, no UI)
var tabs = $('#tabs-titles li'); //grab tabs
var contents = $('#tabs-contents li'); //grab contents
tabs.bind('click',function(){
contents.hide(); //hide all contents
tabs.removeClass('current'); //remove 'current' classes
$(contents[$(this).index()]).show(); //show tab content that matches tab title index
$(this).addClass('current'); //add current class on clicked tab title
});
Here's one of many free tutorials: Vertical Tabs for jQuery lovers!
I found this one in pure javascript with no jquery:
http://webdevel.blogspot.com/2009/03/pure-accessible-javascript-tabs.html
Haven't tested it yet. I also found this one that uses no jquery, but leverages html5 and css3:
http://www.my-html-codes.com/javascript-tabs-html-5-css3
It seems my most successful search phrase for this topic is "pure javascript tabs" (without the quotes, of course). You'll find a those above plus some others if you run that search.
Found an example using jQuery UI
http://jquery-ui.googlecode.com/svn/trunk/demos/tabs/vertical.html
If you look at the source, it seems like they're just adding a class which positions it vertically and not horizontally
I've been having nothing but problems with this script for a simple hide/show gallery of testimonials.
I think the java is somewhat self explanatory...
When the page loads, I tell it to show the first testimonial in the line up (as the css is display:none) and gives it a selected class name. Works fine in across the board.
On click I want it to remove the selected class place it to another, and then hide the first testimonial and pull up a corresponding one. Except all that happens here is the first testimonial disappears (hide) and the selected class is added.
<script type="text/javascript">
$(document).ready(function(){
$(".testimonial:first").show();
$("li.testID:first").addClass("selectedName");
$("li.testID").click(function(){
$("li.testID").removeClass("selectedName");
$(this).addClass("selectedName");
$(".testimonial").hide();
$(this).next(".testimonial").fadeIn("slow");
});
});
</script>
Example of markup
<ul id="testName">
<li class="testID">Persons Name</li>
<blockquote class="testimonial">
<span class="bqStart">“</span>
Testimoinal here
<span class="bqEnd">”</span><br /><br />
<span class="testAuthor"><b>Name</b><a target="_blank" href="#">Website</a> Company</span>
</blockquote>
As a side note this is working fine in FF and Safari
Your help is greatly appreciated.
Thanks.
It's probably not working in IE because it's not valid markup: you can't have a blockquote as a direct child of a UL, so IE probably stores them in some weird place in the DOM tree which means .next doesn't find them. Can you move the blockquote elements into the li?
Is .testimonial the class you have given to your lists? <ul> or <ol>
It seems as if you are trying to get the next testimonial list to show, when infact you are actually getting the next <li> which has a class of .testimonial which I suspect is incorrect as you are using .testID as the class for your list items.
Please try this instead:
$(this).parent().next(".testimonial").fadeIn("slow");