changeset 6434:1ab38cd72704

template: use Bootstrap tooltips and popover instead of handmade tooltips Based on work from Andrew Shadura <andrew@shadura.me>. Further modified by Mads Kiilerich. show_changeset_tooltip is merged into tooltip_activate.
author domruf <dominikruf@gmail.com>
date Tue, 20 Sep 2016 20:01:59 +0200
parents 6c1bf3d48def
children 94a9ce213964
files kallithea/controllers/changeset.py kallithea/lib/helpers.py kallithea/public/css/style.css kallithea/public/js/base.js kallithea/templates/admin/admin_log.html kallithea/templates/base/root.html kallithea/templates/data_table/_dt_elements.html kallithea/templates/files/files_source.html kallithea/templates/followers/followers.html kallithea/templates/forks/forks.html kallithea/templates/journal/journal.html
diffstat 11 files changed, 200 insertions(+), 136 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/controllers/changeset.py	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/controllers/changeset.py	Tue Sep 20 20:01:59 2016 +0200
@@ -108,7 +108,7 @@
 
     params['anchor'] = fileid
     icon = h.literal('<i class="icon-strike"></i>')
-    return h.link_to(icon, h.url.current(**params), title=lbl, class_='tooltip')
+    return h.link_to(icon, h.url.current(**params), title=lbl, **{'data-toggle': 'tooltip'})
 
 
 def get_line_ctx(fid, GET):
@@ -168,7 +168,7 @@
 
     params['anchor'] = fileid
     icon = h.literal('<i class="icon-sort"></i>')
-    return h.link_to(icon, h.url.current(**params), title=lbl, class_='tooltip')
+    return h.link_to(icon, h.url.current(**params), title=lbl, **{'data-toggle': 'tooltip'})
 
 
 # Could perhaps be nice to have in the model but is too high level ...
--- a/kallithea/lib/helpers.py	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/lib/helpers.py	Tue Sep 20 20:01:59 2016 +0200
@@ -311,9 +311,9 @@
             author = escape(changeset.author)
             date = changeset.date
             message = escape(changeset.message)
-            tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
-                            " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
-                            "</b> %s<br/></div>") % (author, date, message)
+            tooltip_html = ("<b>Author:</b> %s<br/>"
+                            "<b>Date:</b> %s</b><br/>"
+                            "<b>Message:</b> %s") % (author, date, message)
 
             lnk_format = show_id(changeset)
             uri = link_to(
@@ -321,9 +321,8 @@
                     url('changeset_home', repo_name=repo_name,
                         revision=changeset.raw_id),
                     style=get_color_string(changeset.raw_id),
-                    class_='safe-html-title',
-                    title=tooltip_html,
-                    **{'data-toggle': 'tooltip'}
+                    **{'data-toggle': 'popover',
+                       'data-content': tooltip_html}
                   )
 
             uri += '\n'
@@ -568,7 +567,7 @@
                 lbl = rev[:12]
                 title_ = _('Changeset %s not found') % lbl
             if parse_cs:
-                return link_to(lbl, url_, title=title_, class_='tooltip')
+                return link_to(lbl, url_, title=title_, **{'data-toggle': 'tooltip'})
             return link_to(lbl, url_, class_='lazy-cs' if lazy_cs else '',
                            **{'data-raw_id':rev.raw_id, 'data-repo_name':repo_name})
 
--- a/kallithea/public/css/style.css	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/public/css/style.css	Tue Sep 20 20:01:59 2016 +0200
@@ -2624,37 +2624,6 @@
     z-index: 2;
 }
 
