|
1 CubicWeb.require('python.js'); |
|
2 |
|
3 /* returns the document's baseURI. (baseuri() uses document.baseURI if |
|
4 * available and inspects the <base> tag manually otherwise.) |
|
5 */ |
|
6 function baseuri() { |
|
7 var uri = document.baseURI; |
|
8 if (uri) { // some browsers don't define baseURI |
|
9 return uri; |
|
10 } |
|
11 var basetags = document.getElementsByTagName('base'); |
|
12 if (basetags.length) { |
|
13 return getNodeAttribute(basetags[0], 'href'); |
|
14 } |
|
15 return ''; |
|
16 } |
|
17 |
|
18 function insertText(text, areaId) { |
|
19 var textarea = jQuery('#' + areaId); |
|
20 if (document.selection) { // IE |
|
21 var selLength; |
|
22 textarea.focus(); |
|
23 sel = document.selection.createRange(); |
|
24 selLength = sel.text.length; |
|
25 sel.text = text; |
|
26 sel.moveStart('character', selLength-text.length); |
|
27 sel.select(); |
|
28 } else if (textarea.selectionStart || textarea.selectionStart == '0') { // mozilla |
|
29 var startPos = textarea.selectionStart; |
|
30 var endPos = textarea.selectionEnd; |
|
31 // insert text so that it replaces the [startPos, endPos] part |
|
32 textarea.value = textarea.value.substring(0,startPos) + text + textarea.value.substring(endPos,textarea.value.length); |
|
33 // set cursor pos at the end of the inserted text |
|
34 textarea.selectionStart = textarea.selectionEnd = startPos+text.length; |
|
35 textarea.focus(); |
|
36 } else { // safety belt for other browsers |
|
37 textarea.value += text; |
|
38 } |
|
39 } |
|
40 |
|
41 /* taken from dojo toolkit */ |
|
42 function setCaretPos(element, start, end){ |
|
43 if(!end){ end = element.value.length; } // NOTE: Strange - should be able to put caret at start of text? |
|
44 // Mozilla |
|
45 // parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130 |
|
46 if(element.setSelectionRange){ |
|
47 element.focus(); |
|
48 element.setSelectionRange(start, end); |
|
49 } else if(element.createTextRange){ // IE |
|
50 var range = element.createTextRange(); |
|
51 with(range){ |
|
52 collapse(true); |
|
53 moveEnd('character', end); |
|
54 moveStart('character', start); |
|
55 select(); |
|
56 } |
|
57 } else { //otherwise try the event-creation hack (our own invention) |
|
58 // do we need these? |
|
59 element.value = element.value; |
|
60 element.blur(); |
|
61 element.focus(); |
|
62 // figure out how far back to go |
|
63 var dist = parseInt(element.value.length)-end; |
|
64 var tchar = String.fromCharCode(37); |
|
65 var tcc = tchar.charCodeAt(0); |
|
66 for(var x = 0; x < dist; x++){ |
|
67 var te = document.createEvent("KeyEvents"); |
|
68 te.initKeyEvent("keypress", true, true, null, false, false, false, false, tcc, tcc); |
|
69 element.dispatchEvent(te); |
|
70 } |
|
71 } |
|
72 } |
|
73 |
|
74 function setProgressMessage(label) { |
|
75 var body = document.getElementsByTagName('body')[0]; |
|
76 body.appendChild(DIV({id: 'progress'}, label)); |
|
77 jQuery('#progress').show(); |
|
78 } |
|
79 |
|
80 function resetProgressMessage() { |
|
81 var body = document.getElementsByTagName('body')[0]; |
|
82 jQuery('#progress').hide(); |
|
83 } |
|
84 |
|
85 |
|
86 /* set body's cursor to 'progress' |
|
87 */ |
|
88 function setProgressCursor() { |
|
89 var body = document.getElementsByTagName('body')[0]; |
|
90 body.style.cursor = 'progress'; |
|
91 } |
|
92 |
|
93 /* |
|
94 * reset body's cursor to default (mouse cursor). The main |
|
95 * purpose of this function is to be used as a callback in the |
|
96 * deferreds' callbacks chain. |
|
97 */ |
|
98 function resetCursor(result) { |
|
99 var body = document.getElementsByTagName('body')[0]; |
|
100 body.style.cursor = 'default'; |
|
101 // pass result to next callback in the callback chain |
|
102 return result; |
|
103 } |
|
104 |
|
105 function updateMessage(msg) { |
|
106 var msgdiv = DIV({'class':'message'}); |
|
107 // don't pass msg to DIV() directly because DIV will html escape it |
|
108 // and msg should alreay be html escaped at this point. |
|
109 msgdiv.innerHTML = msg; |
|
110 jQuery('#appMsg').removeClass('hidden').empty().append(msgdiv); |
|
111 } |
|
112 |
|
113 /* builds an url from an object (used as a dictionnary) |
|
114 * Notable difference with MochiKit's queryString: as_url does not |
|
115 * *url_quote* each value found in the dictionnary |
|
116 * |
|
117 * >>> as_url({'rql' : "RQL", 'x': [1, 2], 'itemvid' : "oneline"}) |
|
118 * rql=RQL&vid=list&itemvid=oneline&x=1&x=2 |
|
119 */ |
|
120 function as_url(props) { |
|
121 var chunks = []; |
|
122 for(key in props) { |
|
123 var value = props[key]; |
|
124 // generate a list of couple key=value if key is multivalued |
|
125 if (isArrayLike(value)) { |
|
126 for (var i=0; i<value.length;i++) { |
|
127 chunks.push(key + '=' + value[i]); |
|
128 } |
|
129 } else { |
|
130 chunks.push(key + '=' + value); |
|
131 } |
|
132 } |
|
133 return chunks.join('&'); |
|
134 } |
|
135 |
|
136 /* return selected value of a combo box if any |
|
137 */ |
|
138 function firstSelected(selectNode) { |
|
139 var selection = filter(attrgetter('selected'), selectNode.options); |
|
140 return (selection.length>0) ? getNodeAttribute(selection[0], 'value'):null; |
|
141 } |
|
142 |
|
143 /* toggle visibility of an element by its id |
|
144 */ |
|
145 function toggleVisibility(elemId) { |
|
146 jqNode(elemId).toggleClass('hidden'); |
|
147 } |
|
148 |
|
149 /* |
|
150 * return true (resp. false) if <element> (resp. doesn't) matches <properties> |
|
151 */ |
|
152 function elementMatches(properties, element) { |
|
153 for (prop in properties) { |
|
154 if (getNodeAttribute(element, prop) != properties[prop]) { |
|
155 return false; |
|
156 } |
|
157 } |
|
158 return true; |
|
159 } |
|
160 |
|
161 /* returns the list of elements in the document matching the tag name |
|
162 * and the properties provided |
|
163 * |
|
164 * @param tagName the tag's name |
|
165 * @param properties a js Object used as a dict |
|
166 * @return an iterator (if a *real* array is needed, you can use the |
|
167 * list() function) |
|
168 */ |
|
169 function getElementsMatching(tagName, properties, /* optional */ parent) { |
|
170 var filterfunc = partial(elementMatches, properties); |
|
171 parent = parent || document; |
|
172 return filter(filterfunc, parent.getElementsByTagName(tagName)); |
|
173 } |
|
174 |
|
175 /* |
|
176 * sets checked/unchecked status of checkboxes |
|
177 */ |
|
178 function setCheckboxesState(nameprefix, checked){ |
|
179 // XXX: this looks in *all* the document for inputs |
|
180 var elements = getElementsMatching('input', {'type': "checkbox"}); |
|
181 filterfunc = function(cb) { return nameprefix && cb.name.startsWith(nameprefix); }; |
|
182 forEach(filter(filterfunc, elements), function(cb) {cb.checked=checked;}); |
|
183 } |
|
184 |
|
185 function setCheckboxesState2(nameprefix, value, checked){ |
|
186 // XXX: this looks in *all* the document for inputs |
|
187 var elements = getElementsMatching('input', {'type': "checkbox"}); |
|
188 filterfunc = function(cb) { return nameprefix && cb.name.startsWith(nameprefix) && cb.value == value; }; |
|
189 forEach(filter(filterfunc, elements), function(cb) {cb.checked=checked;}); |
|
190 } |
|
191 |
|
192 /* |
|
193 * centers an HTML element on the screen |
|
194 */ |
|
195 function centerElement(obj){ |
|
196 var vpDim = getViewportDimensions(); |
|
197 var elemDim = getElementDimensions(obj); |
|
198 setElementPosition(obj, {'x':((vpDim.w - elemDim.w)/2), |
|
199 'y':((vpDim.h - elemDim.h)/2)}); |
|
200 } |
|
201 |
|
202 /* this function is a hack to build a dom node from html source */ |
|
203 function html2dom(source) { |
|
204 var tmpNode = SPAN(); |
|
205 tmpNode.innerHTML = source; |
|
206 if (tmpNode.childNodes.length == 1) { |
|
207 return tmpNode.firstChild; |
|
208 } |
|
209 else { |
|
210 // we leave the span node when `source` has no root node |
|
211 // XXX This is cleary not the best solution, but css/html-wise, |
|
212 /// a span not should not be too much disturbing |
|
213 return tmpNode; |
|
214 } |
|
215 } |
|
216 |
|
217 |
|
218 // *** HELPERS **************************************************** // |
|
219 function rql_for_eid(eid) { return 'Any X WHERE X eid ' + eid; } |
|
220 function isTextNode(domNode) { return domNode.nodeType == 3; } |
|
221 function isElementNode(domNode) { return domNode.nodeType == 1; } |
|
222 |
|
223 function changeLinkText(link, newText) { |
|
224 jQuery(link).text(newText); |
|
225 // for (var i=0; i<link.childNodes.length; i++) { |
|
226 // var node = link.childNodes[i]; |
|
227 // if (isTextNode(node)) { |
|
228 // swapDOM(node, document.createTextNode(newText)); |
|
229 // break; |
|
230 // } |
|
231 // } |
|
232 } |
|
233 |
|
234 |
|
235 function autogrow(area) { |
|
236 if (area.scrollHeight > area.clientHeight && !window.opera) { |
|
237 if (area.rows < 20) { |
|
238 area.rows += 2; |
|
239 } |
|
240 } |
|
241 } |
|
242 |
|
243 //============= page loading events ==========================================// |
|
244 function roundedCornersOnLoad() { |
|
245 roundClass("div", "sideBox", {corners: "bottom", compact:false}); |
|
246 roundClass("div", "boxTitle", {corners: "top", compact:true}); |
|
247 roundClass("div", "boxPrefTitle", {corners: "top", compact:true}); |
|
248 roundClass("div", "sideBoxTitle", {corners: "top", compact:true}); |
|
249 roundClass("th", "month", {corners: "top", compact:true}); |
|
250 } |
|
251 |
|
252 // jQuery(document).ready(roundedCornersOnLoad); |
|
253 |
|
254 |
|
255 CubicWeb.provide('htmlhelpers.js'); |
|
256 |