diff --git a/editor/css/editor.css b/editor/css/editor.css
index 91170d51b3f8d1660650baf6a097a82aeb1ab79f..4fe7246cec32694e3179f86c97f1eed531d71730 100644
--- a/editor/css/editor.css
+++ b/editor/css/editor.css
@@ -62,3 +62,12 @@ div#ks-editor img.preview-image {
 div#ks-editor #toolbar-settings, div#ks-editor #toolbar-save {
     float: right;
 }
+
+div#ks-editor #boxSelect {
+    position: absolute;
+    z-index: 300000;
+    border-style: dotted;
+    border-color: #3e74cc;
+    background-color: rgba(255, 255, 255, 0.5);
+    pointer-events: none;
+}
diff --git a/editor/editor.php b/editor/editor.php
index 2fc3a38c523dd43cfe9aaf965f032e1929147fc4..b893ec251a9625da12134954d1b39fa702d48adc 100644
--- a/editor/editor.php
+++ b/editor/editor.php
@@ -1,7 +1,7 @@
 <div id="ks-editor">
     <!--The id "ks-editor" indicates, that the javascript associated with this should automatically be executed-->
     <h1>Interface</h1>
-    <div id="2d-graph"></div>
+    <div id="box-select"><div id="2d-graph"></div></div>
     <section id="toolbar"></section>
     <section id="tool-menu">
         <div id="collect-menu" class="hidden">
diff --git a/editor/js/editor.js b/editor/js/editor.js
index 2f82e1f524217b184ec642ffe076380ac786e410..e3f7a2aa379b2690d842820c2c112bdaf8b51571 100644
--- a/editor/js/editor.js
+++ b/editor/js/editor.js
@@ -8,7 +8,7 @@ import { setSpace, SPACE } from "../../config";
 
 export var state = undefined;
 export var graph = undefined;
