Archive

Posts Tagged ‘cross browser’

Calculating the angle between two points on a circle

March 23, 2009 25 comments

I needed to calculate the angle between two points on the same circle. Don’t ask why, totally a new more complicated discussion.
So I had to remember a little trigonometry from the old days. Actually, this is done surprisingly easy, by simply using the atan2 method. Fortunately, this is available in JavaScript in the Math library.
In my problem, I had the center of the circle, one of the coordinates point(p1) and I had to find out the angle between the point (p0) at the 12-hour (imagine the circle as a clock) and the given one.

Angle between two points on a circle

Angle between two points on a circle


First of all the coordinates of the point at 12-hour is

p0(x,y) = (center.x, center.y - radius)

where radius is the circle radius and is calculated (according to Pythagorean theorem) as

radius = sqrt(|center.x - p1.x|<sup>2</sup> * |center.y - p1.y|<sup>2</sup>)

Now let’s calculate the angle:

angle = atan2(p1.y - p0.y, p1.x - p0.x)

This will return the angle in radians. If you want to translate it into the interval [0,2 π] then simply multiply by two. If you want to transform it to degrees use angle * 180 / π.
Below you have a JavaScript function that receives as arguments the coordinates of the center and second point and returns the angle in degrees in the interval (0°, 360°) between the 12-hour point and the second point

function angle(center, p1) {
    var p0 = {x: center.x, y: center.y - Math.sqrt(Math.abs(p1.x - center.x) * Math.abs(p1.x - center.x)
            + Math.abs(p1.y - center.y) * Math.abs(p1.y - center.y))};
    return (2 * Math.atan2(p1.y - p0.y, p1.x - p0.x)) * 180 / Math.PI;
}

I also wrote a small demo.

Later update:
As I had this question in the comments, in case you have the center coordinates, radius, angle and you want to calculate the second point coordinates, below is the JavaScript function. The first point is considered to be at 12’o clock.

function getPointAt(center, radius, angle) {
    // Please note that the angle is given in radians; 
    // if given in degrees uncomment the line below
    //angle *= Math.PI / 180;
    return {x: center.x + Math.sin(Math.PI - angle) * radius,
        y: center.y + Math.cos(Math.PI - angle) * radius};
}

All the coordinates are relative to the top left corner.

Advertisements
Categories: Software, Web Tags: , ,

Behavior helping cross browser transparency

February 16, 2009 1 comment

One of the things that I hate the most when developing DHTML applications is that I have to write code for at least 3 browsers. And nowadays the differences between them are not so big, but 5 years ago …
If you write some DHTML code you have to consider at least Firefox (>=2), Internet Explorer (>=6) and Safari. These are the most common web browsers. Google Chrome is gaining lately some popularity, but you can assimilate it with Firefox. Opera and other browsers have such a low percentage usage that you can safely ignore them.
Every time you will see some JavaScript code that shows you how to do some tricks, you will probably see a notice that is cross-browser. And if you dig deep inside the code, you will probably see lots of code that does nothing else but testing for the browser and then applying specific code for it.
It would be so nice if all the browsers will implement the standard(W3C) and only the standard. Then you will have an environment by default cross-browser.
A compromise are the existing cross-browser frameworks. But … you have to learn a new framework and you’re stuck with that framework, as your code will not work without it. And, if in the future browsers will become more and more compliant (it’s not a joke, IE8 seems to make small steps in that direction), you are still stuck with that framework.
Nice will be a framework that will ensure the cross-browser thingy in a transparent way.
Let’s be more practical. Some time ago I wrote an article about how you can make HTML elements transparent in a cross-browser way. But you actually had to write code for three browsers. Safari follows the standards here, Firefox >= 1.x as well (we can ignore FF 0.x – nobody is probably using it anymore). So I will focus on a workaround to help you write

element.style.opacity = 0.7;

and to have the desired result even in IE. Let’s admit, IE has always been the “rebel kid”, but also the most used.
The idea is simple. Every time I modify the “opacity” property of an element style in IE, I will run some code to do the necessary translation and ensure the cross-browser in a transparent way.
Now, for this we will use behaviors, an IE specific feature. Which in this case is good, as the code will be ignored by other browsers.
First of all attach a behavior, described in cb-opacity.htc, to all the elements, through CSS code (put it in a STYLE tag or a separate .css file):

* { behavior: url(cb-opacity.htc);}

