Faking a toggle switch with an Input Range, dealing with custom range - javascript

I need to fake a toggle switch with an input range.
The idea is to create a short range, with just 2 values, min and max. the css button will match one end of the range. So far you click on it, the div containing the range will move a bit bringing the other end of the ranger under your mouse.
I have this function, which applies on all input ranges on the page. But i need to apply it only on some classes, not all. But i can't find the right syntax and it doesn't work.
The Javascript:
$('input[type="range"]').on('change', function() {
$('div#launcher01').css('margin-top', parseInt($(this).val() ) > 0 ? parseInt($(this).val() ) + 'px' : '0px');
});
CSS:
.fakbl input {
height: 50px;
width: 50px;
HTML:
<div id="launcher01">
<div class="fakbl">
<input type="range" id="launch01" name="launch01" min="0" max="50" step="50"" />
</div>
</div>
Fiddle

Since you are already using jQuery, you can phrase your widget-maker as a jQuery plugin as follows :
$.fn.rangeButton = function(containerSelector) {
return this.each(function() {
var $self = $(this);
$self.on('change', function() {
$self.closest(containerSelector).css('margin-left', ($self.val()/3) > 0 ? ($self.val()/3) + 'px' : '0px');
}).trigger('change'); // trigger 'change' immediately to initialize everything.
});
};
Now, invoke the widget on each of your ranges, and pass a selector for the appropriate container :
$('#launcher01 input[type="range"]').rangeButton('#launcher01');
$('#launcher02 input[type="range"]').rangeButton('#launcher02');
Demo
Alternatively, by giving all containers the same class, you can invoke all your widgets with a single command :
$('.myClass input[type="range"]').rangeButton('.myClass');
Demo

May I ask a refinement please?
I completed the fake button. As you can see in this FIDDLE
(the white box will disappear, I added some opacity to it just to show that the button is working)
The red box (now green due to my buggy code part) is in the background and I would need it to change color depending on the status. I tried this but it doesn't work.
Here the code:
$.fn.rangeButton = function(containerSelector) {
return this.each(function() {
var $self = $(this);
$self.on('change', function() {
$self.closest(containerSelector).css('margin-left', ($self.val()/3) > 0 ? ($self.val()/3) + 'px' : '0px');
// this part is not working, if you remove this part, the button works flawlessy
if ($self = 100) {
document.getElementById("fakbuttonsfondo01").style.backgroundColor="rgb(0, 191, 1)";
} else {
document.getElementById("fakbuttonsfondo01").style.backgroundColor="rgb(0, 0, 255)";
}
// end of buggy code
}).trigger('change'); // trigger 'change' immediately to initialize everything.
});
};
$('#launcher01 input[type="range"]').rangeButton('#launcher01');
$('#launcher02 input[type="range"]').rangeButton('#launcher02');
Thanks:)

Related

HTML "number" input not allowing JavaScript to display commas

