-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcontent.php
137 lines (98 loc) · 5.68 KB
/
content.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<header>
<h1>Server Side Mustard Cutting</h1>
<p>For simplicities sake, our mustard-cut here will be a measuring of the screen width. But it could test for <em>anything</em> client-side. We're also using PHP here because easy, but it could be any server side language.</p>
<p><a href="https://github.com/chriscoyier/server-side-mustard-cut">GitHub Repo</a></p>
</header>
<h2>The Problem</h2>
<ul>
<li>I want to make a distinction between large screens and small screens (just an example mustard cut).</li>
<li>I do not want to UA sniff to do this.</li>
<li>If I just needed some different CSS or JavaScript, I could cut the mustard in JavaScript and conditionally load <a href="https://github.com/filamentgroup/loadCSS">different</a> <a href="https://github.com/filamentgroup/loadJS">resources</a>.</li>
<li>It's too hard to load entirely different HTML, CSS, and JavaScript in one base document at one URL, purely client-side.</li>
<li>I want to serve a different document, server side, that has all the correct resources in it.</li>
<li>I want to make that server-side distinction with client-side mustard-cutting information.</li>
</ul>
<h2>Caveat</h2>
<p>I'm not saying this is the best possible solution. I am saying this seems reasonable to me and I'm using it in production.</p>
<p>This kind of thing has been <a href="https://github.com/jamesgpearce/modernizr-server">approached before</a>. These things aren't necessarily mutually exclusive.</p>
<h2>The Plan</h2>
<ul>
<li>Let's assume there is a cookie available that has all the client side information we want in it.</li>
<li>Server-side, we're all set, we'll use that cookie to serve the correct document. Yay!</li>
<li>If that cookie is <strong>not</strong> there and the browser <strong>does</strong> support cookies (tested at the very top of the document):
<ol>
<li>Mustard cut and save the data to a cookie with JavaScript</li>
<li>Halt the page from loading/doing anything else</li>
<li>Refresh the page</li>
<li>Upon refresh, the cookie will be there for the server</li>
</ol>
</li>
<li>If that cookie is not there and the browser <strong>does not</strong> support cookies (or they are turned off): assume one way or the other which document to load.</li>
<li>If the JavaScript doesn't run: assume one way or another which document to load.</li>
<li><strong>Important things</strong>: 1) under no circumstances should any browser go into a reload loop. 2) Even on a first-load, this should feel fast.</li>
</ul>
<h2>Possible Scenarios</h2>
<ul>
<li><strong>The normal first time visitor</strong>: No cookie is present. Mustard cut script will run and refresh quickly. They will get correct document based on cut.</li>
<li><strong>The repeat visitor</strong>: Cookie is already present. They will get correct document based on cut.</li>
<li><strong>Visitor with incorrect cookie</strong>: Perhaps they have a desktop browser but it was very narrow when the page loaded the first time, but they have since widened it. We can detect that with a CSS @media query and offer a link to correct the problem.</li>
<li><strong>Visitor with cookies off</strong>: We serve our choice of documents. Could potentially be wrong. Serve the best likely case based on data.</li>
<li><strong>Visitor in which JavaScript doesn't run</strong>: We serve our choice of documents. Could potentially be wrong. Serve the best likely case based on data.</li>
</ul>
<h2>The Code</h2>
<p>Server side:</p>
<pre><code><?php
<span>// This is just a FAKE ROUTER</span>
<span>// Do this however your site does routing</span>
if (isset($_COOKIE["screen-width"])) {
<span>// Large screen</span>
if ($_COOKIE["screen-width"] > 700) {
include_once("screen-large.php");
<span>// Small screen</span>
} else {
include_once("screen-small.php");
}
<span>// Choose a default</span>
} else {
include_once("screen-small.php");
}
?></code></pre>
<p>In the document that gets served, if the cookie isn't already present, run the mustard cutting script:</p>
<pre><code><?php
<span>// Run this script as high up the page as you can,
// but only if the cookie isn't already present.</span>
if (!isset($_COOKIE["screen-width"])) { ?>
<script src="mobile-mustard.js"></script>
<?php } ?></code></pre>
<p>The script is:</p>
<pre><code>(function() {
<span>// If the browser supports cookies and they are enabled</span>
if (navigator.cookieEnabled) {
<span>// Set the cookie for 3 days</span>
var date = new Date();
date.setTime(date.getTime() + (3 * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toGMTString();
<span>// This is where we're setting the mustard cutting information.
// In this case we're just setting screen width, but it could
// be anything. Think http://modernizr.com/</span>
document.cookie = "screen-width=" + screen.width + expires + "; path=/";
<span>/*
Only refresh if the WRONG template loads.
Since we're defaulting to a small screen,
and we know if this script is running the
cookie wasn't present on this page load,
we should refresh if the screen is wider
than 700.
This needs to be kept in sync with the server
side distinction
*/</span>
if (screen.width > 700) {
<span>// Halt the browser from loading/doing anything else.</span>
window.stop();
<span>// Reload the page, because the cookie will now be
// set and the server can use it.</span>
location.reload(true);
}
}
}());</code></pre>
<p class="final">୧༼ʘ̆ںʘ̆༽୨</p>