如何让KnokoutJS和ClipboardJS协同工作?

时间:2016-10-30 21:33:33

标签: javascript knockout.js clipboard clipboard.js

我尝试将一些来自Knockout foreach的信息复制到剪贴板:

<?php
    // ***************************************************
    if (!function_exists('gzdecode'))
    {
        function gzdecode($data) 
        {
            // strip header and footer and inflate
            return gzinflate(substr($data, 10, -8));
        }
    }
    // ***************************************************

    // get compressed (gzip) POST request into a string
    $comprReq = file_get_contents('php://input');

    // get decompressed POST request
    $decomprReq = gzdecode($comprReq);

    // decode to json
    $jsonData = json_decode($decomprReq, true);

    // create file if not exits or open file if exists
    $file = fopen('omni.json', 'a');

    if ($jsonData === null)
    {
        // mark as invalid and save. send HTTP response
        fwrite($file, 'invalid json');
        fclose($file);
        header('HTTP/1.0 400 Bad Request');
    }
    else 
    {
        // write json and save. send HTTP response
        fwrite($file, $jsonData);
        fclose($file);
        header('HTTP/1.0 200 OK');          
    }
?>

使用ClipboardJS:

<tbody data-bind="foreach: selections">
    <tr>
        <td>
            <a href="#" class="copy_btn" data-bind="attr: { 'data-clipboard-text' : name}"><i class="fa fa-copy"></i></a>
        </td>
    </tr>
</tbody>

但它没有复制。 我做错了什么?

4 个答案:

答案 0 :(得分:1)

所以,也许有人需要:

ko.bindingHandlers.clipboard = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var clipboard = new Clipboard(element);
    }
};

<a href="#" class="copy_btn" data-bind="clipboard, attr: { 'data-clipboard-text' : name, title: 'Copy to clipboard'}"><i class="fa fa-copy"></i></a>

答案 1 :(得分:0)

好的,谢谢@devspec的初步答复。我以一些关键的方式建立了它:

所以我的最终绑定处理程序是:

ko.bindingHandlers.clipboard = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
            // This will be called when the binding is first applied to an element
            // Set up any initial state, event handlers, etc. here
            var options = ko.unwrap(valueAccessor());
            if(options.textComputed) {
                options.text = function(nodeToIgnore) { return options.textComputed(); };
            }

            if(options.onmodal) {
                options.container = element;
            }

            var cboard = new Clipboard(element, options);
            if(options.success) {
                cboard.on('success', options.success);
            }
            if(options.error) {
                cboard.on('error', options.error);
            }



            ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
                        // This will be called when the element is removed by Knockout or
                        // if some other part of your code calls ko.removeNode(element)
                        cboard.destroy();
                    });
        },
}

使用的一个例子是:

Html:

<a href="#" data-bind="clipboard: { onmodal: true, textComputed: command, success: function(event) { copyCommandResult(true, event); },
error: function(event) { copyCommandResult(false, event); }}"><small
    data-bind="text: clipboardLink ">copy to clipboard</small></a>
视图模型命令上的

是计算的,如果它是一个返回字符串的函数(没有参数),则只能使用text属性

copyCommandResult只是:

 self.copyCommandResult = function(success, e) {
//    console.log("Copy to clipboard success? " + success)
//    console.info('Action:', e.action);
//    console.info('Text:', e.text);
//    console.info('Trigger:', e.trigger);

    if(success) {
      self.clipboardLink("Copied successfully!");
    } else {
      self.clipboardLink("Could not copy to clipboard");
    }
    setTimeout(function(){ self.clipboardLink(DEFAULT_CLIPBOARD_LINK_TEXT); }, 3000);

  }

答案 2 :(得分:0)

如果有人需要TypeScript绑定,该绑定支持用于显示ViewModel中定义的成功或错误消息的回调:

import * as Clipboard from 'clipboard'
import * as ko from 'knockout';

/**
 * Clipboard binding parameters.
 */
interface BindingContext {

    /**
     * Optional callback function which is executed on copy success - e.g show a success message
     */
    successCallback: Function;

    /**
     * Optional callback function which is executed on copy error - e.g show an error message
     */
    errorCallback: Function;

    /**
     * Optional args for the callback function
     */
    args: Array<any>;
}

/**
 * A binding handler for ClipboardJS
 */
class ClipboardBinding implements KnockoutBindingHandler {

    init(element: Element, valueAccessor: () => BindingContext, allBindings: KnockoutAllBindingsAccessor, viewModel: any) {
        const params = ko.unwrap(valueAccessor());
        const successCallback = params.successCallback ? params.successCallback : null;
        const errorCallback = params.successCallback ? params.successCallback : null;
        const args = params.args ? params.args : [];

        // init clipboard
        const clipboard = new Clipboard(element);

        // register success callback
        if (typeof successCallback === 'function') {
            clipboard.on('success', function (e) {
                console.debug('Clipboard event:', e);
                successCallback.apply(viewModel, args);
            });
        }

        // register error callback
        if (typeof errorCallback === 'function') {
            clipboard.on('error', function (e) {
                console.debug('Clipboard event:', e);
                errorCallback.apply(viewModel, args);
            });
        }
    }
}

export default new ClipboardBinding();

HTML:

<button class="btn btn-primary" data-bind="
    clipboard: {
        successCallback: $component.showCopySuccessMessage,
        errorCallback: $component.showCopyErrorMessage
    },
    attr: {
        'data-clipboard-text': 'Text to copy'
    }">Copy to Clipboard</button>

答案 3 :(得分:-1)

self.functionName = function(text) {
var input = document.body.appendChild(document.createElement("input"));
input.value = text;
input.focus();
input.select();
document.execCommand('copy');
input.parentNode.removeChild(input);
}