{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "37b812f4-16e8-46bd-8e32-96137b28b503"
    }
   },
   "source": [
    "# Extending nbpresent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "02873f97-98e8-43dd-a9e8-10e2780417d1"
    }
   },
   "source": [
    "The nbpresent JavaScript runtime application (both the presenter and the authoring application) is built on:\n",
    "- d3\n",
    "- baobab\n",
    "- the Jupyter notebook!\n",
    "- webfontloader\n",
    "\n",
    "Let's look at what each provides."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "a5bbaf7b-33ee-4c57-9691-38c74c0e3b49"
    }
   },
   "source": [
    "# the Notebook\n",
    "The notebook is a:\n",
    "- source of underlying truth\n",
    "- storage layer (in notebook and cell metadata)\n",
    "- convenient API for common things like keyboard shortcuts"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "84a99d4e-3150-435b-969d-1a616550d510"
    }
   },
   "source": [
    "# [baobab](https://github.com/Yomguithereal/baobab)\n",
    "The data for a presentation is, at runtime, stored in a Baobab **tree**. Baobab lets your UI rendering subscribe to subsets of your data, as well as embed data-only mutations as *monkeys*.\n",
    "\n",
    "> For hacking purposes, you can access the nbpresent tree from `window.global`. However, when writing \"real code\", use `requirejs` and a `Promise`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "console.log(nbpresent.mode.tree.get());\n",
       "require([\"nbextensions/nbpresent/js/nbpresent.min\"], function(nbpresent){\n",
       "    nbpresent.initialized().then(function(nbp){\n",
       "        console.log(nbp.tree.get());\n",
       "    })\n",
       "});"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "console.log(nbpresent.mode.tree.get());\n",
    "require([\"nbextensions/nbpresent/js/nbpresent.min\"], function(nbpresent){\n",
    "    nbpresent.initialized().then(function(nbp){\n",
    "        console.log(nbp.tree.get());\n",
    "    })\n",
    "});"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "99b00717-76ef-4d1a-bf9d-d864a74a3e49"
    }
   },
   "source": [
    "# [d3](https://d3js.org)\n",
    "d3 is what usually moves the actual DOM around on the page, and handles whether new elements should be created, updated or removed."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "5e8652e3-de6c-41b2-9267-0cf60ee7d51c"
    }
   },
   "source": [
    "# hammer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "8e100442-27f7-449f-b4e2-4f7c310cd2e9"
    }
   },
   "source": [
    "## Making a new Theme\n",
    "An easy way to add new content to nbpresent, both the Authoring environment and the presentation itself, is by working with the Baobab tree."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "b36ccfd8-7700-4dea-b276-64166f950a82"
    }
   },
   "source": [
    "#### `app.theme-manager.themes`\n",
    "If defined in the tree, whenever the theme manager shows the **Community Themes**, your theme will be displayed and available for copying into a presentation for modification."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "nbpresent.mode.tree.set(\n",
       "    [\"app\", \"theme-manager\", \"themes\", \"my-theme\"], \n",
       "    {\n",
       "    palette: {\n",
       "        \"my-blue\": {\n",
       "            id: \"my-blue\",\n",
       "            rgb: [0, 0, 255]\n",
       "        },\n",
       "        \"my-black\": {\n",
       "            id: \"my-black\",\n",
       "            rgb: [0, 0, 0]\n",
       "        }\n",
       "    },\n",
       "    backgrounds: {\n",
       "        \"my-background\": {\n",
       "            \"background-color\": \"my-black\"\n",
       "        }\n",
       "    },\n",
       "    \"text-base\": {\n",
       "        \"font-family\": \"Anonymous Pro\",\n",
       "        \"font-size\": 5\n",
       "    },\n",
       "    rules: {\n",
       "        h1: {\n",
       "            \"font-size\": 7,\n",
       "            color: \"my-blue\"\n",
       "        }\n",
       "    }\n",
       "});"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "nbpresent.mode.tree.set(\n",
    "    [\"app\", \"theme-manager\", \"themes\", \"my-theme\"], \n",
    "    {\n",
    "    palette: {\n",
    "        \"my-blue\": {\n",
    "            id: \"my-blue\",\n",
    "            rgb: [0, 0, 255]\n",
    "        },\n",
    "        \"my-black\": {\n",
    "            id: \"my-black\",\n",
    "            rgb: [0, 0, 0]\n",
    "        }\n",
    "    },\n",
    "    backgrounds: {\n",
    "        \"my-background\": {\n",
    "            \"background-color\": \"my-black\"\n",
    "        }\n",
    "    },\n",
    "    \"text-base\": {\n",
    "        \"font-family\": \"Anonymous Pro\",\n",
    "        \"font-size\": 5\n",
    "    },\n",
    "    rules: {\n",
    "        h1: {\n",
    "            \"font-size\": 7,\n",
    "            color: \"my-blue\"\n",
    "        }\n",
    "    }\n",
    "});"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you want to do this at start-up time, you can listen for when nbpresent has initialized, a la `custom.js`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "nbpresent": {
     "id": "97782e6c-59bb-4627-ae49-462394ebd9ef"
    }
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "require([\"nbextensions/nbpresent/js/nbpresent.min\"], function(nbpresent){\n",
       "    nbpresent.initialized().then(function(nbpresent){\n",
       "        // then do your thing\n",
       "    });\n",
       "});"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "require([\"nbextensions/nbpresent/js/nbpresent.min\"], function(nbpresent){\n",
    "    nbpresent.initialized().then(function(nbpresent){\n",
    "        // then do your thing\n",
    "    });\n",
    "});"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or in an nbextension that you plan to `jupyter nbextension enable`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "define([\"nbextensions/nbpresent/js/nbpresent.min\"], function(nbpresent){\n",
       "    return {\n",
       "        load_ipython_extension: function(){\n",
       "            nbpresent.initialized().then(function(nbpresent){\n",
       "                // then do your thing\n",
       "            });\n",
       "        }\n",
       "    }\n",
       "});"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "define([\"nbextensions/nbpresent/js/nbpresent.min\"], function(nbpresent){\n",
    "    return {\n",
    "        load_ipython_extension: function(){\n",
    "            nbpresent.initialized().then(function(nbpresent){\n",
    "                // then do your thing\n",
    "            });\n",
    "        }\n",
    "    }\n",
    "});"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Importing themes from other notebooks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "require([\n",
       "    \"underscore\", \"nbextensions/nbpresent/js/nbpresent.min\"\n",
       "], function(_, nbpresent){\n",
       "    var base = Jupyter.notebook.base_url + \"api/contents\";\n",
       "\n",
       "    $.get(base)\n",
       "        .done(function(contents){\n",
       "            nbpresent.initialized().then(function(nbpresent){\n",
       "                var themes = nbpresent.mode.tree.select([\"app\", \"theme-manager\", \"themes\"]);\n",
       "                \n",
       "                if(!(themes.exists())){\n",
       "                    themes.set({});\n",
       "                }\n",
       "                \n",
       "                _.chain(contents.content)\n",
       "                    .where({type: \"notebook\"})\n",
       "                    .map(function(nb){\n",
       "                        $.get(base + \"/\" + nb.path)\n",
       "                            .done(function(ipynb){\n",
       "                                var md = ipynb.content.metadata.nbpresent;\n",
       "                                md = md && md.themes && md.themes.theme;\n",
       "                                console.log(md);\n",
       "\n",
       "                                md && themes.deepMerge(md);\n",
       "                            })\n",
       "                     });\n",
       "            });\n",
       "        });\n",
       "});"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "require([\n",
    "    \"underscore\", \"nbextensions/nbpresent/js/nbpresent.min\"\n",
    "], function(_, nbpresent){\n",
    "    var base = Jupyter.notebook.base_url + \"api/contents\";\n",
    "\n",
    "    $.get(base)\n",
    "        .done(function(contents){\n",
    "            nbpresent.initialized().then(function(nbpresent){\n",
    "                var themes = nbpresent.mode.tree.select([\"app\", \"theme-manager\", \"themes\"]);\n",
    "                \n",
    "                if(!(themes.exists())){\n",
    "                    themes.set({});\n",
    "                }\n",
    "                \n",
    "                _.chain(contents.content)\n",
    "                    .where({type: \"notebook\"})\n",
    "                    .map(function(nb){\n",
    "                        $.get(base + \"/\" + nb.path)\n",
    "                            .done(function(ipynb){\n",
    "                                var md = ipynb.content.metadata.nbpresent;\n",
    "                                md = md && md.themes && md.themes.theme;\n",
    "                                console.log(md);\n",
    "\n",
    "                                md && themes.deepMerge(md);\n",
    "                            })\n",
    "                     });\n",
    "            });\n",
    "        });\n",
    "});"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  },
  "nbpresent": {
   "slides": {
    "c7833a65-ab7a-49cf-8811-984a14394241": {
     "id": "c7833a65-ab7a-49cf-8811-984a14394241",
     "layout": "grid",
     "prev": null,
     "regions": {
      "aec486a9-528c-4d83-a0a6-fbcd977758ec": {
       "attrs": {
        "height": 0.16666666666666666,
        "pad": 0.01,
        "width": 0.8333333333333334,
        "x": 0.08333333333333333,
        "y": 0.16666666666666666
       },
       "content": {
        "cell": "37b812f4-16e8-46bd-8e32-96137b28b503",
        "part": "source"
       },
       "id": "aec486a9-528c-4d83-a0a6-fbcd977758ec"
      }
     }
    }
   },
   "themes": {
    "default": "5da146d0-eb28-419a-bf8a-1942ff493a00",
    "theme": {}
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
