Commits

Marcin Kuzminski committed 2bfcec6

new tooltip implementation
- added lazy loading of changeset tooltips for journal data

Comments (0)

Files changed (12)

rhodecode/config/routing.py

                  controller='changeset', action='raw_changeset',
                  revision='tip', conditions=dict(function=check_repo))
 
+    rmap.connect('changeset_info', '/changeset_info/{repo_name:.*?}/{revision}',
+                 controller='changeset', action='changeset_info')
+
     rmap.connect('compare_url',
                  '/{repo_name:.*?}/compare/{org_ref_type}@{org_ref:.*?}...{other_ref_type}@{other_ref:.*?}',
                  controller='compare', action='index',

rhodecode/controllers/changeset.py

 import logging
 import traceback
 from collections import defaultdict
-from webob.exc import HTTPForbidden
+from webob.exc import HTTPForbidden, HTTPBadRequest
 
 from pylons import tmpl_context as c, url, request, response
 from pylons.i18n.translation import _
             return True
         else:
             raise HTTPForbidden()
+
+    @jsonify
+    def changeset_info(self, repo_name, revision):
+        if request.is_xhr or 1:
+            return c.rhodecode_repo.get_changeset(revision)
+        else:
+            raise HTTPBadRequest()

rhodecode/lib/helpers.py

                 title = _('Changeset not found')
             if parse_cs:
                 return link_to(lbl, _url, title=title, class_='tooltip')
-            return link_to(lbl, _url, raw_id=rev.raw_id, class_='journal-cs')
+            return link_to(lbl, _url, raw_id=rev.raw_id, repo_name=repo_name,
+                           class_='lazy-cs')
 
         revs = []
         if len(filter(lambda v: v != '', revs_ids)) > 0:

rhodecode/lib/vcs/backends/base.py

     def __eq__(self, other):
         return self.raw_id == other.raw_id
 
+    def __json__(self):
+        return dict(
+            short_id=self.short_id,
+            raw_id=self.raw_id,
+            message=self.message,
+            date=self.date,
+            author=self.author,
+        )
+
     @LazyProperty
     def last(self):
         if self.repository is None:

rhodecode/public/css/style.css

 	z-index: 2;
 }
 
-.yui-tt {
-	visibility: hidden;
+#tip-box {
 	position: absolute;
-	color: #666;
+	
 	background-color: #FFF;
 	border: 2px solid #003367;
 	font: 100% sans-serif;
 	width: auto;
 	opacity: 1px;
 	padding: 8px;
+	
 	white-space: pre-wrap;
 	-webkit-border-radius: 8px 8px 8px 8px;
 	-khtml-border-radius: 8px 8px 8px 8px;
 	-moz-border-radius: 8px 8px 8px 8px;
 	border-radius: 8px 8px 8px 8px;
 	box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
+	-moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
+	-webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 }
 
 .mentions-container{

rhodecode/public/js/rhodecode.js

 	
 };
 
