From 09d6741a024603ebae5bd098b3bc747ba6511713 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 12 Mar 2014 02:42:47 +0400 Subject: [PATCH] fix clipboard on old webkit versions --- lib/ace/keyboard/textinput.js | 92 ++++++++++++++--------------------- lib/ace/lib/useragent.js | 5 +- 2 files changed, 39 insertions(+), 58 deletions(-) diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index eb27026a..7cba4077 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -36,6 +36,7 @@ var useragent = require("../lib/useragent"); var dom = require("../lib/dom"); var lang = require("../lib/lang"); var BROKEN_SETDATA = useragent.isChrome < 18; +var USE_IE_MIME_TIPE = useragent.isIE; var TextInput = function(parentNode, host) { var text = dom.createElement("textarea"); @@ -54,7 +55,6 @@ var TextInput = function(parentNode, host) { var PLACEHOLDER = "\x01\x01"; - var cut = false; var copied = false; var pasted = false; var inComposition = false; @@ -186,9 +186,7 @@ var TextInput = function(parentNode, host) { } var onSelect = function(e) { - if (cut) { - cut = false; - } else if (copied) { + if (copied) { copied = false; } else if (isAllSelected(text)) { host.selectAll(); @@ -243,55 +241,31 @@ var TextInput = function(parentNode, host) { sendText(data); resetValue(); }; - - var onCut = function(e) { - var data = host.getCopyText(); - if (!data) { - event.preventDefault(e); - return; - } - + + var handleClipboardData = function(e, data) { var clipboardData = e.clipboardData || window.clipboardData; - - if (clipboardData && !BROKEN_SETDATA) { - // Safari 5 has clipboardData object, but does not handle setData() - var supported = clipboardData.setData("Text", data); - if (supported) { - host.onCut(); - event.preventDefault(e); - } - } - - if (!supported) { - cut = true; - text.value = data; - text.select(); - setTimeout(function(){ - cut = false; - resetValue(); - resetSelection(); - host.onCut(); - }); - } - }; - - var onCopy = function(e) { - var data = host.getCopyText(); - if (!data) { - event.preventDefault(e); + if (!clipboardData || BROKEN_SETDATA) return; - } - - var clipboardData = e.clipboardData || window.clipboardData; - if (clipboardData && !BROKEN_SETDATA) { + // using "Text" doesn't work on old webkit but ie needs it + // TODO are there other browsers that require "Text"? + var mime = USE_IE_MIME_TIPE ? "Text" : "text/plain"; + if (data) { // Safari 5 has clipboardData object, but does not handle setData() - var supported = clipboardData.setData("Text", data); - if (supported) { - host.onCopy(); - event.preventDefault(e); - } + return clipboardData.setData(mime, data); + } else { + return clipboardData.getData(mime); } - if (!supported) { + } + + var doCopy = function(e, isCut) { + var data = host.getCopyText(); + if (!data) + return event.preventDefault(e); + + if (handleClipboardData(e, data)) { + isCut ? host.onCut() : host.onCopy(); + event.preventDefault(e); + } else { copied = true; text.value = data; text.select(); @@ -299,16 +273,22 @@ var TextInput = function(parentNode, host) { copied = false; resetValue(); resetSelection(); - host.onCopy(); + isCut ? host.onCut() : host.onCopy(); }); } }; - + + var onCut = function(e) { + doCopy(e, true); + } + + var onCopy = function(e) { + doCopy(e, false); + } + var onPaste = function(e) { - var clipboardData = e.clipboardData || window.clipboardData; - - if (clipboardData) { - var data = clipboardData.getData("Text"); + var data = handleClipboardData(e); + if (typeof data == "string") { if (data) host.onPaste(data); if (useragent.isIE) @@ -336,7 +316,7 @@ var TextInput = function(parentNode, host) { if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)){ event.addListener(parentNode, "keydown", function(e) { if ((useragent.isMac && !e.metaKey) || !e.ctrlKey) - return; + return; switch (e.keyCode) { case 67: diff --git a/lib/ace/lib/useragent.js b/lib/ace/lib/useragent.js index 908a2a4c..e56e89a9 100644 --- a/lib/ace/lib/useragent.js +++ b/lib/ace/lib/useragent.js @@ -76,7 +76,8 @@ exports.isLinux = (os == "linux"); // Windows Store JavaScript apps (aka Metro apps written in HTML5 and JavaScript) do not use the "Microsoft Internet Explorer" string in their user agent, but "MSAppHost" instead. exports.isIE = (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0) - && parseFloat(navigator.userAgent.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:|MSIE )([0-9]+[\.0-9]+)/)[1]); + ? parseFloat((ua.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]) + : parseFloat((ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]); // for ie exports.isOldIE = exports.isIE && exports.isIE < 9; @@ -84,7 +85,7 @@ exports.isOldIE = exports.isIE && exports.isIE < 9; exports.isGecko = exports.isMozilla = window.controllers && window.navigator.product === "Gecko"; // oldGecko == rev < 2.0 -exports.isOldGecko = exports.isGecko && parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1], 10) < 4; +exports.isOldGecko = exports.isGecko && parseInt((ua.match(/rv\:(\d+)/)||[])[1], 10) < 4; // Is this Opera exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]";