.
And now the most interesting part – cb-opacity.htc

<PUBLIC:COMPONENT lightWeight="true"> 

<PUBLIC:ATTACH event="onpropertychange" handler="doOnPropertyChange"/>
<PUBLIC:ATTACH event="oncontentready" handler="doOnContentReady"/>

<SCRIPT>
function doOnContentReady() {
    // when this behavior is attached to an element, then check if the opacity was not already set
    // most likely through CSS code
    if (element.currentStyle.opacity != null) {
        element.style.filter = 'alpha(opacity=' + (element.currentStyle.opacity * 100) + ')';
    } else if (element.style.opacity != null) {
        element.style.filter = 'alpha(opacity=' + (element.style.opacity * 100) + ')';
    }    
}

function doOnPropertyChange() {
    // every time the style opacity is changed through JavaScript, then modify the CSS filter too
    if (window.event.propertyName == "style.opacity") {
        element.style.filter = 'alpha(opacity=' + (element.style.opacity * 100) + ')';
    }
}
</SCRIPT>
</PUBLIC:COMPONENT>

And now IE has support for style.opacity. Pretty nice, isn’t it?

Later edit: The same can be applied to cssFloat and styleFloat.

Categories: Web Tags: , ,

!u@#!^$ “Invalid character” IE error

January 28, 2009 15 comments

Internet Explorer is probably the worst browser for web development. Or maybe I’m too used to Firefox.
Let me give you just a simple example, that can drive you mad.
Have you ever encountered the below error?

Line: 2
Char: 1
Error: Invalid character
Code: 0
URL: ... 

I did. So I googled a little bit to see what could be the problem and I come over this article. Of course, that wasn’t the problem. Finally, I realized myself: one of the referenced JavaScript files was missing.

I know that this is my mistake, but I’m totally amazed about the usefulness of the IE error messages. It is a missing file, not an invalid character.
Not to mention, that the URL is always the main one, even though the error occurred in one of the referenced JavaScript files and the line reported is not the actual line where the error occurred, but increased by 1. But this is already common knowledge.

That’s one of the reasons I always use Firefox for web development, try to stick to the standards and only in the end, test the solution on Internet Explorer too. And there is no decent JavaScript debugger for IE. And …

I also wrote a small HTML, for you to see what I’m talking about.

Later update: This was tested on IE6. In IE8 works as expected.

Categories: Web Tags: , ,

Fixing IE: CSS fixed position

November 14, 2008 2 comments

I will start a series of articles about how you can fix some IE bugs. We all agree that IE is very buggy, but instead of whining, let’s see what we can do about it. So I will present you the problem, the fix, explain the fix and how you can EASILY INTEGRATE it.

Before, I will explain you a few things that I will use in these fixes. There are few different things in IE when it comes to CSS.

If you prefix a CSS property with _, IE will still recognize it. If you think this can be very useful. You can specify values for CSS properties only for IE. Let’s take an example.

color: green;
_color: red;

The font color will be green in all the browsers, except IE, where it will be red.
Instead of _, you can also use *, + and some other special signs.

The CSS value supports in IE a special value: expression([expr]). The [expr] is a JavaScript expression, which is evaluated and the CSS value is assigned to it. Again an example:

_height: expression((1 + 1) + 'px');

The CSS height in the above example is actually 2 pixels in IE. In the expression we can even use this to refer to the element for which the CSS value is applied.

Now let’s get back to the current issue. If you specify the fixed value for the position property, the element should be absolutely positioned, but relatively to the viewport, instead of the document. For more detailed info, please see the CSS specification. Not surprisingly, this works in most of the browsers, except IE.
And now, the fix. Which is actually very simple. We will use absolute positioning but we will calculate the coordinates dynamically relative to the viewport.
So the CSS code

position: fixed;
top: 10px;
left: 20px;

will have the following IE equivalent

_position: absolute;
_top: expression(((ignoreMe
= document.documentElement.scrollTop
? document.documentElement.scrollTop
: document.body.scrollTop ) + 10) + 'px' );
_left: expression(((ignoreMe
= document.documentElement.scrollLeft
? document.documentElement.scrollLeft
: document.body.scrollLeft ) + 20) + 'px' );

.
Don’t remove the ignoreMe variable as this will force the expression to be evaluated not only the first time the page is loaded, but always.

