Repository: bokeh/bokeh

Issue:
unicode `__javascript__` external resources breaks output notebook in python 2
Defining `__javascript__` using a list of unicode strings, causes a Javascript error upon calling `output_notebook`:

```
from __future__ import unicode_literals, print_function
import sys
print(sys.version)

from bokeh.models import Model
from bokeh.io import output_notebook

class TestCustom(Model):
    __javascript__ = ["https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js",
                      "https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.4/js/ion.rangeSlider.js"]

    __implementation__ = """
    p = require "core/properties"
    BokehModel = require "model"

    class TestCustom extends BokehModel
        type: "TestCustom"

    module.exports = 
        Model: TestCustom
    
    """

output_notebook()
```

The cell output is:
```
2.7.12 |Anaconda 4.2.0 (x86_64)| (default, Jul  2 2016, 17:43:17) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)]
Loading BokehJS ...
Javascript error adding output!
SyntaxError: Unexpected string
See your browser Javascript console for more details.
```

And the console error message is:
```
SyntaxError: Unexpected string
    at OutputArea.append_javascript (outputarea.js:625)
    at OutputArea.append_mime_type (outputarea.js:569)
    at OutputArea.append_display_data (outputarea.js:533)
    at OutputArea.append_output (outputarea.js:319)
    at OutputArea.handle_output (outputarea.js:233)
    at output (codecell.js:356)
    at Kernel._handle_output_message (kernel.js:1060)
    at i (jquery.min.js:4)
    at Kernel._handle_iopub_message (kernel.js:1087)
    at Kernel._finish_ws_message (kernel.js:924)
```

* The Javascript error goes away using a byte string `b"https://cdnjs.cloudflare.com..."`, but then the same error pops up in Python 3.
* The error only happens with `__javascript__` not `__css__`.

Bokeh version: 0.12.3
Jupyter version: 1.0.0
Notebook version: 4.2.3


Discussion:
@nathanielatom my guess is that this is not related to the notebook, can you confirm (or disconfirm) that it also happens from simple scripts?
Interestingly it does not. I was unable to use `show` directly with the above sample code, so I had to make a slightly beefier example:

```
from __future__ import unicode_literals, print_function
import sys
print(sys.version)

from bokeh.models import LayoutDOM
from bokeh.io import output_file, show
from bokeh.layouts import layout

class TestCustom(LayoutDOM):
    __javascript__ = ["https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js",
                      "https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.4/js/ion.rangeSlider.js"]

    __implementation__ = """
    p = require "core/properties"
    LayoutDOM = require "models/layouts/layout_dom"

    class TestCustomView extends LayoutDOM.View
        prop: "Test"

    class TestCustom extends LayoutDOM.Model
        type: "TestCustom"
        default_view: TestCustomView

    module.exports = 
        Model: TestCustom
    
    """

output_file("test.html")
show(layout([[TestCustom()]]))
```

The above results in no javascript errors when run as a script, but when `output_file` is changed to `output_notebook`, results in the following:

```
SyntaxError: Unexpected string
    at OutputArea.append_javascript (main.min.js:20450)
    at OutputArea.append_mime_type (main.min.js:20394)
    at OutputArea.append_display_data (main.min.js:20358)
    at OutputArea.append_output (main.min.js:20144)
    at OutputArea.fromJSON (main.min.js:20712)
    at CodeCell.fromJSON (main.min.js:21864)
    at Notebook.fromJSON (main.min.js:27327)
    at Notebook.load_notebook_success (main.min.js:27696)
    at i (main.min.js:87)
main.min.js:20240 
SyntaxError: Unexpected string
    at eval (<anonymous>)
    at Function.globalEval (main.min.js:87)
    at init.domManip (main.min.js:88)
    at init.append (main.min.js:88)
    at OutputArea._safe_append (main.min.js:20238)
    at OutputArea.append_display_data (main.min.js:20359)
    at OutputArea.append_output (main.min.js:20144)
    at OutputArea.fromJSON (main.min.js:20712)
    at CodeCell.fromJSON (main.min.js:21864)
    at Notebook.fromJSON (main.min.js:27327)
```

It looks like calling `show` causes an additional error.

Well, that's surprising to me, but good to know. We are in the midst of trying to find more robust mechanisms for extension handling in general, due to some other issues that have cropped up. A fix for this might fall out of that work (but possibly not).

ping @mattpap just to be aware 

Resolving patch:
diff --git a/bokeh/core/templates.py b/bokeh/core/templates.py
--- a/bokeh/core/templates.py
+++ b/bokeh/core/templates.py
@@ -16,9 +16,12 @@
 '''
 from __future__ import absolute_import
 
-from jinja2 import Environment, PackageLoader
+import json
+
+from jinja2 import Environment, PackageLoader, Markup
 
 _env = Environment(loader=PackageLoader('bokeh.core', '_templates'))
+_env.filters['json'] = lambda obj: Markup(json.dumps(obj))
 
 JS_RESOURCES = _env.get_template("js_resources.html")
 CSS_RESOURCES = _env.get_template("css_resources.html")
diff --git a/bokeh/util/notebook.py b/bokeh/util/notebook.py
--- a/bokeh/util/notebook.py
+++ b/bokeh/util/notebook.py
@@ -81,7 +81,7 @@ def _load_notebook_html(resources=None, verbose=False, hide_banner=False,
         css_urls = resources.css_files,
         js_raw   = resources.js_raw + ([] if hide_banner else [FINALIZE_JS % element_id]),
         css_raw  = resources.css_raw_str,
-        force    = 1,
+        force    = True,
         timeout  = load_timeout
     )
 


Test patch: