├── include ├── after_content.php ├── header.php └── before_content.php ├── css └── style.css ├── third_page.php ├── first_page.php ├── second_page.php └── js └── ajax_nav.js /include/after_content.php: -------------------------------------------------------------------------------- 1 |

This is the footer. It is shared between all ajax pages.

2 | -------------------------------------------------------------------------------- /include/header.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /include/before_content.php: -------------------------------------------------------------------------------- 1 |

2 | [ First example 3 | | Second example 4 | | Third example 5 | | Unexisting page ] 6 |

7 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | #ajax-loader { 2 | position: fixed; 3 | display: table; 4 | top: 0; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | } 9 | 10 | #ajax-loader > div { 11 | display: table-cell; 12 | width: 100%; 13 | height: 100%; 14 | vertical-align: middle; 15 | text-align: center; 16 | background-color: #000000; 17 | opacity: 0.65; 18 | } 19 | -------------------------------------------------------------------------------- /third_page.php: -------------------------------------------------------------------------------- 1 | This is the content of third_page.php. This content is stored into a php variable.

"; 4 | 5 | if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { 6 | echo json_encode(array("page" => $page_title, "content" => $page_content)); 7 | } else { 8 | ?> 9 | 10 | 11 | 12 | " . $page_title . ""; 15 | ?> 16 | 17 | 18 | 19 | 20 | 21 | 22 |

This paragraph is shown only when the navigation starts from third_page.php.

23 | 24 |
25 | 26 |
27 | 28 |

This paragraph is shown only when the navigation starts from third_page.php.

29 | 30 | \n"; 33 | } 34 | -------------------------------------------------------------------------------- /first_page.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | " . $page_title . ""; 16 | ?> 17 | 18 | 19 | 20 | 21 | 22 | 23 |

This paragraph is shown only when the navigation starts from first_page.php.

24 | 25 |
26 | 27 | 28 |

This is the content of first_page.php.

