<script language="javascript">
    /* Define the NDSlider class */
    function NDSlider(frames, id, slider_ids, keyMap, dim_vals, notFound, load_json, mpld3, nbagg, cached){
        this.frames = frames;
        this.fig_id = "fig_" + id;
        this.img_id = "_anim_img" + id;
        this.id = id;
        this.slider_ids = slider_ids;
        this.keyMap = keyMap
        this.current_frame = 0;
        this.current_vals = dim_vals;
        this.load_json = load_json;
        this.mpld3 = mpld3;
	this.nbagg = nbagg;
        this.notFound = notFound;
	this.cached = cached;
	this.update();
	if(this.nbagg) {
            this.set_frame(this.current_vals[0], 0);
	}
    }

    NDSlider.prototype.update = function(){
	if(this.current_frame == undefined) {
            $("#" + this.img_id).html(this.notFound);
        } else if(this.load_json) {
            var data_url = "{{ server }}/" + this.fig_id + "/" + this.current_frame;
	    if(this.mpld3) {
                d3.select("#"+this.img_id).selectAll("*").remove();
		$.getJSON(data_url, (function(img_id) {
		    return function(data) {
                        mpld3.draw_figure(img_id, data);
			};
		}(this.img_id)));
	    } else {
                $("#" + this.img_id).load("{{ server }}/" + this.fig_id + "/" + this.current_frame);
            }
	} else {
	    if(this.mpld3) {
                d3.select("#" + this.img_id).selectAll("*").remove();
                mpld3.draw_figure(this.img_id, this.frames[this.current_frame]);
            } else {
                $("#" + this.img_id).html(this.frames[this.current_frame]);
            }
        }
    }

    NDSlider.prototype.set_frame = function(dim_val, dim_idx){
        this.current_vals[dim_idx] = dim_val
        var key = "("
        for (var i=0; i<this.slider_ids.length; i++)
        {
            val = this.current_vals[i];
            if (!(isNaN(val))) {
                if (val % 1 === 0) { var fixed = 1;}
                else { var fixed = 10;}
                val = val.toFixed(fixed)
            }
            key += "'" + val + "'";

            if(i != this.slider_ids.length-1) { key += ', ';}
            else if(this.slider_ids.length == 1) { key += ',';}
        }
        key += ")";
	if(this.cached) {
	    this.current_frame = this.keyMap[key];
            this.update()
	} else {
	    var kernel = IPython.notebook.kernel;
	    if(this.nbagg) {
		function callback(msg) { }
	    } else {
		function callback(msg){
		    /* This callback receives data from Python as a string
		       in order to parse it correctly quotes are sliced off*/
		    var data = msg.content.data['text/plain'].slice(1, -1);
		    if(this.mpld3){
			data = JSON.parse(data);
		    } else {
			data = {0: data};
		    }
		    this.frames = data;
		    this.update()
		}
	    }
	    callbacks = {iopub: {output: $.proxy(callback, this)}};
	    var cmd = "holoviews.ipython.widgets.SelectionWidget.widgets['" + this.id + "'].update(" + this.keyMap[key] + ")";
	    kernel.execute("import holoviews;" + cmd, callbacks, {silent : false});
	}
    }
</script>

