source: sandbox/newExpressoMail/prototype/plugins/fgmenu/fg.menuPlugin.js @ 7168

Revision 7168, 23.3 KB checked in by gustavo, 12 years ago (diff)

Ticket #2939 - Melhorias na exibicao das abas e da listagem de email

  • Property svn:executable set to *
Line 
1/*--------------------------------------------------------------------
2Scripts for creating and manipulating custom menus based on standard <ul> markup
3Version: 3.0, 03.31.2009
4
5By: Maggie Costello Wachs (maggie@filamentgroup.com) and Scott Jehl (scott@filamentgroup.com)
6        http://www.filamentgroup.com
7        * reference articles: http://www.filamentgroup.com/lab/jquery_ipod_style_drilldown_menu/
8               
9Copyright (c) 2009 Filament Group
10Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
11--------------------------------------------------------------------*/
12
13
14var allUIMenus = [];
15
16$.fn.menuPlugin = function(options){
17        var caller = this;
18        var options = options;
19        var m = new Menu(caller, options);     
20        allUIMenus.push(m);
21       
22        $(this)
23        .mousedown(function(){
24                if (!m.menuOpen) { m.showLoading(); };
25        })     
26        .click(function(){
27                if (m.menuOpen == false) { m.showMenu(); }
28                else { m.kill(); };
29                return false;
30        });     
31};
32
33function Menu(caller, options){
34        var menu = this;
35        var caller = $(caller);
36        var container = $('<div class="fg-menu-container ui-widget ui-widget-content ui-corner-all">'+options.content+'</div>');
37       
38        this.menuOpen = false;
39        this.menuExists = false;
40       
41        var options = jQuery.extend({
42                content: null,
43                width: 180, // width of menu container, must be set or passed in to calculate widths of child menus
44                maxHeight: 180, // max height of menu (if a drilldown: height does not include breadcrumb)
45                positionOpts: {
46                        posX: 'left',
47                        posY: 'bottom',
48                        offsetX: 0,
49                        offsetY: 0,
50                        directionH: 'right',
51                        directionV: 'down',
52                        detectH: true, // do horizontal collision detection 
53                        detectV: true, // do vertical collision detection
54                        linkToFront: false
55                },
56                showSpeed: 200, // show/hide speed in milliseconds
57                callerOnState: 'ui-state-active', // class to change the appearance of the link/button when the menu is showing
58                loadingState: 'ui-state-loading', // class added to the link/button while the menu is created
59                linkHover: 'ui-state-hover', // class for menu option hover state
60                linkHoverSecondary: 'li-hover', // alternate class, may be used for multi-level menus           
61        // ----- multi-level menu defaults -----
62                crossSpeed: 200, // cross-fade speed for multi-level menus
63                crumbDefaultText: 'Choose an option:',
64                backLink: true, // in the ipod-style menu: instead of breadcrumbs, show only a 'back' link
65                backLinkText: 'Back',
66                flyOut: false, // multi-level menus are ipod-style by default; this parameter overrides to make a flyout instead
67                flyOutOnState: 'ui-state-default',
68                nextMenuLink: 'ui-icon-triangle-1-e', // class to style the link (specifically, a span within the link) used in the multi-level menu to show the next level
69                topLinkText: 'All',
70                nextCrumbLink: 'ui-icon-carat-1-e'     
71        }, options);
72       
73        var killAllMenus = function(){
74                $.each(allUIMenus, function(i){
75                        if (allUIMenus[i].menuOpen) { allUIMenus[i].kill(); }; 
76                });
77        };
78       
79        this.kill = function(){
80                caller
81                        .removeClass(options.loadingState)
82                        .removeClass('fg-menu-open')
83                        .removeClass(options.callerOnState);   
84                container.find('li').removeClass(options.linkHoverSecondary).find('a').removeClass(options.linkHover);         
85                if (options.flyOutOnState) { container.find('li a').removeClass(options.flyOutOnState); };     
86                if (options.callerOnState) {    caller.removeClass(options.callerOnState); };                   
87                if (container.is('.fg-menu-ipod')) { menu.resetDrilldownMenu(); };
88                if (container.is('.fg-menu-flyout')) { menu.resetFlyoutMenu(); };       
89                container.parent().hide();     
90                menu.menuOpen = false;
91                $(document).unbind('click', killAllMenus);
92                $(document).unbind('keydown');
93        };
94       
95        this.showLoading = function(){
96                caller.addClass(options.loadingState);
97        };
98
99        this.showMenu = function(){
100                killAllMenus();
101                if (!menu.menuExists) { menu.create() };
102                caller
103                        .addClass('fg-menu-open')
104                        .addClass(options.callerOnState);
105                container.parent().show().click(function(){ menu.kill(); return false; });
106                container.hide().slideDown(options.showSpeed).find('.fg-menu:eq(0)');
107                menu.menuOpen = true;
108                caller.removeClass(options.loadingState);
109                $(document).click(killAllMenus);
110               
111                // assign key events
112                $(document).keydown(function(event){
113                        var e;
114                        if (event.which !="") { e = event.which; }
115                        else if (event.charCode != "") { e = event.charCode; }
116                        else if (event.keyCode != "") { e = event.keyCode; }
117                       
118                        var menuType = ($(event.target).parents('div').is('.fg-menu-flyout')) ? 'flyout' : 'ipod' ;
119                       
120                        switch(e) {
121                                case 37: // left arrow
122                                        if (menuType == 'flyout') {
123                                                $(event.target).trigger('mouseout');
124                                                if ($('.'+options.flyOutOnState).size() > 0) { $('.'+options.flyOutOnState).trigger('mouseover'); };
125                                        };
126                                       
127                                        if (menuType == 'ipod') {
128                                                $(event.target).trigger('mouseout');
129                                                if ($('.fg-menu-footer').find('a').size() > 0) { $('.fg-menu-footer').find('a').trigger('click'); };
130                                                if ($('.fg-menu-header').find('a').size() > 0) { $('.fg-menu-current-crumb').prev().find('a').trigger('click'); };
131                                                if ($('.fg-menu-current').prev().is('.fg-menu-indicator')) {
132                                                        $('.fg-menu-current').prev().trigger('mouseover');                                                     
133                                                };                                             
134                                        };
135                                        return false;
136                                        break;
137                                       
138                                case 38: // up arrow
139                                        if ($(event.target).is('.' + options.linkHover)) {     
140                                                var prevLink = $(event.target).parent().prev().find('a:eq(0)');                                         
141                                                if (prevLink.size() > 0) {
142                                                        $(event.target).trigger('mouseout');
143                                                        prevLink.trigger('mouseover');
144                                                };                                             
145                                        }
146                                        else { container.find('a:eq(0)').trigger('mouseover'); }
147                                        return false;
148                                        break;
149                                       
150                                case 39: // right arrow
151                                        if ($(event.target).is('.fg-menu-indicator')) {                                         
152                                                if (menuType == 'flyout') {
153                                                        $(event.target).next().find('a:eq(0)').trigger('mouseover');
154                                                }
155                                                else if (menuType == 'ipod') {
156                                                        $(event.target).trigger('click');                                               
157                                                        setTimeout(function(){
158                                                                $(event.target).next().find('a:eq(0)').trigger('mouseover');
159                                                        }, options.crossSpeed);
160                                                };                             
161                                        };
162                                        return false;
163                                        break;
164                                       
165                                case 40: // down arrow
166                                        if ($(event.target).is('.' + options.linkHover)) {
167                                                var nextLink = $(event.target).parent().next().find('a:eq(0)');                                         
168                                                if (nextLink.size() > 0) {                                                     
169                                                        $(event.target).trigger('mouseout');
170                                                        nextLink.trigger('mouseover');
171                                                };                             
172                                        }
173                                        else { container.find('a:eq(0)').trigger('mouseover'); }               
174                                        return false;                                           
175                                        break;
176                                       
177                                case 27: // escape
178                                        killAllMenus();
179                                        break;
180                                       
181                                case 13: // enter
182                                        if ($(event.target).is('.fg-menu-indicator') && menuType == 'ipod') {                                                   
183                                                $(event.target).trigger('click');                                               
184                                                setTimeout(function(){
185                                                        $(event.target).next().find('a:eq(0)').trigger('mouseover');
186                                                }, options.crossSpeed);                                 
187                                        };
188                                        break;
189                        };                     
190                });
191        };
192       
193        this.create = function(){       
194                container.css({ width: options.width }).appendTo('body').find('ul:first').not('.fg-menu-breadcrumb').addClass('fg-menu');
195                container.find('ul, li a').addClass('ui-corner-all');
196               
197                // aria roles & attributes
198                container.find('ul').attr('role', 'menu').eq(0).attr('aria-activedescendant','active-menuitem').attr('aria-labelledby', caller.attr('id'));
199                container.find('li').attr('role', 'menuitem');
200                container.find('li:has(ul)').attr('aria-haspopup', 'true').find('ul').attr('aria-expanded', 'false');
201                container.find('a').attr('tabindex', '-1');
202               
203                // when there are multiple levels of hierarchy, create flyout or drilldown menu
204                if (container.find('ul').size() > 1) {
205                        if (options.flyOut) { menu.flyout(container, options); }
206                        else { menu.drilldown(container, options); }   
207                }
208                else {
209                        container.find('a').click(function(){
210                                menu.chooseItem(this);
211                                return false;
212                        });
213                };     
214               
215                if (options.linkHover) {
216                        var allLinks = container.find('.fg-menu li a');
217                        allLinks.hover(
218                                function(){
219                                        var menuitem = $(this);
220                                        $('.'+options.linkHover).removeClass(options.linkHover).blur().parent().removeAttr('id');
221                                        $(this).addClass(options.linkHover).focus().parent().attr('id','active-menuitem');
222                                },
223                                function(){
224                                        $(this).removeClass(options.linkHover).blur().parent().removeAttr('id');
225                                }
226                        );
227                };
228               
229                if (options.linkHoverSecondary) {
230                        container.find('.fg-menu li').hover(
231                                function(){
232                                        $(this).siblings('li').removeClass(options.linkHoverSecondary);
233                                        if (options.flyOutOnState) { $(this).siblings('li').find('a').removeClass(options.flyOutOnState); }
234                                        $(this).addClass(options.linkHoverSecondary);
235                                },
236                                function(){ $(this).removeClass(options.linkHoverSecondary); }
237                        );
238                };     
239               
240                menu.setPosition(container, caller, options);
241                menu.menuExists = true;
242        };
243       
244        this.chooseItem = function(item){
245                if ($(item).hasClass('menu-pass-through')) {
246                        return true;
247                } else if ($(item).hasClass('menu-command')) {
248                       
249                        menu.kill();
250                        //alert($(item).attr('class'));
251                        // edit this for your own custom function/callback:
252                }
253                $('#menuSelection').text($(item).text());       
254                location.href = $(item).attr('href');
255               
256        };
257};
258
259Menu.prototype.flyout = function(container, options) {
260        var menu = this;
261       
262        this.resetFlyoutMenu = function(){
263                var allLists = container.find('ul ul');
264                allLists.removeClass('ui-widget-content').hide();       
265        };
266       
267        container.addClass('fg-menu-flyout').find('li:has(ul)').each(function(){
268                var linkWidth = container.width();
269                var showTimer, hideTimer;
270                var allSubLists = $(this).find('ul');           
271               
272                allSubLists.css({ left: linkWidth, width: linkWidth }).hide();
273                       
274                $(this).find('a:eq(0)').addClass('fg-menu-indicator').html('<span>' + $(this).find('a:eq(0)').text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>').hover(
275                        function(){
276                                clearTimeout(hideTimer);
277                                var subList = $(this).next();
278                                if (!fitVertical(subList, $(this).offset().top)) { subList.css({ top: 'auto', bottom: 0 }); };
279                                if (!fitHorizontal(subList, $(this).offset().left + 100)) { subList.css({ left: 'auto', right: linkWidth, 'z-index': 999 }); };
280                                showTimer = setTimeout(function(){
281                                        subList.addClass('ui-widget-content').show(options.showSpeed).attr('aria-expanded', 'true');   
282                                }, 300);       
283                        },
284                        function(){
285                                clearTimeout(showTimer);
286                                var subList = $(this).next();
287                                hideTimer = setTimeout(function(){
288                                        subList.removeClass('ui-widget-content').hide(options.showSpeed).attr('aria-expanded', 'false');
289                                }, 400);       
290                        }
291                );
292
293                $(this).find('ul a').hover(
294                        function(){
295                                clearTimeout(hideTimer);
296                                if ($(this).parents('ul').prev().is('a.fg-menu-indicator')) {
297                                        $(this).parents('ul').prev().addClass(options.flyOutOnState);
298                                }
299                        },
300                        function(){
301                                hideTimer = setTimeout(function(){
302                                        allSubLists.hide(options.showSpeed);
303                                        container.find(options.flyOutOnState).removeClass(options.flyOutOnState);
304                                }, 500);       
305                        }
306                );     
307        });
308       
309        container.find('a').click(function(){
310                menu.chooseItem(this);
311                return false;
312        });
313};
314
315
316Menu.prototype.drilldown = function(container, options) {
317        var menu = this;       
318        var topList = container.find('.fg-menu');       
319        var breadcrumb = $('<ul class="fg-menu-breadcrumb ui-widget-header ui-corner-all ui-helper-clearfix"></ul>');
320        var crumbDefaultHeader = $('<li class="fg-menu-breadcrumb-text">'+options.crumbDefaultText+'</li>');
321        var firstCrumbText = (options.backLink) ? options.backLinkText : options.topLinkText;
322        var firstCrumbClass = (options.backLink) ? 'fg-menu-prev-list' : 'fg-menu-all-lists';
323        var firstCrumbLinkClass = (options.backLink) ? 'ui-state-default ui-corner-all' : '';
324        var firstCrumbIcon = (options.backLink) ? '<span class="ui-icon ui-icon-triangle-1-w"></span>' : '';
325        var firstCrumb = $('<li class="'+firstCrumbClass+'"><a href="#" class="'+firstCrumbLinkClass+'">'+firstCrumbIcon+firstCrumbText+'</a></li>');
326       
327        container.addClass('fg-menu-ipod');
328       
329        if (options.backLink) { breadcrumb.addClass('fg-menu-footer').appendTo(container).hide(); }
330        else { breadcrumb.addClass('fg-menu-header').prependTo(container); };
331        breadcrumb.append(crumbDefaultHeader);
332       
333        var checkMenuHeight = function(el){
334                if (el.height() > options.maxHeight) { el.addClass('fg-menu-scroll') };
335                el.css({ height: options.maxHeight });
336        };
337       
338        var resetChildMenu = function(el){ el.removeClass('fg-menu-scroll').removeClass('fg-menu-current').height('auto'); };
339       
340        this.resetDrilldownMenu = function(){
341                $('.fg-menu-current').removeClass('fg-menu-current');
342                topList.animate({ left: 0 }, options.crossSpeed, function(){
343                        $(this).find('ul').each(function(){
344                                $(this).hide();
345                                resetChildMenu($(this));                               
346                        });
347                        topList.addClass('fg-menu-current');                   
348                });             
349                $('.fg-menu-all-lists').find('span').remove(); 
350                breadcrumb.empty().append(crumbDefaultHeader);         
351                $('.fg-menu-footer').empty().hide();   
352                checkMenuHeight(topList);               
353        };
354       
355        topList
356                .addClass('fg-menu-content fg-menu-current ui-widget-content ui-helper-clearfix')
357                .css({ width: container.width() })
358                .find('ul')
359                        .css({ width: container.width(), left: container.width() })
360                        .addClass('ui-widget-content')
361                        .hide();               
362        checkMenuHeight(topList);       
363       
364        topList.find('a').each(function(){
365                // if the link opens a child menu:
366                if ($(this).next().is('ul')) {
367                        $(this)
368                                .addClass('fg-menu-indicator')
369                                .each(function(){ $(this).html('<span>' + $(this).text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>'); })
370                                .click(function(){ // ----- show the next menu                 
371                                        var nextList = $(this).next();
372                                var parentUl = $(this).parents('ul:eq(0)');             
373                                var parentLeft = (parentUl.is('.fg-menu-content')) ? 0 : parseFloat(topList.css('left'));               
374                                var nextLeftVal = Math.round(parentLeft - parseFloat(container.width()));
375                                var footer = $('.fg-menu-footer');
376                               
377                                // show next menu               
378                                resetChildMenu(parentUl);
379                                checkMenuHeight(nextList);
380                                        topList.animate({ left: nextLeftVal }, options.crossSpeed);                                             
381                                nextList.show().addClass('fg-menu-current').attr('aria-expanded', 'true');   
382                               
383                                var setPrevMenu = function(backlink){
384                                        var b = backlink;
385                                        var c = $('.fg-menu-current');
386                                        var prevList = c.parents('ul:eq(0)');
387                                        c.hide().attr('aria-expanded', 'false');
388                                        resetChildMenu(c);
389                                        checkMenuHeight(prevList);
390                                        prevList.addClass('fg-menu-current').attr('aria-expanded', 'true');
391                                        if (prevList.hasClass('fg-menu-content')) { b.remove(); footer.hide(); };
392                                };             
393               
394                                        // initialize "back" link
395                                        if (options.backLink) {
396                                                if (footer.find('a').size() == 0) {
397                                                        footer.show();
398                                                        $('<a href="#"><span class="ui-icon ui-icon-triangle-1-w"></span> <span>Back</span></a>')
399                                                                .appendTo(footer)
400                                                                .click(function(){ // ----- show the previous menu
401                                                                        var b = $(this);
402                                                                var prevLeftVal = parseFloat(topList.css('left')) + container.width();                                                                         
403                                                                topList.animate({ left: prevLeftVal },  options.crossSpeed, function(){
404                                                                        setPrevMenu(b);
405                                                                });                     
406                                                                        return false;
407                                                                });
408                                                }
409                                        }
410                                        // or initialize top breadcrumb
411                                else {
412                                        if (breadcrumb.find('li').size() == 1){                         
413                                                        breadcrumb.empty().append(firstCrumb);
414                                                        firstCrumb.find('a').click(function(){
415                                                                menu.resetDrilldownMenu();
416                                                                return false;
417                                                        });
418                                                }
419                                                $('.fg-menu-current-crumb').removeClass('fg-menu-current-crumb');
420                                                var crumbText = $(this).find('span:eq(0)').text();
421                                                var newCrumb = $('<li class="fg-menu-current-crumb"><a href="javascript://" class="fg-menu-crumb">'+crumbText+'</a></li>');     
422                                                newCrumb
423                                                        .appendTo(breadcrumb)
424                                                        .find('a').click(function(){
425                                                                if ($(this).parent().is('.fg-menu-current-crumb')){
426                                                                        menu.chooseItem(this);
427                                                                }
428                                                                else {
429                                                                        var newLeftVal = - ($('.fg-menu-current').parents('ul').size() - 1) * 180;
430                                                                        topList.animate({ left: newLeftVal }, options.crossSpeed, function(){
431                                                                                setPrevMenu();
432                                                                        });
433                                                               
434                                                                        // make this the current crumb, delete all breadcrumbs after this one, and navigate to the relevant menu
435                                                                        $(this).parent().addClass('fg-menu-current-crumb').find('span').remove();
436                                                                        $(this).parent().nextAll().remove();                                                                   
437                                                                };
438                                                                return false;
439                                                        });
440                                                newCrumb.prev().append(' <span class="ui-icon '+options.nextCrumbLink+'"></span>');
441                                };                     
442                                return false;                   
443                        });
444                }
445                // if the link is a leaf node (doesn't open a child menu)
446                else {
447                        $(this).click(function(){
448                                menu.chooseItem(this);
449                                return false;
450                        });
451                };
452        });
453};
454
455
456/* Menu.prototype.setPosition parameters (defaults noted with *):
457        referrer = the link (or other element) used to show the overlaid object
458        settings = can override the defaults:
459                - posX/Y: where the top left corner of the object should be positioned in relation to its referrer.
460                                X: left*, center, right
461                                Y: top, center, bottom*
462                - offsetX/Y: the number of pixels to be offset from the x or y position.  Can be a positive or negative number.
463                - directionH/V: where the entire menu should appear in relation to its referrer.
464                                Horizontal: left*, right
465                                Vertical: up, down*
466                - detectH/V: detect the viewport horizontally / vertically
467                - linkToFront: copy the menu link and place it on top of the menu (visual effect to make it look like it overlaps the object) */
468
469Menu.prototype.setPosition = function(widget, caller, options) {
470        var el = widget;
471        var referrer = caller;
472        var dims = {
473                refX: referrer.offset().left,
474                refY: referrer.offset().top,
475                refW: referrer.getTotalWidth(),
476                refH: referrer.getTotalHeight()
477        };     
478        var options = options;
479        var xVal, yVal;
480       
481        var helper = $('<div class="positionHelper"></div>');
482        helper.css({ position: 'absolute', left: dims.refX, top: dims.refY, width: dims.refW, height: dims.refH });
483        el.wrap(helper);
484       
485        // get X pos
486        switch(options.positionOpts.posX) {
487                case 'left':    xVal = 0;
488                        break;                         
489                case 'center': xVal = dims.refW / 2;
490                        break;                         
491                case 'right': xVal = dims.refW;
492                        break;
493        };
494       
495        // get Y pos
496        switch(options.positionOpts.posY) {
497                case 'top':     yVal = 0;
498                        break;                         
499                case 'center': yVal = dims.refH / 2;
500                        break;                         
501                case 'bottom': yVal = dims.refH;
502                        break;
503        };
504       
505        // add the offsets (zero by default)
506        xVal += options.positionOpts.offsetX;
507        yVal += options.positionOpts.offsetY;
508       
509        // position the object vertically
510        if (options.positionOpts.directionV == 'up') {
511                el.css({ top: 'auto', bottom: yVal });
512                if (options.positionOpts.detectV && !fitVertical(el)) {
513                        el.css({ bottom: 'auto', top: yVal });
514                }
515        }
516        else {
517                el.css({ bottom: 'auto', top: yVal });
518                if (options.positionOpts.detectV && !fitVertical(el)) {
519                        el.css({ top: 'auto', bottom: yVal });
520                }
521        };
522       
523        // and horizontally
524        if (options.positionOpts.directionH == 'left') {
525                el.css({ left: 'auto', right: xVal });
526                if (options.positionOpts.detectH && !fitHorizontal(el)) {
527                        el.css({ right: 'auto', left: xVal });
528                }
529        }
530        else {
531                el.css({ right: 'auto', left: xVal });
532                if (options.positionOpts.detectH && !fitHorizontal(el)) {
533                        el.css({ left: 'auto', right: xVal });
534                }
535        };
536       
537        // if specified, clone the referring element and position it so that it appears on top of the menu
538        if (options.positionOpts.linkToFront) {
539                referrer.clone().addClass('linkClone').css({
540                        position: 'absolute',
541                        top: 0,
542                        right: 'auto',
543                        bottom: 'auto',
544                        left: 0,
545                        width: referrer.width(),
546                        height: referrer.height()
547                }).insertAfter(el);
548        };
549};
550
551
552/* Utilities to sort and find viewport dimensions */
553
554function sortBigToSmall(a, b) { return b - a; };
555
556jQuery.fn.getTotalWidth = function(){
557        return $(this).width() + parseInt($(this).css('paddingRight')) + parseInt($(this).css('paddingLeft')) + parseInt($(this).css('borderRightWidth')) + parseInt($(this).css('borderLeftWidth'));
558};
559
560jQuery.fn.getTotalHeight = function(){
561        return $(this).height() + parseInt($(this).css('paddingTop')) + parseInt($(this).css('paddingBottom')) + parseInt($(this).css('borderTopWidth')) + parseInt($(this).css('borderBottomWidth'));
562};
563
564function getScrollTop(){
565        return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
566};
567
568function getScrollLeft(){
569        return self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
570};
571
572function getWindowHeight(){
573        var de = document.documentElement;
574        return self.innerHeight || (de && de.clientHeight) || document.body.clientHeight;
575};
576
577function getWindowWidth(){
578        var de = document.documentElement;
579        return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
580};
581
582/* Utilities to test whether an element will fit in the viewport
583        Parameters:
584        el = element to position, required
585        leftOffset / topOffset = optional parameter if the offset cannot be calculated (i.e., if the object is in the DOM but is set to display: 'none') */
586       
587function fitHorizontal(el, leftOffset){
588        var leftVal = parseInt(leftOffset) || $(el).offset().left;
589        return (leftVal + $(el).width() <= getWindowWidth() + getScrollLeft() && leftVal - getScrollLeft() >= 0);
590};
591
592function fitVertical(el, topOffset){
593        var topVal = parseInt(topOffset) || $(el).offset().top;
594        return (topVal + $(el).height() <= getWindowHeight() + getScrollTop() && topVal - getScrollTop() >= 0);
595};
596
597/*--------------------------------------------------------------------
598 * javascript method: "pxToEm"
599 * by:
600   Scott Jehl (scott@filamentgroup.com)
601   Maggie Wachs (maggie@filamentgroup.com)
602   http://www.filamentgroup.com
603 *
604 * Copyright (c) 2008 Filament Group
605 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
606 *
607 * Description: Extends the native Number and String objects with pxToEm method. pxToEm converts a pixel value to ems depending on inherited font size. 
608 * Article: http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/
609 * Demo: http://www.filamentgroup.com/examples/pxToEm/         
610 *                                                     
611 * Options:                                                                     
612                scope: string or jQuery selector for font-size scoping
613                reverse: Boolean, true reverses the conversion to em-px
614 * Dependencies: jQuery library                                           
615 * Usage Example: myPixelValue.pxToEm(); or myPixelValue.pxToEm({'scope':'#navigation', reverse: true});
616 *
617 * Version: 2.0, 08.01.2008
618 * Changelog:
619 *              08.02.2007 initial Version 1.0
620 *              08.01.2008 - fixed font-size calculation for IE
621--------------------------------------------------------------------*/
622
623Number.prototype.pxToEm = String.prototype.pxToEm = function(settings){
624        //set defaults
625        settings = jQuery.extend({
626                scope: 'body',
627                reverse: false
628        }, settings);
629       
630        var pxVal = (this == '') ? 0 : parseFloat(this);
631        var scopeVal;
632        var getWindowWidth = function(){
633                var de = document.documentElement;
634                return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
635        };     
636       
637        /* When a percentage-based font-size is set on the body, IE returns that percent of the window width as the font-size.
638                For example, if the body font-size is 62.5% and the window width is 1000px, IE will return 625px as the font-size.     
639                When this happens, we calculate the correct body font-size (%) and multiply it by 16 (the standard browser font size)
640                to get an accurate em value. */
641                               
642        if (settings.scope == 'body' && $.browser.msie && (parseFloat($('body').css('font-size')) / getWindowWidth()).toFixed(1) > 0.0) {
643                var calcFontSize = function(){         
644                        return (parseFloat($('body').css('font-size'))/getWindowWidth()).toFixed(3) * 16;
645                };
646                scopeVal = calcFontSize();
647        }
648        else { scopeVal = parseFloat(jQuery(settings.scope).css("font-size")); };
649                       
650        var result = (settings.reverse == true) ? (pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em';
651        return result;
652};
Note: See TracBrowser for help on using the repository browser.