source: Dev/branches/rest-dojo-ui/client/dojox/html/ellipsis.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 5.9 KB
Line 
1define("dojox/html/ellipsis",["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/array", "dojo/_base/Color", "dojo/colors"], function(d){
2        /*=====
3        dojox.html.ellipsis = {
4                // summary: offers cross-browser support for text-overflow: ellipsis
5                //
6                // description: Add "dojoxEllipsis" on any node that you want to ellipsis-ize. In order to function properly,
7                //      the node with the dojoxEllipsis class set on it should be a child of a node with a defined width.
8                //      It should also be a block-level element (i.e. <div>) - it will not work on td elements.
9                //      NOTE: When using the dojoxEllipsis class within tables, the table needs to have the table-layout: fixed style
10        }
11        =====*/
12       
13        if(d.isFF < 7){ //TODO: feature detect text-overflow in computed style?
14                // The delay (in ms) to wait so that we don't keep querying when many
15                // changes happen at once - set config "dojoxFFEllipsisDelay" if you
16                // want a different value
17                var delay = 1;
18                if("dojoxFFEllipsisDelay" in d.config){
19                        delay = Number(d.config.dojoxFFEllipsisDelay);
20                        if(isNaN(delay)){
21                                delay = 1;
22                        }
23                }
24                try{
25                        var createXULEllipsis = (function(){
26                                // Create our stub XUL elements for cloning later
27                                // NOTE: this no longer works as of FF 4.0:
28                                // https://developer.mozilla.org/En/Firefox_4_for_developers#Remote_XUL_support_removed
29                                var sNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
30                                var xml = document.createElementNS(sNS, 'window');
31                                var label = document.createElementNS(sNS, 'description');
32                                label.setAttribute('crop', 'end');
33                                xml.appendChild(label);
34
35                                return function(/* Node */ n){
36                                        // Summary:
37                                        //              Given a node, it creates the XUL and sets its
38                                        //              content so that it will have an ellipsis
39                                        var x = xml.cloneNode(true);
40                                        x.firstChild.setAttribute('value', n.textContent);
41                                        n.innerHTML = '';
42                                        n.appendChild(x);
43                                };
44                        })();
45                }catch(e){}
46               
47                // Create our iframe elements for cloning later
48                var create = d.create;
49                var dd = d.doc;
50                var dp = d.place;
51                var iFrame = create("iframe", {className: "dojoxEllipsisIFrame",
52                                        src: "javascript:'<html><head><script>if(\"loadFirebugConsole\" in window){window.loadFirebugConsole();}</script></head><body></body></html>'"});
53                var rollRange = function(/* W3C Range */ r, /* int? */ cnt){
54                        // Summary:
55                        //              Rolls the given range back one character from the end
56                        //
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});
Note: See TracBrowser for help on using the repository browser.