-#tip-box {
-    position: absolute;
-
-    background-color: #FFF;
-    border: 2px solid #577632;
-    font: 100% sans-serif;
-    width: auto;
-    opacity: 1;
-    padding: 8px;
-
-    white-space: pre-wrap;
-    border-radius: 8px 8px 8px 8px;
-    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
-    z-index: 100000;
-}
-
-.hl-tip-box {
-    z-index: 1;
-    position: absolute;
-    color: #666;
-    background-color: #FFF;
-    border: 2px solid #577632;
-    font: 100% sans-serif;
-    width: auto;
-    opacity: 1;
-    padding: 8px;
-    white-space: pre-wrap;
-    border-radius: 8px 8px 8px 8px;
-    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
-}
-
 
 .mentions-container {
     width: 90% !important;
@@ -2983,7 +2952,7 @@
 
 input[disabled].btn,
 .btn.disabled {
-    color: #999;
+    opacity: 0.5;
 }
 
 .label,
@@ -4434,3 +4403,144 @@
 ul.user_group_member li {
     clear: both;
 }
+
+.tooltip {
+    position: absolute;
+    z-index: 1070;
+    display: block;
+    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+    font-size: 12px;
+    font-style: normal;
+    font-weight: 400;
+    line-height: 1.42857143;
+    text-align: left;
+    text-align: start;
+    text-decoration: none;
+    text-shadow: none;
+    text-transform: none;
+    letter-spacing: normal;
+    word-break: normal;
+    word-spacing: normal;
+    word-wrap: normal;
+    white-space: normal;
+}
+.tooltip-arrow {
+    position: absolute;
+    width: 0;
+    height: 0;
+    border-color: transparent;
+    border-style: solid;
+}
+.tooltip-inner {
+    max-width: 200px;
+    padding: 3px 8px;
+    color: #fff;
+    text-align: center;
+    background-color: #000;
+    border-radius: 4px;
+}
+
+.tooltip.top {
+    padding: 5px 0;
+    margin-top: -3px;
+}
+.tooltip.top .tooltip-arrow {
+    bottom: 0;
+    left: 50%;
+    margin-left: -5px;
+    border-width: 5px 5px 0;
+    border-top-color: #000;
+}
+
+.tooltip.bottom {
+    padding: 5px 0;
+    margin-top: 3px;
+}
+.tooltip.bottom .tooltip-arrow {
+    top: 0;
+    left: 50%;
+    margin-left: -5px;
+    border-width: 0 5px 5px;
+    border-bottom-color: #000;
+}
+
+
+.popover {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 1060;
+    max-width: 276px;
+    padding: 1px;
+    background-color: #fff;
+    background-clip: padding-box;
+    border: 1px solid #ccc;
+    border: 1px solid rgba(0,0,0,.2);
+    border-radius: 6px;
+    box-shadow: 0 5px 10px rgba(0,0,0,.2);
+    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+    font-size: 12px;
+    font-style: normal;
+    font-weight: 400;
+    line-height: 1.42857143;
+    text-align: left;
+    text-align: start;
+    text-decoration: none;
+    text-shadow: none;
+    text-transform: none;
+    letter-spacing: normal;
+    word-break: normal;
+    word-spacing: normal;
+    word-wrap: normal;
+    white-space: normal;
+}
+
+.popover > .arrow {
+    border-width: 11px;
+}
+.popover > .arrow,
+.popover > .arrow::after {
+    position: absolute;
+    display: block;
+    width: 0;
+    height: 0;
+    border-color: transparent;
+    border-style: solid;
+}
+
+.popover-title {
+    padding: 8px 14px;
+    margin: 0;
+    font-size: 14px;
+    background-color: #f7f7f7;
+    border-bottom: 1px solid #ebebeb;
+    border-radius: 5px 5px 0 0;
+}
+
+.popover-content {
+    padding: 9px 14px;
+}
+
+.popover.top {
+    margin-top: -10px;
+}
+.popover.top > .arrow {
+    bottom: -11px;
+    left: 50%;
+    margin-left: -11px;
+    border-top-color: #999;
+    border-top-color: rgba(0,0,0,.25);
+    border-bottom-width: 0;
+}
+
+.popover.bottom {
+    margin-top: 10px;
+}
+.popover.bottom > .arrow {
+    top: -11px;
+    left: 50%;
+    margin-left: -11px;
+    border-top-width: 0;
+    border-bottom-color: #999;
+    border-bottom-color: rgba(0,0,0,.25);
+}
--- a/kallithea/public/js/base.js	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/public/js/base.js	Tue Sep 20 20:01:59 2016 +0200
@@ -411,25 +411,6 @@
     });
 };
 
-/**
- * activate .lazy-cs mouseover for showing changeset tooltip
- */
-var show_changeset_tooltip = function(){
-    $('.lazy-cs').mouseover(function(e){
-        var $target = $(e.currentTarget);
-        var rid = $target.data('raw_id');
-        var repo_name = $target.data('repo_name');
-        if(rid && !$target.hasClass('tooltip')){
-            _show_tooltip(e, _TM['loading ...']);
-            var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": rid});
-            ajaxGET(url, function(json){
-                    $target.addClass('tooltip');
-                    _show_tooltip(e, json['message']);
-                    _activate_tooltip($target);
-                });
-        }
-    });
-};
 
 var _onSuccessFollow = function(target){
     var $target = $(target);
@@ -475,76 +456,56 @@
 };
 
 /**
- * tooltips
+ * load tooltips dynamically based on data attributes, used for .lazy-cs changeset links
  */
