<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Widget Events
In this lecture we will discuss widget events, such as button clicks!
Special events
Step1:  The Button is not used to represent a data type.  Instead the button widget is used to handle mouse clicks.  The on_click method of the Button can be used to register function to be called when the button is clicked.  The doc string of the on_click can be seen below.
Step2:  Example
Since button clicks are stateless, they are transmitted from the front-end to the back-end using custom messages.  By using the on_click method, a button that prints a message when it has been clicked is shown below.
Step3:  on_submit
The Text widget also has a special on_submit event.  The on_submit event fires when the user hits return.
Step4:  Traitlet events
Widget properties are IPython traitlets and traitlets are eventful.  To handle  changes, the on_trait_change method of the widget can be used to register a callback.  The doc string for on_trait_change can be seen below.
Step5:  Signatures
Mentioned in the doc string, the callback registered can have 4 possible signatures
Step6:  Linking Widgets
Often, you may want to simply link widget attributes together. Synchronization of attributes can be done in a simpler way than by using bare traitlets events. 
Linking traitlets attributes from the server side
The first method is to use the link and dlink functions from the traitlets module.
Step7:  Function traitlets.link and traitlets.dlink return a Link or DLink object. The link can be broken by calling the unlink method.
Step8:  Linking widgets attributes from the client side
When synchronizing traitlets attributes, you may experience a lag because of the latency due to the roundtrip to the server side. You can also directly link widget attributes in the browser using the link widgets, in either a unidirectional or a bidirectional fashion.
Step9:  Function widgets.jslink returns a Link widget. The link can be broken by calling the unlink method.
<ASSISTANT_TASK:>
Python Code:
from __future__ import print_function
Explanation: Widget Events
In this lecture we will discuss widget events, such as button clicks!
Special events
End of explanation
import ipywidgets as widgets
print(widgets.Button.on_click.__doc__)
Explanation: The Button is not used to represent a data type.  Instead the button widget is used to handle mouse clicks.  The on_click method of the Button can be used to register function to be called when the button is clicked.  The doc string of the on_click can be seen below.
End of explanation
from IPython.display import display
button = widgets.Button(description="Click Me!")
display(button)
def on_button_clicked(b):
    print("Button clicked.")
button.on_click(on_button_clicked)
Explanation: Example
Since button clicks are stateless, they are transmitted from the front-end to the back-end using custom messages.  By using the on_click method, a button that prints a message when it has been clicked is shown below.
End of explanation
text = widgets.Text()
display(text)
def handle_submit(sender):
    print(text.value)
text.on_submit(handle_submit)
Explanation: on_submit
The Text widget also has a special on_submit event.  The on_submit event fires when the user hits return.
End of explanation
print(widgets.Widget.on_trait_change.__doc__)
Explanation: Traitlet events
Widget properties are IPython traitlets and traitlets are eventful.  To handle  changes, the on_trait_change method of the widget can be used to register a callback.  The doc string for on_trait_change can be seen below.
End of explanation
int_range = widgets.IntSlider()
display(int_range)
def on_value_change(name, value):
    print(value)
int_range.on_trait_change(on_value_change, 'value')
Explanation: Signatures
Mentioned in the doc string, the callback registered can have 4 possible signatures:
callback()
callback(trait_name)
callback(trait_name, new_value)
callback(trait_name, old_value, new_value)
Using this method, an example of how to output an IntSlider's value as it is changed can be seen below.
End of explanation
import traitlets
# Create Caption
caption = widgets.Latex(value = 'The values of slider1 and slider2 are synchronized')
# Create IntSlider
slider1 = widgets.IntSlider(description='Slider 1')
slider2 =  widgets.IntSlider(description='Slider 2')
# Use trailets to link
l = traitlets.link((slider1, 'value'), (slider2, 'value'))
# Display!
display(caption, slider1, slider2)
# Create Caption
caption = widgets.Latex(value = 'Changes in source values are reflected in target1')
# Create Sliders
source = widgets.IntSlider(description='Source')
target1 = widgets.IntSlider(description='Target 1')
# Use dlink
dl = traitlets.dlink((source, 'value'), (target1, 'value'))
display(caption, source, target1)
Explanation: Linking Widgets
Often, you may want to simply link widget attributes together. Synchronization of attributes can be done in a simpler way than by using bare traitlets events. 
Linking traitlets attributes from the server side
The first method is to use the link and dlink functions from the traitlets module.
End of explanation
# May get an error depending on order of cells being run!
l.unlink()
dl.unlink()
Explanation: Function traitlets.link and traitlets.dlink return a Link or DLink object. The link can be broken by calling the unlink method.
End of explanation
# NO LAG VERSION
caption = widgets.Latex(value = 'The values of range1 and range2 are synchronized')
range1 = widgets.IntSlider(description='Range 1')
range2 =  widgets.IntSlider(description='Range 2')
l = widgets.jslink((range1, 'value'), (range2, 'value'))
display(caption, range1, range2)
# NO LAG VERSION
caption = widgets.Latex(value = 'Changes in source_range values are reflected in target_range1')
source_range = widgets.IntSlider(description='Source range')
target_range1 = widgets.IntSlider(description='Target range ')
dl = widgets.jsdlink((source_range, 'value'), (target_range1, 'value'))
display(caption, source_range, target_range1)
Explanation: Linking widgets attributes from the client side
When synchronizing traitlets attributes, you may experience a lag because of the latency due to the roundtrip to the server side. You can also directly link widget attributes in the browser using the link widgets, in either a unidirectional or a bidirectional fashion.
End of explanation
l.unlink()
dl.unlink()
Explanation: Function widgets.jslink returns a Link widget. The link can be broken by calling the unlink method.
End of explanation
<END_TASK>