[ADD] ZeroClipboard-based "copy" button on snippets
authorXavier Morel <xmo@openerp.com>
Fri, 7 Nov 2014 13:00:49 +0000 (14:00 +0100)
committerXavier Morel <xmo@openerp.com>
Fri, 7 Nov 2014 13:01:32 +0000 (14:01 +0100)
Also fix ruby setup code, some of its bits were actually Python and didn't
quite work when pasted into irb...

doc/_themes/odoodoc/static/app.js
doc/_themes/odoodoc/static/style.css
doc/_themes/odoodoc/static/style.less
doc/modules/api_integration.rst

index 36a2dcf..47c33f4 100644 (file)
@@ -35,28 +35,28 @@ $(function () {
     * actually not all blocks because we don't want to add the setup bits to
       the setup bits, so that's kinda shit
      */
-    document.addEventListener('copy', function (e) {
-        var target = $(e.target).closest('.switchable:not(.setup)').get(0);
-        // not in a switchable
-        if (!target) { return; }
-        var lang = getHighlightLanguage(target);
-        if (!lang) {
-            // switchable without highlight (e.g. language-specific notes),
-            // don't munge
-            return;
-        }
-        e.preventDefault();
 
-        // get generic setup code
-        var prefix = document.querySelector('.setupcode.highlight-' + lang).textContent;
+    document.addEventListener('copy', copyCode);
 
-        // prepend setup code to current snippet, get all of current snippet
-        // in case only part of it was selected
-        var data = prefix + target.textContent;
-        // sane browsers
-        e.clipboardData.setData('text/plain', data);
-        // MSIE
-        e.clipboardData.setData('Text', data);
+    ZeroClipboard.config({
+        swfPath: '../_static/zeroclipboard-2.1.6/ZeroClipboard.swf',
+        flashLoadTimeout: 3e3,
+    });
+    var zc = new ZeroClipboard();
+    zc.on('ready', function () {
+        var $highlighted = $('.switchable:not(.setup) .highlight').addClass('with-btn-clipboard');
+        var $clipboard_buttons =
+            $('<button type="button" class="btn-clipboard">Copy</button>')
+            .on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
+                $(this).removeClass('active');
+            })
+            .prependTo($highlighted);
+        zc.clip($clipboard_buttons);
+    });
+    zc.on('copy', function (e) {
+        // yellow flash
+        $(e.target).addClass('active');
+        copyCode(e);
     });
 
     // stripe page stuff
@@ -96,6 +96,36 @@ $(function () {
         });
     })(); }
 
+
+    function copyCode(e) {
+        // works for both C-c and "Copy" button if copy button is injected
+        // inside highlighted code section
+        var target = $(e.target).closest('.switchable:not(.setup)').get(0);
+        // not in a switchable
+        if (!target) { return; }
+        var lang = getHighlightLanguage(target);
+        if (!lang) {
+            // switchable without highlight (e.g. language-specific notes),
+            // don't munge
+            return;
+        }
+
+        // get generic setup code
+        var setup_selector = '.setupcode.highlight-' + lang + ' pre';
+        var setup = document.querySelector(setup_selector).textContent;
+
+        // prepend setup code to current snippet, get all of current snippet
+        // in case only part of it was selected. Ensure we don't get e.g.
+        // button text around snippet itself
+        var data = setup + '\n' + target.querySelector('pre').textContent;
+        // sane browsers & ZeroClipboard
+        e.clipboardData.setData('text/plain', data);
+        // MSIE
+        e.clipboardData.setData('Text', data);
+
+        // no preventDefault on ZC event
+        e.preventDefault && e.preventDefault();
+    }
     /**
      * @param {Node} node highlight node to get the language of
      * @returns {String|null} either the highlight language or null
index fba3309..443cae9 100644 (file)
@@ -6653,23 +6653,20 @@ div.section > h2 {
   word-break: normal;
   word-wrap: normal;
 }
+.switchable .highlight.with-btn-clipboard pre {
+  padding-right: 50px;
+}
 /*
  * ZeroClipboard styles
  */
-.zero-clipboard {
+.highlight {
   position: relative;
-  display: none;
-}
-@media (min-width: 768px) {
-  .zero-clipboard {
-    display: block;
-  }
 }
 .btn-clipboard {
   position: absolute;
   top: 0;
   right: 0;
-  z-index: 10;
+  z-index: 3;
   display: block;
   padding: 5px 8px;
   font-size: 12px;
@@ -6679,10 +6676,14 @@ div.section > h2 {
   border: 1px solid #e1e1e8;
   border-radius: 0 4px 0 4px;
 }
-.btn-clipboard-hover {
-  color: #fff;
-  background-color: #a24689;
-  border-color: #a24689;
+.btn-clipboard:focus {
+  outline: none;
+}
+.btn-clipboard.active {
+  background-color: #ffffad;
+  -webkit-transition: background-color 0.5s linear;
+  -o-transition: background-color 0.5s linear;
+  transition: background-color 0.5s linear;
 }
 img.align-center {
   display: block;
index 7107647..a896e01 100644 (file)
@@ -473,23 +473,22 @@ div.section > h2 {
   word-break: normal;
   word-wrap: normal;
 }
+.switchable .highlight.with-btn-clipboard pre {
+  // avoid copy button overlapping with even long lines
+  padding-right: 50px;
+}
 
 /*
  * ZeroClipboard styles
  */
-
-.zero-clipboard {
+.highlight {
   position: relative;
-  display: none;
-  @media (min-width: @screen-sm-min) {
-    display: block;
-  }
 }
 .btn-clipboard {
   position: absolute;
   top: 0;
   right: 0;
-  z-index: 10;
+  z-index: 3;
   display: block;
   padding: 5px 8px;
   font-size: 12px;
@@ -498,11 +497,15 @@ div.section > h2 {
   background-color: #fff;
   border: 1px solid #e1e1e8;
   border-radius: 0 4px 0 4px;
-}
-.btn-clipboard-hover {
-  color: #fff;
-  background-color: @brand-primary;
-  border-color: @brand-primary;
+
+  &:focus {
+    outline: none;
+  }
+
+  &.active {
+    background-color: #ffffad;
+    .transition(background-color .5s linear);
+  }
 }
 
 // rST styles
index 4330197..21d0163 100644 (file)
@@ -43,8 +43,8 @@ Connection and authentication
         url, db, username, password = \
             info['host'], info['database'], info['user'], info['password']
         common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common")
-        uid = common.authenticate(db, username, password, {})
-        models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))
+        uid = common.call('authenticate', db, username, password, {})
+        models = XMLRPC::Client.new2("#{url}/xmlrpc/2/object").proxy
 
     .. code-block:: php