-
-var tooltip_activate = function(){
-    $(document).ready(_init_tooltip);
-};
-
-var _activate_tooltip = function($tt){
-    $tt.mouseover(_show_tooltip);
-    $tt.mousemove(_move_tooltip);
-    $tt.mouseout(_close_tooltip);
-};
+var get_changeset_tooltip = function() {
+    var $target = $(this);
+    var tooltip = $target.data('tooltip');
+    if (!tooltip) {
+        var raw_id = $target.data('raw_id');
+        var repo_name = $target.data('repo_name');
+        var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": raw_id});
 
-var _init_tooltip = function(){
-    var $tipBox = $('#tip-box');
-    if(!$tipBox.length){
-        $tipBox = $('<div id="tip-box"></div>');
-        $(document.body).append($tipBox);
+        $.ajax(url, {
+            async: false,
+            success: function(data) {
+                tooltip = data["message"];
+            }
+        });
+        $target.data('tooltip', tooltip);
     }
-
-    $tipBox.hide();
-    $tipBox.css('position', 'absolute');
-    $tipBox.css('max-width', '600px');
-
-    _activate_tooltip($('[data-toggle="tooltip"]'));
+    return tooltip;
 };
 
-var _show_tooltip = function(e, tipText, safe){
-    e.stopImmediatePropagation();
-    var el = e.currentTarget;
-    var $el = $(el);
-    if(tipText){
-        // just use it
-    } else if(el.tagName.toLowerCase() === 'img'){
-        tipText = el.alt ? el.alt : '';
-    } else {
-        tipText = el.title ? el.title : '';
-        safe = safe || $el.hasClass("safe-html-title");
+/**
+ * activate tooltips and popups
+ */
+var tooltip_activate = function(){
+    function placement(p, e){
+        if(e.getBoundingClientRect().top > 2*$(window).height()/3){
+            return 'top';
+        }else{
+            return 'bottom';
+        }
     }
-
-    if(tipText !== ''){
-        // save org title
-        $el.attr('tt_title', tipText);
-        // reset title to not show org tooltips
-        $el.prop('title', '');
-
-        var $tipBox = $('#tip-box');
-        if (safe) {
-            $tipBox.html(tipText);
-        } else {
-            $tipBox.text(tipText);
-        }
-        $tipBox.css('display', 'block');
-    }
+    $(document).ready(function(){
+        $('[data-toggle="tooltip"]').tooltip({
+            placement: placement
+        });
+        $('[data-toggle="popover"]').popover({
+            html: true,
+            container: 'body',
+            placement: placement,
+            trigger: 'hover',
+            template: '<div class="popover cs-popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+        });
+        $('.lazy-cs').tooltip({
+            title: get_changeset_tooltip,
+            placement: placement
+        });
+    });
 };
 
-var _move_tooltip = function(e){
-    e.stopImmediatePropagation();
-    var $tipBox = $('#tip-box');
-    $tipBox.css('top', (e.pageY + 15) + 'px');
-    $tipBox.css('left', (e.pageX + 15) + 'px');
-};
-
-var _close_tooltip = function(e){
-    e.stopImmediatePropagation();
-    var $tipBox = $('#tip-box');
-    $tipBox.hide();
-    var el = e.currentTarget;
-    $(el).prop('title', $(el).attr('tt_title'));
-};
 
 /**
  * Quick filter widget
--- a/kallithea/templates/admin/admin_log.html	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/templates/admin/admin_log.html	Tue Sep 20 20:01:59 2016 +0200
@@ -44,7 +44,6 @@
       asynchtml(e.target.href, $user_log, function(){
         show_more_event();
         tooltip_activate();
-        show_changeset_tooltip();
       });
       e.preventDefault();
     });
--- a/kallithea/templates/base/root.html	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/templates/base/root.html	Tue Sep 20 20:01:59 2016 +0200
@@ -81,7 +81,6 @@
             $(document).ready(function(){
               tooltip_activate();
               show_more_event();
-              show_changeset_tooltip();
               // routes registration
               pyroutes.register('home', "${h.url('home')}", []);
               pyroutes.register('new_gist', "${h.url('new_gist')}", []);
--- a/kallithea/templates/data_table/_dt_elements.html	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/templates/data_table/_dt_elements.html	Tue Sep 20 20:01:59 2016 +0200
@@ -45,7 +45,7 @@
 <%def name="revision(name,rev,tip,author,last_msg)">
   <div>
   %if rev >= 0:
-      <a data-toggle="tooltip" title="${'%s:\n\n%s' % (h.escape(author), h.escape(last_msg))}" class="revision-link safe-html-title" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a>
+      <a data-toggle="popover" title="${author | entity}" data-content="${last_msg | entity}" class="hash" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a>
   %else:
       ${_('No changesets yet')}
   %endif
--- a/kallithea/templates/files/files_source.html	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/templates/files/files_source.html	Tue Sep 20 20:01:59 2016 +0200
@@ -20,13 +20,13 @@
 <div id="body" class="codeblock">
     <div class="code-header">
         <div class="stats">
-        <div class="pull-left">
+          <div class="pull-left">
             <div class="left img"><i class="icon-doc-inv"></i></div>
             <div class="left item"><pre data-toggle="tooltip" title="${h.fmt_date(c.changeset.date)}">${h.link_to(h.show_id(c.changeset),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</pre></div>
             <div class="left item"><pre>${h.format_byte_size(c.file.size,binary=True)}</pre></div>
             <div class="left item last"><pre>${c.file.mimetype}</pre></div>
-        </div>
-        <div class="pull-right buttons">
+          </div>
+          <div class="pull-right buttons">
               %if c.annotate:
                 ${h.link_to(_('Show Source'),    h.url('files_home',         repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
               %else:
@@ -39,14 +39,14 @@
                 ${h.link_to(_('Edit on Branch: %s') % c.changeset.branch, h.url('files_edit_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-default btn-xs")}
                 ${h.link_to(_('Delete'), h.url('files_delete_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-danger btn-xs")}
                %elif c.on_branch_head and c.file.is_binary:
-                ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled tooltip", title=_('Editing binary files not allowed'))}
+                ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled", title=_('Editing binary files not allowed'),**{'data-toggle':'tooltip'})}
                 ${h.link_to(_('Delete'), h.url('files_delete_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-danger btn-xs")}
                %else:
-                ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled tooltip", title=_('Editing files allowed only when on branch head revision'))}
-                ${h.link_to(_('Delete'), '#', class_="btn btn-danger btn-xs disabled tooltip", title=_('Deleting files allowed only when on branch head revision'))}
+                ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled", title=_('Editing files allowed only when on branch head revision'),**{'data-toggle':'tooltip'})}
+                ${h.link_to(_('Delete'), '#', class_="btn btn-danger btn-xs disabled", title=_('Deleting files allowed only when on branch head revision'),**{'data-toggle':'tooltip'})}
                %endif
               %endif
-        </div>
+          </div>
         </div>
         <div class="author">
             ${h.gravatar_div(h.email_or_none(c.changeset.author), size=16)}
--- a/kallithea/templates/followers/followers.html	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/templates/followers/followers.html	Tue Sep 20 20:01:59 2016 +0200
@@ -32,7 +32,6 @@
         asynchtml(e.target.href, $followers, function(){
             show_more_event();
             tooltip_activate();
-            show_changeset_tooltip();
         });
         e.preventDefault();
     });
--- a/kallithea/templates/forks/forks.html	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/templates/forks/forks.html	Tue Sep 20 20:01:59 2016 +0200
@@ -32,7 +32,6 @@
           asynchtml(e.target.href, $forks, function(){
               show_more_event();
               tooltip_activate();
-              show_changeset_tooltip();
           });
           e.preventDefault();
       });
--- a/kallithea/templates/journal/journal.html	Thu Jan 12 01:34:07 2017 +0100
+++ b/kallithea/templates/journal/journal.html	Tue Sep 20 20:01:59 2016 +0200
@@ -62,7 +62,6 @@
         asynchtml("${h.url.current(filter=c.search_term)}", $("#journal"), function(){
             show_more_event();
             tooltip_activate();
-            show_changeset_tooltip();
             });
         e.preventDefault();
     });
@@ -76,7 +75,6 @@
             asynchtml(e.target.href, $journal, function(){
                 show_more_event();
                 tooltip_activate();
-                show_changeset_tooltip();
             });
             e.preventDefault();
         });