Join a conversation, pose a question, or help a fellow user: The best place to discuss all things Karelia.
You are not logged in.
Pages: 1
Comment w/in "SVPlugin.h":
To persist your reference to the page, override -serializedValueForKey: to use the page's -identifier property.
Likewise, override -setSerializedValue:forKey: to take the serialized ID string and convert it back into a SVPage using
-pageWithIdentifier:All of these methods are documented in SVPageProtocol.h
Neither is in "SVPageProtocol.h".
"-pageWithIdentifier" WORKS as expected, but generates a compiler warning. That the plugin:
may not respond to '-pageWithIdentifier'
Can the API be updated to eliminate the compiler warning?
Sean
Offline
Oh dear, I thought I'd removed all such mentions from the documentation. This API was my original intent, but it turned out not to be fully feasible when you consider handling of deleting of pages, as well as undo/redo.
Some of those APIs still exist privately, but DO NOT depend on them, as I am likely to remove in a future update.
Can I ask what you're after this for? In general, if you need to refer to another page, an Index plug-in is the best choice.
Offline
Hi Mike:
I need a persistent reference to the collection INTO WHICH the plugin is first installed, so that I can reference a "home base" for all further relative URL determinations. It also has to persist between launches.
My plugin is a pure sidebar pagelet, only pertinent to collections w/indexes (serves no purpose at all as either a page or callout) so page deletions are not an issue.
Perhaps I'm overlooking a simpler method.
Sean
Offline
I need a persistent reference to the collection INTO WHICH the plugin is first installed, so that I can reference a "home base" for all further relative URL determinations. It also has to persist between launches.
My plugin is a pure sidebar pagelet, only pertinent to collections w/indexes (serves no purpose at all as either a page or callout) so page deletions are not an issue.
Perhaps I'm overlooking a simpler method.
Bear in mind that users have complete control over which pages your object/plug-in appears in the sidebar of. They might move it to another page, which would render the plug-in's idea of its "home base" invalid I'd have thought? If you use an index plug-in, (generally with Index Inspector too), it will automatically attach itself to the nearest collection when inserted, but then the user is free to adjust that from the Inspector later if desired.
How are you trying to derive these relative URLs? In general, we try to do that completely for you with the -[SVPlugInContext relativeStringFromURL:] method. When generating HTML, the context informs you which page is currently being generated. You can find out its URL from there if you really need to.
Or are you wanting to present these URLs in the Inspector in some fashion, rather than the HTML?
Offline
Mike:
Bear in mind that users have complete control over which pages your object/plug-in appears in the sidebar of. They might move it to another page, which would render the plug-in's idea of its "home base" invalid I'd have thought?
Right you are, I hadn't considered "moving" the plugin!
If you use an index plug-in, (generally with Index Inspector too), it will automatically attach itself to the nearest collection when inserted, but then the user is free to adjust that from the Inspector later if desired.
Hmm, I'm not creating an index per-se, just traversing an existing collection hierarchy, and displaying the "map" based on user control selection. I'll look into it though, it may suffice to grab a "home base" reference.
How are you trying to derive these relative URLs?
Sorry, I mis-spoke about that, relative URLs are not the issue. Since the plugin could be installed at any depth w/in the "site" heirarchy, it needs to know where to start & stop traversing. Needs it specifically on relaunch via "awakeFromFetch".
Of course, I'm trying to migrate this from SV1.5/6, so I may be doing it the hard way, when simpler methods are available in 2.x! I will investigate.
Thanks! Sean
Offline
Ah, so you're basically deriving a sitemap-esque list based on the contents of a collection? You definitely want an index plug-in for this.
Sandvox 1 had the concept of an index as "the bit of a collection page that lists the content". Whereas 2.0 defines it more as "an object whose task is to list the content of a collection". A collection can have multiple indexes associated with it. I think it is a more complex model to wrap your head around, but extremely powerful.
Offline
Mike:
Ah, so you're basically deriving a sitemap-esque list based on the contents of a collection? You definitely want an index plug-in for this.
That's essentially it, with user display options.
Must admit it's my own fault for not trying an Index plugin to begin with. For some reason, I've been thinking all along that SVIndexPlugin was a direct subclass of NSObject, so not appropriate (probably from the old sv1.x mindset). I see now it's subclass of SVPlugin, so should fold in fine, argh!
Made a quick (unsuccessful) attempt to covert over yesterday, but not enough time to do it right. Have other priorities for the next few days, but will get back to it.
Thanks! Sean
Offline
Mike:
Subclassing SVIndexPlug does work to give me a permanent reference, but comes with it's own undesireable baggage.
It now always installs as a "main content" element, not directly to the sidebar, so I have to add a placeholder instructing the user to move it to the sidebar.
How can I tell it to go straight to the sidebar?
Sean
Offline
How can I tell it to go straight to the sidebar?
Sandvox places plug-ins based on a combination of their initial width, and the user's selection. Override -makeOriginalSize to set the width to 200 and your plug-in should always end up in the sidebar.
Offline
Sandvox places plug-ins based on a combination of their initial width, and the user's selection. Override -makeOriginalSize to set the width to 200 and your plug-in should always end up in the sidebar.
Well, that was dirt simple! I would never had made the connection between size & placement.
Thank you Mike!
I have run into a couple of other issues with using an index plugin though, but the descriptions are rather long-winded, so will be another day or two before I can explain them
Thanks again! Sean
Offline
Mike:
re: the "issue" I've come across with "indexedCollection". While it works fine for my plugins functionality, it does not literally return "the page into which the plugin was inserted".
Keep in mind, my plugin is only valid when inserted into a Collection. I had planned to write a "warning" placeholder in the event the user had inserted it into a Page.
But, when inserted into a page, "indexedCollection" backtraces up the hierarchy, and returns the Pages "parent" Collection, so can't be used to validate insertion.
Perhaps that's the way it's supposed to function?
This led me try a different approach, using "pageDidChange" to grab the initial reference (which is where I had been grabbing it prior, using "pageWithIdentifier"):
Subclassing my inspector from "SVIndexInspectorViewController", produces the "Collection to Index - Drag target to a collection in the site outline" control, which is unneccesary, and I don't want. So I left my inspector as standard "SVInspectorViewController", which eliminated the "drag to target" requirement.
But, if I include "pageDidChange" (with only an NSLog to see that it has called) w/either the standard or index inspector view controller, the plugin does not load. Instead displays the grey & white dashed placeholder to "Use the inspector to connect this index to a collection".
That won't do, so, going back to no "pageDidChange" use, I did manage to rig up some boolean checks to determine if the plugin was installed in a collection, and display appropriate placeholder warnings, but that, once again, exposed the "not always rendering" behavior that I'm experiencing with my plugins CSS graphics (I will describe it in that other thread).
In the end, I'm still left desiring a permanent reference to "the page into which the plugin was inserted".
I have been hoping that "awakeFromInsert" might provide what I needed, but I see it's still not implemented. Will it ever be?
Again, none of this prevents my plugin from functioning, it's just not ideal. :-D
Sean
Offline
re: the "issue" I've come across with "indexedCollection". While it works fine for my plugins functionality, it does not literally return "the page into which the plugin was inserted".
Keep in mind, my plugin is only valid when inserted into a Collection. I had planned to write a "warning" placeholder in the event the user had inserted it into a Page.
But, when inserted into a page, "indexedCollection" backtraces up the hierarchy, and returns the Pages "parent" Collection, so can't be used to validate insertion.
Perhaps that's the way it's supposed to function?
Yes, that's our intention. Index plug-ins default to the nearest available collection. Most people never change it after that, but are free to hook up to a different collection from the Inspector if they desire.
This led me try a different approach, using "pageDidChange" to grab the initial reference (which is where I had been grabbing it prior, using "pageWithIdentifier"):
Subclassing my inspector from "SVIndexInspectorViewController", produces the "Collection to Index - Drag target to a collection in the site outline" control, which is unneccesary, and I don't want. So I left my inspector as standard "SVInspectorViewController", which eliminated the "drag to target" requirement.
Please do include it! I know it's not strictly necessary, but it's intended to be a common and consistent Sandvox UI design.
But, if I include "pageDidChange" (with only an NSLog to see that it has called) w/either the standard or index inspector view controller, the plugin does not load. Instead displays the grey & white dashed placeholder to "Use the inspector to connect this index to a collection".
That won't do, so, going back to no "pageDidChange" use, I did manage to rig up some boolean checks to determine if the plugin was installed in a collection, and display appropriate placeholder warnings, but that, once again, exposed the "not always rendering" behavior that I'm experiencing with my plugins CSS graphics (I will describe it in that other thread).
Seriously, please just trust us on this and accept index plug-ins for how they work!
In the end, I'm still left desiring a permanent reference to "the page into which the plugin was inserted".
I have been hoping that "awakeFromInsert" might provide what I needed, but I see it's still not implemented. Will it ever be?
Good point, that I still haven't implemented it. But it wouldn't help you in this case since my intention is not to provide any context of the page the plug-in was inserted into.
Offline
Mike:
Yes, that's our intention. Index plug-ins default to the nearest available collection.
Understood, I can live with that.
re: "indexInspector" drag target
Please do include it! I know it's not strictly necessary, but it's intended to be a common and consistent Sandvox UI design.
Except that it is just not appropriate to my plugin. The plugin already knows what collection it's in.
Most people never change it after that, but are free to hook up to a different collection from the Inspector if they desire.
Which is what should not be available in this particular plugin.
ie. if the user were free to select a different collection to "index", the map would no longer pertain to the collection currently being browsed.
It would be analagous to trying to navigate New York city by looking at a street map of Chicago. Essentially useless.
I suspect most users would be cognizant that no further action is necessary, but, having dealt with "user experience" issues in the past, I know that eventually, some user will think "oh, I have to drag that target somewhere before the plugin will work". And if they drag it anywhere but back to the owning collection (which is already established), it will be all wrong.
So I don't want that "drag target" to appear. It's not a viable "option", is unnecessary and may lead to confusion.
A better example might be the "SiteMap" element. Isn't that an Index plugin? Yet it has no "drag target". You insert it and it's done, a "drag target" would be totally inappropriate for the sitemap. That's what I want my plugin to do, except use the "collection" page as root, instead of "site" root.
Seriously, please just trust us on this and accept index plug-ins for how they work!
I don't distrust you on that :-) I'm sure they work exactly as you intended, w/in the scope of built-in plugins. Mine goes beyond that. It's apparent to me now, that I really don't want an index plugin, but it's the only remaining means I have to grab the needed references.
Perhaps "seeing" what I've done explains it better. Here's a quick demo site:
http://www.macalchemy.com/sandvox/navdemo/
The 1st collection, "Mapped Collection", shows full & proper functionality.
The 2nd, "No-index collection", is a collection w/out an "index" element. The sidebar map still lets it be navigated (that's a "bonus" that I didn't expect from "indexedCollection")
The 3rd, "Mismapped collection", shows why a "drag target" is inappropriate if misapplied. It does nothing but return you to the 1st "Mapped" collection.
Sean
Offline
Which is what should not be available in this particular plugin.
ie. if the user were free to select a different collection to "index", the map would no longer pertain to the collection currently being browsed.
It would be analagous to trying to navigate New York city by looking at a street map of Chicago. Essentially useless.
I suspect most users would be cognizant that no further action is necessary, but, having dealt with "user experience" issues in the past, I know that eventually, some user will think "oh, I have to drag that target somewhere before the plugin will work". And if they drag it anywhere but back to the owning collection (which is already established), it will be all wrong.
So I don't want that "drag target" to appear. It's not a viable "option", is unnecessary and may lead to confusion.
Our whole system for handling indexes is not ideal UI-wise yet; but I see that as our job to improve. In my experience, vast majority of people ignore that bit of the Inspector because it's already set up for them as they like.
A better example might be the "SiteMap" element. Isn't that an Index plugin? Yet it has no "drag target". You insert it and it's done, a "drag target" would be totally inappropriate for the sitemap. That's what I want my plugin to do, except use the "collection" page as root, instead of "site" root.
The sitemap is actually implemented as a regular plug-in, but listed in the Indexes bit of the menu since it serves the same sort of role. There's no drag target because that wouldn't make sense for the role of a site map.
Perhaps "seeing" what I've done explains it better. Here's a quick demo site:
Well now I see what your plug-in does, I've got to say that is pretty awesome!
The 1st collection, "Mapped Collection", shows full & proper functionality.
The 2nd, "No-index collection", is a collection w/out an "index" element. The sidebar map still lets it be navigated (that's a "bonus" that I didn't expect from "indexedCollection")
Quick quibble; it's not a collection without an index, because your plug-in is the index. Sandvox 1 had a one-to-one relationship between and collection and it's index, but that is now far more general. There can be as many indexes associated with a collection as you like.
The 3rd, "Mismapped collection", shows why a "drag target" is inappropriate if misapplied. It does nothing but return you to the 1st "Mapped" collection.
OK, but here's a perfectly reasonable use case:
I have a website laid out much like your demo. There's a collection at the top-level which contains many sub-pages and collections; I want to be able to navigate it, and see where I am within the collection while doing so.
So far, so good. Matches up to your demo.
But what if this the centre-point of my website? The most important content?
Well it seems reasonable to me that I want to showcase that from all pages of the website. Therefore, I set your plug-in to index a collection, but it appears on all pages of the site.
Offline
Here's a demo of my thinking: http://mikeabdullah.net/stuffcorps/
Offline
Sorry Mike, I was gone all day yesterday.
I think I get your drift, but to be sure, does either of these demo sites do what you're thinking of? (recreated your design & layout for familiarity):
http://www.macalchemy.com/sandvox/navdemo1/
http://www.macalchemy.com/sandvox/navdemo2/
Sean
Offline
Yes, I think both of those sites show my thinking perfectly :)
Offline
OK Mike. Now I must confess, those are "trick" demos :-)
One was made exclusively with my plugin, installed in the "home" page. The other was made with my plugin installed in the "Products" collection, and a standard "indexedCollection" installed in the "home" page (& disabled in the "Products" collection). They are functionally identical.
I haven't been considering my plugin to be a replacement for a standard indexed collection, just as an adjunct, to provide an alternative means of navigation to sitemenu "drop-downs" and/or "next - prev" buttons.
However, I do see your point. It can be used in place of a standard indexed collection, so I will leave the "drag target" intact.
However #2, used that way, it does come with a lot of additional inspector "baggage", in order to make it "universal" enough to accommodate any current or future "design". The need for the extra baggage is due to:
1) the vastly different ways each "design" implements main CSS styles, and ...
2) that none of the "built-in" plugins utilizes a nested list (except siteMap), and ...
3) some "designs" do not render nested lists at all appropriately
A "siteMap" is a good example. If you install one in the sidebar of a site w/nested collection depths, and cycle through all the designs, you can see what I'm referring to.
In some designs, the default layout is quite acceptable, but in many others it is not:
1) excessive/insufficient indentation (Brown & Green, Crimson Royale, may others)
2) excessive/insufficient line spacing (Edge of Town & others)
3) irregular line spacing (Dashed, Neo News, Sunbrellas)
4) wrapping/non-wrapping lines (Brown & Green, Crimson Royale, many others)
5) irregular font sizing (Kokomo)
6) and a few designs in particular, completely mangle a nested list (Grey Leaf, Trippy Bubbles)
To get consistent & acceptable layouts for any design, I had to make a choice:
A) provide 40 some different & unique CSS resource files & have the user select the appropriate one to install, or ...
B) have a plist with the all the different values, & detect which design was being used, or ...
C) reset all list properties for the plugin only, declare new defaults, and let the user set & choose others via inspector
I rejected "A" outright, it's not an acceptable "user" requirement. "B" works, but only by going outside the published API (which I want to avoid), and would require updating the plist for any new "design".
"C" was the most logical choice: accomodates all known designs, is "future" proof, and gives the user ultimate control over how it looks & feels (i'm a big fan of "users" choice, regardless of "designers" intention).
Sean
Offline
In some designs, the default layout is quite acceptable, but in many others it is not:
1) excessive/insufficient indentation (Brown & Green, Crimson Royale, may others)
2) excessive/insufficient line spacing (Edge of Town & others)
3) irregular line spacing (Dashed, Neo News, Sunbrellas)
4) wrapping/non-wrapping lines (Brown & Green, Crimson Royale, many others)
5) irregular font sizing (Kokomo)
6) and a few designs in particular, completely mangle a nested list (Grey Leaf, Trippy Bubbles)To get consistent & acceptable layouts for any design, I had to make a choice:
A) provide 40 some different & unique CSS resource files & have the user select the appropriate one to install, or ...
B) have a plist with the all the different values, & detect which design was being used, or ...
C) reset all list properties for the plugin only, declare new defaults, and let the user set & choose others via inspectorI rejected "A" outright, it's not an acceptable "user" requirement. "B" works, but only by going outside the published API (which I want to avoid), and would require updating the plist for any new "design".
"C" was the most logical choice: accomodates all known designs, is "future" proof, and gives the user ultimate control over how it looks & feels (i'm a big fan of "users" choice, regardless of "designers" intention).
This is quite a general problem with plug-in development sadly. My preference is for plug-ins to do as little custom styling as possible. Then to have options in the UI to add custom styling on top. (The custom styling can be turned on by default of course!).
A sufficiently popular plug-in then stands a good chance of designs — both ours, and third party — being updated to better accommodate it.
Offline
Mike:
This is quite a general problem with plug-in development sadly. My preference is for plug-ins to do as little custom styling as possible.
It was not a complaint (I can certainly understand how the problem arises in a "design" paradigm), was just to illustrate how I don't consider the plugin to be acceptable as a "replacement" for an indexed collection: it's far too heavy-handed with inspector controls.
Then to have options in the UI to add custom styling on top. (The custom styling can be turned on by default of course!).
What are the chances of getting some kind of API "design" exposure for the plugin? eg: -(NSString*)currentDesign. That would at least let me pre-populate the inspector with appropriate values, relieving the user from the burden of recreating the layout entirely from scratch. (I can get it now, via "[[[page master] design] title]", but those aren't currently supported methods)
As it stands now, there are at least 2 "designs" which require additional user code-injection to display properly. If I could "detect" those designs, the plugin could programatically write the appropriate strings, eliminating the code-injection.
A sufficiently popular plug-in then stands a good chance of designs — both ours, and third party — being updated to better accommodate it.
I hope mine proves popular, so I can get some return on the time invested :-)
Sean
Offline
I'd really rather not add an API for that because there's somewhere around 80 designs in the world for you to take into account! And don't use private API; I can and will change it in the future.
I meant as in, generate markup which the design takes care of styling for you as much as possible, with customisations applied on top of that as the user chooses.
Offline
Mike:
I'd really rather not add an API for that because there's somewhere around 80 designs in the world for you to take into account! And don't use private API; I can and will change it in the future.
I'm not planning to use the private API, just brought it up as a "wish list" item. I just always trying to think like a "user", and do whatever I can to make the user "experience" as easy as possible.
It's a trade-off: additional up-front programming effort vs. additional user effort. The effort to accommodate all current designs isn't that much at all (I've already got a plist w/all the needed Sandvox design properties, just for the exercise), and adding new designs as they come into existence is fairly simple (could even be done by the user, for purely "custom" designs).
I meant as in, generate markup which the design takes care of styling for you as much as possible, with customisations applied on top of that as the user chooses.
I understood that. But at this time, I'm only interested in what can be done presently.
I'll always work within the limits of the published APIs, and explain to the user, as needed, what needs to be done to set it up.
Sean
Offline
The effort to accommodate all current designs isn't that much at all (I've already got a plist w/all the needed Sandvox design properties, just for the exercise), and adding new designs as they come into existence is fairly simple (could even be done by the user, for purely "custom" designs).
Could I get a copy of that plist do you think? I'm intrigued to see what info you're wanting that the built-in CSS styling is falling short on.
Offline
Could I get a copy of that plist do you think? I'm intrigued to see what info you're wanting that the built-in CSS styling is falling short on.
Mike:
I can send it, but it probably won't make sense outside the context of the rest of the plugin code. And it's out of sync with my current inspector controls (I stopped using it a long time ago, once I had determined that it could work).
Meanwhile, I can explain it. As you might guess by the wild variablity in each designs rendering of a nested list, I had to try & compensate for all the anomalies. It quickly became apparent that trying to do so on a design-by-design basis was futile. It was much cleaner & easier to reset (zero-out) every list element style, and start anew.
The fixed "resets" are done in a plugin.css resource file, added to page <head>. Then the code generates the remaining CSS styles, initializing them from plist, and allowing the user to "fine tune" by inspector.
The "generated" CSS consists of 2 parts:
"Generic" values, which produce a consistent & acceptable "list", but which may or may not come close to looking like the "design" intended. These values are:
plugin <div> left margin (relative to "designs" #sidebar & .pagelet)
main list <UL> left margin
sub (nested) list <UL> left margins
line-height
"Design" specific values, required to adapt to either "list-style" or "background-image" design bullet types:
page title text left-padding to uncover "background-image" types
"background-image" vertical positioning
sub-list left-margins (to align sublists with variable width "background-images")
the plugins custom bullet shade (dark/medium/light) to best match the designs background shade
It's the last 4 that would benefit most with "design detection" ability. As it is now, if you set it up to look good in a design that uses "list-style" bullets, then switch to a design that uses "background-image" bullets, it all goes wonky, requiring re-manilpulation of inspector values.
Sean
Offline
Pages: 1