+var ajaxGET = function(url,success) {
+	// Set special header for ajax == HTTP_X_PARTIAL_XHR
+	YUC.initHeader('X-PARTIAL-XHR',true);
+
+    var sUrl = url;
+    var callback = {
+        success: success,
+        failure: function (o) {
+            alert("error");
+        },
+    };
+
+    var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
+    return request;
+};
+
+
+
 var ajaxPOST = function(url,postData,success) {
 	// Set special header for ajax == HTTP_X_PARTIAL_XHR
 	YUC.initHeader('X-PARTIAL-XHR',true);
  * tooltip activate
  */
 var tooltip_activate = function(){
-    function toolTipsId(){
-        var ids = [];
-        var tts = YUQ('.tooltip');
-        for (var i = 0; i < tts.length; i++) {
-            // if element doesn't not have and id 
-        	//  autogenerate one for tooltip 
-            if (!tts[i].id){
-                tts[i].id='tt'+((i*100)+tts.length);
-            }
-            ids.push(tts[i].id);
-        }
-        return ids
-    };
-    var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
-        context: [[toolTipsId()],"tl","bl",null,[0,5]],
-        monitorresize:false,
-        xyoffset :[0,0],
-        autodismissdelay:300000,
-        hidedelay:5,
-        showdelay:20,
-    });
+	yt = YAHOO.yuitip.main;
+	YUE.onDOMReady(yt.init);
 };
 
 /**
     });
 };
 
+/**
+ * show changeset tooltip
+ */
+var show_changeset_tooltip = function(){
+	YUE.on(YUD.getElementsByClassName('lazy-cs'), 'mouseover', function(e){
+		var target = e.currentTarget;
+		var rid = YUD.getAttribute(target,'raw_id');
+		var repo_name = YUD.getAttribute(target,'repo_name');
+		var ttid = 'tt-'+rid;
+		var success = function(o){
+			console.log(o.responseText);
+			var json = JSON.parse(o.responseText);
+			YUD.addClass(target,'tooltip')
+			YUD.setAttribute(target, 'title',json['message']);
+			YAHOO.yuitip.main.show_yuitip(e, target);
+		}
+		if(rid && !YUD.hasClass(target, 'tooltip')){
+			YUD.setAttribute(target,'id',ttid);
+			ajaxGET('/changeset_info/{0}/{1}'.format(repo_name,rid), success)
+		}
+	});
+};
+
+
+/**
+ * TOOLTIP IMPL.
+ */
+YAHOO.namespace('yuitip');
+YAHOO.yuitip.main = {
+
+	YE:			YAHOO.util.Event,
+	Dom:		YAHOO.util.Dom,
+	$:			YAHOO.util.Dom.get,
+
+	bgColor:	'#000',
+	speed:		0.3,
+	opacity:	0.9,
+	offset:		[15,15],
+	useAnim:	false,
+	maxWidth:	200,
+	add_links:	true,
+
+	init: function(){
+		yt._tooltip = '';
+		yt.tipBox = yt.$('tip-box');
+		if(!yt.tipBox){
+			yt.tipBox = document.createElement('div');
+			document.body.appendChild(yt.tipBox);
+			yt.tipBox.id = 'tip-box';
+		}
+
+		yt.Dom.setStyle(yt.tipBox, 'display', 'none');
+		yt.Dom.setStyle(yt.tipBox, 'position', 'absolute');
+		if(yt.maxWidth !== null){
+			yt.Dom.setStyle(yt.tipBox, 'max-width', yt.maxWidth+'px');
+		}
+
+		var yuitips = yt.Dom.getElementsByClassName('tooltip');
+
+		if(yt.add_links === true){
+			var links = document.getElementsByTagName('a');
+			var linkLen = links.length;
+			for(i=0;i<linkLen;i++){
+				yuitips.push(links[i]);
+			}
+		}
+
+		var yuiLen = yuitips.length;
+
+		for(i=0;i<yuiLen;i++){
+			yt.YE.on(yuitips[i], 'mouseover', yt.show_yuitip, yuitips[i]);
+			yt.YE.on(yuitips[i], 'mousemove', yt.move_yuitip, yuitips[i]);
+			yt.YE.on(yuitips[i], 'mouseout', yt.close_yuitip, yuitips[i]);
+		}
+	},
+
+	show_yuitip: function(e, el){
+		yt.YE.stopEvent(e);
+		if(el.tagName.toLowerCase() === 'img'){
+			yt.tipText = el.alt ? el.alt : '';
+		} else {
+			yt.tipText = el.title ? el.title : '';
+		}
+
+		
+		if(yt.tipText !== ''){
+			// save org title
+			yt._tooltip = yt.tipText;
+			// reset title to not show org tooltips
+			YUD.setAttribute(el, 'title', '');
+
+			var newTipText = yt.tipText.split(' - ');
+			var tipLen = newTipText.length;
+			yt.tipText = '';
+			for(var i=0;i<tipLen;i++){
+				yt.tipText+= newTipText[i]+"<br/>";
+			}
+			yt.tipBox.innerHTML = yt.tipText;
+			yt.Dom.setStyle(yt.tipBox, 'display', 'block');
+			if(yt.useAnim === true){
+				yt.Dom.setStyle(yt.tipBox, 'opacity', '0');
+				var newAnim = new YAHOO.util.Anim(yt.tipBox,
+					{
+						opacity: { to: yt.opacity }
+					}, yt.speed, YAHOO.util.Easing.easeOut
+				);
+				newAnim.animate();
+			}
+		}
+	},
+
+	move_yuitip: function(e, el){
+		yt.YE.stopEvent(e);
+		var movePos = yt.YE.getXY(e);
+		yt.Dom.setStyle(yt.tipBox, 'top', (movePos[1] + yt.offset[1]) + 'px');
+		yt.Dom.setStyle(yt.tipBox, 'left', (movePos[0] + yt.offset[0]) + 'px');
+	},
+
+	close_yuitip: function(e, el){
+		yt.YE.stopEvent(e);
+	
+		if(yt.useAnim === true){
+			var newAnim = new YAHOO.util.Anim(yt.tipBox,
+				{
+					opacity: { to: 0 }
+				}, yt.speed, YAHOO.util.Easing.easeOut
+			);
+			newAnim.animate();
+		} else {
+			yt.Dom.setStyle(yt.tipBox, 'display', 'none');
+		}
+		YUD.setAttribute(el,'title', yt._tooltip);
+	}
+}
 
 /**
  * Quick filter widget

rhodecode/templates/base/root.html

            YUE.onDOMReady(function(){
              tooltip_activate();
              show_more_event();
+             show_changeset_tooltip();
 
              YUE.on('quick_login_link','click',function(e){
                  // make sure we don't redirect

rhodecode/templates/followers/followers_data.html

 <script type="text/javascript">
 YUE.onDOMReady(function(){
     YUE.delegate("followers","click",function(e, matchedEl, container){
-        ypjax(e.target.href,"followers",function(){show_more_event();tooltip_activate();});
+        ypjax(e.target.href,"followers",function(){
+        	show_more_event();
+        	tooltip_activate();
+        	show_changeset_tooltip();	
+        });
         YUE.preventDefault(e);
     },'.pager_link');
 });

rhodecode/templates/forks/forks_data.html

   <script type="text/javascript">
   YUE.onDOMReady(function(){
       YUE.delegate("forks","click",function(e, matchedEl, container){
-          ypjax(e.target.href,"forks",function(){show_more_event();tooltip_activate();});
+          ypjax(e.target.href,"forks",function(){
+        	  show_more_event();
+        	  tooltip_activate();
+        	  show_changeset_tooltip(); 
+          });
           YUE.preventDefault(e);
       },'.pager_link');
   });

rhodecode/templates/journal/journal.html

     }    
     
     YUE.on('refresh','click',function(e){
-        ypjax(e.currentTarget.href,"journal",function(){show_more_event();tooltip_activate();});
+        ypjax(e.currentTarget.href,"journal",function(){
+        	show_more_event();
+        	tooltip_activate();
+        	show_changeset_tooltip();
+        	});
         YUE.preventDefault(e);
     });
 

rhodecode/templates/journal/journal_data.html

     <script type="text/javascript">
     YUE.onDOMReady(function(){
         YUE.delegate("journal","click",function(e, matchedEl, container){
-        	ypjax(e.target.href,"journal",function(){show_more_event();tooltip_activate();});
+        	ypjax(e.target.href,"journal",function(){
+        		show_more_event();
+        		tooltip_activate();
+        		show_changeset_tooltip();
+        		});
             YUE.preventDefault(e);
         },'.pager_link');
     });

rhodecode/templates/journal/public_journal.html

      </li>
      </ul>
   </div>
-  <script type="text/javascript">
-  function show_more_event(){
-  YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
-      var el = e.target;
-      YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
-      YUD.setStyle(el.parentNode,'display','none');
-  });
-  }
-  </script>
+
   <div id="journal">${c.journal_data}</div>
 </div>