JavaScript DHTML/Ext JS/Drag Drop
Содержание
Create DropTarget object
<source lang="html4strict">
<html> <head> <title>Hello World Window</title> <link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css" /> <script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="ext-3.0.0/ext-all.js"></script> </head>
<body> <script type="text/javascript"> Ext.onReady(function() {
var myData = { records : [ { name : "Record 0", column1 : "0", column2 : "0" }, { name : "Record 1", column1 : "1", column2 : "1" }, { name : "Record 2", column1 : "2", column2 : "2" }, { name : "Record 3", column1 : "3", column2 : "3" }, { name : "Record 4", column1 : "4", column2 : "4" }, { name : "Record 5", column1 : "5", column2 : "5" }, { name : "Record 6", column1 : "6", column2 : "6" }, { name : "Record 7", column1 : "7", column2 : "7" }, { name : "Record 8", column1 : "8", column2 : "8" }, { name : "Record 9", column1 : "9", column2 : "9" } ] };
// Generic fields array to use in both store defs. var fields = [ {name: "name", mapping : "name"}, {name: "column1", mapping : "column1"}, {name: "column2", mapping : "column2"} ]; // create the data store var gridStore = new Ext.data.JsonStore({ fields : fields, data : myData, root : "records" });
// Column Model shortcut array var cols = [ { id : "name", header: "Record Name", width: 160, sortable: true, dataIndex: "name"}, {header: "column1", width: 50, sortable: true, dataIndex: "column1"}, {header: "column2", width: 50, sortable: true, dataIndex: "column2"} ]; // declare the source Grid var grid = new Ext.grid.GridPanel({ ddGroup : "gridDDGroup", store : gridStore, columns : cols, enableDragDrop : true, stripeRows : true, autoExpandColumn : "name", width : 325, region : "west", title : "Data Grid", selModel : new Ext.grid.RowSelectionModel({singleSelect : true}) });
// Declare the text fields. This could have been done inline, is easier to read // for folks learning :) var textField1 = new Ext.form.TextField({ fieldLabel : "Record Name", name : "name" });
var textField2 = new Ext.form.TextField({ fieldLabel : "Column 1", name : "column1" });
var textField3 = new Ext.form.TextField({ fieldLabel : "Column 2", name : "column2" });
// Setup the form panel var formPanel = new Ext.form.FormPanel({ region : "center", title : "Generic Form Panel", bodyStyle : "padding: 10px; background-color: #DFE8F6", labelWidth : 100, width : 325, items : [ textField1, textField2, textField3 ] });
//Simple "border layout" panel to house both grids var displayPanel = new Ext.Panel({ width : 650, height : 300, layout : "border", renderTo : "panel", items : [ grid, formPanel ], bbar : [ "->", // Fill { text : "Reset Example", handler : function() { //refresh source grid gridStore.loadData(myData); formPanel.getForm().reset(); } } ] });
// used to add records to the destination stores var blankRecord = Ext.data.Record.create(fields); /**** * Setup Drop Targets ***/ // This will make sure we only drop to the view container var formPanelDropTargetEl = formPanel.body.dom; var formPanelDropTarget = new Ext.dd.DropTarget(formPanelDropTargetEl, { ddGroup : "gridDDGroup", notifyEnter : function(ddSource, e, data) { //Add some flare to invite drop. formPanel.body.stopFx(); formPanel.body.highlight(); }, notifyDrop : function(ddSource, e, data){ // Reference the record (single selection) for readability var selectedRecord = ddSource.dragData.selections[0];
// Load the record into the form formPanel.getForm().loadRecord(selectedRecord);
// Delete record from the grid. not really required. ddSource.grid.store.remove(selectedRecord); return(true); } });
}); </script>
</body> </html>
</source>
Create Ext.dd.DragSource and Ext.dd.DropTarget
<source lang="html4strict">
<html> <head> <title>Hello World Window</title> <link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css" /> <script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="ext-3.0.0/ext-all.js"></script> </head> <script type="text/javascript"> Ext.onReady(function(){
new Ext.dd.DragSource("drag"); new Ext.dd.DropTarget("drop", { notifyDrop : function(source, event, data) { this.getEl().appendChild(source.getEl()); } });
}); </script> <body>
</body> </html>
</source>
Define notifyDrop handler
<source lang="html4strict">
<html> <head> <title>Hello World Window</title> <link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css" /> <script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="ext-3.0.0/ext-all.js"></script> </head> <script type="text/javascript"> Ext.onReady(function(){
new Ext.dd.DragSource("drag"); new Ext.dd.DropTarget("drop", { notifyDrop : function(source, event, data) { this.getEl().appendChild(source.getEl()); } });
}); </script> <body>
</body> </html>
</source>
Drag and drop between two grids
<source lang="html4strict">
<html> <head> <title>Hello World Window</title> <link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css" /> <script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="ext-3.0.0/ext-all.js"></script> </head> <body> <script type="text/javascript"> Ext.onReady(function() {
var myData = { records : [ { name : "Rec 0", column1 : "0", column2 : "0" }, { name : "Rec 1", column1 : "1", column2 : "1" }, { name : "Rec 2", column1 : "2", column2 : "2" }, { name : "Rec 3", column1 : "3", column2 : "3" }, { name : "Rec 4", column1 : "4", column2 : "4" }, { name : "Rec 5", column1 : "5", column2 : "5" }, { name : "Rec 6", column1 : "6", column2 : "6" }, { name : "Rec 7", column1 : "7", column2 : "7" }, { name : "Rec 8", column1 : "8", column2 : "8" }, { name : "Rec 9", column1 : "9", column2 : "9" } ] };
// Generic fields array to use in both store defs. var fields = [ {name: "name", mapping : "name"}, {name: "column1", mapping : "column1"}, {name: "column2", mapping : "column2"} ]; // create the data store var firstGridStore = new Ext.data.JsonStore({ fields : fields, data : myData, root : "records" });
// Column Model shortcut array var cols = [ { id : "name", header: "Record Name", width: 160, sortable: true, dataIndex: "name"}, {header: "column1", width: 50, sortable: true, dataIndex: "column1"}, {header: "column2", width: 50, sortable: true, dataIndex: "column2"} ]; // declare the source Grid var firstGrid = new Ext.grid.GridPanel({ ddGroup : "secondGridDDGroup", store : firstGridStore, columns : cols, enableDragDrop : true, stripeRows : true, autoExpandColumn : "name", width : 325, region : "west", title : "First Grid" }); var secondGridStore = new Ext.data.JsonStore({ fields : fields, root : "records" }); // create the destination Grid var secondGrid = new Ext.grid.GridPanel({ ddGroup : "firstGridDDGroup", store : secondGridStore, columns : cols, enableDragDrop : true, stripeRows : true, autoExpandColumn : "name", width : 325, region : "center", title : "Second Grid" });
//Simple "border layout" panel to house both grids var displayPanel = new Ext.Panel({ width : 650, height : 300, layout : "border", renderTo : "panel", items : [ firstGrid, secondGrid ], bbar : [ "->", // Fill { text : "Reset both grids", handler : function() { //refresh source grid firstGridStore.loadData(myData); //purge destination grid secondGridStore.removeAll(); } } ] }); // used to add records to the destination stores var blankRecord = Ext.data.Record.create(fields); /**** * Setup Drop Targets ***/ // This will make sure we only drop to the view container var firstGridDropTargetEl = firstGrid.getView().el.dom.childNodes[0].childNodes[1]; var firstGridDropTarget = new Ext.dd.DropTarget(firstGridDropTargetEl, { ddGroup : "firstGridDDGroup", copy : true, notifyDrop : function(ddSource, e, data){ // Generic function to add records. function addRow(record, index, allItems) { // Search for duplicates var foundItem = firstGridStore.findExact("name", record.data.name); // if not found if (foundItem == -1) { firstGridStore.add(record); // Call a sort dynamically firstGridStore.sort("name", "ASC"); //Remove Record from the source ddSource.grid.store.remove(record); } } // Loop through the selections Ext.each(ddSource.dragData.selections ,addRow); return(true); } });
// This will make sure we only drop to the view container var secondGridDropTargetEl = secondGrid.getView().el.dom.childNodes[0].childNodes[1] var destGridDropTarget = new Ext.dd.DropTarget(secondGridDropTargetEl, { ddGroup : "secondGridDDGroup", copy : false, notifyDrop : function(ddSource, e, data){ // Generic function to add records. function addRow(record, index, allItems) { // Search for duplicates var foundItem = secondGridStore.findExact("name", record.data.name); // if not found if (foundItem == -1) { secondGridStore.add(record); // Call a sort dynamically secondGridStore.sort("name", "ASC"); //Remove Record from the source ddSource.grid.store.remove(record); } } // Loop through the selections Ext.each(ddSource.dragData.selections ,addRow); return(true); } });
}); </script>
</body> </html>
</source>
Drop and drop from a table to a form
<source lang="html4strict">
<html> <head> <title>Hello World Window</title> <link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css" /> <script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="ext-3.0.0/ext-all.js"></script> </head>
<body> <script type="text/javascript"> Ext.onReady(function() {
var myData = { records : [ { name : "Record 0", column1 : "0", column2 : "0" }, { name : "Record 1", column1 : "1", column2 : "1" }, { name : "Record 2", column1 : "2", column2 : "2" }, { name : "Record 3", column1 : "3", column2 : "3" }, { name : "Record 4", column1 : "4", column2 : "4" }, { name : "Record 5", column1 : "5", column2 : "5" }, { name : "Record 6", column1 : "6", column2 : "6" }, { name : "Record 7", column1 : "7", column2 : "7" }, { name : "Record 8", column1 : "8", column2 : "8" }, { name : "Record 9", column1 : "9", column2 : "9" } ] };
// Generic fields array to use in both store defs. var fields = [ {name: "name", mapping : "name"}, {name: "column1", mapping : "column1"}, {name: "column2", mapping : "column2"} ]; // create the data store var gridStore = new Ext.data.JsonStore({ fields : fields, data : myData, root : "records" });
// Column Model shortcut array var cols = [ { id : "name", header: "Record Name", width: 160, sortable: true, dataIndex: "name"}, {header: "column1", width: 50, sortable: true, dataIndex: "column1"}, {header: "column2", width: 50, sortable: true, dataIndex: "column2"} ]; // declare the source Grid var grid = new Ext.grid.GridPanel({ ddGroup : "gridDDGroup", store : gridStore, columns : cols, enableDragDrop : true, stripeRows : true, autoExpandColumn : "name", width : 325, region : "west", title : "Data Grid", selModel : new Ext.grid.RowSelectionModel({singleSelect : true}) });
// Declare the text fields. This could have been done inline, is easier to read // for folks learning :) var textField1 = new Ext.form.TextField({ fieldLabel : "Record Name", name : "name" });
var textField2 = new Ext.form.TextField({ fieldLabel : "Column 1", name : "column1" });
var textField3 = new Ext.form.TextField({ fieldLabel : "Column 2", name : "column2" });
// Setup the form panel var formPanel = new Ext.form.FormPanel({ region : "center", title : "Generic Form Panel", bodyStyle : "padding: 10px; background-color: #DFE8F6", labelWidth : 100, width : 325, items : [ textField1, textField2, textField3 ] });
//Simple "border layout" panel to house both grids var displayPanel = new Ext.Panel({ width : 650, height : 300, layout : "border", renderTo : "panel", items : [ grid, formPanel ], bbar : [ "->", // Fill { text : "Reset Example", handler : function() { //refresh source grid gridStore.loadData(myData); formPanel.getForm().reset(); } } ] });
// used to add records to the destination stores var blankRecord = Ext.data.Record.create(fields); /**** * Setup Drop Targets ***/ // This will make sure we only drop to the view container var formPanelDropTargetEl = formPanel.body.dom; var formPanelDropTarget = new Ext.dd.DropTarget(formPanelDropTargetEl, { ddGroup : "gridDDGroup", notifyEnter : function(ddSource, e, data) { //Add some flare to invite drop. formPanel.body.stopFx(); formPanel.body.highlight(); }, notifyDrop : function(ddSource, e, data){ // Reference the record (single selection) for readability var selectedRecord = ddSource.dragData.selections[0];
// Load the record into the form formPanel.getForm().loadRecord(selectedRecord);
// Delete record from the grid. not really required. ddSource.grid.store.remove(selectedRecord); return(true); } });
}); </script>
</body> </html>
</source>
Field to grid drag and drop
<source lang="html4strict">
<html>
<head>
<title>Hello World Window</title>
<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css" />
<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>
</head>
<body> <script type="text/javascript"> /*!
* Ext JS Library 3.0.0 * Copyright(c) 2006-2009 Ext JS, LLC * licensing@extjs.ru * http://www.extjs.ru/license */
// A DropZone which cooperates with DragZones whose dragData contains // a "field" property representing a form Field. Fields may be dropped onto // grid data cells containing a matching data type. Ext.ux.CellFieldDropZone = Ext.extend(Ext.dd.DropZone, {
constructor: function(){},
// Call the DropZone constructor using the View"s scrolling element // only after the grid has been rendered.
init: function(grid) { if (grid.rendered) { this.grid = grid; this.view = grid.getView(); this.store = grid.getStore(); Ext.ux.CellFieldDropZone.superclass.constructor.call(this, this.view.scroller); } else { grid.on("render", this.init, this); } },
// Scroll the main configured Element when we drag close to the edge
containerScroll: true, getTargetFromEvent: function(e) {
// Ascertain whether the mousemove is within a grid cell
var t = e.getTarget(this.view.cellSelector); if (t) {
// We *are* within a grid cell, so ask the View exactly which one, // Extract data from the Model to create a target object for // processing in subsequent onNodeXXXX methods. Note that the target does // not have to be a DOM element. It can be whatever the noNodeXXX methods are // programmed to expect.
var rowIndex = this.view.findRowIndex(t); var columnIndex = this.view.findCellIndex(t); if ((rowIndex !== false) && (columnIndex !== false)) { return { node: t, record: this.store.getAt(rowIndex), fieldName: this.grid.getColumnModel().getDataIndex(columnIndex) } } } },
// On Node enter, see if it is valid for us to drop the field on that type of column.
onNodeEnter: function(target, dd, e, dragData) { delete this.dropOK; if (!target) { return; }
// Check that a field is being dragged.
var f = dragData.field; if (!f) { return; }
// Check whether the data type of the column being dropped on accepts the // dragged field type. If so, set dropOK flag, and highlight the target node.
var type = target.record.fields.get(target.fieldName).type; switch (type) { case "float": case "int": if (!f.isXType("numberfield")) { return; } break; case "date": if (!f.isXType("datefield")) { return; } break; case "boolean": if (!f.isXType("checkbox")) { return; } } this.dropOK = true; Ext.fly(target.node).addClass("x-drop-target-active"); },
// Return the class name to add to the drag proxy. This provides a visual indication // of drop allowed or not allowed.
onNodeOver: function(target, dd, e, dragData) { return this.dropOK ? this.dropAllowed : this.dropNotAllowed; },
// nhighlight the target node.
onNodeOut: function(target, dd, e, dragData) { Ext.fly(target.node).removeClass("x-drop-target-active"); },
// Process the drop event if we have previously ascertained that a drop is OK.
onNodeDrop: function(target, dd, e, dragData) { if (this.dropOK) { target.record.set(target.fieldName, dragData.field.getValue()); return true; } }
}); // A class which makes Fields within a Panel draggable. // the dragData delivered to a coooperating DropZone"s methods contains // the dragged Field in the property "field". Ext.ux.PanelFieldDragZone = Ext.extend(Ext.dd.DragZone, {
constructor: function(){},
// Call the DRagZone"s constructor. The Panel must have been rendered.
init: function(panel) { if (panel.nodeType) { Ext.ux.PanelFieldDragZone.superclass.init.apply(this, arguments); } else { if (panel.rendered) { Ext.ux.PanelFieldDragZone.superclass.constructor.call(this, panel.getEl()); var i = Ext.fly(panel.getEl()).select("input"); i.unselectable(); } else { panel.on("afterlayout", this.init, this, {single: true}); } } }, scroll: false,
// On mousedown, we ascertain whether it is on one of our draggable Fields. // If so, we collect data about the draggable object, and return a drag data // object which contains our own data, plus a "ddel" property which is a DOM // node which provides a "view" of the dragged data.
getDragData: function(e) { var t = e.getTarget("input"); if (t) { e.stopEvent();
// Ugly code to "detach" the drag gesture from the input field. // Without this, Opera never changes the mouseover target from the input field // even when dragging outside of the field - it just keeps selecting.
if (Ext.isOpera) { Ext.fly(t).on("mousemove", function(e1){ t.style.visibility = "hidden"; (function(){ t.style.visibility = ""; }).defer(1); }, null, {single:true}); }
// Get the data we are dragging: the Field // create a ddel for the drag proxy to display
var f = Ext.getCmp(t.id); var d = document.createElement("div"); d.className = "x-form-text"; d.appendChild(document.createTextNode(t.value)); Ext.fly(d).setWidth(f.getEl().getWidth()); return { field: f, ddel: d }; } },
// The coordinates to slide the drag proxy back to on failed drop.
getRepairXY: function() { return this.dragData.field.getEl().getXY(); }
}); Ext.onReady(function(){
var myData = [ ["3m Co",71.72,0.02,0.03,"9/1 12:00am"], ["Alcoa Inc",29.01,0.42,1.47,"9/1 12:00am"], ["Altria Group Inc",83.81,0.28,0.34,"9/1 12:00am"], ["American Express Company",52.55,0.01,0.02,"9/1 12:00am"], ["American International Group, Inc.",64.13,0.31,0.49,"9/1 12:00am"], ["AT&T Inc.",31.61,-0.48,-1.54,"9/1 12:00am"], ["Boeing Co.",75.43,0.53,0.71,"9/1 12:00am"], ["Caterpillar Inc.",67.27,0.92,1.39,"9/1 12:00am"], ["Citigroup, Inc.",49.37,0.02,0.04,"9/1 12:00am"], ["E.I. du Pont de Nemours and Company",40.48,0.51,1.28,"9/1 12:00am"], ["Exxon Mobil Corp",68.1,-0.43,-0.64,"9/1 12:00am"], ["General Electric Company",34.14,-0.08,-0.23,"9/1 12:00am"], ["General Motors Corporation",30.27,1.09,3.74,"9/1 12:00am"], ["Hewlett-Packard Co.",36.53,-0.03,-0.08,"9/1 12:00am"], ["Honeywell Intl Inc",38.77,0.05,0.13,"9/1 12:00am"], ["Intel Corporation",19.88,0.31,1.58,"9/1 12:00am"], ["International Business Machines",81.41,0.44,0.54,"9/1 12:00am"], ["Johnson & Johnson",64.72,0.06,0.09,"9/1 12:00am"], ["JP Morgan & Chase & Co",45.73,0.07,0.15,"9/1 12:00am"], ["McDonald\"s Corporation",36.76,0.86,2.40,"9/1 12:00am"], ["Merck & Co., Inc.",40.96,0.41,1.01,"9/1 12:00am"], ["Microsoft Corporation",25.84,0.14,0.54,"9/1 12:00am"], ["Pfizer Inc",27.96,0.4,1.45,"9/1 12:00am"], ["The Coca-Cola Company",45.07,0.26,0.58,"9/1 12:00am"], ["The Home Depot, Inc.",34.64,0.35,1.02,"9/1 12:00am"], ["The Procter & Gamble Company",61.91,0.01,0.02,"9/1 12:00am"], ["United Technologies Corporation",63.26,0.55,0.88,"9/1 12:00am"], ["Verizon Communications",35.57,0.39,1.11,"9/1 12:00am"], ["Wal-Mart Stores, Inc.",45.45,0.73,1.63,"9/1 12:00am"] ]; // example of custom renderer function function change(val){ if(val > 0){ return "" + val + ""; }else if(val < 0){ return "" + val + ""; } return val; } // example of custom renderer function function pctChange(val){ if(val > 0){ return "" + val + "%"; }else if(val < 0){ return "" + val + "%"; } return val; } // create the data store var store = new Ext.data.ArrayStore({ fields: [ {name: "company"}, {name: "price", type: "float"}, {name: "change", type: "float"}, {name: "pctChange", type: "float"}, {name: "lastChange", type: "date", dateFormat: "n/j h:ia"} ] }); store.loadData(myData); var helpWindow = new Ext.Window({ title: "Source code", width: 920, height: 500, closeAction: "hide", bodyCfg: {tag: "textarea", readonly: true}, bodyStyle: { backgroundColor: "white", margin: "0px", border: "0px none" }, listeners: { render: function(w) { Ext.Ajax.request({ url: "field-to-grid-dd.js", success: function(r) { w.body.dom.value = r.responseText; } }); } } }); // create the Grid var grid = new Ext.grid.GridPanel({ store: store, columns: [ {id:"company",header: "Company", width: 160, sortable: true, dataIndex: "company"}, {header: "Price", width: 75, sortable: true, renderer: "usMoney", dataIndex: "price"}, {header: "Change", width: 75, sortable: true, renderer: change, dataIndex: "change"}, {header: "% Change", width: 75, sortable: true, renderer: pctChange, dataIndex: "pctChange"}, {header: "Last Updated", width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer("m/d/Y"), dataIndex: "lastChange"} ], plugins: new Ext.ux.CellFieldDropZone(), stripeRows: true, autoExpandColumn: "company", height:350, width:600, title:"Array Grid", bbar: new Ext.PagingToolbar({ buttons: [{ text: "View Source", handler: function() { helpWindow.show(); } }], store: store, pageSize: 25 }) }); grid.render("grid-example"); grid.getSelectionModel().selectFirstRow(); var f = new Ext.Panel({ frame: true, layout: "form", width: 600, plugins: new Ext.ux.PanelFieldDragZone(), style: { "margin-top": "10px" }, labelWidth: 150, items: [{ xtype: "textfield", fieldLabel: "Drag this text", value: "test" },{ xtype: "numberfield", fieldLabel: "Drag this number", value: "1.2" },{ xtype: "datefield", fieldLabel: "Drag this date", value: new Date() }], renderTo: Ext.getBody() });
}); </script>
</body> </html>
</source>
Set up drag and drop zone
<source lang="html4strict">
<html>
<head>
<title>Hello World Window</title>
<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css" />
<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>
</head>
<body> <script type="text/javascript"> Ext.onReady(function() {
var patients = [{ insuranceCode: "11111", name: "Fred Bloggs", address: "Main Street", telephone: "555 1234 123" }, { insuranceCode: "22222", name: "Fred West", address: "Cromwell Street", telephone: "666 666 666" }, { insuranceCode: "33333", name: "Fred Mercury", address: "Over The Rainbow", telephone: "555 321 0987" }, { insuranceCode: "44444", name: "Fred Forsyth", address: "Blimp Street", telephone: "555 111 2222" }, { insuranceCode: "55555", name: "Fred Douglass", address: "Talbot County, Maryland", telephone: "N/A" }]; var PatientRecord = Ext.data.Record.create([{ name: "name" }, { name: "address" }, { name: "telephone" }]); var patientStore = new Ext.data.Store({ data: patients, reader: new Ext.data.JsonReader({ id: "insuranceCode" }, PatientRecord) }); var hospitals = [{ code: "AAAAA", name: "Saint Thomas", address: "Westminster Bridge Road, SE1 7EH", telephone: "020 7188 7188" }, { code: "BBBBB", name: "Queen\"s Medical Centre", address: "Derby Road, NG7 2UH", telephone: "0115 924 9924" }, { code: "CCCCC", name: "Saint Bartholomew", address: "West Smithfield, EC1A 7BE", telephone: "020 7377 7000" }, { code: "DDDDD", name: "Royal London", address: "Whitechapel, E1 1BB", telephone: "020 7377 7000" }]; var HospitalRecord = Ext.data.Record.create([{ name: "name" }, { name: "address" }, { name: "telephone" }]); var hospitalStore = new Ext.data.Store({ data: hospitals, reader: new Ext.data.JsonReader({ id: "code" }, HospitalRecord) }); var patientView = new Ext.DataView({ cls: "patient-view", tpl: "<tpl for=".">" +"
Name | {name} |
Address | {address} |
Telephone | {telephone} |
"</tpl>", itemSelector: "div.patient-source", store: patientStore, listeners: { render: initializePatientDragZone } }); var helpWindow = new Ext.Window({ title: "Source code", width: 920, height: 500, closeAction: "hide", bodyCfg: {tag: "textarea", readonly: true}, bodyStyle: { backgroundColor: "white", margin: "0px", border: "0px none" }, listeners: { render: function(w) { Ext.Ajax.request({ url: "dragdropzones.js", success: function(r) { w.body.dom.value = r.responseText; } }); } } }); var hospitalGrid = new Ext.grid.GridPanel({ title: "Hospitals", region: "center", margins: "0 5 5 0", bbar: [{ text: "View Source", handler: function() { //helpWindow.show(); } }], columns: [{ dataIndex: "name", header: "Name", width: 200 }, { dataIndex: "address", header: "Address", width: 300 }, { dataIndex: "telephone", header: "Telephone", width: 100 }], viewConfig: {tpl: new Ext.XTemplate(""),
enableRowBody: true, getRowClass: function(rec, idx, p, store) { p.body = this.tpl.apply(rec.data); } }, store: hospitalStore, listeners: { render: initializeHospitalDropZone } }); new Ext.Viewport({ layout: "border", items: [{ cls: "app-header", region: "north", height: 100,html: "
Patient Hospital Assignment
",margins: "5 5 5 5" }, { title: "Patients", region: "west", width: 300, margins: "0 5 5 5", items: patientView }, hospitalGrid ] });
}); /*
* Here is where we "activate" the DataView. * We have decided that each node with the class "patient-source" encapsulates a single draggable * object. * * So we inject code into the DragZone which, when passed a mousedown event, interrogates * the event to see if it was within an element with the class "patient-source". If so, we * return non-null drag data. * * Returning non-null drag data indicates that the mousedown event has begun a dragging process. * The data must contain a property called "ddel" which is a DOM element which provides an image * of the data being dragged. The actual node clicked on is not dragged, a proxy element is dragged. * We can insert any other data into the data object, and this will be used by a cooperating DropZone * to perform the drop operation. */
function initializePatientDragZone(v) {
v.dragZone = new Ext.dd.DragZone(v.getEl(), {
// On receipt of a mousedown event, see if it is within a draggable element. // Return a drag data object if so. The data object can contain arbitrary application // data, but it should also contain a DOM element in the ddel property to provide // a proxy to drag.
getDragData: function(e) { var sourceEl = e.getTarget(v.itemSelector, 10); if (sourceEl) { d = sourceEl.cloneNode(true); d.id = Ext.id(); return v.dragData = { sourceEl: sourceEl, repairXY: Ext.fly(sourceEl).getXY(), ddel: d, patientData: v.getRecord(sourceEl).data } } },
// Provide coordinates for the proxy to slide back to on failed drag. // This is the original XY coordinates of the draggable element.
getRepairXY: function() { return this.dragData.repairXY; } });
} /*
* Here is where we "activate" the GridPanel. * We have decided that the element with class "hospital-target" is the element which can receieve * drop gestures. So we inject a method "getTargetFromEvent" into the DropZone. This is constantly called * while the mouse is moving over the DropZone, and it returns the target DOM element if it detects that * the mouse if over an element which can receieve drop gestures. * * Once the DropZone has been informed by getTargetFromEvent that it is over a target, it will then * call several "onNodeXXXX" methods at various points. These include: * * onNodeEnter * onNodeOut * onNodeOver * onNodeDrop * * We provide implementations of each of these to provide behaviour for these events. */
function initializeHospitalDropZone(g) {
g.dropZone = new Ext.dd.DropZone(g.getView().scroller, {
// If the mouse is over a target node, return that node. This is // provided as the "target" parameter in all "onNodeXXXX" node event handling functions
getTargetFromEvent: function(e) { return e.getTarget(".hospital-target"); },
// On entry into a target node, highlight that node.
onNodeEnter : function(target, dd, e, data){ Ext.fly(target).addClass("hospital-target-hover"); },
// On exit from a target node, unhighlight that node.
onNodeOut : function(target, dd, e, data){ Ext.fly(target).removeClass("hospital-target-hover"); },
// While over a target node, return the default drop allowed class which // places a "tick" icon into the drag proxy.
onNodeOver : function(target, dd, e, data){ return Ext.dd.DropZone.prototype.dropAllowed; },
// On node drop, we can interrogate the target node to find the underlying // application object that is the real target of the dragged data. // In this case, it is a Record in the GridPanel"s Store. // We can use the data set up by the DragZone"s getDragData method to read // any data we decided to attach.
onNodeDrop : function(target, dd, e, data){ var rowIndex = g.getView().findRowIndex(target); var h = g.getStore().getAt(rowIndex); Ext.Msg.alert("Drop gesture", "Dropped patient " + data.patientData.name + " on hospital " + h.data.name); return true; } });
} </script>
</body> </html>
</source>