[Rt-commit] rt branch, 4.4/keyboard-shortcuts, created. rt-4.2.11-210-g6909b3b

Dustin Graves dustin at bestpractical.com
Tue Sep 29 15:42:17 EDT 2015


The branch, 4.4/keyboard-shortcuts has been created
        at  6909b3b2f8dd8bb3a3f8a635122066491e2680d4 (commit)

- Log -----------------------------------------------------------------
commit 6909b3b2f8dd8bb3a3f8a635122066491e2680d4
Author: Dustin Graves <dustin at bestpractical.com>
Date:   Thu Sep 17 14:04:17 2015 +0000

    add global / page-specific keyboard shortcuts
    
    global shortcuts:
    gh - click on home link
    gb - browser back
    gf - browser forward
    /  - highlight quick search
    
    search results shortcuts:
    k/j - up/down through search results
    o or <Enter> - view highlighted ticket
    x - toggle highlighted ticket's checkbox (on bulk update)
    
    Fixes: T#151846

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index b936325..3d54559 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -128,6 +128,7 @@ sub JSFiles {
       forms.js
       event-registration.js
       late.js
+      /static/js/keyboard-shortcuts/global.js
       /static/RichText/ckeditor.js
       dropzone.min.js
       }, RT->Config->Get('JSFiles');
diff --git a/share/html/Elements/KeyboardShortcuts b/share/html/Elements/KeyboardShortcuts
new file mode 100644
index 0000000..b0dbba3
--- /dev/null
+++ b/share/html/Elements/KeyboardShortcuts
@@ -0,0 +1,87 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%#                                          <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%#
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+<%INIT>
+</%INIT>
+<%ARGS>
+</%ARGS>
+<link href="/static/css/tipso.min.css" rel="stylesheet">
+<div>
+    <a align="right" href="#">
+        <img src="<% RT->Config->Get('WebPath') %>/static/images/keyboard-shortcuts.svg" alt="<% loc('Keyboard Shortcuts') %>" style="border-style: none" height="13"/>
+    </a>
+</div>
+<script src="/static/js/tipso.min.js"></script>
+<script>
+jQuery(function() {
+    var liKeyboardShortcuts = jQuery('#li-page-keyboard-shortcuts')
+    liKeyboardShortcuts.tipso({
+        content:
+            '<div class="keyboard-shortcuts"><table><tbody>' +
+                '<tr>' +
+                    '<td><span class="key">/</span></td>' +
+                    '<td>Quick Search</td>' +
+                '</tr>' +
+                '<tr>' +
+                    '<td><span class="key">gh</span></td>' +
+                    '<td>Return Home</td>' +
+                '</tr>' +
+                '<tr>' +
+                    '<td><span class="key">gb</span> <span class="sm">/</span> <span class="key">gf</span></td>' +
+                    '<td>Go Back / Forward</td>' +
+                '</tr>' +
+            '</tbody></table></div>',
+        background: '#eee',
+        color: '#000',
+        titleContent: 'Keyboard Shortcuts',
+        titleBackground: '#547CCC',
+        position: 'bottom',
+        tooltipHover: true
+    });
+    liKeyboardShortcuts.css('border-bottom','none');
+});
+</script>
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index 9a39f5e..c7b05f1 100644
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -939,6 +939,9 @@ my $build_main_nav = sub {
         PageMenu()->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
     }
 
+    # Keyboard Shortcuts Legend
+    PageMenu()->child( 'keyboard-shortcuts' => raw_html => $m->scomp( '/Elements/KeyboardShortcuts' ), sort_order => 999 );
+
     $m->callback( CallbackName => 'Privileged', Path => $request_path );
 };
 
diff --git a/share/html/Search/Bulk.html b/share/html/Search/Bulk.html
index 10799af..ea29952 100644
--- a/share/html/Search/Bulk.html
+++ b/share/html/Search/Bulk.html
@@ -190,6 +190,33 @@ $cfs->SetContextObject( values %$seen_queues ) if keys %$seen_queues == 1;
 
 </form>
 
