src/cm/media/js/client/c_sync.js
changeset 341 053551f213fb
parent 339 0508284129cf
child 375 d6439b3eb2de
equal deleted inserted replaced
340:9e2b9e568e42 341:053551f213fb
     1 gShowingAllComments = false ;
     1 gShowingAllComments = false ;
     2 // YUI : queue, overlay
     2 // YUI : queue, overlay
     3 Sync = function() {
     3 Sync = function() {
     4 	// this queue handles both animations and io requests
     4   // this queue handles both animations and io requests
     5 	this._q = null ;
     5   this._q = null ;
     6 	
     6   
     7 	this._iPreventClick = false ; // oh really ?
     7   this._iPreventClick = false ; // oh really ?
     8 }
     8 }
     9 
     9 
    10 Sync.prototype = {
    10 Sync.prototype = {
    11 	init : function (iComment) {
    11   init : function (iComment) {
    12 	this._q = new CY.AsyncQueue() ;
    12   this._q = new CY.AsyncQueue() ;
    13 // pr2 this._q = new CY.Queue() ;
    13 // pr2 this._q = new CY.Queue() ;
    14 	},
    14   },
    15 	
    15   
    16 	setPreventClickOn : function () {
    16   setPreventClickOn : function () {
    17 		CY.log("setPreventClickOn !") ;
    17     CY.log("setPreventClickOn !") ;
    18 		if (gLayout.isInFrame())
    18     if (gLayout.isInFrame())
    19 			parent.f_interfaceFreeze()		
    19       parent.f_interfaceFreeze()    
    20 		this._iPreventClick = true ;
    20     this._iPreventClick = true ;
    21 	},
    21   },
    22 
    22 
    23 	setPreventClickOff : function () {
    23   setPreventClickOff : function () {
    24 		CY.log("setPreventClickOff !") ;
    24     CY.log("setPreventClickOff !") ;
    25 		if (gLayout.isInFrame())
    25     if (gLayout.isInFrame())
    26 			parent.f_interfaceUnfreeze()		
    26       parent.f_interfaceUnfreeze()    
    27 		this._iPreventClick = false ;
    27     this._iPreventClick = false ;
    28 	},
    28   },
    29 
    29 
    30 	removeCommentRet : function(args) {
    30   removeCommentRet : function(args) {
    31 		var successfull = args['successfull'] ;
    31     var successfull = args['successfull'] ;
    32 		
    32     
    33 		var iComment = (successfull) ? args['failure']['iComment'] : args['success']['iComment'] ;
    33     var iComment = (successfull) ? args['failure']['iComment'] : args['success']['iComment'] ;
    34 		
    34     
    35 		if (successfull) {
    35     if (successfull) {
    36 			var filterData = args['returned']['filterData'] ;
    36       var filterData = args['returned']['filterData'] ;
    37 			if (gLayout.isInFrame()) {
    37       if (gLayout.isInFrame()) {
    38 				parent.f_updateFilterData(filterData) ;
    38         parent.f_updateFilterData(filterData) ;
    39 			}
    39       }
    40 			
    40       
    41 			var y = gIComments.getTopPosition()[1] ;
    41       var y = gIComments.getTopPosition()[1] ;
    42 			
    42       
    43 			var comment = gDb.getComment(iComment.commentId) ;
    43       var comment = gDb.getComment(iComment.commentId) ;
    44 			this._q.add(
    44       this._q.add(
    45 		            function(){
    45                 function(){
    46 		            	
    46                   
    47 		    	    	unpaintCommentScope(comment) ;
    47                 unpaintCommentScope(comment) ;
    48 		    	    	gIComments.close(comment.id) ;
    48                 gIComments.close(comment.id) ;
    49 		    	    	gIComments.remove(comment.id) ;
    49                 gIComments.remove(comment.id) ;
    50 		    	    	if (comment.reply_to_id != null)
    50                 if (comment.reply_to_id != null)
    51 		    	    		gIComments.refresh(comment.reply_to_id) ;
    51                   gIComments.refresh(comment.reply_to_id) ;
    52 		    	    	
    52                 
    53 		    	    	gDb.del(comment) ;
    53                 gDb.del(comment) ;
    54 		    	    	
    54                 
    55 		    	    	if (gLayout.isInFrame()) {
    55                 if (gLayout.isInFrame()) {
    56 		    		    	if (gDb.comments.length == 0 && gDb.allComments.length != 0) {
    56                   if (gDb.comments.length == 0 && gDb.allComments.length != 0) {
    57 		    		    		parent.f_enqueueMsg(gettext("no filtered comments left")) ;
    57                     parent.f_enqueueMsg(gettext("no filtered comments left")) ;
    58 		    					parent.resetFilter() ;  
    58                   parent.resetFilter() ;  
    59 		    		    	}
    59                   }
    60 		    		    	else {
    60                   else {
    61 		    					// just counting here ...
    61                   // just counting here ...
    62 		    					var filterRes = gDb.computeFilterResults() ;
    62                   var filterRes = gDb.computeFilterResults() ;
    63 		    					updateFilterResultsCount(filterRes['nbDiscussions'], filterRes['nbComments'], filterRes['nbReplies']) ;
    63                   updateFilterResultsCount(filterRes['nbDiscussions'], filterRes['nbComments'], filterRes['nbReplies']) ;
    64 		    		    	}
    64                   }
    65 		    	    	}
    65                 }
    66 		            }
    66                 }
    67 			);
    67       );
    68 			
    68       
    69 			this._animateTo(y) ;		
    69       this._animateTo(y) ;    
    70 		}
    70     }
    71 		this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
    71     this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
    72 		this.resume() ;
    72     this.resume() ;
    73 	},
    73   },
    74 	
    74   
    75 	moderateCommentRet : function(args) {
    75   moderateCommentRet : function(args) {
    76 		var successfull = args['successfull'] ;
    76     var successfull = args['successfull'] ;
    77 
    77 
    78 		var iComment = (successfull) ? args['failure']['iComment'] : args['success']['iComment'] ;
    78     var iComment = (successfull) ? args['failure']['iComment'] : args['success']['iComment'] ;
    79 
    79 
    80 		if (successfull) {
    80     if (successfull) {
    81 			var ret = args['returned'] ;
    81       var ret = args['returned'] ;
    82 			var comment = ret['comment'] ;
    82       var comment = ret['comment'] ;
    83 
    83 
    84 			gDb.upd(comment) ;
    84       gDb.upd(comment) ;
    85 			
    85       
    86 			var shouldReset = gLayout.isInFrame() && !parent.f_isFrameFilterFieldsInit() ;
    86       var shouldReset = gLayout.isInFrame() && !parent.f_isFrameFilterFieldsInit() ;
    87 			if (shouldReset){
    87       if (shouldReset){
    88 				parent.resetFilter() ;
    88         parent.resetFilter() ;
    89 				this._showSingleComment(comment) ;
    89         this._showSingleComment(comment) ;
    90 			}
    90       }
    91 			else 
    91       else 
    92 				iComment.changeModeration(comment) ;
    92         iComment.changeModeration(comment) ;
    93 		}
    93     }
    94 
    94 
    95 		this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
    95     this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
    96 		this.resume() ;
    96     this.resume() ;
    97 	},
    97   },
    98 	
    98   
    99 	saveCommentRet : function(args) {
    99   saveCommentRet : function(args) {
   100 		var successfull = args['successfull'] ;
   100     var successfull = args['successfull'] ;
   101 		if (successfull) {
   101     if (successfull) {
   102 			var formId = args['success']['formId'] ;
   102       var formId = args['success']['formId'] ;
   103 			var ret = args['returned'] ;
   103       var ret = args['returned'] ;
   104 		
   104     
   105 			removeFormErrMsg(formId) ;
   105       removeFormErrMsg(formId) ;
   106 		
   106     
   107 			if ('errors' in ret) { // validation error
   107       if ('errors' in ret) { // validation error
   108 				var errors = ret['errors'] ;
   108         var errors = ret['errors'] ;
   109 				for (var eltName in errors) {
   109         for (var eltName in errors) {
   110 					addFormErrMsg(formId, eltName, errors[eltName]) ;
   110           addFormErrMsg(formId, eltName, errors[eltName]) ;
   111 				}
   111         }
   112 				this._animateToTop() ;
   112         this._animateToTop() ;
   113 			}
   113       }
   114 			else {
   114       else {
   115 				var isReply = function() {return (gNewReply != null) && (formId == gNewReply['ids']['formId']) ;} ;
   115         var isReply = function() {return (gNewReply != null) && (formId == gNewReply['ids']['formId']) ;} ;
   116 				var isNewComment = function() {return (gICommentForm != null) && (formId == gICommentForm['formId']) ;} ;
   116         var isNewComment = function() {return (gICommentForm != null) && (formId == gICommentForm['formId']) ;} ;
   117 				var isEdit = function() {return (gEdit != null) && (formId == gEdit['ids']['formId']) ;} ;
   117         var isEdit = function() {return (gEdit != null) && (formId == gEdit['ids']['formId']) ;} ;
   118 				
   118         
   119 				// doing this here for the a priori moderation case
   119         // doing this here for the a priori moderation case
   120 				if (isNewComment())
   120         if (isNewComment())
   121 					this.hideICommentForm(cleanICommentForm()) ;
   121           this.hideICommentForm(cleanICommentForm()) ;
   122 				else if (isEdit())
   122         else if (isEdit())
   123 					this._hideEditForm() ;
   123           this._hideEditForm() ;
   124 				else if (isReply())
   124         else if (isReply())
   125 					this._hideNewReplyForm() ;
   125           this._hideNewReplyForm() ;
   126 				
   126         
   127 				if ("ask_for_notification" in ret) {  
   127         if ("ask_for_notification" in ret) {  
   128 					if (ret['ask_for_notification']) {
   128           if (ret['ask_for_notification']) {
   129 						// TODO ask for notification ...or use AUTO_CONTRIB ?
   129             // TODO ask for notification ...or use AUTO_CONTRIB ?
   130 						parent.f_yesNoDialog(gettext("Do you want to be notified of all replies in all discussions you participated in?"), gettext("Reply notification"), 
   130             parent.f_yesNoDialog(gettext("Do you want to be notified of all replies in all discussions you participated in?"), gettext("Reply notification"), 
   131 							function() { // special case : no waiting for the return, no error check, nothing !
   131               function() { // special case : no waiting for the return, no error check, nothing !
   132 									var cfg = {
   132                   var cfg = {
   133 									method: "POST", 
   133                   method: "POST", 
   134 									data: urlEncode({'fun':'ownNotify', 'key':sv_key, 'version_key':sv_version_key, 'email':ret['email'], 'active':false}) 
   134                   data: urlEncode({'fun':'ownNotify', 'key':sv_key, 'version_key':sv_version_key, 'email':ret['email'], 'active':false}) 
   135 								} ; 
   135                 } ; 
   136 								CY.io(sv_client_url, cfg);
   136                 CY.io(sv_client_url, cfg);
   137 							}, this, null,
   137               }, this, null,
   138 							function() { // special case : no waiting for the return, no error check, nothing !
   138               function() { // special case : no waiting for the return, no error check, nothing !
   139 									var cfg = {
   139                   var cfg = {
   140 									method: "POST", 
   140                   method: "POST", 
   141 									data: urlEncode({'fun':'ownNotify', 'key':sv_key, 'version_key':sv_version_key, 'email':ret['email'], 'active':true}) 
   141                   data: urlEncode({'fun':'ownNotify', 'key':sv_key, 'version_key':sv_version_key, 'email':ret['email'], 'active':true}) 
   142 								} ; 
   142                 } ; 
   143 								CY.io(sv_client_url, cfg);
   143                 CY.io(sv_client_url, cfg);
   144 							}, this, null) ;
   144               }, this, null) ;
   145 					}
   145           }
   146 				}
   146         }
   147 					
   147           
   148 				
   148         
   149 				if ("comment" in ret) { // won't be when add with a priori moderation
   149         if ("comment" in ret) { // won't be when add with a priori moderation
   150 					var comment = ret['comment'] ;
   150           var comment = ret['comment'] ;
   151 	
   151   
   152 					gDb.upd(comment) ;
   152           gDb.upd(comment) ;
   153 	
   153   
   154 					var shouldReset = gLayout.isInFrame() && !parent.f_isFrameFilterFieldsInit() ;
   154           var shouldReset = gLayout.isInFrame() && !parent.f_isFrameFilterFieldsInit() ;
   155 					if (shouldReset)
   155           if (shouldReset)
   156 						parent.resetFilter() ;
   156             parent.resetFilter() ;
   157 					else { // ASSUMING filter is in init state ! (because when not // TODO $$$$$$$$$$$ this isn't true anymore .... when passing filter arguments in url !!
   157           else { // ASSUMING filter is in init state ! (because when not // TODO $$$$$$$$$$$ this isn't true anymore .... when passing filter arguments in url !!
   158 							// in frame for now data can't be filtered)
   158               // in frame for now data can't be filtered)
   159 						if (comment.reply_to_id == null) { // not a reply
   159             if (comment.reply_to_id == null) { // not a reply
   160 							unpaintCommentScope(comment) ; // for the edit case
   160               unpaintCommentScope(comment) ; // for the edit case
   161 							paintCommentScope(comment) ;
   161               paintCommentScope(comment) ;
   162 						}
   162             }
   163 					}
   163           }
   164 	
   164   
   165 					// UPDATE FILTER DATA // TODO move ????
   165           // UPDATE FILTER DATA // TODO move ????
   166 					var filterData = ret['filterData'] ;
   166           var filterData = ret['filterData'] ;
   167 					if (gLayout.isInFrame()) {
   167           if (gLayout.isInFrame()) {
   168 						parent.f_updateFilterData(filterData) ;
   168             parent.f_updateFilterData(filterData) ;
   169 						updateResetFilterResultsCount() ;				
   169             updateResetFilterResultsCount() ;       
   170 					}
   170           }
   171 
   171 
   172 					if (isReply()) { // add reply case
   172           if (isReply()) { // add reply case
   173 						if (!shouldReset) {
   173             if (!shouldReset) {
   174 							this._insertReply(comment) ;
   174               this._insertReply(comment) ;
   175 						}
   175             }
   176 					}
   176           }
   177 					else { // edit (reply or comment) or add (comment) case
   177           else { // edit (reply or comment) or add (comment) case
   178 				    	this._showSingleComment(comment) ;
   178               this._showSingleComment(comment) ;
   179 					}
   179           }
   180 				}
   180         }
   181 				else 
   181         else 
   182 					this._animateToTop() ;
   182           this._animateToTop() ;
   183 			}
   183       }
   184 
   184 
   185 		}
   185     }
   186 		else { // TODO ? ALL ret-FUNCTIONS ?
   186     else { // TODO ? ALL ret-FUNCTIONS ?
   187 			this._q.add({id:"expl", fn:function () {CY.log('in example .........') ;}}) ;
   187       this._q.add({id:"expl", fn:function () {CY.log('in example .........') ;}}) ;
   188 			this._q.promote("expl") ;
   188       this._q.promote("expl") ;
   189 		}
   189     }
   190 
   190 
   191 		this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   191     this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   192 		this.resume() ;
   192     this.resume() ;
   193 	},
   193   },
   194 	
   194   
   195 	example : function () {
   195   example : function () {
   196 		CY.log('in example .........') ;
   196     CY.log('in example .........') ;
   197 	},
   197   },
   198 
   198 
   199 	moderateComment	: function(iComment, state) {
   199   moderateComment : function(iComment, state) {
   200 		var comment = gDb.getComment(iComment['commentId']) ;
   200     var comment = gDb.getComment(iComment['commentId']) ;
   201         this._q.add(
   201         this._q.add(
   202 	            {fn:CY.bind(this.setPreventClickOn, this)},
   202               {fn:CY.bind(this.setPreventClickOn, this)},
   203 	            {autoContinue:false, fn:CY.bind(doExchange, null, "editComment", {'comment_key':comment.key, 'state':state}, null, this.moderateCommentRet, this, {'iComment':iComment}, gettext("could not save comment"))}
   203               {autoContinue:false, fn:CY.bind(doExchange, null, "editComment", {'comment_key':comment.key, 'state':state}, null, this.moderateCommentRet, this, {'iComment':iComment}, gettext("could not save comment"))}
   204 	            ).run();
   204               ).run();
   205 	},
   205   },
   206 	
   206   
   207 	_saveComment : function(serverFun, formId) {
   207   _saveComment : function(serverFun, formId) {
   208         this._q.add(
   208         this._q.add(
   209 	            {fn:CY.bind(this.setPreventClickOn, this)},
   209               {fn:CY.bind(this.setPreventClickOn, this)},
   210 	            {autoContinue:false, fn:CY.bind(doExchange, null, serverFun, {}, formId, this.saveCommentRet, this, {'formId':formId}, gettext("could not save comment"))}
   210               {autoContinue:false, fn:CY.bind(doExchange, null, serverFun, {}, formId, this.saveCommentRet, this, {'formId':formId}, gettext("could not save comment"))}
   211 	            ).run();
   211               ).run();
   212 	},
   212   },
   213 	
   213   
   214 	editComment : function() {
   214   editComment : function() {
   215 		this._saveComment("editComment", gEdit['ids']['formId']) ;
   215     this._saveComment("editComment", gEdit['ids']['formId']) ;
   216 	},
   216   },
   217 	
   217   
   218 	saveComment : function(formId) {
   218   saveComment : function(formId) {
   219 		this._saveComment("addComment", formId) ;
   219     this._saveComment("addComment", formId) ;
   220 	},
   220   },
   221 	
   221   
   222 	removeComment : function(iComment) {
   222   removeComment : function(iComment) {
   223 		checkForOpenedDialog(iComment, function() {
   223     checkForOpenedDialog(iComment, function() {
   224 			if (gLayout.isInFrame()) {
   224       if (gLayout.isInFrame()) {
   225 				parent.f_yesNoDialog(gettext("Are you sure you want to delete this comment?"), gettext("Warning"), function() { this.animateToTop() ;}, this, null, function() {
   225         parent.f_yesNoDialog(gettext("Are you sure you want to delete this comment?"), gettext("Warning"), function() { this.animateToTop() ;}, this, null, function() {
   226 					var comment = gDb.getComment(iComment.commentId) ;
   226           var comment = gDb.getComment(iComment.commentId) ;
   227 			        this._q.add(
   227               this._q.add(
   228 				            {fn:CY.bind(this.setPreventClickOn, this)},
   228                     {fn:CY.bind(this.setPreventClickOn, this)},
   229 				            {autoContinue:false, fn:CY.bind(doExchange, null, "removeComment", {'comment_key':comment.key}, null, this.removeCommentRet, this, {'iComment':iComment}, gettext("could not remove comment"))}
   229                     {autoContinue:false, fn:CY.bind(doExchange, null, "removeComment", {'comment_key':comment.key}, null, this.removeCommentRet, this, {'iComment':iComment}, gettext("could not remove comment"))}
   230 				            ).run();
   230                     ).run();
   231 				}, this, null) ;
   231         }, this, null) ;
   232 		        
   232             
   233 			}
   233       }
   234 //			else {
   234 //      else {
   235 //				alert("TODO : can't yet delete comments when not embed in text_view_frame because can't 'dialog' confirmation") ;
   235 //        alert("TODO : can't yet delete comments when not embed in text_view_frame because can't 'dialog' confirmation") ;
   236 //			}
   236 //      }
   237 		
   237     
   238 		}, this, null) ;
   238     }, this, null) ;
   239 	},
   239   },
   240 	
   240   
   241 	resume : function(commentDbIds, mouseXY) {
   241   resume : function(commentDbIds, mouseXY) {
   242 		this._q.run() ;
   242     this._q.run() ;
   243 	},
   243   },
   244 	
   244   
   245 	resetAutoContinue : function(callbackId) {
   245   resetAutoContinue : function(callbackId) {
   246 		this._q.getCallback(callbackId).autoContinue = true;
   246     this._q.getCallback(callbackId).autoContinue = true;
   247 	},
   247   },
   248 	
   248   
   249 	hideICommentForm : function(funObj) {
   249   hideICommentForm : function(funObj) {
   250 //		this._q.add({fn:function() {persistICommentFormValues();}}) ;
   250 //    this._q.add({fn:function() {persistICommentFormValues();}}) ;
   251 		this._q.add({autoContinue:false, fn:CY.bind(gICommentForm['animationHide'].run, gICommentForm['animationHide'])}) ;
   251     this._q.add({autoContinue:false, fn:CY.bind(gICommentForm['animationHide'].run, gICommentForm['animationHide'])}) ;
   252 //		this._q.add({fn:function() {cleanICommentForm();}}) ;
   252 //    this._q.add({fn:function() {cleanICommentForm();}}) ;
   253 		if (funObj)
   253     if (funObj)
   254 			this._q.add(funObj) ;
   254       this._q.add(funObj) ;
   255 	},
   255   },
   256 	
   256   
   257 	/* ANIMATION DRIVEN INTERFACE CHANGES */
   257   /* ANIMATION DRIVEN INTERFACE CHANGES */
   258 	
   258   
   259 	showCommentForm : function(iComment) {
   259   showCommentForm : function(iComment) {
   260 		checkForOpenedDialog(null, function() {
   260     checkForOpenedDialog(null, function() {
   261 	        this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   261           this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   262 			this._q.add({fn:function() {
   262       this._q.add({fn:function() {
   263 								if (iComment == null) {
   263                 if (iComment == null) {
   264 									var selection = getSelectionInfo() ;
   264                   var selection = getSelectionInfo() ;
   265 									updateICommentFormSelection(selection) ;
   265                   updateICommentFormSelection(selection) ;
   266 								}
   266                 }
   267 								showICommentForm(iComment);
   267                 showICommentForm(iComment);
   268 							}}) ;
   268               }}) ;
   269 			this._q.add({autoContinue:false, fn:CY.bind(gICommentForm['animationShow'].run, gICommentForm['animationShow'])},
   269       this._q.add({autoContinue:false, fn:CY.bind(gICommentForm['animationShow'].run, gICommentForm['animationShow'])},
   270 					{fn:CY.bind(this.setPreventClickOff, this)}
   270           {fn:CY.bind(this.setPreventClickOff, this)}
   271 					).run();
   271           ).run();
   272 		}, this, null) ;
   272     }, this, null) ;
   273 	},
   273   },
   274 	
   274   
   275 	showEditForm : function(iComment) {
   275   showEditForm : function(iComment) {
   276 		checkForOpenedDialog(null, function() {
   276     checkForOpenedDialog(null, function() {
   277 	        this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   277           this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   278 
   278 
   279 	        this._q.add({fn:function() {
   279           this._q.add({fn:function() {
   280 	        				showEditForm(iComment) ;
   280                   showEditForm(iComment) ;
   281 	        			}});
   281                 }});
   282 			this._animateToTop() ;
   282       this._animateToTop() ;
   283 			
   283       
   284 	        this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   284           this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   285 	        this._q.run() ;
   285           this._q.run() ;
   286 		}, this, null) ;
   286     }, this, null) ;
   287 	},
   287   },
   288 	
   288   
   289 	showReplyForm : function(iComment) {
   289   showReplyForm : function(iComment) {
   290 		checkForOpenedDialog(null, function() {
   290     checkForOpenedDialog(null, function() {
   291 	        this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   291           this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   292 
   292 
   293 	        this._q.add({fn:function() {
   293           this._q.add({fn:function() {
   294 	        					instanciateNewReplyForm(iComment) ;
   294                     instanciateNewReplyForm(iComment) ;
   295 	        					}});
   295                     }});
   296 			this._animateToTop() ;
   296       this._animateToTop() ;
   297 			
   297       
   298 	        this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   298           this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   299 	        this._q.run() ;
   299           this._q.run() ;
   300 		}, this, null) ;
   300     }, this, null) ;
   301 	},
   301   },
   302 	
   302   
   303 	cancelICommentForm : function() {
   303   cancelICommentForm : function() {
   304         this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   304         this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   305         
   305         
   306 //		this._q.add({fn:function() {cleanICommentForm();}}) ;
   306 //    this._q.add({fn:function() {cleanICommentForm();}}) ;
   307     	this.hideICommentForm() ;
   307       this.hideICommentForm() ;
   308     	
   308       
   309         this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   309         this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   310         this._q.run() ;
   310         this._q.run() ;
   311 	},
   311   },
   312 	cancelEdit : function() {
   312   cancelEdit : function() {
   313         this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   313         this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   314         
   314         
   315     	this._q.add({fn:function() {cancelEditForm();}}) ;
   315       this._q.add({fn:function() {cancelEditForm();}}) ;
   316     	this._animateToTop() ;
   316       this._animateToTop() ;
   317     	
   317       
   318         this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   318         this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   319         this._q.run() ;
   319         this._q.run() ;
   320 	},
   320   },
   321 	cancelReply : function() {
   321   cancelReply : function() {
   322         this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   322         this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   323         
   323         
   324     	this._q.add({fn:function() {cancelNewReplyForm();}}) ;
   324       this._q.add({fn:function() {cancelNewReplyForm();}}) ;
   325     	this._animateToTop() ;
   325       this._animateToTop() ;
   326     	
   326       
   327         this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   327         this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   328         this._q.run() ;
   328         this._q.run() ;
   329 	},
   329   },
   330 	changeScopeFormClick : function() {
   330   changeScopeFormClick : function() {
   331         this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   331         this._q.add({fn:CY.bind(this.setPreventClickOn, this)});
   332         
   332         
   333     	this._q.add({fn:function() {changeScopeFormClick();}}) ;
   333       this._q.add({fn:function() {changeScopeFormClick();}}) ;
   334     	this._animateToTop() ;
   334       this._animateToTop() ;
   335     	
   335       
   336         this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   336         this._q.add({fn:CY.bind(this.setPreventClickOff, this)});
   337         this._q.run() ;
   337         this._q.run() ;
   338 	},
   338   },
   339 	// this is invoked during queue execution
   339   // this is invoked during queue execution
   340 	_hideNewReplyForm : function() {
   340   _hideNewReplyForm : function() {
   341 		this._q.add({fn:function() {
   341     this._q.add({fn:function() {
   342 					cleanNewReplyForm() ; 
   342           cleanNewReplyForm() ; 
   343 					cancelNewReplyForm() ;}}) ;
   343           cancelNewReplyForm() ;}}) ;
   344 	},
   344   },
   345 	// this is invoked during queue execution
   345   // this is invoked during queue execution
   346 	_hideEditForm : function() {
   346   _hideEditForm : function() {
   347 		this._q.add({fn:function() {
   347     this._q.add({fn:function() {
   348 					cancelEditForm() ;}}) ;
   348           cancelEditForm() ;}}) ;
   349 	},
   349   },
   350 	// this is invoked during queue execution
   350   // this is invoked during queue execution
   351 	_insertReply : function(comment) {
   351   _insertReply : function(comment) {
   352 		this._q.add({fn:function() {
   352     this._q.add({fn:function() {
   353 					var parentComment = gDb.getComment(comment.reply_to_id) ;
   353           var parentComment = gDb.getComment(comment.reply_to_id) ;
   354 					var parentThread = gDb.getThreads([parentComment]) ;
   354           var parentThread = gDb.getThreads([parentComment]) ;
   355 					var previousComment = parentThread[parentThread.length - 2] ; // - 2 because now that comment has been added comment is parentThread[parentThread.length - 1]
   355           var previousComment = parentThread[parentThread.length - 2] ; // - 2 because now that comment has been added comment is parentThread[parentThread.length - 1]
   356 
   356 
   357 					var iComment = gIComments.insertAfter(previousComment, comment) ;
   357           var iComment = gIComments.insertAfter(previousComment, comment) ;
   358 					// iComment CAN'T BE NULL ! (TODO check that there is a
   358           // iComment CAN'T BE NULL ! (TODO check that there is a
   359 					// check server side that parent exists when adding a reply
   359           // check server side that parent exists when adding a reply
   360 					// !)
   360           // !)
   361 					
   361           
   362 					var parentPosition = gIComments.getPosition(comment.reply_to_id) ;
   362           var parentPosition = gIComments.getPosition(comment.reply_to_id) ;
   363 					iComment.setPosition(parentPosition) ;
   363           iComment.setPosition(parentPosition) ;
   364 					
   364           
   365 					// check if activation is necessary (will always be ?)
   365           // check if activation is necessary (will always be ?)
   366 					var comment_path = gDb.getPath(comment) ;
   366           var comment_path = gDb.getPath(comment) ;
   367 					var topComment = comment_path[comment_path.length - 1] ;
   367           var topComment = comment_path[comment_path.length - 1] ;
   368 					if (gIComments.isTopActive(topComment.id))
   368           if (gIComments.isTopActive(topComment.id))
   369 						iComment.activate() ;
   369             iComment.activate() ;
   370 
   370 
   371 					iComment.show() ;}}) ;
   371           iComment.show() ;}}) ;
   372     	this._animateToTop() ;
   372       this._animateToTop() ;
   373 	},
   373   },
   374 	_showSingleComment : function(comment) {
   374   _showSingleComment : function(comment) {
   375 		if (comment != null) {
   375     if (comment != null) {
   376 			var path = gDb.getPath(comment) ;
   376       var path = gDb.getPath(comment) ;
   377 			var topAncestorComment = path[path.length - 1] ;
   377       var topAncestorComment = path[path.length - 1] ;
   378 			var topY = 0 ;
   378       var topY = 0 ;
   379 			if (comment['start_wrapper'] != -1) 
   379       if (comment['start_wrapper'] != -1) 
   380 				topY = CY.get(".c-id-"+topAncestorComment.id).getY() ;
   380         topY = CY.get(".c-id-"+topAncestorComment.id).getY() ;
   381 			else 
   381       else 
   382 				topY = CY.get('document').get('scrollTop') ;
   382         topY = CY.get('document').get('scrollTop') ;
   383 			
   383       
   384 			this._showComments([topAncestorComment.id], topY, false) ;
   384       this._showComments([topAncestorComment.id], topY, false) ;
   385 			// optim when browsing comments with no reply			
   385       // optim when browsing comments with no reply     
   386 			if (topAncestorComment.replies.length > 0)
   386       if (topAncestorComment.replies.length > 0)
   387 				this._animateTo(topY) ;
   387         this._animateTo(topY) ;
   388 		}
   388     }
   389 	},
   389   },
   390 	_showFocusSingleComment : function(topComment, focusComment, reply) {
   390   _showFocusSingleComment : function(topComment, focusComment, reply) {
   391 		if (topComment != null) {
   391     if (topComment != null) {
   392 			var topY = 0 ;
   392       var topY = 0 ;
   393 			if (topComment['start_wrapper'] != -1) 
   393       if (topComment['start_wrapper'] != -1) 
   394 				topY = CY.get(".c-id-"+topComment.id).getY() ;
   394         topY = CY.get(".c-id-"+topComment.id).getY() ;
   395 			else 
   395       else 
   396 				topY = CY.get('document').get('scrollTop') ;
   396         topY = CY.get('document').get('scrollTop') ;
   397 			
   397       
   398 			this._showComments([topComment.id], topY, false) ;
   398       this._showComments([topComment.id], topY, false) ;
   399 			// optim when browsing comments with no reply			
   399       // optim when browsing comments with no reply     
   400 			if (topComment.replies.length > 0 || reply)
   400       if (topComment.replies.length > 0 || reply)
   401 				this._animateToAndFocus(topY, focusComment.id, reply) ;
   401         this._animateToAndFocus(topY, focusComment.id, reply) ;
   402 		}
   402     }
   403 	},
   403   },
   404 
   404 
   405 	showSingleComment : function(comment) {
   405   showSingleComment : function(comment) {
   406 		this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   406     this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   407 		this._showSingleComment(comment) ;
   407     this._showSingleComment(comment) ;
   408 		this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   408     this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   409 		this._q.run();
   409     this._q.run();
   410 	},
   410   },
   411 	
   411   
   412 	showFocusSingleComment : function(topComment, focusComment, reply) {
   412   showFocusSingleComment : function(topComment, focusComment, reply) {
   413 		this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   413     this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   414 		this._showFocusSingleComment(topComment, focusComment, reply) ;
   414     this._showFocusSingleComment(topComment, focusComment, reply) ;
   415 		this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   415     this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   416 		this._q.run();
   416     this._q.run();
   417 	},
   417   },
   418 	
   418   
   419 	browse : function(order, whereto) { 
   419   browse : function(order, whereto) { 
   420 		var comment = gIComments.browse(order, whereto) ;
   420     var comment = gIComments.browse(order, whereto) ;
   421 		if (comment != null) 
   421     if (comment != null) 
   422 			this.showSingleComment(comment) ;
   422       this.showSingleComment(comment) ;
   423 	},
   423   },
   424 	
   424   
   425 	_showComments : function(commentDbIds, topY, atDocumentTop) {
   425   _showComments : function(commentDbIds, topY, atDocumentTop) {
   426 		this._q.add(
   426     this._q.add(
   427 			{fn:function() {
   427       {fn:function() {
   428 				gShowingAllComments = atDocumentTop ;			
   428         gShowingAllComments = atDocumentTop ;     
   429 				gIComments.hide() ; 
   429         gIComments.hide() ; 
   430 				var cs = CY.Array.map(commentDbIds, function(id) { return gDb.getComment(id) ; }) ;
   430         var cs = CY.Array.map(commentDbIds, function(id) { return gDb.getComment(id) ; }) ;
   431 				var comments = gDb.getThreads(cs) ;
   431         var comments = gDb.getThreads(cs) ;
   432 				gIComments.fetch(comments) ;
   432         gIComments.fetch(comments) ;
   433 	
   433   
   434 				if (commentDbIds.length > 0) {
   434         if (commentDbIds.length > 0) {
   435 					if (atDocumentTop) {
   435           if (atDocumentTop) {
   436 						CY.get('document').set('scrollTop', 0) ; 
   436             CY.get('document').set('scrollTop', 0) ; 
   437 					}
   437           }
   438 					else {
   438           else {
   439 						gIComments.activate(commentDbIds[0]) ;
   439             gIComments.activate(commentDbIds[0]) ;
   440 						var scopeStart = CY.get(".c-id-"+commentDbIds[0]) ;
   440             var scopeStart = CY.get(".c-id-"+commentDbIds[0]) ;
   441 						if (scopeStart && !scopeStart.inViewportRegion()) // scopeStart could be null when comment has no scope
   441             if (scopeStart && !scopeStart.inViewportRegion()) // scopeStart could be null when comment has no scope
   442 							scopeStart.scrollIntoView(true) ;
   442               scopeStart.scrollIntoView(true) ;
   443 					}
   443           }
   444 				}
   444         }
   445 				
   445         
   446 				gIComments.setPosition([gConf['iCommentLeftPadding'], topY]) ;
   446         gIComments.setPosition([gConf['iCommentLeftPadding'], topY]) ;
   447 	
   447   
   448 				gIComments.show() ;
   448         gIComments.show() ;
   449 			}}) ;
   449       }}) ;
   450 	},
   450   },
   451 	
   451   
   452 	_animateTo : function(topY) {
   452   _animateTo : function(topY) {
   453 		this._q.add({fn:function() {
   453     this._q.add({fn:function() {
   454 						gIComments.setAnimationToPositions(topY) ;
   454             gIComments.setAnimationToPositions(topY) ;
   455 						}},
   455             }},
   456 					{id:"animationRun", autoContinue:false, fn:CY.bind(gIComments.runAnimations, gIComments)}
   456           {id:"animationRun", autoContinue:false, fn:CY.bind(gIComments.runAnimations, gIComments)}
   457 	            ) ;
   457               ) ;
   458 	},
   458   },
   459 	
   459   
   460 	_animateToAndFocus : function(topY, focusCommentId, reply) {
   460   _animateToAndFocus : function(topY, focusCommentId, reply) {
   461 		this._q.add({fn:function() {
   461     this._q.add({fn:function() {
   462 						gIComments.setAnimationToPositionsAndFocus(topY, focusCommentId, reply) ;
   462             gIComments.setAnimationToPositionsAndFocus(topY, focusCommentId, reply) ;
   463 						}},
   463             }},
   464 					{id:"animationRun", autoContinue:false, fn:CY.bind(gIComments.runAnimations, gIComments)}
   464           {id:"animationRun", autoContinue:false, fn:CY.bind(gIComments.runAnimations, gIComments)}
   465 	            ) ;
   465               ) ;
   466 	},
   466   },
   467 	
   467   
   468 	_animateToTop : function() {
   468   _animateToTop : function() {
   469 		var topPos = gIComments.getTopPosition() ;
   469     var topPos = gIComments.getTopPosition() ;
   470 		if (topPos != null)
   470     if (topPos != null)
   471 			this._animateTo(topPos[1]) ;
   471       this._animateTo(topPos[1]) ;
   472 	},
   472   },
   473 	
   473   
   474 	animateToTop : function() {
   474   animateToTop : function() {
   475 		this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   475     this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   476 		this._animateToTop() ;
   476     this._animateToTop() ;
   477 		this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   477     this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   478 		this._q.run();
   478     this._q.run();
   479 	},
   479   },
   480 	
   480   
   481 	showAllComments : function() {
   481   showAllComments : function() {
   482 		checkForOpenedDialog(null, function() {
   482     checkForOpenedDialog(null, function() {
   483 			gShowingAllComments = true ;
   483       gShowingAllComments = true ;
   484 			var allTopComments = CY.Array.map(gDb.comments, function(c){return c.id;}) ;
   484       var allTopComments = CY.Array.map(gDb.comments, function(c){return c.id;}) ;
   485 			this.showComments(allTopComments, [0,0], true) ;
   485       this.showComments(allTopComments, [0,0], true) ;
   486 		}, this, null) ;
   486     }, this, null) ;
   487 	},
   487   },
   488 
   488 
   489 	showScopeRemovedComments : function() {
   489   showScopeRemovedComments : function() {
   490 		checkForOpenedDialog(null, function() {
   490     checkForOpenedDialog(null, function() {
   491 			gShowingAllComments = true ;
   491       gShowingAllComments = true ;
   492 			var scopeRemovedComments = CY.Array.filter(gDb.comments, function(comment) { return (comment.start_wrapper == -1) ; }) ;
   492       var scopeRemovedComments = CY.Array.filter(gDb.comments, function(comment) { return (comment.start_wrapper == -1) ; }) ;
   493 			var scopeRemovedCommentIds = CY.Array.map(scopeRemovedComments, function(c){return c.id;}) ;
   493       var scopeRemovedCommentIds = CY.Array.map(scopeRemovedComments, function(c){return c.id;}) ;
   494 			this.showComments(scopeRemovedCommentIds, [0,0], true) ;
   494       this.showComments(scopeRemovedCommentIds, [0,0], true) ;
   495 			
   495       
   496 		}, this, null) ;
   496     }, this, null) ;
   497 	},
   497   },
   498 
   498 
   499 	showComments : function(commentDbIds, mouseXY, atDocumentTop) {
   499   showComments : function(commentDbIds, mouseXY, atDocumentTop) {
   500 		checkForOpenedDialog(null, function() {
   500     checkForOpenedDialog(null, function() {
   501 			this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   501       this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   502 			this._showComments(commentDbIds, mouseXY[1], atDocumentTop) ;
   502       this._showComments(commentDbIds, mouseXY[1], atDocumentTop) ;
   503 			this._animateTo(mouseXY[1]) ;
   503       this._animateTo(mouseXY[1]) ;
   504 			this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   504       this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   505 			this._q.run();
   505       this._q.run();
   506 		}, this, null) ;
   506     }, this, null) ;
   507 	},
   507   },
   508 
   508 
   509 	openComment : function(iComment) { 
   509   openComment : function(iComment) { 
   510 		this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   510     this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   511 
   511 
   512 		var y = gIComments.getTopPosition()[1] ;
   512     var y = gIComments.getTopPosition()[1] ;
   513 		this._q.add({fn:function() {
   513     this._q.add({fn:function() {
   514 			gIComments.open(iComment.commentId) ;
   514       gIComments.open(iComment.commentId) ;
   515     		gIComments.refresh(iComment.commentId) ;
   515         gIComments.refresh(iComment.commentId) ;
   516 		}}) ;
   516     }}) ;
   517 		this._animateTo(y) ;
   517     this._animateTo(y) ;
   518 		
   518     
   519 		this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   519     this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   520 		this._q.run();
   520     this._q.run();
   521 	},
   521   },
   522 	
   522   
   523 	closeComment : function(iComment) { 
   523   closeComment : function(iComment) { 
   524 		checkForOpenedDialog(iComment, function() {
   524     checkForOpenedDialog(iComment, function() {
   525 			this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   525       this._q.add({fn:CY.bind(this.setPreventClickOn, this)}) ;
   526 	
   526   
   527 			var y = gIComments.getTopPosition()[1] ;
   527       var y = gIComments.getTopPosition()[1] ;
   528 			this._q.add({fn:function() {
   528       this._q.add({fn:function() {
   529 				var comment = gDb.getComment(iComment.commentId) ;
   529         var comment = gDb.getComment(iComment.commentId) ;
   530 				gIComments.close(iComment.commentId) ;
   530         gIComments.close(iComment.commentId) ;
   531 		    	if (comment.reply_to_id != null)
   531           if (comment.reply_to_id != null)
   532 		    		gIComments.refresh(comment.reply_to_id) ;
   532             gIComments.refresh(comment.reply_to_id) ;
   533 			}}) ;
   533       }}) ;
   534 			this._animateTo(y) ;
   534       this._animateTo(y) ;
   535 	
   535   
   536 			this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   536       this._q.add({fn:CY.bind(this.setPreventClickOff, this)}) ;
   537 			this._q.run() ;
   537       this._q.run() ;
   538 		}, this, null) ;
   538     }, this, null) ;
   539 	},
   539   },
   540 	
   540   
   541 	activate : function(iComment) {
   541   activate : function(iComment) {
   542 		gIComments.activate(iComment.commentId) ;
   542     gIComments.activate(iComment.commentId) ;
   543 	}
   543   }
   544 }
   544 }
   545 			
   545       
   546 readyForAction = function () {
   546 readyForAction = function () {
   547 	return !gSync._iPreventClick ;
   547   return !gSync._iPreventClick ;
   548 };
   548 };