Holoview chart won't appear in Django site - django

i know there is probably something simple i am doing wrong, but i don't know where else to get an answer. I created a django site and the following function returns holoview html:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from charts.models import Ord
from IPython.display import display_html
import pandas as pd
import holoviews as hv
hv.extension('bokeh')
renderer = hv.renderer('bokeh')
# Create your views here.
def displayChart(request):
df = pd.DataFrame(list(Ord.objects.using('DB').all().values('ordtyp')[:500]))
df = df.groupby([df.ordtyp]).size().reset_index(name='counts')
bars = hv.Bars(df, kdims=[('ordtyp', 'Order Type')], vdims=[('counts', 'Count of Orders')])
hv.Store.registry['bokeh'][hv.Bars]
html = renderer.html(bars)
return render(request, 'charts/charts.html', {'html': html})
i put a block in the charts.html file as:
{{ html |safe }}
and all i get is a blank page. i then took the raw html that the renderer is returning and tried to copy and paste it directly into my html file, and got the same thing. the html is below. Also, the chart does work in Jupyter Notebook... can you tell me what i am doing wrong?
charts.html:
> <!DOCTYPE html>
> <html>
> <head>
> <title>Charts</title>
> </head>
> <body>
> {{html|safe}}
> </body>
> </html>
raw html that the renderer returned:
<div style='display: table; margin: 0 auto;'>
<div class="bk-root">
<div class="bk-plotdiv" id="0dd69ef6-4d30-48f5-a95a-1201437920de"></div>
</div>
<script type="text/javascript">
(function(root) {
function now() {
return new Date();
}
var force = false;
if (typeof (root._bokeh_onload_callbacks) === "undefined" || force === true) {
root._bokeh_onload_callbacks = [];
root._bokeh_is_loading = undefined;
}
if (typeof (root._bokeh_timeout) === "undefined" || force === true) {
root._bokeh_timeout = Date.now() + 0;
root._bokeh_failed_load = false;
}
var NB_LOAD_WARNING = {'data': {'text/html':
"<div style='background-color: #fdd'>\n"+
"<p>\n"+
"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \n"+
"may be due to a slow or bad network connection. Possible fixes:\n"+
"</p>\n"+
"<ul>\n"+
"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\n"+
"<li>use INLINE resources instead, as so:</li>\n"+
"</ul>\n"+
"<code>\n"+
"from bokeh.resources import INLINE\n"+
"output_notebook(resources=INLINE)\n"+
"</code>\n"+
"</div>"}};
function display_loaded() {
if (root.Bokeh !== undefined) {
var el = document.getElementById("0dd69ef6-4d30-48f5-a95a-1201437920de");
if (el != null) {
el.textContent = "BokehJS " + Bokeh.version + " successfully loaded.";
}
} else if (Date.now() < root._bokeh_timeout) {
setTimeout(display_loaded, 100)
}
}
function run_callbacks() {
try {
root._bokeh_onload_callbacks.forEach(function(callback) { callback() });
}
finally {
delete root._bokeh_onload_callbacks
}
console.info("Bokeh: all callbacks have finished");
}
function load_libs(js_urls, callback) {
root._bokeh_onload_callbacks.push(callback);
if (root._bokeh_is_loading > 0) {
console.log("Bokeh: BokehJS is being loaded, scheduling callback at", now());
return null;
}
if (js_urls == null || js_urls.length === 0) {
run_callbacks();
return null;
}
console.log("Bokeh: BokehJS not loaded, scheduling load and callback at", now());
root._bokeh_is_loading = js_urls.length;
for (var i = 0; i < js_urls.length; i++) {
var url = js_urls[i];
var s = document.createElement('script');
s.src = url;
s.async = false;
s.onreadystatechange = s.onload = function() {
root._bokeh_is_loading--;
if (root._bokeh_is_loading === 0) {
console.log("Bokeh: all BokehJS libraries loaded");
run_callbacks()
}
};
s.onerror = function() {
console.warn("failed to load library " + url);
};
console.log("Bokeh: injecting script tag for BokehJS library: ", url);
document.getElementsByTagName("head")[0].appendChild(s);
}
};var element = document.getElementById("0dd69ef6-4d30-48f5-a95a-1201437920de");
if (element == null) {
console.log("Bokeh: ERROR: autoload.js configured with elementid '0dd69ef6-4d30-48f5-a95a-1201437920de' but no matching script tag was found. ")
return false;
}
var js_urls = [];
var inline_js = [
function(Bokeh) {
(function() {
var fn = function() {
var docs_json = {"c7d02456-4a61-46d2-8431-34face1e6c67":{"roots":{"references":[{"attributes":{"callback":null,"column_names":["ORDTYP","counts"],"data":{"ORDTYP":["CC","CD","CZ","DB","DR","ED","EI","IC","ID","IP","MC","MF","MI","MK","MP","MS","MX","PC","PM","PT","SD","TI","TX","ZLR"],"counts":[60,3,2,17,1,13,2,28,21,1,3,6,1,2,2,35,10,20,12,2,525,7,225,1]}},"id":"46c2f30a-31d4-4c3f-ade2-4de96e13a4db","type":"ColumnDataSource"},{"attributes":{"active_drag":"auto","active_inspect":"auto","active_scroll":"auto","active_tap":"auto","tools":[{"id":"16eb22e8-c448-49d7-ab20-a02f2ebb3e5c","type":"SaveTool"},{"id":"218dbf74-8190-491c-b2dc-d13097c1f9e4","type":"PanTool"},{"id":"03f67199-1622-4784-b9a2-b36b4a47477b","type":"WheelZoomTool"},{"id":"d48948b1-297b-4915-bf84-916a417b01ee","type":"BoxZoomTool"},{"id":"722ae387-76c5-48cb-a387-7090de91b014","type":"ResetTool"}]},"id":"8ce67c3d-e8dc-41a2-86a8-76685fb90fe9","type":"Toolbar"},{"attributes":{"callback":null,"end":525,"start":0},"id":"16f5dfe6-08a6-4ad8-a190-bdf67979b26c","type":"DataRange1d"},{"attributes":{},"id":"bfe7ff64-0995-43a7-8944-6d491bf93b14","type":"CategoricalTicker"},{"attributes":{"callback":null,"factors":["CC","CD","CZ","DB","DR","ED","EI","IC","ID","IP","MC","MF","MI","MK","MP","MS","MX","PC","PM","PT","SD","TI","TX","ZLR"]},"id":"36f2f454-71a9-4511-a446-2c56a015ecd0","type":"FactorRange"},{"attributes":{"axis_label":"Count of Orders","formatter":{"id":"7303c9ca-b3e1-40be-bd44-1ef7f06d8a2d","type":"BasicTickFormatter"},"plot":{"id":"c84e964a-0b0b-4d95-aa2c-3657b7811bd0","subtype":"Figure","type":"Plot"},"ticker":{"id":"95b801e5-1f32-4ff1-be0c-e64ddcb14fa3","type":"BasicTicker"}},"id":"bd1e5045-1d72-4e92-8914-13be1ee0d04f","type":"LinearAxis"},{"attributes":{},"id":"95b801e5-1f32-4ff1-be0c-e64ddcb14fa3","type":"BasicTicker"},{"attributes":{"grid_line_color":{"value":null},"plot":{"id":"c84e964a-0b0b-4d95-aa2c-3657b7811bd0","subtype":"Figure","type":"Plot"},"ticker":{"id":"bfe7ff64-0995-43a7-8944-6d491bf93b14","type":"CategoricalTicker"}},"id":"0dee56d3-b965-4d15-bf6d-93cd1ea2a20d","type":"Grid"},{"attributes":{"bottom_units":"screen","fill_alpha":{"value":0.5},"fill_color":{"value":"lightgrey"},"left_units":"screen","level":"overlay","line_alpha":{"value":1.0},"line_color":{"value":"black"},"line_dash":[4,4],"line_width":{"value":2},"plot":null,"render_mode":"css","right_units":"screen","top_units":"screen"},"id":"2a376fc3-0bcc-47df-a0e8-2389040d3254","type":"BoxAnnotation"},{"attributes":{"plot":null,"text":"","text_color":{"value":"black"},"text_font_size":{"value":"12pt"}},"id":"04310042-3ae0-4955-bd48-3d9c8e2d9be2","type":"Title"},{"attributes":{},"id":"722ae387-76c5-48cb-a387-7090de91b014","type":"ResetTool"},{"attributes":{"dimension":1,"grid_line_color":{"value":null},"plot":{"id":"c84e964a-0b0b-4d95-aa2c-3657b7811bd0","subtype":"Figure","type":"Plot"},"ticker":{"id":"95b801e5-1f32-4ff1-be0c-e64ddcb14fa3","type":"BasicTicker"}},"id":"a281b265-486f-42a3-829a-c71bfd6830d0","type":"Grid"},{"attributes":{"axis_label":"Order Type","formatter":{"id":"259e4d35-20fb-4eb4-9fbd-6068fef93c0d","type":"CategoricalTickFormatter"},"plot":{"id":"c84e964a-0b0b-4d95-aa2c-3657b7811bd0","subtype":"Figure","type":"Plot"},"ticker":{"id":"bfe7ff64-0995-43a7-8944-6d491bf93b14","type":"CategoricalTicker"}},"id":"9f673b5b-85bf-40d1-96f3-b27737ecc242","type":"CategoricalAxis"},{"attributes":{},"id":"218dbf74-8190-491c-b2dc-d13097c1f9e4","type":"PanTool"},{"attributes":{},"id":"259e4d35-20fb-4eb4-9fbd-6068fef93c0d","type":"CategoricalTickFormatter"},{"attributes":{},"id":"16eb22e8-c448-49d7-ab20-a02f2ebb3e5c","type":"SaveTool"},{"attributes":{},"id":"721998c2-dee0-4e47-9a6d-ecef76d53889","type":"LinearScale"},{"attributes":{},"id":"03f67199-1622-4784-b9a2-b36b4a47477b","type":"WheelZoomTool"},{"attributes":{"overlay":{"id":"2a376fc3-0bcc-47df-a0e8-2389040d3254","type":"BoxAnnotation"}},"id":"d48948b1-297b-4915-bf84-916a417b01ee","type":"BoxZoomTool"},{"attributes":{"data_source":{"id":"46c2f30a-31d4-4c3f-ade2-4de96e13a4db","type":"ColumnDataSource"},"glyph":{"id":"3ab94627-160a-4913-95e6-c25fa17a1d51","type":"VBar"},"hover_glyph":null,"muted_glyph":null,"nonselection_glyph":{"id":"f72f6dc1-7c71-4f5e-80f9-fbd1351268b3","type":"VBar"},"selection_glyph":null,"view":{"id":"9df174a0-4967-47fd-82f3-3d054eee1a12","type":"CDSView"}},"id":"897248ec-4fbd-404c-b3b3-09900b6e3560","type":"GlyphRenderer"},{"attributes":{"fill_alpha":{"value":0.1},"fill_color":{"value":"#30a2da"},"line_alpha":{"value":0.1},"line_color":{"value":"#000000"},"top":{"field":"counts"},"width":{"value":0.8},"x":{"field":"ORDTYP"}},"id":"f72f6dc1-7c71-4f5e-80f9-fbd1351268b3","type":"VBar"},{"attributes":{"fill_color":{"value":"#30a2da"},"line_color":{"value":"#000000"},"top":{"field":"counts"},"width":{"value":0.8},"x":{"field":"ORDTYP"}},"id":"3ab94627-160a-4913-95e6-c25fa17a1d51","type":"VBar"},{"attributes":{"source":{"id":"46c2f30a-31d4-4c3f-ade2-4de96e13a4db","type":"ColumnDataSource"}},"id":"9df174a0-4967-47fd-82f3-3d054eee1a12","type":"CDSView"},{"attributes":{},"id":"eb1872c1-4fa5-47b0-b5c7-43dfe9b890e3","type":"CategoricalScale"},{"attributes":{},"id":"7303c9ca-b3e1-40be-bd44-1ef7f06d8a2d","type":"BasicTickFormatter"},{"attributes":{"background_fill_color":{"value":"white"},"below":[{"id":"9f673b5b-85bf-40d1-96f3-b27737ecc242","type":"CategoricalAxis"}],"left":[{"id":"bd1e5045-1d72-4e92-8914-13be1ee0d04f","type":"LinearAxis"}],"min_border_bottom":10,"min_border_left":10,"min_border_right":10,"min_border_top":10,"plot_height":300,"plot_width":300,"renderers":[{"id":"9f673b5b-85bf-40d1-96f3-b27737ecc242","type":"CategoricalAxis"},{"id":"0dee56d3-b965-4d15-bf6d-93cd1ea2a20d","type":"Grid"},{"id":"bd1e5045-1d72-4e92-8914-13be1ee0d04f","type":"LinearAxis"},{"id":"a281b265-486f-42a3-829a-c71bfd6830d0","type":"Grid"},{"id":"2a376fc3-0bcc-47df-a0e8-2389040d3254","type":"BoxAnnotation"},{"id":"897248ec-4fbd-404c-b3b3-09900b6e3560","type":"GlyphRenderer"}],"title":{"id":"04310042-3ae0-4955-bd48-3d9c8e2d9be2","type":"Title"},"toolbar":{"id":"8ce67c3d-e8dc-41a2-86a8-76685fb90fe9","type":"Toolbar"},"x_range":{"id":"36f2f454-71a9-4511-a446-2c56a015ecd0","type":"FactorRange"},"x_scale":{"id":"eb1872c1-4fa5-47b0-b5c7-43dfe9b890e3","type":"CategoricalScale"},"y_range":{"id":"16f5dfe6-08a6-4ad8-a190-bdf67979b26c","type":"DataRange1d"},"y_scale":{"id":"721998c2-dee0-4e47-9a6d-ecef76d53889","type":"LinearScale"}},"id":"c84e964a-0b0b-4d95-aa2c-3657b7811bd0","subtype":"Figure","type":"Plot"}],"root_ids":["c84e964a-0b0b-4d95-aa2c-3657b7811bd0"]},"title":"Bokeh Application","version":"0.12.7"}};
var render_items = [{"docid":"c7d02456-4a61-46d2-8431-34face1e6c67","elementid":"0dd69ef6-4d30-48f5-a95a-1201437920de","modelid":"c84e964a-0b0b-4d95-aa2c-3657b7811bd0"}];
Bokeh.embed.embed_items(docs_json, render_items);
};
if (document.readyState != "loading") fn();
else document.addEventListener("DOMContentLoaded", fn);
})();
},
function(Bokeh) {
}
];
function run_inline_js() {
if ((root.Bokeh !== undefined) || (force === true)) {
for (var i = 0; i < inline_js.length; i++) {
inline_js[i].call(root, root.Bokeh);
}if (force === true) {
display_loaded();
}} else if (Date.now() < root._bokeh_timeout) {
setTimeout(run_inline_js, 100);
} else if (!root._bokeh_failed_load) {
console.log("Bokeh: BokehJS failed to load within specified timeout.");
root._bokeh_failed_load = true;
} else if (force !== true) {
var cell = $(document.getElementById("0dd69ef6-4d30-48f5-a95a-1201437920de")).parents('.cell').data().cell;
cell.output_area.append_execute_result(NB_LOAD_WARNING)
}
}
if (root._bokeh_is_loading === 0) {
console.log("Bokeh: BokehJS loaded, going straight to plotting");
run_inline_js();
} else {
load_libs(js_urls, function() {
console.log("Bokeh: BokehJS plotting callback run at", now());
run_inline_js();
});
}
}(window));
</script></div>
THANKS!

