Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinzufügen von Drag & Drop für HTML5 zu SharePoint-Listen
Microsoft SharePoint ist eine Unternehmensplattform mit einer langen Geschichte und zahlreichen Features. Deshalb kann die Lösung nicht immer schnell genug auf neue Trends der Webtechnologie reagieren. Trotz einer umfangreichen Unternehmensanpassung von SharePoint und einer mit großem Aufwand durchgeführten Bereitstellung von vielen Features liegt SharePoint in puncto immersiver Benutzeroberflächen immer noch hinter modernen CMS-Produkten zurück, wie z. B. HTML5 und CSS3.
Meiner Ansicht nach ist HTML5 nicht nur eine großartige, neue Technologie, sondern bietet auch viele praktische Vorteile: Es ist einfach, bequem und umfassend – und wird von fast allen heute gängigen Browsern unterstützt (einschließlich Browsern auf mobilen Geräten). Außerdem werden HTML5 und JavaScript als Haupttechnologien bei der Desktop-Programmierung in Windows eingesetzt.
Deshalb hat sich HTML5 seinen Platz in SharePoint redlich verdient, damit die Portale benutzerfreundlicher werden. Zudem kann eine Verbesserung der SharePoint-Schnittstellen Geschäftsbenutzern helfen, da diese dann besser und schneller arbeiten können.
Leider verfügt SharePoint nicht über integrierte HTML5-Funktionen, bietet aber eine unglaubliche Flexibilität. In diesem Artikel zeige ich Ihnen, wie einfach es ist, die Drag & Drop-Unterstützung von HTML5 in SharePoint hinzuzufügen, und wie schön dadurch die Standardbenutzeroberfläche wird, sehen Sie in Abbildung 1.
Abbildung 1 Drag & Drop in SharePoint
Für diese Implementierung arbeite ich mit einem der grundlegenden SharePoint-Bausteine, der zugleich eines meiner bevorzugten SharePoint-Tools ist, nämlich XsltListViewWebPart und dessen XSL-Transformationen (Details dazu finden Sie auf der MSDN Library-Seite bit.ly/wZVSFx).
Warum kein benutzerdefiniertes Webpart?
Wie immer, wenn es um Implementierungen geht, bietet SharePoint ein großes Spektrum an Möglichkeiten. Es ist ausgesprochen wichtig, diejenige herauszupicken, die für Ihre Zwecke am besten geeignet ist.
Da Drag & Drop in der Regel zur Datenverwaltung verwendet wird, hätten es wohl viele SharePoint-Entwickler bei der Problemstellung von Drag & Drop mit HTML5 vorgezogen, ein benutzerdefiniertes Webpart zu erstellen, das in diesem Fall wie ein gewöhnliches ASP.NET-Steuerelement agiert hätte: Die Daten werden in einer standardmäßigen SharePoint-Liste gespeichert, die über das Objektmodell oder das SPDataSource-Steuerelement abgerufen wird, und mithilfe von ASCX-Markup und ASP.NET-Steuerelementen gerendert.
Einfach, klar, deutlich ... aber die beste Wahl?
Vor zwei Jahren hätte ich das noch bejaht. Heute ziehe ich es vor, XsltListViewWebPart mithilfe von dessen eigenen XSL-Transformationen anzupassen. Warum habe ich meine Meinung geändert?
Beginnend mit SharePoint 2010 werden fast alle Listenansichten (die einzige Ausnahme bieten Kalender) durch dieses Webpart angezeigt. Stellen Sie sich das vor: All diese Datentypen, all die verschiedenen Ansichten, Formate und Listentypen, die gesamte Datenvielfalt wird mithilfe von XsltListViewWebPart und dessen XSL-Transformationen gerendert. Das ist ein flexibles und leistungsstarkes Tool.
Wenn Sie sich dazu entschließen, ein eigenes benutzerdefiniertes Webpart zu entwickeln, um HTML5-Markup für die Anzeige von Listendaten zu rendern, sind sämtliche integrierten Features nicht mehr verfügbar. Nach meiner Erfahrung ist das ein großer Verlust. Im Übrigen wurde bei allen Webparts, die ich bisher gesehen habe, letztlich doch mindestens die Hälfte der einsatzbereiten Features von XsltListViewWebPart implementiert.
Mein Plan besteht also darin, vorhandene Funktionalität wiederzuverwenden, anstatt ein neues benutzerdefiniertes Webpart zu erstellen, das wahrscheinlich viel weniger flexibel und leistungsstark wäre.
Außerdem sind in XsltListViewWebPart viele nützliche Features enthalten. Es ist in SharePoint Designer integriert, unterstützt alle möglichen Webpartverbindungen und zeigt sämtliche SharePoint-Datentypen korrekt an. Zudem werden Gruppierung, Zwischensummen, Paging, Kontextmenüs für Elemente, Inlinebearbeitung, Elementauswahl, Anwesenheitsindikatoren usw. unterstützt. Es weist ein kontextbezogenes Menüband auf, bietet eine Benutzeroberfläche zum Sortieren und Filtern, dazu einige grundlegende Ansichtsformatvorlagen und vieles mehr. Zusammengenommen hat XsltListViewWebPart zahlreiche gute Features, deren Nachbildung im Rahmen eines benutzerdefinierten Webparts sehr kompliziert wäre.
XsltListViewWebPart
XsltListViewWebPart liefert zahlreiche Integrationspunkte für Entwickler: eine befehlsorientierte Benutzerschnittstelle, eine CAML-Schnittstelle und natürlich XSL-Transformationen in Verbindung mit Parameterbindungen. Und nicht zu vergessen, dass all diese Objekte und Eigenschaften ihre Entsprechungen im Clientobjektmodell besitzen, Sie können also auch über JavaScript oder Silverlight auf XsltListViewWebPart zugreifen.
XsltListViewWebPart ist ein wirklich leistungsstarkes Tool. Zugegeben, auf den ersten Blick sehen die SharePoint-spezifischen XML-Abschnitte (oder XSLT-Abschnitte) ein wenig beunruhigend aus, aber ich zeige Ihnen einige Tricks, mit denen Sie alles austüfteln können.
Das Szenario
Bevor ich mich den Details der Implementierung zuwende, möchte ich das Gesamtszenario beschreiben.
Ich möchte das Drag & Drop-Feature von HTML5 in SharePoint-Listenansichten einfügen, damit Benutzer Zellen per Drag & Drop von einer Liste in eine andere verschieben können. In meinem Beispiel wird eine Tasks-Liste (Aufgaben) und eine Executors-Liste (Bearbeiter) verwendet, sodass der Projektmanager problemlos Aufgaben zuweisen und neu zuteilen kann, indem er die Bearbeiter in den entsprechenden Tasks-Listenzellen zieht.
Wie Sie sicher wissen, werden mit HTML5 einige neue Attribute für Drag & Drop eingeführt. Das wichtigste hierbei ist das draggable-Attribut (ziehbar). Zudem gibt es mehrere Ereignisse für die verschiedenen Phasen des Drag & Drop-Prozesses. Handlerfunktionen für diese Ereignisse können mithilfe der geeigneten Attribute angefügt werden, wie z. B. ondragstart und ondragend. (Details dazu finden Sie im HTML5-Spezifikationsentwurf des World Wide Web Consortium [W3C] in Kapitel 7.6 unter bit.ly/lNL0FO.)
In meinem Beispiel heißt das, ich muss nur mithilfe von XSLT-Code einige Basisattribute für bestimmte Zellen der Listenansicht hinzufügen, außerdem möglicherweise noch einige benutzerdefinierte Attribute zum Anfügen der Datenwerte (die durch Ziehen übertragen werden). Abschließend stelle ich dann den entsprechenden JavaScript-Code für die Handlerfunktionen bereit.
Erste Schritte
Ich benötige zwei Listen. Ich kann eine Tasks-Liste anhand der Standardvorlage für Tasks erstellen, oder ich erzeuge eine benutzerdefinierte Liste, der ich einige Spalten hinzufüge, darunter eine obligatorische Websitespalte Assigned To (Zugewiesen an). Dann erstelle ich die zweite Liste, die Executors-Liste, als benutzerdefinierte Liste. Ich füge Executor als Spalte des Typs Person or group (Person oder Gruppe) hinzu und lege sie als erforderlich, indiziert und eindeutig fest.
In der Executors-Liste sollten nur Benutzernamen angezeigt werden, hierfür ist die Standardspalte Title nicht erforderlich. Um die Spalte auszublenden, rufe ich die Listeneinstellungen auf, aktiviere die Verwaltung von Inhaltstypen und rufe den Inhaltstyp Item (Element) auf. Dann klicke ich auf die Spalte Title und blende sie wie in Abbildung 2 gezeigt aus.
Abbildung 2 Ausblenden der Title-Spalte in den SharePoint-Listeneinstellungen
Ich habe diese Listen mit Beispieldaten gefüllt und dann eine Webpartseite für mein Dashboard angelegt, wo ich diese Listen nebeneinander (Tasks auf der linken, Executors auf der rechten Seite) wie in Abbildung 3 dargestellt eingefügt habe.
Abbildung 3 Hinzufügen der Listen zum SharePoint-Dashboard
Ich habe nun die Listen und die Daten. Jetzt wird es Zeit für die tatsächliche Implementierung der Drag & Drop-Funktionalität.
SharePoint Designer
Microsoft SharePoint Designer ist ein gänzlich kostenfreies Tool für die schnelle Entwicklung von SharePoint-Anwendungen. Im Vergleich mit SharePoint 2007 wurden an SharePoint 2010 erhebliche Verbesserungen vorgenommen, sodass es außerordentlich nützlich ist, sogar für Entwickler. Das Konzept ist, dass mit der Benutzeroberfläche von SharePoint Designer ein wirklich komplexer XSLT-Code erzeugt und dann durch Kopieren und Einfügen in Ihr Visual Studio-Projekt integriert werden kann, anstelle den für Tippfehler anfälligen und nicht immer gut dokumentierten XML-/XSLT-Code selbst zu schreiben. Diesen Trick setze ich häufig in praktischen Projekten ein, und ich kann Ihnen versprechen, das spart viel Zeit.
Ich öffne SharePoint Designer und navigiere zur zuvor von mir erstellten Dashboard-Seite. Dann wähle ich in der Spalte Assigned To eine Zelle aus (mit der rechten Maustaste klicken und Select | Cell (Auswählen/Zelle) auswählen. Nun folgt der Zauber: In der Statusleiste sehe ich den Pfad zur XSL-Vorlage (und zum entsprechenden HTML-Tag in dieser Vorlage), die für die Anzeige dieser bestimmten Zelle zuständig ist (siehe Abbildung 4).
Abbildung 4 Der Pfad zur aktuellen XSL-Vorlage in SharePoint Designer
Diese Informationen können bei der Bestimmung, welche XSL-Vorlage zum Ändern des Zellen-Markups überschrieben werden muss, sehr hilfreich sein. Den ursprünglichen Code für die Vorlagen finden Sie im Ordner 14/TEMPLATE/LAYOUTS/XSL, Sie können ihn in Ihren eigenen XSLT-Dateien oder im <Xsl>-Tag von XsltListViewWebPart verwenden.
Um mein Ziel zu erreichen, benötige ich diese großen und komplizierten XSLT-Dateien gar nicht. Ich kann stattdessen das Feature der bedingten Formatierung von SharePoint Designer nutzen. Mit ihr werden bestimmte Zeilen oder Zellen unter festgelegten Bedingungen mit einer besonderen Formatierung hervorgehoben. Dazu sind keine besonderen Kenntnisse nötig, mit der Benutzeroberfläche ist das Feature leicht zu nutzen. Aber hinter den Kulissen wird alles mit XSLT-Code implementiert. Folglich enthält SharePoint Designer eine Art einsatzbereiten grafischen XSLT-Generator, den ich nun für meine eigenen Zwecke einsetze.
Ich wähle eine Zelle aus, klicke im Menüband auf die Schaltfläche Conditional Formatting (Bedingte Formatierung) und wähle dann Format Column (Spalte formatieren) (siehe Abbildung 5).
Abbildung 5 Festlegen der bedingten Formatierung in SharePoint Designer
Als Nächstes lege ich eine unwahrscheinliche Bedingung an, ID gleich null, wie in Abbildung 6 dargestellt.
Abbildung 6 Das Dialogfeld für bedingte Formatierung in SharePoint Designer
Nachfolgend klicke ich auf die Schaltfläche Set Style (Formatvorlage festlegen) und wähle ein beliebiges Format aus (wie z. B. Textverzierung: Unterstrichen). Dann klicke ich auf OK und wechsle zur Registerkarte Codeansicht. Hier suche ich nach dem erzeugten Code, der sich natürlich im <Xsl>-Tag des XsltListViewWebPart-Steuerelements befindet.
XSL-Transformationen
Nun kann ich das Markup der Assigned To-Zellen bearbeiten. Die Assigned To-Spalte ist der „Datenakzeptor“, in den ich Executors verschieben will. Also muss ich die Attribute ondragover, ondragenter, ondragleave und ondrop bereitstellen, die auf die entsprechenden JavaScript-Ereignishandlerfunktionen zeigen.
Der von SharePoint Designer im vorigen Absatz erzeugte Code enthält die XSL-Vorlage mit folgender Signatur:
<xsl:template name="FieldRef_printTableCell_EcbAllowed.AssignedTo"
match="FieldRef[@Name='AssignedTo']" mode="printTableCellEcbAllowed"
ddwrt:dvt_mode="body" ddwrt:ghost="" xmlns:ddwrt2="urn:frontpage:internal">
Wie Sie vielleicht wissen, können sich XSL-Vorlagen gegenseitig aufrufen, entweder über den Namen oder über die Bedingung. Die erste Aufrufmöglichkeit erfolgt mithilfe des Elements xsl:call-template, sie entspricht einem Funktionsaufruf, wie er beispielsweise in C# genutzt wird.
Die zweite Option ist wesentlich flexibler und sollte bevorzugt werden: Durch die Verwendung des Elements xsl:apply-templates können Sie den Modus und den Parameter (der über XPath ausgewählt wird und somit viele Elemente enthalten kann) angeben, ohne dass ein bestimmter Vorlagenname dazu erforderlich ist. Für jedes Parameterelement wird die zugehörige Vorlage mit dem match-Attribut abgeglichen. Sie können sich diese Methode ähnlich wie Overloads in C# vorstellen.
Wie Sie im voranstehenden Codebeispiel sehen, werden mit dieser Vorlage FieldRef-Elemente abgeglichen, bei denen das Name-Attribut dem Wert AssignedTo entspricht. Auch das mode-Attribut des entsprechenden Aufrufs von xsl:apply-template muss printTableCellEcbAllowed entsprechen. Diese Vorlage ist im Grunde genommen ein Overload für die Standardfunktion zur Anzeige von Feldwerten. Mit diesem Overload werden nur die Assigned To-Feldwerte abgeglichen.
Mit Abbildung 7 erhalten wir Einblick in die Vorlage (der Einfachheit halber wurde Code ausgelassen).
Abbildung 7 Einblick in die XSL-Vorlage
<xsl:template match="FieldRef[@Name='AssignedTo']" mode="printTableCellEcbAllowed" ...>
<xsl:param name="thisNode" select="."/>
<xsl:param name="class" />
<td>
<xsl:attribute name="style">
<!-- ... -->
</xsl:attribute>
<xsl:if test="@ClassInfo='Menu' or @ListItemMenu='TRUE'">
<xsl:attribute name="height">100%</xsl:attribute>
<xsl:attribute name="onmouseover">OnChildItem(this)</xsl:attribute>
</xsl:if>
<xsl:attribute name="class">
<!-- ... -->
</xsl:attribute>
<xsl:apply-templates select="." mode="PrintFieldWithECB">
<xsl:with-param name="thisNode" select="$thisNode"/>
</xsl:apply-templates>
</td>
</xsl:template>
Wie Sie sehen, sind in der Vorlage zwei xsl:param-Elemente, ein <td>-Element, mehrere xsl:attribute-Elemente sowie ein xsl:apply-templates-Element enthalten, mit dem mehrere untergeordnete Vorlagen angewendet werden.
Um mein Drag & Drop-Ziel zu erreichen, füge ich einfach die Attribute für Drag & Drop zum <td>-Element hinzu:
<td ondragover="return UserDragOver(event, this)" ondragenter=
"return UserDragOver(event, this)" ondragleave=
"UserDragLeave(event, this)" ondrop="UserDrop(event, this)">
Einfach, nicht wahr?
Wenn Sie jQuery in Ihrer SharePoint-Umgebung bereitgestellt haben, können Sie als Alternative auch JavaScript-Ereignishandler mithilfe der jQuery.on-Methode anfügen.
Das Markup für die Assigned To-Spalte ist fertig (die Handler schreibe ich etwas später). Nun kann die Executors-Liste angepasst werden.
Ich wechsle zurück zur Registerkarte Designansicht, wähle eine Zelle in der Executors-Spalte aus und wiederhole den Trick mit der bedingten Formatierung zum Generieren des XSLT-Codes. Dann füge ich das onstartdrag-Attribut ein, damit das Drag & Drop-Feature ordnungsgemäß gestartet werden kann (hier brauche ich das draggable-Attribut nicht, da die Feldwerte für Person oder Gruppe als Links gerendert werden, und bei Links ist das draggable-Attribut gemäß Spezifikation standardmäßig auf True gesetzt).
<td ondragstart="UserDragStart(event, this)">
Cool. Aber wie kann ich die Daten verfolgen? Wie bestimme ich, welcher Executor per Drag & Drop bewegt wird? Ich benötige dafür wohl seinen Anmeldenamen oder, besser noch, seine ID. Meiner Ansicht nach ist das Parsing des TD-Elements unverhältnismäßig kompliziert.
Der Punkt ist, dass in XSLT für jedes Feld des Typs Person oder Gruppe die Benutzer-ID verfügbar ist und mit einer einfachen XPath-Abfrage abgerufen werden kann.
In dieser Abfrage muss ich auf die Werte des aktuellen Elements zeigen. Auf das aktuelle Element wird in allen standardmäßigen XsltListViewWebPart-Vorlagen über den $thisNode-Parameter verwiesen. Zum Abrufen der Benutzer-ID zeigen Sie auf das Attribut des $thisNode-Parameters, wobei der Name dem in der Spalte Person oder Gruppe mit der Erweiterung .id entsprechen muss.
Hier ist also meine Abfrage:
<td ondragstart="UserDragStart(event, {$thisNode/Executor.id}, this)">
Mit den geschweiften Klammern wird der XPath-Ausdruck direkt in den Attributwert eingeschlossen.
Das Markup ist fertig und kann sofort eingesetzt werden. Aber es wäre sicher eine gute Idee, noch weiter am Code zu arbeiten, damit dieser besser erneut verwendet werden.
Erstellen von erneut verwendbaren Vorlagen
Wie Sie bemerkt haben, sind die Vorlagen eng an bestimmte Spaltennamen gebunden und sind nur für spezielle Listen gedacht. Aber es ist ganz einfach, diese Vorlagen so zu verändern, dass Sie diese erneut für andere Listen mit anderen Spaltennamen verwenden können.
Schauen Sie sich zunächst die vorhin von mir vorgestellte Vorlagensignatur an. Sie weist das folgende Attribut auf:
match="FieldRef[@Name='AssignedTo']"
Damit wird offenbar die Vorlage an die Assigned To-Spalte gebunden. Damit die Vorlage etwas weniger eng gefasst ist, ersetzen Sie die Namensbindung durch eine Typbindung, damit jede Spalte des Typs Person oder Gruppe passt. So soll es sein! Hier ist der Code:
match="FieldRef[@Type='User']"
Dieselbe Änderung sollte an der zweiten Vorlage vorgenommen werden, bei der das FieldRef-Element mit dem internen Namen des Executor-Felds abgeglichen wird.
Da ich jede Spalte des Typs Person oder Gruppe sowie jede Liste nutzen kann, muss ich weitere Informationen an meine JavaScript-Handler übergeben. Beim Ausführen von Drag & Drop muss der Wert der Assigned To-Spalte in der Tasks-Liste aktualisiert werden. Dafür benötige ich den Namen der Spalte und die GUID der Liste.
Wie bereits gesagt sind im SharePoint-XSLT einige global verfügbare Standardparameter enthalten. Einer dieser Parameter ist $List, mit dem die GUID der aktuellen Liste gespeichert wird. Und der interne Name des Felds kann problemlos über das passende FieldRef-Element abgerufen werden.
Ich übergebe nun wie folgt die GUID der Liste und den internen Namen der Spalte an den UserDrop-Handler (aus Gründen der Übersichtlichkeit werden die Attribute ondragenter, ondragover und ondragleave ausgelassen):
<td ... ondrop="UserDrop(event, this, '{$List}', '{./@Name}'">
Der Punkt (.) zeigt auf das aktuelle FieldRef-Element (das zuvor von der Vorlage abgeglichen wurde).
Als Nächstes entferne ich mit folgendem Code die Zeichenfolge Executor aus dem id-Parameter im XSLT-Code der Executors-Liste:
<td ondragstart="UserDragStart(event, {$thisNode/@*[name()=
concat(current()/@Name, '.id')]}, this)">
Die Vorlagen sind nun einsatzbereit und wiederverwendbar. Ich schreibe nun den zugehörigen JavaScript-Code zum Implementieren der Handler.
Schreiben von JavaScript-Handlern
Obwohl vier verschiedene Handler zu schreiben sind, handelt es sich meist um sehr einfache und offensichtliche Handler.
Normalerweise empfehle ich, diesen Code in einer separaten JavaScript-Datei zu platzieren. Und in der Regel ist es eine gute Idee, die Handler mit Visual Studio zu erstellen, da Sie IntelliSense nutzen können. In manchen Situationen jedoch ist es sinnvoll, diesen Code im XSLT-Code zu platzieren, für diesen Zweck muss die Stammvorlage (match=“/”) überschrieben werden. Damit können Sie einige XSLT-Variablen und -Parameter in Ihrem JavaScript-Code verwenden, außerdem brauchen Sie sich keine Gedanken mehr über die Bereitstellung von JavaScript-Dateien zu machen.
Schauen wir uns den Code für die Handler DragStart, DragEnter, DragOver, DragLeave und Dropan.
Im UserDragStart-Handler wird die Datenübertragung initialisiert. Das heißt, die per Drag-Vorgang bewegten Daten müssen in einem besonderen HTML5-Datenübertragungsobjekt gespeichert werden, wie nachfolgend dargestellt:
function UserDragStart(e, id, element) {
e.dataTransfer.effectAllowed = 'copy';
e.dataTransfer.setData('Text', id + '|' + element.innerHTML);
}
Beachten Sie, dass die ID des Benutzers nicht der einzig übertragene Datenbestandteil ist. Ich habe auch den innerHTML-Code des <td>-Elements beigefügt, damit die Seite nach dem Drop-Vorgang nicht aktualisiert werden muss (Details dazu finden Sie im Code für den UserDrop-Handler in Abbildung 8).
Abbildung 8 Der Drop-Ereignishandler
function UserDrop(e, toElement, listGuid, columnName) {
// Terminate the event processing
if (e.stopPropagation)
e.stopPropagation();
// Prevent default browser action
if (e.preventDefault)
e.preventDefault();
// Remove styles from the placeholder
toElement.style.backgroundColor = '';
//toElement.className = '';
// iid attribute is attached to tr element by SharePoint
// and contains ID of the current element
var elementId = toElement.parentNode.getAttribute('iid').split(',')[1];
// Transferred data
var data = e.dataTransfer.getData('Text');
var userId = data.split('|')[0];
var userLinkHtml = data.split('|')[1];
// Setting value of the field using SharePoint
// EcmaScript Client Object Model
var ctx = new SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getById(listGuid);
var item = list.getItemById(elementId);
item.set_item(columnName, userId);
item.update();
// Asynchronous call
ctx.executeQueryAsync(
function () { toElement.innerHTML = userLinkHtml; },
function (sender, args) { alert('Drag-and-drop failed.
Message: ' + args.get_message()) }
);
return false;
}
In diesem Fall sind die Handler für das DragEnter- und das DragOver-Ereignis identisch, sodass ich eine einzige Funktion für beide nutzen kann. Sie sollten bei diesen Ereignissen angeben, dass die Benutzer hier die Daten ablegen (Drop-Vorgang) können. Gemäß den Spezifikationen sollte für diesen Zweck die event.preventDefault-Methode aufgerufen werden (sofern vorhanden), die dann den Wert False zurückgibt.
Der DragEnter-/DragOver-Handler ist der perfekte Ort, um benutzerdefinierte Formatvorlagen in den Drag & Drop-Platzhalter einzubinden, um den Benutzer zu informieren, dass er die gezogenen Daten aus dem Drag-Vorgang hier per Drop-Vorgang ablegen kann. Zur Vereinfachung des Beispiels verwende ich CSS-Inlineformatvorlagen, aber für ein praktisches Projekt würde ich die Nutzung von CSS-Klassen empfehlen (siehe die kommentierten Zeilen in Abbildung 9).
Abbildung 9 Die DragOver- und DragLeave-Ereignishandler
function UserDragOver(e, toElement) {
// Highlight the placeholder
toElement.style.backgroundColor = '#efe';
// toElement.className = 'userDragOver';
// Denote the ability to drop
if (e.preventDefault)
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
return false;
}
function UserDragLeave(e, toElement) {
// Remove styles
toElement.style.backgroundColor = '';
// toElement.className = '';
Bei DragLeave muss ich natürlich die zuvor angewendeten Formatvorlagen entfernen, wie in Abbildung 9 gezeigt.
Während des Drop-Ereignisses in Abbildung 8 sind zwei wichtige Schritte auszuführen:
- Änderungen übernehmen. Verwenden Sie das EcmaScript-Clientobjektmodell von SharePoint, und legen Sie den Feldwert auf die übertragene Benutzer-ID fest.
- Ersetzen Sie den innerHTML-Code in der aktuellen Zelle (TD) durch Code aus der übertragenen, damit die Änderungen auch ohne eine Seitenaktualisierung angezeigt werden.
Nun sind alle Handler implementiert, und Sie können JavaScript bereitstellen. Dazu stehen Ihnen mehrere Möglichkeiten zur Verfügung: Sie können die Masterseite anpassen, mit einem Stellvertretungs-Steuerelement arbeiten, eine benutzerdefinierte Aktion erstellen, bei der Location auf ScriptLink gesetzt ist oder, wie bereits gesagt, JavaScript direkt in XSLT einbinden.
Am einfachsten ist es, die Masterseitendatei mit SharePoint Designer anzupassen, weil dafür keine speziellen Kenntnisse erforderlich sind. Aber da Sie ja Entwickler sind, stehen die Chancen gut, dass Sie lieber die JavaScript- und XSLT-Anpassungen zusammenfassen und daraus eine bereitstellbare Lösung entwickeln. Also gut, dann los.
Entwickeln einer bereitstellbaren Lösung
Um eine einsatzbereite Lösung zu erstellen, die Sie an Ihre Kunden weitergeben können, sind ein paar einfache Schritte nötig:
- Öffnen Sie Visual Studio, und legen Sie ein leeres SharePoint-Projekt an. Wählen Sie dann im Dialogfeld Projekteinstellungen die Option Als Farmlösung bereitstellen aus.
- Fügen Sie dem Projekt einen zugeordneten SharePoint-Ordner Layouts mit den folgenden drei Dateien hinzu: UserDragHandlers.js, UserDragProvider.xsl und UserDragConsumer.xsl.
- Dann fügen Sie den zuvor erstellen JavaScript-Code und den XSLT-Code (generiert in SharePoint Designer) in die entsprechenden Dateien ein.
- Ergänzen Sie ein Projektelement Leeres Element, öffnen Sie Elements.xml und fügen nachfolgenden Code ein:
<CustomAction ScriptSrc="/_layouts/SPDragAndDrop/UserDragHandlers.js" Location="ScriptLink" Sequence="10" />
Damit wird der Link zur JavaScript-Datei auf allen Site-Seiten bereitgestellt. - Abschließend fügen Sie für Feature1 (wurde automatisch beim Hinzufügen des Projektelements Leeres Element erstellt) einen Ereignisempfänger hinzu, auskommentieren die FeatureActivated-Methode und kopieren folgenden Code hinein:
var web = properties.Feature.Parent as SPWeb;
SPList list;
SPView view;
list = web.Lists["Tasks"];
view = list.DefaultView;
view.XslLink = "../SPDragAndDrop/UserDragConsumer.xsl";
view.Update();
list = web.Lists["Executors"];
view = list.DefaultView;
view.XslLink = "../SPDragAndDrop/UserDragProvider.xsl";
view.Update();
Und das war's, Sie sind fertig! Einfach, nicht wahr? Wenn Sie nun die Lösung mit der zuvor erstellten Tasks- und Executors-Liste entwickeln und bereitstellen, und zudem ein Dashboard mit einzelnen Standardansichten dafür anlegen, erhalten Sie ein Dashboard mit einem praktischen Drag & Drop-Feature.
Browserunterstützung
Zum aktuellen Zeitpunkt akzeptieren alle gängigen Browser (bis auf Opera) das Drag & Drop-Feature von HTML5. Ich habe Internet Explorer 9.0.8112.16421, Chrome 16.0.912.75 und Firefox 3.6.12 getestet, alle sind vollständig kompatibel mit der beschriebenen Lösung. Ich hatte erwartet, dass es auch mit älteren Versionen der Browser funktioniert. Eigentlich sollte auch der Safari-Browser kompatibel sein, aber zurzeit liegen einige seltsame Bugs in seiner Implementierung des Drag & Drop-Features für HTML5 vor. Deswegen funktioniert die Lösung nicht wie erwartet.
Ausblick
In meiner Lösung enthalten weder die XSLT-Vorlagen noch JavaScript listenspezifischen Code, es gibt keine hartcodierten GUIDs, Namen, Titel usw. Diese Transformationen können also potenziell auf alle Listen oder Dokumentbibliotheken angewendet werden, und Sie können die Drag & Drop-Unterstützung für jede Spalte des Typs Person oder Gruppe hinzufügen. Ist das nicht prima?
Auch andere Spaltentypen lassen sich auf dieselbe Weise per Drag & Drop verschiebbar machen. Sie könnten also eine Lösung erstellen, in der sich alle Zellen in allen SharePoint-Listen per Drag & Drop bewegen lassen. Auf Dashboard-Seiten wären die Benutzer dann in der Lage, Zellen per Drag & Drop zwischen den Listen zu verschieben, was auch sehr praktisch sein kann.
Eine interessante Herausforderung könnte womöglich im Drag & Drop nach Zeilen bestehen. Die Idee ist grundlegend dieselbe, aber zum Erstellen einer geeigneten Vorlage müsste die bedingte Formatierung auf die Zeile angewendet werden. Dadurch könnten beispielsweise Listenelemente verknüpft oder deren Reihenfolge geändert werden. Oder Sie könnten über das Schnellstartmenü einen Papierkorb-Link erstellen, der als Drag & Drop-Akzeptor fungiert, und mit diesem auf coole Art und Weise Elemente aus den Listen löschen.
So vieles ist möglich. Überlegen Sie sich etwas, und probieren Sie es aus. Ihr SharePoint-Portal wird es Ihnen danken.
Andrey Markeev ist MVP für SharePoint Server und als SharePoint-Entwickler bei der Softline-Gruppe in Russland tätig. Markeev zählt zu den 10 größten Experten im Bereich SharePoint StackExchange (bit.ly/w9e4NP), hat zahlreiche Open-Source-Projekte für CodePlex entwickelt und ist als Blogger und Referent aktiv. Sie können ihn auf Twitter unter twitter.com/amarkeev erreichen.
Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Michael Nemtsev und Brandon Satrom