- Mark as New
- Bookmark Message
- Subscribe to Message
- Mute Message
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hey Splunk Gurus,
I am writing a custom Splunk 6 application using Django bindings. Basically, it's similar to the Music App tutorial.
Anyhow -- I'm loading in a third-party javascript plugin that uses jQuery. It's a jquery data grid called jqgrid
When I try to display a data grid on a template, I get a "Uncaught ReferenceError: jQuery is not defined"
Here is a screenshot: imgur.com/LpWCrTD
Now, my experience tells me jquery isn't loaded when this javascript gets called. I looked at other examples (and plugins) and they seems to works. So what's going on here? When is jquery loaded into page?
Here is my code:
{% extends "splunkdj:base_with_app_bar.html" %}
{% load splunkmvc %}
{% block title %}Edit Profiles{% endblock title %}
{% block css %}
<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}{{app_name}}/custom.css" />
<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}splunkjs/css/dashboard.css" />
<link rel="stylesheet" type="text/css" media="screen" href="{{STATIC_URL}}{{app_name}}/ui-lightness/jquery-ui.css" />
<link rel="stylesheet" type="text/css" media="screen" href="{{STATIC_URL}}{{app_name}}/jqGrid/css/ui.jqgrid.css" />
{% endblock css %}
{% block content %}
<div style="padding: 50px">
<p>Hello World</p>
</div>
{% table id="table_searchresults" managerid="search_resulttable" %}
{% chart id="chart_sourcetype" managerid="search_chart" type="pie" %}
{% endblock content%}
{% block managers %}
{% searchmanager
id="search_resulttable"
search="index=_internal sourcetype=splunkd | head 3"
cache=True
%}
{% searchmanager
id="search_chart"
search="index=_internal | head 1000 | stats count by sourcetype"
cache=True
%}
{% endblock managers %}
{% block js %}
<script src="{{STATIC_URL}}{{app_name}}/jqGrid/js/i18n/grid.locale-en.js" type="text/javascript"></script>
<script src="{{STATIC_URL}}{{app_name}}/jqGrid/js/jquery.jqGrid.src.js" type="text/javascript"></script>
{% endblock js %}
- Mark as New
- Bookmark Message
- Subscribe to Message
- Mute Message
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Good question, and the answer is a bit subtle.
We load very few of our JS dependencies using script tags, mostly because it
quickly becomes problematic to work out all the dependencies, especially as we
don't know what components you're going to load on a page.
Given that, we use require.js
(http://requirejs.org/) to do our dependency
management and loading. That's why you see all these instances in the examples
of doing things like:
require(['splunkjs/mvc/chartview'], function(ChartView) { ... });
However, this makes things a bit interesting in your case, where you want to
load something that depends on jQuery (jqgrid, in your case). The reason you're
getting the error is that when your <script>
tags get executed, jQuery hasn't
loaded yet, because it hasn't finished being required. As such, when jqgrid tries
to reference the jQuery
global variable, it can't.
So what's the solution? There are a couple of options:
You can use
require.js
to load jqgrid. This would probably mean doing a
require.config
call in your page to define the paths (and possibly the shim
definitions). This might look like this:require.config({ paths: { "jqgrid.locale": "{{STATIC_URL}}{{app_name}}/jqGrid/js/i18n/grid.locale-en.js", "jqgrid": "{{STATIC_URL}}{{app_name}}/jqGrid/js/jquery.jqGrid.src.js" }, shim: { "jqgrid.locale": { deps: ["jquery"] }, "jqgrid": { deps: ["jquery", "grid.locale"], exports: "jQuery.fn.jqGrid" } } }); require(["jqgrid"], function(jqgrid) { // ... });
I don't know that the above code is 100% correct, but it's a rough estimation
of what this might look like in arequire
-ified way.One interesting note is that you are going to be dependent on the JS Stack's
versionAnother option might be to include your own version of jQuery, and then when
the rest of your dependencies are loaded, you can callnoConflict()
on it. This
might look like:<script src="{{STATIC_URL}}{{app_name}}/jquery.js" type="text/javascript"></script> <script src="{{STATIC_URL}}{{app_name}}/jqGrid/js/i18n/grid.locale-en.js" type="text/javascript"></script> <script src="{{STATIC_URL}}{{app_name}}/jqGrid/js/jquery.jqGrid.src.js" type="text/javascript"></script> <script> jQuery.noConflict(); </script>
That way, you know you can always rely on your version of jQuery, and also that
only the jqgrid code will have access to that jQuery reference.
Hopefully the above options make sense. Let me know if I can expand or explain
something further. Also, we always love to hear what people are building, so
feel free to share 🙂
- Mark as New
- Bookmark Message
- Subscribe to Message
- Mute Message
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I actually solved this in a very hacky way. Basically I wait until splunk is ready, then I use a jquery getScript() to pull in the external scripts.
Now, if you look closely you'll notice they are nested. This is because there's AJAX taking place, and I need to wait for everything to come back before I can start using it. Nesting the functions() solves this.
Although it works, this is definitely not the best approach. Requirejs (like ineeman mentioned above) seems a lot cleaner.
<script>
require(["splunkjs/ready!"], function(mvc) {
//get the scripts using jquery
$.getScript( "/dj/static/josh_app/jqGrid/js/i18n/grid.locale-en.js", function( data, textStatus, jqxhr ) {
console.log( "grid.locale-en.js load was performed." );
$.getScript( "/dj/static/josh_app/jqGrid/js/jquery.jqGrid.min.js", function( data, textStatus, jqxhr ) {
console.log( "jquery.jqGrid.min.js load was performed." );
console.log("about to access the grid");
//the rest of this is all jqGrid stuff
jQuery("#list2").jqGrid({
url:'http://172.16.127.128:8000/dj/en-us/josh_app/ajax-request',
datatype: "json",
colNames:['ID','User', 'Date', 'Profile Name','Low Warn','Low Error','High Warn','High Error'],
colModel:[
{name:'id',index:'id'},
{name:'userid',index:'userid'},
{name:'date',index:'date'},
{name:'profile_name',index:'profile_name'},
{name:'low_warn',index:'low_warn'},
{name:'low_error',index:'low_error'},
{name:'high_warn',index:'high_warn'},
{name:'high_error',index:'high_error'}
],
rowNum:10,
rowList:[10,25,50],
pager: '#pager2',
sortname: 'id',
viewrecords: true,
sortorder: "desc",
caption:"Threshold Profiles"
});
jQuery("#list2").jqGrid('navGrid','#pager2',{edit:false,add:false,del:false});
});
});
});
</script>
- Mark as New
- Bookmark Message
- Subscribe to Message
- Mute Message
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

This is not necessarily hacky. A different way to do the above is just to use nested require calls.
So it might look something like:
require(["jquery"], function() {
require(["/path/to/grid.locale.js"], function() {
require(["/path/to/jqgrid.js"], function() {
// Use $.grid here
});
});
})
That's not a super uncommon require-approach for non-AMD scripts.
- Mark as New
- Bookmark Message
- Subscribe to Message
- Mute Message
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Good question, and the answer is a bit subtle.
We load very few of our JS dependencies using script tags, mostly because it
quickly becomes problematic to work out all the dependencies, especially as we
don't know what components you're going to load on a page.
Given that, we use require.js
(http://requirejs.org/) to do our dependency
management and loading. That's why you see all these instances in the examples
of doing things like:
require(['splunkjs/mvc/chartview'], function(ChartView) { ... });
However, this makes things a bit interesting in your case, where you want to
load something that depends on jQuery (jqgrid, in your case). The reason you're
getting the error is that when your <script>
tags get executed, jQuery hasn't
loaded yet, because it hasn't finished being required. As such, when jqgrid tries
to reference the jQuery
global variable, it can't.
So what's the solution? There are a couple of options:
You can use
require.js
to load jqgrid. This would probably mean doing a
require.config
call in your page to define the paths (and possibly the shim
definitions). This might look like this:require.config({ paths: { "jqgrid.locale": "{{STATIC_URL}}{{app_name}}/jqGrid/js/i18n/grid.locale-en.js", "jqgrid": "{{STATIC_URL}}{{app_name}}/jqGrid/js/jquery.jqGrid.src.js" }, shim: { "jqgrid.locale": { deps: ["jquery"] }, "jqgrid": { deps: ["jquery", "grid.locale"], exports: "jQuery.fn.jqGrid" } } }); require(["jqgrid"], function(jqgrid) { // ... });
I don't know that the above code is 100% correct, but it's a rough estimation
of what this might look like in arequire
-ified way.One interesting note is that you are going to be dependent on the JS Stack's
versionAnother option might be to include your own version of jQuery, and then when
the rest of your dependencies are loaded, you can callnoConflict()
on it. This
might look like:<script src="{{STATIC_URL}}{{app_name}}/jquery.js" type="text/javascript"></script> <script src="{{STATIC_URL}}{{app_name}}/jqGrid/js/i18n/grid.locale-en.js" type="text/javascript"></script> <script src="{{STATIC_URL}}{{app_name}}/jqGrid/js/jquery.jqGrid.src.js" type="text/javascript"></script> <script> jQuery.noConflict(); </script>
That way, you know you can always rely on your version of jQuery, and also that
only the jqgrid code will have access to that jQuery reference.
Hopefully the above options make sense. Let me know if I can expand or explain
something further. Also, we always love to hear what people are building, so
feel free to share 🙂
- Mark as New
- Bookmark Message
- Subscribe to Message
- Mute Message
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

Awesome, really looking forward to seeing it.
- Mark as New
- Bookmark Message
- Subscribe to Message
- Mute Message
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Good call on the requirejs. I knew splunk was using it, but I didn't quite understand the syntax.
I'm building a sweet-sweet data gird (with a SQLite backedn) just like -> http://trirand.com/blog/jqgrid/jqgrid.html
I'll write up a blog post once it's done.
