<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 All About DataTables
Display tabular data.
Built on slickgrid.
Sortable, filterable.
Step1:  Sample Application
Step2:  Simple DataTable
Sortable
Scrollable
Step4:  Add Filtering
Add two filter widgets.
Use CustomJS to alter the displayed data.
Step5:  Links
<ASSISTANT_TASK:>
Python Code:
from bokeh.io import output_file
output_file('/tmp/bokeh_notebook.html')
Explanation: All About DataTables
Display tabular data.
Built on slickgrid.
Sortable, filterable.
End of explanation
from pandas_datareader import wb
indicators_df = wb.get_indicators()
indicators_df['sourceOrganization'] = indicators_df['sourceOrganization'].str.decode("utf-8") 
indicators_df.head()
Explanation: Sample Application: World Bank data explorer
Use pandas-datareader to access World Bank data.
End of explanation
from bokeh.io import show, vform
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.layouts import HBox
from bokeh.models.widgets import DataTable, TableColumn, StringFormatter, DateFormatter, Select
import pandas as pd
table_columns = [
    TableColumn(field='id', title='ID'),
    TableColumn(field='name', title='Name'),
    TableColumn(field='source', title='Source'),
    TableColumn(field='sourceNote', title='Source Note'),
    TableColumn(field='sourceOrganization', title='Source Organization'),
    TableColumn(field='topics', title='Topics'),
]
column_names = [tc.field for tc in table_columns]
table_source = ColumnDataSource(indicators_df[column_names])
data_table = DataTable(source=table_source, columns=table_columns, height=400, editable=False)
show(vform(data_table))
Explanation: Simple DataTable
Sortable
Scrollable
End of explanation
# two widgets
source_list = ['ALL'] + sorted(indicators_df['source'].unique().tolist())
source_select = Select(title="Source:", value=source_list[0], options=source_list)
topic_list = ['ALL'] + sorted(set([topic.strip() for topics in indicators_df['topics'].unique().tolist() 
                                                 for topic in topics.split(';') if topic.strip()]))
topic_select = Select(title="Topic:", value=topic_list[0], options=topic_list)
# make a copy of the original data - "immutable"
original_table_source = ColumnDataSource(indicators_df[column_names])
arg_dct = dict(
    source=table_source,
    original_source=original_table_source,
    source_select=source_select,
    topic_select=topic_select,
    target_obj=data_table
)
# filtering done in JS
callback_code = 
    var data = source.get('data');
    var original_data = original_source.get('data');
    var source_name = source_select.get('value');
    var topic_name = topic_select.get('value');
    
    // now construct the new data object based on the filtered values
    for (var key in original_data) {
        data[key] = [];
        for (var i = 0; i < original_data["id"].length; ++i) {
            if ((source_name === "ALL" || original_data["source"][i] === source_name) &&
                (topic_name === "ALL" || original_data["topics"][i].indexOf(topic_name) > -1)) {
                data[key].push(original_data[key][i]);
            }
        }
    }
    target_obj.trigger('change');
    source.trigger('change');
generic_callback = CustomJS(args=arg_dct, code=callback_code)
source_select.callback = generic_callback
topic_select.callback = generic_callback
filter_widgets = HBox(children=[source_select, topic_select])
show(vform(filter_widgets, data_table))
Explanation: Add Filtering
Add two filter widgets.
Use CustomJS to alter the displayed data.
End of explanation
from bokeh.models.widgets.tables import HTMLTemplateFormatter
try:
    from urllib import quote
except ImportError as e:
    from urllib.parse import quote
name_template_str = '<a target="_blank" href="<%= url %>"><%= value %></a>'
table_columns = [
    TableColumn(field='id', title='ID'),
    TableColumn(field='name', title='Name', formatter=HTMLTemplateFormatter(template=name_template_str)),
    TableColumn(field='source', title='Source'),
    TableColumn(field='sourceNote', title='Source Note'),
    TableColumn(field='sourceOrganization', title='Source Organization'),
    TableColumn(field='topics', title='Topics'),
]
column_names = [tc.field for tc in table_columns]
df = indicators_df.copy()
df['url'] = df['name'].apply(lambda s: 'http://search.worldbank.org/all?qterm={term}&language=EN'.format(term=quote(s)))
table_source = ColumnDataSource(df)
data_table = DataTable(source=table_source, columns=table_columns, height=400, editable=False)
show(vform(data_table))
Explanation: Links
End of explanation
<END_TASK>