2008-02-11:
[2:43] <jkridner> I just found another bug in my code.[2:43] <jkridner> I was doing a root.add(x) and a root.removeChild(x), but if my object had a parent other than root, this didn't work.[2:43] <jkridner> this._parent doesn't seem to work right. maybe it is this.parent?[2:45] <jkridner> hmm... docs seem to say the property is this._parent, but this._parent.removeChild(this) says that this._parent is null.[2:56] <midnightmonster> you can have a this.parent if you make it yourself, but the magic one is _parent[2:56] <midnightmonster> if your objects don't have that, perhaps you never add()'ed them to anything?[2:57] <midnightmonster> unlike with the relational db, your objects don't become children just by being the right type--you have to explicitly attach them to their parent[2:58] <midnightmonster> or you followed my suggestion about add()ing to the new parent before removing from root and it doesn't actually work well :-)[2:58] <midnightmonster> I've not really tried moving objects between parents yet.[2:59] <midnightmonster> do you have helmaTools.zip added as a code repository for your app?[3:00] <midnightmonster> 'cause once you do you should be able to access /shell or /whatever/shell and have a shell you can try experimenting with on the live data[3:02] <midnightmonster> lets you see the live properties of your object, too[3:02] <midnightmonster> so it's easy to just play and figure out the right sequence[3:21] <jkridner> it turns out I had messed up the objects a bit by editing... I was able to clean up the situation by editing the db XML files.[3:21] <midnightmonste1> yes--the ability to fiddle with the xml files both giveth and taketh away[3:21] <jkridner> :)[3:22] <jkridner> same with changing the object definitions while the database exists.[3:22] <jkridner> hmmm... it still seems to be deleting my old objects, rather than just removing them from root's children.[3:25] <midnightmonste1> *fiddling*[3:25] <jkridner> HopObject.removeChild is only meant to remove the one reference, right? as long as I do NewObject.history.add(this) before root.removeChild(this), the object should still be around, right?[3:26] <midnightmonste1> correct. I would expect it to stay around even if you didn't add it to history first--just as an orphan object[3:26] <jkridner> but the related .xml file is going away.[3:26] <midnightmonste1> that would indicate deletion[3:26] <midnightmonste1> trying with mine[3:29] <midnightmonste1> running this code on root:[3:29] <midnightmonste1> var c = this.get(0); c._parent.removeChild(c);[3:29] <midnightmonste1> results in Root's child list no longer containing its former first item[3:29] <midnightmonste1> but the xml entry for that item still exists with its parent still set to Root[3:30] <midnightmonste1> darned if I know how I can access it now, though[3:31] <jkridner> I'm seeing different behavior.[3:31] <midnightmonste1> you have the latest helma, right?[3:31] <midnightmonste1> 1.6.1?[3:31] <jkridner> no, 1.6.0[3:31] <midnightmonste1> ok, well that shouldn't make this kind of difference[3:32] <midnightmonste1> do you see the same if you run just that code snippet?[3:32] <jkridner> var x = new Page(); this._parent.add(x); x.history.add(this); this._parent.removeChild(this);[3:34] <midnightmonste1> little tip it took me a while to learn: you can have a constructor function, e.g., my Page constructor function looks like:[3:34] <midnightmonste1> function constructor(name,parent) {[3:34] <midnightmonste1> this.name = name;[3:34] <midnightmonste1> this.parent = parent;[3:34] <midnightmonste1> }[3:34] <midnightmonste1> *but when you change it you have to restart the app*[3:34] <midnightmonste1> constructors are the only thing that work that way--changes are ignored until app restart[3:35] <midnightmonste1> doesn't solve your present problem, but it's useful[3:36] <jkridner> k. I have a constructor function, but I only use it to fill in values. Also, it seems the _id value is junk in the middle of my function.[3:36] <jkridner> (for the new object)[3:36] <jkridner> I'd guess that is normal.[3:36] <jkridner> something like 't##'[3:36] <midnightmonste1> hrm. dunno[3:36] <midnightmonste1> do you have anything about _id in type.properties?[3:37] <midnightmonste1> (you shouldn't anymore now that you're not using the relational thing)[3:37] <jkridner> I do.[3:37] <jkridner> is it bad?[3:39] <midnightmonste1> I did this code in my wiki (which has no history feature yet):[3:39] <midnightmonste1> var x = new Page('doodle',this._parent); this._parent.add(x); x.add(this); this._parent.removeChild(this); this.parent = x;[3:39] <midnightmonste1> before: /poodle exists[3:39] <midnightmonste1> after: /poodle doesn't exist, /doodle exists, /doodle/poodle exists[3:39] <midnightmonste1> worked exactly as expected[3:40] <jkridner> var x = root.get("dummy"); x._parent.removeChild(x);[3:40] <midnightmonste1> what do you have in type.properties?[3:40] <jkridner> that worked as expected. I see the XML object in the DB, but the reference is gone.[3:40] <midnightmonste1> ok.[3:41] <jkridner> Root/type.properties:[3:41] <jkridner> _children = collection(Page)[3:41] <jkridner> _children.accessname = uri[3:41] <jkridner> _children.order = uri asc[3:41] <jkridner> user = mountpoint(User)[3:41] <jkridner> Page/type.properties:[3:41] <jkridner> _id = id[3:41] <jkridner> _parent = prev[3:41] <jkridner> _children = collection(Page)[3:41] <jkridner> _children.accessname = uri[3:41] <jkridner> user = username[3:41] <jkridner> uri = uri[3:41] <jkridner> body = body[3:41] <jkridner> lang = lang[3:41] <jkridner> time = createtime[3:41] <jkridner> alt = collection(Page)[3:41] <jkridner> alt.accessname = lang[3:41] <jkridner> alt.order = lang[3:41] <jkridner> history = collection(Page)[3:42] <jkridner> history.accessname = id[3:42] <midnightmonste1> ack! pastebin![3:42] <midnightmonste1> fyi, .order doesn't work in the xml db[3:43] <midnightmonste1> and user = mountpoint(User) doesn't do what you think it does[3:43] <jkridner> k. dumping .order.[3:43] <midnightmonste1> and you should just omit the _id = id line[3:43] <jkridner> how do I get to look at the users?[3:43] <jkridner> k.[3:43] <midnightmonste1> but I wouldn't expect any of those to solve the problem[3:44] <midnightmonste1> afaict, there's no way to map the application users into the url space with only type.properties stuff[3:44] <midnightmonste1> requires a little custom code[3:44] <jkridner> argh.[3:44] <midnightmonste1> (which sample I'm about to provide--it's not hard)[3:45] <jkridner> yeah, made those changes and my history objects are still disappearing.[3:46] <jkridner> for history.accessname, what would you think I should use?[3:47] <midnightmonste1> hard call. either revision #s or timestamps would be my choice, I think[3:47] <jkridner> since all of the objects would have the same 'uri' (name of the object/page), I thought that 'id' would be appropriate.[3:47] <jkridner> I could go with time stamps.[3:47] <midnightmonste1> id is not helpful since it's global to the app. I would expect to either have reivsion #s I could increment/decrement to do something useful or else timestamps that gave me some info[3:49] <midnightmonste1> for users, in root/type.properties, put:[3:49] <midnightmonste1> users = mountpoint(UserMgr)[3:49] <midnightmonste1> then in UserMgr, there is no type.properties but you need this code somewhere:[3:49] <midnightmonste1> function getChildElement(name) { return app.getUser(name); }[3:49] <midnightmonste1> that's it[3:51] <jkridner> k.[3:51] <jkridner> I still can't seem to reference my history objects.[3:52] <jkridner> for some reason, this time the old object stuck around, but I can't seem to access it via the 'createtime'.[3:53] <midnightmonste1> oh... right[3:53] <midnightmonste1> you can't.[3:53] <midnightmonste1> basically, it has to be either a 'name' (which can't look like a number) or an 'id' which is a number[3:54] <midnightmonste1> sorry, forgot about that[3:55] <jkridner> argh.[3:55] <midnightmonste1> *wonders what happens if he wiki-creates a page with a numeric name*[3:56] <midnightmonste1> uh, weird. it worked[3:58] <midnightmonste1> ok, semi-scratch the above about string vs number things.[3:59] <midnightmonste1> oh-hey! an easy way to simulate revision numbers[3:59] <midnightmonste1> well, sorta easy[3:59] <midnightmonste1> instead of history being a generic collection, make it a History object[4:00] <jkridner> Why do I want to define a new object?[4:00] <jkridner> I want everything to be a Page.[4:00] <jkridner> In order to add some new elements?[4:01] <midnightmonste1> it's so you can define a custom getChildElement on it[4:03] <midnightmonste1> this.get(n) where n is an int gets the nth child of this[4:03] <jkridner> I guess you can fully inherit from Page if you set it as the prototype?[4:04] <midnightmonste1> yes[4:04] <midnightmonste1> so your History.getChildElement function looks like this: function getChildElement(rev){ return this.get(1*rev); }[4:05] <midnightmonste1> now /foo/history/0 gets the first-ever version of foo, /foo/history/1 gets the second, etc.[4:07] <midnightmonste1> but building history like this is going to require a slightly different way than you were doing, 'cause I think the way you were doing would end up with the foo/history/1 having its own history prop with a single reference to foo/history/0 in it, then foo/history/2 has references to foo/history/1 and foo/history/0, etc.[4:07] <jkridner> I've now rearranged my code to make it more suitable for backing up the database and discussing: http://www.beagleboard.org/gitweb/?p=beagleboard.org.git;a=tree;h=ba6d1e803bf1d28652ef6adf840fe701265eaa3b;hb=fac73bf52b53590cd73cb4f8b3cc6aca2dfbdd92[4:09] <jkridner> too bad gitweb doesn't put helma.xsl in the right place for sharing. Maybe I could change objects to point to a shared helma.xsl to make it easy to view?[4:10] <midnightmonste1> *lightbulb moment*--lol--duh. that's what helma.xsl is for! I've been viewing the raw xml files in my text editor, didn't even think of that[4:11] <jkridner> :)[4:11] <midnightmonste1> so it's no problem for me[4:11] <jkridner> when I view the blobs with gitweb, they try to point to helma.xsl, but that doesn't work.[4:13] <midnightmonste1> gitweb seems nice enough, but I'm a little scared of git. I'm torn between reading how amazing and powerful it is and reading how weird and difficult to use it is[4:13] <midnightmonste1> plus my dev workstation is still windows xp, even though I deploy on linux[4:15] <midnightmonste1> (I was looking at the code before--now I see the problem with the db stuff[4:15] <jkridner> I really like git. I haven't looked back much at svn.[4:16] <midnightmonste1> you should just be able to copy/symlink the xsl to that path, no?[4:16] <jkridner> git under cygwin is still a little iffy, but works.[4:16] <jkridner> not really. gitweb is a cgi.[4:16] <midnightmonste1> I've not had a lot of luck with cygwin[4:17] <midnightmonste1> could do it with mod_rewrite[4:17] <midnightmonste1> or even just with a simple alias, I think[4:17] <jkridner> true. but I can also just view source. :)[4:17] <jkridner> I guess it might make browsing a bit nicer, but it seems like a real hack.[4:18] <midnightmonste1> putting in an alias wouldn't be, imo[4:18] <midnightmonste1> I can't viewsource of the broken xml pages in firefox 2[4:22] <jkridner> try manually right click then view source?[4:23] <midnightmonste1> that worked. neither ctrl+u nor view > Page Source did[4:24] <midnightmonste1> alright... I think what I'm going to do with mine is have a more-primitive-than-page type that just holds the same basic properties as a normal Page without most of the methods/actions. and I'll extend it to make a VersionedPage which will have a history collection and all the editing functions. and I'll also extend it to make a PageRevision type which will have no editing functions and tweaked display functions. the Vers[4:25] <midnightmonste1> and whenever the VersionedPage is edited, it will push a new PageRevision with the same data as its new self onto the HistoryCollection[4:25] <midnightmonste1> so the latest entry in history has the same data as current, and I don't have to play any games with parents[4:26] <jkridner> it is getting too complex for me. I'm planning to keep a lot of the information within the 'body' of my page.[4:26] <midnightmonste1> a lot of what info?[4:27] <jkridner> One of my missions here is to run HTMLCleaner on the 'body' and fetch/place RDFa entries out/into of it.[4:27] <jkridner> things like editing permissions.[4:27] <midnightmonste1> *lost*[4:27] <jkridner> I'll use something like dojo to provide a WYSIWYG editor...[4:27] <jkridner> and then I'll provide some buttons to add RDFa information...[4:28] <jkridner> RDFa is like microformats...[4:28] <jkridner> Microformats is really what I mean.[4:28] <midnightmonste1> (just googled)[4:28] <midnightmonste1> me: "oh, look! RDFa!"[4:29] <jkridner> information in my Page record that isn't part of the lookup will just go into the body.[4:29] <midnightmonste1> so you're going to trust the client to not screw up the RDFa, etc?[4:29] <jkridner> I needed to have 'lang' and 'uri' as separate columns, because they are needed for lookups.[4:29] <jkridner> no, I won't trust the RDFa...[4:30] <jkridner> I'll let client-side javascript code generate the entries, but I'll check them when the edit/create/etc. actions are called.[4:30] <jkridner> I'll run HTMLCleaner to make sure it is XHTML...[4:30] <midnightmonste1> parsing those in and out sounds so much harder than just setting properties[4:30] <jkridner> I can strip off tags I don't trust.[4:31] <jkridner> somewhat, but it can be made pretty generic.[4:31] <jkridner> and, it is a lot more flexible.[4:31] <midnightmonste1> not much more than using the XML store[4:31] <jkridner> but, the point is to make it something that can be fetched by external websites as well.[4:31] <jkridner> the information is right out on the page, so it acts as a web service API.[4:32] <jkridner> I just have some very simple edit/create methods...[4:32] <midnightmonste1> (the xml store will persist any property you set--it doesn't have to be listed in type.properties)[4:32] <jkridner> and all of the properties are RDFa.[4:32] <jkridner> sure, but then I'd have to create a presentation for it.[4:33] <jkridner> the RDFa will show up on the page using whatever presentation the user desires, as long as the syntax checker approves.[4:33] <midnightmonste1> I like better the idea of storing my data where I can easily see it and making the presentation where I want it with exactly the info I want to show[4:33] <midnightmonste1> your last line makes me think I'm missing something[4:33] <jkridner> it depends on your goal. I'm trying to give much more power to the users.[4:33] <midnightmonste1> "Whatever presentation the user desires"?[4:33] <jkridner> yes.[4:33] <midnightmonste1> I don't know what that means with respect to rdfa[4:34] <jkridner> well, the RDFa is independent of presentation.[4:34] <jkridner> so, you can place the properties anywhere within the body.[4:34] <midnightmonste1> I can image a browser extension that did useful things with rdfa stuff. If I had one, though, I can't imagine how your syntax checker would know or care[4:35] <jkridner> I'm trying to make a site that will automatically pull in project data from many hosting sites...[4:35] <jkridner> such as sf.net and code.google.com.[4:36] <jkridner> I plan on making methods that will automatically create pages based on updates to those sites...[4:36] <jkridner> and I don't want to try to figure out all my properties ahead of time.[4:36] <jkridner> your point about not being tied to that with the XML database is good.[4:37] <jkridner> still, I want to be able to create a large amount of properties, things like bug tracking fields, etc.[4:38] <jkridner> for me, it is just about keeping this wiki-style code as simple as possible.[4:38] <midnightmonste1> you're probably adding an order of magnitude (or more) more computation to the task if you ever need to work on those extra properties/fields in aggregate though[4:39] <jkridner> true.[4:40] <jkridner> I'd be adding another level of indirection for each record, since they would need to be converted back into XML from the quoted XML.[4:40] <jkridner> my intention is to only use those properties within the individual record, not typically aggregated.[4:41] <jkridner> if I needed to aggregate them, I'd create a proper new property in the HopObject and copy the value into that during the syntax checking.[4:41] <midnightmonste1> yeah. helma caches the last 500 (by default) HopObjects used in memory, so you can do some things very fast if the data you need is in a hopobject property[4:42] <jkridner> The value there is that I can get crazy on the client-side tools to create new RDFa entries, without needing to do much on the server side until I do decide I want to aggregate some behavior.[4:42] <jkridner> the syntax checker would allow many properties unknown to it to pass through without analysis.[4:43] <jkridner> so, it would be easy to input new fields from the client-side, perhaps using GreaseMonkey or just a lot of typing.[5:01] <midnightmonste1> I was worried about proliferating History objects... but if I use history = object(History) instead of mountpoint(History), then it would be possible to link .history of each version to the same object[5:02] <midnightmonste1> but since my pages can have actual children, I'm not sure what to do with that[5:02] <jkridner> but, you still have to create a new object type, right?[5:02] <jkridner> History, instead of Page.[5:02] <midnightmonste1> yeah. but maybe not more than one kind of page[5:03] <midnightmonste1> it doesn't bother me to have a History type. I always planned to[5:03] <midnightmonste1> I mean, I also have Users.[5:03] <midnightmonste1> they don't bother me[5:04] <jkridner> sure. it wouldn't be totally aweful...[5:05] <jkridner> I'm just making sure it isn't a snowball/pattern.[5:05] <midnightmonste1> in the only complete app/site I've so far built with Helma (http://preachingtheword.net/), I ended up using collection() rarely and mountpoint() (to have custom objects hold my collections instead of generic hopobjects) often. it seems better to me to make my collections a little smarter[5:05] <jkridner> I'd even like to see User be part of a more generic object type if I could. :)[5:06] <midnightmonste1> User can extend Page, I think[5:06] <midnightmonste1> I was planning to do that[5:18] <jkridner> I guess every object type to me is something else I'll have to explain to many of my users, if I get them. I want my users to help me extend the website itself. I'm targeting a very tech-y audience, though not very familiar with web stuff. I'm hoping to ease them into it with javascript, primarily on the client side.[5:19] <midnightmonste1> "All of these things that look different are really the same underneath" is appealing to a certain kind of geek/scientist/philosopher. it is not appealing to most people[5:21] <midnightmonste1> a history list (e.g.) is a component of a wiki page--it is not itself a wiki page, and it's confusing to think of it as one[5:22] <midnightmonste1> you wanted to make history not-a-type and not-a-page either... but that just means that if I want to extend the history, I can't[5:38] <jkridner> well, to a great extent I also simply wanted to be lazy. root.add(newObject); newObject.history.add(oldObject); root.removeChild(oldObject); just seemed very simple to me.[5:39] <jkridner> I wanted to make this operation very fast in the database, simply leave the entry and update some of the pointers.[5:40] <jkridner> the need to walk the history list doesn't seem that painful to me.[5:40] <jkridner> is there any reason I even need to use .history? couldn't I just do newObject.prev = oldObject?[5:41] <midnightmonste1> since you're doing it like that, yes, that's what you should do[5:42] <midnightmonste1> I was advising (and am implementing) keeping a history collection. but if you like the single-linked list thing better then a history collection is just extra indirection and waste[5:42] <midnightmonste1> it means the web location of three revisions ago is: /foo/prev/prev/prev, though[5:43] <midnightmonste1> and it also means no permalinks for previous versions[5:43] <jkridner> true.[5:44] <jkridner> that is probably a good enough reason not to do it.[5:44] <midnightmonste1> 'cause /foo/prev might be revision 4, but once you change again, /foo/prev is revision 5, and 4 is at /foo/prev/prev[5:45] <midnightmonste1> what's the quote?... "For every complex problem, there is a solution that is simple, elegant, and wrong." :-)[5:45] <jkridner> hehe, I'm not familiar with that quote. :)[5:46] <midnightmonste1> H. L. Mencken[5:46] <jkridner> I just want to try to get as close as Newton did. ;)[5:46] <midnightmonste1> gtg for now.[5:47] <jkridner> thanks for the chat.[6:35] <midnightmonste1> sweet. history works now[6:37] <midnightmonste1> and root.latest is a collection that keeps a list of updated pages, most recent first[6:53] <jkridner> is it something you are sharing?[6:55] <midnightmonste1> no convenient way to do so atm[6:56] <midnightmonste1> I never learned how to setup my subversion for anonymous viewing for just part of the repository[6:57] <midnightmonste1> (do you know?)[6:58] <jkridner> not for just part of the repository.[6:58] <jkridner> i have done anonymous browsing support, but it has been over a year now.[6:59] <jkridner> Are you using Apache?[6:59] <midnightmonste1> yeah[7:00] <midnightmonste1> gtg, but I'm joshua at papercrown dot org. email me and I'll send you a zip if you like[7:02] <jkridner> k. thanks.[18:12] <hypersmil> hi, i have a helma/javascript/regexpr problem: /(?=[^\r])\n/ seems to match no matter which character is in front of \n has anybody an idea why this happens - i tried it already in the other direction /\r(?=[^\n])/ and there the regexpr. works as expected[18:14] <midnightmonste1> in plain english, what are you trying to do?[18:16] <hypersmil> i try to match a \n not after an \r -> this doesn't work and i try to match a \r not before a \n which seems to work[18:18] <midnightmonste1> so why not /[^\r]\n/ ?[18:19] <midnightmonste1> ok, got it[18:21] <hypersmil> sorry, i was not exact enough -> i try to replace it "ASDF\n".replace(/[^\r]\n/,"X").toSource();[18:24] <midnightmonste1> bizarrely/not bizarrely, I see the same behavior with simple string[18:24] <midnightmonste1> true == /a(?=b)/.test('abc')[18:24] <midnightmonste1> false == /(?=a)b/.test('abc')[18:24] <midnightmonste1> strangely enough, that appears to be correct according to spec[18:24] <midnightmonste1> the behavior I saw, that is[18:25] <midnightmonste1> the (?=whatever) thing is a "lookahead"--can only be used *after* a pattern, not before[18:26] <hypersmil> -> /""(?=[^\r])\n/[18:26] <hypersmil> works[18:27] <midnightmonste1> what's "" ?[18:29] <midnightmonste1> this'll work, too: "abc\n".replace(/([^\r])\n/g,"$1X");[18:31] <midnightmonste1> bbl[18:32] <hypersmil> thank you
In the channel now:
Logs by date: