From 5d79dd80e578c39a45f1603fbae665772ffaa446 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 7 Nov 2014 14:00:49 +0100 Subject: [PATCH] [ADD] ZeroClipboard-based "copy" button on snippets 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 | 70 +++++++++++++++++++-------- doc/_themes/odoodoc/static/style.css | 25 +++++----- doc/_themes/odoodoc/static/style.less | 27 ++++++----- doc/modules/api_integration.rst | 4 +- 4 files changed, 80 insertions(+), 46 deletions(-) diff --git a/doc/_themes/odoodoc/static/app.js b/doc/_themes/odoodoc/static/app.js index 36a2dcff57e..47c33f41d23 100644 --- a/doc/_themes/odoodoc/static/app.js +++ b/doc/_themes/odoodoc/static/app.js @@ -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 = + $('') + .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 diff --git a/doc/_themes/odoodoc/static/style.css b/doc/_themes/odoodoc/static/style.css index fba330944dd..443cae9b7b5 100644 --- a/doc/_themes/odoodoc/static/style.css +++ b/doc/_themes/odoodoc/static/style.css @@ -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; diff --git a/doc/_themes/odoodoc/static/style.less b/doc/_themes/odoodoc/static/style.less index 71076470e7b..a896e01e170 100644 --- a/doc/_themes/odoodoc/static/style.less +++ b/doc/_themes/odoodoc/static/style.less @@ -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 diff --git a/doc/modules/api_integration.rst b/doc/modules/api_integration.rst index 43301979d0a..21d0163ba46 100644 --- a/doc/modules/api_integration.rst +++ b/doc/modules/api_integration.rst @@ -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