diff --git a/src/editor/js/components/editor.css b/src/editor/js/components/editor.css
index 5869026241c543539cd18b22d38715e7e94726a4..772dd998fe87628a55b0b521aab65e84604da919 100644
--- a/src/editor/js/components/editor.css
+++ b/src/editor/js/components/editor.css
@@ -8,7 +8,7 @@ div#ks-editor #sidepanel {
     /* resize: horizontal; */
     overflow: auto;
     min-width: 300px;
-    max-width: 40%;
+    max-width: 20%;
     height: inherit;
     margin: 0.3rem;
     margin-right: 0.3rem;
diff --git a/src/editor/js/components/editor.tsx b/src/editor/js/components/editor.tsx
index cbabc024e9a72807ef78949492e7ae23df4afe9f..ba47e2e180fbe38ac15953294f13c36d06bce83e 100644
--- a/src/editor/js/components/editor.tsx
+++ b/src/editor/js/components/editor.tsx
@@ -11,38 +11,78 @@ import { GraphElement } from "../structures/graph/graphelement";
 import { Link } from "../structures/graph/link";
 import { NodeTypesEditor } from "./nodetypeseditor";
 import { SpaceManager } from "./spacemanager";
+import { SelectLayer } from "./selectlayer";
+import { NodeType } from "../structures/graph/nodetype";
 
 type propTypes = {
     spaceId: string;
 };
 type stateTypes = {
+    /**
+     * Graph structure holding the basic information.
+     */
     graph: Graph;
+
+    /**
+     * Should labels on nodes be rendered, or none at all.
+     */
     visibleLabels: boolean;
+
+    /**
+     * Should feature be enabled, that nodes get connected with a link of dragged close enough to each other?
+     */
     connectOnDrag: boolean;
-    selectedNode: Node;
+
+    /**
+     * Collection of all currently selected nodes. Can also be undefined or empty.
+     */
+    selectedNodes: Node[];
+
+    /**
+     * True for each key, that is currently considered pressed. If key has not been pressed yet, it will not exist as dict-key.
+     */
     keys: { [name: string]: boolean };
+
+    /**
+     * Current width of graph object. Used to specifically adjust and correct the graph size.
+     */
     graphWidth: number;
 };
-type clickPosition = {
-    graph: { x: number; y: number };
-    window: { x: number; y: number };
-};
-type positionTranslate = {
+
+/**
+ * Coordinate structure used for the force-graph.
+ */
+type graphCoordinates = {
     x: number;
     y: number;
-    z: number;
+};
+/**
+ * Easy to access format for translated positions of a click event.
+ */
+type clickPosition = {
+    graph: graphCoordinates;
+    window: graphCoordinates;
 };
 
+/**
+ * Knowledge space graph editor. Allows easy editing of the graph structure.
+ */
 export class Editor extends React.PureComponent<propTypes, stateTypes> {
     private maxDistanceToConnect = 15;
     private defaultWarmupTicks = 100;
     private warmupTicks = 100;
     private renderer: any;
     private graphContainer: any;
+
+    /**
+     * True, if the graph was the target of the most recent click event.
+     */
     private graphInFocus = false;
 
     constructor(props: propTypes) {
         super(props);
+
+        // Making sure, all functions retain the proper this-bind
         this.loadGraph = this.loadGraph.bind(this);
         this.loadSpace = this.loadSpace.bind(this);
         this.extractPositions = this.extractPositions.bind(this);
@@ -57,10 +97,11 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         this.handleLinkCanvasObject = this.handleLinkCanvasObject.bind(this);
         this.handleBackgroundClick = this.handleBackgroundClick.bind(this);
         this.handleNodeDrag = this.handleNodeDrag.bind(this);
-        this.handleNodeDragEnd = this.handleNodeDragEnd.bind(this);
-        this.handleLinkClick = this.handleLinkClick.bind(this);
+        this.handleElementRightClick = this.handleElementRightClick.bind(this);
         this.selectNode = this.selectNode.bind(this);
         this.handleResize = this.handleResize.bind(this);
+        this.handleBoxSelect = this.handleBoxSelect.bind(this);
+        this.handleNodeTypeSelect = this.handleNodeTypeSelect.bind(this);
 
         this.renderer = React.createRef();
         this.graphContainer = React.createRef();
@@ -70,12 +111,15 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
             graph: undefined,
             visibleLabels: true,
             connectOnDrag: false,
-            selectedNode: undefined,
+            selectedNodes: undefined,
             keys: {},
             graphWidth: 1000,
         };
     }
 
+    /**
+     * Tries to load initial graph after webpage finished loading.
+     */
     componentDidMount() {
         if (this.props.spaceId !== undefined) {
             // Load initial space
@@ -130,6 +174,11 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         return true;
     }
 
+    /**
+     * Processes page wide key down events. Stores corresponding key as pressed in state.
+     *
+     * Also triggers actions corresponding to shortcuts.
+     */
     private handleKeyDown(event: KeyboardEvent) {
         const key: string = event.key;
 
@@ -140,23 +189,62 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
             keys: keys,
         });
 
-        // Key events
+        this.handleShortcutEvents(key);
+    }
+
+    /**
+     * Triggers actions that correspond with certain shortcuts.
+     *
+     * @param key Newly pressed key.
+     */
+    private handleShortcutEvents(key: string) {
         if (key === "Escape") {
-            // Only delete if 2d-graph is the focused element
             this.selectNode(undefined);
         } else if (
             key === "Delete" &&
-            this.state.selectedNode !== undefined &&
-            this.graphInFocus
+            this.graphInFocus // Only delete if 2d-graph is the focused element
         ) {
-            this.state.selectedNode.delete();
+            this.deleteSelectedNodes();
+        }
+    }
+
+    /**
+     * Deletes all nodes currently selected. Handles store points accordingly of the number of deleted nodes.
+     */
+    private deleteSelectedNodes() {
+        if (this.selectedNodes === undefined) {
+            return; // Nothing to delete
+        }
+
+        if (this.selectedNodes.length == 1) {
+            this.selectedNodes[0].delete();
+            return;
+        }
+
+        // Delete multiple connected nodes
+        const count: number = this.selectedNodes.length;
+        try {
+            // Disable storing temporarily to create just one big change.
+            this.state.graph.disableStoring();
+            this.selectedNodes.forEach((node: Node) => node.delete());
+        } finally {
+            this.state.graph.enableStoring();
+            this.state.graph.storeCurrentData(
+                "Deleted " + count + " nodes and all connected links"
+            );
         }
     }
 