You are missing the JS and CSS that's required to render this output. You can either manually include BokehJS as a script tag, e.g. for bokeh 0.12.9 you'd add this:
<link
href="http://cdn.bokeh.org/bokeh/release/bokeh-0.12.9.min.css"
rel="stylesheet" type="text/css">
<link
href="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-0.12.9.min.css"
rel="stylesheet" type="text/css">
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-0.12.9.min.js"></script>
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-0.12.6.min.js"></script>
Alternatively you can also use the renderer.static_html method to export a div which includes all the required JS and CSS, e.g.:
hmap = hv.HoloMap({i: hv.Curve(np.random.rand(10)*i) for i in range(1,5)})
html = hv.renderer('bokeh').static_html(hmap)
with open('test.html', 'w') as f:
f.write(html)
The static_html method also accepts a template to embed the JS, CSS and HTML separately:
<html>
<head>
{css}
{js}
</head>
<body>
{html}
</body>
</html>
In future releases we will also have a components method letting you get the JS, CSS and HTML components separately.

Related

Finding text between tag <a> (regex with variable)

function Selection () {
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
var result = html.indexOf("href");
if (result != -1) {
window.getSelection().empty();
window.getSelection().removeAllRanges();
} else {
var textofclassText = $('.text').html();
//var patt1 = /id=\"load([\s\S]*?)+[selectedTexthtml]/g;
var result_2;
//var result_2 = textofclassText.search(patt1);
if(result_2 != "null") {
window.getSelection().empty();
window.getSelection().removeAllRanges();
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<div class="text" onmouseup="Selection()">
You
<br><a class="good" data-id="3" href="#load" id="load3">are very </a> important for us.
<br>So we're offering you
<br><a class="good" data-id="4" href="#load" id="load4"> win-win</a> option.
<br>You will get 2 refrigerators if you buy one
</div>
</body>
</html>
I need to remove selection if the selected text contains "a" tag. If I start to select link-text from left I will get only text "are very", so I need to find first match in all class ".text". I can't get how to use variable in that regex, because when I try to build string from variables it doesn't work.
var patt1 = new RegExp("id=\"load([\s\S]*?)" + html, "g");
var result = textofclassText.search(patt1);

How to embed Wufoo form in Ember application

My client has asked me to integrate a Wufoo form into their Ember application, and provided the following JS (anonymized):
<script type="text/javascript">var abc123;(function(d, t) {
var s = d.createElement(t), options = {
'userName':'example',
'formHash':'abc123',
'autoResize':true,
'height':'491',
'async':true,
'host':'wufoo.com',
'header':'show',
'ssl':true};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'www.wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function() {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { abc123 = new WufooForm();abc123.initialize(options);abc123.display(); } catch (e) {}};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>
I've tried including it in index.html and also creating a custom component, but keep getting an error from Wufoo:
TypeError: Cannot set property 'innerHTML' of null
Is there a way to use the provided Wufoo JS in an Ember.js app?

Rails or Ember object model breaking browser's pushState functionality?

** I'm using Ember.Object instead of Ember Data, to pull data from an api and I believe that might be causing the issue.**
I have my resources nested as so:
Mdm.Router.map ->
#resource "groups", ->
#resource "group", path: ':group_id'
'/groups/ loads a list of all groups on the left side of the browser. Each group is linking to its specific group_id. When clicked, the 'group' template renders on the right side of the screen, showing details of one group while the list remains to the left.
However, when you click the back button, or manually enter the group_id into the url the individual groups dont render. The url will update in the browser window, but the content wont change to match it.
I have the singular 'group' template rendering inside of the 'groups' template with the {{outlet}}.
My groups_route.js.coffee looks like this:
Mdm.GroupsRoute = Ember.Route.extend(model: ->
Mdm.Group.all()
)
application.hbs:
<div class="container">
<div class="nav-bar">
<img src="assets/logo_loginbox.png" class="logo">
<ul class="nav-menu">
<li>GROUPS</li>
<li>USERS</li>
</ul>
</div><!-- nav-bar -->
<hr>
{{outlet}}
</div><!-- container -->
groups.hbs:
<h1>Groups</h1>
{{ partial groupsList }}
<div class="group">
{{outlet}}
</div><!-- group -->
group.hbs:
<h1>{{name}}</h1>
I'm getting the following error in the console when I use the back button or try to load the page with the group_id present:
Uncaught TypeError: Object function () {
if (!wasApplied) {
Class.proto(); // prepare prototype...
}
o_defineProperty(this, GUID_KEY, undefinedDescriptor);
o_defineProperty(this, '_super', undefinedDescriptor);
var m = meta(this);
m.proto = this;
if (initMixins) {
// capture locally so we can clear the closed over variable
var mixins = initMixins;
initMixins = null;
this.reopen.apply(this, mixins);
}
if (initProperties) {
// capture locally so we can clear the closed over variable
var props = initProperties;
initProperties = null;
var concatenatedProperties = this.concatenatedProperties;
for (var i = 0, l = props.length; i < l; i++) {
var properties = props[i];
Ember.assert("Ember.Object.create no longer supports mixing in other definitions, use createWithMixins instead.", !(properties instanceof Ember.Mixin));
for (var keyName in properties) {
if (!properties.hasOwnProperty(keyName)) { continue; }
var value = properties[keyName],
IS_BINDING = Ember.IS_BINDING;
if (IS_BINDING.test(keyName)) {
var bindings = m.bindings;
if (!bindings) {
bindings = m.bindings = {};
} else if (!m.hasOwnProperty('bindings')) {
bindings = m.bindings = o_create(m.bindings);
}
bindings[keyName] = value;
}
var desc = m.descs[keyName];
Ember.assert("Ember.Object.create no longer supports defining computed properties.", !(value instanceof Ember.ComputedProperty));
Ember.assert("Ember.Object.create no longer supports defining methods that call _super.", !(typeof value === 'function' && value.toString().indexOf('._super') !== -1));
if (concatenatedProperties && indexOf(concatenatedProperties, keyName) >= 0) {
var baseValue = this[keyName];
if (baseValue) {
if ('function' === typeof baseValue.concat) {
value = baseValue.concat(value);
} else {
value = Ember.makeArray(baseValue).concat(value);
}
} else {
value = Ember.makeArray(value);
}
}
if (desc) {
desc.set(this, keyName, value);
} else {
if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) {
this.setUnknownProperty(keyName, value);
} else if (MANDATORY_SETTER) {
Ember.defineProperty(this, keyName, null, value); // setup mandatory setter
} else {
this[keyName] = value;
}
}
}
}
}
finishPartial(this, m);
delete m.proto;
finishChains(this);
this.init.apply(this, arguments);
} has no method 'find' application.js:51233
Mdm.GroupRoute.Ember.Route.extend.model application.js:51233
superWrapper application.js:12849
Ember.Route.Ember.Object.extend.deserialize application.js:36503
collectObjects application.js:35614
proceed application.js:35638
(anonymous function) application.js:1193
fire application.js:1038
self.fireWith application.js:1149
(anonymous function) application.js:1200
fire application.js:1038
self.fireWith application.js:1149
done application.js:8075
script.onload.script.onreadystatechange

Load PHP file with document.createElement()

How could I make this work? I want to load a php file like this:
Click button.
Call Javascript function.
In Javascript function create an img with src file.php.
This should force the loading of the php. Here is the code.
<script type="text/javascript">
var d;
function callSave() {
alert ('calling');
if (d) document.body.removeChild(d);
// d = document.createElement("script");
d = document.createElement("img");
d.src = "savepages.php";
//d.type = "text/javascript";
document.body.appendChild(d);
}
</script>
Then in savepages.php I do another alert to verify that the php is called and it isn't. Here is the savepages.php.
<?php
echo "alert('from the php');";
?>
The alert from the php doesn't happen. Is there a different element type that will force loading of the php? I don't have ajax installed, so I need a workaround like this.
Thanks.
You could use an iframe element
<script type="text/javascript">
var d;
function callSave() {
alert ('calling');
if (d) document.body.removeChild(d);
d = document.createElement("iframe");
d.src = "savepages.php";
document.body.appendChild(d);
}
</script>
Found out the better way to handle this. There is this simple code that explains how to call a javascript function from a form event and from that javascript function load a PHP file. The code found at http://daniel.lorch.cc/docs/ajax_simple/ is also given here:
<script type="text/javascript">
var http = false;
if(navigator.appName == "Microsoft Internet Explorer") {
http = new ActiveXObject("Microsoft.XMLHTTP");
} else {
http = new XMLHttpRequest();
}
function validate(user) {
http.abort();
http.open("GET", "validate.php?name=" + user, true);
http.onreadystatechange=function() {
if(http.readyState == 4) {
document.getElementById('msg').innerHTML = http.responseText;
}
}
http.send(null);
}
</script>
<h1>Please choose your username:</h1>
<form>
<input type="text" onkeyup="validate(this.value)" />
<div id="msg"></div>
</form>
validate.php
<?php
function validate($name) {
if($name == '') {
return '';
}
if(strlen($name) < 3) {
return "<span id=\"warn\">Username too short</span>\n";
}
switch($name) {
case 'bob':
case 'jim':
case 'joe':
case 'carol':
return "<span id=\"warn\">Username already taken</span>\n";
}
return "<span id=\"notice\">Username ok!</span>\n";
}
echo validate(trim($_REQUEST['name']));
?>

Dojo widget controller

I am working on a new project and have been trying to get a JS controller to decide which dojo widgets are needed for any particular page.
I have this working, but only when I inject / hardcode the dojo widget's JS into the page. As soon as I try to get it working with dojo's provide and require mechanisms, everything stops working and I get the following error:
Could not load 'pf.PasswordStrength'; last tried '../dojopf/widget/PasswordStrength.js'
http://pf-dev-ad/wcsstore/js/dojo131/dojo/dojo.js
Line 16
Firebug shows this error right after it includes the file!
I am having real problems with this as dojo 1.3.1 (which I'm not allowed to upgrade) is very poorly documented and there aren't many tutorials.
The requirement is as follows:
1 site-wide JS controller (lib.js)
1 widget specific JS file (PasswordStrength.js)
1 widget template file (PasswordStrength.html)
1 pointer node
The file structre is setup as follows:
js
dojo131
dijit
dojo
dojotest
widget
templates
PasswordStrength.html
PasswordStrength.css
PasswordStrength.js
dojox
//JS controller (lib.js):
if(!ad){ var ad = {} }
ad.base = new (function(){
// init function will run on page load. Called by dojo.addOnLoad
this.init = function (){
/* This function acts as a controller for Dojo widgets.
// it uses a variable ('pageName') set by the JSTL in the parent JSP of a particular page
switch(ad.pageName){
case 'Home':
_getTemplateAssets('PasswordStrength');
break;
}
}
var $ = dojo.query;
var templatePath = 'js/dojo131/dojotest/widget';
var debug = false; // This should be set to false when on production
/*** PRIVATE FUNCTIONS ***/
function _getTemplateAssets(templateName){
// Injects the JS and CSS template assets into the page head
dojo.registerModulePath("ad", '../dojotest/widget'); // relative to dojo.js
//dojo.provide('ad.' + templateName);
dojo.require('ad.' + templateName);
//var headTag = document.getElementsByTagName('head').item(0);
//dojo.create("script", { src: templatePath + '/' + templateName + '.js', type: 'text/javascript' }, headTag);
//dojo.create("link", { href: templatePath + '/templates/' + templateName + '.css', type: 'text/css', rel: 'stylesheet' }, headTag);
}
});
/*** ONLOAD ***/
dojo.addOnLoad(ad.base.init);
// Widget JS (PasswordStrength.js)
if(!ad){ var ad = {} }
ad.passwordCheck = new (function(){
// init function will run on page load. Called by dojo.addOnLoad
this.init = function (){
_temp_addPasswordCheck();
}
/*** PRIVATE VARIABLES ***/
var $ = dojo.query;
var templateName = 'PasswordStrength';
var insertPointID = 'ins_passStrength';
var minLength = 6;
var objAdvice = { enterPass: 'Please enter a password', addChars: 'Add more characters (min ' + minLength + ')', addSpecials: 'Use special characters (!##$%^&*)', addUppers: 'Use some upper case characters', addLowers: 'Use some lower case characters', addNums: 'Use some numbers', remRepeats: 'Too many repeated repeat characters', passPass: 'Your password has been verified as Excellent!' };
var complexity = ['Bad', 'Very weak', 'Weak', 'Good', 'Strong', 'Excellent'];
var content = {
titles: {
h1: 'Password Strength'
},
labels: {
password: 'Password:',
confirmPassword: 'Confirm Password',
obscure: 'Obscure:',
strength: 'Password strength:',
advice: 'Advice:'
},
content:{
advice: 'Please enter a password',
strength: 'None'
}
}
/*** PRIVATE FUNCTIONS ***/
function _temp_addPasswordCheck(){
// Include extras
dojo.provide("ad.PasswordStrength");
dojo.require("ad.PasswordStrength");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojo.parser");
dojo.declare(templateName, [dijit._Widget, dijit._Templated], {
// calls the HTML template to be used
templatePath: dojo.moduleUrl ('dojotest.widget','templates/' + templateName + '.html'),
// Content (titles, labels and general content)
label_password: content.labels.password,
label_confirmPassword: content.labels.confirmPassword,
label_obscure: content.labels.obscure,
label_passwordStrength: content.labels.strength,
label_advice: content.labels.advice,
title_passwordStrength: content.titles.h1,
content_advice: content.content.advice,
content_strength: content.content.strength,
obscurePassword: function(){
if(this.obscurePass.checked){ dojo.attr(this.passwordValue, 'type', 'password'); }
else{ dojo.attr(this.passwordValue, 'type', 'text'); }
},
checkPassword: function(){
// This function checks the password strength on keyup and alters the passwordAdvice div to reflect the strength of the password entered
// Runs the password through a validation function which returns the results
var results = _checkPassWord(this.passwordValue.value), score = results['score'];
var ele = dojo.byId('passStrength');
// Update the markup to inform the user of their passwords score
if(results['count'] == 0){
this.complexity.innerHTML = 'None';
ele.className = '';
this.advice.innerHTML = _doInsert([objAdvice.enterPass]);
}
else if(score <= 50){
this.complexity.innerHTML = complexity[0];
ele.className = 'bad';
this.advice.innerHTML = _doInsert(results.advice);
}
if(score == 60){
this.complexity.innerHTML = complexity[1];
ele.className = 'veryWeak';
this.advice.innerHTML = _doInsert(results.advice);
}
if(score == 70){
this.complexity.innerHTML = complexity[2];
ele.className = 'weak';
this.advice.innerHTML = _doInsert(results.advice);
}
if(score == 80){
this.complexity.innerHTML = complexity[3];
ele.className = 'good';
this.advice.innerHTML = _doInsert(results.advice);
}
if(score == 90){
this.complexity.innerHTML = complexity[4];
ele.className = 'strong';
this.advice.innerHTML = _doInsert(results.advice);
}
if(score >= 100){
this.complexity.innerHTML = complexity[5];
ele.className = 'excellent';
this.advice.innerHTML = _doInsert([objAdvice.passPass]);
}
}
});
// Calls the template into the right ID defined as the insert point as the first child
if(dojo.byId(insertPointID)){
var passStrength = new PasswordStrength().placeAt(insertPointID);
}
};
function _doInsert(arrInsert){
var content = '';
dojo.forEach(arrInsert, function(item, i){
content = content + '<p>' + item + '</p>';
});
return content;
}
function _checkPassWord(strPassword){
// Grades the password string and returns the results
var objResults = {}, scoreFactor = 10, score = 0, advice = [], lengthPass, alphaLCpass, alphaUCpass, numPass, specialsPass, repeatPass, count = strPassword.length;
// Check password string for uppercase alphas, lowercase alphas, numerals, special characters and repeated characters
alphaUCpass = strPassword.match(/[A-Z]/g) ? true : false;
alphaLCpass = strPassword.match(/[a-z]/g) ? true : false;
numPass = strPassword.match(/[0-9]/g) ? true: false;
specialsPass = strPassword.match(/[^a-zA-Z0-9]/g) ? true : false;
repeatPass = strPassword.match(/(.)\1\1/g) ? false : true;
lengthPass = count >= minLength ? true : false;
// Score the password based on the results of the check
if(alphaUCpass){ score += scoreFactor; }
else{ advice.push(objAdvice.addUppers); }
if(alphaLCpass){ score += scoreFactor; }
else{ advice.push(objAdvice.addLowers); }
if(numPass){ score += scoreFactor; }
else{ advice.push(objAdvice.addNums); }
if(specialsPass){ score += scoreFactor; }
else{ advice.push(objAdvice.addSpecials); }
if(repeatPass){ score += scoreFactor; }
else{ advice.push(objAdvice.remRepeats); }
if(lengthPass){ score += scoreFactor * 5; }
else{ advice.push(objAdvice.addChars); }
// Inserts the results into object to be returned
objResults = {
'alphaUC': alphaUCpass,
'alphaLC': alphaLCpass,
'numerals': numPass,
'specials': specialsPass,
'length': lengthPass,
'repeat': repeatPass,
'count': count,
'score': score,
'advice': advice
}
// Return results to parent function
return objResults;
}
/*** PUBLIC FUNCTIONS ***/
});
/*** ONLOAD ***/
dojo.addOnLoad(ad.passwordCheck.init);
// Widget HTML template (PasswordStrength.html)
<div>
<h1>${title_passwordStrength}</h1>
<form method="post" action="">
<fieldset>
<div class="formFields">
<label for="password">${label_password}</label>
<input type="password" name="password" id="password" dojoAttachPoint="passwordValue" dojoAttachEvent="onkeyup: checkPassword" />
</div>
<div class="formFields">
<label for="confirmPassword">${label_confirmPassword}</label>
<input type="password" name="confirmPassword" id="confirmPassword" dojoAttachPoint="passwordConfirmValue" dojoAttachEvent="onkeyup: checkPassword" />
</div>
<div class="formFields">
<label for="obscurePassword" class="wAuto">${label_obscure}</label>
<input class="wAuto" type="checkbox" value="true" checked="checked" name="obscurePassword" id="obscurePassword" dojoAttachPoint="obscurePass" dojoAttachEvent="onchange: obscurePassword" />
</div>
<div class="formFields">
<label>${label_passwordStrength}</label>
<div dojoAttachPoint="strength" id="passStrength" class=""></div>
<div dojoAttachPoint="complexity" id="passStrengthCaption">${content_strength}</div>
</div>
<div class="formFields">
<label>${label_advice}</label>
<div dojoAttachPoint="advice" id="passAdvice"><p>${content_advice}</p></div>
</div>
</fieldset>
</form>
The parent file has a HTML pointer in it as follows:
<div id="ins_passStrength" dojoType="PasswordStrength"></div>
If I change the following function in parent controller (lib.js):
function _getTemplateAssets(templateName){
// Injects the JS and CSS template assets into the page head
dojo.registerModulePath("ad", '../dojotest/widget'); // relative to dojo.js
//dojo.provide('ad.' + templateName);
dojo.require('ad.' + templateName);
//var headTag = document.getElementsByTagName('head').item(0);
//dojo.create("script", { src: templatePath + '/' + templateName + '.js', type: 'text/javascript' }, headTag);
//dojo.create("link", { href: templatePath + '/templates/' + templateName + '.css', type: 'text/css', rel: 'stylesheet' }, headTag);
}
To:
function _getTemplateAssets(templateName){
// Injects the JS and CSS template assets into the page head
dojo.registerModulePath("ad", '../dojotest/widget'); // relative to dojo.js
dojo.provide('ad.' + templateName);
dojo.require('ad.' + templateName);
//var headTag = document.getElementsByTagName('head').item(0);
//dojo.create("script", { src: templatePath + '/' + templateName + '.js', type: 'text/javascript' }, headTag);
//dojo.create("link", { href: templatePath + '/templates/' + templateName + '.css', type: 'text/css', rel: 'stylesheet' }, headTag);
}
The error goes away but the widegt JS isn't included.
And if you change it to:
function _getTemplateAssets(templateName){
// Injects the JS and CSS template assets into the page head
dojo.registerModulePath("ad", '../dojotest/widget'); // relative to dojo.js
//dojo.provide('ad.' + templateName);
//dojo.require('ad.' + templateName);
var headTag = document.getElementsByTagName('head').item(0);
dojo.create("script", { src: templatePath + '/' + templateName + '.js', type: 'text/javascript' }, headTag);
dojo.create("link", { href: templatePath + '/templates/' + templateName + '.css', type: 'text/css', rel: 'stylesheet' }, headTag);
}
It works fine but this is a dirty sidestep... I need to use dojo's prescribed methods.
Any help greatly appreciated.
Thank you!
I believe your error is that you have put your dojo.provide("ad.PasswordStrength") inside a bunch of functions. It needs to be at the top of the file. Dojo evaluates the file it believes to be correct (based on module path), but how is it supposed to know if PasswordStrength is in there, unless you tell it "yes, this file provides ad.PasswordStrength".
Edit: considering what you said on IRC, here's how I think PasswordStrength.js should look:
dojo.provide("ad.PasswordStrength");
if(!ad){ var ad = {} }
ad.passwordCheck = new (function(){
// init function will run on page load. Called by dojo.addOnLoad
this.init = function (){
_temp_addPasswordCheck();
dojo.parser.parse();
}
/*** PRIVATE VARIABLES ***/
var $ = dojo.query;
var templateName = 'PasswordStrength';
....
/*** PRIVATE FUNCTIONS ***/
function _temp_addPasswordCheck(){
// Include extras
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojo.parser");
dojo.declare("ad." + templateName, [dijit._Widget, dijit._Templated], {
// calls the HTML template to be used
templatePath: dojo.moduleUrl ('dojotest.widget','templates/' + templateName + '.html'),
// Content (titles, labels and general content)
label_password: content.labels.password,
label_confirmPassword: content.labels.confirmPassword,
label_obscure: content.labels.obscure,
label_passwordStrength: content.labels.strength,
label_advice: content.labels.advice,
title_passwordStrength: content.titles.h1,
content_advice: content.content.advice,
content_strength: content.content.strength,
obscurePassword: function(){
....
},
checkPassword: function(){
....
}
});
/*
if(dojo.byId(insertPointID)){
var passStrength = new PasswordStrength().placeAt(insertPointID);
}
*/
};
function _doInsert(arrInsert){
....
}
function _checkPassWord(strPassword){
....
}
/*** PUBLIC FUNCTIONS ***/
});
/*** ONLOAD ***/
dojo.addOnLoad(ad.passwordCheck.init);
Moved dojo.provide("ad.PasswordStrength"); to the top of the file.
Removed dojo.require("ad.PasswordStrength"); from _temp_addPasswordCheck() - if this code is executed, ad.PasswordStrength (PasswordStrength.js) has obviously already been required and loaded.
Added dojo.parser.parse(); to the end of init(), so that after the widget has been declared, any widget dojoTypes in the HTML will be parsed. However, I still don't understand why you have to declare the widget inside _temp_addPasswordCheck. Why not have the widget in it's on file, and ad.passwordCheck wherever your applications other "page" files are?
Added "ad." to the widget declaration (dojo.declare("ad." + templateName)), it needs to have the full namespaced name here.
Commented out new PasswordStrength().placeAt(.... Since you want to insert your widgets declaratively in your HTML, it doesn't make sense to manually instantiate one here, and place it manually.
Now you should be able to put PasswordStrength widgets in your HTML, like so:
<script type="text/javascript" src="js/dojo131/dojo/dojo.js"></script>
<script type="text/javascript" src="js/dojo131/dojotest/lib.js"></script>
....
<div id="ins_passStrength" dojoType="ad.PasswordStrength"></div>
<div id="anotherOne" dojoType="ad.PasswordStrength"></div>
Remember that you need the whole namespaced name here as well (i.e. the ad. prerfix).
This worked nicely for me, using Dojo 1.3.3. Uploaded the sandbox if it's any use.
Your error:
Could not load 'pf.PasswordStrength'; last tried '../dojopf/widget/PasswordStrength.js'
http://pf-dev-ad/wcsstore/js/dojo131/dojo/dojo.js
Line 16
Is this a typo? Because it should be trying ../dojotest/widget/PasswordStrength.js
Do you have another dojo.require that is referring to dojopf? Or any other line like dojo.require("pf.PasswordStrength")?
If not, perhaps the registering of the module path is not happening before dojo tries to load your .js. Perhaps try using dojo.require to load your lib.js.