What is the simplest way to find current item ID in the template - tridion

In my C# or dreamweaver template I need to know what am I rendering. The problem is that I don't know for sure if I'm looking for a page or component. I could probably use package.GetByType(ContentType.Page) and if it's empty - get content of a component, but I feel there should be a shorter way.
Example of David is shorter:
engine.PublishingContext.ResolvedItem.Item.Id

engine.PublishingContext.ResolvedItem.Item.Id
You can also check the Publishing Context's resolved Item and see if it's a Page or not (if it's not, then it's a Component).
For example:
Item currentItem;
if (engine.PublishingContext.ResolvedItem.Item is Page)
{
currentItem = package.GetByName(Package.PageName);
}
else
{
currentItem = package.GetByName(Package.ComponentName);
}
TcmUri currentId = engine.GetObject(currentItem).Id;
If you want to shortcut the engine.GetObject() call, then you may be able to get the ID from the Item's XML directly:
String currentId = currentItem.GetAsSource().GetValue("ID");

That's how I've seen it done before:
// Contains the call you describe in your question
Page page = GetPage();
if (page == null)
{
// Contains a call using package.GetByName("Component")
// to avoid the situation with multiple Components on the package
Component comp = GetComponent();
// Do component stuff
}
else
{
// Do page stuff
}
Not sure you can encapsulate it much nicer than that really but I may be proved wrong.

Related

Flex validation popups no longer showing up in popup dialogs?

I am working on an application which has quite a bit of field-validation in it. The validation works great and I am 1000000% sure the validation message popups were appearing earlier. Now I did quite a bit of work and refactoring. One of the things I changed was the way I open up Popups/Dialog. In order to have these centered over the entire application instead of the opening component I refactored the way I open dialogs. I used the source of the Alert as a base for this but extended it quite a bit as I was having other issues (Focus Manager etc.) (I am just mentioning this as I am assuming that my missing popups are related to this).
Here comes the code responsible for opening popups in my application:
public function show(realParent:Sprite,
displayParent:Sprite = null,
closeHandler:Function = null,
moduleFactory:IFlexModuleFactory = null):Dialog {
// Get the parent ...
// If none is set, use the top-level-application.
if (!displayParent) {
var sm:ISystemManager = ISystemManager(FlexGlobals.topLevelApplication.systemManager);
// no types so no dependencies
var mp:Object = sm.getImplementation("mx.managers.IMarshallPlanSystemManager");
if (mp && mp.useSWFBridge())
displayParent = Sprite(sm.getSandboxRoot());
else
displayParent = Sprite(FlexGlobals.topLevelApplication);
}
// Register for close-events, making sure the pop-up is closed.
if (closeHandler != null) {
this.addEventListener(CloseEvent.CLOSE, closeHandler);
}
// Setting a module factory allows the correct embedded font to be found.
if (moduleFactory) {
this.moduleFactory = moduleFactory;
} else if (realParent is IFlexModule) {
this.moduleFactory = IFlexModule(realParent).moduleFactory;
} else {
if (realParent is IFlexModuleFactory) {
this.moduleFactory = IFlexModuleFactory(realParent);
} else {
this.moduleFactory = FlexGlobals.topLevelApplication.moduleFactory;
}
// also set document if parent isn't a UIComponent
if (!parent is UIComponent) {
this.document = FlexGlobals.topLevelApplication.document;
}
}
// Make the dialog center itself relative to the parent.
PopUpManager.addPopUp(this, displayParent, true);
PopUpManager.centerPopUp(this);
return this;
}
What could be responsible for the Validation popups not showing up any more? Where should I look?
Chris
Ok ... so I figgured this out by myself again. I coould bang my head at the wall for taking so long for finding it though.
If I use the Spart forms, the FormItems and Forms themselves can define error text areas in order to output error messages. So as soon as the FormItem posesses a skin part with the id "errorTextDisplay" the error messages go there. I was now expecting that if there was no such part, the old notifications would be used ... nope.
After about 2-3 Hours of messing around with the code of FormItem and it's skins, I noticed that the "contentGroup" explicitly defined an attribute to suppress error tooltyips by setting showErrorTip to false. Simply removing the "errorTextDisplay" from the skin and changing the showErrorTip to true made my popups appear nicely :-)
Hopefully this post might help someone with the same problems.