-    private handleMouseDown(event: any) {
+    /**
+     * Processes page wide mouse down events.
+     */
+    private handleMouseDown() {
         this.graphInFocus = false;
     }
 
+    /**
+     * Processes page wide key up events. Stores corresponding key as not-pressed in state.
+     */
     private handleKeyUp(event: KeyboardEvent) {
         const key: string = event.key;
 
@@ -168,6 +256,9 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         });
     }
 
+    /**
+     * Processes resize window event. Focusses on resizing the graph accordingly.
+     */
     private handleResize() {
         const newGraphWidth = this.graphContainer.current.clientWidth;
         this.setState({
@@ -195,8 +286,8 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
             return;
         }
 
-        // Just deselect if shift key is pressed
-        if (this.state.keys["Shift"]) {
+        // Just deselect if control key is pressed
+        if (this.state.keys["Control"]) {
             this.selectNode(undefined);
             return;
         }
@@ -212,19 +303,30 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
 
         newNode.add(this.state.graph);
         this.forceUpdate();
+
+        // Select newly created node
+        if (this.state.keys["Shift"]) {
+            // Simply add to current selection of shift is pressed
+            this.toggleNodeSelection(newNode);
+        } else {
+            this.selectNode(newNode);
+        }
     }
 
     /**
      * Propagates the changed state of the graph.
      */
     private onHistoryChange() {
-        if (this.state.selectedNode === undefined) {
+        if (this.selectedNodes === undefined) {
             this.selectNode(undefined);
-        } else {
-            this.selectNode(
-                this.state.graph.getNode(this.state.selectedNode.id)
-            );
+            this.forceUpdate();
+            return;
         }
+
+        const nodes: Node[] = this.selectedNodes.map((node: Node) =>
+            this.state.graph.getNode(node.id)
+        );
+        this.selectNodes(nodes);
         this.forceUpdate();
     }
 
@@ -234,19 +336,20 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
      * @returns True, if element should be highlighted.
      */
     private isHighlighted(element: GraphElement): boolean {
-        if (this.state.selectedNode == undefined || element == undefined) {
+        if (this.selectedNodes == undefined || element == undefined) {
             // Default to false if nothing selected.
             return false;
         }
 
         if (element.node) {
-            // Is node
-            return element.equals(this.state.selectedNode);
+            // Is one of nodes
+            return this.selectedNodes.includes(element as Node);
         } else if (element.link) {
             // Is link
             // Is it one of the adjacent links?
-            const found = this.state.selectedNode.links.find(element.equals);
-            return found !== undefined;
+            return this.selectedNodes.some((node: Node) =>
+                node.links.find(element.equals)
+            );
         } else {
             return false;
         }
@@ -267,30 +370,61 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         };
     }
 
+    /**
+     * Selects a single node, or clears selection if given undefined.
+     * @param node Single node to select, or undefined.
+     */
     private selectNode(node: Node) {
+        this.selectNodes([node]);
+    }
+
+    /**
+     * Selects multiple nodes, or clears selection if given undefined or empty array.
+     * @param nodes Multiple nodes to mark as selected.
+     */
+    private selectNodes(nodes: Node[]) {
         this.setState({
-            selectedNode: node,
+            selectedNodes: nodes,
         });
     }
 
+    /**
+     * Makes sure to always offer a valid format of the selected nodes. Is either undefined or contains at least one valid node. An empty array is never returned.
+     */
+    private get selectedNodes(): Node[] {
+        if (this.state.selectedNodes === undefined) {
+            return undefined;
+        }
+
+        // Remove undefines
+        let selectedNodes = this.state.selectedNodes.filter(
+            (n: Node) => n !== undefined
+        );
+
+        // Remove duplicates
+        selectedNodes = [...new Set(selectedNodes)];
+
+        if (selectedNodes.length > 0) {
+            return selectedNodes;
+        }
+
+        return undefined;
+    }
+
     private handleNodeClick(node: Node) {
         this.graphInFocus = true;
 
-        if (this.state.keys["Shift"]) {
-            // Connect two nodes when second select while shift is pressed
-            if (this.state.selectedNode == undefined) {
+        if (this.state.keys["Control"]) {
+            // Connect to clicked node as parent while control is pressed
+            if (this.selectedNodes == undefined) {
                 // Have no node connected, so select
                 this.selectNode(node);
-            } else if (!this.state.selectedNode.equals(node)) {
-                const selected = this.state.selectedNode;
-                // Already have *other* node selected, so connect
-                this.state.selectedNode.connect(node);
-                // Re-select original node for easier workflow
-                this.selectNode(selected);
+            } else if (!this.selectedNodes.includes(node)) {
+                // Already have *other* node/s selected, so connect
+                this.connectSelectionToNode(node);
             }
-        } else if (this.state.keys["Control"]) {
-            // Delete node when control is pressed
-            node.delete();
+        } else if (this.state.keys["Shift"]) {
+            this.toggleNodeSelection(node);
         } else {
             // By default, simply select node
             this.selectNode(node);
@@ -298,6 +432,52 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         this.forceUpdate();
     }
 
+    private connectSelectionToNode(node: Node) {
+        if (this.selectedNodes === undefined) {
+            return;
+        }
+
+        if (this.selectedNodes.length == 1) {
+            node.connect(this.selectedNodes[0]);
+            return;
+        }
+
+        // More than one new link => custom save point handling
+        try {
+            this.state.graph.disableStoring();
+            this.selectedNodes.forEach((selectedNode: Node) =>
+                node.connect(selectedNode)
+            );
+        } finally {
+            this.state.graph.enableStoring();
+            this.state.graph.storeCurrentData(
+                "Added " +
+                    this.selectedNodes.length +
+                    " links on [" +
+                    node.toString() +
+                    "]"
+            );
+        }
+    }
+
+    private toggleNodeSelection(node: Node) {
+        // Convert selection to array as basis
+        let selection = this.selectedNodes;
+        if (selection === undefined) {
+            selection = [];
+        }
+
+        // Add/Remove node
+        if (selection.includes(node)) {
+            // Remove node from selection
+            selection = selection.filter((n: Node) => !n.equals(node));
+        } else {
+            // Add node to selection
+            selection.push(node);
+        }
+        this.selectNodes(selection);
+    }
+
     private handleNodeCanvasObject(node: Node, ctx: any, globalScale: any) {
         // add ring just for highlighted nodes
         if (this.isHighlighted(node)) {
@@ -344,10 +524,17 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         }
 
         // Draw label
+        /**
+         * Nothing selected? => Draw all labels
+         * If this nodes is considered highlighted => Draw label
+         * If this node is a neighbor of a selected node => Draw label
+         */
         const isNodeRelatedToSelection: boolean =
-            this.state.selectedNode === undefined ||
+            this.selectedNodes === undefined ||
             this.isHighlighted(node) ||
-            this.state.selectedNode.neighbors.includes(node);
+            this.selectedNodes.some((selectedNode: Node) =>
+                selectedNode.neighbors.includes(node)
+            );
 
         if (this.state.visibleLabels && isNodeRelatedToSelection) {
             const label = node.name;
@@ -413,9 +600,19 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         return undefined;
     }
 
-    private handleNodeDrag(node: Node, translate: positionTranslate) {
+    private handleNodeTypeSelect(type: NodeType) {
+        const nodesWithType = this.state.graph.nodes.filter((n: Node) =>
+            n.type.equals(type)
+        );
+        this.selectNodes(nodesWithType);
+    }
+
+    private handleNodeDrag(node: Node) {
         this.graphInFocus = true;
-        this.selectNode(node);
+
+        if (!this.selectedNodes || !this.selectedNodes.includes(node)) {
+            this.selectNode(node);
+        }
 
         // Should run connect logic?
         if (!this.state.connectOnDrag) {
@@ -439,18 +636,14 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         this.forceUpdate();
     }
 
-    private handleNodeDragEnd(node: Node, translate: positionTranslate) {
-        return;
-    }
-
-    private handleLinkClick(link: Link) {
+    /**
+     * Processes right-click event on graph elements by deleting them.
+     */
+    private handleElementRightClick(element: GraphElement) {
         this.graphInFocus = true;
 
-        if (this.state.keys["Control"]) {
-            // Delete link when control is pressed
-            link.delete();
-            this.forceUpdate();
-        }
+        element.delete();
+        this.forceUpdate();
     }
 
     private handleEngineStop() {
@@ -465,6 +658,14 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
         this.forceUpdate();
     }
 
+    private handleBoxSelect(selectedNodes: Node[]) {
+        if (selectedNodes !== undefined && selectedNodes.length <= 0) {
+            return;
+        }
+
+        this.selectNodes(selectedNodes.concat(this.selectedNodes));
+    }
+
     render(): React.ReactNode {
         return (
             <div id="ks-editor">
@@ -473,35 +674,56 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
                 <SpaceManager />
                 <div id="content">
                     <div id="force-graph-renderer" ref={this.graphContainer}>
-                        {this.state.graph ? (
-                            <ForceGraph2D
-                                ref={this.renderer}
-                                width={this.state.graphWidth}
-                                graphData={{
-                                    nodes: this.state.graph.data.nodes,
-                                    links: this.state.graph.links,
-                                }}
-                                onNodeClick={this.handleNodeClick}
-                                autoPauseRedraw={false}
-                                cooldownTicks={0}
-                                warmupTicks={this.warmupTicks}
-                                onEngineStop={this.handleEngineStop}
-                                nodeCanvasObject={this.handleNodeCanvasObject}
-                                nodeCanvasObjectMode={() => "after"}
-                                linkCanvasObject={this.handleLinkCanvasObject}
-                                linkCanvasObjectMode={() => "replace"}
-                                nodeColor={(node: Node) => node.type.color}
-                                onNodeDrag={this.handleNodeDrag}
-                                onNodeDragEnd={this.handleNodeDragEnd}
-                                onLinkClick={this.handleLinkClick}
-                                onBackgroundClick={(event: any) =>
-                                    this.handleBackgroundClick(
-                                        event,
-                                        this.extractPositions(event)
-                                    )
-                                }
-                            />
-                        ) : undefined}
+                        <SelectLayer
+                            allNodes={
+                                this.state.graph ? this.state.graph.nodes : []
+                            }
+                            screen2GraphCoords={
+                                this.renderer.current
+                                    ? this.renderer.current.screen2GraphCoords
+                                    : undefined
+                            }
+                            isEnable={() => this.state.keys["Shift"]}
+                            onBoxSelect={this.handleBoxSelect}
+                        >
+                            {this.state.graph ? (
+                                <ForceGraph2D
+                                    ref={this.renderer}
+                                    width={this.state.graphWidth}
+                                    graphData={{
+                                        nodes: this.state.graph.data.nodes,
+                                        links: this.state.graph.links,
+                                    }}
+                                    onNodeClick={this.handleNodeClick}
+                                    autoPauseRedraw={false}
+                                    cooldownTicks={0}
+                                    warmupTicks={this.warmupTicks}
+                                    onEngineStop={this.handleEngineStop}
+                                    nodeCanvasObject={
+                                        this.handleNodeCanvasObject
+                                    }
+                                    nodeCanvasObjectMode={() => "after"}
+                                    linkCanvasObject={
+                                        this.handleLinkCanvasObject
+                                    }
+                                    linkCanvasObjectMode={() => "replace"}
+                                    nodeColor={(node: Node) => node.type.color}
+                                    onNodeDrag={this.handleNodeDrag}
+                                    onLinkRightClick={
+                                        this.handleElementRightClick
+                                    }
+                                    onNodeRightClick={
+                                        this.handleElementRightClick
+                                    }
+                                    onBackgroundClick={(event: any) =>
+                                        this.handleBackgroundClick(
+                                            event,
+                                            this.extractPositions(event)
+                                        )
+                                    }
+                                />
+                            ) : undefined}
+                        </SelectLayer>
                     </div>
                     <div id="sidepanel">
                         <HistoryNavigator
@@ -511,7 +733,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
                         />
                         <hr />
                         <NodeDetails
-                            selectedNode={this.state.selectedNode}
+                            selectedNodes={this.selectedNodes}
                             allTypes={
                                 this.state.graph ? this.state.graph.types : []
                             }
@@ -522,6 +744,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
                         <NodeTypesEditor
                             onChange={this.forceUpdate}
                             graph={this.state.graph}
+                            onSelectAll={this.handleNodeTypeSelect}
                         />
                         <hr />
                         <h3>Settings</h3>
@@ -565,11 +788,18 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
                         <hr />
                         <ul className="instructions">
                             <li>Click background to create node</li>
-                            <li>SHIFT+Click background to clear selection</li>
+                            <li>
+                                SHIFT+Click and drag on background to add nodes
+                                to selection
+                            </li>
+                            <li>CTRL+Click background to clear selection</li>
                             <li>Click node to select and edit</li>
-                            <li>CTRL+Click node to delete</li>
-                            <li>CTRL+Click link to delete</li>
-                            <li>SHIFT+Click a second node to connect</li>
+                            <li>
+                                SHIFT+Click node to add or remove from selection
+                            </li>
+                            <li>CTRL+Click another node to connect</li>
+                            <li>Right-Click node to delete</li>
+                            <li>Right-Click link to delete</li>
                             {this.state.connectOnDrag ? (
                                 <li>
                                     Drag node close to other node to connect
@@ -577,7 +807,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
                             ) : (
                                 ""
                             )}
-                            <li>DELETE to delete selected node</li>
+                            <li>DELETE to delete selected nodes</li>
                             <li>ESCAPE to clear selection</li>
                         </ul>
                     </div>
diff --git a/src/editor/js/components/nodedetails.css b/src/editor/js/components/nodedetails.css
index 20bade5dd9f2508a1e1a968c385971037ee3a7b3..4211813387c9ff1e02816867fe515f50703366bf 100644
--- a/src/editor/js/components/nodedetails.css
+++ b/src/editor/js/components/nodedetails.css
@@ -12,3 +12,7 @@ div#ks-editor #nodedetails #node-name {
     font-weight: bold;
     font-size: large;
 }
+
+div#ks-editor #nodedetails .empty-select-option {
+    display: none;
+}
diff --git a/src/editor/js/components/nodedetails.tsx b/src/editor/js/components/nodedetails.tsx
index 2a619ab3e0a9aede84a9545d178178463787a6df..f6a6ba2270eca997d27a59e53830e930e9a47a19 100644
--- a/src/editor/js/components/nodedetails.tsx
+++ b/src/editor/js/components/nodedetails.tsx
@@ -5,7 +5,7 @@ import { NodeType } from "../structures/graph/nodetype";
 import "./nodedetails.css";
 
 type propTypes = {
-    selectedNode: Node;
+    selectedNodes: Node[];
     allTypes: NodeType[];
     onChange: { (): void };
 };
@@ -23,10 +23,54 @@ export class NodeDetails extends React.Component<propTypes> {
     }
 
     private handleNodeTypeChange(event: any) {
-        this.props.selectedNode.setType(event.target.value);
+        this.props.selectedNodes.forEach(
+            (n: Node) => n.setType(event.target.value) // TODO: Later implement new save point handling to collect them all into a big one
+        );
         this.props.onChange();
     }
 
+    private get referenceNode(): Node {
+        if (
+            this.props.selectedNodes == undefined ||
+            this.props.selectedNodes.length <= 0
+        ) {
+            // Nothing selected
+            return new Node();
+        } else if (this.props.selectedNodes.length === 1) {
+            // Single node handling
+            return this.props.selectedNodes[0];
+        } else {
+            // Multiple nodes selected => Create a kind of merged node
+            const refNode = new Node();
+            Object.assign(refNode, this.props.selectedNodes[0]);
+
+            refNode.banner = this.getCollectiveValue((n: Node) => n.banner);
+            refNode.icon = this.getCollectiveValue((n: Node) => n.icon);
+            refNode.video = this.getCollectiveValue((n: Node) => n.video);
+            refNode.type = this.getCollectiveValue((n: Node) => n.type);
+
+            return refNode;
+        }
+    }
+
+    /**
+     * Tries to find a representative value for a specific property over all selected nodes.
+     * @param propGetter Function that returns the value to test for each node.
+     * @returns If all nodes have the same value, this value is returned. Otherwise undefined is returned.
+     */
+    getCollectiveValue(propGetter: (n: Node) => any): any {
+        const sameValue: any = propGetter(this.props.selectedNodes[0]);
+
+        const differentValueFound = this.props.selectedNodes.some(
+            (n: Node) => propGetter(n) !== sameValue
+        );
+        if (differentValueFound) {
+            return undefined;
+        }
+
+        return sameValue;
+    }
+
     /**
      * Generic function for handeling a changing text input and applying the new value to the currently selected node.
      * @param event Change event of text input.
@@ -36,22 +80,18 @@ export class NodeDetails extends React.Component<propTypes> {
         const newValue = event.target.value;
 
         // Actual change?
-        if ((this.props.selectedNode as any)[property] == newValue) {
+        if ((this.referenceNode as any)[property] == newValue) {
             return;
         }
 
-        (this.props.selectedNode as any)[property] = newValue;
+        this.props.selectedNodes.forEach((n: any) => (n[property] = newValue));
         this.props.onChange();
 
         // Save change, but debounce, so it doesn't trigger too quickly
         this.debounce(
             (property: string) => {
-                this.props.selectedNode.graph.storeCurrentData(
-                    "Changed " +
-                        property +
-                        " of node [" +
-                        this.props.selectedNode.toString() +
-                        "]"
+                this.props.selectedNodes[0].graph.storeCurrentData(
+                    "Changed " + property + " of selected nodes"
                 );
                 this.props.onChange();
             },
@@ -82,50 +122,62 @@ export class NodeDetails extends React.Component<propTypes> {
     }
 
     render(): ReactNode {
-        if (this.props.selectedNode === undefined) {
+        if (
+            this.props.selectedNodes === undefined ||
+            this.props.selectedNodes.length <= 0
+        ) {
             return <p>No Node selected.</p>;
         }
 
         return (
             <div id="nodedetails">
-                <div>
-                    <label htmlFor="node-name" hidden>
-                        Name
-                    </label>
-                    <input
-                        type="text"
-                        id="node-name"
-                        name="node-name"
-                        placeholder="Enter name"
-                        className="bottom-space"
-                        value={this.props.selectedNode.name}
-                        onChange={(event) =>
-                            this.handleTextChange(event, "name")
-                        }
-                    ></input>
-                </div>
-                <div>
-                    <label htmlFor="node-description">Description</label>
-                    <br />
-                    <textarea
-                        id="node-description"
-                        name="node-description"
-                        className="bottom-space"
-                        value={this.props.selectedNode.description}
-                        onChange={(event) =>
-                            this.handleTextChange(event, "description")
-                        }
-                    ></textarea>
-                </div>
+                {this.props.selectedNodes.length === 1 ? (
+                    <div>
+                        <label htmlFor="node-name" hidden>
+                            Name
+                        </label>
+                        <input
+                            type="text"
+                            id="node-name"
+                            name="node-name"
+                            placeholder="Enter name"
+                            className="bottom-space"
+                            value={this.referenceNode.name}
+                            onChange={(event) =>
+                                this.handleTextChange(event, "name")
+                            }
+                        ></input>
+                    </div>
+                ) : (
+                    <h3>{this.props.selectedNodes.length} nodes selected</h3>
+                )}
+
+                {this.props.selectedNodes.length === 1 ? (
+                    <div>
+                        <label htmlFor="node-description">Description</label>
+                        <br />
+                        <textarea
+                            id="node-description"
+                            name="node-description"
+                            className="bottom-space"
+                            value={this.referenceNode.description ?? ""}
+                            onChange={(event) =>
+                                this.handleTextChange(event, "description")
+                            }
+                        ></textarea>
+                    </div>
+                ) : (
+                    ""
+                )}
                 <div>
                     <label htmlFor="node-image">Icon Image</label>
                     <br />
-                    {this.props.selectedNode.icon ? (
+                    {this.referenceNode.icon ? (
                         <div>
                             <img
                                 id="node-image-preview"
                                 className="preview-image"
-                                src={this.props.selectedNode.icon}
+                                src={this.referenceNode.icon}
                             />
                             <br />
                         </div>
@@ -138,7 +190,7 @@ export class NodeDetails extends React.Component<propTypes> {
                         name="node-image"
                         placeholder="Image URL"
                         className="bottom-space"
-                        value={this.props.selectedNode.icon}
+                        value={this.referenceNode.icon ?? ""}
                         onChange={(event) =>
                             this.handleTextChange(event, "icon")
                         }
@@ -147,12 +199,12 @@ export class NodeDetails extends React.Component<propTypes> {
                 <div>
                     <label htmlFor="node-detail-image">Banner Image</label>
                     <br />
-                    {this.props.selectedNode.banner ? (
+                    {this.referenceNode.banner ? (
                         <div>
                             <img
                                 id="node-image-preview"
                                 className="preview-image"
-                                src={this.props.selectedNode.banner}
+                                src={this.referenceNode.banner}
                             />
                             <br />
                         </div>
@@ -165,7 +217,7 @@ export class NodeDetails extends React.Component<propTypes> {
                         name="node-detail-image"
                         placeholder="Image URL"
                         className="bottom-space"
-                        value={this.props.selectedNode.banner}
+                        value={this.referenceNode.banner ?? ""}
                         onChange={(event) =>
                             this.handleTextChange(event, "banner")
                         }
@@ -178,9 +230,18 @@ export class NodeDetails extends React.Component<propTypes> {
                         id="node-type"
                         name="node-type"
                         className="bottom-space"
-                        value={this.props.selectedNode.type.id}
+                        value={
+                            this.referenceNode.type
+                                ? this.referenceNode.type.id
+                                : ""
+                        }
                         onChange={this.handleNodeTypeChange}
                     >
+                        <option
+                            className="empty-select-option"
+                            disabled
+                            selected
+                        ></option>
                         {this.props.allTypes.map((type) => (
                             <option key={type.id} value={type.id}>
                                 {type.name}
@@ -196,26 +257,30 @@ export class NodeDetails extends React.Component<propTypes> {
                         placeholder="Video URL"
                         id="node-video"
                         name="node-video"
-                        value={this.props.selectedNode.video}
+                        value={this.referenceNode.video ?? ""}
                         onChange={(event) =>
                             this.handleTextChange(event, "video")
                         }
                     ></input>
                 </div>
-                <div>
-                    <label htmlFor="node-references">References</label>{" "}
-                    <small>One URL per line</small>
-                    <br />
-                    <textarea
-                        id="node-references"
-                        name="node-references"
-                        className="bottom-space"
-                        value={this.props.selectedNode.references}
-                        onChange={(event) =>
-                            this.handleTextChange(event, "references")
-                        }
-                    ></textarea>
-                </div>
+                {this.props.selectedNodes.length === 1 ? (
+                    <div>
+                        <label htmlFor="node-references">References</label>{" "}
+                        <small>One URL per line</small>
+                        <br />
+                        <textarea
+                            id="node-references"
+                            name="node-references"
+                            className="bottom-space"
+                            value={this.referenceNode.references}
+                            onChange={(event) =>
+                                this.handleTextChange(event, "references")
+                            }
+                        ></textarea>
+                    </div>
+                ) : (
+                    ""
+                )}
             </div>
         );
     }
diff --git a/src/editor/js/components/nodetypeentry.tsx b/src/editor/js/components/nodetypeentry.tsx
index a5a1cc3b52bd1056d45ba36ad49abc7ef91199ef..fab85cf7e2e71dc6b0185590d99c446d0f35b0d8 100644
--- a/src/editor/js/components/nodetypeentry.tsx
+++ b/src/editor/js/components/nodetypeentry.tsx
@@ -8,6 +8,7 @@ type propTypes = {
     graph: Graph;
     type: NodeType;
     onChange: { (): void };
+    onSelectAll: (type: NodeType) => void;
 };
 type stateTypes = {
     temporaryColor: string;
@@ -82,7 +83,6 @@ export class NodeTypeEntry extends React.Component<propTypes, stateTypes> {
             return;
         }
 
-        //TODO: Make sure, that this event is not triggered to quickly!
         (this.props.type as any)[property] = newValue;
         this.props.onChange();
 
@@ -139,6 +139,9 @@ export class NodeTypeEntry extends React.Component<propTypes, stateTypes> {
                     }
                     onChange={(event) => this.handleColorChange(event)}
                 />
+                <button onClick={() => this.props.onSelectAll(this.props.type)}>
+                    Select nodes
+                </button>
                 {this.props.graph && this.props.graph.types.length > 1 ? (
                     <button onClick={this.deleteType}>Delete</button>
                 ) : (
diff --git a/src/editor/js/components/nodetypeseditor.tsx b/src/editor/js/components/nodetypeseditor.tsx
index b649a1da777e15a2f10fe45deea5ff9e831763e8..d429dcec671352d43a6d1cb604773e0990e55bf9 100644
--- a/src/editor/js/components/nodetypeseditor.tsx
+++ b/src/editor/js/components/nodetypeseditor.tsx
@@ -8,6 +8,7 @@ import { NodeType } from "../structures/graph/nodetype";
 type propTypes = {
     graph: Graph;
     onChange: { (): void };
+    onSelectAll: (type: NodeType) => void;
 };
 
 export class NodeTypesEditor extends React.Component<propTypes> {
@@ -35,6 +36,7 @@ export class NodeTypesEditor extends React.Component<propTypes> {
                             key={type.id}
                             type={type}
                             graph={this.props.graph}
+                            onSelectAll={this.props.onSelectAll}
                         />
                     ))}
                 </ul>
diff --git a/src/editor/js/components/selectlayer.css b/src/editor/js/components/selectlayer.css
new file mode 100644
index 0000000000000000000000000000000000000000..d30216a4599d7df361ee9bb8e0a4647b038bc876
--- /dev/null
+++ b/src/editor/js/components/selectlayer.css
@@ -0,0 +1,28 @@
+div#ks-editor #select-layer {
+    position: relative;
+}
+
+div#ks-editor #box-select {
+    position: absolute;
+    z-index: 300000;
+    border-style: dotted;
+    border-color: rgba(0, 0, 0, 0);
+    border-width: 2px;
+    background-color: rgba(0, 0, 0, 0);
+    pointer-events: none;
+
+    -webkit-transition-property: border-color, background-color;
+    -moz-transition-property: border-color, background-color;
+    -o-transition-property: border-color, background-color;
+    transition-property: border-color, background-color;
+
+    -webkit-transition-duration: 200ms;
+    -moz-transition-duration: 200ms;
+    -o-transition-duration: 200ms;
+    transition-duration: 200ms;
+}
+
+div#ks-editor #box-select.visible {
+    border-color: #3e74cc;
+    background-color: rgba(255, 255, 255, 0.5);
+}
diff --git a/src/editor/js/components/selectlayer.tsx b/src/editor/js/components/selectlayer.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..94ece3104268917e32d96f9ae4f649f6e4e6955e
--- /dev/null
+++ b/src/editor/js/components/selectlayer.tsx
@@ -0,0 +1,161 @@
+import React from "react";
+import { ReactNode } from "react";
+import { Node } from "../structures/graph/node";
+import "./selectlayer.css";
+
+type propTypes = {
+    children: any;
+    allNodes: Node[];
+    isEnable: () => boolean;
+    screen2GraphCoords: (x: number, y: number) => any;
+    onBoxSelect: (nodes: Node[]) => void;
+};
+
+type layerCoordinates = {
+    x: number;
+    y: number;
+};
+
+export class SelectLayer extends React.Component<propTypes> {
+    private layerContainer: any;
+    private layerBox: any;
+    private initialSelectPoint: layerCoordinates = undefined;
+
+    constructor(props: propTypes) {
+        super(props);
+
+        this.isSelecting = this.isSelecting.bind(this);
+        this.onBoxSelect = this.onBoxSelect.bind(this);
+        this.boxSelectOnPointerDown = this.boxSelectOnPointerDown.bind(this);
+        this.boxSelectOnPointerMove = this.boxSelectOnPointerMove.bind(this);
+        this.boxSelectOnPointerUp = this.boxSelectOnPointerUp.bind(this);
+
+        this.layerContainer = React.createRef();
+        this.layerBox = React.createRef();
+    }
+
+    componentDidMount(): void {
+        this.setupBoxSelect();
+    }
+
+    setupBoxSelect() {
+        // Source: https://github.com/vasturiano/force-graph/issues/151#issuecomment-735850938
+        this.layerContainer.current.onpointerdown = this.boxSelectOnPointerDown;
+        this.layerContainer.current.onpointermove = this.boxSelectOnPointerMove;
+        this.layerContainer.current.onpointerup = this.boxSelectOnPointerUp;
+    }
+
+    private isSelecting(): boolean {
+        if (!this.initialSelectPoint) {
+            return false;
+        }
+
+        if (!this.props.isEnable()) {
+            this.initialSelectPoint = undefined;
+            this.layerBox.current.className = "";
+            return false;
+        }
+
+        return true;
+    }
+
+    onBoxSelect(left: number, bottom: number, top: number, right: number) {
+        // Filter out selected nodes
+        const hitNodes: Node[] = [];
+        const tl = this.props.screen2GraphCoords(left, top);
+        const br = this.props.screen2GraphCoords(right, bottom);
+        this.props.allNodes.forEach((node: any) => {
+            if (
+                tl.x < node.x &&
+                node.x < br.x &&
+                br.y > node.y &&
+                node.y > tl.y
+            ) {
+                // Add node if in box area
+                hitNodes.push(node);
+            }
+        });
+
+        this.props.onBoxSelect(hitNodes);
+    }
+
+    boxSelectOnPointerDown(e: any) {
+        if (!this.props.isEnable()) {
+            return;
+        }
+
+        e.preventDefault();
+        this.layerBox.current.style.left = e.offsetX.toString() + "px";
+        this.layerBox.current.style.top = e.offsetY.toString() + "px";
+        this.layerBox.current.style.width = "0px";
+        this.layerBox.current.style.height = "0px";
+        this.initialSelectPoint = {
+            x: e.offsetX,
+            y: e.offsetY,
+        };
+        this.layerBox.current.className = "visible";
+    }
+
+    boxSelectOnPointerMove(e: any) {
+        if (!this.isSelecting()) {
+            return;
+        }
+
+        e.preventDefault();
+        if (e.offsetX < this.initialSelectPoint.x) {
+            this.layerBox.current.style.left = e.offsetX.toString() + "px";
+            this.layerBox.current.style.width =
+                (this.initialSelectPoint.x - e.offsetX).toString() + "px";
+        } else {
+            this.layerBox.current.style.left =
+                this.initialSelectPoint.x.toString() + "px";
+            this.layerBox.current.style.width =
+                (e.offsetX - this.initialSelectPoint.x).toString() + "px";
+        }
+        if (e.offsetY < this.initialSelectPoint.y) {
+            this.layerBox.current.style.top = e.offsetY.toString() + "px";
+            this.layerBox.current.style.height =
+                (this.initialSelectPoint.y - e.offsetY).toString() + "px";
+        } else {
+            this.layerBox.current.style.top =
+                this.initialSelectPoint.y.toString() + "px";
+            this.layerBox.current.style.height =
+                (e.offsetY - this.initialSelectPoint.y).toString() + "px";
+        }
+    }
+
+    boxSelectOnPointerUp(e: any) {
+        if (!this.isSelecting()) {
+            return;
+        }
+
+        e.preventDefault();
+        let left, bottom, top, right;
+        if (e.offsetX < this.initialSelectPoint.x) {
+            left = e.offsetX;
+            right = this.initialSelectPoint.x;
+        } else {
+            left = this.initialSelectPoint.x;
+            right = e.offsetX;
+        }
+        if (e.offsetY < this.initialSelectPoint.y) {
+            top = e.offsetY;
+            bottom = this.initialSelectPoint.y;
+        } else {
+            top = this.initialSelectPoint.y;
+            bottom = e.offsetY;
+        }
+        this.initialSelectPoint = undefined;
+        this.layerBox.current.className = "";
+        this.onBoxSelect(left, bottom, top, right);
+    }
+
+    render(): ReactNode {
+        return (
+            <div ref={this.layerContainer} id="select-layer">
+                <div ref={this.layerBox} id="box-select"></div>
+                {this.props.children}
+            </div>
+        );
+    }
+}
diff --git a/src/editor/js/structures/graph/node.ts b/src/editor/js/structures/graph/node.ts
index dfa16a209cd39f6d93600cae5ba778dacfffe091..e79dbc7b07dcd997064d3a9fe18a8ecf84fbc0a5 100644
--- a/src/editor/js/structures/graph/node.ts
+++ b/src/editor/js/structures/graph/node.ts
@@ -115,8 +115,8 @@ export class Node extends GraphElement implements Common.Node {
     }
 
     /**
-     * Connects a given node to itself. Only works if they are in the same graph.
-     * @param node Other node to connect.
+     * Connects a given node to itself. Only works if they are in the same graph. This node will be source.
+     * @param node Other node to connect. Will be target.
      * @returns The created link, if successful, otherwise undefined.
      */
     public connect(node: Node): Link {
diff --git a/src/editor/js/structures/manageddata.ts b/src/editor/js/structures/manageddata.ts
index 65c6eeb1d540fa3567ea7c9b0ea1cde518f7f095..702dd86db8884c74145888c5110e988693366516 100644
--- a/src/editor/js/structures/manageddata.ts
+++ b/src/editor/js/structures/manageddata.ts
@@ -16,7 +16,7 @@ export default class ManagedData extends SerializableItem {
     public history: SavePoint[]; // All save points of the data.
     public historyPosition: number; // Currently selected save point in history. Latest always at index 0.
     private savedHistoryId: number; // Id of save point that is considered saved.
-    private storingEnabled: boolean; // To internally disable saving of objects on save call.
+    private storingDisabled: number; // Storing is only enabled if this is 0 (or below).
 
     /**
      * Sets initial states.
@@ -28,7 +28,7 @@ export default class ManagedData extends SerializableItem {
         this.history = []; // Newest state is always at 0
         this.historyPosition = 0;
         this.savedHistoryId = 0;
-        this.storingEnabled = true;
+        this.storingDisabled = 0;
     }
 
     /**
@@ -88,14 +88,17 @@ export default class ManagedData extends SerializableItem {
      * Setter to disable storing save points.
      */
     public disableStoring() {
-        this.storingEnabled = false;
+        this.storingDisabled += 1;
     }
 
     /**
      * Setter to enable storing save points.
      */
     public enableStoring() {
-        this.storingEnabled = true;
+        this.storingDisabled -= 1;
+        if (this.storingDisabled < 0) {
+            this.storingDisabled = 0;
+        }
     }
 
     /**
@@ -217,7 +220,7 @@ export default class ManagedData extends SerializableItem {
      * @param relevantChanges Indicates major or minor changes. Major changes get a new id to indicate an actual changed state. Should usually be true.
      */
     public storeCurrentData(description: string, relevantChanges = true) {
-        if (this.storingEnabled === false) {
+        if (this.storingDisabled) {
             return;
         }