Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jquery - css "transform:scale" affects '.offset()' of jquery

I'm Trying To do Validation in jQuery.

It'll produce error after blur event occurs by checking whether the given input is empty. Based on that, it'll create a <div class="errdiv"> next to that input which will have the specific error. I use .offset to get the position of that specific input to position .errdiv there.

CSS:

.inpt {
    width:500px;
    height:50px;
    background:#eee;
    color:#444;
    border:2px solid #ddd;
    padding:5px;
    transition: all ease 1s;
    border-radius:5px;
    outline:none;
}
.inpt:focus {
    background:#fff;
    color:#222;
    border:2px solid #000;
}
.err {
    background:pink;
    border:2px solid #f00;
    color:#a00;
}
.errdiv {
    position:absolute;
    top:0px;
    left:0px;
    height:30px;
    display:inline-block;
    padding:5px;
    border-radius:5px;
    background:#a00;
    border:1px solid #a44;
    color:#fff;
    text-align:center;    
    font-weight:bolder;
    visibility:visible;
    opacity:0;
}

JS:

$(document).ready(function(){
    $(".inpt").blur(function(){
        // Check Input for validation.
        $(".errdiv").remove(); //Remove Any Previous Error.
        var vl=$(this).val();
        var vl1=vl.split(" ").join("");
        if(vl==""||vl1==""){
            // Input is Empty Mark It red.
            $(this).addClass("err");
        }
    });
    $(".inpt").focus(function(){
        //Check Whether Input is marked Red or Not (hasClass) err?
        $(".errdiv").remove(); //Remove Any Previous Error.
        if($(this).hasClass("err")){
        // Input is Marked!
        $(this).removeClass("err");
        var tp=$(this).offset().top+12;
        var lf=$(this).offset().left+$(this).width()+12;
         // Add Error Div and appropriate Message.
        $("body").append("<div class='errdiv' style='position:absolute;top:"+tp+"px;left:"+lf+"px;'>*This is Required.</div>");
        $(".errdiv").animate({
            "visibility":"visible",
            "opacity":"1"
        },1000); //Show What is The Error?
    });
});

HTML:

<center>Hello Every One!</center>
<hr>    
<center>
<input class="inpt" placeholder="name" type="text" /><br />
<input class="inpt" placeholder="email" type="text" /><br />
<input class="inpt" placeholder="password" type="password" /><br />
 </center>
 <center>
Just Try Focusing and Bluring the Inputs
</center>

And it works fine. You can test it here.

As you can see it creates error <div> and displays it as follows:

"Actual and Expected Output".


Actual Problem

The Problem occurs when I try to scale(zoom) my page for visually impaired peoples and/or for really big screen displays, using:

body{
    /*mozilla hack*/
    -moz-transform: scale(1.25,1.25);
    /* Chrome and Safari */
   -webkit-transform: scale(1.25,1.25);
    /*IE */
    -ms-transform:scale(1.25,1.25);
    /*Opera*/
    -o-transform:scale(1.25,1.25);
    /*Others*/
    transform:scale(1.25,1.25);
} 

Then I don't know what happens. But things go terribly wrong. the .offset() doesn't seems to work properly. You can see it Here.

The error div now gets positioned as: Error After Zoom


Can anyone please tell me how to position that .errdiv correctly even after scaling the page?

What I'm doing wrong?

Any suggestions or ideas are welcome. Hope you all will help me soon. Thanks in advance :).


PS:
transform-origin: 0 0;

didn't helped me. and I don't want to use <table><td> or write div previously in HTML I want to add it dynamically.

Edit For Bounty

The solution I've accepted Is okay for The validation part, But Now I'm trying to implement it with ajax, where the content will be dynamically added to the div, and I've to add transition:all ease 2.0s to body's css to make some stuff look amazing. But after adding trasition that affects the nature of transform which is altered by the solution accepted (transform also gets animated). and it doesn't solve the problem of positioning. So Is there any better way to satisfy the need? Can Anyone please provide a cross browser solution?

like image 579
Vedant Terkar Avatar asked Jun 02 '14 16:06

Vedant Terkar


2 Answers

your problem is that jquery is not returning the correct size of your element ($(this).width()).

try using getBoundingClientRect function (refer this) to get a rectangle object that encloses your element.

you can use it in your function in this way

var lf=$(this).offset().left+$(this)[0].getBoundingClientRect().width+12;

try this workaround

http://jsfiddle.net/H5sW9/10/

get current scale in matches[ 1] (scaleX) and matches[ 2] (scaleY)

var matrixRegex = /matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/;
var matches =$("body").css('transform').match(matrixRegex);

before append store the zoom to 100%

$("body").css('transform', 'scale(' + '1' + ')');

after you've added the div restore to 125%

 $("body").css('transform', 'scale(' + matches[1] + ')');

I have used only transform and not -webkit-transition,-moz-transform.... that you should use.

to scale for different factors x and y you should use

$("body").css('transform', 'scale(' + '1' +','  +'1' + ')');
like image 79
faby Avatar answered Oct 14 '22 07:10

faby


here is the working solution

CSS

.inpt:focus {
    background:#fff;
    color:#222;
    border:2px solid #000;
}
.err {
    background:pink;
    border:2px solid #f00;
    color:#a00;
}
.errdiv {
    position:absolute;    
    height:30px;
    display:inline-block;
    padding:5px;
    border-radius:5px;
    background:#a00;
    border:1px solid #a44;
    color:#fff;
    text-align:center;    
    font-weight:bolder;
    visibility:visible;
    opacity:0;
}

HTML

<center>Hello Every One!</center>
<hr>    
<center>
    <input class="inpt" placeholder="name" type="text" /><br />
    <input class="inpt" placeholder="email" type="text" /><br />
    <input class="inpt" placeholder="password" type="password" /><br />
</center>
<center>
    Just Try Focusing and Bluring the Inputs
</center>

JAVASCRIPT

$(document).ready(function() {
    $(".inpt").blur(function() {
        // Check Input for validation.
        $(".errdiv").remove(); //Remove Any Previous Error.
        var vl = $(this).val();
        var vl1 = vl.split(" ").join("");
        if (vl == "" || vl1 == "") {
            // Input is Empty Mark It red.
            $(this).addClass("err");
        }
    });
    $(".inpt").focus(function() {
        //Check Whether Input is marked Red or Not (hasClass) err?
        // $(".errdiv").remove(); //Remove Any Previous Error.
        if ($(this).hasClass("err")) {
            // Input is Marked!
            $(this).removeClass("err");
//            var tp=$(this).offset().top+12;// not needed 
//            var lf=$(this).offset().left+$(this).width()+12;// not needed
//             // Add Error Div and appropriate Message.
            $('<div class="errdiv">*This is Required.</div>').insertAfter(this);

            $(".errdiv").animate({
                "visibility": "visible",
                "opacity": "1"
            }, 1000); //Show What is The Error?
        }
    });
});

A bit of modification that is all

Remove top and left property from your .errdiv class and append the div dynamically after the element

like image 35
Deepak Kumar Avatar answered Oct 14 '22 05:10

Deepak Kumar