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 -~----------~----~----~----~------~----~------~--~---