/*
* Copyright (C) NetStruxr, Inc. All rights reserved.
*
* This software is published under the terms of the NetStruxr
* Public Software License version 0.5, a copy of which has been
* included with this distribution in the LICENSE.NPL file. */
package er.directtoweb.pages;
import org.apache.log4j.Logger;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WORequest;
import com.webobjects.directtoweb.EditPageInterface;
import com.webobjects.foundation.NSNotificationCenter;
import com.webobjects.foundation.NSValidation;
import er.directtoweb.ERD2WContainer;
import er.directtoweb.ERD2WFactory;
import er.directtoweb.interfaces.ERDTabEditPageInterface;
import er.extensions.components._private.ERXWOForm;
import er.extensions.foundation.ERXStringUtilities;
import er.extensions.foundation.ERXValueUtilities;
/**
* Superclass for all tab and wizard pages.
*
* @d2wKey firstResponder
* @d2wKey tabComponentName
*/
public class ERD2WTabInspectPage extends ERD2WInspectPage implements ERDTabEditPageInterface {
/**
* Do I need to update serialVersionUID?
* See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the
* <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a>
*/
private static final long serialVersionUID = 1L;
public final static String WILL_SWITCH_TAB = "willSwitchTab";
public ERD2WTabInspectPage(WOContext c) {
super(c);
}
/** logging support */
public static final Logger log = Logger.getLogger(ERD2WTabInspectPage.class);
public static final Logger validationLog = Logger.getLogger("er.directtoweb.validation.ERD2WTabInspectPage");
public String switchTabActionName() { return isEditing() ? "switchTabAction" : null; }
public boolean switchTabAction() {
boolean switchTab = true;
if (shouldSaveChangesForTab()) {
if (validationLog.isDebugEnabled())
validationLog.debug("Calling tryToSaveChanges");
switchTab = tryToSaveChanges(true);
}
if (switchTab && errorMessages.count()==0 && object().editingContext().hasChanges() && shouldNotSwitchIfHasChanges()) {
validationFailedWithException(new NSValidation.ValidationException("You currently have changes outstanding. Please either save or cancel your changes before navigating elsewhere."), null, "editingContextChanges");
}
return switchTab && errorMessages.count()==0;
}
@Override
public void takeValuesFromRequest(WORequest request, WOContext context) {
// ak: this only works in a direct link or if there are no form
// values...
String tabName = request.stringFormValueForKey("__tab");
setTabByName(tabName);
super.takeValuesFromRequest(request, context);
}
//AK: what are these used for? They do nothing?
protected Integer _tabNumber;
public Integer tabNumber(){ return _tabNumber;}
public void setTabNumber(Integer newTabNumber){ _tabNumber = newTabNumber;}
@Override
public WOComponent printerFriendlyVersion() {
WOComponent result=ERD2WFactory.erFactory().printerFriendlyPageForD2WContext(d2wContext(),session());
((EditPageInterface)result).setObject(object());
return result;
}
public void setTabByName(String tabName) {
if (tabName != null) {
int i = 0;
for (ERD2WContainer container : tabSectionsContents()) {
if (tabName.equals(container.name)) {
setTabNumber(Integer.valueOf(i));
setCurrentTab(container);
break;
}
i++;
}
}
}
@Override
public String urlForCurrentState() {
String url = super.urlForCurrentState();
if (currentTab() != null) {
// AK: sloppy, I know...
url = url + "&__tab=" + ERXStringUtilities.urlEncode(currentTab().name);
}
return url;
}
/**
* <p>Constructs a JavaScript string that will give a particular field focus when the page is loaded. If the key
* <code>firstResponderKey</code> from the d2wContext resolves, the script will attempt to focus on the form field
* belonging to the property key named by the <code>firstResponderKey</code>. Otherwise, the script will just focus
* on the first field in the form.</p>
*
* <p>Note that the key <code>useFocus</code> must resolve to <code>true</code> in order for the script to be
* generated.</p>
* @return a JavaScript string.
*/
@Override
public String tabScriptString() {
if (d2wContext().valueForKey(Keys.firstResponderKey) != null) {
return scriptForFirstResponderActivation();
} else {
String formName = ERXWOForm.formName(context(), "EditForm");
String result = "var focusedElement = document.querySelector('form[name=\"" + formName + "\"] input:focus');"
// only continue when no form element is focused, yet
+ "if (focusedElement == undefined) {"
+ " var focusableElements = document.querySelectorAll('form[name=\"" + formName + "\"] input');"
+ " var qualifiedTypes = ['text', 'textarea'];"
+ " for (i = 0; i < focusableElements.length; i++) { "
+ " var anElement = focusableElements[i];"
+ " if (qualifiedTypes.include(anElement.type.toLowerCase())) {"
+ " anElement.focus();"
+ " break;"
+ " }"
+ " }"
+ "}";
return result;
}
}
private boolean d2wContextValueForKey(String key, boolean defaultValue) {
return ERXValueUtilities.booleanValueWithDefault(d2wContext().valueForKey(key), defaultValue);
}
// These style rules should definately be restricted to tabKeys if needed.
// CHECKME ak is this default correct?
public boolean shouldNotSwitchIfHasChanges() {
return d2wContextValueForKey("shouldNotSwitchIfHasChanges", false);
}
// CHECKME ak is this default correct?
public boolean shouldSaveChangesForTab() {
return d2wContextValueForKey("shouldSaveChangesForTab", false);
}
// CHECKME ak What's all this??? Why not simply show the buttons and en-/disable them??
public boolean shouldShowNextPreviousButtons() {
return d2wContextValueForKey("shouldShowNextPreviousButtons", true);
}
public boolean shouldShowPreviousButton() {
return d2wContextValueForKey("shouldShowPreviousButton", !currentTabIsFirstTab());
}
public boolean shouldShowNextButton() {
return d2wContextValueForKey("shouldShowNextButton", !currentTabIsLastTab());
}
//CHECKME ak Is this needed?
public boolean useSubmitImages() {
return d2wContextValueForKey("useSubmitImages", false);
}
public boolean useTabImages() {
return d2wContextValueForKey("useTabImages", false);
}
public boolean useTabSectionImages() {
return d2wContextValueForKey("useTabSectionImages", false);
}
public WOComponent nextTabAction() {
if (switchTabAction()) {
int currentIndex = tabSectionsContents().indexOfObject(currentTab());
if (tabSectionsContents().count() >= currentIndex + 2 && currentIndex >= 0) {
NSNotificationCenter.defaultCenter().postNotification(WILL_SWITCH_TAB, this);
setCurrentTab(tabSectionsContents().objectAtIndex(currentIndex + 1));
}
else
log.warn("Attempting to move to next tab when current index is: " + currentIndex + " and tab count: " +
tabSectionsContents().count());
}
return null;
}
public WOComponent previousTabAction() {
if (switchTabAction()) {
int currentIndex = tabSectionsContents().indexOfObject(currentTab());
if (tabSectionsContents().count() >= currentIndex && currentIndex > 0)
setCurrentTab(tabSectionsContents().objectAtIndex(currentIndex - 1));
else
log.warn("Attempting to move to previous tab when current index is: " + currentIndex + " and tab count: " +
tabSectionsContents().count());
}
return null;
}
public boolean currentTabIsFirstTab() {
return tabSectionsContents() != null && tabSectionsContents().count() > 0 && currentTab() != null ?
tabSectionsContents().objectAtIndex(0).equals(currentTab()) : false;
}
public boolean currentTabIsLastTab() {
return tabSectionsContents() != null && tabSectionsContents().count() > 0 && currentTab() != null ?
tabSectionsContents().lastObject().equals(currentTab()) : false;
}
public String tabComponentName() {
return (String)d2wContext().valueForKey("tabComponentName");
}
public boolean disablePrevious() {
return currentTabIsFirstTab();
}
public boolean disableNext() {
return currentTabIsLastTab();
}
public boolean disableCancel() {
return !showCancel();
}
public boolean disableSave() {
return false;
}
}