Help with containers

I am using view stack...so when view change like when we move from one page to another hide event is dispatched.So i am saving the information of last page in hide event before i go to next page.but thing is that if i change nothing still change on view hide event is invoked nd call go to backend...i just want do call only if sumthing change in the view..like sum text value...So i have two options
use event listener on each component if sumthing change its make the flag true...nd hide event check, if flag is true send call to backend.
event listener at container level ..if sumthing change in child componenet through bubbling container knows if sum event is dispatched.nd makes the flag true.
I have doubt with container...
Can i use container, and how?
Reason why I can't use container?
What are the pros and cons either way?
I would recommend using a dataProvider with the ability to compare them. For instance, if you are changing things with textinputs, you could basically do something like this:
[Bindable]
private var myDataProvider:Object = new Object();
private function creationCompleteHandler():void {
myDataProvider.updated = false;
myDataProvider.defaultValue = 'default';
myDataProvider.defaultValueTwo = 'default';
}
etc.
Then, in your mxml, you can have something like this:
<mx:TextInput id="myText" text="{myDataProvider.defaultValue}" change="myDataProvider.defaultValue=myText.text; myDataProvider.updated=true;" />
Lastly, in your hide event, you can do the following:
private function hideEventHandler( event:Event ):void {
if( myDataProvider.updated ){
// Call your RemoteServices (or w/e) to update the information
}
}
This way, when anything changes, you can update your dataProvider and have access to the new information each time.
Hope this helps!
I've used an approach similar to your first option in a couple of my past projects. In the change event for each of my form's controls I make a call to a small function that just sets a changesMade flag to true in my model. When the user tries to navigate away from my form, I check the changesMade flag to see if I need to save the info.
Data models are your friend!
If you get in the habit of creating strongly typed data models out of your loaded data, questions like this become very basic.
I always have a key binding set to generate a code snipit similar to this...
private var _foo:String;
public function get foo():String
{
return _foo;
}
public function set foo(value:String):void
{
if(_foo == value)
return;
var oldVal:String = _foo;
_foo = value;
this.invalidateProperty("foo", oldVal, value);
}
If your data used getters/setters like this, it would be very easy to validate a change on the model level, cutting the view out of the process entirely.

Adobe Flex3: Keyboard shortcuts when a view is visible?