In the end, a live example. And if you complain that in Mozilla the things are smoother, then simply switch to Mozilla :).

Categories: Web Tags: , , ,

Web progress bar

September 16, 2008 4 comments

Would you like something like this in your web page?
web progress bar
Then I will show you how to do it.
The basic idea is pretty simple: implement it using 3 DIVs – one for the progress bar background, one for the completed part and one for the label (indicating the completed value or percent). They are stacked on top of each other in the specified order, from bottom to top.

We will have a main DIV, the actual progress bar, and inside it a completed one that will take as much space from its parent as the task is completed and a label to indicate that percentage.

On the main DIV we specify a border that will enclose the entire progress bar and a background that will indicate the remaining part. We also specify a different background on the completed DIV to indicate the completed part of the task. As for the label we specify only a font color and the background should remain transparent, so the label just sits on the progress bar.

Both children DIVs of the progress bar are floated to left and the label one has a negative margin to allow to be displayed at the same coordinates as the completed one.

  • HTML code

    <div id='progressbar' class='progressbar'>
        <div id='completed' class='completed'></div>
        <div id='label' class='label'>0%</div>
    </div>
    

  • CSS

    .progressbar {
        /* only for better layout :) */
        background-color: white;
        border: solid 1px black;
        width: 100px;
        height: 10px;
        font-family: arial;
        font-size: 10px;
    }
    
    .progressbar .completed {
        /* mandatory */
        width: 0%; 
        height: 100%; 
        z-index: 1; 
        float: left;
    
        /* only for better layout :) */
        background-color: navy;
    }
    
    .label {
        /* mandatory */
        width: 100%;
        height: 100%;
        z-index: 2;
        float: left;
    
        /* only for better layout :) */
        text-align: center;
        vertical-align: middle;
        color: yellow;
    }
    

    As you can see some of the CSS properties are mandatory for the component to render as a progress bar, as some of the properties are used only for a visually appealing layout.

  • JavaScript

    function setPercent(percent) {
        document.getElementById("label").innerHTML = percent + "%";
        document.getElementById("label").style.marginLeft = "-" + percent + "%";
        document.getElementById("completed").style.width = percent + "%";
    }
    

Next step will be to wrap all these into a nice component (JavaScript class). But this depends only on your architectural skills, as now you have the basic technique.

And in the end you can see a full working example, tested on IE6, FF3 and Safari 3. If you get rid of the hassle of implementing this yourself and you want a ready to use and easy to integrate progress bar component for your web pages you should see the MyUI JavaScript library. A demo is also available.

Just a side note, a throbber (or indeterminate progress bar) is easier to implement, that one being only a simple animated image.

Cross browser XMLHttpRequest

September 12, 2008 4 comments

AJAX has become more and more widely used. It is a cool thing, you can do a lot with it, but basically (and here is the best part) it is only a new JavaScript object: XMLHttpRequest. There is no need to learn new technologies or languages.
Unfortunately, not all the browsers (please read especially IE) support this in a native and smooth way. If in FF2+ and even IE7, this comes in a native way, in IE6 this comes only as an ActiveX object.
The good news is that, except how the objects are instantiated, everything else is the same.
As I said in FF/Mozilla this comes in a native smooth way


var xmlHttp = new XMLHttpRequest();

but in IE5 and 6, to create it, you actually create an ActiveX object


var xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");

And that’s not all, even the ActiveX object class can be different from Windows version to another, so you might also have:


xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");

So every time you want AJAX you might end up with something like this:

    var xmlHttp;
    // use the ActiveX control for IE5.x and IE6
    try {
        xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
    } catch (othermicrosoft){
        try { 
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        } 
        catch (native) {
            // If IE7, Mozilla, Safari, etc: Use native object
            xmlHttp = new XMLHttpRequest();
        } 
    } 

As I’m lazy and I don’t want to write this code every time, I decided to wrap it up in a nice cross browser way.

How? Look at the code below.

try {
    // test to see if XMLHttpRequest is defined
    XMLHttpRequest.DONE;
}
catch (e) {
    XMLHttpRequest = new Object();
    // define also all the constants
    XMLHttpRequest.UNSENT = 0;
    XMLHttpRequest.OPENED = 1;
    XMLHttpRequest.HEADERS_RECEIVED = 2;
    XMLHttpRequest.LOADING = 3;
    XMLHttpRequest.DONE = 4;
}

