or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-api.mdevents.mdindex.mdplugins.mdutilities.md

events.mddocs/

0

# Events

1

2

Rich event lifecycle with callbacks for drag start/end, list changes, and custom interactions.

3

4

## Capabilities

5

6

### Drag Lifecycle Events

7

8

Events that track the complete drag and drop lifecycle from selection to completion.

9

10

#### onChoose

11

12

Called when an element is selected for dragging.

13

14

```javascript { .api }

15

/**

16

* Called when element is chosen (selected for dragging)

17

* @param evt - Event object with oldIndex property

18

*/

19

onChoose?: (evt: SortableEvent) => void;

20

```

21

22

**Usage Examples:**

23

24

```javascript

25

Sortable.create(el, {

26

onChoose: (evt) => {

27

console.log('Item chosen at index:', evt.oldIndex);

28

evt.item.classList.add('being-dragged');

29

}

30

});

31

```

32

33

#### onUnchoose

34

35

Called when element selection is cancelled before dragging starts.

36

37

```javascript { .api }

38

/**

39

* Called when element selection is cancelled

40

* @param evt - Event object with same properties as onEnd

41

*/

42

onUnchoose?: (evt: SortableEvent) => void;

43

```

44

45

#### onStart

46

47

Called when dragging starts (after any configured delay).

48

49

```javascript { .api }

50

/**

51

* Called when dragging actually starts

52

* @param evt - Event object with oldIndex and item properties

53

*/

54

onStart?: (evt: SortableEvent) => void;

55

```

56

57

**Usage Examples:**

58

59

```javascript

60

Sortable.create(el, {

61

onStart: (evt) => {

62

console.log('Drag started:', evt.item.textContent);

63

document.body.classList.add('dragging-active');

64

}

65

});

66

```

67

68

#### onEnd

69

70

Called when dragging ends (whether successful or cancelled).

71

72

```javascript { .api }

73

/**

74

* Called when dragging ends

75

* @param evt - Event object with comprehensive drag information

76

*/

77

onEnd?: (evt: SortableEvent) => void;

78

```

79

80

**Usage Examples:**

81

82

```javascript

83

Sortable.create(el, {

84

onEnd: (evt) => {

85

document.body.classList.remove('dragging-active');

86

87

if (evt.oldIndex !== evt.newIndex) {

88

console.log(`Item moved from ${evt.oldIndex} to ${evt.newIndex}`);

89

// Save new order

90

saveOrder(evt.from);

91

}

92

}

93

});

94

```

95

96

### List Change Events

97

98

Events that fire when the list structure changes due to drag operations.

99

100

#### onAdd

101

102

Called when an element is added to the list from another list.

103

104

```javascript { .api }

105

/**

106

* Called when element is added from another list

107

* @param evt - Event object with same properties as onEnd

108

*/

109

onAdd?: (evt: SortableEvent) => void;

110

```

111

112

**Usage Examples:**

113

114

```javascript

115

Sortable.create(targetList, {

116

onAdd: (evt) => {

117

console.log('Item added from another list:', evt.item.textContent);

118

console.log('Added at index:', evt.newIndex);

119

120

// Update data model

121

addItemToList(evt.item.dataset.id, evt.newIndex);

122

123

// Animate the new item

124

evt.item.classList.add('newly-added');

125

setTimeout(() => evt.item.classList.remove('newly-added'), 300);

126

}

127

});

128

```

129

130

#### onUpdate

131

132

Called when element order changes within the same list.

133

134

```javascript { .api }

135

/**

136

* Called when list order changes within the same list

137

* @param evt - Event object with same properties as onEnd

138

*/

139

onUpdate?: (evt: SortableEvent) => void;

140

```

141

142

#### onRemove

143

144

Called when an element is removed from the list to another list.

145

146

```javascript { .api }

147

/**

148

* Called when element is removed to another list

149

* @param evt - Event object with same properties as onEnd

150

*/

151

onRemove?: (evt: SortableEvent) => void;

152

```

153

154

#### onSort

155

156

Called for any list change (add, update, or remove).

157

158

```javascript { .api }

159

/**

160

* Called for any change to the list (add/update/remove)

161

* @param evt - Event object with same properties as onEnd

162

*/

163

onSort?: (evt: SortableEvent) => void;

164

```

165

166

**Usage Examples:**

167

168

```javascript

169

Sortable.create(el, {

170

onSort: (evt) => {

171

// This fires for any list change

172

console.log('List changed:', evt.type);

173

174

// Save to localStorage

175

const order = Array.from(evt.to.children)

176

.map(item => item.dataset.id);

177

localStorage.setItem('list-order', JSON.stringify(order));

178

}

179

});

180

```

181

182

### Interaction Events

183

184

Events for handling special interactions and custom drag behavior.

185

186

#### onFilter

187

188

Called when attempting to drag a filtered (non-draggable) element.

189

190

```javascript { .api }

191

/**

192

* Called when trying to drag a filtered element

193

* @param evt - Event object with item property

194

*/

195

onFilter?: (evt: SortableEvent) => void;

196

```

197

198

**Usage Examples:**

199

200

