/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ RED.clipboard = (function() { var dialog; var dialogContainer; var exportNodesDialog; var importNodesDialog; var disabled = false; var popover; var currentPopoverError; function setupDialogs() { dialog = $('
') .appendTo("body") .dialog({ modal: true, autoOpen: false, width: 500, resizable: false, buttons: [ { id: "clipboard-dialog-cancel", text: RED._("common.label.cancel"), click: function() { $( this ).dialog( "close" ); } }, { id: "clipboard-dialog-close", class: "primary", text: RED._("common.label.close"), click: function() { $( this ).dialog( "close" ); } }, { id: "clipboard-dialog-copy", class: "primary", text: RED._("clipboard.export.copy"), click: function() { $("#clipboard-export").select(); document.execCommand("copy"); document.getSelection().removeAllRanges(); RED.notify(RED._("clipboard.nodesExported")); $( this ).dialog( "close" ); } }, { id: "clipboard-dialog-ok", class: "primary", text: RED._("common.label.import"), click: function() { RED.view.importNodes($("#clipboard-import").val(),$("#import-tab > a.selected").attr('id') === 'import-tab-new'); $( this ).dialog( "close" ); } } ], open: function(e) { $(this).parent().find(".ui-dialog-titlebar-close").hide(); }, close: function(e) { popover.close(true); currentPopoverError = null; } }); dialogContainer = dialog.children(".dialog-form"); exportNodesDialog = '
'+ ''+ ''+ ''+ ''+ ''+ ''+ '
'+ '
'+ ''+ '
'+ '
'+ ''+ ''+ ''+ ''+ '
'; importNodesDialog = '
'+ ''+ '
'+ '
'+ ''+ ''+ ''+ ''+ ''+ '
'; } function validateImport() { var importInput = $("#clipboard-import"); var v = importInput.val().trim(); if (v === "") { popover.close(true); currentPopoverError = null; importInput.removeClass("input-error"); $("#clipboard-dialog-ok").button("disable"); return; } try { if (!/^\[[\s\S]*\]$/m.test(v)) { throw new Error(RED._("clipboard.import.errors.notArray")); } var res = JSON.parse(v); for (var i=0;i').text(errString); var errorPos; // Chrome error messages var m = /at position (\d+)/i.exec(errString); if (m) { errorPos = parseInt(m[1]); } else { // Firefox error messages m = /at line (\d+) column (\d+)/i.exec(errString); if (m) { var line = parseInt(m[1])-1; var col = parseInt(m[2])-1; var lines = v.split("\n"); errorPos = 0; for (var i=0;i').appendTo(message); var code = $('
').appendTo(parseError);
                        $('').text(v.substring(errorPos-12,errorPos)).appendTo(code)
                        $('').text(v.charAt(errorPos)).appendTo(code);
                        $('').text(v.substring(errorPos+1,errorPos+12)).appendTo(code);
                    }
                    popover.close(true).setContent(message).open();
                    currentPopoverError = errString;
                }
            } else {
                currentPopoverError = null;
            }
            $("#clipboard-dialog-ok").button("disable");
        }
    }

    function importNodes() {
        if (disabled) {
            return;
        }
        dialogContainer.empty();
        dialogContainer.append($(importNodesDialog));
        dialogContainer.i18n();

        $("#clipboard-dialog-ok").show();
        $("#clipboard-dialog-cancel").show();
        $("#clipboard-dialog-close").hide();
        $("#clipboard-dialog-copy").hide();
        $("#clipboard-dialog-ok").button("disable");
        $("#clipboard-import").keyup(validateImport);
        $("#clipboard-import").on('paste',function() { setTimeout(validateImport,10)});

        $("#import-tab > a").click(function(evt) {
            evt.preventDefault();
            if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
                return;
            }
            $(this).parent().children().removeClass('selected');
            $(this).addClass('selected');
        });

        dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open");
        popover = RED.popover.create({
            target: $("#clipboard-import"),
            trigger: "manual",
            direction: "bottom",
            content: ""
        });
    }

    function exportNodes() {
        if (disabled) {
            return;
        }

        dialogContainer.empty();
        dialogContainer.append($(exportNodesDialog));
        dialogContainer.i18n();
        var format = RED.settings.flowFilePretty ? "export-format-full" : "export-format-mini";

        $("#export-format-group > a").click(function(evt) {
            evt.preventDefault();
            if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
                $("#clipboard-export").focus();
                return;
            }
            $(this).parent().children().removeClass('selected');
            $(this).addClass('selected');

            var flow = $("#clipboard-export").val();
            if (flow.length > 0) {
                var nodes = JSON.parse(flow);

                format = $(this).attr('id');
                if (format === 'export-format-full') {
                    flow = JSON.stringify(nodes,null,4);
                } else {
                    flow = JSON.stringify(nodes);
                }
                $("#clipboard-export").val(flow);
                $("#clipboard-export").focus();
            }
        });

        $("#export-range-group > a").click(function(evt) {
            evt.preventDefault();
            if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
                $("#clipboard-export").focus();
                return;
            }
            $(this).parent().children().removeClass('selected');
            $(this).addClass('selected');
            var type = $(this).attr('id');
            var flow = "";
            var nodes = null;
            if (type === 'export-range-selected') {
                var selection = RED.view.selection();
                // Don't include the subflow meta-port nodes in the exported selection
                nodes = RED.nodes.createExportableNodeSet(selection.nodes.filter(function(n) { return n.type !== 'subflow'}));
            } else if (type === 'export-range-flow') {
                var activeWorkspace = RED.workspaces.active();
                nodes = RED.nodes.filterNodes({z:activeWorkspace});
                var parentNode = RED.nodes.workspace(activeWorkspace)||RED.nodes.subflow(activeWorkspace);
                nodes.unshift(parentNode);
                nodes = RED.nodes.createExportableNodeSet(nodes);
            } else if (type === 'export-range-full') {
                nodes = RED.nodes.createCompleteNodeSet(false);
            }
            if (nodes !== null) {
                if (format === "export-format-full") {
                    flow = JSON.stringify(nodes,null,4);
                } else {
                    flow = JSON.stringify(nodes);
                }
            }
            if (flow.length > 0) {
                $("#export-copy").removeClass('disabled');
            } else {
                $("#export-copy").addClass('disabled');
            }
            $("#clipboard-export").val(flow);
            $("#clipboard-export").focus();
        })

        $("#clipboard-dialog-ok").hide();
        $("#clipboard-dialog-cancel").hide();
        $("#clipboard-dialog-copy").hide();
        $("#clipboard-dialog-close").hide();
        var selection = RED.view.selection();
        if (selection.nodes) {
            $("#export-range-selected").click();
        } else {
            $("#export-range-selected").addClass('disabled').removeClass('selected');
            $("#export-range-flow").click();
        }
        if (format === "export-format-full") {
            $("#export-format-full").click();
        } else {
            $("#export-format-mini").click();
        }
        $("#clipboard-export")
            .focus(function() {
                var textarea = $(this);
                textarea.select();
                textarea.mouseup(function() {
                    textarea.unbind("mouseup");
                    return false;
                })
            });
        dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );

        $("#clipboard-export").focus();
        if (!document.queryCommandSupported("copy")) {
            $("#clipboard-dialog-cancel").hide();
            $("#clipboard-dialog-close").show();
        } else {
            $("#clipboard-dialog-cancel").show();
            $("#clipboard-dialog-copy").show();
        }
    }

    function hideDropTarget() {
        $("#dropTarget").hide();
        RED.keyboard.remove("escape");
    }
    function copyText(value,element,msg) {
        var truncated = false;
        if (typeof value !== "string" ) {
            value = JSON.stringify(value, function(key,value) {
                if (value !== null && typeof value === 'object') {
                    if (value.__enc__) {
                        if (value.hasOwnProperty('data') && value.hasOwnProperty('length')) {
                            truncated = value.data.length !== value.length;
                            return value.data;
                        }
                        if (value.type === 'function' || value.type === 'internal') {
                            return undefined
                        }
                        if (value.type === 'number') {
                            // Handle NaN and Infinity - they are not permitted
                            // in JSON. We can either substitute with a String
                            // representation or null
                            return null;
                        }
                    }
                }
                return value;
            });
        }
        if (truncated) {
            msg += "_truncated";
        }
        $("#clipboard-hidden").val(value).select();
        var result =  document.execCommand("copy");
        if (result && element) {
            var popover = RED.popover.create({
                target: element,
                direction: 'left',
                size: 'small',
                content: RED._(msg)
            });
            setTimeout(function() {
                popover.close();
            },1000);
            popover.open();
        }
        return result;
    }
    return {
        init: function() {
            setupDialogs();

            $('').appendTo("body");

            RED.actions.add("core:show-export-dialog",exportNodes);
            RED.actions.add("core:show-import-dialog",importNodes);


            RED.events.on("editor:open",function() { disabled = true; });
            RED.events.on("editor:close",function() { disabled = false; });
            RED.events.on("search:open",function() { disabled = true; });
            RED.events.on("search:close",function() { disabled = false; });
            RED.events.on("type-search:open",function() { disabled = true; });
            RED.events.on("type-search:close",function() { disabled = false; });


            $('#chart').on("dragenter",function(event) {
                if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
                     $.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
                    $("#dropTarget").css({display:'table'});
                    RED.keyboard.add("*", "escape" ,hideDropTarget);
                }
            });

            $('#dropTarget').on("dragover",function(event) {
                if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
                     $.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
                    event.preventDefault();
                }
            })
            .on("dragleave",function(event) {
                hideDropTarget();
            })
            .on("drop",function(event) {
                if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
                    var data = event.originalEvent.dataTransfer.getData("text/plain");
                    data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
                    RED.view.importNodes(data);
                } else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
                    var files = event.originalEvent.dataTransfer.files;
                    if (files.length === 1) {
                        var file = files[0];
                        var reader = new FileReader();
                        reader.onload = (function(theFile) {
                            return function(e) {
                                RED.view.importNodes(e.target.result);
                            };
                        })(file);
                        reader.readAsText(file);
                    }
                }
                hideDropTarget();
                event.preventDefault();
            });

        },
        import: importNodes,
        export: exportNodes,
        copyText: copyText
    }
})();