I have a quite large Flex application with a large set of views and I ceratain views I'd like to add shortcuts.
And i'm looking for something like:
<mx:Vbox>
<foo:Shortcut keys="ctrl+s" action="{bar();}"/>
....
</mx:VBox>
Is there any framwork or component already done that does something like this? I guess it should be too difficult to build? When building this I only want the shortcuts to be active when the view is visible. How do I detect this? What base class is best to inherit from when working with non visual components?
I don't know of any framework component that does that already, but the examples above should get you started if you try to build your own.
There's no need to inherit from any component for a non-visual component like the one you've described here (your "foo" class needs no parents.) There's nothing in the Flex framework you need to inherit from for this.
However you architect it, your foo class is going to have to take in and parse keyboard codes to listen for and accept one or more methods to call. All you have to do is figure out when to add and remove the event listeners that will call the passed-in methods.
To handle turning your keyboard events on and off based on visibility, just have your foo component bind to the "visible" property of it's parent and add/remove event listeners accordingly.
You might also consider having the listeners added when the component that foo is nested in is on the display list rather than just visible. To do this, simply added and remove your event listeners in one of the component lifecycle methods - probably commitProperties is the most appropriate.
I don't think this solution answer your question directly but anyway, to help solve your problem here is an example.
For instance, I've extended the TextArea component like so. This is the best I can do so far, it can definitely be improved upon. Like, I don't know how to make the cursor go to the end after the next shortcut is pressed.
public class TextArea extends mx.controls.TextArea
{
// the keysmap is an example dictionary holding keycodes
private var keysmap:*={
112 = "some text for F1"
,113 = "the text for F2!"
//etc, etc
}
public var handleKeyDown:Boolean =false;
public function TextArea(){
if(handleKeyDown ==true){
this.addEventListener(KeyboardEvent.KEY_DOWN,this.keydownHandler);
}
}
public function keydownHandler(e:KeyboardEvent):void{
if(e.keyCode >= 112 && e.keyCode <= 123){
e.currentTarget["text"] += String(keysmap[e.keyCode]) +" ";
}//focusManager.setFocus(this);
}
}
I can't give you a solution using MXML, however my first thought would involve a singleton static class with a Dictionary that contains a list of objects as its keys and dynamically created dictionaries as the value pairing that contain keys denoting the desired key press with a function reference as the value.
So, say you had a Sprite and you wanted to capture ctrl+s for save when focus is on that object, I would get the instance of that Singleton, and call a function such as registerKeyBinding passing in the Sprite, the keyCode you want, and your pre-defined callback:
private var registeredObjects:Dictionary = new Dictionary(true);
public function registerKeyBinding(targetObject:Object, keyCode:int, callback:Function) {
if (registeredObjects[targetObject]) {
Dictionary(registeredObjects[targetObject])[keyCode] = callback;
}
else {
registeredObjects[targetObject] = new Dictionary();
Dictionary(registeredObjects[targetObject])[keyCode] = callback;
targetObject.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
}
}
private function keyDownListener(e:KeyboardEvent):void {
if (e.ctrlKey == true) {
//calls the function if that key exists.
Dictionary(registeredObjects[e.target])[e.keyCode];
}
}
Can't say I've tested this, but it was just the first thing that popped into my head. You could then setup functions to deregister and delete keys from the dictionaries, check states of the objects in addition to the keyCodes, remove old listeners, and delete entire dictionaries when there is no longer a need for them. Hopefully this is at least a tiny bit helpful.

Setting multiple literals that contain the same text in ASP.NET

I have instances where I need to dynamically load 5-10 literals with the same text value. It seems like there has to be a more elegant way of doing it than setting the TEXT property of all the controls to the same value. Any methods out there that I'm not aware of? I thought about setting a protected property on my webform, and then using inline code on my aspx page. Is that a good approach?
Edit: I should add that I also want to handle the situation where a designer could simply add another place to load dynamically to the aspx file on the web server without having to do another rollout.
Pseudo code:
var literals = new List<Literal>() { l1,l2,l3 ...} ;
literals.ForEach(x=>x.Text = "some value");
When faced with the same problem I often use:
litOne.Text = litTwo.Text = litThree.Text = "some value";
It's not perfect but at least it's on one line.
How about this?
foreach (ITextControl textControl in new[] { literal1, literal2, literal3 })
{
textControl.Text = "foo";
}
You could even be fancier and just loop through all controls and check only those that implement the ITextControl interface or so.

Struts2 back button and linking