```javascript

201

Sortable.create(el, {

202

filter: '.locked',

203

onFilter: (evt) => {

204

console.log('Cannot drag locked item:', evt.item.textContent);

205

206

// Show user feedback

207

evt.item.classList.add('shake-animation');

208

setTimeout(() => evt.item.classList.remove('shake-animation'), 500);

209

}

210

});

211

```

212

213

#### onMove

214

215

Called when an element moves during dragging, allows controlling insertion behavior.

216

217

```javascript { .api }

218

/**

219

* Called when element moves during drag, can control insertion

220

* @param evt - Event object with movement data

221

* @param originalEvent - Original DOM event

222

* @returns Control insertion: false (cancel), -1 (before), 1 (after), true/void (default)

223

*/

224

onMove?: (evt: SortableEvent, originalEvent: Event) => boolean | number | void;

225

```

226

227

**Usage Examples:**

228

229

```javascript

230

Sortable.create(el, {

231

onMove: (evt, originalEvent) => {

232

// Prevent dropping on certain elements

233

if (evt.related.classList.contains('no-drop')) {

234

return false; // Cancel the move

235

}

236

237

// Custom insertion logic

238

if (evt.related.classList.contains('insert-before')) {

239

return -1; // Force insert before

240

}

241

242

if (evt.related.classList.contains('insert-after')) {

243

return 1; // Force insert after

244

}

245

246

// Allow default behavior

247

return true;

248

}

249

});

250

```

251

252

#### onClone

253

254

Called when an element is cloned (in clone mode).

255

256

```javascript { .api }

257

/**

258

* Called when element is cloned

259

* @param evt - Event object with item (original) and clone properties

260

*/

261

onClone?: (evt: SortableEvent) => void;

262

```

263

264

#### onChange

265

266

Called when the dragging element changes position during drag.

267

268

```javascript { .api }

269

/**

270

* Called when dragging element changes position

271

* @param evt - Event object with newIndex property

272

*/

273

onChange?: (evt: SortableEvent) => void;

274

```

275

276

**Usage Examples:**

277

278

```javascript

279

Sortable.create(el, {

280

onChange: (evt) => {

281

console.log('Element moved to index:', evt.newIndex);

282

283

// Real-time preview of changes

284

updatePreview(evt.newIndex);

285

}

286

});

287

```

288

289

## Event Object Properties

290

291

```javascript { .api }

292

interface SortableEvent {

293

/** Target list element */

294

to: HTMLElement;

295

296

/** Source list element */

297

from: HTMLElement;

298

299

/** The dragged element */

300

item: HTMLElement;

301

302

/** Clone element (when using clone mode) */

303

clone?: HTMLElement;

304

305

/** Element's old index within parent */

306

oldIndex: number;

307

308

/** Element's new index within parent */

309

newIndex: number;

310

311

/** Element's old index within parent, only counting draggable elements */

312

oldDraggableIndex: number;

313

314

/** Element's new index within parent, only counting draggable elements */

315

newDraggableIndex: number;

316

317

/** Pull mode when item is in another sortable: "clone" if cloning, true if moving */

318

pullMode?: string | boolean;

319

320

/** Element on which have guided (onMove event only) */

321

related?: HTMLElement;

322

323

/** DOMRect of related element (onMove event only) */

324

relatedRect?: DOMRect;

325

326

/** DOMRect of dragged element (onMove event only) */

327

draggedRect?: DOMRect;

328

329

/** Whether Sortable will insert drag element after target by default (onMove event only) */

330

willInsertAfter?: boolean;

331

}

332

```

333

334

## Usage Patterns

335

336

### Complete Event Lifecycle

337

338

```javascript

339

Sortable.create(el, {

340

onChoose: (evt) => console.log('1. Item chosen'),

341

onStart: (evt) => console.log('2. Drag started'),

342

onChange: (evt) => console.log('3. Position changed'),

343

onEnd: (evt) => console.log('4. Drag ended'),

344

onAdd: (evt) => console.log('5a. Item added (if from another list)'),

345

onUpdate: (evt) => console.log('5b. Item updated (if same list)'),

346

onRemove: (evt) => console.log('5c. Item removed (if to another list)'),

347

onSort: (evt) => console.log('6. Any sort change occurred')

348

});

349

```

350

351

### Data Persistence

352

353

```javascript

354

Sortable.create(el, {

355

onEnd: (evt) => {

356

// Save to server

357

const newOrder = Array.from(evt.to.children)

358

.map(item => item.dataset.id);

359

360

fetch('/api/save-order', {

361

method: 'POST',

362

headers: { 'Content-Type': 'application/json' },

363

body: JSON.stringify({ order: newOrder })

364

});

365

}

366

});

367

```

368

369

### Cross-List Communication

370

371

```javascript

372

const lists = [el1, el2, el3].map(el =>

373

Sortable.create(el, {

374

group: 'shared',

375

onAdd: (evt) => {

376

console.log(`Item moved to list ${evt.to.id}`);

377

updateListCounters();

378

},

379

onRemove: (evt) => {

380

console.log(`Item left list ${evt.from.id}`);

381

updateListCounters();

382

}

383

})

384

);

385

```