src/cm/media/js/client/c_scopes.js
changeset 341 053551f213fb
parent 103 61fd17f9ab78
child 373 f6fe14eb51bc
equal deleted inserted replaced
340:9e2b9e568e42 341:053551f213fb
     5 // classes :
     5 // classes :
     6 // c-s is for 'textnode wrapper span'
     6 // c-s is for 'textnode wrapper span'
     7 // c-c is a comment marker
     7 // c-c is a comment marker
     8 
     8 
     9 paintCommentScope = function(comment) {
     9 paintCommentScope = function(comment) {
    10 	if (comment.reply_to_id == null && comment['start_wrapper'] != -1) {
    10   if (comment.reply_to_id == null && comment['start_wrapper'] != -1) {
    11 		var selection = { 	'start' : { 'elt' : document.getElementById("sv_"+comment['start_wrapper']), 'offset' : comment['start_offset'] },
    11     var selection = {   'start' : { 'elt' : document.getElementById("sv_"+comment['start_wrapper']), 'offset' : comment['start_offset'] },
    12 							'end' : { 'elt' : document.getElementById("sv_"+comment['end_wrapper']), 'offset' : comment['end_offset'] }
    12               'end' : { 'elt' : document.getElementById("sv_"+comment['end_wrapper']), 'offset' : comment['end_offset'] }
    13 						} ;
    13             } ;
    14 		if (document.getElementById("sv_"+comment['start_wrapper'])== null) {
    14     if (document.getElementById("sv_"+comment['start_wrapper'])== null) {
    15 			warn_server({'from':'paintCommentScope', 'start_wrapper':comment['start_wrapper']}) ;
    15       warn_server({'from':'paintCommentScope', 'start_wrapper':comment['start_wrapper']}) ;
    16 		}
    16     }
    17 		else {
    17     else {
    18 			if (document.getElementById("sv_"+comment['end_wrapper'])== null)
    18       if (document.getElementById("sv_"+comment['end_wrapper'])== null)
    19 				warn_server({'from':'paintCommentScope', 'end_wrapper':comment['end_wrapper']}) ;
    19         warn_server({'from':'paintCommentScope', 'end_wrapper':comment['end_wrapper']}) ;
    20 			else {
    20       else {
    21 			    selection['start'] = _convertSelectionFromCSToCC(selection['start']) ;
    21           selection['start'] = _convertSelectionFromCSToCC(selection['start']) ;
    22 			    selection['end'] = _convertSelectionFromCSToCC(selection['end']) ;
    22           selection['end'] = _convertSelectionFromCSToCC(selection['end']) ;
    23 			
    23       
    24 			    renderComment(selection, comment['id']) ;
    24           renderComment(selection, comment['id']) ;
    25 			}
    25       }
    26 		}
    26     }
    27 	}
    27   }
    28 } ;
    28 } ;
    29 
    29 
    30 getCommentIdsFromClasses = function (elt) {
    30 getCommentIdsFromClasses = function (elt) {
    31 	var commentIds = [] ;
    31   var commentIds = [] ;
    32 	var classes = elt['className'].split(" ") ;
    32   var classes = elt['className'].split(" ") ;
    33 	for (var i = 0, ilen = classes.length ; i < ilen ; i++) {
    33   for (var i = 0, ilen = classes.length ; i < ilen ; i++) {
    34 		if (classes[i].indexOf('c-id-') == 0) {
    34     if (classes[i].indexOf('c-id-') == 0) {
    35 			commentIds.push(parseInt(classes[i].substring('c-id-'.length))) ;
    35       commentIds.push(parseInt(classes[i].substring('c-id-'.length))) ;
    36 		}
    36     }
    37 	}
    37   }
    38 	return commentIds ;
    38   return commentIds ;
    39 } ;
    39 } ;
    40 
    40 
    41 renderComment = function (selection, commentId) {
    41 renderComment = function (selection, commentId) {
    42 	var startOffset = selection['start']['offset'] ;
    42   var startOffset = selection['start']['offset'] ;
    43 	var endOffset = selection['end']['offset'] ;
    43   var endOffset = selection['end']['offset'] ;
    44 	var startElt = selection['start']['elt'] ;
    44   var startElt = selection['start']['elt'] ;
    45 	var endElt = selection['end']['elt'] ;
    45   var endElt = selection['end']['elt'] ;
    46 
    46 
    47 	
    47   
    48     if ((startElt != null) && (endElt != null) && _getTextNodeContent(startElt) != '' && _getTextNodeContent(endElt) != ''){
    48     if ((startElt != null) && (endElt != null) && _getTextNodeContent(startElt) != '' && _getTextNodeContent(endElt) != ''){
    49 // log('startElt.id : ' + startElt.id) ;
    49 // log('startElt.id : ' + startElt.id) ;
    50 // log('endElt.id : ' + endElt.id) ;
    50 // log('endElt.id : ' + endElt.id) ;
    51 //    	log('startElt.innerHTML : ' + startElt.innerHTML) ;
    51 //      log('startElt.innerHTML : ' + startElt.innerHTML) ;
    52 //    	log('endElt.innerHTML : ' + endElt.innerHTML) ;
    52 //      log('endElt.innerHTML : ' + endElt.innerHTML) ;
    53 	    markWholeNodesAsComments(startElt, endElt, commentId) ;
    53       markWholeNodesAsComments(startElt, endElt, commentId) ;
    54 	    markEndsAsComments(startElt, startOffset, endElt, endOffset, commentId) ;
    54       markEndsAsComments(startElt, startOffset, endElt, endOffset, commentId) ;
    55 	}
    55   }
    56 } ;
    56 } ;
    57 
    57 
    58 markWholeNodesAsComments = function (startElt, endElt, commentId) {
    58 markWholeNodesAsComments = function (startElt, endElt, commentId) {
    59     var commonAncestor = _findCommonAncestor(startElt, endElt) ;
    59     var commonAncestor = _findCommonAncestor(startElt, endElt) ;
    60     _dynSpanToAnc(startElt, commonAncestor, commentId, false) ;
    60     _dynSpanToAnc(startElt, commonAncestor, commentId, false) ;
    71 _getTextNodeContent = function(txtNodeParent) {
    71 _getTextNodeContent = function(txtNodeParent) {
    72     return CY.DOM.getText(txtNodeParent);
    72     return CY.DOM.getText(txtNodeParent);
    73 } ;
    73 } ;
    74 
    74 
    75 markEndsAsComments = function(startElt, startOffset, endElt, endOffset, commentId) {
    75 markEndsAsComments = function(startElt, startOffset, endElt, endOffset, commentId) {
    76 	
    76   
    77 //	alert('starting with: ' + startElt.childNodes.length + 'and a length of : ' + startElt.firstChild.data.length) ; 
    77 //  alert('starting with: ' + startElt.childNodes.length + 'and a length of : ' + startElt.firstChild.data.length) ; 
    78 //	alert('2 and a length of : ' + CY.DOM.getText(startElt).length) ; 
    78 //  alert('2 and a length of : ' + CY.DOM.getText(startElt).length) ; 
    79 
    79 
    80 	var beforeStart = _getTextNodeContent(startElt).substring(0, startOffset) ; 
    80   var beforeStart = _getTextNodeContent(startElt).substring(0, startOffset) ; 
    81 	var afterStart = _getTextNodeContent(startElt).substring(startOffset) ;
    81   var afterStart = _getTextNodeContent(startElt).substring(startOffset) ;
    82 	var beforeEnd = _getTextNodeContent(endElt).substring(0, endOffset) ;
    82   var beforeEnd = _getTextNodeContent(endElt).substring(0, endOffset) ;
    83 	var afterEnd = _getTextNodeContent(endElt).substring(endOffset) ;
    83   var afterEnd = _getTextNodeContent(endElt).substring(endOffset) ;
    84 
    84 
    85     var sameNode = (startElt === endElt) ;
    85     var sameNode = (startElt === endElt) ;
    86     
    86     
    87 //    log('beforeStart : ' + beforeStart + ' , afterStart : ' + afterStart + ' , beforeEnd : ' + beforeEnd + ' , afterEnd : ' + afterEnd + ' , sameNode : ' + sameNode) ;
    87 //    log('beforeStart : ' + beforeStart + ' , afterStart : ' + afterStart + ' , beforeEnd : ' + beforeEnd + ' , afterEnd : ' + afterEnd + ' , sameNode : ' + sameNode) ;
    88  
    88  
    89     // taking care of start node : (and 'sameNode' case when start and end lie
    89     // taking care of start node : (and 'sameNode' case when start and end lie
    90 	// on same node)
    90   // on same node)
    91     if (afterStart != "") { // otherwise nothing to do on the start node
    91     if (afterStart != "") { // otherwise nothing to do on the start node
    92     	if (CY.DOM.hasClass(startElt, 'c-c')) {
    92       if (CY.DOM.hasClass(startElt, 'c-c')) {
    93     		var lastElt = null, afterStartElt = null, afterEndElt = null, beforeStartElt = null ;
    93         var lastElt = null, afterStartElt = null, afterEndElt = null, beforeStartElt = null ;
    94     		
    94         
    95         	var btw = (sameNode) ? _getTextNodeContent(startElt).substring(startOffset, endOffset) : afterStart ;
    95           var btw = (sameNode) ? _getTextNodeContent(startElt).substring(startOffset, endOffset) : afterStart ;
    96         	        	
    96                     
    97 
    97 
    98         	if (sameNode && (afterEnd != "")) {
    98           if (sameNode && (afterEnd != "")) {
    99 				afterEndElt = startElt ;
    99         afterEndElt = startElt ;
   100 				lastElt = afterEndElt ;
   100         lastElt = afterEndElt ;
   101 			}
   101       }
   102 	    	if (btw != "") {
   102         if (btw != "") {
   103 	    		if (lastElt == null) {
   103           if (lastElt == null) {
   104 	    			afterStartElt = startElt ;
   104             afterStartElt = startElt ;
   105 	    		}
   105           }
   106 	    		else {
   106           else {
   107 	    			afterStartElt = _yuiCloneNode(startElt) ;
   107             afterStartElt = _yuiCloneNode(startElt) ;
   108 	    			lastElt.parentNode.insertBefore(afterStartElt, lastElt) ;
   108             lastElt.parentNode.insertBefore(afterStartElt, lastElt) ;
   109 	    		}
   109           }
   110 				lastElt = afterStartElt ;
   110         lastElt = afterStartElt ;
   111 	    	}
   111         }
   112 	    	if (beforeStart != "") {
   112         if (beforeStart != "") {
   113 	    		if (lastElt == null) {
   113           if (lastElt == null) {
   114 	    			beforeStartElt = startElt ;
   114             beforeStartElt = startElt ;
   115 	    		}
   115           }
   116 	    		else {
   116           else {
   117 	    			beforeStartElt = _yuiCloneNode(startElt) ;
   117             beforeStartElt = _yuiCloneNode(startElt) ;
   118 	    			lastElt.parentNode.insertBefore(beforeStartElt, lastElt) ;
   118             lastElt.parentNode.insertBefore(beforeStartElt, lastElt) ;
   119 	    		}
   119           }
   120 				lastElt = beforeStartElt ;
   120         lastElt = beforeStartElt ;
   121 	    	}
   121         }
   122 	    	
   122         
   123 			if (afterEndElt != null) {
   123       if (afterEndElt != null) {
   124 				_setTextNodeContent(afterEndElt, afterEnd) ;
   124         _setTextNodeContent(afterEndElt, afterEnd) ;
   125 			}
   125       }
   126 			
   126       
   127 	    	if (afterStartElt != null) {
   127         if (afterStartElt != null) {
   128 				_setTextNodeContent(afterStartElt, btw) ;
   128         _setTextNodeContent(afterStartElt, btw) ;
   129 	    		_addIdClass(afterStartElt, commentId) ;
   129           _addIdClass(afterStartElt, commentId) ;
   130 	    	}
   130         }
   131 
   131 
   132 //	    	alert('beforeStartElt.firstChild.data.length: ' + beforeStartElt.firstChild.data.length);
   132 //        alert('beforeStartElt.firstChild.data.length: ' + beforeStartElt.firstChild.data.length);
   133 //	    	alert('beforeStartElt.childNodes.length: ' + beforeStartElt.childNodes.length);
   133 //        alert('beforeStartElt.childNodes.length: ' + beforeStartElt.childNodes.length);
   134 	    	if (beforeStartElt != null) {
   134         if (beforeStartElt != null) {
   135 				_setTextNodeContent(beforeStartElt, beforeStart) ; 
   135         _setTextNodeContent(beforeStartElt, beforeStart) ; 
   136 	    	}
   136         }
   137 //	    	alert('beforeStartElt.childNodes.length: ' + beforeStartElt.childNodes.length);
   137 //        alert('beforeStartElt.childNodes.length: ' + beforeStartElt.childNodes.length);
   138 	    	//alert('typeof beforeStartElt: ' + typeof beforeStartElt);
   138         //alert('typeof beforeStartElt: ' + typeof beforeStartElt);
   139 //	    	alert('beforeStartElt.lastChild ==  beforeStartElt.firstChild : ' + (beforeStartElt.lastChild == beforeStartElt.firstChild));
   139 //        alert('beforeStartElt.lastChild ==  beforeStartElt.firstChild : ' + (beforeStartElt.lastChild == beforeStartElt.firstChild));
   140 	    	
   140         
   141 //	    	alert('beforeStartElt.firstChild.id : ' + beforeStartElt.firstChild.id);
   141 //        alert('beforeStartElt.firstChild.id : ' + beforeStartElt.firstChild.id);
   142 //	    	alert('beforeStartElt.lastChild.data : ' + beforeStartElt.lastChild.data);
   142 //        alert('beforeStartElt.lastChild.data : ' + beforeStartElt.lastChild.data);
   143 //	    	alert('beforeStartElt.firstChild.data : ' + beforeStartElt.firstChild.data);
   143 //        alert('beforeStartElt.firstChild.data : ' + beforeStartElt.firstChild.data);
   144 //	    	alert('afterStartElt.firstChild.data : ' + afterStartElt.firstChild.data);
   144 //        alert('afterStartElt.firstChild.data : ' + afterStartElt.firstChild.data);
   145 //	    	alert('afterEndElt.firstChild.data : ' + afterEndElt.firstChild.data);
   145 //        alert('afterEndElt.firstChild.data : ' + afterEndElt.firstChild.data);
   146 	    	
   146         
   147        	}
   147         }
   148     }
   148     }
   149     if ( ( !sameNode ) && ( beforeEnd != "" ) ) { // otherwise nothing to do
   149     if ( ( !sameNode ) && ( beforeEnd != "" ) ) { // otherwise nothing to do
   150 													// on the end node
   150                           // on the end node
   151     	if (CY.DOM.hasClass(endElt, 'c-c')) {
   151       if (CY.DOM.hasClass(endElt, 'c-c')) {
   152     		var lastElt = null, beforeEndElt = null, afterEndElt = null ;
   152         var lastElt = null, beforeEndElt = null, afterEndElt = null ;
   153     		
   153         
   154 	    	if (afterEnd != "") {
   154         if (afterEnd != "") {
   155 	    		afterEndElt = endElt ;
   155           afterEndElt = endElt ;
   156 				lastElt = endElt ;
   156         lastElt = endElt ;
   157 			}
   157       }
   158 			
   158       
   159 	    	if (beforeEnd != "") {
   159         if (beforeEnd != "") {
   160 	    		if (lastElt == null)
   160           if (lastElt == null)
   161 	    			beforeEndElt = endElt ;
   161             beforeEndElt = endElt ;
   162 	    		else {
   162           else {
   163 	    			beforeEndElt = _yuiCloneNode(endElt) ;
   163             beforeEndElt = _yuiCloneNode(endElt) ;
   164 	    			lastElt.parentNode.insertBefore(beforeEndElt, lastElt) ;
   164             lastElt.parentNode.insertBefore(beforeEndElt, lastElt) ;
   165 	    		}
   165           }
   166 				lastElt = beforeEndElt ;
   166         lastElt = beforeEndElt ;
   167 	    	}
   167         }
   168 	    	if (afterEndElt != null) {
   168         if (afterEndElt != null) {
   169 	    		_setTextNodeContent(afterEndElt, afterEnd) ;
   169           _setTextNodeContent(afterEndElt, afterEnd) ;
   170 			}
   170       }
   171 			
   171       
   172 	    	if (beforeEndElt != null) {
   172         if (beforeEndElt != null) {
   173 	    		_addIdClass(beforeEndElt, commentId) ;
   173           _addIdClass(beforeEndElt, commentId) ;
   174 	    		_setTextNodeContent(beforeEndElt, beforeEnd) ;
   174           _setTextNodeContent(beforeEndElt, beforeEnd) ;
   175 	    	}
   175         }
   176     	}
   176       }
   177     }
   177     }
   178 } ;
   178 } ;
   179 
   179 
   180 // WARNING (200891108): had to use YUI cloneNode instead of the native cloneNode
   180 // WARNING (200891108): had to use YUI cloneNode instead of the native cloneNode
   181 // (because of the _yuid that is cloned under IE, cf tests made in textYUIcloneNode.html)
   181 // (because of the _yuid that is cloned under IE, cf tests made in textYUIcloneNode.html)
   183 // afterStartElt = startElt.cloneNode(true) ;
   183 // afterStartElt = startElt.cloneNode(true) ;
   184 // afterStartElt.id = CY.guid() ;
   184 // afterStartElt.id = CY.guid() ;
   185 // was replaced with :
   185 // was replaced with :
   186 // afterStartElt = _yuiCloneNode(startElt) ;
   186 // afterStartElt = _yuiCloneNode(startElt) ;
   187 _yuiCloneNode = function (srcElt) {
   187 _yuiCloneNode = function (srcElt) {
   188 	var ret = CY.Node.getDOMNode(CY.get('#'+srcElt.id).cloneNode(true)) ;
   188   var ret = CY.Node.getDOMNode(CY.get('#'+srcElt.id).cloneNode(true)) ;
   189 	ret.id = CY.guid();
   189   ret.id = CY.guid();
   190 	return ret ;
   190   return ret ;
   191 } ;
   191 } ;
   192 
   192 
   193 // will wrap textNodes into c-c spans going up the DOM tree from elt to ancestor
   193 // will wrap textNodes into c-c spans going up the DOM tree from elt to ancestor
   194 // textNodes impacted here will be those that are :
   194 // textNodes impacted here will be those that are :
   195 // the same generation or older than elt (but elt is excluded)
   195 // the same generation or older than elt (but elt is excluded)
   199 // 2 elt is a textNode.
   199 // 2 elt is a textNode.
   200 // argumentss :
   200 // argumentss :
   201 // prev : will spannify previous siblings if true, next siblings otherwise
   201 // prev : will spannify previous siblings if true, next siblings otherwise
   202 _dynSpanToAnc = function (elt, ancestor, commentId, prev) {
   202 _dynSpanToAnc = function (elt, ancestor, commentId, prev) {
   203 // log('in : _dynSpanToAnc, elt : ' + elt.id) ;
   203 // log('in : _dynSpanToAnc, elt : ' + elt.id) ;
   204 	var c = elt ;
   204   var c = elt ;
   205     while ((c != null) && (c !== ancestor) && (c.parentNode !== ancestor)) {
   205     while ((c != null) && (c !== ancestor) && (c.parentNode !== ancestor)) {
   206 		var c_sib = null ;
   206     var c_sib = null ;
   207 		if (prev) {
   207     if (prev) {
   208 			c_sib = c.previousSibling ;
   208       c_sib = c.previousSibling ;
   209 		}
   209     }
   210 		else {
   210     else {
   211 			c_sib = c.nextSibling ;
   211       c_sib = c.nextSibling ;
   212 		}
   212     }
   213 		
   213     
   214 		if (c_sib == null) {
   214     if (c_sib == null) {
   215 			c = c.parentNode ;
   215       c = c.parentNode ;
   216 		}
   216     }
   217 		else {
   217     else {
   218 			c = c_sib ;			
   218       c = c_sib ;     
   219 			_recAddComment(c, commentId) ;
   219       _recAddComment(c, commentId) ;
   220 		}
   220     }
   221 	} ;
   221   } ;
   222 } ;
   222 } ;
   223 
   223 
   224 // between elt1 and elt2 (which are excluded)
   224 // between elt1 and elt2 (which are excluded)
   225 _dynSpanInBetween = function (anc, elt1, elt2, commentId) {
   225 _dynSpanInBetween = function (anc, elt1, elt2, commentId) {
   226 	var a = elt1 ;
   226   var a = elt1 ;
   227 	var elt1Anc = null ;
   227   var elt1Anc = null ;
   228     while (a) {
   228     while (a) {
   229         if (a.parentNode === anc) {
   229         if (a.parentNode === anc) {
   230         	elt1Anc = a ;
   230           elt1Anc = a ;
   231         	break;
   231           break;
   232         }
   232         }
   233         a = a.parentNode;
   233         a = a.parentNode;
   234     }
   234     }
   235 	if (elt1Anc != null) {
   235   if (elt1Anc != null) {
   236 		a = elt2 ;
   236     a = elt2 ;
   237 		var elt2Anc = null ;
   237     var elt2Anc = null ;
   238 	    while (a) {
   238       while (a) {
   239 	        if (a.parentNode === anc) {
   239           if (a.parentNode === anc) {
   240 	        	elt2Anc = a ;
   240             elt2Anc = a ;
   241 	        	break;
   241             break;
   242 	        }
   242           }
   243 	        a = a.parentNode;
   243           a = a.parentNode;
   244 	    }
   244       }
   245 		if (elt2Anc != null) { // found both ancestor, now doing the work
   245     if (elt2Anc != null) { // found both ancestor, now doing the work
   246 			a = elt1Anc.nextSibling ;
   246       a = elt1Anc.nextSibling ;
   247 			while ((a != null) && (a !== elt2Anc)) {
   247       while ((a != null) && (a !== elt2Anc)) {
   248 				_recAddComment(a, commentId) ;
   248         _recAddComment(a, commentId) ;
   249 				a = a.nextSibling ;
   249         a = a.nextSibling ;
   250 			}
   250       }
   251 		}
   251     }
   252 	}
   252   }
   253 } ;
   253 } ;
   254 
   254 
   255 // (copied from YUI dom-base)
   255 // (copied from YUI dom-base)
   256 _bruteContains = function(element, needle) {
   256 _bruteContains = function(element, needle) {
   257     while (needle) {
   257     while (needle) {
   263     return false;
   263     return false;
   264 },
   264 },
   265 
   265 
   266 //elt is supposed to be c-c classed
   266 //elt is supposed to be c-c classed
   267 _addIdClass = function (elt, commentId) {
   267 _addIdClass = function (elt, commentId) {
   268 	CY.DOM.addClass(elt, 'c-id-' + commentId) ;
   268   CY.DOM.addClass(elt, 'c-id-' + commentId) ;
   269 	_updateCommentCounter(elt) ;
   269   _updateCommentCounter(elt) ;
   270 } ;
   270 } ;
   271 
   271 
   272 //elt is supposed to be c-c classed
   272 //elt is supposed to be c-c classed
   273 _removeIdClass = function (elt, commentId) {
   273 _removeIdClass = function (elt, commentId) {
   274 	CY.DOM.removeClass(elt, 'c-id-' + commentId) ;
   274   CY.DOM.removeClass(elt, 'c-id-' + commentId) ;
   275 	_updateCommentCounter(elt) ;
   275   _updateCommentCounter(elt) ;
   276 } ;
   276 } ;
   277 
   277 
   278 //elt is supposed to be c-c classed
   278 //elt is supposed to be c-c classed
   279 _removeIdClasses = function (elt) {
   279 _removeIdClasses = function (elt) {
   280 	var re = _cgetRegExp('(?:^|\\s+)c-id-(?:\\d+)', 'g');
   280   var re = _cgetRegExp('(?:^|\\s+)c-id-(?:\\d+)', 'g');
   281 	elt['className'] = elt['className'].replace(re, " ") ;
   281   elt['className'] = elt['className'].replace(re, " ") ;
   282 	_updateCommentCounter(elt) ;
   282   _updateCommentCounter(elt) ;
   283 } ;
   283 } ;
   284 
   284 
   285 _recAddComment = function (elt, commentId) {
   285 _recAddComment = function (elt, commentId) {
   286 	if (CY.DOM.hasClass(elt, 'c-c')) {
   286   if (CY.DOM.hasClass(elt, 'c-c')) {
   287 		_addIdClass(elt, commentId) ;
   287     _addIdClass(elt, commentId) ;
   288 	}
   288   }
   289 	else {
   289   else {
   290 		var c = elt.firstChild ;
   290     var c = elt.firstChild ;
   291         while (c != null) {
   291         while (c != null) {
   292         	_recAddComment(c, commentId) ;
   292           _recAddComment(c, commentId) ;
   293 			c = c.nextSibling ;
   293       c = c.nextSibling ;
   294         }
   294         }
   295     }
   295     }
   296 } ;
   296 } ;
   297 
   297 
   298 // might be expensive ... (? maybe should use contains when available, instead
   298 // might be expensive ... (? maybe should use contains when available, instead
   299 // of custom _bruteContains)
   299 // of custom _bruteContains)
   300 _findCommonAncestor = function (elt1, elt2) {
   300 _findCommonAncestor = function (elt1, elt2) {
   301 	if (_bruteContains(elt1, elt2))
   301   if (_bruteContains(elt1, elt2))
   302 		return elt1 ;
   302     return elt1 ;
   303 	else {
   303   else {
   304 		var e = elt2 ;
   304     var e = elt2 ;
   305 		while ((e != null) && !_bruteContains(e, elt1)) {
   305     while ((e != null) && !_bruteContains(e, elt1)) {
   306 			e = e.parentNode ; 
   306       e = e.parentNode ; 
   307 		}
   307     }
   308 		return e ;
   308     return e ;
   309 	}
   309   }
   310 } ;
   310 } ;
   311 
   311 
   312 _cregexCache = {} ;
   312 _cregexCache = {} ;
   313 // inspired (copied) from dom-base-debug in yui
   313 // inspired (copied) from dom-base-debug in yui
   314 _cgetRegExp = function(str, flags) {
   314 _cgetRegExp = function(str, flags) {
   320 } ;
   320 } ;
   321 
   321 
   322 //c-c should be classed with a c-count-x where x is a number for color graduation
   322 //c-c should be classed with a c-count-x where x is a number for color graduation
   323 //c-c should be classed with many c-id-xid where xid is the comment db id of comment that apply to it
   323 //c-c should be classed with many c-id-xid where xid is the comment db id of comment that apply to it
   324 _updateCommentCounter = function (elt) {
   324 _updateCommentCounter = function (elt) {
   325 	var re = _cgetRegExp('(?:^|\\s+)c-id-(?:\\d+)', 'g');
   325   var re = _cgetRegExp('(?:^|\\s+)c-id-(?:\\d+)', 'g');
   326 	var matches = elt['className'].match(re);
   326   var matches = elt['className'].match(re);
   327 	var countIds = (matches == null) ? 0 : matches.length ;
   327   var countIds = (matches == null) ? 0 : matches.length ;
   328 	
   328   
   329 	re = _cgetRegExp('(?:^|\\s+)c-count-(?:\\d+)', 'g');
   329   re = _cgetRegExp('(?:^|\\s+)c-count-(?:\\d+)', 'g');
   330 	elt['className'] = elt['className'].replace(re, " ") ;
   330   elt['className'] = elt['className'].replace(re, " ") ;
   331 	CY.DOM.addClass(elt, 'c-count-'+countIds+' ') ;
   331   CY.DOM.addClass(elt, 'c-count-'+countIds+' ') ;
   332 } ;
   332 } ;
   333 
   333 
   334 _convertSelectionFromCCToCS = function (sel) {
   334 _convertSelectionFromCCToCS = function (sel) {
   335 	var offset = sel['offset'] ;
   335   var offset = sel['offset'] ;
   336 	var elt = sel['elt'].parentNode ;
   336   var elt = sel['elt'].parentNode ;
   337 	
   337   
   338 	var e = sel['elt'].previousSibling ;
   338   var e = sel['elt'].previousSibling ;
   339 	while (e != null) {
   339   while (e != null) {
   340 		offset += _getTextNodeContent(e).length ;
   340     offset += _getTextNodeContent(e).length ;
   341 		e = e.previousSibling ; // will be a c-c !!
   341     e = e.previousSibling ; // will be a c-c !!
   342 	}
   342   }
   343 	
   343   
   344 	return  {'elt':elt, 'offset':offset} ;
   344   return  {'elt':elt, 'offset':offset} ;
   345 } ;
   345 } ;
   346 
   346 
   347 _convertSelectionFromCSToCC = function (sel) {
   347 _convertSelectionFromCSToCC = function (sel) {
   348 	var ret = {'elt':null, 'offset':-1} ;
   348   var ret = {'elt':null, 'offset':-1} ;
   349 	
   349   
   350 	var cc = null ;
   350   var cc = null ;
   351 	var ccElt = sel['elt'].firstChild ;
   351   var ccElt = sel['elt'].firstChild ;
   352 	var length = 0 ;
   352   var length = 0 ;
   353 	while (ccElt != null) {
   353   while (ccElt != null) {
   354 		var prevLength = length ;
   354     var prevLength = length ;
   355 		length += _getTextNodeContent(ccElt).length ;
   355     length += _getTextNodeContent(ccElt).length ;
   356 		if (length >= sel['offset']) {
   356     if (length >= sel['offset']) {
   357 			ret['elt'] = ccElt ;
   357       ret['elt'] = ccElt ;
   358 			ret['offset'] = sel['offset'] - prevLength ;
   358       ret['offset'] = sel['offset'] - prevLength ;
   359 			break ;
   359       break ;
   360 		}
   360     }
   361 		ccElt = ccElt.nextSibling ; // will be a c-c !!
   361     ccElt = ccElt.nextSibling ; // will be a c-c !!
   362 	}
   362   }
   363 	return ret ;
   363   return ret ;
   364 } ;
   364 } ;
   365 
   365 
   366 
   366 
   367 /*******************************************************************************/
   367 /*******************************************************************************/
   368 /* SCOPE REMOVAL */
   368 /* SCOPE REMOVAL */
   369 /*******************************************************************************/
   369 /*******************************************************************************/
   370 
   370 
   371 unpaintCommentScope = function(comment) {
   371 unpaintCommentScope = function(comment) {
   372     var dbId = comment.id;
   372     var dbId = comment.id;
   373 
   373 
   374 	var classeId = 'c-id-' + dbId ;
   374   var classeId = 'c-id-' + dbId ;
   375 	var toBeRemovedElts = [] ;
   375   var toBeRemovedElts = [] ;
   376 
   376 
   377 	var cNodeList = CY.all("."+classeId) ;
   377   var cNodeList = CY.all("."+classeId) ;
   378 	if (cNodeList != null) { // null in case of a reply ...
   378   if (cNodeList != null) { // null in case of a reply ...
   379 		for (var i = 0, ilen = cNodeList.size() ; i < ilen ; i++)  {
   379     for (var i = 0, ilen = cNodeList.size() ; i < ilen ; i++)  {
   380 			var c = cNodeList.item(i) ;
   380       var c = cNodeList.item(i) ;
   381 			if (c.hasClass('c-c')) { // always will !!
   381       if (c.hasClass('c-c')) { // always will !!
   382 				var cElt = CY.Node.getDOMNode(c) ;
   382         var cElt = CY.Node.getDOMNode(c) ;
   383 				_removeIdClass(cElt, dbId) ;
   383         _removeIdClass(cElt, dbId) ;
   384 				
   384         
   385 				var cIds = getCommentIdsFromClasses(cElt) ;
   385         var cIds = getCommentIdsFromClasses(cElt) ;
   386 				quicksort(cIds) ;
   386         quicksort(cIds) ;
   387 				
   387         
   388 				var p = c.get('previousSibling') ;
   388         var p = c.get('previousSibling') ;
   389 				if (p != null) {
   389         if (p != null) {
   390 					var pElt = CY.Node.getDOMNode(p) ;
   390           var pElt = CY.Node.getDOMNode(p) ;
   391 					var pIds = getCommentIdsFromClasses(pElt) ; 
   391           var pIds = getCommentIdsFromClasses(pElt) ; 
   392 					quicksort(pIds) ;
   392           quicksort(pIds) ;
   393 					if (areSortedArraysEqual(cIds, pIds)) {
   393           if (areSortedArraysEqual(cIds, pIds)) {
   394 						_setTextNodeContent(cElt, _getTextNodeContent(pElt) + _getTextNodeContent(cElt)) ;						
   394             _setTextNodeContent(cElt, _getTextNodeContent(pElt) + _getTextNodeContent(cElt)) ;            
   395 						toBeRemovedElts.push(pElt) ;
   395             toBeRemovedElts.push(pElt) ;
   396 					}
   396           }
   397 				}
   397         }
   398 				
   398         
   399 				var n = c.get('nextSibling') ;
   399         var n = c.get('nextSibling') ;
   400 				if (n != null) {
   400         if (n != null) {
   401 					var nElt = CY.Node.getDOMNode(n) ;
   401           var nElt = CY.Node.getDOMNode(n) ;
   402 					var nIds = getCommentIdsFromClasses(nElt) ; 
   402           var nIds = getCommentIdsFromClasses(nElt) ; 
   403 					quicksort(nIds) ;
   403           quicksort(nIds) ;
   404 					if (areSortedArraysEqual(cIds, nIds)) {
   404           if (areSortedArraysEqual(cIds, nIds)) {
   405 						cElt.firstChild.data = cElt.firstChild.data + nElt.firstChild.data; 
   405             cElt.firstChild.data = cElt.firstChild.data + nElt.firstChild.data; 
   406 						toBeRemovedElts.push(nElt) ;
   406             toBeRemovedElts.push(nElt) ;
   407 					}
   407           }
   408 				}
   408         }
   409 			}
   409       }
   410 			else {
   410       else {
   411 				alert('HAS NO c-c ? : ' + commentNode.get('id') + " , innerHTML :" + commentNode.get('innerHTML')) ;
   411         alert('HAS NO c-c ? : ' + commentNode.get('id') + " , innerHTML :" + commentNode.get('innerHTML')) ;
   412 				return ;
   412         return ;
   413 			}
   413       }
   414 		}
   414     }
   415 	}
   415   }
   416 	for (var i = 0, ilen = toBeRemovedElts.length ; i < ilen ; i++)  {
   416   for (var i = 0, ilen = toBeRemovedElts.length ; i < ilen ; i++)  {
   417 		toBeRemovedElts[i].parentNode.removeChild(toBeRemovedElts[i]) ;
   417     toBeRemovedElts[i].parentNode.removeChild(toBeRemovedElts[i]) ;
   418 	}
   418   }
   419 } ;
   419 } ;
   420 
   420 
   421 // not related to the unpaintCommentScope function (faster)
   421 // not related to the unpaintCommentScope function (faster)
   422 unpaintAllComments = function() {
   422 unpaintAllComments = function() {
   423 	var cNodeList= CY.all(".c-s") ;
   423   var cNodeList= CY.all(".c-s") ;
   424 	var toBeRemovedElts = [] ;
   424   var toBeRemovedElts = [] ;
   425 	for (var i = 0, ilen = cNodeList.size() ; i < ilen ; i++)  {
   425   for (var i = 0, ilen = cNodeList.size() ; i < ilen ; i++)  {
   426 		var c = cNodeList.item(i) ;
   426     var c = cNodeList.item(i) ;
   427 		
   427     
   428 		// remove Classes
   428     // remove Classes
   429 		var fc = c.get('firstChild') ;
   429     var fc = c.get('firstChild') ;
   430 		var fcElt = CY.Node.getDOMNode(c.get('firstChild')) ;
   430     var fcElt = CY.Node.getDOMNode(c.get('firstChild')) ;
   431 		_removeIdClasses(fcElt) ;
   431     _removeIdClasses(fcElt) ;
   432 		
   432     
   433 		// merge nodes
   433     // merge nodes
   434 		var n = fc.get('nextSibling') ;
   434     var n = fc.get('nextSibling') ;
   435 		while (n != null)  {
   435     while (n != null)  {
   436 			var nElt = CY.Node.getDOMNode(n) ;
   436       var nElt = CY.Node.getDOMNode(n) ;
   437 			fcElt.firstChild.data = fcElt.firstChild.data + nElt.firstChild.data; 
   437       fcElt.firstChild.data = fcElt.firstChild.data + nElt.firstChild.data; 
   438 			toBeRemovedElts.push(nElt) ;
   438       toBeRemovedElts.push(nElt) ;
   439 			n = n.get('nextSibling') ;
   439       n = n.get('nextSibling') ;
   440 		}
   440     }
   441 	}
   441   }
   442 	for (var i = 0, ilen = toBeRemovedElts.length ; i < ilen ; i++)  {
   442   for (var i = 0, ilen = toBeRemovedElts.length ; i < ilen ; i++)  {
   443 		toBeRemovedElts[i].parentNode.removeChild(toBeRemovedElts[i]) ;
   443     toBeRemovedElts[i].parentNode.removeChild(toBeRemovedElts[i]) ;
   444 	}
   444   }
   445 
   445 
   446 } ;
   446 } ;
   447 
   447 
   448 showScope = function(commentDbId) {
   448 showScope = function(commentDbId) {
   449 	var s = CY.all('.c-id-' + commentDbId); 
   449   var s = CY.all('.c-id-' + commentDbId); 
   450 	if (s != null)
   450   if (s != null)
   451 		s.addClass('c-scope') ;
   451     s.addClass('c-scope') ;
   452 } ;
   452 } ;
   453 
   453 
   454 hideScopeAnyway = function() {
   454 hideScopeAnyway = function() {
   455 	var s = CY.all('.c-scope'); 
   455   var s = CY.all('.c-scope'); 
   456 	if (s != null)
   456   if (s != null)
   457 		s.removeClass('c-scope') ;
   457     s.removeClass('c-scope') ;
   458 }
   458 }
   459 
   459