-var graphObj;
+export var renderer;
 
 window.onload = function () {
     // Only execute, if corresponding dom is present
@@ -43,7 +43,7 @@ export function loadSpace(spaceId) {
 
 function extractPositions(event) {
     return {
-        graph: graphObj.screen2GraphCoords(event.layerX, event.layerY),
+        graph: renderer.screen2GraphCoords(event.layerX, event.layerY),
         window: { x: event.clientX, y: event.clientY },
     };
 }
@@ -52,7 +52,7 @@ function load() {
     const graphContainer = document.getElementById("2d-graph");
     const width = graphContainer.offsetWidth;
 
-    graphObj = ForceGraph()(graphContainer)
+    renderer = ForceGraph()(graphContainer)
         .height(600)
         .width(width)
         .graphData(graph.data)
@@ -76,9 +76,9 @@ function load() {
         .onLinkClick((link) => state.onLinkClick(link));
 
     graph.onChangeCallbacks.push((data) => {
-        graphObj.cooldownTicks(0);
-        graphObj.graphData(data);
+        renderer.cooldownTicks(0);
+        renderer.graphData(data);
     });
 
-    graph.setRenderer(graphObj);
+    graph.setRenderer(renderer);
 }
diff --git a/editor/js/state.js b/editor/js/state.js
index 1672b394d06a8a6b6c04fdc8a8160658b3a95719..73edbcdb96f21e827c52e8c79eeb832e470ce210 100644
--- a/editor/js/state.js
+++ b/editor/js/state.js
@@ -2,6 +2,7 @@ import Tool from "./tools/tool";
 import UndoTool from "./tools/undotool";
 import RedoTool from "./tools/redotool";
 import SelectTool from "./tools/selecttool";
+import CollectTool from "./tools/collecttool";
 import DeleteTool from "./tools/deletetool";
 import AddNodeTool from "./tools/addnodetool";
 import ConnectTool from "./tools/connecttool";
@@ -15,6 +16,7 @@ export const TOOLS = {
     undo: new UndoTool("undo"),
     redo: new RedoTool("redo"),
     select: new SelectTool("select"),
+    collect: new CollectTool("collect"),
     delete: new DeleteTool("delete"),
     addnode: new AddNodeTool("addnode"),
     connect: new ConnectTool("connect"),
@@ -26,7 +28,7 @@ export const CONTEXT = {
     node: "node",
     link: "link",
     mixed: "mixed",
-    nothing: "nothing"
+    nothing: "nothing",
 };
 
 export class State extends Tool {
@@ -73,6 +75,12 @@ export class State extends Tool {
         this.selectedItems.add(item);
     }
 
+    addSelectedItems(items) {
+        Object.values(items).forEach((item) => {
+            this.selectedItems.add(item);
+        });
+    }
+
     removeSelectedItem(item) {
         this.selectedItems.delete(item);
     }
@@ -91,11 +99,11 @@ export class State extends Tool {
     }
 
     linkColor(link) {
-        return 'red';
+        return "red";
     }
 
     nodeColor(node) {
-        return 'black';
+        return "black";
     }
 
     onKeyDown(key) {
@@ -144,7 +152,7 @@ export class State extends Tool {
         // Draw image
         if (node[Graph.NODE_IMAGE] !== undefined) {
             var path = node[Graph.NODE_IMAGE];
-            
+
             if (!path.includes("/")) {
                 path = Graph.IMAGE_SRC + path;
             }
@@ -163,18 +171,24 @@ export class State extends Tool {
         // Draw label
         if (this.labelVisible) {
             const label = node[Graph.NODE_LABEL];
-            const fontSize = 11/globalScale;
+            const fontSize = 11 / globalScale;
             ctx.font = `${fontSize}px Sans-Serif`;
             const textWidth = ctx.measureText(label).width;
-            const bckgDimensions = [textWidth, fontSize].map(n => n + fontSize * 0.2); // some padding
-    
+            const bckgDimensions = [textWidth, fontSize].map(
+                (n) => n + fontSize * 0.2
+            ); // some padding
+
             const nodeHeightOffset = Graph.IMAGE_SIZE / 3 + bckgDimensions[1];
-            ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
-            ctx.fillRect(node.x - bckgDimensions[0] / 2, node.y - bckgDimensions[1] / 2 + nodeHeightOffset, ...bckgDimensions);
-    
-            ctx.textAlign = 'center';
-            ctx.textBaseline = 'middle';
-            ctx.fillStyle = 'white';
+            ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
+            ctx.fillRect(
+                node.x - bckgDimensions[0] / 2,
+                node.y - bckgDimensions[1] / 2 + nodeHeightOffset,
+                ...bckgDimensions
+            );
+
+            ctx.textAlign = "center";
+            ctx.textBaseline = "middle";
+            ctx.fillStyle = "white";
             ctx.fillText(label, node.x, node.y + nodeHeightOffset);
         }
 
@@ -230,7 +244,12 @@ export class State extends Tool {
         }
 
         // Draw gradient link
-        var gradient = ctx.createLinearGradient(link.source.x, link.source.y, link.target.x, link.target.y);
+        var gradient = ctx.createLinearGradient(
+            link.source.x,
+            link.source.y,
+            link.target.x,
+            link.target.y
+        );
         // Have reversed colors
         // Color at source node referencing the target node and vice versa
         gradient.addColorStop("0", graph.getNodeColor(link.target));
@@ -247,7 +266,7 @@ export class State extends Tool {
         // if (link === lastLink) {
         //     ctx.stroke();
         // }
-        
+
         return undefined;
     }
 
diff --git a/editor/js/tools/collecttool.js b/editor/js/tools/collecttool.js
index ffd3f71db598a33f7613e741fb93dfd8f0947daf..9fde474ff691107f4b45b5c0cc959d9593f17551 100644
--- a/editor/js/tools/collecttool.js
+++ b/editor/js/tools/collecttool.js
@@ -1,11 +1,128 @@
 import Tool from "./tool";
-import { state } from "../editor";
+import { graph, state, renderer } from "../editor";
 import { CONTEXT } from "../state";
 import { CollectMenu, COLLECTION_KEY } from "./menus/collectmenu";
+import * as Graph from "../graph";
 
 export default class CollectTool extends Tool {
     constructor(key) {
         super("Collect", "collect", key, new CollectMenu());
+        this.setupBoxSelect();
+    }
+
+    setupBoxSelect() {
+        document.addEventListener("load", () => {
+            // Source: https://github.com/vasturiano/force-graph/issues/151#issuecomment-735850938
+
+            // forceGraph element is the element provided to the Force Graph Library
+            document
+                .getElementById("ks-editor 2d-graph")
+                .addEventListener("pointerdown", (e) => {
+                    if (e.shiftKey) {
+                        e.preventDefault();
+                        this.boxSelect = document.createElement("div");
+                        this.boxSelect.id = "boxSelect";
+                        this.boxSelect.style.left = e.offsetX.toString() + "px";
+                        this.boxSelect.style.top = e.offsetY.toString() + "px";
+                        this.boxSelectStart = {
+                            x: e.offsetX,
+                            y: e.offsetY,
+                        };
+                        // app element is the element just above the forceGraph element.
+                        document
+                            .getElementById("ks-editor box-select")
+                            .appendChild(this.boxSelect);
+                    }
+                });
+
+            document
+                .getElementById("ks-editor 2d-graph")
+                .addEventListener("pointermove", (e) => {
+                    if (e.shiftKey && this.boxSelect) {
+                        e.preventDefault();
+                        if (e.offsetX < this.boxSelectStart.x) {
+                            this.boxSelect.style.left =
+                                e.offsetX.toString() + "px";
+                            this.boxSelect.style.width =
+                                (this.boxSelectStart.x - e.offsetX).toString() +
+                                "px";
+                        } else {
+                            this.boxSelect.style.left =
+                                this.boxSelectStart.x.toString() + "px";
+                            this.boxSelect.style.width =
+                                (e.offsetX - this.boxSelectStart.x).toString() +
+                                "px";
+                        }
+                        if (e.offsetY < this.boxSelectStart.y) {
+                            this.boxSelect.style.top =
+                                e.offsetY.toString() + "px";
+                            this.boxSelect.style.height =
+                                (this.boxSelectStart.y - e.offsetY).toString() +
+                                "px";
+                        } else {
+                            this.boxSelect.style.top =
+                                this.boxSelectStart.y.toString() + "px";
+                            this.boxSelect.style.height =
+                                (e.offsetY - this.boxSelectStart.y).toString() +
+                                "px";
+                        }
+                    } else if (this.boxSelect) {
+                        this.boxSelect.remove();
+                    }
+                });
+
+            document
+                .getElementById("ks-editor 2d-graph")
+                .addEventListener("pointerup", (e) => {
+                    if (e.shiftKey && this.boxSelect) {
+                        e.preventDefault();
+                        let left, bottom, top, right;
+                        if (e.offsetX < this.boxSelectStart.x) {
+                            left = e.offsetX;
+                            right = this.boxSelectStart.x;
+                        } else {
+                            left = this.boxSelectStart.x;
+                            right = e.offsetX;
+                        }
+                        if (e.offsetY < this.boxSelectStart.y) {
+                            top = e.offsetY;
+                            bottom = this.boxSelectStart.y;
+                        } else {
+                            top = this.boxSelectStart.y;
+                            bottom = e.offsetY;
+                        }
+                        runBoxSelect(left, bottom, top, right);
+                        this.boxSelect.remove();
+                    } else if (this.boxSelect) {
+                        this.boxSelect.remove();
+                    }
+                });
+
+            const runBoxSelect = (left, bottom, top, right) => {
+                const tl = renderer.screen2GraphCoords(left, top);
+                const br = renderer.screen2GraphCoords(right, bottom);
+                const hitNodes = [];
+                graph.data[Graph.GRAPH_NODES].forEach((node) => {
+                    if (
+                        tl.x < node.x &&
+                        node.x < br.x &&
+                        br.y > node.y &&
+                        node.y > tl.y
+                    ) {
+                        hitNodes.push(node);
+                    }
+                });
+                // run code to select your nodes here
+                // return selectGraphObjects(hitNodes);
+                console.log(hitNodes);
+
+                if (state.itemsContext !== CONTEXT.node) {
+                    state.clearSelectedItems();
+                    state.itemsContext = CONTEXT.node;
+                }
+                state.addSelectedItems(hitNodes);
+            };
+        });
     }
 
     onNodeClick(node) {