/[drupal]/contributions/sandbox/borismann/purple/purple-include.js
ViewVC logotype

Contents of /contributions/sandbox/borismann/purple/purple-include.js

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download) (as text)
Thu Jul 19 06:56:00 2007 UTC (2 years, 4 months ago) by borismann
Branch: MAIN
CVS Tags: HEAD
File MIME type: text/javascript
Now adding files in purple module folder
1 /*
2 purple-include.js -- Purple Include (version 0.8)
3
4 Based on Mark Nottingham's most excellent hinclude.js (version 0.9)
5
6 Copyright (c) 2007 Jonathan Cheyer <jonathan@cheyer.biz>,
7 Eugene Eric Kim <eekim@blueoxen.com>,
8 Brad Neuberg <bradneuberg@yahoo.com>
9 Copyright (c) 2005-2006 Mark Nottingham <mnot@pobox.com>
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28
29 -------------------------------------------------------------------------------
30
31 See http://blueoxen.net/c/purple/purple-include/ for documentation.
32 See http://www.mnot.net/javascript/hinclude/ for hinclude documentation.
33
34 TODO:
35 - check navigator property to see if browser will handle this without
36 javascript
37
38 -------------------------------------------------------------------------------
39 */
40
41 var hinclude = {
42 set_content_async: function (url, element, req) {
43 if (req.readyState == 4) {
44 element.className = "included include_" + req.status;
45 if (req.status == 200 | req.status == 304) {
46 this.setHTML(url, req.responseText, element);
47 }else{
48 var origURL = url;
49 if(url.indexOf("purple-proxy.php") != -1){
50 origURL = url.match(/(https?:.*$)/i)[1];
51 }
52
53 element.innerHTML = "<p>Include error for " + url + ": "
54 + req.status + "</p>";
55 element.className += " include_error";
56 }
57 }
58 },
59
60 buffer: new Array(),
61 set_content_buffered: function (url, element, req) {
62 if (req.readyState == 4) {
63 hinclude.buffer.push({url: url, element: element, req: req});
64 hinclude.outstanding--;
65 if (hinclude.outstanding == 0) {
66 hinclude.show_buffered_content();
67 }
68 }
69 },
70 show_buffered_content: function () {
71 while (hinclude.buffer.length > 0) {
72 var include = hinclude.buffer.pop();
73 include.element.className = "included include_"
74 + include.req.status;
75 if (include.req.status == 200 | include.req.status == 304) {
76 var replaceMe = include.element;
77 this.setHTML(include.url, include.req.responseText,
78 include.element);
79 }else{
80 var origURL = include.url;
81 if(include.url.indexOf("purple-proxy.php") != -1){
82 origURL = include.url.match(/(https?:.*$)/i)[1];
83 }
84
85 include.element.innerHTML = "<p>Include error for " + origURL
86 + ": " + include.req.status
87 + "</p>";
88 include.element.className += " include_error";
89 }
90 }
91 },
92
93 setHTML: function (url, html, element) {
94 // parse out the anchor
95 url = decodeURI(url);
96 var anchor = url.match(/#xpath!(.*)$/);
97 if(anchor){ // xpath! style
98 anchor = anchor[1];
99 }else{
100 anchor = url.match(/#(.*)$/);
101 if (anchor) { // purple number or anchor
102 anchor = "//a[@name='" + anchor[1] + "' or "
103 + "@id='" + anchor[1] + "']/.."
104 + " | "
105 + "//p[@name='" + anchor[1] + "' or "
106 + "@id='" + anchor[1] + "']";
107
108 }
109 else { // nothing; just grab whole document
110 anchor = "/body";
111 }
112 }
113
114 // simply write the HTML/XHTML into an iframe
115 // and then get our DOM document -- this is the
116 // only way to deal with unformed HTML, and it
117 // actually turns out to be a more robust way of
118 // dealing with XHTML than the DOMParser since
119 // malformed XHTML will still work in an iframe,
120 // but the DOMParser throws exceptions (and almost
121 // everyone's XHTML is actually broken)
122 var f = document.createElement("iframe");
123 f.style.display = "none";
124 document.getElementsByTagName("body")[0].appendChild(f);
125 var doc = f.contentDocument;
126
127 var self = this;
128 // the iframe doesn't immediately parse the content --
129 // it can take an arbitrary amount of time, so register
130 // ourselves to continue working once the iframe is
131 // finished loading
132 f.onload = function(){
133 var origURL = url;
134 if(url.indexOf("purple-proxy.php") != -1){
135 origURL = url.match(/(https?:.*$)/i)[1];
136 }
137
138 // find XPath matches and serialize
139 var isXML = /<\?xml/.test(html);
140 html = "";
141 var matches;
142 var exp = null;
143 try{
144 matches = self.evaluateXPath(doc, anchor, isXML);
145 }catch(e){
146 exp = e;
147 }
148
149 if(!exp && matches){
150 for(var i = 0; i < matches.length; i++){
151 html += (new XMLSerializer()).serializeToString(matches[i])
152 + "\n";
153 }
154 }
155
156 if(!exp && !matches.length){
157 html = "<p>No include match for " + origURL + "</p>";
158 element.className += " include_error";
159 }else if(exp){
160 html = "<p>Invalid include address for " + origURL + ": "
161 + exp.message + "</p>";
162 element.className += " include_error";
163 }
164
165 // inline our HTML fragment now, to replace the
166 // hx:include element
167 element.innerHTML = html;
168 };
169
170 // now have the iframe do its magic
171 doc.open();
172 doc.write(html);
173 doc.close();
174 },
175
176 evaluateXPath: function (aDoc, aExpr, isXML) {
177 var nsResolver = (isXML == false) ? null : function (prefix) {
178 return 'http://www.w3.org/1999/xhtml';
179 };
180 var nodes = aDoc.evaluate(aExpr, aDoc.documentElement, nsResolver,
181 XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
182 null);
183 var results = [];
184 for(var i = 0; i < nodes.snapshotLength; i++){
185 results.push(nodes.snapshotItem(i));
186 }
187
188 return results;
189 },
190
191 outstanding: 0,
192 run: function () {
193 var mode = this.get_meta("include_mode", "buffered");
194 var callback = function(element, req) {};
195 var includes = document.getElementsByTagName("hx:include");
196 if (includes.length == 0) { // remove ns for IE
197 includes = document.getElementsByTagName("include");
198 }
199 if (mode == "async") {
200 callback = "set_content_async";
201 } else if (mode == "buffered") {
202 callback = "set_content_buffered";
203 var timeout = this.get_meta("include_timeout", 2.5) * 1000;
204 setTimeout("hinclude.show_buffered_content()", timeout);
205 }
206 for (var i=0; i < includes.length; i++) {
207 includes[i].innerHTML = '<img src="roller.gif" />';
208 this.include(includes[i], includes[i].getAttribute("src"),
209 callback);
210 }
211 },
212
213 include: function (element, url, incl_cb) {
214 var scheme = url.substring(0,url.indexOf(":"));
215
216 if (scheme.toLowerCase() == "data") { // just text/plain for now
217 data = unescape(url.substring(url.indexOf(",") + 1, url.length));
218 element.innerHTML = data;
219 }else {
220 if(scheme) {
221 var url_base = this.get_meta("purple_proxy_path",
222 "/hypertext/purple-include/purple-proxy.php");
223 url = url_base + "?url=" + encodeURI(url);
224 }
225 var req = false;
226 if(window.XMLHttpRequest) {
227 try {
228 req = new XMLHttpRequest();
229 } catch(e) {
230 req = false;
231 }
232 } else if(window.ActiveXObject) {
233 try {
234 req = new ActiveXObject("Microsoft.XMLHTTP");
235 } catch(e) {
236 req = false;
237 }
238 }
239 if(req) {
240 this.outstanding++;
241 var self = this;
242 req.onreadystatechange = function() {
243 self[incl_cb](url, element, req);
244 };
245 try {
246 req.open("GET", url, true);
247 req.send("");
248 } catch (e) {
249 this.outstanding--;
250 alert("Include error: " + url + " (" + e + ")");
251 }
252 }
253 }
254 },
255
256 get_meta: function (name, value_default) {
257 var metas = document.getElementsByTagName("meta");
258 for (var m=0; m < metas.length; m++) {
259 var meta_name = metas[m].getAttribute("name");
260 if (meta_name == name) {
261 return metas[m].getAttribute("content");
262 }
263 }
264 return value_default;
265 },
266
267 /*
268 * (c)2006 Dean Edwards/Matthias Miller/John Resig
269 * Special thanks to Dan Webb's domready.js Prototype extension
270 * and Simon Willison's addLoadEvent
271 *
272 * For more info, see:
273 * http://dean.edwards.name/weblog/2006/06/again/
274 * http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
275 * http://simon.incutio.com/archive/2004/05/26/addLoadEvent
276 *
277 * Thrown together by Jesse Skinner (http://www.thefutureoftheweb.com/)
278 *
279 *
280 * To use: call addDOMLoadEvent one or more times with functions, ie:
281 *
282 * function something() {
283 * // do something
284 * }
285 * addDOMLoadEvent(something);
286 *
287 * addDOMLoadEvent(function() {
288 * // do other stuff
289 * });
290 *
291 */
292 addDOMLoadEvent: function(func) {
293 if (!window.__load_events) {
294 var init = function () {
295 // quit if this function has already been called
296 if (arguments.callee.done) return;
297
298 // flag this function so we don't do the same thing twice
299 arguments.callee.done = true;
300
301 // kill the timer
302 if (window.__load_timer) {
303 clearInterval(window.__load_timer);
304 window.__load_timer = null;
305 }
306
307 // execute each function in the stack in the order they were added
308 for (var i=0;i < window.__load_events.length;i++) {
309 window.__load_events[i]();
310 }
311 window.__load_events = null;
312
313 // clean up the __ie_onload event
314 /*@cc_on @*/
315 /*@if (@_win32)
316 document.getElementById("__ie_onload").onreadystatechange = "";
317 /*@end @*/
318 };
319
320 // for Mozilla/Opera9
321 if (document.addEventListener) {
322 document.addEventListener("DOMContentLoaded", init, false);
323 }
324
325 // for Internet Explorer
326 /*@cc_on @*/
327 /*@if (@_win32)
328 document.write("<scr"+"ipt id=__ie_onload defer src=javascript:void(0)><\/scr"+"ipt>");
329 var script = document.getElementById("__ie_onload");
330 script.onreadystatechange = function() {
331 if (this.readyState == "complete") {
332 init(); // call the onload handler
333 }
334 };
335 /*@end @*/
336
337 // for Safari
338 if (/WebKit/i.test(navigator.userAgent)) { // sniff
339 window.__load_timer = setInterval(function() {
340 if (/loaded|complete/.test(document.readyState)) {
341 init(); // call the onload handler
342 }
343 }, 10);
344 }
345
346 // for other browsers
347 window.onload = init;
348
349 // create event function stack
350 window.__load_events = [];
351 }
352
353 // add function to event stack
354 window.__load_events.push(func);
355 }
356 }
357
358 hinclude.addDOMLoadEvent(function() { hinclude.run(); });
359
360 /* Simon Willison - http://simonwillison.net/2004/May/30/plinks/ */
361 function plinkHighlight() {
362 if (/#p-/.test(document.location)) {
363 // The user arrived via a plink
364 var plink_id = document.location.href.split('#')[1];
365 var para = document.getElementById(plink_id);
366 para.className = para.className + ' plinkHighlight';
367 }
368 }
369
370 function addpLinks() {
371 var paras = document.getElementsByTagName('p');
372 for (var i = 0; i < paras.length; i++) {
373 var current = paras[i];
374 if (/^p-/.test(current.id)) {
375 // It's a purple link paragraph
376 var plink = document.createElement('a');
377 plink.href = document.location.href.split('#')[0] + '#' + current.id;
378 plink.className = 'plink';
379 plink.appendChild(document.createTextNode(' #'));
380 current.appendChild(plink);
381 }
382 }
383 }
384
385 function addLoadEvent(func) {
386 var oldonload = window.onload;
387 if (typeof window.onload != 'function') {
388 window.onload = func;
389 } else {
390 window.onload = function() {
391 oldonload();
392 func();
393 }
394 }
395 }
396
397 addLoadEvent(addpLinks);
398 addLoadEvent(plinkHighlight);

  ViewVC Help
Powered by ViewVC 1.1.2