+<div class="clear"></div>
+
+<div class="titlebox keyboard-shortcuts short">
+    <div class="titlebox-title">
+        <span class="left"><&|/l&>Keyboard Shortcuts</&></span>
+        <span class="right-empty"></span>
+    </div>
+    <div class="titlebox-content">
+        <hr class="clear">
+        <table>
+            <tr>
+                <td><span class="key">k</span><span class="sm"> / </span><span class="key">j</span></td>
+                <td><&|/l&>Move up/down the list of results</&></td>
+            </tr>
+            <tr>
+                <td><span class="key">o</span> <span class="sm">or</span> <span class="key"><<&|/l&>Enter</&>></span></td>
+                <td><&|/l&>View highlighted ticket</&></td>
+            </tr>
+            <tr>
+                <td><span class="key">x</span></td>
+                <td><&|/l&>Toggle highlighted ticket's checkbox</&></td>
+            </tr>
+        </table>
+    </div>
+</div>
+
+<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/static/js/keyboard-shortcuts/search.js"></script>
 
 <%INIT>
 unless ( defined $Rows ) {
diff --git a/share/html/Search/Results.html b/share/html/Search/Results.html
index b6b3379..bab4037 100644
--- a/share/html/Search/Results.html
+++ b/share/html/Search/Results.html
@@ -89,6 +89,31 @@
 <input type="submit" class="button" value="<&|/l&>Change</&>" />
 </form>
 </div>
+
+<div class="clear"></div>
+
+<div class="titlebox keyboard-shortcuts short">
+    <div class="titlebox-title">
+        <span class="left"><&|/l&>Keyboard Shortcuts</&></span>
+        <span class="right-empty"></span>
+    </div>
+    <div class="titlebox-content">
+        <hr class="clear">
+        <table>
+            <tr>
+                <td><span class="key">k</span><span class="sm"> / </span><span class="key">j</span></td>
+                <td><&|/l&>Move up/down the list of results</&></td>
+            </tr>
+            <tr>
+                <td><span class="key">o</span> <span class="sm">or</span> <span class="key"><<&|/l&>Enter</&>></span></td>
+                <td><&|/l&>View highlighted ticket</&></td>
+            </tr>
+        </table>
+    </div>
+</div>
+
+<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/static/js/keyboard-shortcuts/search.js"></script>
+
 <%INIT>
 $m->callback( ARGSRef => \%ARGS, CallbackName => 'Initial' );
 
diff --git a/share/static/css/base/misc.css b/share/static/css/base/misc.css
index 5e088ff..44d4165 100644
--- a/share/static/css/base/misc.css
+++ b/share/static/css/base/misc.css
@@ -85,3 +85,21 @@ textarea.messagebox, #cke_Content, #cke_UpdateContent {
     width: 1em;
     border-style: none;
 }