<div class="animation row row-fluid" style="display: table; table-layout: fixed; width: 100%; height:50%;">
    <div class="span9 col-xs-9" style="display: table-cell; float:None; vertical-align: middle;">
       	<div style="margin:auto auto; width:80%">
             <div id="_anim_img{{ id }}"></div>
	</div>
    </div>
    <div class="span4 col-xs-3" style="display: table-cell; float:None; width:25%; vertical-align: middle;">
        {% for widget_data in widgets %}
	<div class="control-group" style="{{ widget_data['visibility'] }}">
        {% if widget_data['type'] == 'slider' %}
            <div class="row" style="display: table;">
                <div class="span6 col-xs-6" for="textInput{{ id }}_{{ widget_data['dim'] }}" style="display: table-cell; float:None; vertical-align: middle;">
                    <strong>{{ widget_data['dim'] }}:</strong>
                </div>
                <div class="span6 col-xs-6" style="display: table-cell; float:None; vertical-align: middle;">
                    <input type="text" class="form-control input-medium" id="textInput{{ id }}_{{ widget_data['dim'] }}" value="" disabled>
                </div>
            </div>
	    <div class="row" style="margin-top:7%">
	    	 <div class="span8 offset4 col-xs-8 col-xs-offset-4">
                    <div id="_anim_widget{{ id }}_{{ widget_data['dim'] }}"></div>
                </div>
	    </div>
        </br>
        <script>
			/* Load JQuery UI CSS */
            function loadcssfile(filename){
              var fileref=document.createElement("link")
              fileref.setAttribute("rel", "stylesheet")
              fileref.setAttribute("type", "text/css")
              fileref.setAttribute("href", filename)
              document.getElementsByTagName("head")[0].appendChild(fileref)
            }
            loadcssfile("https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css");
			/* Check if jQuery and jQueryUI have been loaded
               otherwise load with require.js */
            var jQuery = window.jQuery,
                // check for old versions of jQuery
                oldjQuery = jQuery && !!jQuery.fn.jquery.match(/^1\.[0-4](\.|$)/),
                jquery_path = 'https://code.jquery.com/jquery-1.11.1.min',
                paths = {},
                noConflict;
            var jQueryUI = jQuery.ui;
            // check for jQuery
            if (!jQuery || oldjQuery) {
                // load if it's not available or doesn't meet min standards
                paths.jQuery = jQuery;
                noConflict = !!oldjQuery;
            } else {
                // register the current jQuery
                define('jquery', [], function() { return jQuery; });
            }
            if (!jQueryUI) {
                paths.jQueryUI = "{{ jqueryui_url }}"
            } else {
                define('jQueryUI', [], function() { return jQuery.ui; });
            }
            var jquery_require = {paths: paths,
                                  shim: {
                                      "jQueryUI": {
                                          export:"$" ,
                                          deps: ['jquery']
                                      }
                                  }}
            require.config(jquery_require);
            require(["jquery", "jQueryUI"], function(args){
                if (noConflict) $.noConflict(true);
                var valMap{{ id }}_{{ widget_data['dim'] }} = {{ widget_data['vals'] }};
                $('#_anim_widget{{ id }}_{{ widget_data['dim'] }}').slider({
                    animate: "fast",
                    min: 0,
                    max: valMap{{ id }}_{{ widget_data['dim'] }}.length - 1,
                    value: 0,
                    slide: function(event, ui) {
                        var dim_val = valMap{{ id }}_{{ widget_data['dim'] }}[ui.value];
                        $('#textInput{{ id }}_{{ widget_data['dim'] }}').val(dim_val);
                        anim{{ id }}.set_frame(dim_val, {{ widget_data['dim_idx'] }});
                    }
                });
                $('#_anim_widget{{ id }}_{{ widget_data['dim'] }}').keypress(function(event) {
                    if (event.which == 80 || event.which == 112) {
                        var start = $(this).slider("option", "value");
                        var stop =  $(this).slider("option", "max");
                        for (var i=start; i<=stop; i++) {
                            var delay = i*{{ delay }};
                            $.proxy(function doSetTimeout(i) { setTimeout($.proxy(function() {
                                var val = {value:i};
                                $(this).slider('value',i);
                                $(this).slider("option", "slide")(null, val);
                            }, $(this)), delay);
                            }, $(this))(i);
                        }
                    }
                    if (event.which == 82 || event.which == 114) {
                        var start = $(this).slider("option", "value");
                        var stop =  $(this).slider("option", "min");
                        var count = 0;
                        for (var i=start; i>=stop; i--) {
                            var delay = count*{{ delay }};
                            count = count + 1;
                            $.proxy(function doSetTimeout(i) { setTimeout($.proxy(function() {
                                var val = {value:i};
                                $(this).slider('value',i);
                                $(this).slider("option", "slide")(null, val);
                            }, $(this)), delay);
                            }, $(this))(i);
                        }
                    }
                });
                $('#textInput{{ id }}_{{ widget_data['dim'] }}').val(valMap{{ id }}_{{ widget_data['dim'] }}[0]);
            });
        </script>
        {% elif widget_data['type']=='dropdown' %}
        <div class="row" style="display: table;">
            <div class="span6 col-xs-6" style="display: table-cell; float:None; vertical-align: middle;">
                <strong>{{ widget_data['dim'] }}:</strong>
            </div>
            <div class="span6 col-xs-6" style="display: table-cell; float:None; vertical-align: middle;">
                <select name="select-choice-min" id="_anim_widget{{ id }}_{{ widget_data['dim'] }}" >
                </select>
            </div>
        </div>
        </br>
        <script>
            var valMap{{ id }}_{{ widget_data['dim'] }} = {{ widget_data['vals'] }};
            var options = $("#_anim_widget{{ id }}_{{ widget_data['dim'] }}");
            for (var i=0; i<valMap{{ id }}_{{ widget_data['dim'] }}.length; i++)
            {
                options.append($("<option>", {
                    value: i,
                    text:  valMap{{ id }}_{{ widget_data['dim'] }}[i]
            }));
            };

            $('#_anim_widget{{ id }}_{{ widget_data['dim'] }}').on('change', function(event, ui) {
                var dim_val = valMap{{ id }}_{{ widget_data['dim'] }}[this.value];
                if(anim{{ id }}) {
                    anim{{ id }}.set_frame(dim_val, {{ widget_data['dim_idx'] }});
            }
            });
        </script>
        {% endif %}
	</div>
        {% endfor %}
    </div>
</div>


<script language="javascript">
    /* Instantiate the NDSlider class. */
    /* The IDs given should match those used in the template above. */
    (function() {
        var widget_ids = new Array({{ Nwidget }});
        {% for dim in dimensions %}
        widget_ids[{{ loop.index0 }}] = "_anim_widget{{ id }}_{{ dim }}";
        {% endfor %}
        var frame_data = {{ frames | safe }};
        var dim_vals = {{ init_dim_vals }};
        var keyMap = {{ key_data }};
        var notFound = "{{ notFound }}";

    	function create_widget() {
            setTimeout(function() {
	            anim{{ id }} = new NDSlider(frame_data, "{{ id }}", widget_ids,
                        keyMap, dim_vals, notFound, {{ load_json }}, {{ mpld3 }}, {{ nbagg }}, {{ cached }});
	        }, 0);
	    }

	    {% if mpld3 %}
        if(typeof(window.mpld3) !== 'undefined' && window.mpld3._mpld3IsLoaded){
	        create_widget();
        }else {
	        var d3_require = {paths: {"d3" : "{{ d3_url }}"}}
            require.config(d3_require);
            require(["d3"], function(d3){
                window.d3 = d3;
                $.getScript("{{ mpld3_url }}", function(){
	                create_widget();
                });
            });
        }
	    {% else %}
	        create_widget();
	    {% endif %}
    })();
</script>
