Styling jQuery mobile Checkboxes - javascript

I have very little experience with CSS.
I'd like to style the default JQuery Checkboxes to move the checked icon from left to right.
I have used my badass Paint skills to illustrate what I'm looking for.
So I'm not asking for someone else to do the job, just some pointers in the right direction.
What would be the best way to achieve this ?
Thank you !

jquery-mobile v1.0 has a custom data attribute that you can use to adjust icon positioning. This includes checkboxes, radio buttons, nav bars, and other elements.
Documentation:
http://code.jquery.com/mobile/latest/demos/docs/buttons/buttons-icons.html
To create the checkbox you've drawn in your question above, your code would be:
<input type="checkbox" name="checkbox-name" id="checkbox-id" />
<label for="checkbox-id" data-iconpos="right">I agree</label>
Notice that data-iconpos is applied to the label. That's because jQuery Mobile styles this element heavily to act as the UI element in the front-end. In other words, with this attribute, you're positioning the checked/unchecked icon to the right side of the label.
Note: If you attempt to workaround this attribute and add class="ui-btn-icon-right" to your elements, jQuery Mobile may drop those classes when the page renders.

Try looking at the rendered output after jQuery Mobile parses your code using Firebug.
You will be able to see the structure and classes added to the form element. The class names added by jQuery Mobile are pretty strait-forward to understand.
--UPDATE--
Here is the HTML from firebug for the jQuery Mobile documentation for check-boxes:
<div data-role="fieldcontain" class="ui-field-contain ui-body ui-br">
<fieldset data-role="controlgroup" class="ui-corner-all ui-controlgroup ui-controlgroup-vertical"><div class="ui-controlgroup-label" role="heading">Agree to the terms:</div><div class="ui-controlgroup-controls">
<div class="ui-checkbox"><input type="checkbox" class="custom" id="checkbox-1" name="checkbox-1"><label for="checkbox-1" data-theme="c" class="ui-btn ui-btn-icon-left ui-corner-top ui-corner-bottom ui-controlgroup-last ui-checkbox-on ui-btn-up-c"><span class="ui-btn-inner ui-corner-top ui-corner-bottom ui-controlgroup-last"><span class="ui-btn-text">I agree</span><span class="ui-icon ui-icon-shadow ui-icon-checkbox-on"></span></span></label></div>
</div></fieldset>
</div>
Notice the "ui-btn-icon-left" class, I'd play with that, you may not just be able to change it to "ui-btn-icon-right" but you can play with the structure. I've done this for other elements however I have not tested with check-boxes.

This is now part of JQM using the standard APIs by setting data-iconpos="right"
See http://demos.jquerymobile.com/1.4.3/checkboxradio-checkbox/#Iconposition for more details

Related

Best way to update aria-expanded attribute when using :focus-within

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>

How can I adjust the z-index of a tooltip for a Bootstrap form field?

I'm trying to add field validation to a "Contact Us" form using Bootstrap and a validation library (a jQuery Plugin) called Validetta (http://lab.hasanaydogdu.com/validetta/).
After implementing the form and the validation, though, I am noticing a problem with the z-index of the tooltip that causes it to show up beneath the next form field.
If I were dealing with normal HTML and CSS, I think the answer would be a little more clear to me, but with Bootstrap, I do not know what sort of mysticism is afoot and am having trouble finding answers on how to solve this problem in the best-practices way.
I know that Validetta is adding a <SPAN> after the form field and is applying a custom CSS class to it, which I can easily modify, override, or append. I've also read, in other contexts, that this problem can be solved using a combination of z-index and position on the tooltip SPAN and one or more of its parent elements... but all of my quick tests and trials have not had the desired affect.
Here's the rendered HTML for the form field shown above:
<div class="form-group has-feedback has-error">
<label class="control-label" for="inputFromName">Your Name</label>
<input type="text" class="form-control" id="inputFromName" name="fromName" placeholder="Your Name Here" data-validetta="required" data-vd-message-required="This field is required!">
<span class="validetta-bubble validetta-bubble--bottom">This field is required!<br></span>
</div>
Any help would be much appreciated!
you may check the z-index attribute on parent elements of "validetta-bubble" ;
because z-index judge from parent to child, if a parent has a lower z-index while child elemtn has a higher this element's z-index finally work base on the parenet's
you may try to set form-group's z-index
.form-group {
z-index: 10000;
position: relative;
}
and set a higher on target like answer 1
.crazy-zindex {
z-index: 10001;
}
Ultimately, I found the answer to this question here: z-index of hover tooltip with CSS
The answer from Панайот Толев provided this example:
<div class="level1">
<span class="level2"> 1 </span>
<span class="level2"> 2 </span>
<span class="level2"> 3 </span>
</div>
So, to solve the problem, I wrapped each row of form elements in a div that specified a z-index in the style attribute. As I went down the rows, I decreased the z-index value, like so:
<div style="z-index: 23;"> .. </div>
<div style="z-index: 22;"> .. </div>
<div style="z-index: 21;"> .. </div>
This ensured that each row fell "behind" the one above, which allowed tool-tips to appear on top of the fields (and labels), rather than beneath them.
I had same issue.
When no other script solved my problem. Then I had used parent class as data-container.
For exp.
<ul id="responsivator">
<li data-placement="bottom" data-toggle="tooltip" data-container="#responsivator" title="iPhone landscape Preview" >
</ul>
I would add a custom class like crazy-zindex (I'm sure you can come up with a better name) and a rule in the css for it.
HTML
<span class="validetta-bubble validetta-bubble--bottom crazy-zindex">This field is required!<br></span>
^^^^^^^^^^^^
CSS
.crazy-zindex {
z-index: 10000;
}
Its important to remember that CSS is cascading, so the last rule will overwrite anything above it, with this said, any overwrites you want to do to bootstrap you'll have to link that stylesheet after bootstrap. Or you can use !important but that's not good practice.

Refactoring overuse of jQuery show/hide methods for simple buttons

I have implemented some buttons on a web page that show and hide some text based on which button the user clicks:
Please bear in mind that the .reveal-1 fragment is set to display:none in the CSS by default.
http://bestclownintown.co.uk/ct/bootstrap-3.3.7/docs/examples/CT_task/index.html
HTML:
<div class="media">
<div class="media-left"> <img alt="New delivery options" class="media-object" src="images/thumbnail-new-delivery-options.jpg"> </div>
<div class="media-body">
<h4 class="media-heading">Cotton Traders Introduces New Delivery Options</h4>
<p class="text-muted">14th January 2016</p>
<p>Cheshire based retailer, Cotton Traders, has added three new delivery options to its e-commerce offering, in order to improve the customer shopping experience.</p>
<a class="btn btn-default reveal-button-1" href="#" role="button">Read More <i class="fa fa-caret-down" aria-hidden="true"></i></a>
<div class="reveal-1">
<p>The casual clothing retailer now offers its UK customers a choice of standard, next day, Sunday and nominated delivery options.</p>
<p>With more delivery options to choose from, customers will benefit from this added convenience, allowing them to get their items quicker and at a time that suits them, for as little as £3.99.</p>
<p>Talking about the introduction, Supply Chain Director, Caroline Allerton, said: "As a company we are constantly striving to improve the offering for our customers and this includes the delivery options.</p>
<p>"We know that our customers all have busy lives, so the introduction of these options will fit into their schedule and allow them to get their orders when they need them."</p>
<p>The introduction comes after Cotton Traders launched its dedicated Australian e-commerce website earlier this year.</p>
<a class="btn btn-default hide-button-1" href="#" role="button">Read Less <i class="fa fa-caret-up" aria-hidden="true"></i></a>
</div>
</div>
</div>
JS:
$(".reveal-button-1").click(function(){
$(".reveal-1").show();
});
$(".reveal-button-1").click(function(){
$(".reveal-button-1").hide();
});
$(".reveal-button-1").click(function(){
$(".hide-button-1").show();
});
$(".hide-button-1").click(function(){
$(".reveal-1").hide();
});
$(".hide-button-1").click(function(){
$(".hide-button-1").hide();
});
$(".hide-button-1").click(function(){
$(".reveal-button-1").show();
});
1) So in the first call to the jQuery object we show the <div> with a class of .reveal-1 when .reveal-button-1 is clicked
2) Then we hide .reveal-button-1
3) We then show .hide-button-1 when .reveal-button-1 is clicked
Now the hide button is present in the DOM.
4) We hide the <div> with a class of .reveal-1 when .hide-button-1 is clicked
5) We hide .hide-button-1
6) Finally we show .reveal-button-1 again.
Are there any solutions I can apply to refactor my JavaScript, so that I am not calling to the jQuery object as often and repeating myself so many times. I am aware of the .toggle method but I am not sure that it can be applied in this case. Please give a thorough explanation with your answer as I need to understand the jQuery logic. I have tried to keep the jQuery logic as simple as possible as I am only of a junior level.
I currently have 24 lines of jQuery code for 4 HTML fragements which seems quite excessive, but I don't know if there is a better way to implement/optimise.
here it is,
On any button click all element toggles visibility. its exactly what you need.
$(".reveal-button-1, .hide-button-1").click(function(){ //on click of either button.
$(".reveal-1, .reveal-button-1, .hide-button-1").toggle(); //toggle visibilty on all the corresponding elements
});
Make sure your initial values (display:none) are correct.
reveal button click will hide itself, show the hide button and toggle the reveal field (to show).
since the hidden button is now visible and the reveal button is no longer. once we click on this button the field will toggle (to be hidden again). the reveal button will be visible again.
side note: You probably want to use better css classes in your html though. (to make a more generic javascript code so that you can re-use its functionality).
re-usable solution
here is a re-usable version, with better classes.
$('.toggle-btn').click(function(){
$(this).closest('.container').find('.toggle').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="toggle-btn toggle" style="display:none;">show</div>
<div class="toggle-btn toggle">hide</div>
<div class="toggle">bla bla</div>
</div>
<div class="container">
<div class="toggle-btn toggle" style="display:none;">show</div>
<div class="toggle-btn toggle">hide</div>
<div class="toggle">bla bla</div>
</div>
Explanation: when a toggle-button is clicked. it goes and finds the first parent that has a class .container. then from this parent, it checks all the html elements with the .toggle class inside this container and toggles their visibility.
Side note on this solution: it is not a very prerformant solution because every time it tries to find the container class in its parents and then tries to find all the childs with class toggle. (better is to cache these classes). but for this simple solution it doesn't really matter.
out of the box libraries
bootstrap collapse
jquery accordion
You only need one event handler for each element. Repeating like that causes a lot of extra functions to be called on each event, which will slow your site down. (Probably not noticeably, but if your site grows it could become problematic.)
If your HTML is structured similarly for each of your sections, you could eliminate the specific classes, and go on a more general approach. (Shortened for brevity.)
<a class="... reveal-button"...>
<div class="reveal">
...
<a class="... hide-button"...>
</div>
Then down inside your JavaScript, instead of 4 sets of all your calls, you can do just a single. I'll explain how this works as we go. The function .on() is the preferred method to wire events since jQuery 1.7.
$('.reveal-button').on('click', function () {
var $self = $(this); // 'this' will be the element that was clicked.
$self.next('div.reveal')
.show();
$self.hide();
});
$('.hide-button').on('click', function () {
var $parent = $(this).parent(); // refers to div.reveal
$parent.hide(); // hide the div
$parent.prev('a.reveal-button').show(); // show the reveal button.
});

Unwanted scrolling with jQuery Buttonset

jQuery UI buttons/buttonsets are giving me fits. I have searched this site for answers, and still do not have a an answer that works well. I am using jQuery rev 1.11.1 and jQuery UI rev 1.9.2.
I have a buttonset of three buttons that my users click to choose 1 of 3 color themes available for use on their website. Once they click the button, I show a sample website banner with the selected color theme to the right of the button set. So I am basically swapping out an image based on their selection.
Relevant HTML:
<div style="float:left; width: 275px;">
<label for="radio">Your Club Website Color Theme</label>
<div id="colortheme">
<input type="radio" style="float:left;" id="colortheme1" name="colortheme" value="1" {{ct1}} ><label for="colortheme1">Theme 1</label>
<input type="radio" style="float:left;" id="colortheme2" name="colortheme" value="2" {{ct2}} ><label for="colortheme2">Theme 2</label>
<input type="radio" style="float:left;" id="colortheme3" name="colortheme" value="3" {{ct3}} ><label for="colortheme3">Theme 3</label>
</div>
</div>
<div style="margin-left:300px;">
<img id="bannerSample" src="/images/club{{BannerTheme}}.jpg" style="max-width:100%">
</div>
Relevant Javascript:
jQuery("#colortheme input:radio").click(function(e){
me.$form.hide();
jQuery("#bannerSample").attr('src','/images/club'+this.value+'.jpg');
me.$form.show();
});
Note: {{ct1}}, {{ct2}}, & {{ct3} are patched in by the Perl server code; me.$form is just a jQuery object for the form set above the code snippet above. This buttonset is located in a tab panel inside a jQuery UI dialog. The problem is that I am getting unintended scrolling down in the dialog when I click one of the buttons in the button set. I have tried all the usual solutions, e.preventDefault(), e.stopPropagation(), return false, .on(), etc., based on research on this and other websites. Cannot find the right solution or combination to stop the unwanted scroll. The above is the best thing I could come up with. It still scrolls down on the first click, but after that, it just flashes as it updates the image.
Can anyone recommend a better approach?
The issue for me was caused by a conflict in css. Specifically the class 'ui-helper-hidden-accessible' has a position of absolute which for some reason causes the scrolling behavior.
I chose to create a more specific rule in my own stylesheet to supercede the default jquery-ui css:
.ui-buttonset .ui-helper-hidden-accessible{
position:relative;
}
Alternatively, you could use display:none but I wasn't sure if that would have unintended consequences in other browsers. I chose this route rather than rewriting the jquery-ui rule because I wasn't sure if there were specific use cases for other ui elements where a position of absolute will be needed and I didn't want to have to remember not to overwrite the css if I update.
I figured this out through a wordpress bug ticket https://core.trac.wordpress.org/ticket/23684 although it should be noted that I am not working on a wordpress site so the solution posed is independent.

Difficulty with selective show/hide based on CSS class

I'm working on a js script which will show / hide multiple divs based on css class, seemingly pretty simple. I set out to find an example of this and found something close in the article linked below. I used the code in the following link as a starting point.
Show/hide multiple divs using JavaScript
In my modified code (shown below) I am able to hide all (which is errant) and show all (which works correctly. I'm not sure why its not targeting the CSS class "red, green or blue" correctly. If I hard one of the class names in the script it works as expected, so I'm fairly certain I'm having an issue in the way I'm referencing the css targets themselves.
I am able to hide all and show all, yet I'm having difficulty showing only the selected class.
Here is the jsFiddle I'm working with: http://jsfiddle.net/juicycreative/WHpXz/4/
My code is below.
JavaScript
$('.categories li a').click(function () {
$('.marker').hide();
$((this).attr('target')).show();
});
$('#cat-show').click(function () {
$('.marker').show();
});
HTML
<ul class="categories">
<li id="cat-show" class="cat-col1" target="all" >All</li>
<li id="cat-models" class="cat-col1" target="red" >Model Homes</li>
<li id="cat-schools" class="cat-col1" target="blue">Schools</li>
<li id="cat-hospital" class="cat-col1" target="green" >Hospitals</li>
</ul>
<div id="locator">
<div id="overview-00" class="marker models" title="Maracay Homes<br />at Artesian Ranch"></div>
<!--SCHOOLS-->
<div id="overview-01" class="marker red" title="Perry High School">1</div>
<div id="overview-02" class="marker red" title="Payne Jr. High School">2</div>
<div id="overview-03" class="marker blue" title="Hamilton Prep">3</div>
<div id="overview-04" class="marker blue" title="Ryan Elementary">4</div>
<div id="overview-05" class="marker green" title="Chandler Traditional – Freedom">5</div>
</div>
Thanks in advance for any responses.
$((this).attr('target')).show();
This is syntactically incorrect. It should be $($(this).attr('target'))
However that's no good either because this is the anchor element that does not have the target. Use $(this).closest('li').attr('target') (or add the target to the <a>).
This is also semantically incorrect as that would interpolate to $("red") which would try to look for a <red> element.
$("." + $(this).closest('li').attr('target'))
http://jsfiddle.net/WHpXz/5/
You are almost there. This is the line that needs tweaking: $((this).attr('target')).show();
$(this) actually refers to the current anchor tag that was clicked. Since the anchor tag doesn't have the target attribute, you need to go up to the parent.
From there, you can get the target and add the '.' to the color to use as a selector.
var catToShow = $(this).parent().attr('target');
$('.' + catToShow).show();
I've edited your fiddle. Give it a shot.
http://jsfiddle.net/juicycreative/WHpXz/4/

Categories

Resources