window.clipboardData löst ‘OpenClipboard failed’ aus

9. September 2013


Weil ich im Internet keine wirklich sofort schlüssige Erklärung gefunden habe, hier kurz ein Hinweis zu einem selten auftretenden Problem.

Im Internet Explorer gibt es die Möglichkeit, mittels des ‚clipboardData‘ objektes lesend und schreibend auf die Zwischenablage zuzugreifen. Andere Browser lassen dies in der Regel aus Sicherheitsgründen nicht zu (schließlich kann eine Webseite damit den Inhalt des Zwischenablage ohne Kenntnis oder Zustimmung des Nutzers im Internet verteilen).

Soll daher im IE diese Funktionalität verwendet werden, zum Beispiel um durch Drücken eines Knopfes mit der id='saveStuffToClipboard' den Textinhalt eines Elements mit der id='copyThisStuff' in die Zwischenablage zu kopieren, bietet sich eine „Feature-weiche“ an, z.B. wenn jQuery verwendet wird:


  if (window.clipboardData) {
    $("#saveStuffToClipboard").click( function() {
       window.clipboardData.setData( $("#copyThisStuff").text() );
    }).show();
  }

(Der Knopf ‚saveStuffToClipboard‘ ist dabei standardmässig ausgeblendet.)

Das ganze findet zweckmäßiger Weise im „onload“-handler der Seite statt.

Nun verbietet Microsoft, dass zwei Programme gleichzeitig die Zwischenablage „offen haben“ (siehe http://msdn.microsoft.com/en-us/library/windows/desktop/ms649048%28v=vs.85%29.aspx, unter „Remarks“)

Der interessante Aspekt dabei ist, dass schon der Zugriff auf das JavaScript-objekt window.clipboardData die Zwischenablage „öffnet“ (zumindest kurzzeitig), und daher potentiell den Fehler auslöst. D.h. nicht der Zugriff mittels setData, sonder schon das „Feature-detect“ if (window.clipboardData) kann den Fehler erzeugen.
Auf JavaScript-Ebene bewirkt dieser Fehler eine Exception, welche unbehandelt die aktuelle Ausführung vorzeitig beendet. Wenn die Exception im onload-handler auftritt, ist dann nicht nur der Knopf ohne Funktion (was egal ist, da er auch nicht sichtbar ist), sondern alle folgenden Initialisierungen werden nicht ausgeführt. Das Ergebnis ist also eine Seite mit mehr oder weniger nicht-funktionalem JavaScript.

In einer idealen Welt treten dann die noscript-fallbacks in Kraft, aber wer kann es heutzutage noch vertreten, eine Funktionalität, die schick mit JavaScript umgesetzt ist, nochmal nur mit HTML und serverseitigem Code umzusetzen? Selbst wenn die Grundfunktionalität noch da ist, ein Wegbrechen der vielen Gadgets, die nur mit Skriptunterstützung funktionieren, lässt den meisten Nutzern die Seite trotzdem als „kaputt“ erscheinen.

Ok, nach den Script/noscript Rant jetzt zurück zu dem eigentlichen Problem: Der Code oben ist also fehlerhaft, wenn auch in kaum reproduzierbarer Weise; richtig ist es, jeden Zugriff auf die Zwischenablage in einen try .. catch block zu setzen, z.B.


  try {
    if (window.clipboardData) {
      $("#saveStuffToClipboard").click( function() {
        window.clipboardData.setData( $("#copyThisStuff").text() );
      }).show();
    }
  } catch (e) {
    // display error mesage here if you care
  }

Zugegebenermaßen hat der eigentliche Zugriff innerhalb des Click-handlers keine Ausnahmebehandlung, aber die Ausführung ist hier nach den Zugriff auf die Zwischenablage sowieso zu Ende, da kann die Exception ruhig fliegen. Bei komplexerem Code, z.b. bei zusätzlichen globalen Klick-handlern würde ein extra Check sicher nicht schaden, aber dann würde der eh schon unschöne Code zu hässlich, als das ich den hier posten wollte.