Integration • 36:16
Wiki Server provides ready-to-use collaboration tools right out of the box. Learn how to tailor Wiki Server's built-in themes to include your organization's look and feel and how to extend out-of-the-box collaboration scripts to include your own web services.
Speakers: John Anderson, James Craig
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it may have transcription errors.
All right, hello. My name is John Anderson, and I'm here today to present Customizing and Extending Your Leopard Server Wikiserver. My name is John Anderson. I'm the Senior Software Engineer and, I guess, iManager of the Wikiserver team. So before we get into how to actually extend the Wikiserver, I want to get a little bit into what the Wikiserver already has to offer and some of the great features that the Wikiserver has. And first and foremost, the wiki server has an excellent WYSIWYG editor. This allows somebody to actually create a wiki and participate in a wiki without having to know any markup and without having to do anything tricky like square braces or alternating caps to make links. So we make all that stuff super easy. But if you're somebody like me that actually thinks in markup and mentally builds every billboard he sees in HTML, we do actually have an HTML mode. You can switch back and forth. And we actually clean up your HTML and close/unclose tags, try and make it basically validatable.
And so that's a nice feature, but you may want to actually add some flexibility in that, and we'll actually get to that so that you can actually go into HTML mode and add some special tags. We actually applied this WYSIWYG editor to our blog server as well. So creating blog entries with rich text and images and even embedded movies is a piece of cake. In addition to that, we offer mailing lists, mailing list archives, which are searchable, of course, and a terrific web-based group calendar.
Now, of course, you want to take this wiki and actually make it look like the rest of your site. You're going to want to take it and add custom tags, as I discussed earlier, to allow through the whitelist. We actually provide at least a dozen professionally designed themes that look great. But maybe you want to do one that actually matches the rest of your web presence. And we'll get a little bit into how to do that as well. You may want to add links to the sidebar of your group homepage. and we'll discuss that a little bit as well.
And lastly, you may want to connect the wiki to your external applications so that you can get data into the wiki and pull data out. And we'll be having a great demo of that as our last demo. So the first way that you can Some customization in the Wiki, without having to write any code or do any manual configuration, is just to use the Settings page. This is where you'll choose between those dozens of great themes. You can upload a banner of your own. We'll scale it for you. You can create a sidebar, which performs a search based on any tag you want. And of course, you can enable podcasting in the blog.
That's kind of basic, so the thing we're gonna get into now is how to do some more advanced things with the server. And the first thing that you may want to do is allow additional tags through the HTML scrubber. And this is going to allow content that normally would get scrubbed out when you save the pages to disk. And that could include things like Flash plugins with video, iframes with content from other sites, JavaScript, and custom tags. So I don't know if you can read the JavaScript dialogue there, but it says, "I have your session ID," and it lists the session ID and then says "Pwned." So how many of you here have heard of cross-site scripting?
A few of you. About a third of them server engineers over there. So, Cross-site scripting refers to the ability of one wiki user, in this particular case, to run a script on somebody else's machine using their context. So it's definitely something you want to watch out for when you're allowing things like plug-ins and scripting that you may not want people to be able to run code on other people's machines. That's why we keep it off by default, but provide a way for you to turn it on.
So the next way you might actually want to customize your wiki is by using a custom theme. And that actually allows you to change the presentation of your wiki and add functionality as well. And to illustrate how a theme actually works, I'm going to go over what actually comprises any page that comes out of the wiki server.
So the first thing we send out in the HTML are link tags for the theme's CSS. So this is where you can place any of your color choices, borders, anything that basically defines the look and feel and makes it match up with the color palette and general theme of your site.
The next thing we send out is the system CSS. And this defines the basic page metrics for everything from the basic page layout to all of our JavaScript controls, such as dialogues, pop-ups, the WYSIWYG editor. We send that after the theme CSS so that it's a little bit more difficult to accidentally override something that our functionality depends on. But there is actually a way to get around that. And there's a couple methods. And James will get into that later on.
The next thing we send out is the system JavaScript. And this concludes all of the interactivity that you see on the wiki. So the WYSIWYG editor, the tagging, comments, history, basically all the functionality with which you interact with the wiki server is sent out at this point. And it's all added via JavaScript after the page loads.
Next, we send out script tags for your theme's JavaScript. This means that you can put any JavaScript in your theme, and it will get automatically added to every page that comes out of the Wiki server. And finally, we, of course, send out the content of the page itself.
So that's what makes up a page, but what makes up a theme? It's basically a bundle. It's a folder full of various files that describe the theme's look and feel and its functionality. The first of those files is actually a thumbnail, so that when the user chooses a theme in the Settings page, they'll be able to see a picture of what the theme's going to look like.
The next thing we include is a screen.css and a print.css. Those define the print and screen style sheets for your theme. Next, we have a theme property list. This contains metadata about the theme, such as a desired banner size to scale to, a display name, and a list of sidebars.
And finally, you can include any JavaScript you want, and anything with a.js extension will get added to every page coming out of the Wiki server. But to back up just a little bit, I'm going to get into the different sidebar types that you can actually specify in your theme's property list.
So there's different sidebar sections. The one that's probably most common for people to use is a search sidebar section. And in this, you can define any kind of search you want based on keywords or tags or both. Define the sorter order, and it will automatically populate the sidebar on the group home page and reload it without refreshing the page.
You can also add a list of static links to your theme. So this means that you can have links to other parts of your site, basically any links that are outside of the Wiki that you just want to add and have them show up statically every time you load the group home page.
There's a calendar sidebar section, which always displays upcoming events from that group's calendar. And then, of course, we add an admin sidebar if somebody is logged in as an administrator or a group owner. And this provides the links to the settings page, as well as a way to edit tags in bulk and find pages that users have deleted.
So the first thing you may want to do in your theme is define CSS. And that's what allows you to turn this-- into this. Now, I'm kind of hoping you're going to do something a little more easy on the eyes, but for the sake of the demo, I wanted to do something a little bit drastic, and I also tend to be a little snarky, so... To show something a little bit more realistic, I'm going to bring up James Craig to demo CSS in Athene.
So can I get the demo machine? All right, so I've got my standard install of Leopard Wiki server running here. And I'm gonna pull up Safari. I'm going to size this window back down a little bit. So I pull up Safari, and I've got a list of groups here. So I'm going to go to the first group, and I want to customize this a little bit. Now, John mentioned that you can do anything you want with CSS, and we have some documentation out there. It's the first result in Google for extending your wiki server. I encourage you to read it. One of the ways that you can do it is to start with our default wireframe wiki theme, And that allows you to do pretty much anything you want. It's kind of a start from scratch CSS theme. But the other thing that you can do, and this might be more beneficial for you guys, is to take one of our existing shipping themes and just change a few properties of it. Essentially piggyback off of our CSS and change a few things. And so I'm gonna pull up Dashcode just to show you what this theme looks like.
So I've got my theme1.wikitheme. This is in the sample code that you can download for this session on the conference site. It's also on the ADC site. And among other things in there, we've got our preview PNG, and that's just a little thumbnail that's going to show up on the settings page. We've also got the theme plist, and this is just an XML file. Now, what John mentioned, you can you - Do a lot more with this, but I've kinda stripped it down to the bare minimum. And what we've got in there, we've got a version.
We've got a display name, and that shows up along with a thumbnail on the Settings page. And we have this name, which is just a unique identifier. And it can really be anything you want, as long as it doesn't conflict with one of your other themes. The other things that we have in this theme folder are print CSS, and this one just imports the default CSS. You might need print CSS, for example, if you have a theme that's got a black background with white text. Well, it turns out that backgrounds don't print very well. They don't print on most browsers by default, so white text doesn't look very good on a white piece of paper. So you can change those CSS. It's a different media type. You can change it and do what you want with it. In this case, we're just using the default one.
Now this next one is Screen CSS. So this is what's going to show up on your iPhones and your desktop browsers and stuff like that. And this first line up at the top just imports the default styles for our existing theme. So as you can see, we've already got this existing theme in there. It happens to be called Horizon Blue. I'm just importing all the CSS from that one. And in addition to that, I'm importing a couple of local styles just to change a couple of properties. And that particular file is this one right here called mystyles.css. So this is all we're going to do for the demo, just change a couple lines of CSS.
So the first one defines a background color for the page. This is a kind of a hex value for a slight yellow. And the next one, we're actually going to rearrange the order of the columns. So I'm actually going to close this because this isn't the live file, and I'm going to open the live file. We're going to edit for the server. So it's just that one, there's a couple lines of code. Now again, this first line changes the background color. So because I'm logged in as an admin, I'm going to go to the Settings page.
And I'm going to edit the settings page, choose the new theme. And all your custom themes show up down here at the bottom. So we've already got these two installed. So here's my thumbnail. Here's the display name. I'm going to choose that one. Click OK. You can already see in this preview mode that it's changed the background color. And that's pretty bright yellow on that monitor.
And once I've saved it, then you can see, OK, well, it's changed it for every page on the site. Here it is on the blog, even though there's no content. Here it is on the Wiki page. So it's across the site. But you might have noticed that the default order of these main two columns here hasn't changed.
So I'm looking at the code, and this is the live code. And I'm thinking, OK, well, this is column secondary, which is the second one here. And I'll show you how I figured out what those classes are. But I'm not sure what's going on. So there's this preference in Safari. If you go to the Advanced tab in Safari, you can show the Develop menu in the menu bar.
And once you enable that, then you get this secondary function on a mouse click. Or on a secondary mouse click, you can say Inspect Element. And this pulls up the WebKit Inspector. It's a really cool debugging tool. And I'm going to click on this DOM node here. That's the column secondary. So again, that's the sidebar contents.
And I can look down in the computed CSS, and I can see that here's where I defined my float left. This is my new mystyles.css. But right above it, it's been overridden by float right. And if I look in the file that's calling that, that's required compressed CSS. This is one of our system styles.
So this is what John was talking about before. In a couple places, we want to make it difficult for you to accidentally break some of our default functionality. So if you're changing the editing toolbar or some of the main layout functions or mainly out of the page or alert dialogues, that kind of thing. We want to make it difficult to override, just at the beginning, but let me show you how to do it.
So if we look at the rules, we've got one called groupHome.columnSecondary. That's the main part of this. And it's set to float right. And then in ours, it's groupHome.columnSecondary. And it's set to float left. And because the system styles come after this, then it wins in the order of the cascade. So in order for me to override this, I'm gonna have to make a CSS rule that is more specific than that other one that has two classes. So instead, what I'm gonna do, is I'm gonna say this is a div with a class of column secondary that is in another thing with a class of group home. And that's a more specific rule, and I'm gonna do the same thing for the primary column. I'm gonna save it and kill the WebKit inspector.
is refresh the page and it flips the columns. So if you're, in case you're running into any, oh, thank you. So in case you're running into any CSS debugging, you can go in and check out the order of the cascade. And John asked me not to say CSS specificity, but that's the word to search for if you want to know more than that. Thanks a lot.
Thanks, James. So as James mentioned, the WebKit Inspector and some of the other similar tools on other browsers are really useful for debugging CSS. And you'll find it invaluable when something in your CSS isn't showing up. You can find out exactly why and how to be more specific. So that's a great tool for you to use.
Now, you may want to do something more than just change the presentation, change the look and feel. You may want to actually add functionality. We had somebody in the lab yesterday that wanted to add server status to the wiki. Things like that are where you'll actually want to add custom JavaScript. And this is where you can add additional functionality and markup to your pages.
And the way you do this is by overriding a method that we implement called prepare. And prepare is a little bit different from onload in that onload will actually only run once the page is entirely rendered and all of the images have been loaded. We found in our usage that sometimes that would make the toolbars and some of our additional functionality that we were adding to the page via JavaScript to show up seconds or, if somebody has a page of 100 images, maybe minutes after the page has displayed. So the prepare method will actually run as soon as the document object is available. There is a method called onDomContentLoaded that is fairly similar, but it doesn't work on all the browsers. So prepare is a great cross-browser way in the wiki to add content to your page immediately as soon as it's visible to the user. And that way they don't see the lag that is typical in adding things to the page using JavaScript.
So after you get called with your prepare method, you use the W3C DOM to modify your document to add whatever you want, remove things, move them around, add your own functionality. And then of course you can add your own AJAX hooks to pull data from servers if you need to.
We include several JavaScript libraries to help you with this and to make your life, and of course ours as well, a lot easier. Those libraries include Prototype and Scriptaculous. You can use Prototype to traverse a DOM really easily, and I'll show you an example in a second. You can use Scriptaculous Builder to build elements with a lot less code than if you were just creating nodes manually in the DOM. And you can even use Scriptaculous Effects to animate in some of your new functionality if you want to have some added pizzazz.
To show you an example of how this might be done, I have some code here that adds an additional link to the footer of every page. So the first thing I'm doing is I'm stashing away the original prepare method. We, of course, implement prepare ourselves so that we can add the toolbars and set up the WYSIWYG functionality and everything else that's interactive. So before you override our prepare method, you'll, of course, want to stash away the original one, and that's what we're doing in this first line here.
Then we implement our own prepare method. And the first thing we do in that prepare method is call the original one that we stashed away. And now we'll add all of the toolbars and everything, just like before. The next thing we're using is-- the next thing we're doing is using prototype to traverse the DOM and find the first unordered list under the page footer element. So this is an example as to how the included libraries make life a lot easier for you in finding a particular part of the page, traversing to it, and adding something to it yourself.
And then I actually said to use the W3C DOM, and I'm cheating a little bit here for brevity's sake. I'm using inner HTML to just add another list item to that unordered list in the footer with a link to Apple's site. Now to show a little bit more of this in practice, I'm going to bring James back up for a demo of custom JavaScript in a theme.
Thanks again, John. So we've got the same default install. standard install. I'm going to bring up Safari. And we'll go to our second group here with the hypno toad. And I've got this blog that I think is filled with terribly, terribly interesting content. And I have a ton of readers and they all think it's terribly interesting too and they want to share it. And so I want to add a dig link. You guys are familiar with the social networking linking site, Digg. So I want to add a dig link to every one of these weblog entry pages. Now, I don't want to put it on this main blog listing here.
And I don't want to put it on the Wiki page. I don't want to put it on my calendar page. I just want to put it on the individual blog entry. So I'm going to click on one of those entries. And you can see that I've just got a regular Wiki page here. It's got the title and some content and an image in the toolbar and paginator control and the comment functionality. It doesn't have a dig link yet. And I don't want to change anything about the way this page looks. I just want to add some JavaScript. So I'm going to show you how to do that. So I'm going to pull up Dashcode again.
And we'll move to the second theme. Now this one is just like before. We've got a preview thumbnail of what it's going to look like. We've got our plist that has -- it's just stripped down to the bare minimum because I don't need to do anything with custom sidebars. I'm going to have a banner on this one. So it's just got the version. It's got a unique identifier for the name. And it's got the display name that's going to show up on the settings page when we choose the theme.
And again, we've got our print CSS. It just defaults to import the shipping print CSS. We've got our screen CSS. And this one is almost the same as the last one. It imports the horizon green theme, because that's the one that we're using on this particular blog. And it does nothing else. Like I said, I don't want to change any of the CSS. I'm just going to import all the CSS from one of the existing themes. And so the only thing special that's in this theme directory is this other file over here called add_dig_link.js. It can be called anything, but it does. As long as it has a.js extension, then the Wiki server is gonna know that it's a JavaScript file, and it's gonna include it on every page.
So as John showed you, we've got our original prepare function. We store it away. And then we override that original prepare function and execute the original one. So what this is going to do is it's going to set up our toolbars, and it's going to set up the dialogs and the comment functionality. It's basically going to keep the rest of the Wikiserver working. And then in addition to that, you can add your own code.
So all the rest of this is in a conditional. And this conditional, I'll explain the shorthand here. This is using the prototype dollar method, or dollar function, to get anything with an ID of wikid. and check to see if it has a class name of WeblogEntry. So how did I find this? I'm going to go back to the wiki page here, and I'm on the WeblogEntry page. I'm going to inspect the element.
I'm going to go up and look at the body tag. And this body tag, you can see right here, has an ID of WikiD and a class that includes web log entry. And so that's what I'm going to do. Any page that's just a web log entry, because I don't want to run this on the calendar. I don't want to run this on the main Wiki page. I don't want to run this on the main web log listing page. It's only going to run on this particular page.
And so the next thing that's running inside this conditional, I set up a dig link that just goes off the dig site and uses whatever the window location URL is. And then I use some more shorthand here. This is builder.node. Some of you guys might be familiar with this. This comes in builder.js, part of Scriptaculous, and a prototype library. And what this is going to do, it's going to set up an A element, that's an anchor, and give it this dig href that I set up the link. And it's going to put this text, dig this, in that text link. We could have made this an image one. We could have done, we could have, you know, had it be the iframe of how many times it's been dug and whether or not the user has dug this page. But we wanted to keep the example pretty simple.
And the last thing this does is it inserts that element before the paginator widget. this thing right here. So we're going to insert that link right before that. So I'm going to go back to the main Wiki page, go to the settings because I'm logged in as an admin, and I'm going to change the theme.
Again, we drop down here to the bottom. Here it is. We select it, save it. Looks exactly the same as it did before. The only difference is that in that list, I know that that's the one that said something about adding a dig link. So if I go to the main Wiki page, nothing happens. If I go to the main blog page, the listing page, nothing happens. But when I go to one of the individual web blog entries, then I show up with this little dig link right here. It runs right as the page loads, adds that DIG link. And this one is running off a local host. So if I clicked it, it would go to the DIG website. But since the DIG server can't see it, then it's going to think it's a bad link. If you were to take the sample code, which is, again, available on the conference site and from the ADC, and run it on your own public web blog, it's going to work right out of the box. And I encourage you guys to mess around with it, because I think you guys can do much more interesting stuff than this. So thanks a lot.
Thanks, James. So along with debugging your CSS, you're probably going to want to debug your theme's JavaScript. And if you're anything like me, if your code works the first time that you try it out, you're a little terrified. Almost all code breaks the first time you try it. So debuggers are crucial here. And in the latest nightlies of WebKit, there's an excellent debugger built right into the inspector. You can set breakpoints, and it's super fast. So it's much improved, in my opinion, over the old Drosera stuff, and it's definitely worth checking out. And it's my debugger of choice now.
But you can see here that the code isn't always going to break in your own JavaScript code. Something may happen, something may cascade, and the bug may actually occur in our code. And I dare you to look at this line of compressed JavaScript code and actually figure out where the problem lies.
So there is actually a way to work around this. And you can go to a URL on your server, which is /collaboration/debugmode.html. That brings up a web page with a checkbox for turning debugging mode on. And when you turn that on, it sets a cookie in your particular web browser, which will then cause the server to send out uncompressed JavaScript. So instead of seeing this in your JavaScript debugger, you see this, complete with comments and much, much easier to find out what's going on. And in this particular case, I actually deliberately broke the page by removing the link search element, which it's looking for in this line of code, and then falling over.
So by turning on debug mode and using the JavaScript debugger, you're going to have a great way to figure out what you did to break things. So the next step that you may want to do is you actually may want to change the HTML that comes out of the server.
And you can do this by creating custom XSL templates. And if you take any of the system's XSL templates and copy them into your theme, it'll use the ones in the theme instead of the system ones. So this allows you to change the HTML that actually gets generated by the server. Now when is this useful? It's useful for browsers in which JavaScript is disabled. And that's the one case in which this is absolutely necessary. But I will give you the caveat that without JavaScript, there's no editing of the Wiki. It's a read-only system at that point. But again, if you want to be able to make the changes without JavaScript, XSL is the way to do it.
This is also one of those things where I'm kind of saying, don't do this, but here's how to do it. And the reason for that is that, for one thing, it's not useful for adding dynamic content to your pages. XSL is a transformation language, so it's taking a context XML document and turning it into a web page. So if there's a piece of information that isn't on the page and you wish to add it, JavaScript is the way to do that and not XSL, because that information isn't there, and therefore it can't be transformed into anything else. Thank you. The other thing to watch out for is that it's not future-proof. When you take Apple's template and you copy it into your theme, it's going to use the copy of the template that's in your theme now and not the Apple one.
This means that if we send out software updates with bug fixes or enhancements, you won't see those because it's going to continue using the one that you've used in your theme. So you at least want to make sure that you track it so that you can look for diffs and patch them into your own XSL templates.
And lastly, you'll definitely want to exercise caution when actually removing elements from the page. As you saw earlier, I removed the link search element using XSL, and that made the JavaScript fall over because it was expecting that element to exist. So if you actually want to have elements not show up on the page, the best way to do that is to turn them off using CSS and using display none. That makes them invisible to the user. but any JavaScript that depends on it will still work.
So that's a little bit about XSL. And again, I kind of issue the edict or the preference that you're going to get a lot more done and be a lot more future-proof if you use JavaScript rather than XSL to change your markup of your page. But lastly, the one thing that you may want to do is talk to the Wiki server from other scripts or other applications.
And there's two great industry standard ways to get data out of the server and to put data into the server. So firstly, if you want to pull data from the server, you can use RSS and Atom for that. And there's lots of different scripting modules that handle RSS and Atom. And every page that you look at has a feed, at least one feed. And every search that you perform also has a feed. So you can perform a search that does what your script needs, grab the RSS feed, and use that for your scripts.
And if you want to push data into the server, we also handle a couple of industry standard methods for that, and those are MetaWebLog and AtomPub. And you can use either of those to add wiki entries and blog entries and get data into the server. And to show a really cool demo of what you can do with the APIs, I'm gonna bring James Craig back up here.
Thanks again, John. So because we're not actually going to be showing the code in this sample, it's more than will fit on a couple pages. I just want to talk to you about what's actually going to happen. So I've got my phone up here. And I'm going to take it out of airplane mode.
so that I can actually use this. And I'm going to take a photo of you guys, hopefully. We'll bring the house lights up in a little bit. And I'm going to email it to my.mac gallery. Eventually this will be mobile me, but we set this up a while back. So I'm going to email it to my.mac photo gallery. And I've got a script that's running on this server, this local server. It could be running anywhere. It could be an external. It's usually on a server, but it could be running anywhere. And what that's doing is every now and then that's checking to see if there's a new image in this RSS feed.
And so when it checks to see if there's a new image, it gets that image back down, pulls it down, it does a little bit of image manipulation, and it pushes it off to the Wikiserver blog via metaweblog. So can I bring the house lights up a little bit? Can I get somebody to bring the house lights up? Maybe. That's okay. I'll take a photo of this and you can kind of see you guys in the background. And I'm going to email this off. Let's see. send to my WWDC demo. It creates an email. I'm sending it right now. Still sending.
And I'll go to the group. And it may or may not be here already. So it's not there. Let's see if it's still sending. Hey guys, quit using your iPhones, because then I can get out. All right, it looks like it's sent. And it's not there yet, but in the meantime, I can show you some vacation photos of mine with impossibly beautiful people if you'd like to see them. The internet is a truck. It's a series of tubes. So it's running a little bit slow, but we'll get it. There it is. I'm in your demo. So I got a little plushy animal and you guys in the background.
And that's it. So thanks again, guys. OK, so as James showed you, there's actually a number of really cool things that you can do using the APIs. And so in summary, there's a number of different ways that you can take the Wiki server and make it yours. You can use the built-in customizations from the search page. You can design your own CSS in a theme. You can add JavaScript in a theme to add functionality.
As a last resort, you can change the XSLT to change the HTML that's generated by the server. And, of course, as James showed you, you can use the API to get data into and, of course, pull data out of the server and integrate it with your own other applications.
So for more information, I'd encourage you to talk to Mark Malone. And the other thing is that if you go to the attendee site for this particular course, you'll find links to the PDF, which describes in detail how to accomplish some of the things that we've done today, and also provides links to the documentation for Prototype and Scriptaculous. And with that, I'd like to bring the Apple engineers up for Q&A.