NOTE: I know this is similar to other questions, but for semantic and other reasons (e.g. ease of input on iOS) I specifically want the HTML input to be type="number". This is where the problem comes in....
I'm trying to set up an HTML form so that number fields show thousands commas -- e.g. "10,000,000" instead of "10000000". I want to set it so that the field displays the commas, but when it gets focus for actual editing the commas go away.
I can manually add commas to the value without any issue (I'm testing mainly in Firefox ~59); but any time I try to have JavaScript add the commas, the field is blanked out instead. Does anyone know how to make this work?
(Note, I'm using Numerals.js for formatting here... http://numeraljs.com/ )
Here is what I have:
$(document).ready(function(){
var numberFields = $("input[type=number]");
numberFields.each( function(){
$(this).val( numeral( $(this).val() ).format('0') );
});
numberFields.focus( function(){
$(this).val( numeral( $(this).val() ).format('0') );
});
numberFields.blur( function(){
$(this).val( numeral( $(this).val() ).format('0,0') );
});
});
Example HTML input:
<input name="myField" value="0" type="number">
(Incidentally -- and conveniently, I've confirmed that submitting a number with commas to the HTML form processing script just drops the commas and puts the unformatted number into the DB. Sweet!)
I'm not familiar with numeral.js, but if I were doing it, I would just save the numeric value as a data attribute, and then format with .toLocaleString, keeping in mind that you have switch between text and number types so that you can display your commas:
Seeing the issues with iOS, I believe the following will work. You can clone the element, THEN set the original to be a text input. Then, get the position of the original, and set the new element to be absolutely positioned over the original. Now, set the number input to opacity: 0, this way you won't see it, but when they click, it will click your clone. When the clone is clicked, set it to opacity: 1, and when it is blurred, set the original input to the cloned input's value, but using toLocaleString. I checked that it works in firefox, in theory it should work on iOS as well.
$(document).ready(function(){
var $clones = [];
var numberFields = $("input[type='number']");
numberFields.each(function(i){
var $clone = $(this).clone();
$(this).attr('type', 'text');
var destination = $(this).offset();
var width = $(this).width();
$clones.push($clone.css({
position: 'absolute',
top: destination.top,
left: destination.left,
opacity: '0',
width: width
}));
$(this).after($clone);
var that = this;
$clone.on('focus', function() {
$(this).css('opacity', '1');
});
$clone.on('blur', function() {
$(this).css('opacity', '0');
$(that).val('' + $(this).val() ? parseInt($(this).val()).toLocaleString() : '');
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" pattern="[0-9,]*" />
NOTE: I'm leaving this original answer in case something here is useful down the road; but please see my other answer, which is a complete solution to the original question.
I've found no way to quite do what I want. Futzing with input "type" is too inconsistent in different browsers; and doesn't work anyway on iOS (which was 90% of the point). However, I did get "pretty close" working smoothly with the following. (NOTE this uses the numeral.js library for formatting):
JavaScript:
<script>
$(document).ready(function(){
var intFields = $("input[data-format=integer]");
intFields.each( function(){
$(this).attr( "pattern", "[0-9,]*" );
$(this).val( numeral( $(this).val() ).format('0,0') );
});
intFields.focus( function(){
$(this).val( numeral( $(this).val() ).format('0') );
});
intFields.blur( function(){
$(this).val( numeral( $(this).val() ).format('0,0') );
});
$("form#myForm").on( "submit", function(){
intFields.each( function() {
$(this).val( numeral( $(this).val() ).format('0') );
} );
return true;
} );
});
</script>
HTML:
<input type="text" data-format="integer" name="some_number" value="12345678>">
Overall, WAAAY too much work for such a common use-case. I hope browsers makers come up with a solution to this soon! There needs to be a simple, standard way to display numbers in fields.
My final function, based on Dave's answer. Dave's was not fully functional (though an effective proof of concept). This handles the name attribute (which is necessary for Form submit), and positions the input overlay relative to the original input, rather than the page (which prevents things going catywampus if the window is resized).
IMPORTANT: When using this, you must use <label>...</label><input>, NOT <label>...<input></label> for your number fields Fixed!:
$(document).ready(function() {
format_integers();
});
/**
* Any form inputs with type=number and data-format=integer will display contents with commas when input not in focus.
* #param container string to be used as jQuery search. Defaults to 'body'; but can be any specific element
*/
function format_integers(container) {
container = (typeof container !== 'undefined') ? container : 'body';
var $wrapper = $('<span>').css({
position: 'relative',
display: 'inline-block',
padding: 0
});
$(container + " input[type='number'][data-format=integer]").each(function() {
var $clone = $(this).clone();
var $parentLabel = $(this).parent('label');
if( $parentLabel.length !== 0 ) {
$parentLabel.css( 'display', 'inline-flex' );
$clone.css( 'order', 1 );
$(this).css( 'order', 2 );
}
$(this).wrapAll($wrapper).css({
position: 'absolute',
top: 0,
left: 0,
opacity: 0
})
.attr('pattern', '[0-9]*');
$clone.removeAttr('name class id pattern')
.attr('type', 'text')
.attr('tabindex', -1)
.css('width', $(this).width)
.val($(this).val() ? parseInt($(this).val()).toLocaleString() : '');
$(this).before($clone);
$(this).on('focus', function() {
$(this).css('opacity', '1');
});
$(this).on('blur', function() {
$(this).css('opacity', '0');
$clone.val($(this).val() ? parseInt($(this).val()).toLocaleString() : '');
});
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<label>Integer Input: <input type="number" data-format="integer" name="test" id="num_input" value="123456789" /></label><br>
<label for="num_input2">Integer Input: </label>
<input type="number" data-format="integer" name="test2" id="num_input2" value="10000000" /><br>
<label>Textarea <textarea>Something to focus other than the number fields</textarea></label>
</form>

jquery keeps on selecting element after changing the class

I have a button which must change what it does after meeting some condition.
So I'm selecting the button by it's class and I want to remove that class upon meeting the condition and add a new class to the element and do something else with it. but it's not working.
I just made up an example for my problem.
this is the code:
$('.button-1').click(function(){
$('.box').width(function(){
return $(this).width() + 10;
});
$(this).removeClass('button-1').addClass('button-2');
});
$('.button-2').click(function(){
$('.box').width(function(){
return $(this).width() - 10;
});
$(this).removeClass('button-2').addClass('button-1');
});
and it's Fiddle
I expect this to toggle between increasing and decreasing the black box width, but it keeps on increasing.
That's because the event is bound statically on the button, use event delegation like this:
$(document).on('click','.button-1', function(){
$('.box').width(function(){
return $(this).width() + 10;
});
$(this).removeClass('button-1').addClass('button-2');
});
$(document).on('click','.button-2', function(){
$('.box').width(function(){
return $(this).width() - 10;
});
$(this).removeClass('button-2').addClass('button-1');
});
DEMO
Offcourse you could do it like that...but isn't it easier to add an another variable that checks whether or not there has been a click? The code is much simpler and you can check later on whether or not the box has been enlarged.
This method also seperates style from computing, which is generally regarded as a good idea.
var large = false;
$('body').on('click', '.button', function(){
if (large) {
$('.box').addClass('clicked');
large = false;
} else {
$('.box').removeClass('clicked');
large = true;
}
});
additionally, you need a css class like so:
.clicked {
width: 110px;
}
and I removed that button-1 and button-2 classes, gave the div the class 'button' instead

jQuery using variables so one function performs multiple tasks

I'm a real noob and every time I've tried to implement any of these things it just stops working altogether...
I have 4 boxes on my page that should each expand and contract in the direction the little blue tabs are facing.
The thing I'd like to know, which I tried to implement but just have no idea about, was if there was a way I could input some variables so the same function could be performed by the other boxes but in different directions...
.exp1 needs to be replaced so a variable with value 1-4 goes in place of the number
eg/ .exp(variable value from 1 to 4)
Depending on which value .exp takes, the other classes variable numbers need to change further down in the code
eg/ .box3 would need to be .box(variable value from 1 to 4)
.miniBox3 would be .miniBox(variable value from 1 to 4)
and lastly .con1 would be .con(variable value from 1 to 4)
The values and properties in animate would also need to change
eg/ instead of being .animate({bottom... it could be .animate({left... with a new va;lue like 30px instead of 10px
In the expandFunction() the rules are:
if it's .exp1... then .box3 closes replaced by .miniBox3, .box1 expands and .exp1 is switched to .con1
if it's .exp2... then .box1 closes replaced by .miniBox1, .box2 expands and .exp2 is switched to .con2
if it's .exp3... then .box4 closes replaced by .miniBox4, .box3 expands and .exp3 is switched to .con3
if it's .exp4... then .box2 closes replaced by .miniBox2, .box4 expands and .exp4 is switched to .con4
In the contractFunction() the .box, .exp and .con numbers are all the same.
Here's the code:
$(document).ready(function () {
//function declared expand
$('.exp1').click(function(){
expandFunction();
});
});
//expand function properties
function expandFunction(){
if($(".box3").is(":visible"))
{
$('.box3').animate({left:'100%', top:'70px', width:'0px', height:'0px'},
"slow", function(){
$(this).switchClass("box3", "miniBox3", "slow");
$('.exp3').hide();$('.miniBox3').show("fast");//hide blue bar, show box in sidebar
$('.box1').animate({bottom:'10px'}, "slow", function(){ //opens box right
$('.exp1').unbind('click').removeClass('exp1').addClass('con1')
.click(function(){
contractFunction();
});
});
});
}
else
{
$('.box1').animate({bottom:'10px'}, "slow", function(){ //opens box right
$('.exp1').unbind('click').removeClass('exp1').addClass('con1')
.click(function(){
contractFunction();
});
});
}
}
//};
function contractFunction(){
$('.box1').animate({bottom:'46.5%'}, "slow", function(){
$('.box1 div').unbind('click').removeClass('con1').addClass('exp1').click(function(){
expandFunction();
});
});
}
Here's a fiddle
(My first problem was that the 1st box (top left) expands once, contracts once and then doesn't do anymore. It should continually expand and contract to infinity. SOLVED WITH IF ELSE STATEMENT)
Thank you very much in advance for any pointers and help you can give me.
i've updated your fiddle with just a few things.
i get rid of the div.miniBox, i thought they weren't necessary for achiving your needs.
i rewrited the css classes you used so i can perform the animations just adding and removing classNames and each box now has a unique id.
i added to the trigger divs a data- attribute (thanks html5) to store the id of the related box to hide/show, so i can retrive that value with ease with the jQuery.data() function.
here a sample of html
<div id="a1" class="box">
<div class="exp" data-related="a3"></div>
1
</div>
and here the code i used
$(function () {
$('.exp').click(function () {
var exp = $(this); //this is the clicked trigger
var parent = exp.parent(); //this is the parent box
var related = $('#' + exp.data('related')); //this is the related box
if (exp.is('.con')) { // check if the box is expanded
// i can do the same with parent.is('.maxi')
//expanded
parent.removeClass('maxi' /* shrink the box */,
'slow',
function () {
exp.removeClass('con'); //now i know the parent box is no more expanded
related.removeClass('mini', 'slow'); //restore the related box
});
} else {
//collapsed
related.addClass('mini' /* minimize the related box */,
'slow',
function () {
exp.addClass('con'); //this to know if parent is expanded
parent.addClass('maxi', 'slow'); //expand the parent box
});
}
});
});
you can check the full code in this fiddle
EDIT: so, to answer your question (how to do this with variables) i say you can use the state of your elements as variables themself.

How to resize text in a textbox if it is too large till a certain size

https://auth.me.com/authenticate
On this website when you type in your email address , the font-size will automatically be reduced if the email address fills the box size.
How can we do the same using Javascript?
which are the events that are being fired / captured ?
$("input").keypress(function(){
if(this.value.length>43)//or some other value
{//do stuff here
}
});
Keydown is what you are looking for
I have made a library, named resize.js, which allow to write:
<input type="text" resize="true" />
This is the library:
var precision=18;
window.onload=function()
{
for(var i=0,t=document.getElementsByTagName("input"),l=t.length;i<l;i++)if(t[i].getAttribute("resize")==="true")
{
var div=document.createElement("div");
div.setAttribute("style","font-size"+parseInt(t[i].s("font-size"))+";font-family:"+t[i].s("font-family")+";position:absolute;top:-10000px;left:-10000px;");
document.body.appendChild(div);
(function(i,div,min,max,dif,l,r,w,h,pre){setInterval(function(){modify(t[i],div,min,max,dif,l,r,w,h,pre);},100);})
(
i,
div,
t[i].getAttribute("min")||parseInt(t[i].s("font-size"))-3,
t[i].getAttribute("max")||parseInt(t[i].s("font-size")),
parseInt(t[i].s("padding-left"))+parseInt(t[i].s("padding-right"))+parseInt(t[i].s("border-left-width"))+parseInt(t[i].s("border-right-width"))+precision,
parseInt(t[i].s("padding-left")),
parseInt(t[i].s("padding-right")),
t[i].offsetWidth,
t[i].offsetHeight,
precision
);
}
}
Object.prototype.s=function(p)
{
return this.currentStyle?this.currentStyle[p]:document.defaultView.getComputedStyle(this,null).getPropertyValue(p);
}
function modify(el,c,min,max,dif,l,r,w,h,pre)
{
el.style.width=w+"px";
el.style.height=h+"px";
c.innerHTML=el.value.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/ /g,"&nbsp");
var test=c.offsetWidth;
while(test>=el.offsetWidth-dif&&parseInt(el.s("font-size"))>min)
{
el.style.fontSize=parseInt(el.s("font-size"))-1+"px";
c.style.fontSize=el.style.fontSize;
test=c.offsetWidth;
}
while(test<el.offsetWidth-dif&&parseInt(el.s("font-size"))<max)
{
el.style.fontSize=parseInt(el.s("font-size"))+1+"px";
c.style.fontSize=el.style.fontSize;
test=c.offsetWidth;
}
if(parseInt(el.s("font-size"))===min&&c.offsetWidth>el.offsetWidth-dif)
{
el.style.paddingLeft="0px";
el.style.paddingRight="0px";
}
else
{
el.style.paddingLeft=l+"px";
el.style.paddingRight=r+"px";
}
}
A fiddle: http://jsfiddle.net/mageek/GEp2y/1
Some advices:
If the attribute "resize" equals anything other than true, or is not set, the text-box will behave as a normal text-box.
You can set the maximum font-size and the minimum font-size allowed by setting the "max" and the "min" attributes. By default, the maximum is the current font-size and the minimum is 3 sizes smaller than the maximum.
I added something, like https://auth.me.com/authenticate, which removes the padding to gain space when the minimum font-size is reached.
There is the variable 'precision' (at the beginning of resize.js) that depends on the text-box, I set it to 18 for default text-box but if you modify the style of the text-box, you will maybe have to modify the variable to a better value (by testing).
I don't ensure the host of resize.js on the website like in the fiddle, you should copy the source code in a new file and save it.
I've made the code for you, I took for example what I did on my own website for the contact form: the <textarea> gets taller if there is lot's of text.
The thing to do is to create an invisible<div>, for each keydown in the <input>, take its content and puts it into the <div>, and check its width is bigger than the <input>'s one.
The HTML
<form>
<input>
<div></div>
</form>
​
The CSS where we set the same font-size for the <input> and the <div> and hide the <div> (with position: absolute because we need it's width and we don't want it to change the layout)
form > * {
font-size: 22px
}
form > input {
width: 150px;
font-size: 18px;
}
form > div {
position: absolute;
left: -10000px;
}​
And the JavaScript (with jQuery here)
var $form = $('form')
, $input = $('input', $form)
, $autoResize = $('div', $form)
, $both = $input.add($autoResize)
, fontSize = parseInt($input.css('font-size'), 10)
$input.on('keydown', function() {
$autoResize.html(this.value.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/ {2,}/g, function(spaces) {
// Change the spaces to $nbsp; except the last one
for (var i = 1, fakeSpaces = '', space; space = spaces[i++];) {
fakeSpaces += ' '
}
return fakeSpaces + ' '
})
)
// We add 10px to be sure it doesn't stick to the edges
if ($autoResize.outerWidth() >= $input.outerWidth() - 10) {
do {
$both.css('font-size', --fontSize)
} while ($autoResize.outerWidth() >= $input.outerWidth() && fontSize > 10)
// 10px is the smallest font-size accepted
if (fontSize === 10) {
$input.off('keydown')
}
}
})​
Here is the jsFiddle.
You must use JavaScript to count how much characters've been typed already (I believe with .change() in jQuery) and change the font-size accordingly.
Yes,I think what #somebody is in trouble is doing is what they are doing in here.
Calculate how many letters will fit into the box - you know the width of the textbox. You know the font-size & padding that is being given here. So you know how many letters can be typed in the textbox before it overflows( not exactly) .
Or you can just type random letters & see how many can fit ! :)
Well, if you have time, you can as well dive into the events being fired when you keydown on the email address text box. You will learn a lot!

jquery click .addClass issue

Hi i have been having trouble all day with this, it almost works but not quite, i need the corresponding p (#p-1 etc) to stay highlighted once the thumb nail is clicked. I have used a Plug in for an image slider which i have customized slightly and the mouseover and mouseleave events are working fine but the click event doesn't appear to add the class to the target paragraph.
Example on jsfiddle http://jsfiddle.net/RVYnb/7/
The relevant jQuery is written inline on the example.
this is driving me crazy, please help!
The error is in the image slider plugin. It also binds to the click event in the code.
Here's the relevant code part in the plugin:
jQuery("div#thumbSlider" + j + " a").each(function(z) {
jQuery(this).bind("click", function(){
jQuery(this).find("p.tmbrdr").css({borderColor: settings.thumbsActiveBorderColor, opacity: settings.thumbsActiveBorderOpacity});
jQuery(this).parent().parent().find("p.tmbrdr").not(jQuery(this).find("p.tmbrdr")).css({borderColor: settings.thumbsBorderColor, opacity: settings.thumbsBorderOpacity});
var cnt = -(pictWidth*z);
(cnt != container.find("ul").css("left").replace(/px/, "")) ? container.find("span.typo").animate({"opacity": 0}, 250) : null ;
container.find("ul").animate({ left: cnt}, settings.easeTime, settings.easeFunc, function(){container.find("span.typo").animate({"opacity": settings.typoFullOpacity}, 250)});
return false;
});
});
The problem is the "return false" at the end. It stopps the propagation to other click events.
Change the code to the following:
Query(this).bind("click", function(e){
jQuery(this).find("p.tmbrdr").css({borderColor: settings.thumbsActiveBorderColor, opacity: settings.thumbsActiveBorderOpacity});
jQuery(this).parent().parent().find("p.tmbrdr").not(jQuery(this).find("p.tmbrdr")).css({borderColor: settings.thumbsBorderColor, opacity: settings.thumbsBorderOpacity});
var cnt = -(pictWidth*z);
(cnt != container.find("ul").css("left").replace(/px/, "")) ? container.find("span.typo").animate({"opacity": 0}, 250) : null ;
container.find("ul").animate({ left: cnt}, settings.easeTime, settings.easeFunc, function(){container.find("span.typo").animate({"opacity": settings.typoFullOpacity}, 250)});
e.preventDefault();
});
});
and it should work.
It looks to me, according to the "fiddle", that your "click" event isn't working on your thumbnails. It's never adding the "clicked" class to your .
I threw an "alert" into this:
$("#t1").live("click", function() {
alert('clicking');
$("#p-1").addClass("clicked").addClass("highlighted");
});
and the alert never popped.

Categories