+
+.keyboard-shortcuts.short {
+    width: 50%;
+}
+
+.keyboard-shortcuts td {
+    text-align: left;
+    padding-right: 5px;
+}
+
+.keyboard-shortcuts .key {
+    color: #3858a3;
+    font-family: 'Courier New';
+}
+
+.keyboard-shortcuts .sm {
+    font-size: 75%;
+}
diff --git a/share/static/css/tipso.min.css b/share/static/css/tipso.min.css
new file mode 100644
index 0000000..fda0e4c
--- /dev/null
+++ b/share/static/css/tipso.min.css
@@ -0,0 +1,2 @@
+/* Tipso Bubble Styles */
+.tipso_bubble,.tipso_bubble > .tipso_arrow{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.tipso_bubble{position:absolute;text-align:center;border-radius:6px;z-index:9999}.tipso_style{cursor:help;border-bottom:1px dotted}.tipso_title{border-radius:6px 6px 0 0}.tipso_content{word-wrap:break-word;padding:0.5em}.tipso_bubble.tiny{font-size:0.6rem}.tipso_bubble.small{font-size:0.8rem}.tipso_bubble.default{font-size:1rem}.tipso_bubble.large{font-size:1.2rem;width:100%}.tipso_bubble > .tipso_arrow{position:absolute;width:0;height:0;border:8px solid;pointer-events:none}.tipso_bubble.top > .tipso_arrow{border-top-color:#000;border-right-color:transparent;border-left-color:transparent;border-bottom-color:transparent;top:100%;left:50%;margin-left:-8px}.tipso_bubble.bottom > .tipso_arrow{border-bottom-color:#000;border-right-color:transparent;border-left-color:transparent;border-top-color:transparent;bottom:100%;left:50%;margin-left:-8px}.tipso_bubble.left > .ti
 pso_arrow{border-left-color:#000;border-top-color:transparent;border-bottom-color:transparent;border-right-color:transparent;top:50%;left:100%;margin-top:-8px}.tipso_bubble.right > .tipso_arrow{border-right-color:#000;border-top-color:transparent;border-bottom-color:transparent;border-left-color:transparent;top:50%;right:100%;margin-top:-8px}.tipso_bubble .top_right_corner,.tipso_bubble.top_right_corner{border-bottom-left-radius:0}.tipso_bubble .bottom_right_corner,.tipso_bubble.bottom_right_corner{border-top-left-radius:0}.tipso_bubble .top_left_corner,.tipso_bubble.top_left_corner{border-bottom-right-radius:0}.tipso_bubble .bottom_left_corner,.tipso_bubble.bottom_left_corner{border-top-right-radius:0}
\ No newline at end of file
diff --git a/share/static/images/keyboard-shortcuts.svg b/share/static/images/keyboard-shortcuts.svg
new file mode 100644
index 0000000..70ae598
--- /dev/null
+++ b/share/static/images/keyboard-shortcuts.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="512px" height="403.983px" viewBox="0 0 512 403.983" enable-background="new 0 0 512 403.983" xml:space="preserve">
+<path d="M32.002,0h447.985C497.672,0,512,14.329,512,31.998V256c0,17.664-14.328,31.992-32.013,31.992H32.002  C14.329,287.992,0,273.664,0,256V31.998C0,14.329,14.329,0,32.002,0z M47.999,47.999v191.995h416.002V47.999H47.999z M80.001,64  h79.996v79.996H80.001V64z M175.999,64h63.995v79.996h-63.995V64z M80.001,160.003h79.996v63.984H80.001V160.003z M175.999,160.003  h159.987v63.984H175.999V160.003z M255.995,64h79.991v79.996h-79.991V64z M351.992,64h79.997v79.996h-79.997V64z M351.992,160.003  h79.997v63.984h-79.997V160.003z M187.998,335.991h135.988l-67.991,67.992L187.998,335.991z" fill="#000000"/>
+</svg>
diff --git a/share/static/js/keyboard-shortcuts/global.js b/share/static/js/keyboard-shortcuts/global.js
new file mode 100644
index 0000000..8236d62
--- /dev/null
+++ b/share/static/js/keyboard-shortcuts/global.js
@@ -0,0 +1,138 @@
+var rtKeyboardShortcuts = (function() {
+    var module = {};
+
+    var _keyDelayThreshold = 1000, // Delay between multi-key commands in milliseconds
+        _lastKeyPressedTimestamp,
+        _lastPressedKeyCode,
+         _keys = [],
+        _secondKeys = [];
+
+    module.add = function(args) {
+        if (args.secondKeyCode) {
+            var modifierExists = Boolean(_keys.filter(function(key) { return key.keyCode === args.keyCode; }).length);
+            if (!modifierExists) {
+                _keys.push({
+                    keyCode: args.keyCode,
+                    modifierKey: true
+                });
+            }
+            _secondKeys.push({
+                keyCode: args.secondKeyCode,
+                callback: args.callback
+            });
+        } else {
+            _keys.push({
+                keyCode: args.keyCode,
+                callback: args.callback
+            });
+        }
+    };
+
+    module.init = function() {
+        jQuery('html').keydown(function(e) {
+            // if we're focusing an input field, ignore keyboard shortcuts
+            if (jQuery('input:focus').length) return;
+
+            // if we sucessfully parsed a double-key shortcut, exit
+            if (parseDoubleKey(e)) {
+                e.preventDefault();
+                return;
+            }
+
+            if (parseSingleKey(e)) e.preventDefault();
+        });
+    };
+
+    function hasModifierKey(keyCode) {
+        return _keys.some(function(key) {
+            return (key.modifierKey && key.keyCode === keyCode);
+        });
+    }
+
+    function parseDoubleKey(keyboardEvent) {
+        if (!_lastKeyPressedTimestamp) return false;
+
+        if (Date.now() - _lastKeyPressedTimestamp > _keyDelayThreshold) {
+            _lastKeyPressedTimestamp = null;
+            return false;
+        }
+
+        _lastKeyPressedTimestamp = null;
+
+        if (!hasModifierKey(_lastPressedKeyCode)) return false;
+
+        return _secondKeys.some(function(key) {
+            if (key.keyCode === keyboardEvent.keyCode) {
+                key.callback(keyboardEvent);
+                return true;
+            }
+        });
+    }
+
+    function parseSingleKey(keyboardEvent) {
+        return _keys.some(function(key) {
+            if (key.keyCode === keyboardEvent.keyCode) {
+                if (key.modifierKey) {
+                    _lastKeyPressedTimestamp = Date.now();
+                    _lastPressedKeyCode = keyboardEvent.keyCode;
+                } else {
+                    key.callback(keyboardEvent);
+                }
+                return true;
+            }
+        });
+    }
+
+    return module;
+}());
+
+jQuery(function() {
+    rtKeyboardShortcuts.add({
+        keyCode: 71,
+        secondKeyCode: 66,
+        callback: function() {
+            window.history.back();
+        }
+    });
+
+    rtKeyboardShortcuts.add({
+        keyCode: 71,
+        secondKeyCode: 70,
+        callback: function() {
+            window.history.forward();
+        }
+    });
+
+    function goHome() {
+        var homeLink = jQuery('a#home');
+        window.location.href = homeLink.attr('href');
+    }
+
+    rtKeyboardShortcuts.add({
+        keyCode: 71,
+        secondKeyCode: 72,
+        callback: function() {
+            goHome();
+        }
+    });
+
+    function simpleSearch() {
+        var searchInput = jQuery('#simple-search').find('input');
+
+        if (!searchInput.length || searchInput.is(':focus')) return false;
+
+        searchInput.focus();
+        searchInput.select();
+
+        return true;
+    }
+
+    rtKeyboardShortcuts.add({
+        keyCode: 191,
+        callback: function() {
+            simpleSearch();
+        }
+    });
+
+    rtKeyboardShortcuts.init();
+});
diff --git a/share/static/js/keyboard-shortcuts/search.js b/share/static/js/keyboard-shortcuts/search.js
new file mode 100644
index 0000000..f190e0c
--- /dev/null
+++ b/share/static/js/keyboard-shortcuts/search.js
@@ -0,0 +1,90 @@
+jQuery(function() {
+    function navigateToCurrentTicket() {
+        if (!currentRow) return;
+        var ticketLink = currentRow.find('a');
+        if (!ticketLink.length) return;
+        window.location.href = ticketLink.attr('href');
+    }
+
+    rtKeyboardShortcuts.add({
+        keyCode: 13,
+        callback: function(e) {
+            navigateToCurrentTicket();
+            e.preventDefault();
+        }
+    });
+
+    rtKeyboardShortcuts.add({
+        keyCode: 79,
+        callback: function(e) {
+            navigateToCurrentTicket();
+            e.preventDefault();
+        }
+    });
+
+    var currentRow;
+
+    function setNewRow(newRow) {
+        if (currentRow) currentRow.attr('style', '');
+        currentRow = newRow;
+        currentRow.attr('style', 'border-left-color: #3858a3; border-left-width: 3px;');
+        scrollToElement(currentRow);
+    }
+
+    function scrollToElement(element) {
+        if (!element.length) return;
+
+        var viewportHeight = jQuery(window).height(),
+            currentScrollPosition = jQuery(window).scrollTop(),
+            currentItemPosition = element.offset().top,
+            currentItemSize = element.height() + element.next().height();
+
+        if (currentScrollPosition + viewportHeight < currentItemPosition + currentItemSize) {
+            jQuery('html, body').scrollTop(currentItemPosition - viewportHeight + currentItemSize);
+        } else if (currentScrollPosition > currentItemPosition) {
+            jQuery('html, body').scrollTop(currentItemPosition);
+        }
+    }
+
+    rtKeyboardShortcuts.add({
+        keyCode: 74,
+        callback: function(e) {
+            var nextRow;
+            var searchResultsTable = jQuery('.ticket-list.collection-as-table');
+            if (!currentRow || !(nextRow = currentRow.next().next(':not(.collection-as-table)')).length) {
+                nextRow = searchResultsTable.find('tr.oddline').first();
+            }
+            setNewRow(nextRow);
+
+            e.preventDefault();
+        }
+    });
+
+    rtKeyboardShortcuts.add({
+        keyCode: 75,
+        callback: function(e) {
+            var prevRow;
+            var searchResultsTable = jQuery('.ticket-list.collection-as-table');
+            if (!currentRow || !(prevRow = currentRow.prev().prev(':not(.collection-as-table)')).length) {
+                prevRow = searchResultsTable.find('tr').last().prev();
+            }
+            setNewRow(prevRow);
+
+            e.preventDefault();
+        }
+    });
+
+    function toggleTicketCheckbox() {
+        if (!currentRow) return;
+        var ticketCheckBox = currentRow.find('input[type=checkbox]');
+        if (!ticketCheckBox.length) return;
+        ticketCheckBox.prop("checked", !ticketCheckBox.prop("checked"));
+    }
+
+    rtKeyboardShortcuts.add({
+        keyCode: 88,
+        callback: function(e) {
+            toggleTicketCheckbox();
+        }
+    });
+});
diff --git a/share/static/js/tipso.min.js b/share/static/js/tipso.min.js
new file mode 100644
index 0000000..178586b
--- /dev/null
+++ b/share/static/js/tipso.min.js
@@ -0,0 +1 @@
+!function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports?module.exports=t(require("jquery")):t(jQuery)}(function(t){function o(o,e){this.element=t(o),this.doc=t(document),this.win=t(window),this.settings=t.extend({},a,e),"object"==typeof this.element.data("tipso")&&t.extend(this.settings,this.element.data("tipso"));for(var r=Object.keys(this.element.data()),s={},i=0;i<r.length;i++){var l=r[i].replace(n,"");if(""!==l){l=l.charAt(0).toLowerCase()+l.slice(1),s[l]=this.element.data(r[i]);for(var p in this.settings)p.toLowerCase()==l&&(this.settings[p]=s[l]);}}this._defaults=a,this._name=n,this._title=this.element.attr("title"),this.mode="hide",this.ieFade=!d,this.settings.preferedPosition=this.settings.position,this.init()}function e(){var t=window.navigator.msMaxTouchPoints,o="ontouchstart"in document.createElement("div");return t||o?!0:!1}function r(o){var e=o.clone();e.css("visibility","hidden"),t("body").append(e);var r=e.outerHeight(),s=e.out
 erWidth();return e.remove(),{width:s,height:r}}function s(t){t.removeClass("top_right_corner bottom_right_corner top_left_corner bottom_left_corner"),t.find(".tipso_title").removeClass("top_right_corner bottom_right_corner top_left_corner bottom_left_corner")}function i(o){var e,n,a,d=o.tooltip(),l=o.element,p=o,f=t(window),c=10,g=p.settings.background,h=p.titleContent();switch(void 0!==h&&""!==h&&(g=p.settings.titleBackground),l.parent().outerWidth()>f.outerWidth()&&(f=l.parent()),p.settings.position){case"top-right":n=l.offset().left+l.outerWidth(),e=l.offset().top-r(d).height-c,d.find(".tipso_arrow").css({marginLeft:-p.settings.arrowWidth,marginTop:""}),e<f.scrollTop()?(e=l.offset().top+l.outerHeight()+c,d.find(".tipso_arrow").css({"border-bottom-color":g,"border-top-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.addClass("bottom_right_corner"),d.find(".tipso_title").addClass("bottom_right_corner"),d.find(".tipso_arrow").css({"b
 order-left-color":g}),d.removeClass("top-right top bottom left right"),d.addClass("bottom")):(d.find(".tipso_arrow").css({"border-top-color":p.settings.background,"border-bottom-color":"transparent ","border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.addClass("top_right_corner"),d.find(".tipso_arrow").css({"border-left-color":p.settings.background}),d.removeClass("top bottom left right"),d.addClass("top"));break;case"top-left":n=l.offset().left-r(d).width,e=l.offset().top-r(d).height-c,d.find(".tipso_arrow").css({marginLeft:-p.settings.arrowWidth,marginTop:""}),e<f.scrollTop()?(e=l.offset().top+l.outerHeight()+c,d.find(".tipso_arrow").css({"border-bottom-color":g,"border-top-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.addClass("bottom_left_corner"),d.find(".tipso_title").addClass("bottom_left_corner"),d.find(".tipso_arrow").css({"border-right-color":g}),d.removeClass("top-right top bottom left right"),
 d.addClass("bottom")):(d.find(".tipso_arrow").css({"border-top-color":p.settings.background,"border-bottom-color":"transparent ","border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.addClass("top_left_corner"),d.find(".tipso_arrow").css({"border-right-color":p.settings.background}),d.removeClass("top bottom left right"),d.addClass("top"));break;case"bottom-right":n=l.offset().left+l.outerWidth(),e=l.offset().top+l.outerHeight()+c,d.find(".tipso_arrow").css({marginLeft:-p.settings.arrowWidth,marginTop:""}),e+r(d).height>f.scrollTop()+f.outerHeight()?(e=l.offset().top-r(d).height-c,d.find(".tipso_arrow").css({"border-bottom-color":"transparent","border-top-color":p.settings.background,"border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.addClass("top_right_corner"),d.find(".tipso_title").addClass("top_left_corner"),d.find(".tipso_arrow").css({"border-left-color":p.settings.background}),d.removeClass("top-right top bottom left right"),d
 .addClass("top")):(d.find(".tipso_arrow").css({"border-top-color":"transparent","border-bottom-color":g,"border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.addClass("bottom_right_corner"),d.find(".tipso_title").addClass("bottom_right_corner"),d.find(".tipso_arrow").css({"border-left-color":g}),d.removeClass("top bottom left right"),d.addClass("bottom"));break;case"bottom-left":n=l.offset().left-r(d).width,e=l.offset().top+l.outerHeight()+c,d.find(".tipso_arrow").css({marginLeft:-p.settings.arrowWidth,marginTop:""}),e+r(d).height>f.scrollTop()+f.outerHeight()?(e=l.offset().top-r(d).height-c,d.find(".tipso_arrow").css({"border-bottom-color":"transparent","border-top-color":p.settings.background,"border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.addClass("top_left_corner"),d.find(".tipso_title").addClass("top_left_corner"),d.find(".tipso_arrow").css({"border-right-color":p.settings.background}),d.removeClass("top-right top bottom lef
 t right"),d.addClass("top")):(d.find(".tipso_arrow").css({"border-top-color":"transparent","border-bottom-color":g,"border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.addClass("bottom_left_corner"),d.find(".tipso_title").addClass("bottom_left_corner"),d.find(".tipso_arrow").css({"border-right-color":g}),d.removeClass("top bottom left right"),d.addClass("bottom"));break;case"top":n=l.offset().left+l.outerWidth()/2-r(d).width/2,e=l.offset().top-r(d).height-c,d.find(".tipso_arrow").css({marginLeft:-p.settings.arrowWidth,marginTop:""}),e<f.scrollTop()?(e=l.offset().top+l.outerHeight()+c,d.find(".tipso_arrow").css({"border-bottom-color":g,"border-top-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),d.removeClass("top bottom left right"),d.addClass("bottom")):(d.find(".tipso_arrow").css({"border-top-color":p.settings.background,"border-bottom-color":"transparent","border-left-color":"transparent","border-right-color":"tr
 ansparent"}),d.removeClass("top bottom left right"),d.addClass("top"));break;case"bottom":n=l.offset().left+l.outerWidth()/2-r(d).width/2,e=l.offset().top+l.outerHeight()+c,d.find(".tipso_arrow").css({marginLeft:-p.settings.arrowWidth,marginTop:""}),e+r(d).height>f.scrollTop()+f.outerHeight()?(e=l.offset().top-r(d).height-c,d.find(".tipso_arrow").css({"border-top-color":p.settings.background,"border-bottom-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),d.removeClass("top bottom left right"),d.addClass("top")):(d.find(".tipso_arrow").css({"border-bottom-color":g,"border-top-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),d.removeClass("top bottom left right"),d.addClass(p.settings.position));break;case"left":n=l.offset().left-r(d).width-c,e=l.offset().top+l.outerHeight()/2-r(d).height/2,d.find(".tipso_arrow").css({marginTop:-p.settings.arrowWidth,marginLeft:""}),n<f.scrollLeft()?(n=l.offset().lef
 t+l.outerWidth()+c,d.find(".tipso_arrow").css({"border-right-color":p.settings.background,"border-left-color":"transparent","border-top-color":"transparent","border-bottom-color":"transparent"}),d.removeClass("top bottom left right"),d.addClass("right")):(d.find(".tipso_arrow").css({"border-left-color":p.settings.background,"border-right-color":"transparent","border-top-color":"transparent","border-bottom-color":"transparent"}),d.removeClass("top bottom left right"),d.addClass(p.settings.position));break;case"right":n=l.offset().left+l.outerWidth()+c,e=l.offset().top+l.outerHeight()/2-r(d).height/2,d.find(".tipso_arrow").css({marginTop:-p.settings.arrowWidth,marginLeft:""}),n+c+p.settings.width>f.scrollLeft()+f.outerWidth()?(n=l.offset().left-r(d).width-c,d.find(".tipso_arrow").css({"border-left-color":p.settings.background,"border-right-color":"transparent","border-top-color":"transparent","border-bottom-color":"transparent"}),d.removeClass("top bottom left right"),d.addClass("left
 ")):(d.find(".tipso_arrow").css({"border-right-color":p.settings.background,"border-left-color":"transparent","border-top-color":"transparent","border-bottom-color":"transparent"}),d.removeClass("top bottom left right"),d.addClass(p.settings.position))}if("top-right"===p.settings.position&&d.find(".tipso_arrow").css({"margin-left":-p.settings.width/2}),"top-left"===p.settings.position){var m=d.find(".tipso_arrow").eq(0);m.css({"margin-left":p.settings.width/2-2*p.settings.arrowWidth})}if("bottom-right"===p.settings.position){var m=d.find(".tipso_arrow").eq(0);m.css({"margin-left":-p.settings.width/2,"margin-top":""})}if("bottom-left"===p.settings.position){var m=d.find(".tipso_arrow").eq(0);m.css({"margin-left":p.settings.width/2-2*p.settings.arrowWidth,"margin-top":""})}n<f.scrollLeft()&&("bottom"===p.settings.position||"top"===p.settings.position)&&(d.find(".tipso_arrow").css({marginLeft:n-p.settings.arrowWidth}),n=0),n+p.settings.width>f.outerWidth()&&("bottom"===p.settings.posit
 ion||"top"===p.settings.position)&&(a=f.outerWidth()-(n+p.settings.width),d.find(".tipso_arrow").css({marginLeft:-a-p.settings.arrowWidth,marginTop:""}),n+=a),n<f.scrollLeft()&&("left"===p.settings.position||"right"===p.settings.position||"top-right"===p.settings.position||"top-left"===p.settings.position||"bottom-right"===p.settings.position||"bottom-left"===p.settings.position)&&(n=l.offset().left+l.outerWidth()/2-r(d).width/2,d.find(".tipso_arrow").css({marginLeft:-p.settings.arrowWidth,marginTop:""}),e=l.offset().top-r(d).height-c,e<f.scrollTop()?(e=l.offset().top+l.outerHeight()+c,d.find(".tipso_arrow").css({"border-bottom-color":g,"border-top-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),d.removeClass("top bottom left right"),s(d),d.addClass("bottom")):(d.find(".tipso_arrow").css({"border-top-color":p.settings.background,"border-bottom-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),d.rem
 oveClass("top bottom left right"),s(d),d.addClass("top")),n+p.settings.width>f.outerWidth()&&(a=f.outerWidth()-(n+p.settings.width),d.find(".tipso_arrow").css({marginLeft:-a-p.settings.arrowWidth,marginTop:""}),n+=a),n<f.scrollLeft()&&(d.find(".tipso_arrow").css({marginLeft:n-p.settings.arrowWidth}),n=0)),n+p.settings.width>f.outerWidth()&&("left"===p.settings.position||"right"===p.settings.position||"top-right"===p.settings.position||"top-left"===p.settings.position||"bottom-right"===p.settings.position||"bottom-right"===p.settings.position)&&(n=l.offset().left+l.outerWidth()/2-r(d).width/2,d.find(".tipso_arrow").css({marginLeft:-p.settings.arrowWidth,marginTop:""}),e=l.offset().top-r(d).height-c,e<f.scrollTop()?(e=l.offset().top+l.outerHeight()+c,d.find(".tipso_arrow").css({"border-bottom-color":g,"border-top-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.removeClass("top bottom left right"),d.addClass("bottom")):(d.find(".tipso_
 arrow").css({"border-top-color":p.settings.background,"border-bottom-color":"transparent","border-left-color":"transparent","border-right-color":"transparent"}),s(d),d.removeClass("top bottom left right"),d.addClass("top")),n+p.settings.width>f.outerWidth()&&(a=f.outerWidth()-(n+p.settings.width),d.find(".tipso_arrow").css({marginLeft:-a-p.settings.arrowWidth,marginTop:""}),n+=a),n<f.scrollLeft()&&(d.find(".tipso_arrow").css({marginLeft:n-p.settings.arrowWidth}),n=0)),d.css({left:n+p.settings.offsetX,top:e+p.settings.offsetY}),e<f.scrollTop()&&("right"===p.settings.position||"left"===p.settings.position)&&(l.tipso("update","position","bottom"),i(p)),e+r(d).height>f.scrollTop()+f.outerHeight()&&("right"===p.settings.position||"left"===p.settings.position)&&(l.tipso("update","position","top"),i(p))}var n="tipso",a={speed:400,background:"#55b555",titleBackground:"#333333",color:"#ffffff",titleColor:"#ffffff",titleContent:"",showArrow:!0,position:"top",width:200,maxWidth:"",delay:200,an
 imationIn:"",animationOut:"",offsetX:0,offsetY:0,arrowWidth:8,tooltipHover:!1,content:null,ajaxContentUrl:null,contentElementId:null,useTitle:!1,templateEngineFunc:null,onBeforeShow:null,onShow:null,onHide:null};t.extend(o.prototype,{init:function(){var t=this,o=this.element,r=this.doc;if(o.addClass("tipso_style").removeAttr("title"),e())o.on("click."+n,function(o){"hide"===t.mode?t.show():t.hide(),o.stopPropagation()}),r.on("click",function(){"show"===t.mode&&t.hide()});else if(t.settings.tooltipHover){var s=null,i=null;o.on("mouseover."+n,function(){clearTimeout(s),clearTimeout(i),i=setTimeout(function(){t.show()},150)}),o.on("mouseout."+n,function(){clearTimeout(s),clearTimeout(i),s=setTimeout(function(){t.hide()},200),t.tooltip().on("mouseover."+n,function(){t.mode="tooltipHover"}).on("mouseout."+n,function(){t.mode="show",clearTimeout(s),s=setTimeout(function(){t.hide()},200)})})}else o.on("mouseover."+n,function(){t.show()}),o.on("mouseout."+n,function(){t.hide()})},tooltip:fu
 nction(){return this.tipso_bubble||(this.tipso_bubble=t('<div class="tipso_bubble"><div class="tipso_title"></div><div class="tipso_content"></div><div class="tipso_arrow"></div></div>')),this.tipso_bubble},show:function(){var o=this.tooltip(),e=this,r=this.win;e.settings.showArrow===!1?o.find(".tipso_arrow").hide():o.find(".tipso_arrow").show(),"hide"===e.mode&&(t.isFunction(e.settings.onBeforeShow)&&e.settings.onBeforeShow(this.element,this),e.settings.size&&o.addClass(e.settings.size),e.settings.width?o.css({background:e.settings.background,color:e.settings.color,width:e.settings.width}).hide():e.settings.maxWidth?o.css({background:e.settings.background,color:e.settings.color,maxWidth:e.settings.maxWidth}).hide():o.css({background:e.settings.background,color:e.settings.color,width:200}).hide(),o.find(".tipso_title").css({background:e.settings.titleBackground,color:e.settings.titleColor}),o.find(".tipso_content").html(e.content()),o.find(".tipso_title").html(e.titleContent()),i(e)
 ,r.resize(function(){e.settings.position=e.settings.preferedPosition,i(e)}),e.timeout=window.setTimeout(function(){e.ieFade||""===e.settings.animationIn||""===e.settings.animationOut?o.appendTo("body").stop(!0,!0).fadeIn(e.settings.speed,function(){e.mode="show",t.isFunction(e.settings.onShow)&&e.settings.onShow(this.element,this)}):o.remove().appendTo("body").stop(!0,!0).removeClass("animated "+e.settings.animationOut).addClass("noAnimation").removeClass("noAnimation").addClass("animated "+e.settings.animationIn).fadeIn(e.settings.speed,function(){t(this).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){t(this).removeClass("animated "+e.settings.animationIn)}),e.mode="show",t.isFunction(e.settings.onShow)&&e.settings.onShow(this.element,this),r.off("resize",null,"tipsoResizeHandler")})},e.settings.delay))},hide:function(){var o=this,e=this.win;tipso_bubble=this.tooltip(),window.clearTimeout(o.timeout),o.timeout=null,"tooltipHover"!==o.mo
 de&&(o.ieFade||""===o.settings.animationIn||""===o.settings.animationOut?tipso_bubble.stop(!0,!0).fadeOut(o.settings.speed,function(){t(this).remove(),t.isFunction(o.settings.onHide)&&"show"===o.mode&&o.settings.onHide(this.element,this),o.mode="hide",e.off("resize",null,"tipsoResizeHandler")}):tipso_bubble.stop(!0,!0).removeClass("animated "+o.settings.animationIn).addClass("noAnimation").removeClass("noAnimation").addClass("animated "+o.settings.animationOut).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){t(this).removeClass("animated "+o.settings.animationOut).remove(),t.isFunction(o.settings.onHide)&&"show"===o.mode&&o.settings.onHide(this.element,this),o.mode="hide",e.off("resize",null,"tipsoResizeHandler")}))},destroy:function(){var t=this.element,o=this.win,r=this.doc;t.off("."+n),o.off("resize",null,"tipsoResizeHandler"),e()&&r.off("click",null,"closeTipso"),t.removeData(n),t.removeClass("tipso_style").attr("title",this._title)}
 ,titleContent:function(){var t,o=this.element,e=this;return t=e.settings.titleContent?e.settings.titleContent:o.data("tipso-title")},content:function(){var o,e=this.element,r=this,s=this._title;return r.settings.ajaxContentUrl?o=t.ajax({type:"GET",url:r.settings.ajaxContentUrl,async:!1}).responseText:r.settings.contentElementId?o=t("#"+r.settings.contentElementId).text():r.settings.content?o=r.settings.content:r.settings.useTitle===!0?o=s:"string"==typeof e.data("tipso")&&(o=e.data("tipso")),null!==r.settings.templateEngineFunc&&(o=r.settings.templateEngineFunc(o)),o},update:function(t,o){var e=this;return o?void(e.settings[t]=o):e.settings[t]}});var d=function(){var t=document.createElement("p").style,o=["ms","O","Moz","Webkit"];if(""===t.transition)return!0;for(;o.length;)if(o.pop()+"Transition"in t)return!0;return!1}();t[n]=t.fn[n]=function(e){var r=arguments;if(void 0===e||"object"==typeof e)return this instanceof t||t.extend(a,e),this.each(function(){t.data(this,"plugin_"+n)||t
 .data(this,"plugin_"+n,new o(this,e))});if("string"==typeof e&&"_"!==e[0]&&"init"!==e){var s;return this.each(function(){var i=t.data(this,"plugin_"+n);i||(i=t.data(this,"plugin_"+n,new o(this,e))),i instanceof o&&"function"==typeof i[e]&&(s=i[e].apply(i,Array.prototype.slice.call(r,1))),"destroy"===e&&t.data(this,"plugin_"+n,null)}),void 0!==s?s:this}}});
\ No newline at end of file

-----------------------------------------------------------------------


More information about the rt-commit mailing list