source: Dev/trunk/src/client/dojox/html/ellipsis.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 6.0 KB
Line 
1define("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});
Note: See TracBrowser for help on using the repository browser.