/** Creates new instance of the XMLHttpRequest object */
XMLHttpRequest.newInstance = function() {
    var xmlHttp = null;
    // use the ActiveX control for IE5.x and IE6
    try {
        xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
    } catch (othermicrosoft){
        try { 
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        } 
        catch (native) {
            // If IE7, Mozilla, Safari, etc: Use native object
            xmlHttp = new XMLHttpRequest();
        } 
    } 

    return xmlHttp;
};

Just to explain a little bit what happens. First we test if the XMLHttpRequest exists, by calling a property on it. If it doesn’t exist, then this will raise an exception and then we will create it. After this, the next step will be to define a method (similar to a static one) to create a new instance and enclose the entire cross browser code. So now we will create a new XMLHttpRequest like this:


var xmlHttp = XMLHttpRequest.newInstance();

Lazy enough for you !? 😉

Categories: Web Tags: , ,

Cross-browser custom CSS cursors

January 8, 2008 103 comments

I saw sometime ago the funny drawing below.
Time breakdown of modern web design

You can see that big portion is for making the design work in Internet Explorer.
First you laugh, but if you developed rich web sites/user interfaces you actually realize that this is only underevaluated. I would also extend it and say “make the design cross-browser”.

The tip that I’ll present you next it’s actually a small workaround and it will help you reduce that big pie slice.

Let’s say that you want to change the cursor for a page, for links or for some other specific elements. How? Using CSS. Then we should first go at W3C and read how to do it.
So the cursor property is the answer.
As good web developers we will separate the CSS from HTML and create the following structure

  /
  +-- cursor.html
  |-- cursor
      +-- cursor.css
      |-- cursor.cur    
  • cursor.html
    <html>
      <head>
        <link rel="stylesheet" type="text/css" href="cursor/cursor.css">
      </head>
      <body>
        Hello world!
        Look at me, I have a new cool cursor! 
      </body>
    </html>
    
  • cursor.css
    BODY {
        cursor: url(cursor.cur);
    }
    

Now everything should be set, so let’s give it a spin. Of course, we want everything to be cross-browser. For the sake of testing open cursor.html in Internet Explorer, Firefox and (for those Mac lovers) Safari. Surprise, the cursor is the default one in IE and Mozilla, but it’s the desired one in Safari. Frustrating isn’t it? You write W3C compliant code and it doesn’t work in the first two major browsers. The “best” part is that this is happening for different reasons.

Let’s first take care of Mozilla. Remember from CSS2 specification that cursor property holds a list of possible cursors and the browser should use the first found one or the default one if none is found.
Add to this list default and modify the cursor property from

cursor: url(cursor.cur);

to

cursor: url(cursor.cur),default;

And now refresh the page in Firefox. Even tough it doesn’t make sense at all, it will work and you will see your nice cursor.

And now IE comes next (as it still doesn’t work). As you noticed in cursor.css, we used for the cursor property relative URIs. To quote from there: For CSS style sheets, the base URI is that of the style sheet, not that of the source document. But if you modify the cursor property to

cursor: url(cursor/cursor.cur),default;

this will actually work. This is because in IE, for style sheets, the base URI is that of the source element, not that of the style sheet. Totally opposite to W3C specifications, but, yeah … that’s MSIE.

And if we want to still work in Firefox and Safari we have to keep the property value as below:

cursor: url(cursor.cur),url(cursor/cursor.cur),default;

. So everytime you want to define a crossbrowser CSS cursor you should define it as a list containing the url relative to the source element, the url relative to the style sheet and the default value.

The above examples were tested on IE 6.0.2900.2180, IE 7.0.5730, Firefox 2.0.0.11, Firefox 3.0.1, Safari 3.0.4, all under Windows XP SP2. I also tested in Opera 9.25, but it seems that it doesn’t support custom cursors.

Later edit – Jan 28, 2009:
The above examples were also tested under Firefox 3.0.5, Internet Explorer 8 beta 2 (inside IETester), Internet Explorer 8 RC1 (version 8.0.6001.18372CO), Safari 3.2.1 (525.27.1), Google Chrome 1.0.154.43 under Windows Vista.
I also tested with IE 5.5 (inside IETester), but it doesn’t support custom cursors.
There is also an example.

Later edit – Feb 10th, 2010:
If you want a custom cursor for an image (IMG) or link (A), then you need to attach the CSS to that tag, not to an enclosing container (e.g. DIV).