I am using Struts 2.1.6 with Dojo plugin, whole app has ajax links (sx:a).
Did anybody succeed to implement back button functionality and linking to certain content?
Does anybody have any experience how to implement? I am planning to implement (if there is no good solution already) something like so:
changing address bar link (adding parameters) with js which I can then read and get proper content and then publish it with notifyTopics.
Or should I just change whole app to use jQuery plugin? Do jQuery has good solutions for back button and linking on ajax pages?
I can think of 2 simple ways off the top of my head:
<s:form action="actionName">
<input type="hidden" value="<s:property value="someProperty"/>" name="someProperty"/>
<input type="hidden" value="<s:property value="someProperty2"/>" name="someProperty2"/>
<s:submit value="Back" />
</s:form>
or
<s:url name="backURL" action="actionName">
<s:param name="someProperty" value="someProperty"/>
<s:param name="someProperty2" value="someProperty2"/>
</s:url>
Back
If you already have query string parameters:
Back
or
<input type="button" value="Back" onclick="javascript.window=document.referrer;"/>
I have tried to use Struts 2 with dojo and implement the back button. You are already way over the head of Struts 2's ajax implementation. They mainly used and wrote it to write simple and quick ajax function calls and is not very well suited for more extensive uses. Plus when you do s:head theme='ajax' tag; struts will import every ajax js file you 'may' need which kills load time.
I would suggest either 1. Learn dojo and use the library independent of struts 2. Or 2. Get jQuery, I was able to implement a back button functionality relatively simple (more so then struts 2 theme='ajax').
Don't know Struts, but have you looked at dojo.undo (0.4.3)?
All my links go through one action which looks for a parameter menuId (of course id of a menu which has to be shown).
From this action, before returning response I set one javascript function to be called:
setBackMenuId(menuId,sometext)
MenuId is the id, sometext is a name of that menu, so browser log history better.
function setBackMenuId(id,subtekst) {
window.location.hash = "menuId="+id;
document.title = subtekst;
selectedHash = document.location.hash;
if(intervalHashSearch == '') {
initializeHashSearch();
}
}
Then, other needed js functions:
function publishLinkTarget() {
var param = window.location.hash;
if(param) {
if(param.indexOf("menuId") > 0) {
var id = param.split("=", 2);
if(id[1]) {
setCookie('backMenuId',id[1],1,false);
setTimeout('publishLayoutContent()', 100);
}
}
}
}
var selectedHash = '';
var intervalHashSearch = '';
function initializeHashSearch() {
intervalHashSearch = window.setInterval('checkHash()', 500);
}
function stopHashSearch() {
window.clearInterval(intervalHashSearch);
intervalHashSearch = '';
}
function checkHash() {
var currentHash = document.location.hash;
if(selectedHash != currentHash) {
selectedHash = currentHash;
publishLinkTarget();
}
}
function publishLayoutContent() {
dojo.event.topic.publish("layoutContentTarget");
}
If you look at it you see, that first it is called 'setBackMenuId', which adds hash and parameter to address bar and changes title, and then remembers this hash, so interval hash search can find out the differrence. Then it initializes this hash search.
'checkHash' is running ever 500 miliseconds and is checking if hash has changed (that means, that back button was pressed, and not a new link was clicked (setBackMenuId sets selectedHash). If true (back/forward button was pressed) function 'publishLinkTarget' is called, which reads the parameters from hash, and if they are ok, first I set a cookie, so I can read it from the HttpServletRequest and find out for which menu id link is. If I am here it means that I have to also publish the content which is made with 'publishLayoutContent'.
In action class (this is MenuAction, method view, the same as published in ) only this is important:
Integer menuId = null;
if(request.getParameter("menuId") != null) {
menuId = Integer.valueOf(request.getParameter("menuId"));
} else {
menuId = getIntCookie("hiddenMenuId");
}
So, if I don't get the menu id from the parameter (link clicked) I get from a cookie (back/forward button).
And JSP with this target:
<s:url var="layoutContentUrl" action="Menu-view" namespace="/public" />
<sx:div showLoadingText="false" indicator="ajaxIndicator"
id="layout-content" href="%{layoutContentUrl}" theme="ajax"
listenTopics="layoutContentTarget" preload="false"
afterNotifyTopics="/ajaxAfter">
</sx:div>
NOTE: This is a special case if you have everything connected through one parameter, but it can be easily extended with other parameters which publish other targets. I will try to make it enough generic to publish it somewhere, but this is (I guess) a long way ahead :)
If you have any question, please post it.

Resources