Introduction

Installation

Limitations of the "file" protocol

Frequently asked questions

Syntax, keywords and built-in functions

Standard distribution

import implementation

Brython packages

Browser interface

Introduction - DOM API
Creating a document
Accessing elements
Attributes, properties and methods

Events
Mouse events
Keyboard events
Focus events
Drag events

Query string

Interactions with Javascript

Brython-specific built-in modules

browser
browser.aio
browser.ajax
browser.html
browser.local_storage
browser.markdown
browser.object_storage
browser.session_storage
browser.svg
browser.template
browser.timer
browser.webcomponent
browser.websocket
browser.worker

Widgets
browser.widgets.dialog
browser.widgets.menu

interpreter
javascript

Working with Brython

Execution options
Testing and debugging
Deploying an application

Cookbook

Hello world !
Insert content in an element
HTML markup (bold,italic...)
HTML table
Bind and unbind events
Handle options in a SELECT
Drag and drop
Get the content of an element
Read the content of a file
Store objects locally
Example of onmouseover
 

Problem

Drag and drop an element on the web page

Solution

Brython implements an API based on HTML5 drag and drop specification. In the basic form presented in this example, it consists in defining callback functions for 3 events :

  • dragstart on the draggable element (when the user starts dragging it)
  • dragover on the destination zone (when the draggable element is moved over it)
  • drop on the destination zone (when the user releases the mouse button)

To attach the function callback to an event on an element, we use the method element.bind(event,callback)

The callback functions take a single argument, an instance of DOMEvent. To communicate information during the drag and drop operation, the event has an attribute data that receives a value in the callback associated to dragstart ; this value is used in the callback associated with drop to identify the element that is being dropped.

In the example, when the draggable object has been dropped, it can't be dragged any more ; for this, we remove the bindings attached to an event on this object using the method element.unbind(event)

destination zone
draggable object

from browser import document

panel = document["panel"] # yellow zone

source = document["source"] # red zone
# place it at (10, 10) from panel top left corner
source.style.top = "{}px".format(10 + panel.abs_top)
source.style.left = "{}px".format(10 + panel.abs_left)
# make red zone draggable
source.draggable = True

dest = document["dest"] # green zone
# place it at (10, 150) from panel top left corner
dest.style.top = "{}px".format(10 + panel.abs_top)
dest.style.left = "{}px".format(150 + panel.abs_left)

# offset of mouse relatively to dragged object when dragging starts
m0 = [None, None]

def mouseover(ev):
    """When mouse is over the draggable element, change cursor."""
    print('mouse over ! ')
    ev.target.style.cursor = "pointer"

source.bind("mouseover", mouseover)

def dragstart(ev):
    """Function called when the user starts dragging the object."""
    global m0
    # compute mouse offset
    # ev.x and ev.y are the coordinates of the mouse when the event is fired
    # ev.target is the dragged element. Its attributes "left" and "top" are
    # integers, the distance from the left and top borders of the document
    m0 = [ev.x - ev.target.left, ev.y - ev.target.top]
    # associate data to the dragging process
    ev.dataTransfer.setData("text", ev.target.id)
    # allow dragged object to be moved
    ev.dataTransfer.effectAllowed = "move"

source.bind("dragstart", dragstart)

def dragover(ev):
    """Function called when the draggable object comes over the destination
    zone.
    """
    ev.dataTransfer.dropEffect = "move"
    # here we must prevent the default behaviour for this kind of event
    ev.preventDefault()

dest.bind("dragover", dragover)

def drop(ev):
    """Function attached to the destination zone.
    Describes what happens when the object is dropped, ie when the mouse is
    released while the object is over the zone.
    """
    # retrieve data stored in drag_start (the draggable element's id)
    src_id = ev.dataTransfer.getData('text')
    elt = document[src_id]
    # set the new coordinates of the dragged object
    elt.style.left = "{}px".format(ev.x - m0[0])
    elt.style.top = "{}px".format(ev.y - m0[1])
    # don't drag the object any more
    elt.draggable = False
    # remove the callback function
    elt.unbind("mouseover")
    elt.style.cursor = "auto"
    ev.preventDefault()

dest.bind("drop", drop)