1 | define("dojox/html/ellipsis",["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/array", "dojo/_base/Color", "dojo/colors"], function(d){ |
---|
2 | /*===== |
---|
3 | return { |
---|
4 | // summary: |
---|
5 | // offers cross-browser support for text-overflow: ellipsis |
---|
6 | // description: |
---|
7 | // Add "dojoxEllipsis" on any node that you want to ellipsis-ize. In order to function properly, |
---|
8 | // the node with the dojoxEllipsis class set on it should be a child of a node with a defined width. |
---|
9 | // It should also be a block-level element (i.e. `<div>`) - it will not work on td elements. |
---|
10 | // NOTE: When using the dojoxEllipsis class within tables, the table needs to have the table-layout: fixed style |
---|
11 | }; |
---|
12 | =====*/ |
---|
13 | |
---|
14 | if(d.isFF < 7){ //TODO: feature detect text-overflow in computed style? |
---|
15 | // The delay (in ms) to wait so that we don't keep querying when many |
---|
16 | // changes happen at once - set config "dojoxFFEllipsisDelay" if you |
---|
17 | // want a different value |
---|
18 | var delay = 1; |
---|
19 | if("dojoxFFEllipsisDelay" in d.config){ |
---|
20 | delay = Number(d.config.dojoxFFEllipsisDelay); |
---|
21 | if(isNaN(delay)){ |
---|
22 | delay = 1; |
---|
23 | } |
---|
24 | } |
---|
25 | try{ |
---|
26 | var createXULEllipsis = (function(){ |
---|
27 | // Create our stub XUL elements for cloning later |
---|
28 | // NOTE: this no longer works as of FF 4.0: |
---|
29 | // https://developer.mozilla.org/En/Firefox_4_for_developers#Remote_XUL_support_removed |
---|
30 | var sNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; |
---|
31 | var xml = document.createElementNS(sNS, 'window'); |
---|
32 | var label = document.createElementNS(sNS, 'description'); |
---|
33 | label.setAttribute('crop', 'end'); |
---|
34 | xml.appendChild(label); |
---|
35 | |
---|
36 | return function(/* Node */ n){ |
---|
37 | // Summary: |
---|
38 | // Given a node, it creates the XUL and sets its |
---|
39 | // content so that it will have an ellipsis |
---|
40 | var x = xml.cloneNode(true); |
---|
41 | x.firstChild.setAttribute('value', n.textContent); |
---|
42 | n.innerHTML = ''; |
---|
43 | n.appendChild(x); |
---|
44 | }; |
---|
45 | })(); |
---|
46 | }catch(e){} |
---|
47 | |
---|
48 | // Create our iframe elements for cloning later |
---|
49 | var create = d.create; |
---|
50 | var dd = d.doc; |
---|
51 | var dp = d.place; |
---|
52 | var iFrame = create("iframe", {className: "dojoxEllipsisIFrame", |
---|
53 | src: "javascript:'<html><head><script>if(\"loadFirebugConsole\" in window){window.loadFirebugConsole();}</script></head><body></body></html>'", style: {display: "none"}}); |
---|
54 | var rollRange = function(/* W3C Range */ r, /* int? */ cnt){ |
---|
55 | // summary: |
---|
56 | // Rolls the given range back one character from the end |
---|
57 | // r: W3C Range |
---|
58 | // The range to roll back |
---|
59 | // cnt: int? |
---|
60 | // An optional number of times to roll back (defaults 1) |
---|
61 | if(r.collapsed){ |
---|
62 | // Do nothing - we are already collapsed |
---|
63 | return; |
---|
64 | } |
---|
65 | if(cnt > 0){ |
---|
66 | do{ |
---|
67 | rollRange(r); |
---|
68 | cnt--; |
---|
69 | }while(cnt); |
---|
70 | return; |
---|
71 | } |
---|
72 | if(r.endContainer.nodeType == 3 && r.endOffset > 0){ |
---|
73 | r.setEnd(r.endContainer, r.endOffset - 1); |
---|
74 | }else if(r.endContainer.nodeType == 3){ |
---|
75 | r.setEndBefore(r.endContainer); |
---|
76 | rollRange(r); |
---|
77 | return; |
---|
78 | }else if(r.endOffset && r.endContainer.childNodes.length >= r.endOffset){ |
---|
79 | var nCont = r.endContainer.childNodes[r.endOffset - 1]; |
---|
80 | if(nCont.nodeType == 3){ |
---|
81 | r.setEnd(nCont, nCont.length - 1); |
---|
82 | }else if(nCont.childNodes.length){ |
---|
83 | r.setEnd(nCont, nCont.childNodes.length); |
---|
84 | rollRange(r); |
---|
85 | return; |
---|
86 | }else{ |
---|
87 | r.setEndBefore(nCont); |
---|
88 | rollRange(r); |
---|
89 | return; |
---|
90 | } |
---|
91 | }else{ |
---|
92 | r.setEndBefore(r.endContainer); |
---|
93 | rollRange(r); |
---|
94 | return; |
---|
95 | } |
---|
96 | }; |
---|
97 | var createIFrameEllipsis = function(/* Node */ n){ |
---|
98 | // summary: |
---|
99 | // Given a node, it creates an iframe and and ellipsis div and |
---|
100 | // sets up the connections so that they will work correctly. |
---|
101 | // This function is used when createXULEllipsis is not able |
---|
102 | // to be used (because there is markup within the node) - it's |
---|
103 | // a bit slower, but does the trick |
---|
104 | var c = create("div", {className: "dojoxEllipsisContainer"}); |
---|
105 | var e = create("div", {className: "dojoxEllipsisShown", style: {display: "none"}}); |
---|
106 | n.parentNode.replaceChild(c, n); |
---|
107 | c.appendChild(n); |
---|
108 | c.appendChild(e); |
---|
109 | var i = iFrame.cloneNode(true); |
---|
110 | var ns = n.style; |
---|
111 | var es = e.style; |
---|
112 | var ranges; |
---|
113 | var resizeNode = function(){ |
---|
114 | ns.display = ""; |
---|
115 | es.display = "none"; |
---|
116 | if(n.scrollWidth <= n.offsetWidth){ return; } |
---|
117 | var r = dd.createRange(); |
---|
118 | r.selectNodeContents(n); |
---|
119 | ns.display = "none"; |
---|
120 | es.display = ""; |
---|
121 | var done = false; |
---|
122 | do{ |
---|
123 | var numRolls = 1; |
---|
124 | dp(r.cloneContents(), e, "only"); |
---|
125 | var sw = e.scrollWidth, ow = e.offsetWidth; |
---|
126 | done = (sw <= ow); |
---|
127 | var pct = (1 - ((ow * 1) / sw)); |
---|
128 | if(pct > 0){ |
---|
129 | numRolls = Math.max(Math.round(e.textContent.length * pct) - 1, 1); |
---|
130 | } |
---|
131 | rollRange(r, numRolls); |
---|
132 | }while(!r.collapsed && !done); |
---|
133 | }; |
---|
134 | i.onload = function(){ |
---|
135 | i.contentWindow.onresize = resizeNode; |
---|
136 | resizeNode(); |
---|
137 | }; |
---|
138 | c.appendChild(i); |
---|
139 | }; |
---|
140 | |
---|
141 | // Function for updating the ellipsis |
---|
142 | var hc = d.hasClass; |
---|
143 | var doc = d.doc; |
---|
144 | var s, fn, opt; |
---|
145 | if(doc.querySelectorAll){ |
---|
146 | s = doc; |
---|
147 | fn = "querySelectorAll"; |
---|
148 | opt = ".dojoxEllipsis"; |
---|
149 | }else if(doc.getElementsByClassName){ |
---|
150 | s = doc; |
---|
151 | fn = "getElementsByClassName"; |
---|
152 | opt = "dojoxEllipsis"; |
---|
153 | }else{ |
---|
154 | s = d; |
---|
155 | fn = "query"; |
---|
156 | opt = ".dojoxEllipsis"; |
---|
157 | } |
---|
158 | fx = function(){ |
---|
159 | d.forEach(s[fn].apply(s, [opt]), function(n){ |
---|
160 | if(!n || n._djx_ellipsis_done){ return; } |
---|
161 | n._djx_ellipsis_done = true; |
---|
162 | if(createXULEllipsis && n.textContent == n.innerHTML && !hc(n, "dojoxEllipsisSelectable")){ |
---|
163 | // We can do the faster XUL version, instead of calculating |
---|
164 | createXULEllipsis(n); |
---|
165 | }else{ |
---|
166 | createIFrameEllipsis(n); |
---|
167 | } |
---|
168 | }); |
---|
169 | }; |
---|
170 | |
---|
171 | d.addOnLoad(function(){ |
---|
172 | // Apply our initial stuff |
---|
173 | var t = null; |
---|
174 | var c = null; |
---|
175 | var connFx = function(){ |
---|
176 | if(c){ |
---|
177 | // disconnect us - so we don't fire anymore |
---|
178 | d.disconnect(c); |
---|
179 | c = null; |
---|
180 | } |
---|
181 | if(t){ clearTimeout(t); } |
---|
182 | t = setTimeout(function(){ |
---|
183 | t = null; |
---|
184 | fx(); |
---|
185 | // Connect to the modified function so that we can catch |
---|
186 | // our next change |
---|
187 | c = d.connect(d.body(), "DOMSubtreeModified", connFx); |
---|
188 | }, delay); |
---|
189 | }; |
---|
190 | connFx(); |
---|
191 | }); |
---|
192 | } |
---|
193 | }); |
---|