29 | 30 | $page_title, "content" => ob_get_clean())); 33 | } else { 34 | ?> 35 |
36 | 37 |

This paragraph is shown only when the navigation starts from first_page.php.

38 | 39 | \n"; 42 | } 43 | -------------------------------------------------------------------------------- /second_page.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | " . $page_title . ""; 16 | ?> 17 | 18 | 19 | 20 | 21 | 22 | 23 |

This paragraph is shown only when the navigation starts from second_page.php.

24 | 25 |
26 | 27 | 28 |

This is the content of second_page.php.

29 | 30 | $page_title, "content" => ob_get_clean())); 33 | } else { 34 | ?> 35 |
36 | 37 |

This paragraph is shown only when the navigation starts from second_page.php.

38 | 39 | \n"; 42 | } 43 | -------------------------------------------------------------------------------- /js/ajax_nav.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const ajaxRequest = new (function () { 4 | 5 | function closeReq () { 6 | oLoadingBox.parentNode && document.body.removeChild(oLoadingBox); 7 | bIsLoading = false; 8 | } 9 | 10 | function abortReq () { 11 | if (!bIsLoading) { return; } 12 | oReq.abort(); 13 | closeReq(); 14 | } 15 | 16 | function ajaxError () { 17 | alert("Unknown error."); 18 | } 19 | 20 | function ajaxLoad () { 21 | var vMsg, nStatus = this.status; 22 | switch (nStatus) { 23 | case 200: 24 | vMsg = JSON.parse(this.responseText); 25 | document.title = oPageInfo.title = vMsg.page; 26 | document.getElementById(sTargetId).innerHTML = vMsg.content; 27 | if (bUpdateURL) { 28 | history.pushState(oPageInfo, oPageInfo.title, oPageInfo.url); 29 | bUpdateURL = false; 30 | } 31 | break; 32 | default: 33 | vMsg = nStatus + ": " + (oHTTPStatus[nStatus] || "Unknown"); 34 | switch (Math.floor(nStatus / 100)) { 35 | /* 36 | case 1: 37 | // Informational 1xx 38 | console.log("Information code " + vMsg); 39 | break; 40 | case 2: 41 | // Successful 2xx 42 | console.log("Successful code " + vMsg); 43 | break; 44 | case 3: 45 | // Redirection 3xx 46 | console.log("Redirection code " + vMsg); 47 | break; 48 | */ 49 | case 4: 50 | /* Client Error 4xx */ 51 | alert("Client Error #" + vMsg); 52 | break; 53 | case 5: 54 | /* Server Error 5xx */ 55 | alert("Server Error #" + vMsg); 56 | break; 57 | default: 58 | /* Unknown status */ 59 | ajaxError(); 60 | } 61 | } 62 | closeReq(); 63 | } 64 | 65 | function filterURL (sURL, sViewMode) { 66 | return sURL.replace(rSearch, "") + ("?" + sURL.replace(rHost, "&").replace(rView, sViewMode ? "&" + sViewKey + "=" + sViewMode : "").slice(1)).replace(rEndQstMark, ""); 67 | } 68 | 69 | function getPage (sPage) { 70 | if (bIsLoading) { return; } 71 | oReq = new XMLHttpRequest(); 72 | bIsLoading = true; 73 | oReq.onload = ajaxLoad; 74 | oReq.onerror = ajaxError; 75 | if (sPage) { oPageInfo.url = filterURL(sPage, null); } 76 | oReq.open("get", filterURL(oPageInfo.url, "json"), true); 77 | oReq.send(); 78 | oLoadingBox.parentNode || document.body.appendChild(oLoadingBox); 79 | } 80 | 81 | function requestPage (sURL) { 82 | if (history.pushState) { 83 | bUpdateURL = true; 84 | getPage(sURL); 85 | } else { 86 | /* Ajax navigation is not supported */ 87 | location.assign(sURL); 88 | } 89 | } 90 | 91 | function processLink () { 92 | if (this.className === sAjaxClass) { 93 | requestPage(this.href); 94 | return false; 95 | } 96 | return true; 97 | } 98 | 99 | function init () { 100 | oPageInfo.title = document.title; 101 | for (var oLink, nIdx = 0, nLen = document.links.length; nIdx < nLen; document.links[nIdx++].onclick = processLink); 102 | } 103 | 104 | const 105 | 106 | /* customizable constants */ 107 | sTargetId = "ajax-content", sViewKey = "view_as", sAjaxClass = "ajax-nav", 108 | 109 | /* not customizable constants */ 110 | rSearch = /\?.*$/, rHost = /^[^\?]*\?*&*/, rView = new RegExp("&" + sViewKey + "\\=[^&]*|&*$", "i"), rEndQstMark = /\?$/, 111 | oLoadingBox = document.createElement("div"), oCover = document.createElement("div"), oLoadingImg = new Image(), 112 | oPageInfo = { 113 | title: null, 114 | url: location.href 115 | }, oHTTPStatus = /* http://www.iana.org/assignments/http-status-codes/http-status-codes.xml */ { 116 | 100: "Continue", 117 | 101: "Switching Protocols", 118 | 102: "Processing", 119 | 200: "OK", 120 | 201: "Created", 121 | 202: "Accepted", 122 | 203: "Non-Authoritative Information", 123 | 204: "No Content", 124 | 205: "Reset Content", 125 | 206: "Partial Content", 126 | 207: "Multi-Status", 127 | 208: "Already Reported", 128 | 226: "IM Used", 129 | 300: "Multiple Choices", 130 | 301: "Moved Permanently", 131 | 302: "Found", 132 | 303: "See Other", 133 | 304: "Not Modified", 134 | 305: "Use Proxy", 135 | 306: "Reserved", 136 | 307: "Temporary Redirect", 137 | 308: "Permanent Redirect", 138 | 400: "Bad Request", 139 | 401: "Unauthorized", 140 | 402: "Payment Required", 141 | 403: "Forbidden", 142 | 404: "Not Found", 143 | 405: "Method Not Allowed", 144 | 406: "Not Acceptable", 145 | 407: "Proxy Authentication Required", 146 | 408: "Request Timeout", 147 | 409: "Conflict", 148 | 410: "Gone", 149 | 411: "Length Required", 150 | 412: "Precondition Failed", 151 | 413: "Request Entity Too Large", 152 | 414: "Request-URI Too Long", 153 | 415: "Unsupported Media Type", 154 | 416: "Requested Range Not Satisfiable", 155 | 417: "Expectation Failed", 156 | 422: "Unprocessable Entity", 157 | 423: "Locked", 158 | 424: "Failed Dependency", 159 | 425: "Unassigned", 160 | 426: "Upgrade Required", 161 | 427: "Unassigned", 162 | 428: "Precondition Required", 163 | 429: "Too Many Requests", 164 | 430: "Unassigned", 165 | 431: "Request Header Fields Too Large", 166 | 500: "Internal Server Error", 167 | 501: "Not Implemented", 168 | 502: "Bad Gateway", 169 | 503: "Service Unavailable", 170 | 504: "Gateway Timeout", 171 | 505: "HTTP Version Not Supported", 172 | 506: "Variant Also Negotiates (Experimental)", 173 | 507: "Insufficient Storage", 174 | 508: "Loop Detected", 175 | 509: "Unassigned", 176 | 510: "Not Extended", 177 | 511: "Network Authentication Required" 178 | }; 179 | 180 | var 181 | 182 | oReq, bIsLoading = false, bUpdateURL = false; 183 | 184 | oLoadingBox.id = "ajax-loader"; 185 | oCover.onclick = abortReq; 186 | oLoadingImg.src = "data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="; 187 | oCover.appendChild(oLoadingImg); 188 | oLoadingBox.appendChild(oCover); 189 | 190 | onpopstate = function (oEvent) { 191 | bUpdateURL = false; 192 | oPageInfo.title = oEvent.state.title; 193 | oPageInfo.url = oEvent.state.url; 194 | getPage(); 195 | }; 196 | 197 | window.addEventListener ? addEventListener("load", init, false) : window.attachEvent ? attachEvent("onload", init) : (onload = init); 198 | 199 | // Public methods 200 | 201 | this.open = requestPage; 202 | this.stop = abortReq; 203 | this.rebuildLinks = init; 204 | 205 | })(); 206 | --------------------------------------------------------------------------------