I am overriding a lot of SAP's Portal functionality in my current project. I have to create a custom fixed width framework, custom iView trays, custom KM API functionality, and more.
With all of these custom parts, I will not be using a lot of the style functionality implemented by SAP's Theme editor. What I would like to do is create an external CSS, store it outside of the Portal and reference it. Storing externally will allow for easier updates rather than storing the CSS within a portal application. It would also allow for all custom pieces to have their styles in once place.
Unfortunately, I've not found a way to gain access to the HEAD portion of the page that allows me to insert an external stylesheet. Portal Applications can do so using the IResource object to gain access to internal references, but not items on another server.
I'm looking for any ideas that would allow me to gain this functionality. I have x-posted on SAP's SDN, but I suspect I'll get a better answer here.
I'd consider it dirty hack, but as a non-Portal developer I'd consider using JavaScript to insert a new link element in the head pointing to your new CSS file. Of course you'd have a flash of un-styled content because the script probably won't run until after part of the page has been downloaded and rendered, but it may be an adequate solution.
I hate that I'm answering my own question, but I did find a potential solution that's not documented well and in typical SAP fashion uses deprecated methods. So it might be a slightly less dirty hack than what Eric suggested. I found it through an unrelated SDN forum post.
Basically, you dive into the request object and gather the PortalNode. Once you have that, you ask it for a value of a IPortalResponse. This object can be cast to a PortalHtmlResponse. That object has a deprecated method called getHtmlDocument. Using that method, you can use some Html mirror objects to get the head and insert new links.
Sample:
IPortalNode node = request.getNode().getPortalNode();
IPortalResponse resp = (IPortalResponse) node.getValue(IPortalResponse.class.getName());
if (resp instanceof PortalHtmlResponse) {
PortalHtmlResponse htmlResp = (PortalHtmlResponse) resp;
HtmlDocument doc = htmlResp.getHtmlDocument();
HtmlHead myHead = doc.getHead();
HtmlLink cssLink = new HtmlLink("http://myserver.com/css/mycss.css");
cssLink.setType("text/css");
cssLink.setRel("stylesheet");
myHead.addElement(cssLink);
}
Related
I am using a Repeater web part in Kentico to pick out pages from the content tree, to generate nicely repeatable snippets of structured HTML, based on an ASCX transformation. (No surprises here - its been working great!).
However, a new requirement landed whereby alongside the existing HTML structure mentioned above, each repeated item must also have an area where we can add any amount of additional content; based on other web parts.
I have previously written a few "layout" type web parts; implementing CMSAbstractLayoutWebPart, as described here, which has allowed me to generate a repeating amount of web part zones, so I feel like I'm half way there. The issue with that though is that as it stands, I don't seem to be able to make use of the great power and flexibility of the transformations on the page type (which I really think I need to do, and seems like it should be possible..).
I thought I may be able to specify the WebPartZone control in the transformation markup directly, like in the following:
<%# Register Src="~/CMSInlineControls/WebPartZone.ascx" TagName="CMSWebPartZone" TagPrefix="cms" %>
<cms:CMSWebPartZone ZoneID="ZoneIDHere" runat="server" />
<div>
<h3><%# Eval("Heading") %></h3>
<p><%# Eval("Summary") %></p>
</div>
But the design view doesn't seem to pick up the web part zone; so I'm assuming the page lifecycle may not allow me to do this as I'd hoped.
So what I would like to know is:
Is it possible to include WebPartZone control in a transformation such that I can then bring in new web parts in Design view?
If not, what is the recommended way to go about this? (If a custom web part is the way to go, I'd like to clone the Repeater web part in the first instance, as many of its existing properties will be needed - but presumably this must still inherit from CMSAbstractLayoutWebPart?
Thanks!
Update
Good point about the editor's experience; I would definitely like to keep this as consistent as possible. The issue for me is that the requirements that drive my data structures are not always fully understood - and are certainly subject to change. Also, they are liable to vary (albeit subtly) across different products. So I've been trying to keep templates and page types more or less the same across the board, and push out the differences into page properties that drive web part config through macros. So given that the transformation approach won't work, I expect a custom web part is the right fit for me.
I shall post my findings!
I think adding a web part zone into transformation is not a right direction as web part zone should be a part of page template (not transformation) in order to utilize it.
I'd probably try to organize my content so each item you currently showing in the repeater has any number of child pages (potentially of a different type) and use something like hierarchical viewer in order to present all of them on the page. It allows using different transformation based on either page type or node level. Another advantage of this approach is that you keep editors experience consistent.
In the end, I was able to use transformation markup to specify the generation of web part zones. I went down the route of creating a custom web part that inherits from CMSAbstractLayoutWebPart, rather than using CMSRepeater web part or similar...
Here's a breakdown of things I needed to do this:
Gave the custom layout-type web part some properties with which to query the content tree, and supply them to a TreeProvider.SelectNodes() method in the web part code once it has initialised (by overriding the OnInit() method)
Gave the web part a TransformationName property so that the raw markup can be retrieved using TransformationInfoProvider.GetTransformation(this.TransformationName)
Used the markup above and resolved macros within it using each node from the node query
Example of macro resolution code (HTML transformations with macros)
protected virtual string ResolveNode(TreeNode node)
{
var resolver = this.ContextResolver.CreateChild();
resolver.AddAnonymousSourceData(node);
return resolver.ResolveMacros(rawTransformationMarkup);
}
Then I go looking for placeholder text in the transformation markup and use the methods available in the CMSAbstractLayoutWebPart parent class(es), as detailed here, to Append() the resolved markup and also call AddZone() as necessary to tap into the response string builder
Summary: The great functionality of the API allowed me to completely avoid the use of any repeater controls. I could generate web part zones as part of the layout web part usual layout generation process.
It would be nice if I could figure out how to resolve the expressions in SCRIPT tags in ASCX transformations to complete the story, but by using HTML transformations I can use the above to accomplish what I need.
We are building a Page with dynamic functionality using ASP.NET + Sitecore 7.0.
Is it practical and appropriate use Sitecore templates for:
SQL Stored Procedure Name to be invoked
JavaScript to be invoked
ColumnNames to be used etc (related to coding customization)
Or should these configuration properties remain inside the ASP.NET Project itself?
What is the primary purpose of Data Templates in Sitecore?
Are they for developer customization or customer-level customization?
The purpose of a data template in Sitecore is to define the set of fields for content items which inherit from that template. - Think of a data template as a class and the content items (pages) as instances of that class.
Templates are usually used to define the user-editable content of pages within a site, that being said you can have items to store information which is not managed by regular content editors. The question is where do you draw the line between things which should be put into Sitecore and things which should be a part of the solution. My advice is only put things in Sitecore if they need to be there. If you have to have the ability for editors or admins to configure those settings/properties.
I would say that putting SQL/ColumnNames is probably a bad idea unless you are building some sort of report builder interface in which case it may be essential?
Likewise with placing JavaScript into Sitecore; this can be OK in moderation (e.g. snippets of analytics code which content editors may want control over?). If you're placing whole libraries of JavaScript into Sitecore, you're probably doing it wrong.
One final point to note is findability/re-factorability of code: if you have code spread between Sitecore and your solution, it can make it very difficult to maintain as it is difficult to get a complete overview of code involved.
Using the Core Service API, is there any way to retrieve the fields of a component without having to resort to querying the underlying XML or using a third party(?) wrapper class?
It's fairly simple when using the TOM.NET API
Tridion.ContentManager.ContentManagement.Component component = [get a component];
var componentFields = new Tridion.ContentManager.ContentManagement.Fields.ItemFields(component.Content, component.Schema);
var summary = ((Tridion.ContentManager.ContentManagement.Fields.TextField)componentFields["summary"]).Value;
But when I start using the Core Service API it seems a little more complicated as there is no Tridion.ContentManager.ContentManagement.Fields.ItemFields class to wrap around the component.Content.
I understand Frank van Puffelen has written a set of classes to implement this wrapper functionality but I am a bit wary of using code that is not officially supported by SDL (or is it?).
At the moment it seems to me the functionality to gracefully retrieve fields from a component using the Core Service API has not been fully implemented. I hope I will be proved wrong!
If you are looking for an official wrapper to access the ComponentData content, there is not such a thing as that.
Frank's classes are not officially supported, it is open source code(under the MIT License), but it is built using a supported API, so you should be ok using it.
On the other hand it is not such an extensive piece of code, so if you have an issue, you can probably try to solve it yourself. As already other fellow developers did, as you can see on the page comments.
This question has been asked before, more than once actually..
For example: How to set content to a component without loading XML in SDL Tridion using core services?.
Every tutorial/example i can find for meteor shows a single view application. I would like to build something a little more complex. I'm unclear how to approach multiple views...preferably in a way that's somewhat scalable?
The iron-router package lets you access different views (layouts) by nice, REST-ful human-friendly clean URLs. It supports parameters in the URL, "loading" templates, waiting for subscriptions to finish loading, before and after hooks etc.
At this point you can only create Single Page applications with Meteor. Note that Single Page, doesn't mean you can't have several views - use iron-router for that.
But by design, Meteor serves a big fat unique JavaScript/HTML/CSS application down to the browser, though there's a feature request to allow incremental loading. It is then up to the application (or more precisely, the JavaScript framework), to dynamically render its views in order to display different "pages".
I was wondering the same thing and it took me way too much time getting something started. I finally got a paged app working solidly by using Backbone views and routes, so I created a simple boilerplate project to make setting up an app like this easier in the future.
Live demo here: backbone-boilerplate.meteor.com
Source code here: github.com/justinmc/meteor-backbone-boilerplate
Have you looked at madewith.meteor.com?
A bunch of apps there have multiple views using Backbone also Jonathan Kingston who created britto has started simple meteor framework called Stellar
At this stage of the game not sure if there really are best practices. But these two seem to be the current flow.
You can also make a tabbed interface for multiple views. There is a package project "Smart package for generating a tabbed interface with pushState" github project here: https://github.com/possibilities/meteor-tabs
The best solution right now is using a routing package (router is basic but works). The workflow is something like this:
declare routes; return a template name for each route
place the reactive helper provided by the package in your body tag
the reactive helper will return the template associated to that route
you create a template for each route and optionally set custom publish functions
Router will give you browser history (client side).
Note that at this time there are some limitation on the way Meteor handles html/js. They are load all at the same time. The bright side is that once the app is loaded, page transitions will be instant.
I recently created a website for a friend (asp.net/sql server), the website includes news of his company and he and his team update this frequently.
The question has been asked if i could now create a widget / api of some sort that visitors of the website could now include the news on there own website should they wish too. I feel this needs to be a one line of code intergration or something that is extremely easy to intergrate.
Any recommendations or articles are welcome.
EDIT: how is something like this created
http://img830.imageshack.us/img830/7769/codingabandwebsitecreat.png
Thanks
With jQuery's ajax and an asp.net handler that returns an injectable html chunk is my off hand guess at simple way. Other's will probably know of frameworks if you don't want to roll your own. Is RSS to primitive?
you could also write a REST service in WCF since you're using asp.net and have it return XML or JSON, depending on how you write your widget.
How something like that is created... Well, I've created a number of these and the process is fairly simple. Sorry I don't have an article to reference. Create a 'widget creation/builder' page with input parameters, when submitted either store those in the database and return an ID to associate with those settings, or generate a list of param's for those settings, or both. Simply output the <script> tag into a textbox. Like so (inside an AJAX callback):
$("#results").html("<script type='text/javascript' src='" + widget_path + params + "'></script>");
Where widget_path is the absolute path to the widget ASP script, and params is either something like key=454 or theme=sunny&source=34&count=50 etc. Either manually or using something like jQuery.param to serialize the form. An alternative would be two <script> tags with settings in the 2nd and calling a widget initialize function.
They can copy and paste that into their site, and that ASP script should output only JavaScript, which you can either document.write() or use a JS library (such as jQuery) to operate on the DOM (.click() etc). If using a database the ASP script would check the key param and grab the widget settings, if not then simply process the params. It's important to mention if you want to communicate back and forth with an API, you need cross-domain enabled or you could simply use JSON (in ASP script check for a 'callback' parameter, wrap JSON in that function name, and use jQuery.getJSON with &callback=? at the end); there are other methods of course.
If you use a database, make sure to take security into account (SQL injection, etc.)
WidgetBox looks like a good, mainline method as well.