How can create a mask input for number that have percent by jQuery? Do I make input just accept until three numbers and put percent sign after numbers while user finished typing(keyup)?
I don't use plugins.
Example:
1% Or 30% Or 99% Or 100% Or 200%
<input name="number" class="num_percent">
You're better off not using JavaScript for this. Besides the problems that come with using onkeyup for detecting text input, you also have the hassle of parsing the resulting string back to a number in your client/server scripts. If you want the percent sign to look integrated, you could do something like this:
<div class="percentInput">
<input type="text" name="number" class="num_percent">
<span>%</span>
</div>
.percentInput { position:relative; }
.percentInput span { position: absolute; right: 4px; top:2px; }
.num_percent { text-align: right; padding-right: 12px; }
http://jsfiddle.net/BvVq4/
I'm rushing slightly, so you may have to tweak the styles to get it to look right cross-browser. At least it gives you the general idea.
I've stayed with input number, moved the percentage char and then modified its position according to the length of the input (the amount of digits).
HTML
<input type="number" min="0" max="100" value="100"> //chose 100 only for the sake of the example
<span class="percentage-char">%</span>
CSS
input {
width: 55px;
height: 20px;
font-size:18px;
}
.percentage-char {
position: absolute;
left: 32px; // default position - in this case 100
top: 1px;
font-size: 18px;
}
.one-digit { //position of the '%' when input is 0-9
left: 13px;
}
.two-digits{ //position of the '%' when input is 10-99
left: 24px;
}
JS
$(":input").change(function() { //listening to changes on input
if ($(this).val() < 10) { //adding and removing the classes
$('.percentage-char').removeClass('two-digits');
$('.percentage-char').addClass('one-digit');
} else if ($(this).val() > 9 && $(this).val() < 100) {
$('.percentage-char').addClass('two-digits');
} else {
$('.percentage-char').removeClass('one-digit two-digits');
}
});
Check out this fiddle
function setPercentageMask() {
let input = $('.percent');
input.mask('##0,00', {reverse: true});
input.bind("change keyup", function() {
isBetweenPercentage($(this));
});
}
function isBetweenPercentage(input) {
let myNumber = (input.val()) ? parseFloat(input.val()) : 0;
(myNumber.isBetween(0, 100.00)) ? myNumber : input.val('100,00');
}
if (typeof(Number.prototype.isBetween) === "undefined") {
Number.prototype.isBetween = function(min, max, notBoundaries) {
var between = false;
if (notBoundaries) {
if ((this < max) && (this > min)) between = true;
} else {
if ((this <= max) && (this >= min)) between = true;
}
return between;
}
}
setPercentageMask();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.16/jquery.mask.min.js" integrity="sha512-pHVGpX7F/27yZ0ISY+VVjyULApbDlD0/X0rgGbTqCE7WFW5MezNTWG/dnhtbBuICzsd0WQPgpE4REBLv+UqChw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<input name="text" class="percent">
Related
In the attached code, I have BTC to USD conversions working correctly, However, I am struggling to introduce a bilateral conversion from USD to BTC.
How can I have these two conversions working in parallel?
Thank you in advance for your efforts.
$("input[name='calc']").keyup(function(){
$.getJSON( "https://api.coindesk.com/v1/bpi/currentprice/usd.json",
function( data) {
var amountInBtc = parseFloat($("input[name='calc']").val());
//convert btc to usd
var exchangeRate = parseInt(data.bpi.USD.rate_float);
var amount = amountInBtc * exchangeRate;
$("input[name='rslt']").val(amount);
});
});
.calculator{
display:flex;
margin-top: 50px;
justify-content: center;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<!--------- Calculator----------------->
<div class="calculator">
<input type="number" name="calc" placeholder="BTC">
<div class="arrow" style="margin: 0 10px";>=</div>
<input type="number" name="rslt" placeholder="USD">
</div>
See below... simple approach is to use a class for both fields and call the onChange function on the class, and use variables for the field names instead of hard coding them inside your function. Also note that using toFixed(2) fixes 2 decimal points, which will be 0.00 for anything less than 0.01.
Everything else is self explanatory
$(".currencyField").keyup(function(){ //input[name='calc']
let convFrom;
if($(this).prop("name") == "btc") {
convFrom = "btc";
convTo = "usd";
}
else {
convFrom = "usd";
convTo = "btc";
}
$.getJSON( "https://api.coindesk.com/v1/bpi/currentprice/usd.json",
function( data) {
var origAmount = parseFloat($("input[name='" + convFrom + "']").val());
var exchangeRate = parseInt(data.bpi.USD.rate_float);
let amount;
if(convFrom == "btc")
amount = parseFloat(origAmount * exchangeRate);
else
amount = parseFloat(origAmount/ exchangeRate);
$("input[name='" + convTo + "']").val(amount.toFixed(2));
});
});
.calculator{
display:flex;
margin-top: 50px;
justify-content: center;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<!--------- Calculator----------------->
<div class="calculator">
<input type="number" name="btc" class="currencyField" placeholder="BTC">
<div class="arrow" style="margin: 0 10px";>=</div>
<input type="number" name="usd" class="currencyField" placeholder="USD">
</div>
<div class="range-wrap">
<input id="range" type="range" name="range" min="3" max="20" value="10" step="1">
<label id="rangevalue">10</label>
</div>
I to need to create range slider, where the values below 7 are labelled modest, 7 to 15 as moderate and anything above labelled as extensive. How I do add these labels to my range slide?
The idea will to be just simply get the value of existing slider and based on the value, do an if statement.
And to get the value when someone moves the slider, you can use oninput.
Try this:
First Answer Without The Partition
var slider = document.getElementById("range");
var display = document.getElementById("display");
var getVal = slider.value;
numVal.innerHTML = getVal; // If you don't want the number to be displayed, delete this. This is to show at which number the label will change
if(getVal<7) {
display.innerHTML = "Modest";
}
if(getVal>=7 && getVal<=15) {
display.innerHTML = "Moderate";
}
if(getVal>15){
display.innerHTML = "Extensive";
}
slider.oninput = function() {
numVal.innerHTML = this.value;// If you don't want the number to be displayed, delete this. This is to show at which number the label will change
var getVal = this.value;
if(getVal<7) {
display.innerHTML = "Modest";
}
if(getVal>=7 && getVal<=15) {
display.innerHTML = "Moderate";
}
if(getVal>15){
display.innerHTML = "Extensive";
}
}
<div class="range-wrap">
<input id="range" type="range" name="range" min="3" max="20" value="10" step="1">
<label id="display"></label>
<p id="numVal"></p> <!-- If you don't want the number to be displayed, delete this. This is to show at which number the label will change -->
</div>
ps: I've added comments in the code to hide the number if you don't want it. The numbers are there so you can see the change is happening at the right number. Delete the commented code accordingly to hide number values from displaying.
Updated Answer: (with partition)
You can use child elements to create a bar and push it on top of the slider using absolute and relative position. Its just a simple CSS trick.
The idea is to set a width for your range. Then, create 2 divs that looks like bars using border-right and then absolutely position it to your parent (which would be the range input)
Try this:
var slider = document.getElementById("range");
var display = document.getElementById("display");
var getVal = slider.value;
numVal.innerHTML = getVal; // If you don't want the number to be displayed, delete this. This is to show at which number the label will change
if(getVal<7) {
display.innerHTML = "Modest";
}
if(getVal>=7 && getVal<=15) {
display.innerHTML = "Moderate";
}
if(getVal>15){
display.innerHTML = "Extensive";
}
slider.oninput = function() {
numVal.innerHTML = this.value;// If you don't want the number to be displayed, delete this. This is to show at which number the label will change
var getVal = this.value;
if(getVal<7) {
display.innerHTML = "Modest";
}
if(getVal>=7 && getVal<=15) {
display.innerHTML = "Moderate";
}
if(getVal>15){
display.innerHTML = "Extensive";
}
}
#range-wrap {
position: relative;
}
input[type=range] {
width: 200px;
}
#range-bars {
width: 1px;
height: 10px;
border-right: 2px solid black;
position: absolute;
top: 13px;
left: 47px;
}
#range-bars-two {
width: 1px;
height: 10px;
border-right: 2px solid black;
position: absolute;
top: 13px;
left: 157px;
}
<div class="range-wrap">
<input id="range" type="range" name="range" min="3" max="20" value="10" step="1">
<label id="display"></label>
<p id="numVal"></p> <!-- If you don't want the number to be displayed, delete this. This is to show at which number the label will change -->
<div id="range-bars"></div>
<div id="range-bars-two"></div>
</div>
ps: there was a slight error in the if statement and I have made the changes to this answer plus the snippet 1 answer.
I have a page like below image
According to my requirement, user is allowed to enter digits from the keypad that is provided on the page only. So input field is readonly.
Now I am trying to get is, when user start entering month then other text should remain in text field until user types that. e.g. 05/DD/YYYY like this. And accordingly that text will be hide.
If I placed placeholder then when user starts entering digits all text gone. I don't want that. So I have taken "MM/DD/YYYY" text in seperate span tag.
var Memory = "0", // initialise memory variable
Current = "", // and value of Display ("current" value)
Operation = 0, // Records code for eg * / etc.
MAXLENGTH = 8; // maximum number of digits before decimal!
function format(input, format, sep) {
var output = "";
var idx = 0;
for (var i = 0; i < format.length && idx < input.length; i++) {
output += input.substr(idx, format[i]);
if (idx + format[i] < input.length) output += sep;
idx += format[i];
}
output += input.substr(idx);
return output;
}
function AddDigit(dig) { //ADD A DIGIT TO DISPLAY (keep as 'Current')
if (Current.indexOf("!") == -1) { //if not already an error
if ((eval(Current) == undefined) &&
(Current.indexOf(".") == -1)) {
Current = dig;
document.calc.display.focus();
} else {
Current = Current + dig;
document.calc.display.focus();
}
Current = Current.toLowerCase(); //FORCE LOWER CASE
} else {
Current = "Hint! Press 'Clear'"; //Help out, if error present.
}
if (Current.length > 0) {
Current = Current.replace(/\D/g, "");
Current = format(Current, [2, 2, 4], "/");
}
document.calc.display.value = Current.substring(0, 10);
document.getElementById("cursor").style.visibility = "hidden";
}
function Clear() { //CLEAR ENTRY
Current = "";
document.calc.display.value = Current;
document.calc.display.focus();
document.getElementById("cursor").style.visibility = "visible";
//setInterval ("cursorAnimation()", 5000);
}
function backspace() {
Current = document.calc.display.value;
var num = Current;
Current = num.slice(0,num.length - 1);
document.calc.display.value = Current;
document.calc.display.focus();
document.getElementById("cursor").style.visibility = "hidden";
}
function cursorAnimation() {
$("#cursor").animate({
opacity: 0
}, "fast", "swing").animate({
opacity: 1
}, "fast", "swing");
}
//--------------------------------------------------------------->
$(document).ready(function() {
document.getElementById("cursor").style.visibility = "visible";
//setInterval ("cursorAnimation()", 1000);
});
.intxt1 {
padding: 16px;
border-radius: 3px;
/* border: 0; */
width: 1017px;
border: 1px solid #000;
font-family: Droid Sans Mono;
background: #fff;
}
.txtplaceholder {
font-family: "Droid Sans Mono";
color: #D7D7D7;
position: relative;
float: left;
left: 219px;
top: 17px;
z-index: 10 !important;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: inline-block;
}
#cursor {
position: relative;
z-index: 1;
left: 32px;
top: 2px;
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<form Name="calc" method="post">
<div style="position:relative">
<span id="cursor">_</span>
<span class="txtplaceholder">MM/DD/YYYY</span>
<span style="z-index:100">
<input class="intxt1" autocomplete="off" id="pt_dob" name="display" value="" type="text" readonly>
</span>
<button class="cancel-icon" type="reset" onClick="Clear()"></button>
</div>
<div class="num_keypad1" style=" margin-top:19px;">
<!-- Screen and clear key -->
<div class="num_keys">
<!-- operators and other keys -->
<span id="key1" onClick="AddDigit('1')">1</span>
<span id="key2" onClick="AddDigit('2')">2</span>
<span id="key3" onClick="AddDigit('3')">3</span>
<span id="key4" onClick="AddDigit('4')">4</span>
<span id="key5" onClick="AddDigit('5')">5</span>
<span id="key6" onClick="AddDigit('6')">6</span>
<span id="key7" onClick="AddDigit('7')">7</span>
<span id="key8" onClick="AddDigit('8')">8</span>
<span id="key9" onClick="AddDigit('9')">9</span>
<span id="key0" onClick="AddDigit('0')" style="width: 200px;">0</span>
<span id="keyback" class="clear" onClick="backspace()"> <div class="num_xBox">X</div></span>
</div>
</div>
</form>
With the above Html code I am getting below result:
Problems coming are below:
My digits are going below the text "MM/DD/YYYY". I am not getting how should I get my digits above that text
How should I hide the text which is entered by user and display other accordingly e.g. "MM" should hide if user enters 05 and display other text like this "05/DD/YYYY".
Can anyone please help me in this?
NOTE: With input type=date or by any other plugins I can achieve above functionality but my requirement is different. I have to achieve this with HTML, CSS, JS only.
I would use a ready built data picker for this kind of thing as it would have all the error checking in built to ensure you enter a date in the correct format.
The way you are doing it, you are not able to check if the day is valid until you have entered the month, by which time the user will have to backspace and it will be a very slow and clunky process which is not very user friendly.
Anyway, if you persist with a number pad, here is how I would do it.
put the date in a global array
have a global index counter
add and remove values based on the index counter
The following is a very quick example of the above
var dateBits = ["D", "D", "M", "M", "Y", "Y", "Y", "Y"],
letters = ["D", "D", "M", "M", "Y", "Y", "Y", "Y"],
input = document.getElementById('pt_dob'),
currentIndex = 0;
function makeDate() {
return dateBits[0] + dateBits[1] + "/" + dateBits[2] + dateBits[3] + "/" + dateBits[4] + dateBits[5] + dateBits[6] + dateBits[7];
}
function AddDigit(number) {
dateBits[currentIndex] = number;
if (currentIndex < 8) {
currentIndex++;
}
input.value = makeDate();
}
function RemoveDigit() {
if (currentIndex > 0) {
currentIndex--;
}
dateBits[currentIndex] = letters[currentIndex];
input.value = makeDate();
}
function Clear() {
for (i = 0; i < letters.length; i++) {
dateBits[i] = letters[i];
}
currentIndex = 0;
input.value = makeDate();
}
input.value = makeDate(); // run this line onload or include this whole script at the bottom of the page to get your input to start with your text
.intxt1 {
padding: 16px;
border-radius: 3px;
/* border: 0; */
width: 1017px;
border: 1px solid #000;
font-family: Droid Sans Mono;
background: #fff;
}
#cursor {
position: relative;
z-index: 1;
left: 32px;
top: 2px;
visibility: hidden;
}
.num_keys > span {
display: inline-flex;
width: 2em;
height: 2em;
align-items: center;
justify-content: center;
cursor: pointer;
border: 1px solid black;
}
<form Name="calc" method="post">
<div style="position:relative"><span id="cursor">_</span>
<span class="txtplaceholder">MM/DD/YYYY</span><span style="z-index:100"><input class="intxt1" autocomplete="off" id="pt_dob" name="display" value="" type="text" autocomplete="off" readonly></span>
<button class="cancel-icon" type="reset" onClick="Clear(); return false;">clear</button>
</div>
<div class="num_keypad1" style=" margin-top:19px;">
<!-- Screen and clear key -->
<div class="num_keys">
<!-- operators and other keys -->
<span id="key1" onClick="AddDigit('1')">1</span>
<span id="key2" onClick="AddDigit('2')">2</span>
<span id="key3" onClick="AddDigit('3')">3</span>
<span id="key4" onClick="AddDigit('4')">4</span>
<span id="key5" onClick="AddDigit('5')">5</span>
<span id="key6" onClick="AddDigit('6')">6</span>
<span id="key7" onClick="AddDigit('7')">7</span>
<span id="key8" onClick="AddDigit('8')">8</span>
<span id="key9" onClick="AddDigit('9')">9</span>
<span id="key0" onClick="AddDigit('0')" style="width: 200px;">0</span>
<span id="keyback" class="clear" onClick="RemoveDigit()"> <div class="num_xBox">X</div></span>
</div>
</div>
</form>
var text = "DD/MM/YYYY";
$(".textbox").on("focus blur", function(){
$(".wrapper").toggleClass("focused");
});
$(".wrapper").click(function (e) {
if (e.target == this) {
var b = $(".textbox", this).focus();
}
}).trigger("click");
$(".wrapper > .textbox").on("input", function(){
var ipt = $(this).text().replace(/\u00A0/g, " ");
$(".gray").text(text.substr(ipt.length, text.length));
}).trigger("input");
check this fiddle http://jsfiddle.net/7sD2r/22/
If ive understood all well. I think the one solution is to store user input in hidden field. Then get this input to split digits and return to visible input value that consists of splitted values etc.
I have been looking around, googling here and there, how to properly code a very simplistic calculator. More specifically a Boolean calculator with set values. If I've lost you, bear with me I'll try to explain.
I have the need to use checkboxes to set a input.value. This value will be picked up elsewhere in a Web-Java applet; hence the need for input.value.
To save time and confusion I have built a small snippet using JS Fiddle, and realised I have no real idea how to work with Numbers in JS. Everything I have learned so far has been self taught using the web and various other sources.
I struggle in understanding efficient ways of writing logic, but can scrape by, by writing really simplistic logic. The more I write and ask questons the more I learn. So I've come here seeking some advice on how to minimize my given code snippet.
It's not robust, It's not elegant; but it's my route in.
function calculate() {
// set the variables
var a = document.getElementById('checkboxopt');
var b = document.getElementById('checkboxopt1');
var c = document.getElementById('pnvar');
var d = document.getElementById('adjvar');
var e = document.getElementById('adjvar2');
var i = 0;
var i2 = 0;
if (a.checked) {
console.log('Arg True')
i = i + 80;
d.value = i;
} else {
console.log('Arg False')
d.value = i;
}
if (b.checked) {
console.log('Arg True')
i2 = i2 + 30;
e.value = i2
} else {
console.log('Arg False')
e.value = i2;
}
console.log(i, i2);
c.value = i + i2;
};
var cbs = document.querySelectorAll('[type="checkbox"]');
[].forEach.call(cbs, function(cb) {
cb.addEventListener("click", function() {
console.log(this.id);
calculate();
});
});
calculate();
.editoropt {
font-family: Calibri, sans-serif;
width: 160px;
background: #f8f8ff;
padding: .5em;
border: solid 1px #ddd;
}
#checkboxopt {
float: left;
margin-right: 1em;
margin-top: 4px;
}
#checkboxopt1 {
float: left;
margin-right: 1em;
margin-top: 4px;
}
.pnvar {
width: 95%;
}
input:-moz-read-only {
/* For Firefox */
background-color: transparent;
border: none;
border-width: 0px;
}
input:read-only {
background-color: transparent;
border: none;
border-width: 0px;
}
<div class="seq-box-form-field editoropt ">
<label for="opt1"><span style="padding-right: 10px; vertical-align: 1px;">Default 80mm </span>
<input type="checkbox" name="checkboxopt" id="checkboxopt" value="true" checked />
<input type="hidden" name="opt1" id="opt1" value="true" />
</label>
</div>
<div class="seq-box-form-field editoropt ">
<label for="opt1"><span style="padding-right: 10px; vertical-align: 1px;">Add 30mm </span>
<input type="checkbox" name="checkboxopt1" id="checkboxopt1" value="true" />
<input type="hidden" name="opt2" id="opt2" value="true" />
</label>
</div>
<div class="editoropt">
<input class="pnvar" id="pnvar" name="pnvar" placeholder="Null" onkeydown="if (event.keyCode == 13) { event.preventDefault(); return false; }" value="" class="required" type="text">
<input name="adjvar" class="pnvar" id="adjvar" readonly value="0">
<input name="adjvar" class="pnvar" id="adjvar2" readonly value="0">
</div>
</div>
My Question
What would be the best way to simplify my given code, and improve it's performance. More Specifically, is there a more simplistic way of working with numbers within JS? Or am I on the right track with my current snippet?
If you are an experienced JS developer how would you tackle the desired result above?
A little detailed guidance is what I'm hoping for.
First, try to make code as reusable as possible. So,
if (a.checked) {
console.log('Arg True')
i = i + 80;
d.value = i;
} else {
console.log('Arg False')
d.value = i;
}
if (b.checked) {
console.log('Arg True')
i2 = i2 + 30;
e.value = i2
} else {
console.log('Arg False')
e.value = i2;
}
can be replaced as
function dummy(el, val) {
i2 += el.checked ? val : 0;
}
Second, do not have inline functions in HTML. It will dirty your HTML and make debug difficult. You should wrap all listeners in a wrapper function. This will enable you to even export all of them to separate file and you will know where to look.
Third, instead of hard coding value 80 or 30 in your code, make a map or bind it to element using data-attribute
Fourth and more Important one, use better variable names. a-e or i, i1, i2 are bad names. Only you will understand your code (till you are in context). Always use precise meaningful name. This will help in long run. I have even kept function names as long as 30+ chars just to define its purpose.
Also try to break your code in smaller functions. This will increase scope for reusing them.
You can refer updated code and ask any queries, if you have.
Hope it helps!
I have a problem that I want to detect if an element is covered by another one in one page.
eg:
DOM elements
<div class="ele ele1"><p>A</p></div>
<div class="ele ele2"><p>B</p></div>
<div class="ele ele3"><p>C</p></div>
<div class="cover"><p>D</p></div>
CSS style
.ele{
display: inline-block;
width: 100px;
height: 100px;
position: relative;
}
p{
width: 100%;
text-align: center;
}
.ele1{
background-color: red;
}
.ele2{
background-color: blue;
}
.ele3{
background-color: green;
}
.cover{
position: absolute;
width: 100px;
height: 100px;
left: 300px;
top: 10px;
background: grey;
}
http://jsfiddle.net/veraWei/6v89b1fy/
How to detect element A is not been covered but element C is covered by ele D?
One more thing: the number of "D" is uncertain. Maybe there are E/F/G... in the page.
I appreciate all the thoughts or existing examples/jQuery plugins/CSS/etc.
Thanks all your guys' detailed answers. But I need more shortly explanation maybe one attribute that indicate that A is not covered by any elements and C is covered by rendering. Is there any plugin or attribute existing?
Why not try the following :
1) Find the element position relative to the viewport:
rect=elt.getBoundingClientRect();
x=rect.left;
y=rect.top;
(or may be consider the midpoints coordinates)
2) Find the top element at position x, y:
topElt=document.elementFromPoint(x,y);
3) Check if the top element is the same than the original element :
if(elt.isSameNode(topElt)) console.log('no overlapping');
Are you looking for something like this?
http://jsfiddle.net/6v89b1fy/4/
var coverElem = $(".cover");
var elemArray = [];
elemArray.push($(".ele1"), $(".ele2"), $(".ele3"));
for(i=0; i< elemArray.length; i++)
{
var currElemOffset = elemArray[i].offset();
var currElemWidth = elemArray[i].width();
var currElemStPoint = currElemOffset.left ;
var currElemEndPoint = currElemStPoint + currElemWidth;
if(currElemStPoint <= coverElem.offset().left && coverElem.offset().left <= currElemEndPoint)
{
elemArray[i].append("<span>Covered</span>");
}
else
{
elemArray[i].append("<span>Not covered</span>");
}
}
Here is a quick example of how you may go about doing it. This would check for both vertical and horizontal overlapping. This is kind of generic and not-so-generic as well since this is based off the HTML in your question. Adjust the top/left values of the .cover to see it work for all possible cases.
var $cover = $(".cover"),
cWidth = $cover.width(),
cHeight = $cover.height(),
cLeft = $cover.offset().left,
cRight = $(window).width() - (cLeft + cWidth),
cTop = $cover.offset().top,
cBtm = $(window).height() - (cTop + cHeight);
$("div:not(.cover)").each(function() {
var $this = $(this),
eleWidth = $this.width(),
eleHeight = $this.height(),
eleLeft = $this.offset().left,
eleTop = $this.offset().top,
eleRight = $(window).width() - (eleLeft + eleWidth),
eleBtm = $(window).height() - (eleTop + eleHeight);
if (
cLeft < (eleLeft + eleWidth) &&
cRight < (eleRight + eleWidth) &&
cTop < (eleTop + eleHeight) &&
cBtm < (eleBtm + eleHeight)
) {
alert($this.text() + " is covered by " + $cover.text());
}
});
.ele {
display: inline-block;
width: 100px;
height: 100px;
position: relative;
margin-top: 40px;
}
p {
width: 100%;
text-align: center;
}
.ele1 {
background-color: red;
}
.ele2 {
background-color: blue;
}
.ele3 {
background-color: green;
}
.cover {
position: absolute;
width: 100px;
height: 100px;
left: 60px;
top: 110px;
background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ele ele1">
<p>A</p>
</div>
<div class="ele ele2">
<p>B</p>
</div>
<div class="ele ele3">
<p>C</p>
</div>
<div class="ele ele3">
<p>D</p>
</div>
<div class="ele ele3">
<p>E</p>
</div>
<div class="ele ele3">
<p>F</p>
</div>
<div class="ele ele3">
<p>G</p>
</div>
<div class="cover">
<p>COVER</p>
</div>
OK. I've gone through all cases of overlapping and have created this fiddle. I've used getBoundintClientRect() and have used it to get top, left, bottom, right values of two divs on which overlapping is to be checked and then I've compared the offsets using various conditional statements and conditions too which you'll find below. In the fiddle all your four elements are having position: absolute, adjust their top and left values to make them overlap one another and to check whether two elements are overlapping or not? pass the two elements in the function -
checkElements(elA, elB); // pass two elements to check
which is in the very last.
You will see the long if else conditions in the fiddle, they are just for testing all possibilities of overlapping. Here is that all possible conditions used to check overlapping -
if((eleB.top >= eleA.top && eleB.top <= eleA.bottom) || (eleB.bottom >= eleA.top && eleB.bottom <= eleA.bottom)) {
if((eleB.left >= eleA.left && eleB.left <= eleA.right) || (eleB.right >= eleA.left && eleB.right <= eleA.right)) {
el1.innerHTML = '<p>covered</p>';
}
else {
el1.innerHTML = '<p>not covered</p>';
}
}
else {
el1.innerHTML = '<p>not covered</p>';
}
You will also see if B overlaps A then it will write A is covered because I've compared using x and y coordinates of A and B. In this case, I think an additional condition checking z-index will be used. I've not created for that.
Check the fiddle, and adjust top and left values of different elements and then pass two elements in the function checkElements() and see the result is correct or not.
You can also do all the checking simultaneously as -
checkElements(elA, elB); // check if A is overlapped by B
checkElements(elB, elC); // check if B is overlapped by C
checkElements(elC, elD); // check if C is overlapped by D
See this fiddle using the multiple checking.
EDIT: If looping is the problem, then you can combine all the loops of if else into a single if else like this -
if(((eleB.top >= eleA.top && eleB.top <= eleA.bottom) || (eleB.bottom >= eleA.top && eleB.bottom <= eleA.bottom)) && ((eleB.left >= eleA.left && eleB.left <= eleA.right) || (eleB.right >= eleA.left && eleB.right <= eleA.right))) {
el1.innerHTML = '<p>covered</p>'; // or your code of adding true to the attribute that tells about overlapping
}
else {
el1.innerHTML = '<p>not covered</p>';
}
Updated fiddle