-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathjquery.writeCapture.js
155 lines (139 loc) · 4.04 KB
/
jquery.writeCapture.js
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* jquery.writeCapture.js
*
* Note that this file only provides the jQuery plugin functionality, you still
* need writeCapture.js. The compressed version will contain both as as single
* file.
*
* @author noah <[email protected]>
*
*/
(function($,wc,noop) {
// methods that take HTML content (according to API)
var methods = {
html: html
};
// TODO wrap domManip instead?
$.each(['append', 'prepend', 'after', 'before', 'wrap', 'wrapAll', 'replaceWith',
'wrapInner'],function() { methods[this] = makeMethod(this); });
function isString(s) {
return Object.prototype.toString.call(s) == "[object String]";
}
function executeMethod(method,content,options,cb) {
if(arguments.length == 0) return proxyMethods.call(this);
var m = methods[method];
if(method == 'load') {
return load.call(this,content,options,cb);
}
if(!m) error(method);
return doEach.call(this,content,options,m);
}
$.fn.writeCapture = executeMethod;
var PROXIED = '__writeCaptureJsProxied-fghebd__';
// inherit from the jQuery instance, proxying the HTML injection methods
// so that the HTML is sanitized
function proxyMethods() {
if(this[PROXIED]) return this;
var jq = this;
function F() {
var _this = this, sanitizing = false;
this[PROXIED] = true;
$.each(methods,function(method) {
var _super = jq[method];
if(!_super) return;
_this[method] = function(content,options,cb) {
// if it's unsanitized HTML, proxy it
if(!sanitizing && isString(content)) {
try {
sanitizing = true;
return executeMethod.call(_this,method,content,
options,cb);
} finally {
sanitizing = false;
}
}
return _super.apply(_this,arguments); // else delegate
};
});
// wrap pushStack so that the new jQuery instance is also wrapped
this.pushStack = function() {
return proxyMethods.call(jq.pushStack.apply(_this,arguments));
};
this.endCapture = function() { return jq; };
}
F.prototype = jq;
return new F();
}
function doEach(content,options,action) {
var done, self = this;
if(options && options.done) {
done = options.done;
delete options.done;
} else if($.isFunction(options)) {
done = options;
options = null;
}
wc.sanitizeSerial($.map(this,function(el) {
return {
html: content,
options: options,
action: function(text) {
action.call(el,text);
}
};
}),done && function() { done.call(self); } || done);
return this;
}
function html(safe) {
$(this).html(safe);
}
function makeMethod(method) {
return function(safe) {
$(this)[method](safe);
};
}
function load(url,options,callback) {
var self = this, selector, off = url.indexOf(' ');
if ( off >= 0 ) {
selector = url.slice(off, url.length);
url = url.slice(0, off);
}
if($.isFunction(callback)) {
options = options || {};
options.done = callback;
}
return $.ajax({
url: url,
type: options && options.type || "GET",
dataType: "html",
data: options && options.params,
complete: loadCallback(self,options,selector)
});
}
function loadCallback(self,options,selector) {
return function(res,status) {
if ( status == "success" || status == "notmodified" ) {
var text = getText(res.responseText,selector);
doEach.call(self,text,options,html);
}
};
}
var PLACEHOLDER = /jquery-writeCapture-script-placeholder-(\d+)-wc/g;
function getText(text,selector) {
if(!selector || !text) return text;
var id = 0, scripts = {};
return $('<div/>').append(
text.replace(/<script(.|\s)*?\/script>/g, function(s) {
scripts[id] = s;
return "jquery-writeCapture-script-placeholder-"+(id++)+'-wc';
})
).find(selector).html().replace(PLACEHOLDER,function(all,id) {
return scripts[id];
});
}
function error(method) {
throw "invalid method parameter "+method;
}
// expose core
$.writeCapture = wc;
})(jQuery,writeCapture.noConflict());