1

I'm developing a dynamic html pop-up window (an absolute positioned div) using jQuery that automatically centers itself on the screen. It can also accommodate content that fits or exceeds the dimensions of the window screen.

The idea is that our customer clicks a "read more" link next to our product listing and then this pop-up window comes up and displays its sales letter. Each sales letter also contains a video that further describes the product.

The pop-up window will remain at the center of the screen until it is dismissed by either clicking the close button in the window or clicking outside of it. It remains in the center by adjusting its absolute positioning based upon where the user scrolls and if they resize the window.

My problem is in the video element. In all other browsers except Firefox (of all things) the video is rendered perfectly within the pop-up window as the user scrolls around the document or resizes the video. However, in Firefox, when the user scrolls/resizes and the pop-up window adjusts its absolute positioning the video looks like it smudges from where it was originally to where it is now or the video screen goes transparent.

I thought maybe what needed to be done is force Firefox to redraw the video screen. I tried a few different ways to accomplish this. Simply making the element disappear and reappear quickly didn't seem to do the job. However, if I quickly adjusted its margins or position back and forth, it seemed to work.

At first, I was going to go with this solution. But then, as I began to test it across other browsers, this "wiggling" motion seemed to slow down the browser, specifically I noticed it in Chrome (I haven't tested it on the other browsers yet).

I thought about limiting this fix to Firefox, but the browser data field in jQuery was deprecated in 1.3. I could always make the javascript myself to identify the browser, but I was wondering if there was a better way to go about forcing the browser to redraw the video element. Or maybe I'm on the wrong track and it doesn't need to be redrawn.

I'm using FireFox 3.0.1, Chrome 1.0.154.48, Internet Explorer 7 and Safari 3.

Any input would be appreciated :) Here's the code for the wiggleVids function:

**Update: I changed the code so that way embeded elements are wiggled only when the popup box's position has changed, instead of binding it to the window scroll function. This has sped up chrome's execution a little, but its still not there quite yet. Its still a noticeable lag.

**Update 2: Following Lee's suggestion, I changed the code so that the embeded videos in the popup window are stored in an array. This way, when this function gets executed the browser won't have to search the DOM again and again for the embeded objects. myVids is globally declared and cleared when the popup closes.

function wiggleVids3() {
    if ( myVids.length <= 0 ) {
        $('#popup embed').each( function(ctr) { myVids[ctr] = $(this); } );
    }

    if ( myVids.length > 0 ) {
        for( var ctr = 0; ctr < myVids.length; ctr++ ) {
            var myObj = myVids[ctr];
            var temp = myObj.css("margin-top");
            var suffix =  temp.substr( temp.length - 2,temp.length );
            var currentMargin =  ( ( suffix == 'px' ) || ( suffix == 'em' ) ) ? parseInt( temp.substr( 0, temp.length - 2 ) ) : parseInt( temp );
            var newMargin = currentMargin + 2;
            myObj.css('margin-top', newMargin + 'px');
            setTimeout( function(){ myObj.css('margin-top', currentMargin ); }, 1 );
        }
    }
}
TJ Kirchner
  • 4,321
  • 6
  • 24
  • 26
  • Wouldn't this be more efficient if you stored $('#popup embed') in an array instead of retrieving it with jQuery three times? Just a thought... – leeand00 Mar 19 '09 at 18:12
  • Not sure I understand.. $('#popup embed').each() works like a for each loop. I only loop through once. – TJ Kirchner Mar 19 '09 at 18:16
  • Right but the $('#popup embed') is making a query on the DOM, another words it has too look through all of the DOM again to find all the elements from that query (well, that is unless @jeresig coded it so that it caches your search results...) I guess you could ask him, I don't know for sure. – leeand00 Mar 19 '09 at 18:25
  • $('#popup embed') does return an array though, so you should be able to do a .each on the array that it returns. – leeand00 Mar 19 '09 at 18:26
  • Oh! I think I see what your saying. Since this function is executing every time the popup window moves, this function makes the browser run through the DOM again. Better to store that result in an array the first time the popup loads and run the function on that. Actually I wrote the function^^() – TJ Kirchner Mar 19 '09 at 19:15

2 Answers2

1

Building on what @Adam said,

Use the Strategy Pattern combined with with a Factory Pattern to create the objects with a similar interface for generating the HTML, then you can create one for each browser that acts differently.

Oh, and the Factory does all of the browser detection...as well as sets up your object.

This question is relevant to my answer:

Community
  • 1
  • 1
leeand00
  • 25,510
  • 39
  • 140
  • 297
  • Wow, pretty deep. I think I understand though. Kinda like polymorphism. I think if I knew that the elements would act very differently depending on the browser types or diff environments (& I wasn't new to jQuery) I'd do something like that. For now, a browser class & if statement is probably enough – TJ Kirchner Mar 19 '09 at 18:46
  • @TJ Kirchner Yeah sure for now...but what about for later? – leeand00 Mar 19 '09 at 18:55
  • Lol. I want to... I'll try to :) Its hard, cus a lot of what I do @ work doesn't involve this much design and planning. (Sigh) I need a new job, lol. I'll try man, I'll try. – TJ Kirchner Mar 19 '09 at 19:08
0

Even though jquery doesn't support it, I think you're better off using different code for each browser, or only 'enabling' the special firefox code when a firefox browser is detected. Seems like it would solve your problem with little work.

-Adam

Adam Davis
  • 91,931
  • 60
  • 264
  • 330
  • Yea, that's what I thought too. I just wondered if there was a better way to do it, especially since jQuery.browser is deprecated in 1.3. I guess I may have no choice though – TJ Kirchner Mar 19 '09 at 18:17