websash
2008-Apr-07 19:29 UTC
Staff Manager tutorial from "Prototype and script.aculo.us" by Christophe Porteneuve
Hi there,
Taking my first steps in Prototype and reading this very helpful book
by Christophe Porteneuve. There''s an interesting tutorial (Chpt. 7) on
making a tree to organize staff members. The problem is that I can''t
make it working in IE. In Firefox it works just great.
Did anybody fiddle with it? Maybe somebody has already figured it out.
IE says "''undefined'' is null or not an object" for
n.container nodes; from the init method:
......
init: function(id, nodes) {
id = id || ''staff'';
nodes = nodes || this.nodes;
nodes.each(function(n) {
n.container = nodes;
this.createDOMFragment(id, n);
if (n.children)
this.init(n.id, n.children);
}.bind(this));
},
......
In IE nothing works at all, though the tree loads properly
Here''s the full code of people.js:
---------------------------------------------
var Staff = {
_templates: {
person: new Template(
''<span class="person">'' +
''<input type="checkbox" name="item[]"
value="#{id}" /><span>#{name}</span></span>''),
group: new Template(
''<span class="group">'' +
''<a href="" title="Click to
collapse">'' +
''<img class="toggler" src="group_open.gif"
alt="-" /></a>'' +
''<input type="checkbox" name="item[]"
value="#{id}" /><span>#{name}</span></span>'' +
''<ul></ul>'')
},
_currentId: 1000,
selected: null,
nodes: [
{ id: ''item1'', name: ''ACME'',
children: [
{ id: ''item11'', name: ''IT'',
children: [
{ id: ''item111'', name: ''Sébastien
Gruhier'' },
{ id: ''item112'', name: ''Alexis
Jaubert'' },
{ id: ''item113'', name: ''Guillaume
Réan'' }
] },
{ id: ''item12'', name: ''HR'',
children: [
{ id: ''item121'', name: ''Sandrine
Daspet'' }
] },
{ id: ''item13'', name: ''Xavier
Borderie'' }
] },
],
create: function(name, isGroup) {
var container = this.selected ? this.selected.children :
this.nodes;
var node = { id: ''item'' + this.genId(), name: name,
container:
container };
if (isGroup)
node.children = [];
container.push(node);
return this.createDOMFragment(
this.selected ? this.selected.id : ''staff'', node);
},
createDOMFragment: function(parentId, node) {
var element = new Element(''li'', { id: node.id });
var tpl = this._templates[node.children ? ''group'' :
''person''];
var escapedNode = { id: node.id, name: node.name.escapeHTML() };
element.update(tpl.evaluate(escapedNode));
$(parentId).down(''ul'').appendChild(element);
element.down(''input'').checked = node.checked;
this.makeVisible(node.id);
return node;
},
find: function(id, nodes) {
nodes = nodes || this.nodes;
var result;
nodes.each(function(n) {
result = n.id == id ? n : n.children && this.find(id,
n.children);
if (result)
throw $break;
}.bind(this));
return result;
},
genId: function() {
return ++this._currentId;
},
init: function(id, nodes) {
id = id || ''staff'';
nodes = nodes || this.nodes;
nodes.each(function(n) {
n.container = nodes;
this.createDOMFragment(id, n);
if (n.children)
this.init(n.id, n.children);
}.bind(this));
},
makeVisible: function(id) {
var elt = $(id);
// Open all containing groups
while (elt = elt.up(''ul''))
if (!elt.visible())
this.toggle(elt.up(''li'').id);
},
removeSelected: function() {
if (!this.selected)
throw ''No selection to remove'';
var container = this.selected.container;
container = container.without(this.selected);
var elt = $(this.selected.id);
var previous = elt.previous(''li'');
if (!previous)
previous = elt.up(''li'');
elt.remove();
this.selected = null;
if (previous)
this.select(previous.id);
else
this.updateEditor();
},
select: function(id) {
if (this.selected)
$(this.selected.id).down(''span'').removeClassName(''selected'');
this.selected = (this.selected && this.selected.id == id
? null : this.find(id));
if (this.selected) {
var elt = $(id);
elt.down(''span'').addClassName(''selected'');
this.makeVisible(id);
}
this.updateEditor();
return this.selected;
},
toggle: function(id) {
var elt = $(id);
var group = elt.down(''ul'');
var toggler = elt.down(''img'');
var groupIsVisible = group.toggle().visible();
toggler.src = ''group_'' + (groupIsVisible ?
''open'' : ''closed'') +
''.gif'';
toggler.alt = (groupIsVisible ? ''-'' :
''+'');
toggler.up(''a'').title = ''Click to '' +
(groupIsVisible ? ''collapse'' :
''expand'');
},
update: function() {
this.selected.label = $F(''edtName'');
$(this.selected.id).down(''span'', 1).update(
this.selected.label.escapeHTML());
},
updateEditor: function() {
if (!this.selected) {
$(''edtName'').value = '''';
$(''chkIsGroup'').enable().checked = false;
$(''btnSubmit'').value = ''Create'';
$(''btnRemove'', ''btnAddChild'',
''btnSubmit'').invoke(''disable'');
} else {
$(''edtName'').value = this.selected.name;
var isGroup = this.selected.children;
$(''chkIsGroup'').checked = isGroup;
$(''btnSubmit'').value = ''Rename'';
$(''btnRemove'').enable();
$(''btnAddChild'',
''chkIsGroup'').invoke(isGroup ? ''enable'' :
''disable'');
}
$(''edtName'').activate();
}
}; // Staff
function handleTreeClick(e) {
var elt = e.element();
if (elt.tagName == ''INPUT'')
return;
e.stop();
if (elt.tagName == ''IMG'')
elt = elt.up(''a'');
if (elt.tagName == ''A'') {
Staff.toggle(elt.up(''li'').id);
return;
}
// Other click. Let''s select if we''re on a valid item!
if (''LI'' != elt.tagName)
elt = elt.up(''li'');
if (!elt)
return;
Staff.select(elt.id);
} // handleTreeClick
function processForm(e, addChild) {
e.stop();
if (Staff.selected && !addChild)
Staff.update($F(''edtName''));
else
Staff.create($F(''edtName''),
$(''chkIsGroup'').checked);
} // processForm
document.observe(''dom:loaded'', function() {
Staff.init();
Staff.updateEditor();
$(''tree'').observe(''click'',
handleTreeClick);
$(''editor'').observe(''submit'',
processForm);
$(''btnRemove'').observe(''click'',
Staff.removeSelected.bind(Staff));
$(''btnAddChild'').observe(''click'',
processForm.bindAsEventListener(this, true));
new Field.Observer(''edtName'', 0.3, function() {
$(''btnSubmit'').disabled =
$F(''edtName'').blank();
});
});
---------------------------------------------
people.html:
---------------------------------------------
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://
www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8">
<title>Organizing your staff</title>
<link rel="stylesheet" type="text/css"
href="people.css">
<script type="text/javascript"
src="prototype.js"></script>
<script type="text/javascript"
src="people.js"></script>
</head>
<body>
<h1>Organizing your staff</h1>
<div id="tree" >
<h2>Your staff</h2>
<form id="staff" >
<ul>
</ul>
</form>
</div>
<div id="props" >
<h2>Item properties</h2>
<form id="editor" >
<p>
<label for="edtName" accesskey="N"
>Name:</label>
<input type="text" id="edtName" />
</p>
<p>
<input type="checkbox" id="chkIsGroup" />
<label for="chkIsGroup" id="lblIsGroup"
accesskey="G" >Is a group?</label>
</p>
<p>
<input type="button" id="btnRemove"
value="Remove"
accesskey="R" />
<input type="button" id="btnAddChild"
value="Add as child"
accesskey="C" />
<input type="submit" id="btnSubmit"
value="Create" />
</p>
</form>
</div>
</body>
</html>
---------------------------------------------
and people.css:
---------------------------------------------
body { font-family: sans-serif; font-size: small; }
h1 { color: navy; font-size: x-large; font-weight: normal; }
h2 {
color: green; font-size: larger;
border-bottom: 1px solid green; margin: 0 0 0.5em;
}
img { border: 0; }
#tree {
width: 25em; height: 30em; overflow: auto; float: left;
border: 1px solid #444; background: #eee; padding: 0.5em;
cursor: default;
}
#props {
width: 25em; height: 10em; margin-left: 27em;
border: 1px solid #444; background: #eee; padding: 0.5em;
}
#tree ul {
list-style-type: none;
margin: 0; padding: 0;
}
#tree ul ul { padding-left: 1.3em; } /* <label
id="code.dom.style.dynamic1"/> */
#tree li { padding-left: 0.1em; margin: 0.4em 0; }
#tree span { padding: 5px; }
span.group { font-weight: bold; }
#tree span.person { font-weight: normal; margin-left: 16px; }
#tree span.selected {
border: 1px solid #004; padding: 4px; background: #ddf;
color: navy;
} /* <label id="code.dom.style.dynamic2"/> */
#editor p { position: relative; height: 1.3em; }
#edtName, #chkIsGroup { position: absolute; left: 4em; margin-left:
0; }
#edtName { padding: 0 0.1em; right: 0; }
#edtName:focus, #edtName:active { border: 2px solid black;
background: #ffd; }
#lblIsGroup { position: absolute; left: 6.3em; }
---------------------------------------------
I''m using Prototype v. 1.6.0
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Spinoffs" group.
To post to this group, send email to
rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---
Christophe Porteneuve
2008-Apr-07 21:02 UTC
Re: Staff Manager tutorial from "Prototype and script.aculo.us" by Christophe Porteneuve
Hey, A cursory look at your posted code doesn''t make any obvious error jump at me; I would suggest grabbing the online version of the code [1] and checking whether it runs in your instance of IE (it sure does for me, both versions 6 and 7), and perhaps then diff against your sources? It''s obviously some sneaky typo somewhere. ''HTH [1] http://media.pragprog.com/titles/cppsu/code/prototype/dom/people.html http://media.pragprog.com/titles/cppsu/code/prototype/dom/people.css http://media.pragprog.com/titles/cppsu/code/prototype/dom/people.js -- Christophe Porteneuve aka TDD tdd-x+CfDp/qHev2eFz/2MeuCQ@public.gmane.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Tom
2008-Apr-08 00:31 UTC
Re: Staff Manager tutorial from "Prototype and script.aculo.us" by Christophe Porteneuve
You have an extra comma at the end of the nodes array - IIRC FF will
ignore this, wheras IE inserts a null as the last element of the array
nodes: [
{ id: ''item1'', name: ''ACME'',
children: [
{ id: ''item11'', name: ''IT'',
children: [
{ id: ''item111'', name: ''Sébastien
Gruhier'' },
{ id: ''item112'', name: ''Alexis
Jaubert'' },
{ id: ''item113'', name: ''Guillaume
Réan'' }
] },
{ id: ''item12'', name: ''HR'',
children: [
{ id: ''item121'', name: ''Sandrine
Daspet'' }
] },
{ id: ''item13'', name: ''Xavier
Borderie'' }
] },
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Extra
comma here
],
Tom
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Spinoffs" group.
To post to this group, send email to
rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---
websash
2008-Apr-08 02:49 UTC
Re: Staff Manager tutorial from "Prototype and script.aculo.us" by Christophe Porteneuve
Thanx a lot! I would never guess this extra comma can be the reason in
IE. Indeed, I started to debug it in IE and noticed it produced
''undefined'' on the last iteration. So I decided to insert a
condition
if(n){}:
...
init: function(id, nodes) {
var id = id || ''staff'' ;
var nodes = nodes || this.nodes;
nodes.each(function(n) {
if(n){
n.container = nodes;
this.createDOMFragment(id, n);
if (n.children)
this.init(n.id, n.children);
}
}.bind(this));
},
...
But now on removing the extra comma the condition is unnecessary.
to Christophe: I checked this version at
http://media.pragprog.com/titles/cppsu/code/prototype/dom/people.js to
make sure I haven''t made any errors on my own. But this sneaky comma
is there.
Btw. is there a decent debugger for IE like Firebug for Firefox? Maybe
you could recommend something.
Thank you
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Spinoffs" group.
To post to this group, send email to
rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---
Christophe Porteneuve
2008-Apr-08 06:52 UTC
Re: Staff Manager tutorial from "Prototype and script.aculo.us" by Christophe Porteneuve
websash a écrit :> to Christophe: I checked this version at > http://media.pragprog.com/titles/cppsu/code/prototype/dom/people.js to > make sure I haven''t made any errors on my own. But this sneaky comma > is there.Damn me for a bad memory! This was reported before, and I need to fix it (but fixing it online while the PDF and book are still faulty would cause even more confusion…). I''ll post on the book''s blog.> Btw. is there a decent debugger for IE like Firebug for Firefox? Maybe > you could recommend something.Alas, I''ve been searching for a decent debugger for IE, and could find nothing in the lightweight category. The IE Developer Toolbar is a giant mess, which I find mostly useless. I keep hearing MS Script Editor and VSExpress (or some such, not sure about the names) provide decent JS debugging, but it feels like a sledgehammer when you''re used to Firefox… Still, usually my contention with IE6/7 is entirely around CSS. I very seldom have JS issues as I use Prototype all the time, and when I do hit a snag, a couple alerts (coupled with hand-waving bafflement when discovering what IE can''t handle, which is usually DOM-side) are what it takes for me to move on. Good luck, then! -- Christophe Porteneuve aka TDD tdd-x+CfDp/qHev2eFz/2MeuCQ@public.gmane.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---