6
votes

I have a responsive site that has a simple drop-down login menu when the site is in a "desktop" view (screen available width > 768) next to other navigational links. When the screen width drops below 768 the navigational links end up in a select option. The problem is that the drop-down login menu doesn't work from within a select option.

I would like to use PHP to change the drop-down login menu to a simple <a href> link when the screen width gets smaller than 768.

Right now I have in my page <head>:

<?
$screenWidth = '<script type="text/javascript">document.write(screen.availWidth);</script>';
?>

In the <body>:

<?
if($screenWidth <= "768") {
echo '<li><a href="login.php">Log in</a></li>';
} else {
?>
<div id="fancy">
<li id="login">
<a id="login-trigger" href="#">Log in <span>&#x25BC;</span></a>
<div id="login-content">
    <form>
        <fieldset id="inputs">
            <input id="username" type="email" name="Email" placeholder="Your email address" required>   
            <input id="password" type="password" name="Password" placeholder="Password" required>
        </fieldset>
        <fieldset id="actions">
            <input type="submit" id="submit" value="Log in">
            <label><input type="checkbox" checked="checked"> Keep me signed in</label>
        </fieldset>
    </form>
</div>                     
</li>
<? } ?>

On my desktop, I have echoed the $screenWidth, which gives 1920. Therefore I would expect the "fancy" drop-down login menu to be displayed. (And it does).

On my mobile, the $screenWidth echo gives 320. I would then expect the <a href> link to be displayed. (It does not - instead it displays the "fancy" menu).

It seems odd that the variable when echoed in the body will give a different number, but when compared in the if statement it does not change the output.

Is there a better way of changing the output?

Edit: jquery responsive menu code

jquery.responsivemenu.js:

(function($) {
$.fn.responsiveMenu = function(options) {
    var defaults = {autoArrows: false}
    var options = $.extend(defaults, options);
    return this.each(function() {
        var $this = $(this);
        var $window = $(window);
        var setClass = function() {
            if ($window.width() > 768) {$this.addClass('dropdown').removeClass('accordion').find('li:has(ul)').removeClass('accorChild');}
            else {$this.addClass('accordion').find('li:has(ul)').addClass('accorChild').parent().removeClass('dropdown');}
        }
        $window.resize(function() {
            setClass();
            $this.find('ul').css('display', 'none');
        });
        setClass();
        $this
            .addClass('responsive-menu')
            .find('li.current a')
            .live('click', function(e) {
                var $a = $(this);
                var container = $a.next('ul,div');
                if ($this.hasClass('accordion') && container.length > 0) {
                    container.slideToggle();
                    return false;
                }
            })
            .stop()
            .siblings('ul').parent('li').addClass('hasChild');
        if (options.autoArrows) {
            $('.hasChild > a', $this)
            .find('strong').append('<span class="arrow">&nbsp;</span>');
        }
    });
}
})(jQuery);
5
Are you trying to say that $screenWidth = '<script type="text/javascript">document.write(screen.availWidth);</script>'; has actually worked for you, by assigning that variable a numeric value? - Mark
This is helpful, but it doesn't really explain why I can use PHP to <? echo $screenWidth; ?> and get a result with no problems, but can't compare the output <? if ($screenWidth <= "768") { //something } else { //something else } ?> - ScottD
@scd1982 Yes, the screen width appears, because the JavaScript gets parsed by your browser and is included in the document. As far as PHP is concerned, $screenWidth is of type string(72). PHP never sees the integer value, because by the time your browser sees the web page, PHP is done working - Mark
The reason your <? echo $screenWidth; ?> call is only showing the number, is because the browser isn't displaying the script blocks around it. Hence the string(72) (72 characters). This is why your comparison won't work. The $screenWidth variable is actually the entire script block string. - Barryrowe

5 Answers

5
votes

Your simplest option might be to populate both options in the DOM, then use CSS3 Media queries to hide/show the proper element based on screen size.

So your HTML might look like:

          <li class="login-link"><a href="login.php">Log in</a></li>
          <div id="fancy">
          <li id="login">
            <a id="login-trigger" href="#">Log in <span>&#x25BC;</span></a>
            <div id="login-content">
                <form>
                    <fieldset id="inputs">
                        <input id="username" type="email" name="Email" placeholder="Your email address" required>   
                        <input id="password" type="password" name="Password" placeholder="Password" required>
                    </fieldset>
                    <fieldset id="actions">
                        <input type="submit" id="submit" value="Log in">
                        <label><input type="checkbox" checked="checked"> Keep me signed in</label>
                    </fieldset>
                </form>
            </div>                     
        </li>

And your CSS could look like:

.login-link, #login{
    display: none;
}
@media screen and (max-width: 767px){
    .login-link {
         display: block;
    }
    #login{
         display: none;
    }
}
@media screen and (min-width: 768px) {
    #login{
         display: block;
    }
    .login-link{
         display: none;
    }
}

Edit: Fixed #login reference. Edit 2: Adding JSFiddle Example JSFiddle Example

5
votes

PHP is server side executed, this means that var screenWidth contains exactly: "document.write(screen.availWidth);" when you compare it. Your output is executed on client side..

3
votes

To make a responsive design, in the past, we'd use JavaScript. Since CCS3 you can use @media to respond to changes in the viewport.

Like:

@media screen and (max-width: 1280px) and (max-height: 1024px) {
    .splash {
        width: 100px;
    }
}
@media screen and (min-width: 1281px) and (max-width: 1920px) and (max-height: 960px) {
    .splash {
        width: 300px;
    }
}
1
votes

Some thoughts:

I don't think the PHP can interact directly with the desktop like that.

Best bet is to have the client send you the response via javascript. Do an immediate postback to the same page with the screen size variable included in the header, add it as a cookie and if the cookie exists then don't do the post back again.

So step 1: Check if cookie exists with value telling you the client's screen size. (or use session variables) if Yes, run with it. if no, have a javascript that sends you to the same page with a query string identifying the window size. Step 2: if no cookie exists and you have the query string indicating the window size, create the cookie and format accordingly.

0
votes

You could try

$userBrowserAtts = get_browser(null, true)

Returns a handy array of all sorts of information about the browser. But beware- this relies on the $_SERVER['HTTP_USER_AGENT'] and this can be spoofed. So this method isn't bullet proof. I don't know if it returns screen-width as such, but you should probably be able to find out if it's mobile, or if it's a tablet or desktop.

handy:

http://www.php.net/manual/en/function.get-browser.php

The best way to do this kind of thing is with the CSS3 media queries, but if the server really has to know about the browser, this is about the only thing you can do.