modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ContentGWTService.java
| 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
| 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
| 381
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
| 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/GwtRelativeDurationConverter.java
| 18
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMeasurementConverter.java
| 353
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMonitorUtils.java
| 47
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ContentGWTServiceImpl.java
| 25
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
| 17
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
| 3
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
| 2
modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
| 2
modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.4.4.js
| 7179 ++++++++++
modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js
| 1271 +
14 files changed, 9200 insertions(+), 117 deletions(-)
New commits:
commit 1887278d305b584ac6446dc213e90921220a34f3
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Tue Jan 18 03:16:07 2011 -0500
modify OperationGWTServiceImpl to conditionally include resourceId in query.
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
index da95be6..e1d5e40 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
@@ -131,7 +131,7 @@ public class RecentOperationsDataSource extends
}
}
- int resourceId = getFilter(request, "id", Integer.class);
+ int resourceId = -1;
GWTServiceLookup.getOperationService().findRecentCompletedOperations(resourceId,
pageControl,
new
AsyncCallback<List<DisambiguationReport<ResourceOperationLastCompletedComposite>>>()
{
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
index 44ba3c8..5fc3c0d 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
@@ -38,7 +38,6 @@ import org.rhq.core.util.IntExtractor;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.gui.coregui.client.gwt.OperationGWTService;
import org.rhq.enterprise.gui.coregui.server.util.SerialUtility;
-import org.rhq.enterprise.server.exception.UnscheduleException;
import org.rhq.enterprise.server.operation.OperationManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import
org.rhq.enterprise.server.resource.disambiguation.DefaultDisambiguationUpdateStrategies;
@@ -102,10 +101,11 @@ public class OperationGWTServiceImpl extends AbstractGWTServiceImpl
implements O
}
}
- public void unscheduleResourceOperation(ResourceOperationSchedule
resourceOperationSchedule) throws RuntimeException {
+ public void unscheduleResourceOperation(ResourceOperationSchedule
resourceOperationSchedule)
+ throws RuntimeException {
try {
- operationManager.unscheduleResourceOperation(getSessionSubject(),
resourceOperationSchedule.getJobId().toString(),
- resourceOperationSchedule.getResource().getId());
+ operationManager.unscheduleResourceOperation(getSessionSubject(),
resourceOperationSchedule.getJobId()
+ .toString(), resourceOperationSchedule.getResource().getId());
} catch (RuntimeException e) {
e.printStackTrace();
throw new RuntimeException(ThrowableUtil.getAllMessages(e));
@@ -117,9 +117,13 @@ public class OperationGWTServiceImpl extends AbstractGWTServiceImpl
implements O
*/
public
List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
findRecentCompletedOperations(
int resourceId, PageControl pageControl) throws RuntimeException {
+ Integer resourceIdentifier = null;
+ if (resourceId > 0) {
+ resourceIdentifier = new Integer(resourceId);
+ }
try {
PageList<ResourceOperationLastCompletedComposite>
lastCompletedResourceOps = operationManager
- .findRecentlyCompletedResourceOperations(getSessionSubject(), resourceId,
pageControl);
+ .findRecentlyCompletedResourceOperations(getSessionSubject(),
resourceIdentifier, pageControl);
//translate the returned problem resources to disambiguated links
List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
disambiguatedLastCompletedResourceOps = resourceManager
commit c2b516c7c2ee1baa778df5ec4effab15363a038c
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu Jan 13 08:53:11 2011 -0500
fix bug with recent operations and display when no data returned.
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
index 465b700..a23a8d1 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
@@ -46,7 +46,7 @@ public interface OperationGWTService extends RemoteService {
PageList<GroupOperationHistory>
findGroupOperationHistoriesByCriteria(GroupOperationHistoryCriteria criteria)
throws RuntimeException;
- List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
findRecentCompletedOperations(
+ List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
findRecentCompletedOperations(int resourceId,
PageControl pageControl) throws RuntimeException;
List<DisambiguationReport<ResourceOperationScheduleComposite>>
findScheduledOperations(int pageSize)
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
index 0a7f905..3181eef 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
@@ -146,7 +146,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
leftPane.addMember(recentOobsTitle);
leftPane.addMember(recentOobContent);
recentOobContent.setHeight(20);
- recentOobContent.setContents(RECENT_OOB_NONE);
//rightPane
rightPane = new LocatableVLayout(extendLocatorId("Right"));
@@ -160,7 +159,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
rightPane.addMember(recentConfigUpdatesTitle);
rightPane.addMember(recentConfigurationContent);
recentConfigurationContent.setHeight(20);
- // recentConfigurationContent.setContents(RECENT_CONFIGURATIONS_NONE);
rightPane.addMember(divider3);
//recentOperations.xhtml
LocatableHLayout recentOperationsTitle = new TitleWithIcon(leftPane,
"RecentOperations",
@@ -168,7 +166,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
rightPane.addMember(recentOperationsTitle);
rightPane.addMember(recentOperationsContent);
recentOperationsContent.setHeight(20);
- // recentOperationsContent.setContents(RECENT_OPERATIONS_NONE);
rightPane.addMember(divider4);
//recentEventCounts.xhtml
LocatableHLayout recentEventsTitle = new TitleWithIcon(leftPane,
"RecentEvent",
@@ -305,7 +302,7 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
//fetches five most recent operations.
PageControl pageControl = new PageControl(0, 5);
pageControl.initDefaultOrderingField("ro.createdTime",
PageOrdering.DESC);
-
GWTServiceLookup.getOperationService().findRecentCompletedOperations(pageControl,
+ GWTServiceLookup.getOperationService().findRecentCompletedOperations(resourceId,
pageControl,
new
AsyncCallback<List<DisambiguationReport<ResourceOperationLastCompletedComposite>>>()
{
@Override
@@ -352,7 +349,15 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
column.addMember(row);
}
} else {
- column.setContents(RECENT_OPERATIONS_NONE);
+ LocatableDynamicForm row = new
LocatableDynamicForm(recentOperationsContent
+ .extendLocatorId("ContentForm"));
+ row.setNumCols(3);
+ StaticTextItem none = new StaticTextItem();
+ none.setShowTitle(false);
+ none.setDefaultValue(RECENT_OPERATIONS_NONE);
+ none.setWrap(false);
+ row.setItems(none);
+ column.addMember(row);
}
for (Canvas child : recentOperationsContent.getChildren()) {
child.destroy();
@@ -558,7 +563,15 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
// column.addMember(row);
}
} else {
- column.setContents(RECENT_OOB_NONE);
+ LocatableDynamicForm row = new
LocatableDynamicForm(recentOobContent
+ .extendLocatorId("ContentForm"));
+ row.setNumCols(3);
+ StaticTextItem none = new StaticTextItem();
+ none.setShowTitle(false);
+ none.setDefaultValue(RECENT_OOB_NONE);
+ none.setWrap(false);
+ row.setItems(none);
+ column.addMember(row);
}
recentOobContent.setContents("");
for (Canvas child : recentOobContent.getChildren()) {
@@ -566,7 +579,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
}
recentOobContent.addChild(column);
recentOobContent.markForRedraw();
-
}
});
}
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
index ab200f7..da95be6 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
@@ -131,7 +131,9 @@ public class RecentOperationsDataSource extends
}
}
-
GWTServiceLookup.getOperationService().findRecentCompletedOperations(pageControl,
+ int resourceId = getFilter(request, "id", Integer.class);
+
+ GWTServiceLookup.getOperationService().findRecentCompletedOperations(resourceId,
pageControl,
new
AsyncCallback<List<DisambiguationReport<ResourceOperationLastCompletedComposite>>>()
{
public void onFailure(Throwable throwable) {
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
index c3c2607..44ba3c8 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
@@ -116,10 +116,10 @@ public class OperationGWTServiceImpl extends AbstractGWTServiceImpl
implements O
*
*/
public
List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
findRecentCompletedOperations(
- PageControl pageControl) throws RuntimeException {
+ int resourceId, PageControl pageControl) throws RuntimeException {
try {
PageList<ResourceOperationLastCompletedComposite>
lastCompletedResourceOps = operationManager
- .findRecentlyCompletedResourceOperations(getSessionSubject(), null,
pageControl);
+ .findRecentlyCompletedResourceOperations(getSessionSubject(), resourceId,
pageControl);
//translate the returned problem resources to disambiguated links
List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
disambiguatedLastCompletedResourceOps = resourceManager
commit 6f1dfbadb0160c7c94d3911f96d1b87340a340bf
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu Jan 13 06:55:30 2011 -0500
enable recentPackageHistory, but links still point to portalWar to display history.
Not yet iframed. Will have to be
fixed when content properly converted.
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ContentGWTService.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ContentGWTService.java
index a8da933..7cd0f55 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ContentGWTService.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ContentGWTService.java
@@ -27,6 +27,7 @@ import java.util.List;
import com.google.gwt.user.client.rpc.RemoteService;
import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.InstalledPackageHistory;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.criteria.PackageVersionCriteria;
@@ -41,6 +42,8 @@ public interface ContentGWTService extends RemoteService {
PageList<PackageVersion> findPackageVersionsByCriteria(PackageVersionCriteria
criteria) throws RuntimeException;
+ PageList<InstalledPackageHistory> getInstalledPackageHistoryForResource(int
resourceId, int count);
+
List<Architecture> getArchitectures() throws RuntimeException;
PackageType getResourceCreationPackageType(int resourceTypeId) throws
RuntimeException;
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
index d5dc3cb..0a7f905 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
@@ -25,7 +25,6 @@ import java.util.List;
import java.util.Set;
import com.allen_sauer.gwt.log.client.Log;
-import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.ContentsType;
@@ -39,12 +38,12 @@ import com.smartgwt.client.widgets.form.fields.StaticTextItem;
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
+import org.rhq.core.domain.content.InstalledPackageHistory;
import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.criteria.EventCriteria;
import org.rhq.core.domain.criteria.InstalledPackageCriteria;
import org.rhq.core.domain.criteria.ResourceConfigurationUpdateCriteria;
import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
import org.rhq.core.domain.measurement.composite.MeasurementOOBComposite;
import org.rhq.core.domain.operation.composite.ResourceOperationLastCompletedComposite;
@@ -96,16 +95,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
private String RECENT_PKG_HISTORY_NONE =
MSG.view_resource_inventory_activity_no_recent_pkg_history();
private Timer sparklineReloader = null;
- private long KBYTES = 1024;
- private long MBYTES = KBYTES * KBYTES;
- private long GBYTES = MBYTES * KBYTES;
- private long TBYTES = GBYTES * KBYTES;
- private long PBYTES = TBYTES * KBYTES;
- private long[] byteCount = { PBYTES, TBYTES, GBYTES, MBYTES, KBYTES };
- private String[] byteDesc = { "PB", "TB", "GB",
"MB", "KB" };
- private NumberFormat decimalThreeAndOne = NumberFormat.getFormat("###.#");
- private NumberFormat decimalThreeAndTwo =
NumberFormat.getFormat("###.##");
-
private ResourceComposite resourceComposite;
public ActivityView2(String locatorId, ResourceComposite resourceComposite) {
@@ -150,7 +139,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
leftPane.addMember(recentAlertsTitle);
leftPane.addMember(recentAlertsContent);
recentAlertsContent.setHeight(20);
- // recentAlertsContent.setContents(RECENT_ALERTS_NONE);
leftPane.addMember(divider2);
//recentOOBs.xhtml
LocatableHLayout recentOobsTitle = new TitleWithIcon(leftPane,
"RecentOobs",
@@ -196,7 +184,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
rightPane.addMember(recentPkgHistoryTitle);
rightPane.addMember(recentPkgHistoryContent);
recentPkgHistoryContent.setHeight(20);
- recentPkgHistoryContent.setContents(RECENT_PKG_HISTORY_NONE);
loadData();
}
@@ -223,7 +210,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
public void refresh() {
// int resourceId = this.resourceComposite.getResource().getId();
//
this.iFrame.setContentsURL("/rhq/resource/summary/overview-plain.xhtml?id=" +
resourceId);
- // Log.debug("$$$$$$$$$$$$$ ActivityView2.refresh()");
markForRedraw();
}
@@ -585,79 +571,79 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
});
}
+ /** Fetches recent package history information and updates the DynamicForm instance
with details.
+ */
private void getRecentPkgHistory() {
final int resourceId = this.resourceComposite.getResource().getId();
InstalledPackageCriteria criteria = new InstalledPackageCriteria();
criteria.addFilterResourceId(resourceId);
- // criteria.
PageControl pageControl = new PageControl(0, 5);
criteria.setPageControl(pageControl);
- //
GWTServiceLookup.getContentService().getInstalledPackageHistoryForResource(resourceId, 5,
- // new AsyncCallback<PageList<InstalledPackageHistory>>()
{
- // @Override
- // public void onFailure(Throwable caught) {
- // Log.debug("Error retrieving installed package history
for resource [" + resourceId + "]:"
- // + caught.getMessage());
- // }
- //
- // @Override
- // public void onSuccess(PageList<InstalledPackageHistory>
result) {
- // LocatableVLayout column = new
LocatableVLayout(recentPkgHistoryContent.extendLocatorId("Content"));
- // column.setHeight(10);
- // if (!result.isEmpty()) {
- // for (InstalledPackageHistory history : result) {
- // LocatableDynamicForm row = new
LocatableDynamicForm(recentPkgHistoryContent
- // .extendLocatorId("ContentForm"));
- // row.setNumCols(3);
- //
- // StaticTextItem iconItem = new StaticTextItem();
- // FormItemIcon img = new FormItemIcon();
- //
img.setSrc("subsystems/content/Content_16.png");
- // img.setWidth(16);
- // img.setHeight(16);
- // iconItem.setIcons(img);
- // iconItem.setShowTitle(false);
- //
- // LinkItem link = new LinkItem();
- //
link.setLinkTitle(history.getPackageVersion().getDisplayName());
- //
link.setTitle(history.getPackageVersion().getDisplayName());
- // //
link.setValue(ReportDecorator.GWT_RESOURCE_URL + resourceId +
"/Configuration/History/"
- // // + update.getId());
- //
//link.setValue(rhq/resource/content/audit-trail-item.xhtml?id=10005&selectedHistoryId=10002
- //
link.setValue("rhq/resource/content/audit-trail-item.xhtml?id=" + resourceId
- // + "&selectedHistoryId=" +
history.getId());
- // link.setTarget("_self");
- // link.setShowTitle(false);
- //
- // StaticTextItem time = new StaticTextItem();
- // time.setDefaultValue(new
Date(history.getTimestamp()).toString());
- // time.setShowTitle(false);
- // time.setShowPickerIcon(false);
- // time.setWrap(false);
- // row.setItems(iconItem, link, time);
- //
- // column.addMember(row);
- // }
- // } else {
- // LocatableDynamicForm row = new
LocatableDynamicForm(recentPkgHistoryContent
- // .extendLocatorId("ContentForm"));
- // row.setNumCols(3);
- // StaticTextItem none = new StaticTextItem();
- // none.setShowTitle(false);
- // none.setDefaultValue(RECENT_PKG_HISTORY_NONE);
- // none.setWrap(false);
- // row.setItems(none);
- // column.addMember(row);
- // }
- // //cleanup
- // for (Canvas child : recentPkgHistoryContent.getChildren())
{
- // child.destroy();
- // }
- // recentPkgHistoryContent.addChild(column);
- // recentPkgHistoryContent.markForRedraw();
- // }
- // });
+
GWTServiceLookup.getContentService().getInstalledPackageHistoryForResource(resourceId, 5,
+ new AsyncCallback<PageList<InstalledPackageHistory>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.debug("Error retrieving installed package history for
resource [" + resourceId + "]:"
+ + caught.getMessage());
+ }
+
+ @Override
+ public void onSuccess(PageList<InstalledPackageHistory> result) {
+ LocatableVLayout column = new
LocatableVLayout(recentPkgHistoryContent.extendLocatorId("Content"));
+ column.setHeight(10);
+ if (!result.isEmpty()) {
+ for (InstalledPackageHistory history : result) {
+ LocatableDynamicForm row = new
LocatableDynamicForm(recentPkgHistoryContent
+ .extendLocatorId("ContentForm"));
+ row.setNumCols(3);
+
+ StaticTextItem iconItem = new StaticTextItem();
+ FormItemIcon img = new FormItemIcon();
+ img.setSrc("subsystems/content/Content_16.png");
+ img.setWidth(16);
+ img.setHeight(16);
+ iconItem.setIcons(img);
+ iconItem.setShowTitle(false);
+
+ LinkItem link = new LinkItem();
+ link.setLinkTitle(history.getPackageVersion().getFileName() +
":");
+ link.setTitle(history.getPackageVersion().getFileName() +
":");
+
+ //TODO: spinder. Upgrade link when content available in
coreGui. Not yet iframed correctly.
+
link.setValue("/rhq/resource/content/audit-trail-item.xhtml?id=" + resourceId
+ + "&selectedHistoryId=" +
history.getId());
+ link.setTarget("_self");
+ link.setShowTitle(false);
+
+ StaticTextItem time = new StaticTextItem();
+
time.setDefaultValue(GwtRelativeDurationConverter.format(history.getTimestamp()));
+ time.setShowTitle(false);
+ time.setShowPickerIcon(false);
+ time.setWrap(false);
+ row.setItems(iconItem, link, time);
+
+ column.addMember(row);
+ }
+ } else {
+ LocatableDynamicForm row = new
LocatableDynamicForm(recentPkgHistoryContent
+ .extendLocatorId("ContentForm"));
+ row.setNumCols(3);
+ StaticTextItem none = new StaticTextItem();
+ none.setShowTitle(false);
+ none.setDefaultValue(RECENT_PKG_HISTORY_NONE);
+ none.setWrap(false);
+ row.setItems(none);
+ column.addMember(row);
+ }
+ //cleanup
+ for (Canvas child : recentPkgHistoryContent.getChildren()) {
+ child.destroy();
+ }
+ recentPkgHistoryContent.addChild(column);
+ recentPkgHistoryContent.markForRedraw();
+ }
+ });
}
/** Fetches recent metric information and updates the DynamicForm instance with
i)sparkline information,
@@ -815,7 +801,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
* @return formatted String representation of the last value retrieved.
*/
protected String convertLastValueForDisplay(double lastValue, MeasurementDefinition
md) {
- MeasurementUnits mu = md.getUnits();
String convertedValue = "";
String[] convertedValues = GwtMonitorUtils.formatSimpleMetrics(new double[] {
lastValue }, md);
convertedValue = convertedValues[0];
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ContentGWTServiceImpl.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ContentGWTServiceImpl.java
index 3df2f0b..caee06b 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ContentGWTServiceImpl.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ContentGWTServiceImpl.java
@@ -25,14 +25,17 @@ package org.rhq.enterprise.gui.coregui.server.gwt;
import java.util.List;
import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.InstalledPackageHistory;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.criteria.PackageVersionCriteria;
+import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.gui.coregui.client.gwt.ContentGWTService;
import org.rhq.enterprise.gui.coregui.server.util.SerialUtility;
import org.rhq.enterprise.server.content.ContentManagerLocal;
+import org.rhq.enterprise.server.content.ContentUIManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
/**
@@ -44,7 +47,8 @@ public class ContentGWTServiceImpl extends AbstractGWTServiceImpl
implements Con
private ContentManagerLocal contentManager = LookupUtil.getContentManager();
- //private ContentUIManagerLocal contentUiManager = LookupUtil.getContentUIManager();
+ //TODO: spinder. should the become it's own GWTService?
+ private ContentUIManagerLocal contentUiManager = LookupUtil.getContentUIManager();
public void deletePackageVersion(int packageVersionId) throws RuntimeException {
try {
@@ -64,15 +68,16 @@ public class ContentGWTServiceImpl extends AbstractGWTServiceImpl
implements Con
}
}
- // public PageList<InstalledPackageHistory>
getInstalledPackageHistoryForResource(int resourceId, int count) throws RuntimeException
{
- // try {
- // PageControl pc = new PageControl(0, count);
- // return
SerialUtility.prepare(contentUiManager.getInstalledPackageHistoryForResource(resourceId,
pc),
- // "ContentService.getInstalledPackageHistoryForResource");
- // } catch (Throwable t) {
- // throw new RuntimeException(ThrowableUtil.getAllMessages(t));
- // }
- // }
+ public PageList<InstalledPackageHistory>
getInstalledPackageHistoryForResource(int resourceId, int count)
+ throws RuntimeException {
+ try {
+ PageControl pc = new PageControl(0, count);
+ return
SerialUtility.prepare(contentUiManager.getInstalledPackageHistoryForResource(resourceId,
pc),
+ "ContentService.getInstalledPackageHistoryForResource");
+ } catch (Throwable t) {
+ throw new RuntimeException(ThrowableUtil.getAllMessages(t));
+ }
+ }
public List<Architecture> getArchitectures() throws RuntimeException {
try {
commit 37a311ff079dc49c47ef18c273313e08bc4f747f
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Wed Jan 12 21:27:01 2011 -0500
add format grouping separator for measurement converter.
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMeasurementConverter.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMeasurementConverter.java
index 75a7bc1..a8577e3 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMeasurementConverter.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMeasurementConverter.java
@@ -25,7 +25,7 @@ public class GwtMeasurementConverter {
private static final String NULL_OR_NAN_FORMATTED_VALUE = "--no data
available--";
private static NumberFormat getDefaultNumberFormat() {
- NumberFormat nf = NumberFormat.getFormat("##0.##");
+ NumberFormat nf = NumberFormat.getFormat("##,##0.##");
return nf;
}
@@ -138,7 +138,7 @@ public class GwtMeasurementConverter {
for (int i = 0; i < precisionDigits; i++) {
formatPattern += "#";
}
- nf = NumberFormat.getFormat("#####." + formatPattern);
+ nf = NumberFormat.getFormat("#,###." + formatPattern);
Double[] scaledValues = new Double[values.length];
@@ -223,7 +223,7 @@ public class GwtMeasurementConverter {
}
}
if ((null != minimumFractionDigits) || (null != maximumFractionDigits)) {
- numberFormat = NumberFormat.getFormat("#####." + pattern);
+ numberFormat = NumberFormat.getFormat("#,###." + pattern);
}
String formatted = numberFormat.format(value);
commit c3411cd74988baadc96b6589a0138c796b11875f
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Wed Jan 12 20:10:36 2011 -0500
include scripts in CoreGUI app across all pages.
diff --git
a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index c9d5224..452df0f 100644
---
a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++
b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -63,6 +63,9 @@
<when-type-assignable
class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
+ <!-- External javascript libraries -->
+ <script src="/coregui/js/jquery-1.4.4.js"/>
+ <script src="/coregui/js/jquery.sparkline-1.6.js"/>
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
commit b8574c80a2b2fe9a893dacbf06d28305223076e7
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Wed Jan 12 17:42:12 2011 -0500
i)update configuration upates link
ii)numerous recent metric fixes & display formatting for most recent value.
iii)temporary gwt serializable versions of measurement and display utilities not in
core.domain
# Long term goal is move these elements into the core.domain package to
facilitate GWT RPC serialization
# and correct inclusion as client side components in GWT style uis.
iv) include gquery and sparkline lib versions.
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
index 5e6c4b5..d5dc3cb 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
@@ -43,7 +43,6 @@ import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.criteria.EventCriteria;
import org.rhq.core.domain.criteria.InstalledPackageCriteria;
import org.rhq.core.domain.criteria.ResourceConfigurationUpdateCriteria;
-import org.rhq.core.domain.measurement.DisplayType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
@@ -59,6 +58,7 @@ import org.rhq.enterprise.gui.coregui.client.RefreshableView;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.resource.disambiguation.ReportDecorator;
import org.rhq.enterprise.gui.coregui.client.util.GwtRelativeDurationConverter;
+import org.rhq.enterprise.gui.coregui.client.util.measurement.GwtMonitorUtils;
import org.rhq.enterprise.gui.coregui.client.util.selenium.Locatable;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableCanvas;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
@@ -377,6 +377,9 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
});
}
+ /** Fetches configuration updates and updates the DynamicForm instance with the
latest
+ * config change information.
+ */
private void getRecentConfigurationUpdates() {
final int resourceId = this.resourceComposite.getResource().getId();
ResourceConfigurationUpdateCriteria criteria = new
ResourceConfigurationUpdateCriteria();
@@ -411,9 +414,10 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
iconItem.setShowTitle(false);
LinkItem link = new LinkItem();
-
link.setLinkTitle(MSG.view_resource_inventory_activity_changed_by()
+
link.setLinkTitle(MSG.view_resource_inventory_activity_changed_by() + " "
+ + update.getSubjectName());
+
link.setTitle(MSG.view_resource_inventory_activity_changed_by() + " "
+ update.getSubjectName());
-
link.setTitle(MSG.view_resource_inventory_activity_changed_by() +
update.getSubjectName());
link.setValue(ReportDecorator.GWT_RESOURCE_URL + resourceId +
"/Configuration/History/"
+ update.getId());
link.setTarget("_self");
@@ -656,6 +660,10 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
// });
}
+ /** Fetches recent metric information and updates the DynamicForm instance with
i)sparkline information,
+ * ii) link to recent metric graph for more details and iii) last metric value
formatted to show significant
+ * digits.
+ */
private void getRecentMetrics() {
//display container
final LocatableVLayout column = new
LocatableVLayout(recentMeasurementsContent.extendLocatorId("Content"));
@@ -696,79 +704,86 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
@Override
public void
onSuccess(List<List<MeasurementDataNumericHighLowComposite>> results) {
- //iterate over the retrieved charting data
- for (int index = 0; index < displayOrder.length; index++) {
-
- //retrieve the correct measurement definition
- MeasurementDefinition md =
measurementDefMap.get(displayOrder[index]);
-
- //load the data results for the given metric definition
- List<MeasurementDataNumericHighLowComposite> data =
results.get(index);
-
- //locate last and minimum values.
- double lastValue = -1;
- double minValue = Double.MAX_VALUE;//
- for (MeasurementDataNumericHighLowComposite d : data) {
- if (!Double.isNaN(d.getValue())) {
- if (d.getValue() < minValue) {
- minValue = d.getValue();
+ if (!results.isEmpty()) {
+ //iterate over the retrieved charting data
+ for (int index = 0; index < displayOrder.length; index++) {
+
+ //retrieve the correct measurement definition
+ MeasurementDefinition md =
measurementDefMap.get(displayOrder[index]);
+
+ //load the data results for the given metric definition
+ List<MeasurementDataNumericHighLowComposite> data =
results.get(index);
+
+ //locate last and minimum values.
+ double lastValue = -1;
+ double minValue = Double.MAX_VALUE;//
+ for (MeasurementDataNumericHighLowComposite d : data) {
+ if ((!Double.isNaN(d.getValue()))
+ &&
(String.valueOf(d.getValue()).indexOf("NaN") == -1)) {
+ if (d.getValue() < minValue) {
+ minValue = d.getValue();
+ }
+ lastValue = d.getValue();
}
- lastValue = d.getValue();
}
- }
- //collapse the data into comma delimited list for consumption by
third party javascript library(jquery.sparkline)
- String commaDelimitedList = "";
+ //collapse the data into comma delimited list for consumption
by third party javascript library(jquery.sparkline)
+ String commaDelimitedList = "";
- for (MeasurementDataNumericHighLowComposite d : data) {
- if (!Double.isNaN(d.getValue())) {
- commaDelimitedList += d.getValue() + ",";
+ for (MeasurementDataNumericHighLowComposite d : data) {
+ if ((!Double.isNaN(d.getValue()))
+ &&
(String.valueOf(d.getValue()).indexOf("NaN") == -1)) {
+ commaDelimitedList += d.getValue() + ",";
+ }
}
- }
- LocatableDynamicForm row = new
LocatableDynamicForm(column.extendLocatorId("ContentForm"));
- row.setNumCols(3);
- HTMLFlow graph = new HTMLFlow();
- // String contents = "<span
id='sparkline_" + index + "' class='dynamicsparkline'
width='0'>"
- // + commaDelimitedList +
"</span>";
- String contents = "<span id='sparkline_" + index
+ "' class='dynamicsparkline' width='0' "
- + "values='" + commaDelimitedList +
"'>...</span>";
- graph.setContents(contents);
- graph.setContentsType(ContentsType.PAGE);
- //diable scrollbars on span
- graph.setScrollbarSize(0);
-
- CanvasItem graphContainer = new CanvasItem();
- graphContainer.setShowTitle(false);
- graphContainer.setHeight(16);
- graphContainer.setWidth(60);
- graphContainer.setCanvas(graph);
-
- //Link/title element
- LinkItem link = new LinkItem();
- link.setLinkTitle(md.getDisplayName() + ":");
- //TODO: spinder, change link whenever portal.war/graphing is
removed.
-
link.setValue("/resource/common/monitor/Visibility.do?mode=chartSingleMetricSingleResource&id="
- + resourceId + "&m=" + md.getId());
- link.setTarget("_self");
- link.setShowTitle(false);
+ LocatableDynamicForm row = new
LocatableDynamicForm(column.extendLocatorId("ContentForm"));
+ row.setNumCols(3);
+ HTMLFlow graph = new HTMLFlow();
+ // String contents = "<span
id='sparkline_" + index + "' class='dynamicsparkline'
width='0'>"
+ // + commaDelimitedList +
"</span>";
+ String contents = "<span id='sparkline_" +
index + "' class='dynamicsparkline' width='0' "
+ + "values='" + commaDelimitedList +
"'>...</span>";
+ graph.setContents(contents);
+ graph.setContentsType(ContentsType.PAGE);
+ //diable scrollbars on span
+ graph.setScrollbarSize(0);
+
+ CanvasItem graphContainer = new CanvasItem();
+ graphContainer.setShowTitle(false);
+ graphContainer.setHeight(16);
+ graphContainer.setWidth(60);
+ graphContainer.setCanvas(graph);
+
+ //Link/title element
+ LinkItem link = new LinkItem();
+ link.setLinkTitle(md.getDisplayName() + ":");
+ //TODO: spinder, change link whenever portal.war/graphing is
removed.
+ link
+
.setValue("/resource/common/monitor/Visibility.do?mode=chartSingleMetricSingleResource&id="
+ + resourceId + "&m=" + md.getId());
+ link.setTarget("_self");
+ link.setShowTitle(false);
- //Value
- StaticTextItem value = new StaticTextItem();
- String convertedValue = lastValue + " " +
md.getUnits();
- convertedValue = convertLastValueForDisplay(lastValue, md);
-
- value.setDefaultValue(convertedValue);
- value.setShowTitle(false);
- value.setShowPickerIcon(false);
- value.setWrap(false);
- row.setItems(graphContainer, link, value);
- //if graph content returned
- if (commaDelimitedList.trim().length() > 100) {
- column.addMember(row);
+ //Value
+ StaticTextItem value = new StaticTextItem();
+ String convertedValue = lastValue + " " +
md.getUnits();
+ convertedValue = convertLastValueForDisplay(lastValue, md);
+
+ value.setDefaultValue(convertedValue);
+ value.setShowTitle(false);
+ value.setShowPickerIcon(false);
+ value.setWrap(false);
+ row.setItems(graphContainer, link, value);
+ //if graph content returned
+ if ((md.getName().trim().indexOf("Trait.") == -1)
&& (lastValue != -1)) {
+ column.addMember(row);
+ }
}
+ //call out to 3rd party javascript lib
+ graphSparkLines();
+ } else {
+ column.setContents(RECENT_MEASUREMENTS_NONE);
}
- //call out to 3rd party javascript lib
- graphSparkLines();
}
});
@@ -800,32 +815,10 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
* @return formatted String representation of the last value retrieved.
*/
protected String convertLastValueForDisplay(double lastValue, MeasurementDefinition
md) {
-
+ MeasurementUnits mu = md.getUnits();
String convertedValue = "";
- if (md.getUnits() == MeasurementUnits.BYTES) {
- double value;
- boolean converted = false;
- for (int i = 0; (!converted && (i < byteCount.length)); i++) {
- //detect first byte translation 1 > N < 1000
- value = lastValue / byteCount[i];
- if (value > 1) {
- converted = true;
- convertedValue = md.getDisplayType() == DisplayType.SUMMARY ?
(decimalThreeAndOne.format(value) + byteDesc[i])
- : (decimalThreeAndTwo.format(value)) + byteDesc[i];
- }
- }
- } else if (md.getUnits() == MeasurementUnits.PERCENTAGE) {
- double value = lastValue * 100;
- convertedValue = (md.getDisplayType() == DisplayType.SUMMARY ?
(decimalThreeAndOne.format(value))
- : (decimalThreeAndTwo.format(value)))
- + "%";
- } else if (md.getUnits() == MeasurementUnits.NONE) {
- double value = lastValue;
- convertedValue = md.getDisplayType() == DisplayType.SUMMARY ?
(decimalThreeAndOne.format(value))
- : (decimalThreeAndTwo.format(value));
- } else {
- convertedValue = decimalThreeAndTwo.format(lastValue / 100) + md.getUnits();
- }
+ String[] convertedValues = GwtMonitorUtils.formatSimpleMetrics(new double[] {
lastValue }, md);
+ convertedValue = convertedValues[0];
return convertedValue;
}
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMeasurementConverter.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMeasurementConverter.java
new file mode 100644
index 0000000..75a7bc1
--- /dev/null
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMeasurementConverter.java
@@ -0,0 +1,353 @@
+package org.rhq.enterprise.gui.coregui.client.util.measurement;
+
+//import java.text.NumberFormat;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.google.gwt.i18n.client.NumberFormat;
+import com.google.gwt.i18n.client.TimeZone;
+
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits;
+import org.rhq.core.domain.measurement.util.MeasurementConversionException;
+
+/** An RPC gwt serializable implemenation of the MeasurementConverter
+ * utility.
+ *
+ * @author Simeon Pinder
+ */
+public class GwtMeasurementConverter {
+
+ public static TimeZone tz = null;
+
+ private static final int MAX_PRECISION_DIGITS = 4;
+ private static final String NULL_OR_NAN_FORMATTED_VALUE = "--no data
available--";
+
+ private static NumberFormat getDefaultNumberFormat() {
+ NumberFormat nf = NumberFormat.getFormat("##0.##");
+ return nf;
+ }
+
+ public static Double scale(MeasurementNumericValueAndUnits origin, MeasurementUnits
targetUnits)
+ throws MeasurementConversionException {
+ MeasurementUnits originUnits = origin.getUnits();
+ Double originValue = origin.getValue();
+
+ return originValue * MeasurementUnits.calculateOffset(originUnits, targetUnits);
+ }
+
+ public static Double scale(Double origin, MeasurementUnits targetUnits) throws
MeasurementConversionException {
+ boolean wasNegative = false;
+ if (origin < 0) {
+ wasNegative = true;
+ origin = -origin;
+ }
+
+ MeasurementUnits baseUnit = targetUnits.getBaseUnits();
+ MeasurementNumericValueAndUnits valueAndUnits = new
MeasurementNumericValueAndUnits(origin, baseUnit);
+
+ Double results = scale(valueAndUnits, targetUnits);
+ if (wasNegative) {
+ results = -results;
+ }
+
+ return results;
+ }
+
+ public static String format(String value, MeasurementUnits targetUnits) {
+ if (targetUnits == null) {
+ return value;
+ } else {
+ return value + targetUnits;
+ }
+ }
+
+ /**
+ * Formats the given array of double values: determines the necessary precision such
that when formatted, they are
+ * distinct and reasonable to look at. For example, for values { 1.45 1.46 1.47 1.48
1.49 } the desired precision is
+ * 2 - less precision loses significant digits, and more precision provides no added
benefit. Max precision is
+ * bounded for presentation considerations.
+ *
+ * @param values the values to be formatted
+ * @param targetUnits the target units for the values
+ * @param bestFit whether or not to use a normalized scale for the family of units
+ *
+ * @return the formatted values
+ */
+ public static String[] formatToSignificantPrecision(double[] values, MeasurementUnits
targetUnits, boolean bestFit) {
+ if ((null == values) || (values.length == 0)) {
+ return null;
+ }
+
+ MeasurementUnits originalUnits = targetUnits;
+
+ /*
+ * in the overwhelming majority of cases, you're going to want to apply a
bestFit
+ * to the passed data, but it's not required; it's perfectly possible to
allow a
+ * list of doubles to be formatted without being fit, in which case the
targetUnits
+ * will be part of the formatted display for each result element
+ */
+ if (bestFit) {
+ // find bestFit units by taking the average
+ Double average = 0.0;
+
+ for (int i = 0, sz = values.length; i < sz; i++) {
+ /*
+ * adding fractional amount iterative leads to greater
+ * error, but prevents overflow on large data sets
+ */
+ average += (values[i] / sz);
+ }
+
+ MeasurementNumericValueAndUnits fittedAverage = fit(average, targetUnits);
+ //noinspection UnnecessaryLocalVariable
+ MeasurementUnits fittedUnits = fittedAverage.getUnits();
+
+ /*
+ * and change the local reference to targetUnits, so that the same logic
+ * can be used both for the bestFit and non-bestFit computations
+ */
+ targetUnits = fittedUnits;
+ }
+
+ @SuppressWarnings("unused")
+ Set<String> existingStrings; // technically this *is* unused because
+ int precisionDigits = 1;
+ boolean scaleWithMorePrecision = true;
+ String[] results = new String[values.length];
+ NumberFormat nf = getDefaultNumberFormat();
+
+ /*
+ * we scale at most to MAX_PRECISION_DIGITS to allow for presentation limits
+ *
+ * increase the maxPrecisionDigits in the while condition
+ * itself to ensure it gets done for every loop
+ */
+ while (scaleWithMorePrecision && (++precisionDigits <=
MAX_PRECISION_DIGITS)) {
+ /*
+ * make the assumption that we no longer need to scale beyond this iteration
+ */
+ scaleWithMorePrecision = false;
+
+ /*
+ * we need to record the uniquely formatted values so we can determine
+ */
+ existingStrings = new HashSet<String>();
+ String formatPattern = "";
+ for (int i = 0; i < precisionDigits; i++) {
+ formatPattern += "#";
+ }
+ nf = NumberFormat.getFormat("#####." + formatPattern);
+
+ Double[] scaledValues = new Double[values.length];
+
+ for (int i = 0; i < scaledValues.length; i++) {
+ /*
+ * For relative units apply the scale now, prior to the nf.format(),
since we are not using format( Double...).
+ * Otherwise, apply standard multi-unit scaling.
+ */
+ if (MeasurementUnits.Family.RELATIVE == originalUnits.getFamily()) {
+ scaledValues[i] = MeasurementUnits.scaleUp(values[i],
originalUnits);
+ } else {
+ scaledValues[i] = scale(new
MeasurementNumericValueAndUnits(values[i], originalUnits), targetUnits);
+ }
+ }
+
+ for (int i = 0; i < results.length; i++) {
+ /*
+ * JUST get the formatted value, specifically DON'T tack on the
formatted units yet;
+ * we do this to see how many units we'll have to scale to afterwards
(outside this
+ * while loop) to make the array of values passed to us unique
+ */
+ String formatted = nf.format(scaledValues[i]);
+
+ /*
+ * check whether formatted value was in the set or not; if it was, we
have to
+ * loop, but only if we're not not already at our maximum precision
+ */
+ boolean wasNewElement = existingStrings.add(formatted);
+
+ if ((!wasNewElement) && (precisionDigits <
MAX_PRECISION_DIGITS)) {
+ scaleWithMorePrecision = true;
+ break;
+ }
+
+ results[i] = formatted;
+ }
+ }
+
+ /*
+ * we did the best we could in terms of trying to find a precision that adds the
most
+ * uniqueness to the given set of values, NOW tack on the formatted value for the
units
+ */
+ for (int i = 0; i < results.length; i++) {
+ results[i] = format(results[i], targetUnits);
+ }
+
+ return results;
+ }
+
+ public static String format(Double value, MeasurementUnits targetUnits, boolean
bestFit) {
+ return format(value, targetUnits, bestFit, null, null);
+ }
+
+ public static String format(Double value, MeasurementUnits targetUnits, boolean
bestFit,
+ Integer minimumFractionDigits, Integer maximumFractionDigits) {
+ if (value == null || Double.isNaN(value)) {
+ return NULL_OR_NAN_FORMATTED_VALUE;
+ }
+ if (bestFit) {
+ MeasurementNumericValueAndUnits valueAndUnits = fit(value, targetUnits);
+
+ value = valueAndUnits.getValue();
+ targetUnits = valueAndUnits.getUnits();
+ }
+
+ // apply relative scale at presentation time
+ if (MeasurementUnits.Family.RELATIVE == targetUnits.getFamily()) {
+ value = MeasurementUnits.scaleUp(value, targetUnits);
+ }
+
+ NumberFormat numberFormat = getDefaultNumberFormat();
+ String pattern = "";
+
+ if (null != minimumFractionDigits) {
+ for (int i = 0; i < minimumFractionDigits; i++) {
+ pattern += "0";
+ }
+ }
+ if (null != maximumFractionDigits) {
+ for (int i = 0; i < maximumFractionDigits; i++) {
+ pattern += "#";
+ }
+ }
+ if ((null != minimumFractionDigits) || (null != maximumFractionDigits)) {
+ numberFormat = NumberFormat.getFormat("#####." + pattern);
+ }
+
+ String formatted = numberFormat.format(value);
+
+ return format(formatted, targetUnits);
+ }
+
+ public static String scaleAndFormat(Double origin, MeasurementSchedule
targetSchedule, boolean bestFit)
+ throws MeasurementConversionException {
+ MeasurementUnits targetUnits = targetSchedule.getDefinition().getUnits();
+
+ return scaleAndFormat(origin, targetUnits, bestFit, null, null);
+ }
+
+ public static String scaleAndFormat(Double origin, MeasurementUnits targetUnits,
boolean bestFit)
+ throws MeasurementConversionException {
+
+ return scaleAndFormat(origin, targetUnits, bestFit, null, null);
+ }
+
+ public static String scaleAndFormat(Double origin, MeasurementUnits targetUnits,
boolean bestFit,
+ Integer minimumFractionDigits, Integer maximumFractionDigits) throws
MeasurementConversionException {
+
+ MeasurementUnits baseUnits = targetUnits.getBaseUnits();
+ MeasurementNumericValueAndUnits valueAndUnits = new
MeasurementNumericValueAndUnits(origin, baseUnits);
+ Double scaledMagnitude = scale(valueAndUnits, targetUnits);
+
+ return format(scaledMagnitude, targetUnits, bestFit);
+ }
+
+ public static MeasurementNumericValueAndUnits fit(Double origin, MeasurementUnits
units) {
+ return fit(origin, units, null, null);
+ }
+
+ public static MeasurementNumericValueAndUnits fit(Double origin, MeasurementUnits
units, MeasurementUnits lowUnits,
+ MeasurementUnits highUnits) {
+
+ // work-around for the various Chart descendants not properly setting their units
field;
+ if (null == units) {
+ return new MeasurementNumericValueAndUnits(origin, units);
+ }
+
+ // by definition, absolutely specified units don't scale to anything
+ if ((MeasurementUnits.Family.ABSOLUTE == units.getFamily())
+ || (MeasurementUnits.Family.DURATION == units.getFamily())) {
+ return new MeasurementNumericValueAndUnits(origin, units);
+ }
+
+ // by definition relative-valued units are self-scaled (converted at formatting)
+ if (MeasurementUnits.Family.RELATIVE == units.getFamily()) {
+ return new MeasurementNumericValueAndUnits(origin, units);
+ }
+
+ if (MeasurementUnits.Family.TEMPERATURE == units.getFamily()) {
+ return new MeasurementNumericValueAndUnits(origin, units);
+ }
+
+ // if the magnitude is zero, the best-fit also will spin around forever since it
won't change
+ if (Math.abs(origin) < 1e-9) {
+ return new MeasurementNumericValueAndUnits(origin, units);
+ }
+
+ boolean wasNegative = false;
+
+ if (origin < 0) {
+ wasNegative = true;
+ origin = -origin;
+ }
+
+ MeasurementNumericValueAndUnits currentValueAndUnits;
+ MeasurementNumericValueAndUnits nextValueAndUnits = new
MeasurementNumericValueAndUnits(origin, units);
+
+ // first, make the value smaller if it's too big
+ int maxOrdinal = (highUnits != null) ? (highUnits.ordinal() + 1) :
MeasurementUnits.values().length;
+
+ do {
+ currentValueAndUnits = nextValueAndUnits;
+
+ int nextOrdinal = currentValueAndUnits.getUnits().ordinal() + 1;
+ if (nextOrdinal == maxOrdinal) {
+ // we could theoretically get bigger, but we don't have any units to
represent that
+ break;
+ }
+
+ MeasurementUnits biggerUnits = MeasurementUnits.values()[nextOrdinal];
+ if (biggerUnits.getFamily() != currentValueAndUnits.getUnits().getFamily())
{
+ // we're as big as we can get, break out of the loop so we can
return
+ break;
+ }
+
+ Double smallerValue = scale(currentValueAndUnits, biggerUnits);
+
+ nextValueAndUnits = new MeasurementNumericValueAndUnits(smallerValue,
biggerUnits);
+ } while (nextValueAndUnits.getValue() > 1.0);
+
+ // next, make the value bigger if it's too small
+ int minOrdinal = (lowUnits != null) ? (lowUnits.ordinal() - 1) : -1;
+
+ while (currentValueAndUnits.getValue() < 1.0) {
+ int nextOrdinal = currentValueAndUnits.getUnits().ordinal() - 1;
+ if (nextOrdinal == minOrdinal) {
+ // we could theoretically get smaller, but we don't have any units to
represent that
+ break;
+ }
+
+ MeasurementUnits smallerUnits = MeasurementUnits.values()[nextOrdinal];
+ if (smallerUnits.getFamily() != currentValueAndUnits.getUnits().getFamily())
{
+ // we're as small as we can get, break out of the loop so we can
return
+ break;
+ }
+
+ Double biggerValue = scale(currentValueAndUnits, smallerUnits);
+
+ nextValueAndUnits = new MeasurementNumericValueAndUnits(biggerValue,
smallerUnits);
+
+ currentValueAndUnits = nextValueAndUnits;
+ }
+
+ if (wasNegative) {
+ return new MeasurementNumericValueAndUnits(-currentValueAndUnits.getValue(),
currentValueAndUnits
+ .getUnits());
+ }
+
+ return currentValueAndUnits;
+ }
+
+}
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMonitorUtils.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMonitorUtils.java
new file mode 100644
index 0000000..786c2f8
--- /dev/null
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/measurement/GwtMonitorUtils.java
@@ -0,0 +1,47 @@
+package org.rhq.enterprise.gui.coregui.client.util.measurement;
+
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+
+/** An RPC gwt serializable implemenation of parts of MonitorUtils
+ * utility.
+ *
+ * @author Joseph Marques
+ * @author Simeon Pinder
+ */
+public class GwtMonitorUtils {
+ public static final String RO = "ro";
+ public static final String LASTN = "lastN";
+ public static final String UNIT = "unit";
+ public static final String BEGIN = "begin";
+ public static final String END = "end";
+
+ public static final int DEFAULT_CURRENTHEALTH_LASTN = 8;
+
+ public static final int THRESHOLD_BASELINE_VALUE = 1;
+ public static final String THRESHOLD_BASELINE_LABEL = "Baseline";
+ public static final int THRESHOLD_HIGH_RANGE_VALUE = 2;
+ public static final String THRESHOLD_HIGH_RANGE_LABEL = "HighRange";
+ public static final int THRESHOLD_LOW_RANGE_VALUE = 3;
+ public static final String THRESHOLD_LOW_RANGE_LABEL = "LowRange";
+
+ public static final int THRESHOLD_UNDER_VALUE = 1;
+ public static final int THRESHOLD_OVER_VALUE = 2;
+
+ /**
+ * Formats the passed summary. The userLocale is currently ignored
+ * @param summary MetricDisplaySummary with some values
+ * @param userLocale ignored
+ */
+ public static String[] formatSimpleMetrics(double[] summary, MeasurementDefinition
md) {
+ String units = md.getUnits().getName();
+ if (units.length() < 1) {
+ units = MeasurementUnits.NONE.name();
+ }
+
+ String[] formattedValues =
GwtMeasurementConverter.formatToSignificantPrecision(summary, MeasurementUnits
+ .valueOf(units), true);
+
+ return formattedValues;
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 6d1fa4a..7659443 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -8,7 +8,7 @@
var isomorphicDir = "org.rhq.enterprise.gui.coregui.CoreGUI/sc/";
</script>
<script type="text/javascript"
src="js/jquery-1.4.4.js"></script>
- <script type="text/javascript"
src="js/jquery.sparkline.js"></script>
+ <script type="text/javascript"
src="js/jquery.sparkline-1.6.js"></script>
<!-- support internationalized characters -->
<meta http-equiv="content-type"
content="text/html;charset=utf-8" />
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.4.4.js
b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.4.4.js
new file mode 100644
index 0000000..c53482c
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.4.4.js
@@ -0,0 +1,7179 @@
+/*!
+ * jQuery JavaScript Library v1.4.4
+ *
http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ *
http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 11 19:04:53 2010 -0500
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // A simple way to check for HTML strings or ID strings
+ // (both of which we optimize for)
+ quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
+
+ // Is it a simple selector
+ isSimple = /^.[^:#\[\.,]*$/,
+
+ // Check if a string has a non-whitespace character in it
+ rnotwhite = /\S/,
+ rwhite = /\s/,
+
+ // Used for trimming whitespace
+ trimLeft = /^\s+/,
+ trimRight = /\s+$/,
+
+ // Check for non-word characters
+ rnonword = /\W/,
+
+ // Check for digits
+ rdigit = /\d/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+ rvalidtokens =
/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+ // Useragent RegExp
+ rwebkit = /(webkit)[ \/]([\w.]+)/,
+ ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+ rmsie = /(msie) ([\w.]+)/,
+ rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+ // Keep a UserAgent string for use with jQuery.browser
+ userAgent = navigator.userAgent,
+
+ // For matching the engine and version of the browser
+ browserMatch,
+
+ // Has the ready events already been bound?
+ readyBound = false,
+
+ // The functions to execute on DOM ready
+ readyList = [],
+
+ // The ready event handler
+ DOMContentLoaded,
+
+ // Save a reference to some core methods
+ toString = Object.prototype.toString,
+ hasOwn = Object.prototype.hasOwnProperty,
+ push = Array.prototype.push,
+ slice = Array.prototype.slice,
+ trim = String.prototype.trim,
+ indexOf = Array.prototype.indexOf,
+
+ // [[Class]] -> type pairs
+ class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+ init: function( selector, context ) {
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), or $(undefined)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // The body element only exists once, optimize finding it
+ if ( selector === "body" && !context && document.body ) {
+ this.context = document;
+ this[0] = document.body;
+ this.selector = "body";
+ this.length = 1;
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ match = quickExpr.exec( selector );
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ doc = (context ? context.ownerDocument || context : document);
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ ret = rsingleTag.exec( selector );
+
+ if ( ret ) {
+ if ( jQuery.isPlainObject( context ) ) {
+ selector = [ document.createElement( ret[1] ) ];
+ jQuery.fn.attr.call( selector, context, true );
+
+ } else {
+ selector = [ doc.createElement( ret[1] ) ];
+ }
+
+ } else {
+ ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+ selector = (ret.cacheable ? ret.fragment.cloneNode(true) :
ret.fragment).childNodes;
+ }
+
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $("#id")
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $("TAG")
+ } else if ( !context && !rnonword.test( selector ) ) {
+ this.selector = selector;
+ this.context = document;
+ selector = document.getElementsByTagName( selector );
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return (context || rootjQuery).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return jQuery( context ).find( selector );
+ }
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if (selector.selector !== undefined) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.4.4",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return slice.call( this, 0 );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = jQuery();
+
+ if ( jQuery.isArray( elems ) ) {
+ push.apply( ret, elems );
+
+ } else {
+ jQuery.merge( ret, elems );
+ }
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" ) {
+ ret.selector = this.selector + (this.selector ? " " : "") +
selector;
+ } else if ( name ) {
+ ret.selector = this.selector + "." + name + "(" + selector +
")";
+ }
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Attach the listeners
+ jQuery.bindReady();
+
+ // If the DOM is already ready
+ if ( jQuery.isReady ) {
+ // Execute the function immediately
+ fn.call( document, jQuery );
+
+ // Otherwise, remember the function for later
+ } else if ( readyList ) {
+ // Add the function to the wait list
+ readyList.push( fn );
+ }
+
+ return this;
+ },
+
+ eq: function( i ) {
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, +i + 1 );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ),
+ "slice", slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || jQuery(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray =
jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ window.$ = _$;
+
+ if ( deep ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+ // A third-party is pushing the ready event forwards
+ if ( wait === true ) {
+ jQuery.readyWait--;
+ }
+
+ // Make sure that the DOM is not already loaded
+ if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket
#5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ if ( readyList ) {
+ // Execute all of them
+ var fn,
+ i = 0,
+ ready = readyList;
+
+ // Reset the list of functions
+ readyList = null;
+
+ while ( (fn = ready[ i++ ]) ) {
+ fn.call( document, jQuery );
+ }
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger( "ready" ).unbind( "ready" );
+ }
+ }
+ }
+ },
+
+ bindReady: function() {
+ if ( readyBound ) {
+ return;
+ }
+
+ readyBound = true;
+
+ // Catch cases where $(document).ready() is called after the
+ // browser event has already occurred.
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent("onreadystatechange", DOMContentLoaded);
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var toplevel = false;
+
+ try {
+ toplevel = window.frameElement == null;
+ } catch(e) {}
+
+ if ( document.documentElement.doScroll && toplevel ) {
+ doScrollCheck();
+ }
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ // A crude way of determining if an object is a window
+ isWindow: function( obj ) {
+ return obj && typeof obj === "object" &&
"setInterval" in obj;
+ },
+
+ isNaN: function( obj ) {
+ return obj == null || !rdigit.test( obj ) || isNaN( obj );
+ },
+
+ type: function( obj ) {
+ return obj == null ?
+ String( obj ) :
+ class2type[ toString.call(obj) ] || "object";
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType ||
jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ for ( var name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw msg;
+ },
+
+ parseJSON: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from
http://json.org/json2.js
+ if ( rvalidchars.test(data.replace(rvalidescape, "@")
+ .replace(rvalidtokens, "]")
+ .replace(rvalidbraces, "")) ) {
+
+ // Try to use the native JSON parser first
+ return window.JSON && window.JSON.parse ?
+ window.JSON.parse( data ) :
+ (new Function("return " + data))();
+
+ } else {
+ jQuery.error( "Invalid JSON: " + data );
+ }
+ },
+
+ noop: function() {},
+
+ // Evalulates a script in a global context
+ globalEval: function( data ) {
+ if ( data && rnotwhite.test(data) ) {
+ // Inspired by code by Andrea Giammarchi
+ //
http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom...
+ var head = document.getElementsByTagName("head")[0] ||
document.documentElement,
+ script = document.createElement("script");
+
+ script.type = "text/javascript";
+
+ if ( jQuery.support.scriptEval ) {
+ script.appendChild( document.createTextNode( data ) );
+ } else {
+ script.text = data;
+ }
+
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709).
+ head.insertBefore( script, head.firstChild );
+ head.removeChild( script );
+ }
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0,
+ length = object.length,
+ isObj = length === undefined || jQuery.isFunction(object);
+
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.apply( object[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( object[ i++ ], args ) === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( var value = object[0];
+ i < length && callback.call( value, i, value ) !== false; value =
object[++i] ) {}
+ }
+ }
+
+ return object;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: trim ?
+ function( text ) {
+ return text == null ?
+ "" :
+ trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ text.toString().replace( trimLeft, "" ).replace( trimRight, ""
);
+ },
+
+ // results is for internal usage only
+ makeArray: function( array, results ) {
+ var ret = results || [];
+
+ if ( array != null ) {
+ // The window, strings (and functions) also have 'length'
+ // The extra typeof function check is to prevent crashes
+ // in Safari 2 (See: #3039)
+ // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+ var type = jQuery.type(array);
+
+ if ( array.length == null || type === "string" || type ===
"function" || type === "regexp" || jQuery.isWindow( array ) ) {
+ push.call( ret, array );
+ } else {
+ jQuery.merge( ret, array );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array ) {
+ if ( array.indexOf ) {
+ return array.indexOf( elem );
+ }
+
+ for ( var i = 0, length = array.length; i < length; i++ ) {
+ if ( array[ i ] === elem ) {
+ return i;
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var i = first.length,
+ j = 0;
+
+ if ( typeof second.length === "number" ) {
+ for ( var l = second.length; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [], retVal;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var ret = [], value;
+
+ // Go through the array, translating each of the items to their
+ // new value (or values).
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ return ret.concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ proxy: function( fn, proxy, thisObject ) {
+ if ( arguments.length === 2 ) {
+ if ( typeof proxy === "string" ) {
+ thisObject = fn;
+ fn = thisObject[ proxy ];
+ proxy = undefined;
+
+ } else if ( proxy && !jQuery.isFunction( proxy ) ) {
+ thisObject = proxy;
+ proxy = undefined;
+ }
+ }
+
+ if ( !proxy && fn ) {
+ proxy = function() {
+ return fn.apply( thisObject || this, arguments );
+ };
+ }
+
+ // Set the guid of unique handler to the same of original handler, so it can be
removed
+ if ( fn ) {
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+ }
+
+ // So proxy can be declared as an argument
+ return proxy;
+ },
+
+ // Mutifunctional method to get and set values to a collection
+ // The value/s can be optionally by executed if its a function
+ access: function( elems, key, value, exec, fn, pass ) {
+ var length = elems.length;
+
+ // Setting many attributes
+ if ( typeof key === "object" ) {
+ for ( var k in key ) {
+ jQuery.access( elems, k, key[k], exec, fn, value );
+ }
+ return elems;
+ }
+
+ // Setting one attribute
+ if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = !pass && exec && jQuery.isFunction(value);
+
+ for ( var i = 0; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value,
pass );
+ }
+
+ return elems;
+ }
+
+ // Getting an attribute
+ return length ? fn( elems[0], key ) : undefined;
+ },
+
+ now: function() {
+ return (new Date()).getTime();
+ },
+
+ // Use of jQuery.browser is frowned upon.
+ // More details:
http://docs.jquery.com/Utilities/jQuery.browser
+ uaMatch: function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = rwebkit.exec( ua ) ||
+ ropera.exec( ua ) ||
+ rmsie.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+ [];
+
+ return { browser: match[1] || "", version: match[2] || "0" };
+ },
+
+ browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp
Object".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+ jQuery.browser[ browserMatch.browser ] = true;
+ jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+ jQuery.browser.safari = true;
+}
+
+if ( indexOf ) {
+ jQuery.inArray = function( elem, array ) {
+ return indexOf.call( array, elem );
+ };
+}
+
+// Verify that \s matches non-breaking spaces
+// (IE fails on this test)
+if ( !rwhite.test( "\xA0" ) ) {
+ trimLeft = /^[\s\xA0]+/;
+ trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+ DOMContentLoaded = function() {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ };
+
+} else if ( document.attachEvent ) {
+ DOMContentLoaded = function() {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket
#5443).
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
+ }
+ };
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+ if ( jQuery.isReady ) {
+ return;
+ }
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ //
http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch(e) {
+ setTimeout( doScrollCheck, 1 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+}
+
+// Expose jQuery to the global object
+return (window.jQuery = window.$ = jQuery);
+
+})();
+
+
+(function() {
+
+ jQuery.support = {};
+
+ var root = document.documentElement,
+ script = document.createElement("script"),
+ div = document.createElement("div"),
+ id = "script" + jQuery.now();
+
+ div.style.display = "none";
+ div.innerHTML = " <link/><table></table><a href='/a'
style='color:red;float:left;opacity:.55;'>a</a><input
type='checkbox'/>";
+
+ var all = div.getElementsByTagName("*"),
+ a = div.getElementsByTagName("a")[0],
+ select = document.createElement("select"),
+ opt = select.appendChild( document.createElement("option") );
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return;
+ }
+
+ jQuery.support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType === 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText insted)
+ style: /red/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.55$/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: div.getElementsByTagName("input")[0].value === "on",
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Will be defined later
+ deleteExpando: true,
+ optDisabled: false,
+ checkClone: false,
+ scriptEval: false,
+ noCloneEvent: true,
+ boxModel: null,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableHiddenOffsets: true
+ };
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as diabled)
+ select.disabled = true;
+ jQuery.support.optDisabled = !opt.disabled;
+
+ script.type = "text/javascript";
+ try {
+ script.appendChild( document.createTextNode( "window." + id + "=1;"
) );
+ } catch(e) {}
+
+ root.insertBefore( script, root.firstChild );
+
+ // Make sure that the execution of code works by injecting a script
+ // tag with appendChild/createTextNode
+ // (IE doesn't support this, fails, and uses .text instead)
+ if ( window[ id ] ) {
+ jQuery.support.scriptEval = true;
+ delete window[ id ];
+ }
+
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete script.test;
+
+ } catch(e) {
+ jQuery.support.deleteExpando = false;
+ }
+
+ root.removeChild( script );
+
+ if ( div.attachEvent && div.fireEvent ) {
+ div.attachEvent("onclick", function click() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ jQuery.support.noCloneEvent = false;
+ div.detachEvent("onclick", click);
+ });
+ div.cloneNode(true).fireEvent("onclick");
+ }
+
+ div = document.createElement("div");
+ div.innerHTML = "<input type='radio' name='radiotest'
checked='checked'/>";
+
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild( div.firstChild );
+
+ // WebKit doesn't clone checked state correctly in fragments
+ jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
+
+ // Figure out if the W3C box model works as expected
+ // document.body must exist before we can do this
+ jQuery(function() {
+ var div = document.createElement("div");
+ div.style.width = div.style.paddingLeft = "1px";
+
+ document.body.appendChild( div );
+ jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+
+ if ( "zoom" in div.style ) {
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ // (IE < 8 does this)
+ div.style.display = "inline";
+ div.style.zoom = 1;
+ jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
+
+ // Check if elements with layout shrink-wrap their children
+ // (IE 6 does this)
+ div.style.display = "";
+ div.innerHTML = "<div style='width:4px;'></div>";
+ jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
+ }
+
+ div.innerHTML = "<table><tr><td
style='padding:0;display:none'></td><td>t</td></tr></table>";
+ var tds = div.getElementsByTagName("td");
+
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ // (only IE 8 fails this test)
+ jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
+
+ tds[0].style.display = "";
+ tds[1].style.display = "none";
+
+ // Check if empty table cells still have offsetWidth/Height
+ // (IE < 8 fail this test)
+ jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets &&
tds[0].offsetHeight === 0;
+ div.innerHTML = "";
+
+ document.body.removeChild( div ).style.display = "none";
+ div = tds = null;
+ });
+
+ // Technique from Juriy Zaytsev
+ //
http://thinkweb2.com/projects/prototype/detecting-event-support-without-b...
+ var eventSupported = function( eventName ) {
+ var el = document.createElement("div");
+ eventName = "on" + eventName;
+
+ var isSupported = (eventName in el);
+ if ( !isSupported ) {
+ el.setAttribute(eventName, "return;");
+ isSupported = typeof el[eventName] === "function";
+ }
+ el = null;
+
+ return isSupported;
+ };
+
+ jQuery.support.submitBubbles = eventSupported("submit");
+ jQuery.support.changeBubbles = eventSupported("change");
+
+ // release memory in IE
+ root = script = div = all = a = null;
+})();
+
+
+
+var windowData = {},
+ rbrace = /^(?:\{.*\}|\[.*\])$/;
+
+jQuery.extend({
+ cache: {},
+
+ // Please use with caution
+ uuid: 0,
+
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + jQuery.now(),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ data: function( elem, name, data ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var isNode = elem.nodeType,
+ id = isNode ? elem[ jQuery.expando ] : null,
+ cache = jQuery.cache, thisCache;
+
+ if ( isNode && !id && typeof name === "string" &&
data === undefined ) {
+ return;
+ }
+
+ // Get the data from the object directly
+ if ( !isNode ) {
+ cache = elem;
+
+ // Compute a unique ID for the element
+ } else if ( !id ) {
+ elem[ jQuery.expando ] = id = ++jQuery.uuid;
+ }
+
+ // Avoid generating a new cache unless none exists and we
+ // want to manipulate it.
+ if ( typeof name === "object" ) {
+ if ( isNode ) {
+ cache[ id ] = jQuery.extend(cache[ id ], name);
+
+ } else {
+ jQuery.extend( cache, name );
+ }
+
+ } else if ( isNode && !cache[ id ] ) {
+ cache[ id ] = {};
+ }
+
+ thisCache = isNode ? cache[ id ] : cache;
+
+ // Prevent overriding the named cache with undefined values
+ if ( data !== undefined ) {
+ thisCache[ name ] = data;
+ }
+
+ return typeof name === "string" ? thisCache[ name ] : thisCache;
+ },
+
+ removeData: function( elem, name ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var isNode = elem.nodeType,
+ id = isNode ? elem[ jQuery.expando ] : elem,
+ cache = jQuery.cache,
+ thisCache = isNode ? cache[ id ] : id;
+
+ // If we want to remove a specific section of the element's data
+ if ( name ) {
+ if ( thisCache ) {
+ // Remove the section of cache data
+ delete thisCache[ name ];
+
+ // If we've removed all the data, remove the element's cache
+ if ( isNode && jQuery.isEmptyObject(thisCache) ) {
+ jQuery.removeData( elem );
+ }
+ }
+
+ // Otherwise, we want to remove all of the element's data
+ } else {
+ if ( isNode && jQuery.support.deleteExpando ) {
+ delete elem[ jQuery.expando ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+
+ // Completely remove the data cache
+ } else if ( isNode ) {
+ delete cache[ id ];
+
+ // Remove all fields from the object
+ } else {
+ for ( var n in elem ) {
+ delete elem[ n ];
+ }
+ }
+ }
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ if ( elem.nodeName ) {
+ var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ if ( match ) {
+ return !(match === true || elem.getAttribute("classid") !== match);
+ }
+ }
+
+ return true;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var data = null;
+
+ if ( typeof key === "undefined" ) {
+ if ( this.length ) {
+ var attr = this[0].attributes, name;
+ data = jQuery.data( this[0] );
+
+ for ( var i = 0, l = attr.length; i < l; i++ ) {
+ name = attr[i].name;
+
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = name.substr( 5 );
+ dataAttr( this[0], name, data[ name ] );
+ }
+ }
+ }
+
+ return data;
+
+ } else if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ var parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ data = this.triggerHandler("getData" + parts[1] + "!",
[parts[0]]);
+
+ // Try to fetch any internally stored data first
+ if ( data === undefined && this.length ) {
+ data = jQuery.data( this[0], key );
+ data = dataAttr( this[0], key, data );
+ }
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+
+ } else {
+ return this.each(function() {
+ var $this = jQuery( this ),
+ args = [ parts[0], value ];
+
+ $this.triggerHandler( "setData" + parts[1] + "!", args );
+ jQuery.data( this, key, value );
+ $this.triggerHandler( "changeData" + parts[1] + "!", args );
+ });
+ }
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+ data = elem.getAttribute( "data-" + key );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ !jQuery.isNaN( data ) ? parseFloat( data ) :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+
+
+
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ if ( !elem ) {
+ return;
+ }
+
+ type = (type || "fx") + "queue";
+ var q = jQuery.data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( !data ) {
+ return q || [];
+ }
+
+ if ( !q || jQuery.isArray(data) ) {
+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
+
+ } else {
+ q.push( data );
+ }
+
+ return q;
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift();
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ }
+
+ if ( fn ) {
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift("inprogress");
+ }
+
+ fn.call(elem, function() {
+ jQuery.dequeue(elem, type);
+ });
+ }
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ }
+
+ if ( data === undefined ) {
+ return jQuery.queue( this[0], type );
+ }
+ return this.each(function( i ) {
+ var queue = jQuery.queue( this, type, data );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+
+ // Based off of the plugin by Clint Helfers, with permission.
+ //
http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function() {
+ var elem = this;
+ setTimeout(function() {
+ jQuery.dequeue( elem, type );
+ }, time );
+ });
+ },
+
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ }
+});
+
+
+
+
+var rclass = /[\n\t]/g,
+ rspaces = /\s+/,
+ rreturn = /\r/g,
+ rspecialurl = /^(?:href|src|style)$/,
+ rtype = /^(?:button|input)$/i,
+ rfocusable = /^(?:button|input|object|select|textarea)$/i,
+ rclickable = /^a(?:rea)?$/i,
+ rradiocheck = /^(?:radio|checkbox)$/i;
+
+jQuery.props = {
+ "for": "htmlFor",
+ "class": "className",
+ readonly: "readOnly",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ tabindex: "tabIndex",
+ usemap: "useMap",
+ frameborder: "frameBorder"
+};
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, name, value, true, jQuery.attr );
+ },
+
+ removeAttr: function( name, fn ) {
+ return this.each(function(){
+ jQuery.attr( this, name, "" );
+ if ( this.nodeType === 1 ) {
+ this.removeAttribute( name );
+ }
+ });
+ },
+
+ addClass: function( value ) {
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.addClass( value.call(this, i, self.attr("class")) );
+ });
+ }
+
+ if ( value && typeof value === "string" ) {
+ var classNames = (value || "").split( rspaces );
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ var elem = this[i];
+
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className ) {
+ elem.className = value;
+
+ } else {
+ var className = " " + elem.className + " ",
+ setClass = elem.className;
+
+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( className.indexOf( " " + classNames[c] + " " ) < 0 )
{
+ setClass += " " + classNames[c];
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.removeClass( value.call(this, i, self.attr("class")) );
+ });
+ }
+
+ if ( (value && typeof value === "string") || value === undefined ) {
+ var classNames = (value || "").split( rspaces );
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ var elem = this[i];
+
+ if ( elem.nodeType === 1 && elem.className ) {
+ if ( value ) {
+ var className = (" " + elem.className + " ").replace(rclass,
" ");
+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+ className = className.replace(" " + classNames[c] + " ",
" ");
+ }
+ elem.className = jQuery.trim( className );
+
+ } else {
+ elem.className = "";
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.toggleClass( value.call(this, i, self.attr("class"), stateVal),
stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.split( rspaces );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space seperated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery.data( this, "__className__", this.className );
+ }
+
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery.data(
this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ";
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ if ( (" " + this[i].className + " ").replace(rclass, "
").indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ if ( !arguments.length ) {
+ var elem = this[0];
+
+ if ( elem ) {
+ if ( jQuery.nodeName( elem, "option" ) ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+
+ // We need to handle select boxes special
+ if ( jQuery.nodeName( elem, "select" ) ) {
+ var index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
+
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
+
+ // Loop through all the selected options
+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max;
i++ ) {
+ var option = options[ i ];
+
+ // Don't return options that are disabled or in a disabled optgroup
+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled :
option.getAttribute("disabled") === null) &&
+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode,
"optgroup" )) ) {
+
+ // Get the specific value for the option
+ value = jQuery(option).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ }
+
+ // Handle the case where in Webkit "" is returned instead of "on"
if a value isn't specified
+ if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+
+
+ // Everything else, we just grab the value
+ return (elem.value || "").replace(rreturn, "");
+
+ }
+
+ return undefined;
+ }
+
+ var isFunction = jQuery.isFunction(value);
+
+ return this.each(function(i) {
+ var self = jQuery(this), val = value;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call(this, i, self.val());
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray(val) ) {
+ val = jQuery.map(val, function (value) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
+ this.checked = jQuery.inArray( self.val(), val ) >= 0;
+
+ } else if ( jQuery.nodeName( this, "select" ) ) {
+ var values = jQuery.makeArray(val);
+
+ jQuery( "option", this ).each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ this.selectedIndex = -1;
+ }
+
+ } else {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ attrFn: {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true
+ },
+
+ attr: function( elem, name, value, pass ) {
+ // don't set attributes on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return undefined;
+ }
+
+ if ( pass && name in jQuery.attrFn ) {
+ return jQuery(elem)[name](value);
+ }
+
+ var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
+ // Whether we are setting (or getting)
+ set = value !== undefined;
+
+ // Try to normalize/fix the name
+ name = notxml && jQuery.props[ name ] || name;
+
+ // These attributes require special treatment
+ var special = rspecialurl.test( name );
+
+ // Safari mis-reports the default selected property of an option
+ // Accessing the parent's selectedIndex property fixes it
+ if ( name === "selected" && !jQuery.support.optSelected ) {
+ var parent = elem.parentNode;
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ }
+
+ // If applicable, access the attribute via the DOM 0 way
+ // 'in' checks fail in Blackberry 4.7 #6931
+ if ( (name in elem || elem[ name ] !== undefined) && notxml && !special
) {
+ if ( set ) {
+ // We can't allow the type property to be changed (since it causes problems in
IE)
+ if ( name === "type" && rtype.test( elem.nodeName ) &&
elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ }
+
+ if ( value === null ) {
+ if ( elem.nodeType === 1 ) {
+ elem.removeAttribute( name );
+ }
+
+ } else {
+ elem[ name ] = value;
+ }
+ }
+
+ // browsers index elements by id/name on forms, give priority to attributes.
+ if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name)
) {
+ return elem.getAttributeNode( name ).nodeValue;
+ }
+
+ // elem.tabIndex doesn't always return the correct value when it hasn't been
explicitly set
+ //
http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabi...
+ if ( name === "tabIndex" ) {
+ var attributeNode = elem.getAttributeNode( "tabIndex" );
+
+ return attributeNode && attributeNode.specified ?
+ attributeNode.value :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) &&
elem.href ?
+ 0 :
+ undefined;
+ }
+
+ return elem[ name ];
+ }
+
+ if ( !jQuery.support.style && notxml && name === "style" ) {
+ if ( set ) {
+ elem.style.cssText = "" + value;
+ }
+
+ return elem.style.cssText;
+ }
+
+ if ( set ) {
+ // convert the value to a string (all browsers do this but IE) see #1070
+ elem.setAttribute( name, "" + value );
+ }
+
+ // Ensure that missing attributes return undefined
+ // Blackberry 4.7 returns "" from getAttribute #6938
+ if ( !elem.attributes[ name ] && (elem.hasAttribute &&
!elem.hasAttribute( name )) ) {
+ return undefined;
+ }
+
+ var attr = !jQuery.support.hrefNormalized && notxml && special ?
+ // Some attributes require a special call on IE
+ elem.getAttribute( name, 2 ) :
+ elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return attr === null ? undefined : attr;
+ }
+});
+
+
+
+
+var rnamespaces = /\.(.*)$/,
+ rformElems = /^(?:textarea|input|select)$/i,
+ rperiod = /\./g,
+ rspace = / /g,
+ rescape = /[^\w\s.|`]/g,
+ fcleanup = function( nm ) {
+ return nm.replace(rescape, "\\$&");
+ },
+ focusCounts = { focusin: 0, focusout: 0 };
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+ // Bind an event to an element
+ // Original by Dean Edwards
+ add: function( elem, types, handler, data ) {
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // For whatever reason, IE has trouble passing the window object
+ // around, causing it to be cloned in the process
+ if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement
) ) {
+ elem = window;
+ }
+
+ if ( handler === false ) {
+ handler = returnFalse;
+ } else if ( !handler ) {
+ // Fixes bug #7229. Fix recommended by jdalton
+ return;
+ }
+
+ var handleObjIn, handleObj;
+
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ }
+
+ // Make sure that the function being executed has a unique ID
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure
+ var elemData = jQuery.data( elem );
+
+ // If no elemData is found then we must be trying to bind to one of the
+ // banned noData elements
+ if ( !elemData ) {
+ return;
+ }
+
+ // Use a key less likely to result in collisions for plain JS objects.
+ // Fixes bug #7150.
+ var eventKey = elem.nodeType ? "events" : "__events__",
+ events = elemData[ eventKey ],
+ eventHandle = elemData.handle;
+
+ if ( typeof events === "function" ) {
+ // On plain objects events is a fn that holds the the data
+ // which prevents this data from being JSON serialized
+ // the function does not need to be called, it just contains the data
+ eventHandle = events.handle;
+ events = events.events;
+
+ } else if ( !events ) {
+ if ( !elem.nodeType ) {
+ // On plain objects, create a fn that acts as the holder
+ // of the values to avoid JSON serialization of event data
+ elemData[ eventKey ] = elemData = function(){};
+ }
+
+ elemData.events = events = {};
+ }
+
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function() {
+ // Handle the second event of a trigger and when
+ // an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+ jQuery.event.handle.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ }
+
+ // Add elem as a property of the handle function
+ // This is to prevent a memory leak with non-native events in IE.
+ eventHandle.elem = elem;
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = types.split(" ");
+
+ var type, i = 0, namespaces;
+
+ while ( (type = types[ i++ ]) ) {
+ handleObj = handleObjIn ?
+ jQuery.extend({}, handleObjIn) :
+ { handler: handler, data: data };
+
+ // Namespaced event handlers
+ if ( type.indexOf(".") > -1 ) {
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ handleObj.namespace = namespaces.slice(0).sort().join(".");
+
+ } else {
+ namespaces = [];
+ handleObj.namespace = "";
+ }
+
+ handleObj.type = type;
+ if ( !handleObj.guid ) {
+ handleObj.guid = handler.guid;
+ }
+
+ // Get the current list of functions bound to this event
+ var handlers = events[ type ],
+ special = jQuery.event.special[ type ] || {};
+
+ // Init the event handler queue
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+
+ // Check for a special event handler
+ // Only use addEventListener/attachEvent if the special
+ // events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) ===
false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add the function to the element's handler list
+ handlers.push( handleObj );
+
+ // Keep track of which events have been used, for global triggering
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, pos ) {
+ // don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ if ( handler === false ) {
+ handler = returnFalse;
+ }
+
+ var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj,
origType,
+ eventKey = elem.nodeType ? "events" : "__events__",
+ elemData = jQuery.data( elem ),
+ events = elemData && elemData[ eventKey ];
+
+ if ( !elemData || !events ) {
+ return;
+ }
+
+ if ( typeof events === "function" ) {
+ elemData = events;
+ events = events.events;
+ }
+
+ // types is actually an event object here
+ if ( types && types.type ) {
+ handler = types.handler;
+ types = types.type;
+ }
+
+ // Unbind all events for the element
+ if ( !types || typeof types === "string" && types.charAt(0) ===
"." ) {
+ types = types || "";
+
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types );
+ }
+
+ return;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).unbind("mouseover mouseout", fn);
+ types = types.split(" ");
+
+ while ( (type = types[ i++ ]) ) {
+ origType = type;
+ handleObj = null;
+ all = type.indexOf(".") < 0;
+ namespaces = [];
+
+ if ( !all ) {
+ // Namespaced event handlers
+ namespaces = type.split(".");
+ type = namespaces.shift();
+
+ namespace = new RegExp("(^|\\.)" +
+ jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") +
"(\\.|$)");
+ }
+
+ eventType = events[ type ];
+
+ if ( !eventType ) {
+ continue;
+ }
+
+ if ( !handler ) {
+ for ( j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( all || namespace.test( handleObj.namespace ) ) {
+ jQuery.event.remove( elem, origType, handleObj.handler, j );
+ eventType.splice( j--, 1 );
+ }
+ }
+
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+
+ for ( j = pos || 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( handler.guid === handleObj.guid ) {
+ // remove the given handler for the given type
+ if ( all || namespace.test( handleObj.namespace ) ) {
+ if ( pos == null ) {
+ eventType.splice( j--, 1 );
+ }
+
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+
+ if ( pos != null ) {
+ break;
+ }
+ }
+ }
+
+ // remove generic event handler if no more handlers exist
+ if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ ret = null;
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ var handle = elemData.handle;
+ if ( handle ) {
+ handle.elem = null;
+ }
+
+ delete elemData.events;
+ delete elemData.handle;
+
+ if ( typeof elemData === "function" ) {
+ jQuery.removeData( elem, eventKey );
+
+ } else if ( jQuery.isEmptyObject( elemData ) ) {
+ jQuery.removeData( elem );
+ }
+ }
+ },
+
+ // bubbling is internal
+ trigger: function( event, data, elem /*, bubbling */ ) {
+ // Event object or event type
+ var type = event.type || event,
+ bubbling = arguments[3];
+
+ if ( !bubbling ) {
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[ jQuery.expando ] ? event :
+ // Object literal
+ jQuery.extend( jQuery.Event(type), event ) :
+ // Just the event type (string)
+ jQuery.Event(type);
+
+ if ( type.indexOf("!") >= 0 ) {
+ event.type = type = type.slice(0, -1);
+ event.exclusive = true;
+ }
+
+ // Handle a global trigger
+ if ( !elem ) {
+ // Don't bubble custom events when global (to avoid too much overhead)
+ event.stopPropagation();
+
+ // Only trigger if we've ever bound an event for it
+ if ( jQuery.event.global[ type ] ) {
+ jQuery.each( jQuery.cache, function() {
+ if ( this.events && this.events[type] ) {
+ jQuery.event.trigger( event, data, this.handle.elem );
+ }
+ });
+ }
+ }
+
+ // Handle triggering a single element
+
+ // don't do events on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return undefined;
+ }
+
+ // Clean up in case it is reused
+ event.result = undefined;
+ event.target = elem;
+
+ // Clone the incoming data, if any
+ data = jQuery.makeArray( data );
+ data.unshift( event );
+ }
+
+ event.currentTarget = elem;
+
+ // Trigger the event, it is assumed that "handle" is a function
+ var handle = elem.nodeType ?
+ jQuery.data( elem, "handle" ) :
+ (jQuery.data( elem, "__events__" ) || {}).handle;
+
+ if ( handle ) {
+ handle.apply( elem, data );
+ }
+
+ var parent = elem.parentNode || elem.ownerDocument;
+
+ // Trigger an inline bound script
+ try {
+ if ( !(elem && elem.nodeName &&
jQuery.noData[elem.nodeName.toLowerCase()]) ) {
+ if ( elem[ "on" + type ] && elem[ "on" + type ].apply(
elem, data ) === false ) {
+ event.result = false;
+ event.preventDefault();
+ }
+ }
+
+ // prevent IE from throwing an error for some elements with some event types, see
#3533
+ } catch (inlineError) {}
+
+ if ( !event.isPropagationStopped() && parent ) {
+ jQuery.event.trigger( event, data, parent, true );
+
+ } else if ( !event.isDefaultPrevented() ) {
+ var old,
+ target = event.target,
+ targetType = type.replace( rnamespaces, "" ),
+ isClick = jQuery.nodeName( target, "a" ) && targetType ===
"click",
+ special = jQuery.event.special[ targetType ] || {};
+
+ if ( (!special._default || special._default.call( elem, event ) === false) &&
+ !isClick && !(target && target.nodeName &&
jQuery.noData[target.nodeName.toLowerCase()]) ) {
+
+ try {
+ if ( target[ targetType ] ) {
+ // Make sure that we don't accidentally re-trigger the onFOO events
+ old = target[ "on" + targetType ];
+
+ if ( old ) {
+ target[ "on" + targetType ] = null;
+ }
+
+ jQuery.event.triggered = true;
+ target[ targetType ]();
+ }
+
+ // prevent IE from throwing an error for some elements with some event types, see
#3533
+ } catch (triggerError) {}
+
+ if ( old ) {
+ target[ "on" + targetType ] = old;
+ }
+
+ jQuery.event.triggered = false;
+ }
+ }
+ },
+
+ handle: function( event ) {
+ var all, handlers, namespaces, namespace_re, events,
+ namespace_sort = [],
+ args = jQuery.makeArray( arguments );
+
+ event = args[0] = jQuery.event.fix( event || window.event );
+ event.currentTarget = this;
+
+ // Namespaced event handlers
+ all = event.type.indexOf(".") < 0 && !event.exclusive;
+
+ if ( !all ) {
+ namespaces = event.type.split(".");
+ event.type = namespaces.shift();
+ namespace_sort = namespaces.slice(0).sort();
+ namespace_re = new RegExp("(^|\\.)" +
namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
+ }
+
+ event.namespace = event.namespace || namespace_sort.join(".");
+
+ events = jQuery.data(this, this.nodeType ? "events" :
"__events__");
+
+ if ( typeof events === "function" ) {
+ events = events.events;
+ }
+
+ handlers = (events || {})[ event.type ];
+
+ if ( events && handlers ) {
+ // Clone the handlers to prevent manipulation
+ handlers = handlers.slice(0);
+
+ for ( var j = 0, l = handlers.length; j < l; j++ ) {
+ var handleObj = handlers[ j ];
+
+ // Filter the functions by class
+ if ( all || namespace_re.test( handleObj.namespace ) ) {
+ // Pass in a reference to the handler function itself
+ // So that we can later remove it
+ event.handler = handleObj.handler;
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ var ret = handleObj.handler.apply( this, args );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ if ( event.isImmediatePropagationStopped() ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ props: "altKey attrChange attrName bubbles button cancelable charCode clientX
clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX
layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget
screenX screenY shiftKey srcElement target toElement view wheelDelta
which".split(" "),
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // store a copy of the original event object
+ // and "clone" to set read-only properties
+ var originalEvent = event;
+ event = jQuery.Event( originalEvent );
+
+ for ( var i = this.props.length, prop; i; ) {
+ prop = this.props[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary
+ if ( !event.target ) {
+ // Fixes #1925 where srcElement might not be defined either
+ event.target = event.srcElement || document;
+ }
+
+ // check if target is a textnode (safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && event.fromElement ) {
+ event.relatedTarget = event.fromElement === event.target ? event.toElement :
event.fromElement;
+ }
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && event.clientX != null ) {
+ var doc = document.documentElement,
+ body = document.body;
+
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body &&
body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft
|| 0);
+ event.pageY = event.clientY + (doc && doc.scrollTop || body &&
body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop
|| 0);
+ }
+
+ // Add which for key events
+ if ( event.which == null && (event.charCode != null || event.keyCode != null) )
{
+ event.which = event.charCode != null ? event.charCode : event.keyCode;
+ }
+
+ // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+ if ( !event.metaKey && event.ctrlKey ) {
+ event.metaKey = event.ctrlKey;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && event.button !== undefined ) {
+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button
& 4 ? 2 : 0 ) ));
+ }
+
+ return event;
+ },
+
+ // Deprecated, use jQuery.guid instead
+ guid: 1E8,
+
+ // Deprecated, use jQuery.proxy instead
+ proxy: jQuery.proxy,
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: jQuery.bindReady,
+ teardown: jQuery.noop
+ },
+
+ live: {
+ add: function( handleObj ) {
+ jQuery.event.add( this,
+ liveConvert( handleObj.origType, handleObj.selector ),
+ jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid})
);
+ },
+
+ remove: function( handleObj ) {
+ jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ),
handleObj );
+ }
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( jQuery.isWindow( this ) ) {
+ this.onbeforeunload = eventHandle;
+ }
+ },
+
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
+ }
+ }
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ if ( elem.detachEvent ) {
+ elem.detachEvent( "on" + type, handle );
+ }
+ };
+
+jQuery.Event = function( src ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !this.preventDefault ) {
+ return new jQuery.Event( src );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // timeStamp is buggy for some events on Firefox(#3843)
+ // So we won't rely on the native value
+ this.timeStamp = jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+ return false;
+}
+function returnTrue() {
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+//
http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-bind...
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // otherwise set the returnValue property of the original event to false (IE)
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function( event ) {
+ // Check if mouse(over|out) are still within the same parent element
+ var parent = event.relatedTarget;
+
+ // Firefox sometimes assigns relatedTarget a XUL element
+ // which we cannot access the parentNode property of
+ try {
+ // Traverse up the tree
+ while ( parent && parent !== this ) {
+ parent = parent.parentNode;
+ }
+
+ if ( parent !== this ) {
+ // set the correct event type
+ event.type = event.data;
+
+ // handle event if we actually just moused on to a non sub-element
+ jQuery.event.handle.apply( this, arguments );
+ }
+
+ // assuming we've left the element since we most likely mousedover a xul element
+ } catch(e) { }
+},
+
+// In case of event delegation, we only need to rename the event.type,
+// liveHandler will take care of the rest.
+delegate = function( event ) {
+ event.type = event.data;
+ jQuery.event.handle.apply( this, arguments );
+};
+
+// Create mouseenter and mouseleave events
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ setup: function( data ) {
+ jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement,
orig );
+ },
+ teardown: function( data ) {
+ jQuery.event.remove( this, fix, data && data.selector ? delegate :
withinElement );
+ }
+ };
+});
+
+// submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function( data, namespaces ) {
+ if ( this.nodeName.toLowerCase() !== "form" ) {
+ jQuery.event.add(this, "click.specialSubmit", function( e ) {
+ var elem = e.target,
+ type = elem.type;
+
+ if ( (type === "submit" || type === "image") && jQuery(
elem ).closest("form").length ) {
+ e.liveFired = undefined;
+ return trigger( "submit", this, arguments );
+ }
+ });
+
+ jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
+ var elem = e.target,
+ type = elem.type;
+
+ if ( (type === "text" || type === "password") && jQuery(
elem ).closest("form").length && e.keyCode === 13 ) {
+ e.liveFired = undefined;
+ return trigger( "submit", this, arguments );
+ }
+ });
+
+ } else {
+ return false;
+ }
+ },
+
+ teardown: function( namespaces ) {
+ jQuery.event.remove( this, ".specialSubmit" );
+ }
+ };
+
+}
+
+// change delegation, happens here so we have bind.
+if ( !jQuery.support.changeBubbles ) {
+
+ var changeFilters,
+
+ getVal = function( elem ) {
+ var type = elem.type, val = elem.value;
+
+ if ( type === "radio" || type === "checkbox" ) {
+ val = elem.checked;
+
+ } else if ( type === "select-multiple" ) {
+ val = elem.selectedIndex > -1 ?
+ jQuery.map( elem.options, function( elem ) {
+ return elem.selected;
+ }).join("-") :
+ "";
+
+ } else if ( elem.nodeName.toLowerCase() === "select" ) {
+ val = elem.selectedIndex;
+ }
+
+ return val;
+ },
+
+ testChange = function testChange( e ) {
+ var elem = e.target, data, val;
+
+ if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
+ return;
+ }
+
+ data = jQuery.data( elem, "_change_data" );
+ val = getVal(elem);
+
+ // the current data will be also retrieved by beforeactivate
+ if ( e.type !== "focusout" || elem.type !== "radio" ) {
+ jQuery.data( elem, "_change_data", val );
+ }
+
+ if ( data === undefined || val === data ) {
+ return;
+ }
+
+ if ( data != null || val ) {
+ e.type = "change";
+ e.liveFired = undefined;
+ return jQuery.event.trigger( e, arguments[1], elem );
+ }
+ };
+
+ jQuery.event.special.change = {
+ filters: {
+ focusout: testChange,
+
+ beforedeactivate: testChange,
+
+ click: function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( type === "radio" || type === "checkbox" ||
elem.nodeName.toLowerCase() === "select" ) {
+ return testChange.call( this, e );
+ }
+ },
+
+ // Change has to be called before submit
+ // Keydown will be called before keypress, which is used in submit-event delegation
+ keydown: function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !==
"textarea") ||
+ (e.keyCode === 32 && (type === "checkbox" || type ===
"radio")) ||
+ type === "select-multiple" ) {
+ return testChange.call( this, e );
+ }
+ },
+
+ // Beforeactivate happens also before the previous element is blurred
+ // with this event you can't trigger a change event, but you can store
+ // information
+ beforeactivate: function( e ) {
+ var elem = e.target;
+ jQuery.data( elem, "_change_data", getVal(elem) );
+ }
+ },
+
+ setup: function( data, namespaces ) {
+ if ( this.type === "file" ) {
+ return false;
+ }
+
+ for ( var type in changeFilters ) {
+ jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
+ }
+
+ return rformElems.test( this.nodeName );
+ },
+
+ teardown: function( namespaces ) {
+ jQuery.event.remove( this, ".specialChange" );
+
+ return rformElems.test( this.nodeName );
+ }
+ };
+
+ changeFilters = jQuery.event.special.change.filters;
+
+ // Handle when the input is .focus()'d
+ changeFilters.focus = changeFilters.beforeactivate;
+}
+
+function trigger( type, elem, args ) {
+ args[0].type = type;
+ return jQuery.event.handle.apply( elem, args );
+}
+
+// Create "bubbling" focus and blur events
+if ( document.addEventListener ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig,
fix ) {
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( focusCounts[fix]++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --focusCounts[fix] === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+
+ function handler( e ) {
+ e = jQuery.event.fix( e );
+ e.type = fix;
+ return jQuery.event.trigger( e, null, e.target );
+ }
+ });
+}
+
+jQuery.each(["bind", "one"], function( i, name ) {
+ jQuery.fn[ name ] = function( type, data, fn ) {
+ // Handle object literals
+ if ( typeof type === "object" ) {
+ for ( var key in type ) {
+ this[ name ](key, data, type[key], fn);
+ }
+ return this;
+ }
+
+ if ( jQuery.isFunction( data ) || data === false ) {
+ fn = data;
+ data = undefined;
+ }
+
+ var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
+ jQuery( this ).unbind( event, handler );
+ return fn.apply( this, arguments );
+ }) : fn;
+
+ if ( type === "unload" && name !== "one" ) {
+ this.one( type, data, fn );
+
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ jQuery.event.add( this[i], type, handler, data );
+ }
+ }
+
+ return this;
+ };
+});
+
+jQuery.fn.extend({
+ unbind: function( type, fn ) {
+ // Handle object literals
+ if ( typeof type === "object" && !type.preventDefault ) {
+ for ( var key in type ) {
+ this.unbind(key, type[key]);
+ }
+
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ jQuery.event.remove( this[i], type, fn );
+ }
+ }
+
+ return this;
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.live( types, data, fn, selector );
+ },
+
+ undelegate: function( selector, types, fn ) {
+ if ( arguments.length === 0 ) {
+ return this.unbind( "live" );
+
+ } else {
+ return this.die( types, null, fn, selector );
+ }
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ var event = jQuery.Event( type );
+ event.preventDefault();
+ event.stopPropagation();
+ jQuery.event.trigger( event, data, this[0] );
+ return event.result;
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ i = 1;
+
+ // link all the functions, so any of them can unbind this click handler
+ while ( i < args.length ) {
+ jQuery.proxy( fn, args[ i++ ] );
+ }
+
+ return this.click( jQuery.proxy( fn, function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ }));
+ },
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+});
+
+var liveMap = {
+ focus: "focusin",
+ blur: "focusout",
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+};
+
+jQuery.each(["live", "die"], function( i, name ) {
+ jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
+ var type, i = 0, match, namespaces, preType,
+ selector = origSelector || this.selector,
+ context = origSelector ? this : jQuery( this.context );
+
+ if ( typeof types === "object" && !types.preventDefault ) {
+ for ( var key in types ) {
+ context[ name ]( key, data, types[key], selector );
+ }
+
+ return this;
+ }
+
+ if ( jQuery.isFunction( data ) ) {
+ fn = data;
+ data = undefined;
+ }
+
+ types = (types || "").split(" ");
+
+ while ( (type = types[ i++ ]) != null ) {
+ match = rnamespaces.exec( type );
+ namespaces = "";
+
+ if ( match ) {
+ namespaces = match[0];
+ type = type.replace( rnamespaces, "" );
+ }
+
+ if ( type === "hover" ) {
+ types.push( "mouseenter" + namespaces, "mouseleave" + namespaces
);
+ continue;
+ }
+
+ preType = type;
+
+ if ( type === "focus" || type === "blur" ) {
+ types.push( liveMap[ type ] + namespaces );
+ type = type + namespaces;
+
+ } else {
+ type = (liveMap[ type ] || type) + namespaces;
+ }
+
+ if ( name === "live" ) {
+ // bind live handler
+ for ( var j = 0, l = context.length; j < l; j++ ) {
+ jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
+ { data: data, selector: selector, handler: fn, origType: type, origHandler: fn,
preType: preType } );
+ }
+
+ } else {
+ // unbind live handler
+ context.unbind( "live." + liveConvert( type, selector ), fn );
+ }
+ }
+
+ return this;
+ };
+});
+
+function liveHandler( event ) {
+ var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace,
ret,
+ elems = [],
+ selectors = [],
+ events = jQuery.data( this, this.nodeType ? "events" : "__events__"
);
+
+ if ( typeof events === "function" ) {
+ events = events.events;
+ }
+
+ // Make sure we avoid non-left-click bubbling in Firefox (#3861)
+ if ( event.liveFired === this || !events || !events.live || event.button &&
event.type === "click" ) {
+ return;
+ }
+
+ if ( event.namespace ) {
+ namespace = new RegExp("(^|\\.)" +
event.namespace.split(".").join("\\.(?:.*\\.)?") +
"(\\.|$)");
+ }
+
+ event.liveFired = this;
+
+ var live = events.live.slice(0);
+
+ for ( j = 0; j < live.length; j++ ) {
+ handleObj = live[j];
+
+ if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
+ selectors.push( handleObj.selector );
+
+ } else {
+ live.splice( j--, 1 );
+ }
+ }
+
+ match = jQuery( event.target ).closest( selectors, event.currentTarget );
+
+ for ( i = 0, l = match.length; i < l; i++ ) {
+ close = match[i];
+
+ for ( j = 0; j < live.length; j++ ) {
+ handleObj = live[j];
+
+ if ( close.selector === handleObj.selector && (!namespace || namespace.test(
handleObj.namespace )) ) {
+ elem = close.elem;
+ related = null;
+
+ // Those two events require additional checking
+ if ( handleObj.preType === "mouseenter" || handleObj.preType ===
"mouseleave" ) {
+ event.type = handleObj.preType;
+ related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
+ }
+
+ if ( !related || related !== elem ) {
+ elems.push({ elem: elem, handleObj: handleObj, level: close.level });
+ }
+ }
+ }
+ }
+
+ for ( i = 0, l = elems.length; i < l; i++ ) {
+ match = elems[i];
+
+ if ( maxLevel && match.level > maxLevel ) {
+ break;
+ }
+
+ event.currentTarget = match.elem;
+ event.data = match.handleObj.data;
+ event.handleObj = match.handleObj;
+
+ ret = match.handleObj.origHandler.apply( match.elem, arguments );
+
+ if ( ret === false || event.isPropagationStopped() ) {
+ maxLevel = match.level;
+
+ if ( ret === false ) {
+ stop = false;
+ }
+ if ( event.isImmediatePropagationStopped() ) {
+ break;
+ }
+ }
+ }
+
+ return stop;
+}
+
+function liveConvert( type, selector ) {
+ return (type && type !== "*" ? type + "." : "") +
selector.replace(rperiod, "`").replace(rspace, "&");
+}
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick
" +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error").split(" "),
function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ if ( fn == null ) {
+ fn = data;
+ data = null;
+ }
+
+ return arguments.length > 0 ?
+ this.bind( name, data, fn ) :
+ this.trigger( name );
+ };
+
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
+ }
+});
+
+// Prevent memory leaks in IE
+// Window isn't included so as not to unbind existing unload events
+// More info:
+// -
http://isaacschlueter.com/2006/10/msie-memory-leaks/
+if ( window.attachEvent && !window.addEventListener ) {
+ jQuery(window).bind("unload", function() {
+ for ( var id in jQuery.cache ) {
+ if ( jQuery.cache[ id ].handle ) {
+ // Try/Catch is to handle iframes being unloaded, see #4280
+ try {
+ jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+ } catch(e) {}
+ }
+ }
+ });
+}
+
+
+/*!
+ * Sizzle CSS Selector Engine - v1.0
+ * Copyright 2009, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information:
http://sizzlejs.com/
+ */
+(function(){
+
+var chunker =
/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^
>+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+ done = 0,
+ toString = Object.prototype.toString,
+ hasDuplicate = false,
+ baseHasDuplicate = true;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+// Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+ baseHasDuplicate = false;
+ return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+ results = results || [];
+ context = context || document;
+
+ var origContext = context;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var m, set, checkSet, extra, ret, cur, pop, i,
+ prune = true,
+ contextXML = Sizzle.isXML( context ),
+ parts = [],
+ soFar = selector;
+
+ // Reset the position of the chunker regexp (start from head)
+ do {
+ chunker.exec( "" );
+ m = chunker.exec( soFar );
+
+ if ( m ) {
+ soFar = m[3];
+
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = m[3];
+ break;
+ }
+ }
+ } while ( m );
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context );
+
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] ) {
+ selector += parts.shift();
+ }
+
+ set = posProcess( selector, set );
+ }
+ }
+
+ } else {
+ // Take a shortcut and set the context if the root selector is an ID
+ // (but not if it'll be faster if the inner selector is an ID)
+ if ( !seed && parts.length > 1 && context.nodeType === 9 &&
!contextXML &&
+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1])
) {
+
+ ret = Sizzle.find( parts.shift(), context, contextXML );
+ context = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set )[0] :
+ ret.set[0];
+ }
+
+ if ( context ) {
+ ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~"
|| parts[0] === "+") && context.parentNode ? context.parentNode :
context, contextXML );
+
+ set = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set ) :
+ ret.set;
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray( set );
+
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ cur = parts.pop();
+ pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, contextXML );
+ }
+
+ } else {
+ checkSet = parts = [];
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ Sizzle.error( cur || selector );
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+
+ } else if ( context && context.nodeType === 1 ) {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1
&& Sizzle.contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+
+ } else {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, origContext, results, seed );
+ Sizzle.uniqueSort( results );
+ }
+
+ return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+ if ( sortOrder ) {
+ hasDuplicate = baseHasDuplicate;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[ i - 1 ] ) {
+ results.splice( i--, 1 );
+ }
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+ return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+ return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+ var set;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+ var match,
+ type = Expr.order[i];
+
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+ var left = match[1];
+ match.splice( 1, 1 );
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace(/\\/g, "");
+ set = Expr.find[ type ]( match, context, isXML );
+
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = context.getElementsByTagName( "*" );
+ }
+
+ return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+ var match, anyFound,
+ old = expr,
+ result = [],
+ curLoop = set,
+ isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+ while ( expr && set.length ) {
+ for ( var type in Expr.filter ) {
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+ var found, item,
+ filter = Expr.filter[ type ],
+ left = match[1];
+
+ anyFound = false;
+
+ match.splice(1,1);
+
+ if ( left.substr( left.length - 1 ) === "\\" ) {
+ continue;
+ }
+
+ if ( curLoop === result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter
);
+
+ if ( !match ) {
+ anyFound = found = true;
+
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ var pass = not ^ !!found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+
+ } else {
+ curLoop[i] = false;
+ }
+
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Improper expression
+ if ( expr === old ) {
+ if ( anyFound == null ) {
+ Sizzle.error( expr );
+
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+ throw "Syntax error, unrecognized expression: " + msg;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+ ATTR:
/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+ PSEUDO:
/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+ },
+
+ leftMatch: {},
+
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
+
+ attrHandle: {
+ href: function( elem ) {
+ return elem.getAttribute( "href" );
+ }
+ },
+
+ relative: {
+ "+": function(checkSet, part){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !/\W/.test( part ),
+ isPartStrNotTag = isPartStr && !isTag;
+
+ if ( isTag ) {
+ part = part.toLowerCase();
+ }
+
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() ===
part ?
+ elem || false :
+ elem === part;
+ }
+ }
+
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+
+ ">": function( checkSet, part ) {
+ var elem,
+ isPartStr = typeof part === "string",
+ i = 0,
+ l = checkSet.length;
+
+ if ( isPartStr && !/\W/.test( part ) ) {
+ part = part.toLowerCase();
+
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+ }
+ }
+
+ } else {
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+
+ "": function(checkSet, part, isXML){
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !/\W/.test(part) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+ },
+
+ "~": function( checkSet, part, isXML ) {
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !/\W/.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+ }
+ },
+
+ find: {
+ ID: function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ },
+
+ NAME: function( match, context ) {
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [],
+ results = context.getElementsByName( match[1] );
+
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
+
+ return ret.length === 0 ? null : ret;
+ }
+ },
+
+ TAG: function( match, context ) {
+ return context.getElementsByTagName( match[1] );
+ }
+ },
+ preFilter: {
+ CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+ match = " " + match[1].replace(/\\/g, "") + " ";
+
+ if ( isXML ) {
+ return match;
+ }
+
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + "
").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
+ if ( !inplace ) {
+ result.push( elem );
+ }
+
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+
+ ID: function( match ) {
+ return match[1].replace(/\\/g, "");
+ },
+
+ TAG: function( match, curLoop ) {
+ return match[1].toLowerCase();
+ },
+
+ CHILD: function( match ) {
+ if ( match[1] === "nth" ) {
+ // parse equations like 'even', 'odd', '5', '2n',
'3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+ match[2] === "even" && "2n" || match[2] ===
"odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
+
+ ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+ var name = match[1].replace(/\\/g, "");
+
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+
+ PSEUDO: function( match, curLoop, inplace, result, not ) {
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3])
) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+
+ return false;
+ }
+
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+
+ POS: function( match ) {
+ match.unshift( true );
+
+ return match;
+ }
+ },
+
+ filters: {
+ enabled: function( elem ) {
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+
+ disabled: function( elem ) {
+ return elem.disabled === true;
+ },
+
+ checked: function( elem ) {
+ return elem.checked === true;
+ },
+
+ selected: function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ elem.parentNode.selectedIndex;
+
+ return elem.selected === true;
+ },
+
+ parent: function( elem ) {
+ return !!elem.firstChild;
+ },
+
+ empty: function( elem ) {
+ return !elem.firstChild;
+ },
+
+ has: function( elem, i, match ) {
+ return !!Sizzle( match[3], elem ).length;
+ },
+
+ header: function( elem ) {
+ return (/h\d/i).test( elem.nodeName );
+ },
+
+ text: function( elem ) {
+ return "text" === elem.type;
+ },
+ radio: function( elem ) {
+ return "radio" === elem.type;
+ },
+
+ checkbox: function( elem ) {
+ return "checkbox" === elem.type;
+ },
+
+ file: function( elem ) {
+ return "file" === elem.type;
+ },
+ password: function( elem ) {
+ return "password" === elem.type;
+ },
+
+ submit: function( elem ) {
+ return "submit" === elem.type;
+ },
+
+ image: function( elem ) {
+ return "image" === elem.type;
+ },
+
+ reset: function( elem ) {
+ return "reset" === elem.type;
+ },
+
+ button: function( elem ) {
+ return "button" === elem.type || elem.nodeName.toLowerCase() ===
"button";
+ },
+
+ input: function( elem ) {
+ return (/input|select|textarea|button/i).test( elem.nodeName );
+ }
+ },
+ setFilters: {
+ first: function( elem, i ) {
+ return i === 0;
+ },
+
+ last: function( elem, i, match, array ) {
+ return i === array.length - 1;
+ },
+
+ even: function( elem, i ) {
+ return i % 2 === 0;
+ },
+
+ odd: function( elem, i ) {
+ return i % 2 === 1;
+ },
+
+ lt: function( elem, i, match ) {
+ return i < match[3] - 0;
+ },
+
+ gt: function( elem, i, match ) {
+ return i > match[3] - 0;
+ },
+
+ nth: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ },
+
+ eq: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ }
+ },
+ filter: {
+ PSEUDO: function( elem, match, i, array ) {
+ var name = match[1],
+ filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) ||
"").indexOf(match[3]) >= 0;
+
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var j = 0, l = not.length; j < l; j++ ) {
+ if ( not[j] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ } else {
+ Sizzle.error( "Syntax error, unrecognized expression: " + name );
+ }
+ },
+
+ CHILD: function( elem, match ) {
+ var type = match[1],
+ node = elem;
+
+ switch ( type ) {
+ case "only":
+ case "first":
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ if ( type === "first" ) {
+ return true;
+ }
+
+ node = elem;
+
+ case "last":
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ case "nth":
+ var first = match[2],
+ last = match[3];
+
+ if ( first === 1 && last === 0 ) {
+ return true;
+ }
+
+ var doneName = match[0],
+ parent = elem.parentNode;
+
+ if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+ var count = 0;
+
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
+
+ parent.sizcache = doneName;
+ }
+
+ var diff = elem.nodeIndex - last;
+
+ if ( first === 0 ) {
+ return diff === 0;
+
+ } else {
+ return ( diff % first === 0 && diff / first >= 0 );
+ }
+ }
+ },
+
+ ID: function( elem, match ) {
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+
+ TAG: function( elem, match ) {
+ return (match === "*" && elem.nodeType === 1) ||
elem.nodeName.toLowerCase() === match;
+ },
+
+ CLASS: function( elem, match ) {
+ return (" " + (elem.className || elem.getAttribute("class")) +
" ")
+ .indexOf( match ) > -1;
+ },
+
+ ATTR: function( elem, match ) {
+ var name = match[1],
+ result = Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value !== check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+
+ POS: function( elem, match, i, array ) {
+ var name = match[2],
+ filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS,
+ fescape = function(all, num){
+ return "\\" + (num - 0 + 1);
+ };
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source +
(/(?![^\[]*\])(?![^\(]*\))/.source) );
+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type
].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+ array = Array.prototype.slice.call( array, 0 );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+ makeArray = function( array, results ) {
+ var i = 0,
+ ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+
+ } else {
+ for ( ; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+ return a.compareDocumentPosition ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+ };
+
+} else {
+ sortOrder = function( a, b ) {
+ var al, bl,
+ ap = [],
+ bp = [],
+ aup = a.parentNode,
+ bup = b.parentNode,
+ cur = aup;
+
+ // The nodes are identical, we can exit early
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // If the nodes are siblings (or identical) we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+
+ // If no parents were found then the nodes are disconnected
+ } else if ( !aup ) {
+ return -1;
+
+ } else if ( !bup ) {
+ return 1;
+ }
+
+ // Otherwise they're somewhere else in the tree so we need
+ // to build up a full list of the parentNodes for comparison
+ while ( cur ) {
+ ap.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ cur = bup;
+
+ while ( cur ) {
+ bp.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ al = ap.length;
+ bl = bp.length;
+
+ // Start walking down the tree looking for a discrepancy
+ for ( var i = 0; i < al && i < bl; i++ ) {
+ if ( ap[i] !== bp[i] ) {
+ return siblingCheck( ap[i], bp[i] );
+ }
+ }
+
+ // We ended someplace up the tree so do a sibling check
+ return i === al ?
+ siblingCheck( a, bp[i], -1 ) :
+ siblingCheck( ap[i], b, 1 );
+ };
+
+ siblingCheck = function( a, b, ret ) {
+ if ( a === b ) {
+ return ret;
+ }
+
+ var cur = a.nextSibling;
+
+ while ( cur ) {
+ if ( cur === b ) {
+ return -1;
+ }
+
+ cur = cur.nextSibling;
+ }
+
+ return 1;
+ };
+}
+
+// Utility function for retreiving the text value of an array of DOM nodes
+Sizzle.getText = function( elems ) {
+ var ret = "", elem;
+
+ for ( var i = 0; elems[i]; i++ ) {
+ elem = elems[i];
+
+ // Get the text from text nodes and CDATA nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
+ ret += elem.nodeValue;
+
+ // Traverse everything else, except comment nodes
+ } else if ( elem.nodeType !== 8 ) {
+ ret += Sizzle.getText( elem.childNodes );
+ }
+ }
+
+ return ret;
+};
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("div"),
+ id = "script" + (new Date()).getTime(),
+ root = document.documentElement;
+
+ form.innerHTML = "<a name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( document.getElementById( id ) ) {
+ Expr.find.ID = function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+
+ return m ?
+ m.id === match[1] || typeof m.getAttributeNode !== "undefined" &&
m.getAttributeNode("id").nodeValue === match[1] ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+
+ Expr.filter.ID = function( elem, match ) {
+ var node = typeof elem.getAttributeNode !== "undefined" &&
elem.getAttributeNode("id");
+
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+
+ // release memory in IE
+ root = form = null;
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function( match, context ) {
+ var results = context.getElementsByTagName( match[1] );
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+
+ if ( div.firstChild && typeof div.firstChild.getAttribute !==
"undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
+
+ Expr.attrHandle.href = function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ };
+ }
+
+ // release memory in IE
+ div = null;
+})();
+
+if ( document.querySelectorAll ) {
+ (function(){
+ var oldSizzle = Sizzle,
+ div = document.createElement("div"),
+ id = "__sizzle__";
+
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length ===
0 ) {
+ return;
+ }
+
+ Sizzle = function( query, context, extra, seed ) {
+ context = context || document;
+
+ // Make sure that attribute selectors are quoted
+ query = query.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && !Sizzle.isXML(context) ) {
+ if ( context.nodeType === 9 ) {
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(qsaError) {}
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !==
"object" ) {
+ var old = context.getAttribute( "id" ),
+ nid = old || id;
+
+ if ( !old ) {
+ context.setAttribute( "id", nid );
+ }
+
+ try {
+ return makeArray( context.querySelectorAll( "#" + nid + " " +
query ), extra );
+
+ } catch(pseudoError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ for ( var prop in oldSizzle ) {
+ Sizzle[ prop ] = oldSizzle[ prop ];
+ }
+
+ // release memory in IE
+ div = null;
+ })();
+}
+
+(function(){
+ var html = document.documentElement,
+ matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector
|| html.msMatchesSelector,
+ pseudoWorks = false;
+
+ try {
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( document.documentElement, "[test!='']:sizzle" );
+
+ } catch( pseudoError ) {
+ pseudoWorks = true;
+ }
+
+ if ( matches ) {
+ Sizzle.matchesSelector = function( node, expr ) {
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+ if ( !Sizzle.isXML( node ) ) {
+ try {
+ if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) )
{
+ return matches.call( node, expr );
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle(expr, null, null, [node]).length > 0;
+ };
+ }
+})();
+
+(function(){
+ var div = document.createElement("div");
+
+ div.innerHTML = "<div class='test e'></div><div
class='test'></div>";
+
+ // Opera can't find a second classname (in 9.6)
+ // Also, make sure that getElementsByClassName actually exists
+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length ===
0 ) {
+ return;
+ }
+
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
+
+ if ( div.getElementsByClassName("e").length === 1 ) {
+ return;
+ }
+
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function( match, context, isXML ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML
) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
+
+ // release memory in IE
+ div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem.sizcache === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML ){
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+
+ if ( elem.nodeName.toLowerCase() === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem.sizcache === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+if ( document.documentElement.contains ) {
+ Sizzle.contains = function( a, b ) {
+ return a !== b && (a.contains ? a.contains(b) : true);
+ };
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+ Sizzle.contains = function( a, b ) {
+ return !!(a.compareDocumentPosition(b) & 16);
+ };
+
+} else {
+ Sizzle.contains = function() {
+ return false;
+ };
+}
+
+Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context ) {
+ var match,
+ tmpSet = [],
+ later = "",
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+ // Note: This RegExp should be improved, or likely pulled from Sizzle
+ rmultiselector = /,/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ slice = Array.prototype.slice,
+ POS = jQuery.expr.match.POS;
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var ret = this.pushStack( "", "find", selector ),
+ length = 0;
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( var n = length; n < ret.length; n++ ) {
+ for ( var r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ has: function( target ) {
+ var targets = jQuery( target );
+ return this.filter(function() {
+ for ( var i = 0, l = targets.length; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
+
+ is: function( selector ) {
+ return !!selector && jQuery.filter( selector, this ).length > 0;
+ },
+
+ closest: function( selectors, context ) {
+ var ret = [], i, l, cur = this[0];
+
+ if ( jQuery.isArray( selectors ) ) {
+ var match, selector,
+ matches = {},
+ level = 1;
+
+ if ( cur && selectors.length ) {
+ for ( i = 0, l = selectors.length; i < l; i++ ) {
+ selector = selectors[i];
+
+ if ( !matches[selector] ) {
+ matches[selector] = jQuery.expr.match.POS.test( selector ) ?
+ jQuery( selector, context || this.context ) :
+ selector;
+ }
+ }
+
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ for ( selector in matches ) {
+ match = matches[selector];
+
+ if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
+ ret.push({ selector: selector, elem: cur, level: level });
+ }
+ }
+
+ cur = cur.parentNode;
+ level++;
+ }
+ }
+
+ return ret;
+ }
+
+ var pos = POS.test( selectors ) ?
+ jQuery( selectors, context || this.context ) : null;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+
+ } else {
+ cur = cur.parentNode;
+ if ( !cur || !cur.ownerDocument || cur === context ) {
+ break;
+ }
+ }
+ }
+ }
+
+ ret = ret.length > 1 ? jQuery.unique(ret) : ret;
+
+ return this.pushStack( ret, "closest", selectors );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+ if ( !elem || typeof elem === "string" ) {
+ return jQuery.inArray( this[0],
+ // If it receives a string, the selector is used
+ // If it receives nothing, the siblings are used
+ elem ? jQuery( elem ) : this.parent().children() );
+ }
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context || this.context ) :
+ jQuery.makeArray( selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ }
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return jQuery.nth( elem, 2, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return jQuery.nth( elem, 2, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( elem.parentNode.firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.makeArray( elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 ? jQuery.unique( ret ) : ret;
+
+ if ( (this.length > 1 || rmultiselector.test( selector )) &&
rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret, name, slice.call(arguments).join(",") );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined ||
cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ nth: function( cur, result, dir, elem ) {
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] ) {
+ if ( cur.nodeType === 1 && ++num === result ) {
+ break;
+ }
+ }
+
+ return cur;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return (elem === qualifier) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem, i ) {
+ return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
+ });
+}
+
+
+
+
+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag =
/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnocache = /<(?:script|object|embed|option|style)/i,
+ // checked="checked" or checked (html5)
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ raction = /\=([^="'>\s]+\/)>/g,
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>",
"</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>",
"</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>",
"</tr></tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>",
"</colgroup></table>" ],
+ area: [ 1, "<map>", "</map>" ],
+ _default: [ 0, "", "" ]
+ };
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+ text: function( text ) {
+ if ( jQuery.isFunction(text) ) {
+ return this.each(function(i) {
+ var self = jQuery( this );
+
+ self.text( text.call(this, i, self.text()) );
+ });
+ }
+
+ if ( typeof text !== "object" && text !== undefined ) {
+ return this.empty().append( (this[0] && this[0].ownerDocument ||
document).createTextNode( text ) );
+ }
+
+ return jQuery.text( this );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append(this);
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ return this.each(function() {
+ jQuery( this ).wrapAll( html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ } else if ( arguments.length ) {
+ var set = jQuery(arguments[0]);
+ set.push.apply( set, this.toArray() );
+ return this.pushStack( set, "before", arguments );
+ }
+ },
+
+ after: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ } else if ( arguments.length ) {
+ var set = this.pushStack( this, "after", arguments );
+ set.push.apply( set, jQuery(arguments[0]).toArray() );
+ return set;
+ }
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( events ) {
+ // Do the clone
+ var ret = this.map(function() {
+ if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+ // IE copies events bound via attachEvent when
+ // using cloneNode. Calling detachEvent on the
+ // clone will also remove the events from the orignal
+ // In order to get around this, we use innerHTML.
+ // Unfortunately, this means some modifications to
+ // attributes in IE that are actually only stored
+ // as properties will not be copied (such as the
+ // the name attribute on an input).
+ var html = this.outerHTML,
+ ownerDocument = this.ownerDocument;
+
+ if ( !html ) {
+ var div = ownerDocument.createElement("div");
+ div.appendChild( this.cloneNode(true) );
+ html = div.innerHTML;
+ }
+
+ return jQuery.clean([html.replace(rinlinejQuery, "")
+ // Handle the case in IE 8 where action=/test/> self-closes a tag
+ .replace(raction, '="$1">')
+ .replace(rleadingWhitespace, "")], ownerDocument)[0];
+ } else {
+ return this.cloneNode(true);
+ }
+ });
+
+ // Copy the events from the original to the clone
+ if ( events === true ) {
+ cloneCopyEvent( this, ret );
+ cloneCopyEvent( this.find("*"), ret.find("*") );
+ }
+
+ // Return the cloned set
+ return ret;
+ },
+
+ html: function( value ) {
+ if ( value === undefined ) {
+ return this[0] && this[0].nodeType === 1 ?
+ this[0].innerHTML.replace(rinlinejQuery, "") :
+ null;
+
+ // See if we can take a shortcut and just use innerHTML
+ } else if ( typeof value === "string" && !rnocache.test( value )
&&
+ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ]
) {
+
+ value = value.replace(rxhtmlTag, "<$1></$2>");
+
+ try {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( this[i].nodeType === 1 ) {
+ jQuery.cleanData( this[i].getElementsByTagName("*") );
+ this[i].innerHTML = value;
+ }
+ }
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {
+ this.empty().append( value );
+ }
+
+ } else if ( jQuery.isFunction( value ) ) {
+ this.each(function(i){
+ var self = jQuery( this );
+
+ self.html( value.call(this, i, self.html()) );
+ });
+
+ } else {
+ this.empty().append( value );
+ }
+
+ return this;
+ },
+
+ replaceWith: function( value ) {
+ if ( this[0] && this[0].parentNode ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
+
+ if ( typeof value !== "string" ) {
+ value = jQuery( value ).detach();
+ }
+
+ return this.each(function() {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ jQuery( this ).remove();
+
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ } else {
+ return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value),
"replaceWith", value );
+ }
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+ var results, first, fragment, parent,
+ value = args[0],
+ scripts = [];
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof
value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback, true );
+ });
+ }
+
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call(this, i, table ? self.html() : undefined);
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( this[0] ) {
+ parent = value && value.parentNode;
+
+ // If we're in a fragment, just use that instead of building a new one
+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11
&& parent.childNodes.length === this.length ) {
+ results = { fragment: parent };
+
+ } else {
+ results = jQuery.buildFragment( args, this, scripts );
+ }
+
+ fragment = results.fragment;
+
+ if ( fragment.childNodes.length === 1 ) {
+ first = fragment = fragment.firstChild;
+ } else {
+ first = fragment.firstChild;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ callback.call(
+ table ?
+ root(this[i], first) :
+ this[i],
+ i > 0 || results.cacheable || this.length > 1 ?
+ fragment.cloneNode(true) :
+ fragment
+ );
+ }
+ }
+
+ if ( scripts.length ) {
+ jQuery.each( scripts, evalScript );
+ }
+ }
+
+ return this;
+ }
+});
+
+function root( elem, cur ) {
+ return jQuery.nodeName(elem, "table") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+}
+
+function cloneCopyEvent(orig, ret) {
+ var i = 0;
+
+ ret.each(function() {
+ if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
+ return;
+ }
+
+ var oldData = jQuery.data( orig[i++] ),
+ curData = jQuery.data( this, oldData ),
+ events = oldData && oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( var type in events ) {
+ for ( var handler in events[ type ] ) {
+ jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler
].data );
+ }
+ }
+ }
+ });
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+ var fragment, cacheable, cacheresults,
+ doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
+
+ // Only cache "small" (1/2 KB) strings that are associated with the main
document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a
fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't
cache
+ if ( args.length === 1 && typeof args[0] === "string" &&
args[0].length < 512 && doc === document &&
+ !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test(
args[0] )) ) {
+
+ cacheable = true;
+ cacheresults = jQuery.fragments[ args[0] ];
+ if ( cacheresults ) {
+ if ( cacheresults !== 1 ) {
+ fragment = cacheresults;
+ }
+ }
+ }
+
+ if ( !fragment ) {
+ fragment = doc.createDocumentFragment();
+ jQuery.clean( args, doc, fragment, scripts );
+ }
+
+ if ( cacheable ) {
+ jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
+ }
+
+ return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [],
+ insert = jQuery( selector ),
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1
&& insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
+
+ } else {
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = (i > 0 ? this.clone(true) : this).get();
+ jQuery( insert[i] )[ original ]( elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, insert.selector );
+ }
+ };
+});
+
+jQuery.extend({
+ clean: function( elems, context, fragment, scripts ) {
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof
'object'
+ if ( typeof context.createElement === "undefined" ) {
+ context = context.ownerDocument || context[0] && context[0].ownerDocument ||
document;
+ }
+
+ var ret = [];
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
+
+ if ( !elem ) {
+ continue;
+ }
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" && !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
+
+ } else if ( typeof elem === "string" ) {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0],
+ div = context.createElement("div");
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = rtbody.test(elem),
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( var j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j
].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
+
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) )
{
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ),
div.firstChild );
+ }
+
+ elem = div.childNodes;
+ }
+
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ ret = jQuery.merge( ret, elem );
+ }
+ }
+
+ if ( fragment ) {
+ for ( i = 0; ret[i]; i++ ) {
+ if ( scripts && jQuery.nodeName( ret[i], "script" ) &&
(!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i]
);
+
+ } else {
+ if ( ret[i].nodeType === 1 ) {
+ ret.splice.apply( ret, [i + 1,
0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+ }
+ fragment.appendChild( ret[i] );
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ cleanData: function( elems ) {
+ var data, id, cache = jQuery.cache,
+ special = jQuery.event.special,
+ deleteExpando = jQuery.support.deleteExpando;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ continue;
+ }
+
+ id = elem[ jQuery.expando ];
+
+ if ( id ) {
+ data = cache[ id ];
+
+ if ( data && data.events ) {
+ for ( var type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ if ( deleteExpando ) {
+ delete elem[ jQuery.expando ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ delete cache[ id ];
+ }
+ }
+ }
+});
+
+function evalScript( i, elem ) {
+ if ( elem.src ) {
+ jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+ } else {
+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+}
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity=([^)]*)/,
+ rdashAlpha = /-([a-z])/ig,
+ rupper = /([A-Z])/g,
+ rnumpx = /^-?\d+(?:px)?$/i,
+ rnum = /^-?\d/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display:
"block" },
+ cssWidth = [ "Left", "Right" ],
+ cssHeight = [ "Top", "Bottom" ],
+ curCSS,
+
+ getComputedStyle,
+ currentStyle,
+
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn.css = function( name, value ) {
+ // Setting 'undefined' is a no-op
+ if ( arguments.length === 2 && value === undefined ) {
+ return this;
+ }
+
+ return jQuery.access( this, name, value, true, function( elem, name, value ) {
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ });
+};
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity", "opacity" );
+ return ret === "" ? "1" : ret;
+
+ } else {
+ return elem.style.opacity;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "zIndex": true,
+ "fontWeight": true,
+ "opacity": true,
+ "zoom": true,
+ "lineHeight": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" :
"styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, origName = jQuery.camelCase( name ),
+ style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+ name = jQuery.cssProps[ origName ] || origName;
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( typeof value === "number" && isNaN( value ) || value == null )
{
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS
properties)
+ if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !==
undefined ) {
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are
provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem,
false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra ) {
+ // Make sure that we're working with the right name
+ var ret, origName = jQuery.camelCase( name ),
+ hooks = jQuery.cssHooks[ origName ];
+
+ name = jQuery.cssProps[ origName ] || origName;
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, true,
extra )) !== undefined ) {
+ return ret;
+
+ // Otherwise, if a way to get the computed value exists, use that
+ } else if ( curCSS ) {
+ return curCSS( elem, name, origName );
+ }
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+ },
+
+ camelCase: function( string ) {
+ return string.replace( rdashAlpha, fcamelCase );
+ }
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ var val;
+
+ if ( computed ) {
+ if ( elem.offsetWidth !== 0 ) {
+ val = getWH( elem, name, extra );
+
+ } else {
+ jQuery.swap( elem, cssShow, function() {
+ val = getWH( elem, name, extra );
+ });
+ }
+
+ if ( val <= 0 ) {
+ val = curCSS( elem, name, name );
+
+ if ( val === "0px" && currentStyle ) {
+ val = currentStyle( elem, name, name );
+ }
+
+ if ( val != null ) {
+ // Should return "auto" instead of 0, use 0 for
+ // temporary backwards-compat
+ return val === "" || val === "auto" ? "0px" : val;
+ }
+ }
+
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+
+ // Should return "auto" instead of 0, use 0 for
+ // temporary backwards-compat
+ return val === "" || val === "auto" ? "0px" : val;
+ }
+
+ return typeof val === "string" ? val : val + "px";
+ }
+ },
+
+ set: function( elem, value ) {
+ if ( rnumpx.test( value ) ) {
+ // ignore negative width and height values #1599
+ value = parseFloat(value);
+
+ if ( value >= 0 ) {
+ return value + "px";
+ }
+
+ } else {
+ return value;
+ }
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter
: elem.style.filter) || "") ?
+ (parseFloat(RegExp.$1) / 100) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style;
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // Set the alpha filter to set the opacity
+ var opacity = jQuery.isNaN(value) ?
+ "" :
+ "alpha(opacity=" + value * 100 + ")",
+ filter = style.filter || "";
+
+ style.filter = ralpha.test(filter) ?
+ filter.replace(ralpha, opacity) :
+ style.filter + ' ' + opacity;
+ }
+ };
+}
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+ getComputedStyle = function( elem, newName, name ) {
+ var ret, defaultView, computedStyle;
+
+ name = name.replace( rupper, "-$1" ).toLowerCase();
+
+ if ( !(defaultView = elem.ownerDocument.defaultView) ) {
+ return undefined;
+ }
+
+ if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+ ret = computedStyle.getPropertyValue( name );
+ if ( ret === "" && !jQuery.contains(
elem.ownerDocument.documentElement, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+ }
+
+ return ret;
+ };
+}
+
+if ( document.documentElement.currentStyle ) {
+ currentStyle = function( elem, name ) {
+ var left, rsLeft,
+ ret = elem.currentStyle && elem.currentStyle[ name ],
+ style = elem.style;
+
+ // From the awesome hack by Dean Edwards
+ //
http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+ // Remember the original values
+ left = style.left;
+ rsLeft = elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ style.left = name === "fontSize" ? "1em" : (ret || 0);
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ elem.runtimeStyle.left = rsLeft;
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+ var which = name === "width" ? cssWidth : cssHeight,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
+
+ if ( extra === "border" ) {
+ return val;
+ }
+
+ jQuery.each( which, function() {
+ if ( !extra ) {
+ val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
+ }
+
+ if ( extra === "margin" ) {
+ val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
+
+ } else {
+ val -= parseFloat(jQuery.css( elem, "border" + this + "Width" ))
|| 0;
+ }
+ });
+
+ return val;
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ var width = elem.offsetWidth,
+ height = elem.offsetHeight;
+
+ return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets
&& (elem.style.display || jQuery.css( elem, "display" )) ===
"none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+
+
+
+var jsc = jQuery.now(),
+ rscript =
/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ rselectTextarea = /^(?:select|textarea)/i,
+ rinput =
/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rbracket = /\[\]$/,
+ jsre = /\=\?(&|$)/,
+ rquery = /\?/,
+ rts = /([?&])_=[^&]*/,
+ rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+ r20 = /%20/g,
+ rhash = /#.*$/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load;
+
+jQuery.fn.extend({
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+
+ // Don't do a request if no elements are being requested
+ } else if ( !this.length ) {
+ return this;
+ }
+
+ var off = url.indexOf(" ");
+ if ( off >= 0 ) {
+ var selector = url.slice(off, url.length);
+ url = url.slice(0, off);
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params ) {
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = null;
+
+ // Otherwise, build a param string
+ } else if ( typeof params === "object" ) {
+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+ type = "POST";
+ }
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ complete: function( res, status ) {
+ // If successful, inject the HTML into all the matched elements
+ if ( status === "success" || status === "notmodified" ) {
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(res.responseText.replace(rscript, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ res.responseText );
+ }
+
+ if ( callback ) {
+ self.each( callback, [res.responseText, status, res] );
+ }
+ }
+ });
+
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param(this.serializeArray());
+ },
+
+ serializeArray: function() {
+ return this.map(function() {
+ return this.elements ? jQuery.makeArray(this.elements) : this;
+ })
+ .filter(function() {
+ return this.name && !this.disabled &&
+ (this.checked || rselectTextarea.test(this.nodeName) ||
+ rinput.test(this.type));
+ })
+ .map(function( i, elem ) {
+ var val = jQuery(this).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray(val) ?
+ jQuery.map( val, function( val, i ) {
+ return { name: elem.name, value: val };
+ }) :
+ { name: elem.name, value: val };
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess
ajaxSend".split(" "), function( i, o ) {
+ jQuery.fn[o] = function( f ) {
+ return this.bind(o, f);
+ };
+});
+
+jQuery.extend({
+ get: function( url, data, callback, type ) {
+ // shift arguments if data argument was omited
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = null;
+ }
+
+ return jQuery.ajax({
+ type: "GET",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get(url, null, callback, "script");
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get(url, data, callback, "json");
+ },
+
+ post: function( url, data, callback, type ) {
+ // shift arguments if data argument was omited
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = {};
+ }
+
+ return jQuery.ajax({
+ type: "POST",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ ajaxSetup: function( settings ) {
+ jQuery.extend( jQuery.ajaxSettings, settings );
+ },
+
+ ajaxSettings: {
+ url: location.href,
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ username: null,
+ password: null,
+ traditional: false,
+ */
+ // This function can be overriden by calling jQuery.ajaxSetup
+ xhr: function() {
+ return new window.XMLHttpRequest();
+ },
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ script: "text/javascript, application/javascript",
+ json: "application/json, text/javascript",
+ text: "text/plain",
+ _default: "*/*"
+ }
+ },
+
+ ajax: function( origSettings ) {
+ var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
+ jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type);
+
+ s.url = s.url.replace( rhash, "" );
+
+ // Use original (not extended) context object if it was provided
+ s.context = origSettings && origSettings.context != null ? origSettings.context
: s;
+
+ // convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" )
{
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Handle JSONP Parameter Callbacks
+ if ( s.dataType === "jsonp" ) {
+ if ( type === "GET" ) {
+ if ( !jsre.test( s.url ) ) {
+ s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp ||
"callback") + "=?";
+ }
+ } else if ( !s.data || !jsre.test(s.data) ) {
+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp ||
"callback") + "=?";
+ }
+ s.dataType = "json";
+ }
+
+ // Build temporary JSONP function
+ if ( s.dataType === "json" && (s.data && jsre.test(s.data) ||
jsre.test(s.url)) ) {
+ jsonp = s.jsonpCallback || ("jsonp" + jsc++);
+
+ // Replace the =? sequence both in the query string and the data
+ if ( s.data ) {
+ s.data = (s.data + "").replace(jsre, "=" + jsonp +
"$1");
+ }
+
+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+ // We need to make sure
+ // that a JSONP style response is executed properly
+ s.dataType = "script";
+
+ // Handle JSONP-style loading
+ var customJsonp = window[ jsonp ];
+
+ window[ jsonp ] = function( tmp ) {
+ if ( jQuery.isFunction( customJsonp ) ) {
+ customJsonp( tmp );
+
+ } else {
+ // Garbage collect
+ window[ jsonp ] = undefined;
+
+ try {
+ delete window[ jsonp ];
+ } catch( jsonpError ) {}
+ }
+
+ data = tmp;
+ jQuery.handleSuccess( s, xhr, status, data );
+ jQuery.handleComplete( s, xhr, status, data );
+
+ if ( head ) {
+ head.removeChild( script );
+ }
+ };
+ }
+
+ if ( s.dataType === "script" && s.cache === null ) {
+ s.cache = false;
+ }
+
+ if ( s.cache === false && noContent ) {
+ var ts = jQuery.now();
+
+ // try replacing _= if it is there
+ var ret = s.url.replace(rts, "$1_=" + ts);
+
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" :
"?") + "_=" + ts : "");
+ }
+
+ // If data is available, append data to url for GET/HEAD requests
+ if ( s.data && noContent ) {
+ s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
+ }
+
+ // Watch for a new set of requests
+ if ( s.global && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // Matches an absolute URL, and saves the domain
+ var parts = rurl.exec( s.url ),
+ remote = parts && (parts[1] && parts[1].toLowerCase() !==
location.protocol || parts[2].toLowerCase() !== location.host);
+
+ // If we're requesting a remote document
+ // and trying to load JSON or Script with a GET
+ if ( s.dataType === "script" && type === "GET" &&
remote ) {
+ var head = document.getElementsByTagName("head")[0] ||
document.documentElement;
+ var script = document.createElement("script");
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+ script.src = s.url;
+
+ // Handle Script loading
+ if ( !jsonp ) {
+ var done = false;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function() {
+ if ( !done && (!this.readyState ||
+ this.readyState === "loaded" || this.readyState ===
"complete") ) {
+ done = true;
+ jQuery.handleSuccess( s, xhr, status, data );
+ jQuery.handleComplete( s, xhr, status, data );
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+ if ( head && script.parentNode ) {
+ head.removeChild( script );
+ }
+ }
+ };
+ }
+
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709 and #4378).
+ head.insertBefore( script, head.firstChild );
+
+ // We handle everything using the script element injection
+ return undefined;
+ }
+
+ var requestDone = false;
+
+ // Create the request object
+ var xhr = s.xhr();
+
+ if ( !xhr ) {
+ return;
+ }
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open(type, s.url, s.async, s.username, s.password);
+ } else {
+ xhr.open(type, s.url, s.async);
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ // Set content-type if data specified and content-body is valid for this type
+ if ( (s.data != null && !noContent) || (origSettings &&
origSettings.contentType) ) {
+ xhr.setRequestHeader("Content-Type", s.contentType);
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[s.url] ) {
+ xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
+ }
+
+ if ( jQuery.etag[s.url] ) {
+ xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
+ }
+ }
+
+ // Set header so the called script knows that it's an XMLHttpRequest
+ // Only send the header if it's not a remote XHR
+ if ( !remote ) {
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ]
?
+ s.accepts[ s.dataType ] + ", */*; q=0.01" :
+ s.accepts._default );
+ } catch( headerError ) {}
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) {
+ // Handle the global AJAX counter
+ if ( s.global && jQuery.active-- === 1 ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+
+ // close opended socket
+ xhr.abort();
+ return false;
+ }
+
+ if ( s.global ) {
+ jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] );
+ }
+
+ // Wait for a response to come back
+ var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
+ // The request was aborted
+ if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
+ // Opera doesn't call onreadystatechange before this point
+ // so we simulate the call
+ if ( !requestDone ) {
+ jQuery.handleComplete( s, xhr, status, data );
+ }
+
+ requestDone = true;
+ if ( xhr ) {
+ xhr.onreadystatechange = jQuery.noop;
+ }
+
+ // The transfer is complete and the data is available, or the request timed out
+ } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout
=== "timeout") ) {
+ requestDone = true;
+ xhr.onreadystatechange = jQuery.noop;
+
+ status = isTimeout === "timeout" ?
+ "timeout" :
+ !jQuery.httpSuccess( xhr ) ?
+ "error" :
+ s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
+ "notmodified" :
+ "success";
+
+ var errMsg;
+
+ if ( status === "success" ) {
+ // Watch for, and catch, XML document parse errors
+ try {
+ // process the data (runs the xml through httpData regardless of callback)
+ data = jQuery.httpData( xhr, s.dataType, s );
+ } catch( parserError ) {
+ status = "parsererror";
+ errMsg = parserError;
+ }
+ }
+
+ // Make sure that the request was successful or notmodified
+ if ( status === "success" || status === "notmodified" ) {
+ // JSONP handles its own success callback
+ if ( !jsonp ) {
+ jQuery.handleSuccess( s, xhr, status, data );
+ }
+ } else {
+ jQuery.handleError( s, xhr, status, errMsg );
+ }
+
+ // Fire the complete handlers
+ if ( !jsonp ) {
+ jQuery.handleComplete( s, xhr, status, data );
+ }
+
+ if ( isTimeout === "timeout" ) {
+ xhr.abort();
+ }
+
+ // Stop memory leaks
+ if ( s.async ) {
+ xhr = null;
+ }
+ }
+ };
+
+ // Override the abort handler, if we can (IE 6 doesn't allow it, but that's
OK)
+ // Opera doesn't fire onreadystatechange at all on abort
+ try {
+ var oldAbort = xhr.abort;
+ xhr.abort = function() {
+ if ( xhr ) {
+ // oldAbort has no call property in IE7 so
+ // just do it this way, which works in all
+ // browsers
+ Function.prototype.call.call( oldAbort, xhr );
+ }
+
+ onreadystatechange( "abort" );
+ };
+ } catch( abortError ) {}
+
+ // Timeout checker
+ if ( s.async && s.timeout > 0 ) {
+ setTimeout(function() {
+ // Check to see if the request is still happening
+ if ( xhr && !requestDone ) {
+ onreadystatechange( "timeout" );
+ }
+ }, s.timeout);
+ }
+
+ // Send the data
+ try {
+ xhr.send( noContent || s.data == null ? null : s.data );
+
+ } catch( sendError ) {
+ jQuery.handleError( s, xhr, null, sendError );
+
+ // Fire the complete handlers
+ jQuery.handleComplete( s, xhr, status, data );
+ }
+
+ // firefox 1.5 doesn't fire statechange for sync requests
+ if ( !s.async ) {
+ onreadystatechange();
+ }
+
+ // return XMLHttpRequest to allow aborting the request etc.
+ return xhr;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a, traditional ) {
+ var s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction(value) ? value() : value;
+ s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray(a) || a.jquery ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( var prefix in a ) {
+ buildParams( prefix, a[prefix], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join("&").replace(r20, "+");
+ }
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+ if ( jQuery.isArray(obj) && obj.length ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" ||
jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && obj != null && typeof obj ===
"object" ) {
+ if ( jQuery.isEmptyObject( obj ) ) {
+ add( prefix, "" );
+
+ // Serialize object item.
+ } else {
+ jQuery.each( obj, function( k, v ) {
+ buildParams( prefix + "[" + k + "]", v, traditional, add );
+ });
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ handleError: function( s, xhr, status, e ) {
+ // If a local callback was specified, fire it
+ if ( s.error ) {
+ s.error.call( s.context, xhr, status, e );
+ }
+
+ // Fire the global callback
+ if ( s.global ) {
+ jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] );
+ }
+ },
+
+ handleSuccess: function( s, xhr, status, data ) {
+ // If a local callback was specified, fire it and pass it the data
+ if ( s.success ) {
+ s.success.call( s.context, data, status, xhr );
+ }
+
+ // Fire the global callback
+ if ( s.global ) {
+ jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] );
+ }
+ },
+
+ handleComplete: function( s, xhr, status ) {
+ // Process result
+ if ( s.complete ) {
+ s.complete.call( s.context, xhr, status );
+ }
+
+ // The request was completed
+ if ( s.global ) {
+ jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] );
+ }
+
+ // Handle the global AJAX counter
+ if ( s.global && jQuery.active-- === 1 ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ },
+
+ triggerGlobal: function( s, type, args ) {
+ (s.context && s.context.url == null ? jQuery(s.context) :
jQuery.event).trigger(type, args);
+ },
+
+ // Determines if an XMLHttpRequest was successful or not
+ httpSuccess: function( xhr ) {
+ try {
+ // IE error sometimes returns 1223 when it should be 204 so treat it as success, see
#1450
+ return !xhr.status && location.protocol === "file:" ||
+ xhr.status >= 200 && xhr.status < 300 ||
+ xhr.status === 304 || xhr.status === 1223;
+ } catch(e) {}
+
+ return false;
+ },
+
+ // Determines if an XMLHttpRequest returns NotModified
+ httpNotModified: function( xhr, url ) {
+ var lastModified = xhr.getResponseHeader("Last-Modified"),
+ etag = xhr.getResponseHeader("Etag");
+
+ if ( lastModified ) {
+ jQuery.lastModified[url] = lastModified;
+ }
+
+ if ( etag ) {
+ jQuery.etag[url] = etag;
+ }
+
+ return xhr.status === 304;
+ },
+
+ httpData: function( xhr, type, s ) {
+ var ct = xhr.getResponseHeader("content-type") || "",
+ xml = type === "xml" || !type && ct.indexOf("xml") >=
0,
+ data = xml ? xhr.responseXML : xhr.responseText;
+
+ if ( xml && data.documentElement.nodeName === "parsererror" ) {
+ jQuery.error( "parsererror" );
+ }
+
+ // Allow a pre-filtering function to sanitize the response
+ // s is checked to keep backwards compatibility
+ if ( s && s.dataFilter ) {
+ data = s.dataFilter( data, type );
+ }
+
+ // The filter can actually parse the response
+ if ( typeof data === "string" ) {
+ // Get the JavaScript object, if JSON is used.
+ if ( type === "json" || !type && ct.indexOf("json") >=
0 ) {
+ data = jQuery.parseJSON( data );
+
+ // If the type is "script", eval it in global context
+ } else if ( type === "script" || !type &&
ct.indexOf("javascript") >= 0 ) {
+ jQuery.globalEval( data );
+ }
+ }
+
+ return data;
+ }
+
+});
+
+/*
+ * Create the request object; Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+if ( window.ActiveXObject ) {
+ jQuery.ajaxSettings.xhr = function() {
+ if ( window.location.protocol !== "file:" ) {
+ try {
+ return new window.XMLHttpRequest();
+ } catch(xhrError) {}
+ }
+
+ try {
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
+ } catch(activeError) {}
+ };
+}
+
+// Does this browser support XHR requests?
+jQuery.support.ajax = !!jQuery.ajaxSettings.xhr();
+
+
+
+
+var elemdisplay = {},
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/,
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom",
"paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight",
"paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ];
+
+jQuery.fn.extend({
+ show: function( speed, easing, callback ) {
+ var elem, display;
+
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("show", 3), speed, easing, callback);
+
+ } else {
+ for ( var i = 0, j = this.length; i < j; i++ ) {
+ elem = this[i];
+ display = elem.style.display;
+
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !jQuery.data(elem, "olddisplay") && display ===
"none" ) {
+ display = elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( display === "" && jQuery.css( elem, "display" ) ===
"none" ) {
+ jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName));
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ elem = this[i];
+ display = elem.style.display;
+
+ if ( display === "" || display === "none" ) {
+ elem.style.display = jQuery.data(elem, "olddisplay") || "";
+ }
+ }
+
+ return this;
+ }
+ },
+
+ hide: function( speed, easing, callback ) {
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("hide", 3), speed, easing, callback);
+
+ } else {
+ for ( var i = 0, j = this.length; i < j; i++ ) {
+ var display = jQuery.css( this[i], "display" );
+
+ if ( display !== "none" ) {
+ jQuery.data( this[i], "olddisplay", display );
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ this[i].style.display = "none";
+ }
+
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2, callback ) {
+ var bool = typeof fn === "boolean";
+
+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+ this._toggle.apply( this, arguments );
+
+ } else if ( fn == null || bool ) {
+ this.each(function() {
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ });
+
+ } else {
+ this.animate(genFx("toggle", 3), fn, fn2, callback);
+ }
+
+ return this;
+ },
+
+ fadeTo: function( speed, to, easing, callback ) {
+ return this.filter(":hidden").css("opacity", 0).show().end()
+ .animate({opacity: to}, speed, easing, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed(speed, easing, callback);
+
+ if ( jQuery.isEmptyObject( prop ) ) {
+ return this.each( optall.complete );
+ }
+
+ return this[ optall.queue === false ? "each" : "queue" ](function()
{
+ // XXX 'this' does not always have a nodeName when running the
+ // test suite
+
+ var opt = jQuery.extend({}, optall), p,
+ isElement = this.nodeType === 1,
+ hidden = isElement && jQuery(this).is(":hidden"),
+ self = this;
+
+ for ( p in prop ) {
+ var name = jQuery.camelCase( p );
+
+ if ( p !== name ) {
+ prop[ name ] = prop[ p ];
+ delete prop[ p ];
+ p = name;
+ }
+
+ if ( prop[p] === "hide" && hidden || prop[p] === "show"
&& !hidden ) {
+ return opt.complete.call(this);
+ }
+
+ if ( isElement && ( p === "height" || p === "width" ) )
{
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height
+ // animated
+ if ( jQuery.css( this, "display" ) === "inline" &&
+ jQuery.css( this, "float" ) === "none" ) {
+ if ( !jQuery.support.inlineBlockNeedsLayout ) {
+ this.style.display = "inline-block";
+
+ } else {
+ var display = defaultDisplay(this.nodeName);
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( display === "inline" ) {
+ this.style.display = "inline-block";
+
+ } else {
+ this.style.display = "inline";
+ this.style.zoom = 1;
+ }
+ }
+ }
+ }
+
+ if ( jQuery.isArray( prop[p] ) ) {
+ // Create (if needed) and add to specialEasing
+ (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
+ prop[p] = prop[p][0];
+ }
+ }
+
+ if ( opt.overflow != null ) {
+ this.style.overflow = "hidden";
+ }
+
+ opt.curAnim = jQuery.extend({}, prop);
+
+ jQuery.each( prop, function( name, val ) {
+ var e = new jQuery.fx( self, opt, name );
+
+ if ( rfxtypes.test(val) ) {
+ e[ val === "toggle" ? hidden ? "show" : "hide" : val
]( prop );
+
+ } else {
+ var parts = rfxnum.exec(val),
+ start = e.cur() || 0;
+
+ if ( parts ) {
+ var end = parseFloat( parts[2] ),
+ unit = parts[3] || "px";
+
+ // We need to compute starting value
+ if ( unit !== "px" ) {
+ jQuery.style( self, name, (end || 1) + unit);
+ start = ((end || 1) / e.cur()) * start;
+ jQuery.style( self, name, start + unit);
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] ) {
+ end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
+ }
+
+ e.custom( start, end, unit );
+
+ } else {
+ e.custom( start, val, "" );
+ }
+ }
+ });
+
+ // For JS strict compliance
+ return true;
+ });
+ },
+
+ stop: function( clearQueue, gotoEnd ) {
+ var timers = jQuery.timers;
+
+ if ( clearQueue ) {
+ this.queue([]);
+ }
+
+ this.each(function() {
+ // go in reverse order so anything added to the queue during the loop is ignored
+ for ( var i = timers.length - 1; i >= 0; i-- ) {
+ if ( timers[i].elem === this ) {
+ if (gotoEnd) {
+ // force the next step to be the last
+ timers[i](true);
+ }
+
+ timers.splice(i, 1);
+ }
+ }
+ });
+
+ // start the next in the queue if the last step wasn't forced
+ if ( !gotoEnd ) {
+ this.dequeue();
+ }
+
+ return this;
+ }
+
+});
+
+function genFx( type, num ) {
+ var obj = {};
+
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
+ obj[ this ] = type;
+ });
+
+ return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show", 1),
+ slideUp: genFx("hide", 1),
+ slideToggle: genFx("toggle", 1),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.extend({
+ speed: function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend({},
speed) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction(easing)
&& easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ?
opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] :
jQuery.fx.speeds._default;
+
+ // Queueing
+ opt.old = opt.complete;
+ opt.complete = function() {
+ if ( opt.queue !== false ) {
+ jQuery(this).dequeue();
+ }
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ) {
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ if ( !options.orig ) {
+ options.orig = {};
+ }
+ }
+
+});
+
+jQuery.fx.prototype = {
+ // Simple function for setting a style value
+ update: function() {
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+ },
+
+ // Get the current size
+ cur: function() {
+ if ( this.elem[this.prop] != null && (!this.elem.style ||
this.elem.style[this.prop] == null) ) {
+ return this.elem[ this.prop ];
+ }
+
+ var r = parseFloat( jQuery.css( this.elem, this.prop ) );
+ return r && r > -10000 ? r : 0;
+ },
+
+ // Start an animation from one number to another
+ custom: function( from, to, unit ) {
+ var self = this,
+ fx = jQuery.fx;
+
+ this.startTime = jQuery.now();
+ this.start = from;
+ this.end = to;
+ this.unit = unit || this.unit || "px";
+ this.now = this.start;
+ this.pos = this.state = 0;
+
+ function t( gotoEnd ) {
+ return self.step(gotoEnd);
+ }
+
+ t.elem = this.elem;
+
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval(fx.tick, fx.interval);
+ }
+ },
+
+ // Simple 'show' function
+ show: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any
+ // flash of content
+ this.custom(this.prop === "width" || this.prop === "height" ? 1 :
0, this.cur());
+
+ // Start by showing the element
+ jQuery( this.elem ).show();
+ },
+
+ // Simple 'hide' function
+ hide: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom(this.cur(), 0);
+ },
+
+ // Each step of an animation
+ step: function( gotoEnd ) {
+ var t = jQuery.now(), done = true;
+
+ if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ this.options.curAnim[ this.prop ] = true;
+
+ for ( var i in this.options.curAnim ) {
+ if ( this.options.curAnim[i] !== true ) {
+ done = false;
+ }
+ }
+
+ if ( done ) {
+ // Reset the overflow
+ if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+ var elem = this.elem,
+ options = this.options;
+
+ jQuery.each( [ "", "X", "Y" ], function (index, value)
{
+ elem.style[ "overflow" + value ] = options.overflow[index];
+ } );
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( this.options.hide ) {
+ jQuery(this.elem).hide();
+ }
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( this.options.hide || this.options.show ) {
+ for ( var p in this.options.curAnim ) {
+ jQuery.style( this.elem, p, this.options.orig[p] );
+ }
+ }
+
+ // Execute the complete function
+ this.options.complete.call( this.elem );
+ }
+
+ return false;
+
+ } else {
+ var n = t - this.startTime;
+ this.state = n / this.options.duration;
+
+ // Perform the easing function, defaults to swing
+ var specialEasing = this.options.specialEasing &&
this.options.specialEasing[this.prop];
+ var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" :
"linear");
+ this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1,
this.options.duration);
+ this.now = this.start + ((this.end - this.start) * this.pos);
+
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+};
+
+jQuery.extend( jQuery.fx, {
+ tick: function() {
+ var timers = jQuery.timers;
+
+ for ( var i = 0; i < timers.length; i++ ) {
+ if ( !timers[i]() ) {
+ timers.splice(i--, 1);
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ },
+
+ interval: 13,
+
+ stop: function() {
+ clearInterval( timerId );
+ timerId = null;
+ },
+
+ speeds: {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+
+ step: {
+ opacity: function( fx ) {
+ jQuery.style( fx.elem, "opacity", fx.now );
+ },
+
+ _default: function( fx ) {
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+ fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop ===
"height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
+ } else {
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+ }
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+
+function defaultDisplay( nodeName ) {
+ if ( !elemdisplay[ nodeName ] ) {
+ var elem = jQuery("<" + nodeName +
">").appendTo("body"),
+ display = elem.css("display");
+
+ elem.remove();
+
+ if ( display === "none" || display === "" ) {
+ display = "block";
+ }
+
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+ rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0], box;
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ try {
+ box = elem.getBoundingClientRect();
+ } catch(e) {}
+
+ var doc = elem.ownerDocument,
+ docElem = doc.documentElement;
+
+ // Make sure we're not dealing with a disconnected DOM node
+ if ( !box || !jQuery.contains( docElem, elem ) ) {
+ return box || { top: 0, left: 0 };
+ }
+
+ var body = doc.body,
+ win = getWindow(doc),
+ clientTop = docElem.clientTop || body.clientTop || 0,
+ clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop
|| body.scrollTop ),
+ scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft
|| body.scrollLeft),
+ top = box.top + scrollTop - clientTop,
+ left = box.left + scrollLeft - clientLeft;
+
+ return { top: top, left: left };
+ };
+
+} else {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0];
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ jQuery.offset.initialize();
+
+ var computedStyle,
+ offsetParent = elem.offsetParent,
+ prevOffsetParent = elem,
+ doc = elem.ownerDocument,
+ docElem = doc.documentElement,
+ body = doc.body,
+ defaultView = doc.defaultView,
+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) :
elem.currentStyle,
+ top = elem.offsetTop,
+ left = elem.offsetLeft;
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem )
{
+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position ===
"fixed" ) {
+ break;
+ }
+
+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) :
elem.currentStyle;
+ top -= elem.scrollTop;
+ left -= elem.scrollLeft;
+
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop;
+ left += elem.offsetLeft;
+
+ if ( jQuery.offset.doesNotAddBorder &&
!(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevOffsetParent = offsetParent;
+ offsetParent = elem.offsetParent;
+ }
+
+ if ( jQuery.offset.subtractsBorderForOverflowNotVisible &&
computedStyle.overflow !== "visible" ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position
=== "static" ) {
+ top += body.offsetTop;
+ left += body.offsetLeft;
+ }
+
+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position ===
"fixed" ) {
+ top += Math.max( docElem.scrollTop, body.scrollTop );
+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
+ }
+
+ return { top: top, left: left };
+ };
+}
+
+jQuery.offset = {
+ initialize: function() {
+ var body = document.body, container = document.createElement("div"),
innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body,
"marginTop") ) || 0,
+ html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px
solid
#000;padding:0;width:1px;height:1px;'><div></div></div><table
style='position:absolute;top:0;left:0;margin:0;border:5px solid
#000;padding:0;width:1px;height:1px;' cellpadding='0'
cellspacing='0'><tr><td></td></tr></table>";
+
+ jQuery.extend( container.style, { position: "absolute", top: 0, left: 0,
margin: 0, border: 0, width: "1px", height: "1px", visibility:
"hidden" } );
+
+ container.innerHTML = html;
+ body.insertBefore( container, body.firstChild );
+ innerDiv = container.firstChild;
+ checkDiv = innerDiv.firstChild;
+ td = innerDiv.nextSibling.firstChild.firstChild;
+
+ this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+ this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+ checkDiv.style.position = "fixed";
+ checkDiv.style.top = "20px";
+
+ // safari subtracts parent border width here which is 5px
+ this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
+ checkDiv.style.position = checkDiv.style.top = "";
+
+ innerDiv.style.overflow = "hidden";
+ innerDiv.style.position = "relative";
+
+ this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+ this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
+
+ body.removeChild( container );
+ body = container = innerDiv = checkDiv = table = td = null;
+ jQuery.offset.initialize = jQuery.noop;
+ },
+
+ bodyOffset: function( body ) {
+ var top = body.offsetTop,
+ left = body.offsetLeft;
+
+ jQuery.offset.initialize();
+
+ if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
+ top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+ left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+ }
+
+ return { top: top, left: left };
+ },
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = (position === "absolute" &&
jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is
absolute
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ }
+
+ curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0;
+ curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if (options.top != null) {
+ props.top = (options.top - curOffset.top) + curTop;
+ }
+ if (options.left != null) {
+ props.left = (options.left - curOffset.left) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+ position: function() {
+ if ( !this[0] ) {
+ return null;
+ }
+
+ var elem = this[0],
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } :
offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+ offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.css(offsetParent[0],
"borderTopWidth") ) || 0;
+ parentOffset.left += parseFloat( jQuery.css(offsetParent[0],
"borderLeftWidth") ) || 0;
+
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.body;
+ while ( offsetParent && (!rroot.test(offsetParent.nodeName) &&
jQuery.css(offsetParent, "position") === "static") ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+ var method = "scroll" + name;
+
+ jQuery.fn[ method ] = function(val) {
+ var elem = this[0], win;
+
+ if ( !elem ) {
+ return null;
+ }
+
+ if ( val !== undefined ) {
+ // Set the scroll offset
+ return this.each(function() {
+ win = getWindow( this );
+
+ if ( win ) {
+ win.scrollTo(
+ !i ? val : jQuery(win).scrollLeft(),
+ i ? val : jQuery(win).scrollTop()
+ );
+
+ } else {
+ this[ method ] = val;
+ }
+ });
+ } else {
+ win = getWindow( elem );
+
+ // Return the scroll offset
+ return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" :
"pageXOffset" ] :
+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
+ win.document.body[ method ] :
+ elem[ method ];
+ }
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+
+
+
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+ var type = name.toLowerCase();
+
+ // innerHeight and innerWidth
+ jQuery.fn["inner" + name] = function() {
+ return this[0] ?
+ parseFloat( jQuery.css( this[0], type, "padding" ) ) :
+ null;
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn["outer" + name] = function( margin ) {
+ return this[0] ?
+ parseFloat( jQuery.css( this[0], type, margin ? "margin" :
"border" ) ) :
+ null;
+ };
+
+ jQuery.fn[ type ] = function( size ) {
+ // Get window width or height
+ var elem = this[0];
+ if ( !elem ) {
+ return size == null ? null : this;
+ }
+
+ if ( jQuery.isFunction( size ) ) {
+ return this.each(function( i ) {
+ var self = jQuery( this );
+ self[ type ]( size.call( this, i, self[ type ]() ) );
+ });
+ }
+
+ if ( jQuery.isWindow( elem ) ) {
+ // Everyone else use document.documentElement or document.body depending on Quirks vs
Standards mode
+ return elem.document.compatMode === "CSS1Compat" &&
elem.document.documentElement[ "client" + name ] ||
+ elem.document.body[ "client" + name ];
+
+ // Get document width or height
+ } else if ( elem.nodeType === 9 ) {
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ return Math.max(
+ elem.documentElement["client" + name],
+ elem.body["scroll" + name], elem.documentElement["scroll" +
name],
+ elem.body["offset" + name], elem.documentElement["offset" +
name]
+ );
+
+ // Get or set width or height on the element
+ } else if ( size === undefined ) {
+ var orig = jQuery.css( elem, type ),
+ ret = parseFloat( orig );
+
+ return jQuery.isNaN( ret ) ? orig : ret;
+
+ // Set the width or height on the element (default to pixels if value is unitless)
+ } else {
+ return this.css( type, typeof size === "string" ? size : size +
"px" );
+ }
+ };
+
+});
+
+
+})(window);
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js
b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js
new file mode 100644
index 0000000..d60cf18
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js
@@ -0,0 +1,1271 @@
+/**
+*
+* jquery.sparkline.js
+*
+* v1.6
+* (c) Splunk, Inc
+* Contact: Gareth Watts (gareth(a)splunk.com)
+*
http://omnipotent.net/jquery.sparkline/
+*
+* Generates inline sparkline charts from data supplied either to the method
+* or inline in HTML
+*
+* Compatible with Internet Explorer 6.0+ and modern browsers equipped with the canvas
tag
+* (Firefox 2.0+, Safari, Opera, etc)
+*
+* License: New BSD License
+*
+* Copyright (c) 2010, Splunk Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* * Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* * Neither the name of Splunk Inc nor the names of its contributors may
+* be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+* Usage:
+* $(selector).sparkline(values, options)
+*
+* If values is undefined or set to 'html' then the data values are read from the
specified tag:
+* <p>Sparkline: <span
class="sparkline">1,4,6,6,8,5,3,5</span></p>
+* $('.sparkline').sparkline();
+* There must be no spaces in the enclosed data set
+*
+* Otherwise values must be an array of numbers or null values
+* <p>Sparkline: <span id="sparkline1">This text replaced if the
browser is compatible</span></p>
+* $('#sparkline1').sparkline([1,4,6,6,8,5,3,5])
+* $('#sparkline2').sparkline([1,4,6,null,null,5,3,5])
+*
+* Values can also be specified in an HTML comment, or as a values attribute:
+* <p>Sparkline: <span class="sparkline"><!--1,4,6,6,8,5,3,5
--></span></p>
+* <p>Sparkline: <span class="sparkline"
values="1,4,6,6,8,5,3,5"></span></p>
+* $('.sparkline').sparkline();
+*
+* For line charts, x values can also be specified:
+* <p>Sparkline: <span
class="sparkline">1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5</span></p>
+* $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5],
[9,3], [10,5] ])
+*
+* By default, options should be passed in as teh second argument to the sparkline
function:
+* $('.sparkline').sparkline([1,2,3,4], {type: 'bar'})
+*
+* Options can also be set by passing them on the tag itself. This feature is disabled by
default though
+* as there's a slight performance overhead:
+* $('.sparkline').sparkline([1,2,3,4], {enableTagOptions: true})
+* <p>Sparkline: <span class="sparkline" sparkType="bar"
sparkBarColor="red">loading</span></p>
+* Prefix all options supplied as tag attribute with "spark" (configurable by
setting tagOptionPrefix)
+*
+* Supported options:
+* lineColor - Color of the line used for the chart
+* fillColor - Color used to fill in the chart - Set to '' or false for a
transparent chart
+* width - Width of the chart - Defaults to 3 times the number of values in pixels
+* height - Height of the chart - Defaults to the height of the containing element
+* chartRangeMin - Specify the minimum value to use for the Y range of the chart -
Defaults to the minimum value supplied
+* chartRangeMax - Specify the maximum value to use for the Y range of the chart -
Defaults to the maximum value supplied
+* chartRangeClip - Clip out of range values to the max/min specified by chartRangeMin
and chartRangeMax
+* chartRangeMinX - Specify the minimum value to use for the X range of the chart -
Defaults to the minimum value supplied
+* chartRangeMaxX - Specify the maximum value to use for the X range of the chart -
Defaults to the maximum value supplied
+* composite - If true then don't erase any existing chart attached to the tag, but
draw
+* another chart over the top - Note that width and height are ignored if an
+* existing chart is detected.
+* tagValuesAttribute - Name of tag attribute to check for data values - Defaults to
'values'
+* enableTagOptions - Whether to check tags for sparkline options
+* tagOptionPrefix - Prefix used for options supplied as tag attributes - Defaults to
'spark'
+*
+* There are 7 types of sparkline, selected by supplying a "type" option of
'line' (default),
+* 'bar', 'tristate', 'bullet', 'discrete', 'pie'
or 'box'
+* line - Line chart. Options:
+* spotColor - Set to '' to not end each line in a circular spot
+* minSpotColor - If set, color of spot at minimum value
+* maxSpotColor - If set, color of spot at maximum value
+* spotRadius - Radius in pixels
+* lineWidth - Width of line in pixels
+* normalRangeMin
+* normalRangeMax - If set draws a filled horizontal bar between these two values
marking the "normal"
+* or expected range of values
+* normalRangeColor - Color to use for the above bar
+* drawNormalOnTop - Draw the normal range above the chart fill color if true
+* defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the
chart
+*
+* bar - Bar chart. Options:
+* barColor - Color of bars for postive values
+* negBarColor - Color of bars for negative values
+* zeroColor - Color of bars with zero values
+* nullColor - Color of bars with null values - Defaults to omitting the bar
entirely
+* barWidth - Width of bars in pixels
+* colorMap - Optional mappnig of values to colors to override the *BarColor values
above
+* can be an Array of values to control the color of individual bars
+* barSpacing - Gap between bars in pixels
+* zeroAxis - Centers the y-axis around zero if true
+*
+* tristate - Charts values of win (>0), lose (<0) or draw (=0)
+* posBarColor - Color of win values
+* negBarColor - Color of lose values
+* zeroBarColor - Color of draw values
+* barWidth - Width of bars in pixels
+* barSpacing - Gap between bars in pixels
+* colorMap - Optional mappnig of values to colors to override the *BarColor values
above
+* can be an Array of values to control the color of individual bars
+*
+* discrete - Options:
+* lineHeight - Height of each line in pixels - Defaults to 30% of the graph height
+* thesholdValue - Values less than this value will be drawn using thresholdColor
instead of lineColor
+* thresholdColor
+*
+* bullet - Values for bullet graphs msut be in the order: target, performance, range1,
range2, range3, ...
+* options:
+* targetColor - The color of the vertical target marker
+* targetWidth - The width of the target marker in pixels
+* performanceColor - The color of the performance measure horizontal bar
+* rangeColors - Colors to use for each qualitative range background color
+*
+* pie - Pie chart. Options:
+* sliceColors - An array of colors to use for pie slices
+* offset - Angle in degrees to offset the first slice - Try -90 or +90
+*
+* box - Box plot. Options:
+* raw - Set to true to supply pre-computed plot points as values
+* values should be: low_outlier, low_whisker, q1, median, q3, high_whisker,
high_outlier
+* When set to false you can supply any number of values and the box plot
will
+* be computed for you. Default is false.
+* showOutliers - Set to true (default) to display outliers as circles
+* outlierIRQ - Interquartile range used to determine outliers. Default 1.5
+* boxLineColor - Outline color of the box
+* boxFillColor - Fill color for the box
+* whiskerColor - Line color used for whiskers
+* outlierLineColor - Outline color of outlier circles
+* outlierFillColor - Fill color of the outlier circles
+* spotRadius - Radius of outlier circles
+* medianColor - Line color of the median line
+* target - Draw a target cross hair at the supplied value (default undefined)
+*
+*
+*
+* Examples:
+* $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor:
false });
+* $('.barsparks').sparkline('html', { type:'bar',
height:'40px', barWidth:5 });
+* $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }):
+* $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' });
+* $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' });
+* $('#pie').sparkline([1,1,2], { type:'pie' });
+*/
+
+
+(function($) {
+
+ /*
+ * Default configuration settings
+ */
+ var defaults = {
+ // Settings common to most/all chart types
+ common: {
+ type : 'line',
+ lineColor : '#00f',
+ fillColor : '#cdf',
+ defaultPixelsPerValue : 3,
+ width : 'auto',
+ height : 'auto',
+ composite : false,
+ tagValuesAttribute: 'values',
+ tagOptionsPrefix: 'spark',
+ enableTagOptions: false
+ },
+ // Defaults for line charts
+ line: {
+ spotColor : '#f80',
+ spotRadius : 1.5,
+ minSpotColor : '#f80',
+ maxSpotColor : '#f80',
+ lineWidth: 1,
+ normalRangeMin : undefined,
+ normalRangeMax : undefined,
+ normalRangeColor : '#ccc',
+ drawNormalOnTop: false,
+ chartRangeMin : undefined,
+ chartRangeMax : undefined,
+ chartRangeMinX : undefined,
+ chartRangeMaxX : undefined
+ },
+ // Defaults for bar charts
+ bar: {
+ barColor : '#00f',
+ negBarColor : '#f44',
+ zeroColor: undefined,
+ nullColor: undefined,
+ zeroAxis : undefined,
+ barWidth : 4,
+ barSpacing : 1,
+ chartRangeMax: undefined,
+ chartRangeMin: undefined,
+ chartRangeClip: false,
+ colorMap : undefined
+ },
+ // Defaults for tristate charts
+ tristate: {
+ barWidth : 4,
+ barSpacing : 1,
+ posBarColor: '#6f6',
+ negBarColor : '#f44',
+ zeroBarColor : '#999',
+ colorMap : {}
+ },
+ // Defaults for discrete charts
+ discrete: {
+ lineHeight: 'auto',
+ thresholdColor: undefined,
+ thresholdValue : 0,
+ chartRangeMax: undefined,
+ chartRangeMin: undefined,
+ chartRangeClip: false
+ },
+ // Defaults for bullet charts
+ bullet: {
+ targetColor : 'red',
+ targetWidth : 3, // width of the target bar in pixels
+ performanceColor : 'blue',
+ rangeColors : ['#D3DAFE', '#A8B6FF', '#7F94FF' ],
+ base : undefined // set this to a number to change the base start number
+ },
+ // Defaults for pie charts
+ pie: {
+ sliceColors : ['#f00', '#0f0', '#00f']
+ },
+ // Defaults for box plots
+ box: {
+ raw: false,
+ boxLineColor: 'black',
+ boxFillColor: '#cdf',
+ whiskerColor: 'black',
+ outlierLineColor: '#333',
+ outlierFillColor: 'white',
+ medianColor: 'red',
+ showOutliers: true,
+ outlierIQR: 1.5,
+ spotRadius: 1.5,
+ target: undefined,
+ targetColor: '#4a2',
+ chartRangeMax: undefined,
+ chartRangeMin: undefined
+ }
+ };
+
+ // Provide a cross-browser interface to a few simple drawing primitives
+ var VCanvas_base, VCanvas_canvas, VCanvas_vml;
+ $.fn.simpledraw = function(width, height, use_existing) {
+ if (use_existing && this[0].VCanvas) {
+ return this[0].VCanvas;
+ }
+ if (width === undefined) {
+ width=$(this).innerWidth();
+ }
+ if (height === undefined) {
+ height=$(this).innerHeight();
+ }
+ if ($.browser.hasCanvas) {
+ return new VCanvas_canvas(width, height, this);
+ } else if ($.browser.msie) {
+ return new VCanvas_vml(width, height, this);
+ } else {
+ return false;
+ }
+ };
+
+ var pending = [];
+
+
+ $.fn.sparkline = function(uservalues, userOptions) {
+ return this.each(function() {
+ var options = new $.fn.sparkline.options(this, userOptions);
+ var render = function() {
+ var values, width, height;
+ if (uservalues==='html' || uservalues===undefined) {
+ var vals =
this.getAttribute(options.get('tagValuesAttribute'));
+ if (vals===undefined || vals===null) {
+ vals = $(this).html();
+ }
+ values = vals.replace(/(^\s*<!--)|(-->\s*$)|\s+/g,
'').split(',');
+ } else {
+ values = uservalues;
+ }
+
+ width = options.get('width')=='auto' ?
values.length*options.get('defaultPixelsPerValue') :
options.get('width');
+ if (options.get('height') == 'auto') {
+ if (!options.get('composite') || !this.VCanvas) {
+ // must be a better way to get the line height
+ var tmp = document.createElement('span');
+ tmp.innerHTML = 'a';
+ $(this).html(tmp);
+ height = $(tmp).innerHeight();
+ $(tmp).remove();
+ }
+ } else {
+ height = options.get('height');
+ }
+
+ $.fn.sparkline[options.get('type')].call(this, values, options,
width, height);
+ };
+ // jQuery 1.3.0 completely changed the meaning of :hidden :-/
+ if (($(this).html() && $(this).is(':hidden')) || ($.fn.jquery
< "1.3.0" && $(this).parents().is(':hidden')) ||
!$(this).parents('body').length) {
+ pending.push([this, render]);
+ } else {
+ render.call(this);
+ }
+ });
+ };
+
+ $.fn.sparkline.defaults = defaults;
+
+
+ $.sparkline_display_visible = function() {
+ for (var i=pending.length-1; i>=0; i--) {
+ var el = pending[i][0];
+ if ($(el).is(':visible') &&
!$(el).parents().is(':hidden')) {
+ pending[i][1].call(el);
+ pending.splice(i, 1);
+ }
+ }
+ };
+
+
+ /**
+ * User option handler
+ */
+ var UNSET_OPTION = {};
+ var normalizeValue = function(val) {
+ switch(val) {
+ case 'undefined':
+ val = undefined;
+ break;
+ case 'null':
+ val = null;
+ break;
+ case 'true':
+ val = true;
+ break;
+ case 'false':
+ val = false;
+ break;
+ default:
+ var nf = parseFloat(val);
+ if (val == nf) {
+ val = nf;
+ }
+ }
+ return val;
+ };
+ $.fn.sparkline.options = function(tag, userOptions) {
+ var extendedOptions;
+ this.userOptions = userOptions = userOptions || {};
+ this.tag = tag;
+ this.tagValCache = {};
+ var defaults = $.fn.sparkline.defaults;
+ var base = defaults.common;
+ this.tagOptionsPrefix = userOptions.enableTagOptions &&
(userOptions.tagOptionsPrefix || base.tagOptionsPrefix);
+
+ var tagOptionType = this.getTagSetting('type');
+ if (tagOptionType === UNSET_OPTION) {
+ extendedOptions = defaults[userOptions.type || base.type];
+ } else {
+ extendedOptions = defaults[tagOptionType];
+ }
+ this.mergedOptions = $.extend({}, base, extendedOptions, userOptions);
+ };
+
+
+ $.fn.sparkline.options.prototype.getTagSetting = function(key) {
+ var val, i, prefix = this.tagOptionsPrefix;
+ if (prefix === false || prefix === undefined) {
+ return UNSET_OPTION;
+ }
+ if (this.tagValCache.hasOwnProperty(key)) {
+ val = this.tagValCache.key;
+ } else {
+ val = this.tag.getAttribute(prefix + key);
+ if (val === undefined || val === null) {
+ val = UNSET_OPTION;
+ } else if (val.substr(0, 1) == '[') {
+ val = val.substr(1, val.length-2).split(',');
+ for(i=val.length; i--;) {
+ val[i] = normalizeValue(val[i].replace(/(^\s*)|(\s*$)/g,
''));
+ }
+ } else if (val.substr(0, 1) == '{') {
+ var pairs= val.substr(1, val.length-2).split(',');
+ val = {};
+ for(i=pairs.length; i--;) {
+ var keyval = pairs[i].split(':', 2);
+ val[keyval[0].replace(/(^\s*)|(\s*$)/g, '')] =
normalizeValue(keyval[1].replace(/(^\s*)|(\s*$)/g, ''));
+ }
+ } else {
+ val = normalizeValue(val);
+ }
+ this.tagValCache.key = val;
+ }
+ return val;
+ };
+
+ $.fn.sparkline.options.prototype.get = function(key) {
+ var tagOption = this.getTagSetting(key);
+ if (tagOption !== UNSET_OPTION) {
+ return tagOption;
+ }
+ return this.mergedOptions[key];
+ };
+
+
+ /**
+ * Line charts
+ */
+ $.fn.sparkline.line = function(values, options, width, height) {
+ var xvalues = [], yvalues = [], yminmax = [];
+ for (var i=0; i<values.length; i++) {
+ var val = values[i];
+ var isstr = typeof(values[i])=='string';
+ var isarray = typeof(values[i])=='object' && values[i]
instanceof Array;
+ var sp = isstr && values[i].split(':');
+ if (isstr && sp.length == 2) { // x:y
+ xvalues.push(Number(sp[0]));
+ yvalues.push(Number(sp[1]));
+ yminmax.push(Number(sp[1]));
+ } else if (isarray) {
+ xvalues.push(val[0]);
+ yvalues.push(val[1]);
+ yminmax.push(val[1]);
+ } else {
+ xvalues.push(i);
+ if (values[i]===null || values[i]=='null') {
+ yvalues.push(null);
+ } else {
+ yvalues.push(Number(val));
+ yminmax.push(Number(val));
+ }
+ }
+ }
+ if (options.get('xvalues')) {
+ xvalues = options.get('xvalues');
+ }
+
+ var maxy = Math.max.apply(Math, yminmax);
+ var maxyval = maxy;
+ var miny = Math.min.apply(Math, yminmax);
+ var minyval = miny;
+
+ var maxx = Math.max.apply(Math, xvalues);
+ var minx = Math.min.apply(Math, xvalues);
+
+ var normalRangeMin = options.get('normalRangeMin');
+ var normalRangeMax = options.get('normalRangeMax');
+
+ if (normalRangeMin!==undefined) {
+ if (normalRangeMin<miny) {
+ miny = normalRangeMin;
+ }
+ if (normalRangeMax>maxy) {
+ maxy = normalRangeMax;
+ }
+ }
+ if (options.get('chartRangeMin')!==undefined &&
(options.get('chartRangeClip') || options.get('chartRangeMin')<miny))
{
+ miny = options.get('chartRangeMin');
+ }
+ if (options.get('chartRangeMax')!==undefined &&
(options.get('chartRangeClip') || options.get('chartRangeMax')>maxy))
{
+ maxy = options.get('chartRangeMax');
+ }
+ if (options.get('chartRangeMinX')!==undefined &&
(options.get('chartRangeClipX') || options.get('chartRangeMinX')<minx))
{
+ minx = options.get('chartRangeMinX');
+ }
+ if (options.get('chartRangeMaxX')!==undefined &&
(options.get('chartRangeClipX') || options.get('chartRangeMaxX')>maxx))
{
+ maxx = options.get('chartRangeMaxX');
+ }
+ var rangex = maxx-minx === 0 ? 1 : maxx-minx;
+ var rangey = maxy-miny === 0 ? 1 : maxy-miny;
+ var vl = yvalues.length-1;
+
+ if (vl<1) {
+ this.innerHTML = '';
+ return;
+ }
+
+ var target = $(this).simpledraw(width, height,
options.get('composite'));
+ if (target) {
+ var canvas_width = target.pixel_width;
+ var canvas_height = target.pixel_height;
+ var canvas_top = 0;
+ var canvas_left = 0;
+
+ var spotRadius = options.get('spotRadius');
+ if (spotRadius && (canvas_width < (spotRadius*4) || canvas_height
< (spotRadius*4))) {
+ spotRadius = 0;
+ }
+ if (spotRadius) {
+ // adjust the canvas size as required so that spots will fit
+ if (options.get('minSpotColor') ||
(options.get('spotColor') && yvalues[vl]==miny)) {
+ canvas_height -= Math.ceil(spotRadius);
+ }
+ if (options.get('maxSpotColor') ||
(options.get('spotColor') && yvalues[vl]==maxy)) {
+ canvas_height -= Math.ceil(spotRadius);
+ canvas_top += Math.ceil(spotRadius);
+ }
+ if (options.get('minSpotColor') ||
options.get('maxSpotColor') && (yvalues[0]==miny || yvalues[0]==maxy)) {
+ canvas_left += Math.ceil(spotRadius);
+ canvas_width -= Math.ceil(spotRadius);
+ }
+ if (options.get('spotColor') ||
(options.get('minSpotColor') || options.get('maxSpotColor') &&
(yvalues[vl]==miny||yvalues[vl]==maxy))) {
+ canvas_width -= Math.ceil(spotRadius);
+ }
+ }
+
+
+ canvas_height--;
+
+ var drawNormalRange = function() {
+ if (normalRangeMin!==undefined) {
+ var ytop =
canvas_top+Math.round(canvas_height-(canvas_height*((normalRangeMax-miny)/rangey)));
+ var height =
Math.round((canvas_height*(normalRangeMax-normalRangeMin))/rangey);
+ target.drawRect(canvas_left, ytop, canvas_width, height, undefined,
options.get('normalRangeColor'));
+ }
+ };
+
+ if (!options.get('drawNormalOnTop')) {
+ drawNormalRange();
+ }
+
+ var path = [];
+ var paths = [path];
+ var x, y, vlen=yvalues.length;
+ for(i=0; i<vlen; i++) {
+ x=xvalues[i];
+ y=yvalues[i];
+ if (y===null) {
+ if (i) {
+ if (yvalues[i-1]!==null) {
+ path = [];
+ paths.push(path);
+ }
+ }
+ } else {
+ if (y < miny) {
+ y=miny;
+ }
+ if (y > maxy) {
+ y=maxy;
+ }
+ if (!path.length) {
+ // previous value was null
+
path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)),
canvas_top+canvas_height]);
+ }
+ path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)),
canvas_top+Math.round(canvas_height-(canvas_height*((y-miny)/rangey)))]);
+ }
+ }
+ var lineshapes = [];
+ var fillshapes = [];
+ var plen=paths.length;
+ for(i=0; i<plen; i++) {
+ path = paths[i];
+ if (!path.length) {
+ continue; // last value was null
+ }
+ if (options.get('fillColor')) {
+ path.push([path[path.length-1][0], canvas_top+canvas_height-1]);
+ fillshapes.push(path.slice(0));
+ path.pop();
+ }
+ // if there's only a single point in this path, then we want to
display it as a vertical line
+ // which means we keep path[0] as is
+ if (path.length>2) {
+ // else we want the first value
+ path[0] = [ path[0][0], path[1][1] ];
+ }
+ lineshapes.push(path);
+ }
+
+ // draw the fill first, then optionally the normal range, then the line on
top of that
+ plen = fillshapes.length;
+ for(i=0; i<plen; i++) {
+ target.drawShape(fillshapes[i], undefined,
options.get('fillColor'));
+ }
+
+ if (options.get('drawNormalOnTop')) {
+ drawNormalRange();
+ }
+
+ plen = lineshapes.length;
+ for(i=0; i<plen; i++) {
+ target.drawShape(lineshapes[i], options.get('lineColor'),
undefined, options.get('lineWidth'));
+ }
+
+ if (spotRadius && options.get('spotColor')) {
+
target.drawCircle(canvas_left+Math.round(xvalues[xvalues.length-1]*(canvas_width/rangex)),
canvas_top+Math.round(canvas_height-(canvas_height*((yvalues[vl]-miny)/rangey))),
spotRadius, undefined, options.get('spotColor'));
+ }
+ if (maxy!=minyval) {
+ if (spotRadius && options.get('minSpotColor')) {
+ x = xvalues[$.inArray(minyval, yvalues)];
+
target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)),
canvas_top+Math.round(canvas_height-(canvas_height*((minyval-miny)/rangey))), spotRadius,
undefined, options.get('minSpotColor'));
+ }
+ if (spotRadius && options.get('maxSpotColor')) {
+ x = xvalues[$.inArray(maxyval, yvalues)];
+
target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)),
canvas_top+Math.round(canvas_height-(canvas_height*((maxyval-miny)/rangey))), spotRadius,
undefined, options.get('maxSpotColor'));
+ }
+ }
+
+ } else {
+ // Remove the tag contents if sparklines aren't supported
+ this.innerHTML = '';
+ }
+ };
+
+
+ /**
+ * Bar charts
+ */
+ $.fn.sparkline.bar = function(values, options, width, height) {
+ width = (values.length * options.get('barWidth')) + ((values.length-1) *
options.get('barSpacing'));
+ var num_values = [];
+ for(var i=0, vlen=values.length; i<vlen; i++) {
+ if (values[i]=='null' || values[i]===null) {
+ values[i] = null;
+ } else {
+ values[i] = Number(values[i]);
+ num_values.push(Number(values[i]));
+ }
+ }
+ var max = Math.max.apply(Math, num_values),
+ min = Math.min.apply(Math, num_values);
+ if (options.get('chartRangeMin')!==undefined &&
(options.get('chartRangeClip') || options.get('chartRangeMin')<min)) {
+ min = options.get('chartRangeMin');
+ }
+ if (options.get('chartRangeMax')!==undefined &&
(options.get('chartRangeClip') || options.get('chartRangeMax')>max)) {
+ max = options.get('chartRangeMax');
+ }
+ var zeroAxis = options.get('zeroAxis');
+ if (zeroAxis === undefined) {
+ zeroAxis = min<0;
+ }
+ var range = max-min === 0 ? 1 : max-min;
+
+ var colorMapByIndex, colorMapByValue;
+ if ($.isArray(options.get('colorMap'))) {
+ colorMapByIndex = options.get('colorMap');
+ colorMapByValue = null;
+ } else {
+ colorMapByIndex = null;
+ colorMapByValue = options.get('colorMap');
+ }
+
+ var target = $(this).simpledraw(width, height,
options.get('composite'));
+ if (target) {
+ var color,
+ canvas_height = target.pixel_height,
+ yzero = min<0 && zeroAxis ?
canvas_height-Math.round(canvas_height * (Math.abs(min)/range))-1 : canvas_height-1;
+
+ for(i=values.length; i--;) {
+ var x =
i*(options.get('barWidth')+options.get('barSpacing')),
+ y,
+ val = values[i];
+ if (val===null) {
+ if (options.get('nullColor')) {
+ color = options.get('nullColor');
+ val = (zeroAxis && min<0) ? 0 : min;
+ height = 1;
+ y = (zeroAxis && min<0) ? yzero : canvas_height -
height;
+ } else {
+ continue;
+ }
+ } else {
+ if (val < min) {
+ val=min;
+ }
+ if (val > max) {
+ val=max;
+ }
+ color = (val < 0) ? options.get('negBarColor') :
options.get('barColor');
+ if (zeroAxis && min<0) {
+ height = Math.round(canvas_height*((Math.abs(val)/range)))+1;
+ y = (val < 0) ? yzero : yzero-height;
+ } else {
+ height = Math.round(canvas_height*((val-min)/range))+1;
+ y = canvas_height-height;
+ }
+ if (val===0 && options.get('zeroColor')!==undefined)
{
+ color = options.get('zeroColor');
+ }
+ if (colorMapByValue && colorMapByValue[val]) {
+ color = colorMapByValue[val];
+ } else if (colorMapByIndex && colorMapByIndex.length>i) {
+ color = colorMapByIndex[i];
+ }
+ if (color===null) {
+ continue;
+ }
+ }
+ target.drawRect(x, y, options.get('barWidth')-1, height-1, color,
color);
+ }
+ } else {
+ // Remove the tag contents if sparklines aren't supported
+ this.innerHTML = '';
+ }
+ };
+
+
+ /**
+ * Tristate charts
+ */
+ $.fn.sparkline.tristate = function(values, options, width, height) {
+ values = $.map(values, Number);
+ width = (values.length * options.get('barWidth')) + ((values.length-1) *
options.get('barSpacing'));
+
+ var colorMapByIndex, colorMapByValue;
+ if ($.isArray(options.get('colorMap'))) {
+ colorMapByIndex = options.get('colorMap');
+ colorMapByValue = null;
+ } else {
+ colorMapByIndex = null;
+ colorMapByValue = options.get('colorMap');
+ }
+
+ var target = $(this).simpledraw(width, height,
options.get('composite'));
+ if (target) {
+ var canvas_height = target.pixel_height,
+ half_height = Math.round(canvas_height/2);
+
+ for(var i=values.length; i--;) {
+ var x =
i*(options.get('barWidth')+options.get('barSpacing')),
+ y, color;
+ if (values[i] < 0) {
+ y = half_height;
+ height = half_height-1;
+ color = options.get('negBarColor');
+ } else if (values[i] > 0) {
+ y = 0;
+ height = half_height-1;
+ color = options.get('posBarColor');
+ } else {
+ y = half_height-1;
+ height = 2;
+ color = options.get('zeroBarColor');
+ }
+ if (colorMapByValue && colorMapByValue[values[i]]) {
+ color = colorMapByValue[values[i]];
+ } else if (colorMapByIndex && colorMapByIndex.length>i) {
+ color = colorMapByIndex[i];
+ }
+ if (color===null) {
+ continue;
+ }
+ target.drawRect(x, y, options.get('barWidth')-1, height-1, color,
color);
+ }
+ } else {
+ // Remove the tag contents if sparklines aren't supported
+ this.innerHTML = '';
+ }
+ };
+
+
+ /**
+ * Discrete charts
+ */
+ $.fn.sparkline.discrete = function(values, options, width, height) {
+ values = $.map(values, Number);
+ width = options.get('width')=='auto' ? values.length*2 : width;
+ var interval = Math.floor(width / values.length);
+
+ var target = $(this).simpledraw(width, height,
options.get('composite'));
+ if (target) {
+ var canvas_height = target.pixel_height,
+ line_height = options.get('lineHeight') == 'auto' ?
Math.round(canvas_height * 0.3) : options.get('lineHeight'),
+ pheight = canvas_height - line_height,
+ min = Math.min.apply(Math, values),
+ max = Math.max.apply(Math, values);
+ if (options.get('chartRangeMin')!==undefined &&
(options.get('chartRangeClip') || options.get('chartRangeMin')<min)) {
+ min = options.get('chartRangeMin');
+ }
+ if (options.get('chartRangeMax')!==undefined &&
(options.get('chartRangeClip') || options.get('chartRangeMax')>max))
{
+ max = options.get('chartRangeMax');
+ }
+ var range = max-min;
+
+ for(var i=values.length; i--;) {
+ var val = values[i];
+ if (val < min) {
+ val=min;
+ }
+ if (val > max) {
+ val=max;
+ }
+ var x = (i*interval),
+ ytop = Math.round(pheight-pheight*((val-min)/range));
+ target.drawLine(x, ytop, x, ytop+line_height,
(options.get('thresholdColor') && val <
options.get('thresholdValue')) ? options.get('thresholdColor') :
options.get('lineColor'));
+ }
+ } else {
+ // Remove the tag contents if sparklines aren't supported
+ this.innerHTML = '';
+ }
+
+ };
+
+
+ /**
+ * Bullet charts
+ */
+ $.fn.sparkline.bullet = function(values, options, width, height) {
+ values = $.map(values, Number);
+ // target, performance, range1, range2, range3
+
+ width = options.get('width')=='auto' ? '4.0em' : width;
+
+ var target = $(this).simpledraw(width, height,
options.get('composite'));
+ if (target && values.length>1) {
+ var canvas_width =
target.pixel_width-Math.ceil(options.get('targetWidth')/2),
+ canvas_height = target.pixel_height,
+ min = Math.min.apply(Math, values),
+ max = Math.max.apply(Math, values);
+
+ if (options.get('base') === undefined) {
+ min = min < 0 ? min : 0;
+ } else {
+ min = options.get('base');
+ }
+ var range = max-min;
+
+ // draw range values
+ for(var i=2, vlen=values.length; i<vlen; i++) {
+ var rangeval = values[i],
+ rangewidth = Math.round(canvas_width*((rangeval-min)/range));
+ target.drawRect(0, 0, rangewidth-1, canvas_height-1,
options.get('rangeColors')[i-2], options.get('rangeColors')[i-2]);
+ }
+
+ // draw the performance bar
+ var perfval = values[1],
+ perfwidth = Math.round(canvas_width*((perfval-min)/range));
+ target.drawRect(0, Math.round(canvas_height*0.3), perfwidth-1,
Math.round(canvas_height*0.4)-1, options.get('performanceColor'),
options.get('performanceColor'));
+
+ // draw the target line
+ var targetval = values[0],
+ x =
Math.round(canvas_width*((targetval-min)/range)-(options.get('targetWidth')/2)),
+ targettop = Math.round(canvas_height*0.10),
+ targetheight = canvas_height-(targettop*2);
+ target.drawRect(x, targettop, options.get('targetWidth')-1,
targetheight-1, options.get('targetColor'), options.get('targetColor'));
+ } else {
+ // Remove the tag contents if sparklines aren't supported
+ this.innerHTML = '';
+ }
+ };
+
+
+ /**
+ * Pie charts
+ */
+ $.fn.sparkline.pie = function(values, options, width, height) {
+ values = $.map(values, Number);
+ width = options.get('width')=='auto' ? height : width;
+
+ var target = $(this).simpledraw(width, height,
options.get('composite'));
+ if (target && values.length>1) {
+ var canvas_width = target.pixel_width,
+ canvas_height = target.pixel_height,
+ radius = Math.floor(Math.min(canvas_width, canvas_height)/2),
+ total = 0,
+ next = 0,
+ circle = 2*Math.PI;
+
+ for(var i=values.length; i--;) {
+ total += values[i];
+ }
+
+ if (options.get('offset')) {
+ next += (2*Math.PI)*(options.get('offset')/360);
+ }
+ var vlen = values.length;
+ for(i=0; i<vlen; i++) {
+ var start = next;
+ var end = next;
+ if (total > 0) { // avoid divide by zero
+ end = next + (circle*(values[i]/total));
+ }
+ target.drawPieSlice(radius, radius, radius, start, end, undefined,
options.get('sliceColors')[i % options.get('sliceColors').length]);
+ next = end;
+ }
+ }
+ };
+
+
+ /**
+ * Box plots
+ */
+ var quartile = function(values, q) {
+ if (q==2) {
+ var vl2 = Math.floor(values.length/2);
+ return values.length % 2 ? values[vl2] : (values[vl2]+values[vl2+1])/2;
+ } else {
+ var vl4 = Math.floor(values.length/4);
+ return values.length % 2 ? (values[vl4*q]+values[vl4*q+1])/2 :
values[vl4*q];
+ }
+ };
+
+ $.fn.sparkline.box = function(values, options, width, height) {
+ values = $.map(values, Number);
+ width = options.get('width')=='auto' ? '4.0em' : width;
+
+ var minvalue = options.get('chartRangeMin')===undefined ?
Math.min.apply(Math, values) : options.get('chartRangeMin'),
+ maxvalue = options.get('chartRangeMax')===undefined ?
Math.max.apply(Math, values) : options.get('chartRangeMax'),
+ target = $(this).simpledraw(width, height,
options.get('composite')),
+ vlen = values.length,
+ lwhisker, loutlier, q1, q2, q3, rwhisker, routlier;
+
+ if (target && values.length>1) {
+ var canvas_width = target.pixel_width,
+ canvas_height = target.pixel_height;
+ if (options.get('raw')) {
+ if (options.get('showOutliers') && values.length>5) {
+ loutlier=values[0]; lwhisker=values[1]; q1=values[2]; q2=values[3];
q3=values[4]; rwhisker=values[5]; routlier=values[6];
+ } else {
+ lwhisker=values[0]; q1=values[1]; q2=values[2]; q3=values[3];
rwhisker=values[4];
+ }
+ } else {
+ values.sort(function(a, b) { return a-b; });
+ q1 = quartile(values, 1);
+ q2 = quartile(values, 2);
+ q3 = quartile(values, 3);
+ var iqr = q3-q1;
+ if (options.get('showOutliers')) {
+ lwhisker=undefined; rwhisker=undefined;
+ for(var i=0; i<vlen; i++) {
+ if (lwhisker===undefined && values[i] >
q1-(iqr*options.get('outlierIQR'))) {
+ lwhisker = values[i];
+ }
+ if (values[i] < q3+(iqr*options.get('outlierIQR'))) {
+ rwhisker = values[i];
+ }
+ }
+ loutlier = values[0];
+ routlier = values[vlen-1];
+ } else {
+ lwhisker = values[0];
+ rwhisker = values[vlen-1];
+ }
+ }
+
+ var unitsize = canvas_width / (maxvalue-minvalue+1),
+ canvas_left = 0;
+ if (options.get('showOutliers')) {
+ canvas_left = Math.ceil(options.get('spotRadius'));
+ canvas_width -= 2*Math.ceil(options.get('spotRadius'));
+ unitsize = canvas_width / (maxvalue-minvalue+1);
+ if (loutlier < lwhisker) {
+ target.drawCircle((loutlier-minvalue)*unitsize+canvas_left,
canvas_height/2, options.get('spotRadius'),
options.get('outlierLineColor'), options.get('outlierFillColor'));
+ }
+ if (routlier > rwhisker) {
+ target.drawCircle((routlier-minvalue)*unitsize+canvas_left,
canvas_height/2, options.get('spotRadius'),
options.get('outlierLineColor'), options.get('outlierFillColor'));
+ }
+ }
+
+ // box
+ target.drawRect(
+ Math.round((q1-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height*0.1),
+ Math.round((q3-q1)*unitsize),
+ Math.round(canvas_height*0.8),
+ options.get('boxLineColor'),
+ options.get('boxFillColor'));
+ // left whisker
+ target.drawLine(
+ Math.round((lwhisker-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height/2),
+ Math.round((q1-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height/2),
+ options.get('lineColor'));
+ target.drawLine(
+ Math.round((lwhisker-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height/4),
+ Math.round((lwhisker-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height-canvas_height/4),
+ options.get('whiskerColor'));
+ // right whisker
+ target.drawLine(Math.round((rwhisker-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height/2),
+ Math.round((q3-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height/2),
+ options.get('lineColor'));
+ target.drawLine(
+ Math.round((rwhisker-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height/4),
+ Math.round((rwhisker-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height-canvas_height/4),
+ options.get('whiskerColor'));
+ // median line
+ target.drawLine(
+ Math.round((q2-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height*0.1),
+ Math.round((q2-minvalue)*unitsize+canvas_left),
+ Math.round(canvas_height*0.9),
+ options.get('medianColor'));
+ if (options.get('target')) {
+ var size = Math.ceil(options.get('spotRadius'));
+ target.drawLine(
+
Math.round((options.get('target')-minvalue)*unitsize+canvas_left),
+ Math.round((canvas_height/2)-size),
+
Math.round((options.get('target')-minvalue)*unitsize+canvas_left),
+ Math.round((canvas_height/2)+size),
+ options.get('targetColor'));
+ target.drawLine(
+
Math.round((options.get('target')-minvalue)*unitsize+canvas_left-size),
+ Math.round(canvas_height/2),
+
Math.round((options.get('target')-minvalue)*unitsize+canvas_left+size),
+ Math.round(canvas_height/2),
+ options.get('targetColor'));
+ }
+ } else {
+ // Remove the tag contents if sparklines aren't supported
+ this.innerHTML = '';
+ }
+ };
+
+
+ // Setup a very simple "virtual canvas" to make drawing the few shapes we
need easier
+ // This is accessible as $(foo).simpledraw()
+
+ if ($.browser.msie && !document.namespaces.v) {
+ document.namespaces.add('v', 'urn:schemas-microsoft-com:vml',
'#default#VML');
+ }
+
+ if ($.browser.hasCanvas === undefined) {
+ var t = document.createElement('canvas');
+ $.browser.hasCanvas = t.getContext!==undefined;
+ }
+
+ VCanvas_base = function(width, height, target) {
+ };
+
+ VCanvas_base.prototype = {
+ init : function(width, height, target) {
+ this.width = width;
+ this.height = height;
+ this.target = target;
+ if (target[0]) {
+ target=target[0];
+ }
+ target.VCanvas = this;
+ },
+
+ drawShape : function(path, lineColor, fillColor, lineWidth) {
+ alert('drawShape not implemented');
+ },
+
+ drawLine : function(x1, y1, x2, y2, lineColor, lineWidth) {
+ return this.drawShape([ [x1,y1], [x2,y2] ], lineColor, lineWidth);
+ },
+
+ drawCircle : function(x, y, radius, lineColor, fillColor) {
+ alert('drawCircle not implemented');
+ },
+
+ drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor)
{
+ alert('drawPieSlice not implemented');
+ },
+
+ drawRect : function(x, y, width, height, lineColor, fillColor) {
+ alert('drawRect not implemented');
+ },
+
+ getElement : function() {
+ return this.canvas;
+ },
+
+ _insert : function(el, target) {
+ $(target).html(el);
+ }
+ };
+
+ VCanvas_canvas = function(width, height, target) {
+ return this.init(width, height, target);
+ };
+
+ VCanvas_canvas.prototype = $.extend(new VCanvas_base(), {
+ _super : VCanvas_base.prototype,
+
+ init : function(width, height, target) {
+ this._super.init(width, height, target);
+ this.canvas = document.createElement('canvas');
+ if (target[0]) {
+ target=target[0];
+ }
+ target.VCanvas = this;
+ $(this.canvas).css({ display:'inline-block', width:width,
height:height, verticalAlign:'top' });
+ this._insert(this.canvas, target);
+ this.pixel_height = $(this.canvas).height();
+ this.pixel_width = $(this.canvas).width();
+ this.canvas.width = this.pixel_width;
+ this.canvas.height = this.pixel_height;
+ $(this.canvas).css({width: this.pixel_width, height: this.pixel_height});
+ },
+
+ _getContext : function(lineColor, fillColor, lineWidth) {
+ var context = this.canvas.getContext('2d');
+ if (lineColor !== undefined) {
+ context.strokeStyle = lineColor;
+ }
+ context.lineWidth = lineWidth===undefined ? 1 : lineWidth;
+ if (fillColor !== undefined) {
+ context.fillStyle = fillColor;
+ }
+ return context;
+ },
+
+ drawShape : function(path, lineColor, fillColor, lineWidth) {
+ var context = this._getContext(lineColor, fillColor, lineWidth);
+ context.beginPath();
+ context.moveTo(path[0][0]+0.5, path[0][1]+0.5);
+ for(var i=1, plen=path.length; i<plen; i++) {
+ context.lineTo(path[i][0]+0.5, path[i][1]+0.5); // the 0.5 offset gives
us crisp pixel-width lines
+ }
+ if (lineColor !== undefined) {
+ context.stroke();
+ }
+ if (fillColor !== undefined) {
+ context.fill();
+ }
+ },
+
+ drawCircle : function(x, y, radius, lineColor, fillColor) {
+ var context = this._getContext(lineColor, fillColor);
+ context.beginPath();
+ context.arc(x, y, radius, 0, 2*Math.PI, false);
+ if (lineColor !== undefined) {
+ context.stroke();
+ }
+ if (fillColor !== undefined) {
+ context.fill();
+ }
+ },
+
+ drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor)
{
+ var context = this._getContext(lineColor, fillColor);
+ context.beginPath();
+ context.moveTo(x, y);
+ context.arc(x, y, radius, startAngle, endAngle, false);
+ context.lineTo(x, y);
+ context.closePath();
+ if (lineColor !== undefined) {
+ context.stroke();
+ }
+ if (fillColor) {
+ context.fill();
+ }
+ },
+
+ drawRect : function(x, y, width, height, lineColor, fillColor) {
+ return this.drawShape([ [x,y], [x+width, y], [x+width, y+height], [x,
y+height], [x, y] ], lineColor, fillColor);
+ }
+
+ });
+
+ VCanvas_vml = function(width, height, target) {
+ return this.init(width, height, target);
+ };
+
+ VCanvas_vml.prototype = $.extend(new VCanvas_base(), {
+ _super : VCanvas_base.prototype,
+
+ init : function(width, height, target) {
+ this._super.init(width, height, target);
+ if (target[0]) {
+ target=target[0];
+ }
+ target.VCanvas = this;
+ this.canvas = document.createElement('span');
+ $(this.canvas).css({ display:'inline-block', position:
'relative', overflow:'hidden', width:width, height:height,
margin:'0px', padding:'0px', verticalAlign: 'top'});
+ this._insert(this.canvas, target);
+ this.pixel_height = $(this.canvas).height();
+ this.pixel_width = $(this.canvas).width();
+ this.canvas.width = this.pixel_width;
+ this.canvas.height = this.pixel_height;
+ var groupel = '<v:group coordorigin="0 0"
coordsize="'+this.pixel_width+' '+this.pixel_height+'"' +
+ '
style="position:absolute;top:0;left:0;width:'+this.pixel_width+'px;height='+this.pixel_height+'px;"></v:group>';
+ this.canvas.insertAdjacentHTML('beforeEnd', groupel);
+ this.group = $(this.canvas).children()[0];
+ },
+
+ drawShape : function(path, lineColor, fillColor, lineWidth) {
+ var vpath = [];
+ for(var i=0, plen=path.length; i<plen; i++) {
+ vpath[i] = ''+(path[i][0])+','+(path[i][1]);
+ }
+ var initial = vpath.splice(0,1);
+ lineWidth = lineWidth === undefined ? 1 : lineWidth;
+ var stroke = lineColor === undefined ? ' stroked="false" '
: ' strokeWeight="'+lineWidth+'"
strokeColor="'+lineColor+'" ';
+ var fill = fillColor === undefined ? ' filled="false"' :
' fillColor="'+fillColor+'" filled="true" ';
+ var closed = vpath[0] == vpath[vpath.length-1] ? 'x ' : '';
+ var vel = '<v:shape coordorigin="0 0"
coordsize="'+this.pixel_width+' '+this.pixel_height+'" ' +
+ stroke +
+ fill +
+ '
style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;"
' +
+ ' path="m '+initial+' l '+vpath.join(',
')+' '+closed+'e">' +
+ ' </v:shape>';
+ this.group.insertAdjacentHTML('beforeEnd', vel);
+ },
+
+ drawCircle : function(x, y, radius, lineColor, fillColor) {
+ x -= radius+1;
+ y -= radius+1;
+ var stroke = lineColor === undefined ? ' stroked="false" '
: ' strokeWeight="1" strokeColor="'+lineColor+'" ';
+ var fill = fillColor === undefined ? ' filled="false"' :
' fillColor="'+fillColor+'" filled="true" ';
+ var vel = '<v:oval ' +
+ stroke +
+ fill +
+ ' style="position:absolute;top:'+y+'px;
left:'+x+'px; width:'+(radius*2)+'px;
height:'+(radius*2)+'px"></v:oval>';
+ this.group.insertAdjacentHTML('beforeEnd', vel);
+
+ },
+
+ drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor)
{
+ if (startAngle == endAngle) {
+ return; // VML seems to have problem when start angle equals end angle.
+ }
+ if ((endAngle - startAngle) == (2*Math.PI)) {
+ startAngle = 0.0; // VML seems to have a problem when drawing a full
circle that doesn't start 0
+ endAngle = (2*Math.PI);
+ }
+
+ var startx = x + Math.round(Math.cos(startAngle) * radius);
+ var starty = y + Math.round(Math.sin(startAngle) * radius);
+ var endx = x + Math.round(Math.cos(endAngle) * radius);
+ var endy = y + Math.round(Math.sin(endAngle) * radius);
+
+ // Prevent very small slices from being mistaken as a whole pie
+ if (startx==endx && starty==endy && (endAngle-startAngle)
< Math.PI) {
+ return;
+ }
+
+ var vpath = [ x-radius, y-radius, x+radius, y+radius, startx, starty, endx,
endy ];
+ var stroke = lineColor === undefined ? ' stroked="false" '
: ' strokeWeight="1" strokeColor="'+lineColor+'" ';
+ var fill = fillColor === undefined ? ' filled="false"' :
' fillColor="'+fillColor+'" filled="true" ';
+ var vel = '<v:shape coordorigin="0 0"
coordsize="'+this.pixel_width+' '+this.pixel_height+'" ' +
+ stroke +
+ fill +
+ '
style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;"
' +
+ ' path="m '+x+','+y+' wa '+vpath.join(',
')+' x e">' +
+ ' </v:shape>';
+ this.group.insertAdjacentHTML('beforeEnd', vel);
+ },
+
+ drawRect : function(x, y, width, height, lineColor, fillColor) {
+ return this.drawShape( [ [x, y], [x, y+height], [x+width, y+height],
[x+width, y], [x, y] ], lineColor, fillColor);
+ }
+ });
+
+})(jQuery);
commit fb82ca3fb17e987acc3e773aa66a954517a55a75
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Sat Jan 8 16:58:03 2011 -0500
i)fixed links in Recent Metrics display
ii)updated recent metric display to convert last metric for better display. Still
more to go.
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
index 7d86fe8..5e6c4b5 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
@@ -43,6 +43,7 @@ import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.criteria.EventCriteria;
import org.rhq.core.domain.criteria.InstalledPackageCriteria;
import org.rhq.core.domain.criteria.ResourceConfigurationUpdateCriteria;
+import org.rhq.core.domain.measurement.DisplayType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
@@ -95,6 +96,15 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
private String RECENT_PKG_HISTORY_NONE =
MSG.view_resource_inventory_activity_no_recent_pkg_history();
private Timer sparklineReloader = null;
+ private long KBYTES = 1024;
+ private long MBYTES = KBYTES * KBYTES;
+ private long GBYTES = MBYTES * KBYTES;
+ private long TBYTES = GBYTES * KBYTES;
+ private long PBYTES = TBYTES * KBYTES;
+ private long[] byteCount = { PBYTES, TBYTES, GBYTES, MBYTES, KBYTES };
+ private String[] byteDesc = { "PB", "TB", "GB",
"MB", "KB" };
+ private NumberFormat decimalThreeAndOne = NumberFormat.getFormat("###.#");
+ private NumberFormat decimalThreeAndTwo =
NumberFormat.getFormat("###.##");
private ResourceComposite resourceComposite;
@@ -214,7 +224,6 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
// int resourceId = this.resourceComposite.getResource().getId();
//
this.iFrame.setContentsURL("/rhq/resource/summary/overview-plain.xhtml?id=" +
resourceId);
// Log.debug("$$$$$$$$$$$$$ ActivityView2.refresh()");
- loadData();
markForRedraw();
}
@@ -648,108 +657,112 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
}
private void getRecentMetrics() {
+ //display container
final LocatableVLayout column = new
LocatableVLayout(recentMeasurementsContent.extendLocatorId("Content"));
- column.setHeight(10);
final int resourceId = this.resourceComposite.getResource().getId();
+
+ //retrieve all relevant measurement definition ids.
Set<MeasurementDefinition> definitions =
this.resourceComposite.getResource().getResourceType()
.getMetricDefinitions();
- final HashMap<String, MeasurementDefinition> map = new HashMap<String,
MeasurementDefinition>();
- for (MeasurementDefinition md : definitions) {
- map.put(md.getDisplayName(), md);
+ //build id mapping for measurementDefinition instances Ex. Free Memory ->
MeasurementDefinition[100071]
+ final HashMap<String, MeasurementDefinition> measurementDefMap = new
HashMap<String, MeasurementDefinition>();
+ for (MeasurementDefinition definition : definitions) {
+ measurementDefMap.put(definition.getDisplayName(), definition);
}
+
+ //bundle definition ids for asynch call.
int[] definitionArrayIds = new int[definitions.size()];
final String[] displayOrder = new String[definitions.size()];
- map.keySet().toArray(displayOrder);
+ measurementDefMap.keySet().toArray(displayOrder);
+ //sort the charting data ex. Free Memory, Free Swap Space,..System Load
Arrays.sort(displayOrder);
- int l = 0;
+
+ //organize definitionArrayIds for ordered request on server.
+ int index = 0;
for (String definitionToDisplay : displayOrder) {
- definitionArrayIds[l++] = map.get(definitionToDisplay).getId();
+ definitionArrayIds[index++] =
measurementDefMap.get(definitionToDisplay).getId();
}
+
+ //make the asynchronous call for all the measurement data
GWTServiceLookup.getMeasurementDataService().findDataForResource(resourceId,
definitionArrayIds,
System.currentTimeMillis() - (1000L * 60 * 60 * 8),
System.currentTimeMillis(), 60,
new
AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
@Override
public void onFailure(Throwable caught) {
- Log.debug("Error retrieving metrics charting data for resource
[" + resourceId + "]:"
+ Log.debug("Error retrieving recent metrics charting data for
resource [" + resourceId + "]:"
+ caught.getMessage());
}
@Override
public void
onSuccess(List<List<MeasurementDataNumericHighLowComposite>> results) {
- for (int h = 0; h < displayOrder.length; h++) {
- MeasurementDefinition md = map.get(displayOrder[h]);
- List<MeasurementDataNumericHighLowComposite> data =
results.get(h);
+ //iterate over the retrieved charting data
+ for (int index = 0; index < displayOrder.length; index++) {
+
+ //retrieve the correct measurement definition
+ MeasurementDefinition md =
measurementDefMap.get(displayOrder[index]);
+
+ //load the data results for the given metric definition
+ List<MeasurementDataNumericHighLowComposite> data =
results.get(index);
+
//locate last and minimum values.
- double lastValue = 0;
- double minValue = Double.MAX_VALUE;
+ double lastValue = -1;
+ double minValue = Double.MAX_VALUE;//
for (MeasurementDataNumericHighLowComposite d : data) {
- if ((d.getValue() + "").indexOf("NaN") ==
-1) {
+ if (!Double.isNaN(d.getValue())) {
if (d.getValue() < minValue) {
minValue = d.getValue();
}
+ lastValue = d.getValue();
}
}
- //collapse the data into comma delimited list
+ //collapse the data into comma delimited list for consumption by
third party javascript library(jquery.sparkline)
String commaDelimitedList = "";
for (MeasurementDataNumericHighLowComposite d : data) {
- if ((d.getValue() + "").indexOf("NaN") ==
-1) {
- commaDelimitedList += (d.getValue() - minValue) +
",";
- lastValue = d.getValue();
- if (d.getValue() < minValue) {
- minValue = d.getValue();
- }
+ if (!Double.isNaN(d.getValue())) {
+ commaDelimitedList += d.getValue() + ",";
}
}
LocatableDynamicForm row = new
LocatableDynamicForm(column.extendLocatorId("ContentForm"));
row.setNumCols(3);
- // row.setWidth(300);
HTMLFlow graph = new HTMLFlow();
- //move all sparkline data up to the minimum value
- String contents = "<span id='sparkline_" + 1 +
"' class='dynamicsparkline' width='0'>"
- + commaDelimitedList + "</span>";
+ // String contents = "<span
id='sparkline_" + index + "' class='dynamicsparkline'
width='0'>"
+ // + commaDelimitedList +
"</span>";
+ String contents = "<span id='sparkline_" + index
+ "' class='dynamicsparkline' width='0' "
+ + "values='" + commaDelimitedList +
"'>...</span>";
graph.setContents(contents);
graph.setContentsType(ContentsType.PAGE);
+ //diable scrollbars on span
graph.setScrollbarSize(0);
- CanvasItem ci2 = new CanvasItem();
- ci2.setShowTitle(false);
- ci2.setHeight(16);
- ci2.setWidth(60);
- ci2.setCanvas(graph);
+
+ CanvasItem graphContainer = new CanvasItem();
+ graphContainer.setShowTitle(false);
+ graphContainer.setHeight(16);
+ graphContainer.setWidth(60);
+ graphContainer.setCanvas(graph);
//Link/title element
LinkItem link = new LinkItem();
- link.setLinkTitle(md.getDisplayName());
- link.setTitle(md.getName());
+ link.setLinkTitle(md.getDisplayName() + ":");
+ //TODO: spinder, change link whenever portal.war/graphing is
removed.
+
link.setValue("/resource/common/monitor/Visibility.do?mode=chartSingleMetricSingleResource&id="
+ + resourceId + "&m=" + md.getId());
link.setTarget("_self");
link.setShowTitle(false);
+
//Value
StaticTextItem value = new StaticTextItem();
String convertedValue = lastValue + " " +
md.getUnits();
- long KBYTES = 1024;
- long MBYTES = KBYTES * KBYTES;
- long GBYTES = MBYTES * KBYTES;
- NumberFormat fmt = NumberFormat.getDecimalFormat();
- fmt = NumberFormat.getFormat("###.####");
- if (md.getUnits() == MeasurementUnits.BYTES) {
- if ((lastValue / GBYTES) > 1) {
- convertedValue = fmt.format(lastValue / GBYTES) +
"GB";
- } else if ((lastValue / MBYTES) > 1) {
- convertedValue = fmt.format(lastValue / MBYTES) +
"MB";
- } else {
- convertedValue = fmt.format(lastValue / KBYTES) +
"KB";
- }
- } else {
- convertedValue = fmt.format(lastValue / 100) +
md.getUnits();
- }
+ convertedValue = convertLastValueForDisplay(lastValue, md);
+
value.setDefaultValue(convertedValue);
value.setShowTitle(false);
value.setShowPickerIcon(false);
value.setWrap(false);
-
- row.setItems(ci2, link, value);
+ row.setItems(graphContainer, link, value);
+ //if graph content returned
if (commaDelimitedList.trim().length() > 100) {
column.addMember(row);
}
@@ -759,6 +772,7 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
}
});
+ //cleanup
for (Canvas child : recentMeasurementsContent.getChildren()) {
child.destroy();
}
@@ -776,6 +790,47 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
}
}
+ /** Takes last double value returned and the relevant MeasurementDefinition and
formats
+ * the results for display in the UI. 'Formatting' refers to relevant
rounding,
+ * number format for significant digits depending upon the measurement definition
+ * details.
+ *
+ * @param lastValue
+ * @param md MeasurementDefinition
+ * @return formatted String representation of the last value retrieved.
+ */
+ protected String convertLastValueForDisplay(double lastValue, MeasurementDefinition
md) {
+
+ String convertedValue = "";
+ if (md.getUnits() == MeasurementUnits.BYTES) {
+ double value;
+ boolean converted = false;
+ for (int i = 0; (!converted && (i < byteCount.length)); i++) {
+ //detect first byte translation 1 > N < 1000
+ value = lastValue / byteCount[i];
+ if (value > 1) {
+ converted = true;
+ convertedValue = md.getDisplayType() == DisplayType.SUMMARY ?
(decimalThreeAndOne.format(value) + byteDesc[i])
+ : (decimalThreeAndTwo.format(value)) + byteDesc[i];
+ }
+ }
+ } else if (md.getUnits() == MeasurementUnits.PERCENTAGE) {
+ double value = lastValue * 100;
+ convertedValue = (md.getDisplayType() == DisplayType.SUMMARY ?
(decimalThreeAndOne.format(value))
+ : (decimalThreeAndTwo.format(value)))
+ + "%";
+ } else if (md.getUnits() == MeasurementUnits.NONE) {
+ double value = lastValue;
+ convertedValue = md.getDisplayType() == DisplayType.SUMMARY ?
(decimalThreeAndOne.format(value))
+ : (decimalThreeAndTwo.format(value));
+ } else {
+ convertedValue = decimalThreeAndTwo.format(lastValue / 100) + md.getUnits();
+ }
+
+ return convertedValue;
+ }
+
+ //This is a JSNI call out to the third party javascript lib to execute on the data
inserted into the DOM.
public static native void graphSparkLines()
/*-{
//find all elements where attribute class contains 'dynamicsparkline' and
graph their contents
commit bf7dfc9444514566cf894f983dfdf0408dad43f9
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu Jan 6 21:29:26 2011 -0500
Several fixes to enable sparkline graphs, but more to go:
i) refactor of recentMetrics for more consistend naming and fix Links to point to
old portal war graphs.
ii) refactor of display logic to mirror portal war sparklines as custom display for
each measurementdefinition type.
iii) modify build to pull down and include the correct versions of jquery and
jquery.sparkline.
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
index 24c0199..7d86fe8 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
@@ -18,14 +18,21 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary;
+import java.util.Arrays;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
+import java.util.Set;
import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.i18n.client.NumberFormat;
+import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.ContentsType;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.HTMLFlow;
import com.smartgwt.client.widgets.Img;
+import com.smartgwt.client.widgets.form.fields.CanvasItem;
import com.smartgwt.client.widgets.form.fields.FormItemIcon;
import com.smartgwt.client.widgets.form.fields.LinkItem;
import com.smartgwt.client.widgets.form.fields.StaticTextItem;
@@ -36,6 +43,9 @@ import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.criteria.EventCriteria;
import org.rhq.core.domain.criteria.InstalledPackageCriteria;
import org.rhq.core.domain.criteria.ResourceConfigurationUpdateCriteria;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
import org.rhq.core.domain.measurement.composite.MeasurementOOBComposite;
import org.rhq.core.domain.operation.composite.ResourceOperationLastCompletedComposite;
import org.rhq.core.domain.resource.composite.DisambiguationReport;
@@ -84,6 +94,8 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
private String RECENT_PKG_HISTORY = MSG.common_title_recent_pkg_history();
private String RECENT_PKG_HISTORY_NONE =
MSG.view_resource_inventory_activity_no_recent_pkg_history();
+ private Timer sparklineReloader = null;
+
private ResourceComposite resourceComposite;
public ActivityView2(String locatorId, ResourceComposite resourceComposite) {
@@ -185,7 +197,7 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
getRecentEventUpdates();
getRecentOobs();
getRecentPkgHistory();
- // getRecentMetrics();
+ getRecentMetrics();
}
@Override
@@ -201,6 +213,7 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
public void refresh() {
// int resourceId = this.resourceComposite.getResource().getId();
//
this.iFrame.setContentsURL("/rhq/resource/summary/overview-plain.xhtml?id=" +
resourceId);
+ // Log.debug("$$$$$$$$$$$$$ ActivityView2.refresh()");
loadData();
markForRedraw();
}
@@ -634,138 +647,138 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
// });
}
- // private void getRecentMetrics() {
- // LocatableVLayout column = new
LocatableVLayout(recentAlertsContent.extendLocatorId("Content"));
- // column.setHeight(10);
- //
- // for (int i = 0; i < 1; i++) {
- // LocatableDynamicForm row = new
LocatableDynamicForm(recentOobContent.extendLocatorId("ContentForm"));
- // row.setNumCols(3);
- // row.setBorder("1px dashed green");
- // HTMLFlow graph = new HTMLFlow();
- // // graph.setContents("<span
class='inlinebar'>1,3,4,8,50,5</span>");
- // graph.setContents("<span
class='dynamicsparkline'>1,3,4,8,50,5</span>");
- // // graph.setContentsType(ContentsType.FRAGMENT);
- // graph.setContentsType(ContentsType.PAGE);
- // graph.setBorder("1px dashed black");
- // // graph.setSize("40", "40");
- // CanvasItem ci2 = new CanvasItem();
- // ci2.setCanvas(graph);
- // CanvasItem ci = new CanvasItem();
- // ci.setShowTitle(false);
- // // ci.setDefaultValue("<span
class='inlinesparkline'>1,3,4,8,50,5</span>");
- // ci.setDefaultValue("1,3,4,8,50,5");
- // ci.setValue("1,3,4,8,50,5");
- // String currentClass = ci.getAttribute("class");
- // Log.debug("+++++++++++:Current class for new canvas:" +
currentClass);
- // ci.setAttribute("class", " dynamicsparkline");
- // currentClass = ci.getAttribute("class");
- // Log.debug("+++++++++++:Updated class for new canvas:" +
currentClass);
- // // ci.getAttribute(attribute);
- // // RichTextItem rti = new RichTextItem();
- // BlurbItem rti = new BlurbItem();
- // // rti.setContentsType(ContentsType.PAGE);
- // // rti.setV
- // // rti.setValue("<div
class=\"inlinesparkline\">1,3,4,8,50,5</div>");
- // rti.setValue("<div id=\"dynamic1\"
class=\"dynamicsparkline\">1,3,4,8,50,5</div>");
- // Log.debug("@@@@@@@@@@@@@@@@@@@ Blurb-class-attr:" +
rti.getAttribute("class"));
- // //div id='dynamic1' class='dynamicsparkline'
- // Element newDiv = DOM.createDiv();
- // Log.debug("+++++++++++:" + newDiv);
- // newDiv.setClassName("dynamicsparkline");
- // newDiv.setId("dynamic1");
- // Log.debug("+++++++++++:" + newDiv + ":inH:" +
newDiv.getInnerHTML());
- // Log.debug("+++++++ TO STR:" + DOM.toString(newDiv));
- // Log.debug("+++++++++++:ParentComponent id:" +
recentMeasurementsContent.getID());
- // Log.debug("+++++++++++:ParentComponent id:" +
recentMeasurementsContent.getLocatorId());
- // // Element located =
DOM.getElementById(recentMeasurementsContent.getLocatorId());
- // Element located = DOM.getElementById(this.getLocatorId());
- // Log.debug("+++++++++++ Parent Node Located:" + located);
- // if (located != null) {
- // DOM.appendChild(located, newDiv);
- // }
- //
- // int[] data = { 1, 3, 4, 8, 50, 5 };
- // loadSparkLine(data);
- // // display = loadSparkLine(data);
- // // String loaded = loadSparkLine(data);
- // // Log.debug("+++++++++++:loaded:" + loaded);
- // Log.debug("+++++++++++:Completed:" + newDiv.getInnerHTML());
- // // Log.debug("+++++++++++:JSObject:" + display);
- // // Log.debug("+++++++++++:JSObject-class:" +
display.getClass());
- // Element body = DOM.createElement("body");
- // Element locatedBody = DOM.getChild(body, 0);
- // Log.debug("+++++++++++:DOM:" + locatedBody);
- // // HTMLPane content = new HTMLPane(display);
- // // rti = new BlurbItem(display);
- // // rti.setDefaultValue("<span
class='inlinebar'>1,3,4,8,50,5</span>");
- // // ci.getCanvas().addChild(graph);
- // StaticTextItem link = new StaticTextItem();
- // link.setValue("(Insert NAME)");
- // link.setShowTitle(false);
- // StaticTextItem value = new StaticTextItem();
- // value.setShowTitle(false);
- // value.setValue("142.3");
- // // row.setItems(graph,link,value);
- // // row.setItems(ci, link, value);
- // // row.setItems(rti, link, value);
- // row.setItems(ci, rti, link, value, ci2);
- //
- // column.addMember(row);
- // }
- //
- // for (Canvas child : recentMeasurementsContent.getChildren()) {
- // child.destroy();
- // }
- // recentMeasurementsContent.setContents("");
- // recentMeasurementsContent.addChild(column);
- // column.markForRedraw();
- // recentMeasurementsContent.markForRedraw();
- // int[] data = { 1, 3, 4, 8, 50, 5 };
- // loadSparkLine(data);
- // column.markForRedraw();
- // recentMeasurementsContent.markForRedraw();
- // }
- //
- // // private JavaScriptObject display;
- //
- // /*
- // */
- // // public static native void loadSparkLine(int[] data)
- // // public static native JavaScriptObject loadSparkLine(int[] data)
- // // public static native String loadSparkLine(int[] data)
- // public static native void loadSparkLine(int[] data)
- // /*-{
- //
//alert(JSON.stringify($wnd.jQuery('.dynamicsparkline').sparkline(data)));
- //
//alert(JSON.stringify($wnd.jQuery('.dynamicsparkline').sparkline(data)));
- // // var index = 0;
- // //$wnd.jQuery('.dynamicsparkline').sparkline(data);
- // //return $wnd.jQuery('.dynamicsparkline').sparkline(data);
- // //$doc.write('<div id="spark1"
class="dynamicsparkline"></div>');
- // //$wnd.jQuery('.dynamicsparkline').sparkline(data);
- // //var x=document.getElementById("spark1");
- // //return "X:";
- // //return x.innerHTML;
- //
- // var x=$doc.getElementById("spark1");
- // // alert("SPARK1-LOC:"+x);
- // // alert("SPARK1-LOC-CL:"+x.className);
- // //alert("SPARK1-LOC-html:"+x.innerHTML);
- // // alert("JQ obj:"+$wnd.jQuery('.dynamicsparkline'));
- // // alert("JQ
obj-JSON-Str:"+JSON.stringify($wnd.jQuery('.dynamicsparkline')));
- // $wnd.jQuery('.dynamicsparkline').sparkline();
- // $wnd.jQuery('#dynamic1').sparkline([1,2,3,4,5,4,3,2,1]);
- //
- // // alert("JQ
obj-SP:"+$wnd.jQuery('.dynamicsparkline').sparkline());
- // //alert("JQ
obj-SP-2:"+$wnd.jQuery('.dynamicsparkline').sparkline(data));
- // var x=$doc.getElementById("spark1");
- // // alert("SPARK1-LOC-html:"+x.innerHTML);
- // //$wnd.jQuery('.dynamicsparkline').sparkline(data);
- // //alert();
- // // alert('Window Name:'+$wnd.name);
- // //$doc.write('<div id="spark1"
class="dynamicsparkline"></div>');
- // //var x=$doc.getElementById("spark1");
- // //alert("SPARK:"+x);
- // //alert(x.innerHTML);
- // }-*/;
+ private void getRecentMetrics() {
+ final LocatableVLayout column = new
LocatableVLayout(recentMeasurementsContent.extendLocatorId("Content"));
+ column.setHeight(10);
+ final int resourceId = this.resourceComposite.getResource().getId();
+ Set<MeasurementDefinition> definitions =
this.resourceComposite.getResource().getResourceType()
+ .getMetricDefinitions();
+
+ final HashMap<String, MeasurementDefinition> map = new HashMap<String,
MeasurementDefinition>();
+ for (MeasurementDefinition md : definitions) {
+ map.put(md.getDisplayName(), md);
+ }
+ int[] definitionArrayIds = new int[definitions.size()];
+ final String[] displayOrder = new String[definitions.size()];
+ map.keySet().toArray(displayOrder);
+ Arrays.sort(displayOrder);
+ int l = 0;
+ for (String definitionToDisplay : displayOrder) {
+ definitionArrayIds[l++] = map.get(definitionToDisplay).getId();
+ }
+ GWTServiceLookup.getMeasurementDataService().findDataForResource(resourceId,
definitionArrayIds,
+ System.currentTimeMillis() - (1000L * 60 * 60 * 8),
System.currentTimeMillis(), 60,
+ new
AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.debug("Error retrieving metrics charting data for resource
[" + resourceId + "]:"
+ + caught.getMessage());
+ }
+
+ @Override
+ public void
onSuccess(List<List<MeasurementDataNumericHighLowComposite>> results) {
+ for (int h = 0; h < displayOrder.length; h++) {
+ MeasurementDefinition md = map.get(displayOrder[h]);
+ List<MeasurementDataNumericHighLowComposite> data =
results.get(h);
+ //locate last and minimum values.
+ double lastValue = 0;
+ double minValue = Double.MAX_VALUE;
+ for (MeasurementDataNumericHighLowComposite d : data) {
+ if ((d.getValue() + "").indexOf("NaN") ==
-1) {
+ if (d.getValue() < minValue) {
+ minValue = d.getValue();
+ }
+ }
+ }
+
+ //collapse the data into comma delimited list
+ String commaDelimitedList = "";
+
+ for (MeasurementDataNumericHighLowComposite d : data) {
+ if ((d.getValue() + "").indexOf("NaN") ==
-1) {
+ commaDelimitedList += (d.getValue() - minValue) +
",";
+ lastValue = d.getValue();
+ if (d.getValue() < minValue) {
+ minValue = d.getValue();
+ }
+ }
+ }
+ LocatableDynamicForm row = new
LocatableDynamicForm(column.extendLocatorId("ContentForm"));
+ row.setNumCols(3);
+ // row.setWidth(300);
+ HTMLFlow graph = new HTMLFlow();
+ //move all sparkline data up to the minimum value
+ String contents = "<span id='sparkline_" + 1 +
"' class='dynamicsparkline' width='0'>"
+ + commaDelimitedList + "</span>";
+ graph.setContents(contents);
+ graph.setContentsType(ContentsType.PAGE);
+ graph.setScrollbarSize(0);
+ CanvasItem ci2 = new CanvasItem();
+ ci2.setShowTitle(false);
+ ci2.setHeight(16);
+ ci2.setWidth(60);
+ ci2.setCanvas(graph);
+
+ //Link/title element
+ LinkItem link = new LinkItem();
+ link.setLinkTitle(md.getDisplayName());
+ link.setTitle(md.getName());
+ link.setTarget("_self");
+ link.setShowTitle(false);
+ //Value
+ StaticTextItem value = new StaticTextItem();
+ String convertedValue = lastValue + " " +
md.getUnits();
+ long KBYTES = 1024;
+ long MBYTES = KBYTES * KBYTES;
+ long GBYTES = MBYTES * KBYTES;
+ NumberFormat fmt = NumberFormat.getDecimalFormat();
+ fmt = NumberFormat.getFormat("###.####");
+ if (md.getUnits() == MeasurementUnits.BYTES) {
+ if ((lastValue / GBYTES) > 1) {
+ convertedValue = fmt.format(lastValue / GBYTES) +
"GB";
+ } else if ((lastValue / MBYTES) > 1) {
+ convertedValue = fmt.format(lastValue / MBYTES) +
"MB";
+ } else {
+ convertedValue = fmt.format(lastValue / KBYTES) +
"KB";
+ }
+ } else {
+ convertedValue = fmt.format(lastValue / 100) +
md.getUnits();
+ }
+ value.setDefaultValue(convertedValue);
+ value.setShowTitle(false);
+ value.setShowPickerIcon(false);
+ value.setWrap(false);
+
+ row.setItems(ci2, link, value);
+ if (commaDelimitedList.trim().length() > 100) {
+ column.addMember(row);
+ }
+ }
+ //call out to 3rd party javascript lib
+ graphSparkLines();
+ }
+ });
+
+ for (Canvas child : recentMeasurementsContent.getChildren()) {
+ child.destroy();
+ }
+ recentMeasurementsContent.setContents("");
+ recentMeasurementsContent.addChild(column);
+ // graphSparkLines();
+ recentMeasurementsContent.markForRedraw();
+ if (sparklineReloader == null) {
+ sparklineReloader = new Timer() {
+ public void run() {
+ refresh();
+ }
+ };
+ sparklineReloader.schedule(750);
+ }
+ }
+
+ public static native void graphSparkLines()
+ /*-{
+ //find all elements where attribute class contains 'dynamicsparkline' and
graph their contents
+ $wnd.jQuery('.dynamicsparkline').sparkline();
+ }-*/;
}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index ad2c937..6d1fa4a 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -7,6 +7,8 @@
<script type="text/javascript">
var isomorphicDir = "org.rhq.enterprise.gui.coregui.CoreGUI/sc/";
</script>
+ <script type="text/javascript"
src="js/jquery-1.4.4.js"></script>
+ <script type="text/javascript"
src="js/jquery.sparkline.js"></script>
<!-- support internationalized characters -->
<meta http-equiv="content-type"
content="text/html;charset=utf-8" />
commit 4b215415ff24ad977a07c6050132448d9cab7e23
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Wed Dec 29 10:32:56 2010 -0500
i)fix GWT relative date converter component(no longer displays EST but only -5:00)
ii)a few fixes to synchronize gwt view with old jsf for Recent Operations and Recent
Alerts.
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
index 0ddc80b..465b700 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/OperationGWTService.java
@@ -32,6 +32,7 @@ import org.rhq.core.domain.operation.bean.ResourceOperationSchedule;
import org.rhq.core.domain.operation.composite.ResourceOperationLastCompletedComposite;
import org.rhq.core.domain.operation.composite.ResourceOperationScheduleComposite;
import org.rhq.core.domain.resource.composite.DisambiguationReport;
+import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
/**
@@ -45,8 +46,8 @@ public interface OperationGWTService extends RemoteService {
PageList<GroupOperationHistory>
findGroupOperationHistoriesByCriteria(GroupOperationHistoryCriteria criteria)
throws RuntimeException;
- List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
findRecentCompletedOperations(int pageSize)
- throws RuntimeException;
+ List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
findRecentCompletedOperations(
+ PageControl pageControl) throws RuntimeException;
List<DisambiguationReport<ResourceOperationScheduleComposite>>
findScheduledOperations(int pageSize)
throws RuntimeException;
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
index 15969bb..24c0199 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ActivityView2.java
@@ -42,10 +42,12 @@ import org.rhq.core.domain.resource.composite.DisambiguationReport;
import org.rhq.core.domain.resource.composite.ResourceComposite;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.RefreshableView;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.resource.disambiguation.ReportDecorator;
+import org.rhq.enterprise.gui.coregui.client.util.GwtRelativeDurationConverter;
import org.rhq.enterprise.gui.coregui.client.util.selenium.Locatable;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableCanvas;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
@@ -87,6 +89,7 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
public ActivityView2(String locatorId, ResourceComposite resourceComposite) {
super(locatorId);
this.resourceComposite = resourceComposite;
+ setID(locatorId);
initializeUi();
}
@@ -182,6 +185,7 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
getRecentEventUpdates();
getRecentOobs();
getRecentPkgHistory();
+ // getRecentMetrics();
}
@Override
@@ -219,12 +223,17 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
}
}
+ /** Fetches alerts and updates the DynamicForm instance with the latest
+ * alert information.
+ */
private void getRecentAlerts() {
final int resourceId = this.resourceComposite.getResource().getId();
+ //fetches last five alerts for this resource
AlertCriteria criteria = new AlertCriteria();
- criteria.addFilterResourceIds(resourceId);
PageControl pageControl = new PageControl(0, 5);
+ pageControl.initDefaultOrderingField("ctime", PageOrdering.DESC);
criteria.setPageControl(pageControl);
+ criteria.addFilterResourceIds(resourceId);
GWTServiceLookup.getAlertService().findAlertsByCriteria(criteria, new
AsyncCallback<PageList<Alert>>() {
@Override
public void onSuccess(PageList<Alert> result) {
@@ -241,19 +250,20 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
img.setSrc(ImageManager.getAlertIcon(alert.getAlertDefinition().getPriority()));
img.setWidth(16);
img.setHeight(16);
+
img.setPrompt(alert.getAlertDefinition().getPriority().getDisplayName());
iconItem.setIcons(img);
iconItem.setShowTitle(false);
LinkItem link = new LinkItem();
- link.setLinkTitle(alert.getAlertDefinition().getName());
+ link.setLinkTitle(alert.getAlertDefinition().getName() + ":
");
link.setTitle(alert.getAlertDefinition().getName());
- link.setValue(ReportDecorator.GWT_RESOURCE_URL + resourceId +
"/Alerts/Definitions/"
- + alert.getAlertDefinition().getId());
+ link.setValue(ReportDecorator.GWT_RESOURCE_URL + resourceId +
"/Alerts/History/"
+ + alert.getId());
link.setTarget("_self");
link.setShowTitle(false);
StaticTextItem time = new StaticTextItem();
- time.setDefaultValue(new
Date(alert.getAlertDefinition().getCtime()).toString());
+
time.setDefaultValue(GwtRelativeDurationConverter.format(alert.getCtime()));
time.setShowTitle(false);
time.setShowPickerIcon(false);
time.setWrap(false);
@@ -279,9 +289,15 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
});
}
+ /** Fetches operations and updates the DynamicForm instance with the latest
+ * operation information.
+ */
private void getRecentOperations() {
final int resourceId = this.resourceComposite.getResource().getId();
- GWTServiceLookup.getOperationService().findRecentCompletedOperations(5,
+ //fetches five most recent operations.
+ PageControl pageControl = new PageControl(0, 5);
+ pageControl.initDefaultOrderingField("ro.createdTime",
PageOrdering.DESC);
+
GWTServiceLookup.getOperationService().findRecentCompletedOperations(pageControl,
new
AsyncCallback<List<DisambiguationReport<ResourceOperationLastCompletedComposite>>>()
{
@Override
@@ -305,11 +321,12 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
img.setSrc(ImageManager.getOperationResultsIcon(report.getOriginal().getOperationStatus()));
img.setWidth(16);
img.setHeight(16);
+
img.setPrompt(report.getOriginal().getOperationStatus().getDisplayName());
iconItem.setIcons(img);
iconItem.setShowTitle(false);
LinkItem link = new LinkItem();
- link.setLinkTitle(report.getOriginal().getOperationName());
+ link.setLinkTitle(report.getOriginal().getOperationName() +
": ");
link.setTitle(report.getOriginal().getOperationName());
link.setValue(ReportDecorator.GWT_RESOURCE_URL + resourceId +
"/Operations/History/"
+ report.getOriginal().getOperationHistoryId());
@@ -317,7 +334,8 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
link.setShowTitle(false);
StaticTextItem time = new StaticTextItem();
- time.setDefaultValue(new
Date(report.getOriginal().getOperationStartTime()).toString());
+
time.setDefaultValue(GwtRelativeDurationConverter.format(report.getOriginal()
+ .getOperationStartTime()));
time.setShowTitle(false);
time.setShowPickerIcon(false);
time.setWrap(false);
@@ -615,4 +633,139 @@ public class ActivityView2 extends LocatableHLayout implements
RefreshableView {
// }
// });
}
+
+ // private void getRecentMetrics() {
+ // LocatableVLayout column = new
LocatableVLayout(recentAlertsContent.extendLocatorId("Content"));
+ // column.setHeight(10);
+ //
+ // for (int i = 0; i < 1; i++) {
+ // LocatableDynamicForm row = new
LocatableDynamicForm(recentOobContent.extendLocatorId("ContentForm"));
+ // row.setNumCols(3);
+ // row.setBorder("1px dashed green");
+ // HTMLFlow graph = new HTMLFlow();
+ // // graph.setContents("<span
class='inlinebar'>1,3,4,8,50,5</span>");
+ // graph.setContents("<span
class='dynamicsparkline'>1,3,4,8,50,5</span>");
+ // // graph.setContentsType(ContentsType.FRAGMENT);
+ // graph.setContentsType(ContentsType.PAGE);
+ // graph.setBorder("1px dashed black");
+ // // graph.setSize("40", "40");
+ // CanvasItem ci2 = new CanvasItem();
+ // ci2.setCanvas(graph);
+ // CanvasItem ci = new CanvasItem();
+ // ci.setShowTitle(false);
+ // // ci.setDefaultValue("<span
class='inlinesparkline'>1,3,4,8,50,5</span>");
+ // ci.setDefaultValue("1,3,4,8,50,5");
+ // ci.setValue("1,3,4,8,50,5");
+ // String currentClass = ci.getAttribute("class");
+ // Log.debug("+++++++++++:Current class for new canvas:" +
currentClass);
+ // ci.setAttribute("class", " dynamicsparkline");
+ // currentClass = ci.getAttribute("class");
+ // Log.debug("+++++++++++:Updated class for new canvas:" +
currentClass);
+ // // ci.getAttribute(attribute);
+ // // RichTextItem rti = new RichTextItem();
+ // BlurbItem rti = new BlurbItem();
+ // // rti.setContentsType(ContentsType.PAGE);
+ // // rti.setV
+ // // rti.setValue("<div
class=\"inlinesparkline\">1,3,4,8,50,5</div>");
+ // rti.setValue("<div id=\"dynamic1\"
class=\"dynamicsparkline\">1,3,4,8,50,5</div>");
+ // Log.debug("@@@@@@@@@@@@@@@@@@@ Blurb-class-attr:" +
rti.getAttribute("class"));
+ // //div id='dynamic1' class='dynamicsparkline'
+ // Element newDiv = DOM.createDiv();
+ // Log.debug("+++++++++++:" + newDiv);
+ // newDiv.setClassName("dynamicsparkline");
+ // newDiv.setId("dynamic1");
+ // Log.debug("+++++++++++:" + newDiv + ":inH:" +
newDiv.getInnerHTML());
+ // Log.debug("+++++++ TO STR:" + DOM.toString(newDiv));
+ // Log.debug("+++++++++++:ParentComponent id:" +
recentMeasurementsContent.getID());
+ // Log.debug("+++++++++++:ParentComponent id:" +
recentMeasurementsContent.getLocatorId());
+ // // Element located =
DOM.getElementById(recentMeasurementsContent.getLocatorId());
+ // Element located = DOM.getElementById(this.getLocatorId());
+ // Log.debug("+++++++++++ Parent Node Located:" + located);
+ // if (located != null) {
+ // DOM.appendChild(located, newDiv);
+ // }
+ //
+ // int[] data = { 1, 3, 4, 8, 50, 5 };
+ // loadSparkLine(data);
+ // // display = loadSparkLine(data);
+ // // String loaded = loadSparkLine(data);
+ // // Log.debug("+++++++++++:loaded:" + loaded);
+ // Log.debug("+++++++++++:Completed:" + newDiv.getInnerHTML());
+ // // Log.debug("+++++++++++:JSObject:" + display);
+ // // Log.debug("+++++++++++:JSObject-class:" +
display.getClass());
+ // Element body = DOM.createElement("body");
+ // Element locatedBody = DOM.getChild(body, 0);
+ // Log.debug("+++++++++++:DOM:" + locatedBody);
+ // // HTMLPane content = new HTMLPane(display);
+ // // rti = new BlurbItem(display);
+ // // rti.setDefaultValue("<span
class='inlinebar'>1,3,4,8,50,5</span>");
+ // // ci.getCanvas().addChild(graph);
+ // StaticTextItem link = new StaticTextItem();
+ // link.setValue("(Insert NAME)");
+ // link.setShowTitle(false);
+ // StaticTextItem value = new StaticTextItem();
+ // value.setShowTitle(false);
+ // value.setValue("142.3");
+ // // row.setItems(graph,link,value);
+ // // row.setItems(ci, link, value);
+ // // row.setItems(rti, link, value);
+ // row.setItems(ci, rti, link, value, ci2);
+ //
+ // column.addMember(row);
+ // }
+ //
+ // for (Canvas child : recentMeasurementsContent.getChildren()) {
+ // child.destroy();
+ // }
+ // recentMeasurementsContent.setContents("");
+ // recentMeasurementsContent.addChild(column);
+ // column.markForRedraw();
+ // recentMeasurementsContent.markForRedraw();
+ // int[] data = { 1, 3, 4, 8, 50, 5 };
+ // loadSparkLine(data);
+ // column.markForRedraw();
+ // recentMeasurementsContent.markForRedraw();
+ // }
+ //
+ // // private JavaScriptObject display;
+ //
+ // /*
+ // */
+ // // public static native void loadSparkLine(int[] data)
+ // // public static native JavaScriptObject loadSparkLine(int[] data)
+ // // public static native String loadSparkLine(int[] data)
+ // public static native void loadSparkLine(int[] data)
+ // /*-{
+ //
//alert(JSON.stringify($wnd.jQuery('.dynamicsparkline').sparkline(data)));
+ //
//alert(JSON.stringify($wnd.jQuery('.dynamicsparkline').sparkline(data)));
+ // // var index = 0;
+ // //$wnd.jQuery('.dynamicsparkline').sparkline(data);
+ // //return $wnd.jQuery('.dynamicsparkline').sparkline(data);
+ // //$doc.write('<div id="spark1"
class="dynamicsparkline"></div>');
+ // //$wnd.jQuery('.dynamicsparkline').sparkline(data);
+ // //var x=document.getElementById("spark1");
+ // //return "X:";
+ // //return x.innerHTML;
+ //
+ // var x=$doc.getElementById("spark1");
+ // // alert("SPARK1-LOC:"+x);
+ // // alert("SPARK1-LOC-CL:"+x.className);
+ // //alert("SPARK1-LOC-html:"+x.innerHTML);
+ // // alert("JQ obj:"+$wnd.jQuery('.dynamicsparkline'));
+ // // alert("JQ
obj-JSON-Str:"+JSON.stringify($wnd.jQuery('.dynamicsparkline')));
+ // $wnd.jQuery('.dynamicsparkline').sparkline();
+ // $wnd.jQuery('#dynamic1').sparkline([1,2,3,4,5,4,3,2,1]);
+ //
+ // // alert("JQ
obj-SP:"+$wnd.jQuery('.dynamicsparkline').sparkline());
+ // //alert("JQ
obj-SP-2:"+$wnd.jQuery('.dynamicsparkline').sparkline(data));
+ // var x=$doc.getElementById("spark1");
+ // // alert("SPARK1-LOC-html:"+x.innerHTML);
+ // //$wnd.jQuery('.dynamicsparkline').sparkline(data);
+ // //alert();
+ // // alert('Window Name:'+$wnd.name);
+ // //$doc.write('<div id="spark1"
class="dynamicsparkline"></div>');
+ // //var x=$doc.getElementById("spark1");
+ // //alert("SPARK:"+x);
+ // //alert(x.innerHTML);
+ // }-*/;
}
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
index d81367c..ab200f7 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/operation/RecentOperationsDataSource.java
@@ -33,6 +33,7 @@ import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.operation.OperationRequestStatus;
import org.rhq.core.domain.operation.composite.ResourceOperationLastCompletedComposite;
import org.rhq.core.domain.resource.composite.DisambiguationReport;
+import org.rhq.core.domain.util.PageControl;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
@@ -107,18 +108,18 @@ public class RecentOperationsDataSource extends
* @param response outgoing response
*/
public void executeFetch(final DSRequest request, final DSResponse response) {
- int pageSize = -1;
+ PageControl pageControl = new PageControl();
//retrieve current portlet display settings
if ((this.portlet != null) && (this.portlet instanceof
OperationsPortlet)) {
OperationsPortlet operationsPortlet = (OperationsPortlet) this.portlet;
//populate criteria with portlet preferences defined.
if (operationsPortlet != null) {
if (isOperationsRangeCompletedEnabled()) {
- pageSize = getOperationsRangeCompleted();
+ pageControl.setPageSize(getOperationsRangeCompleted());
operationsPortlet.getCompletedOperationsGrid().setEmptyMessage(
OperationsPortlet.RANGE_DISABLED_MESSAGE_DEFAULT);
} else {//show the component, return no results and indicate that
you've disabled this display
- pageSize = 0;
+ pageControl.setPageSize(0);
operationsPortlet.getCompletedOperationsGrid().setEmptyMessage(
OperationsPortlet.RANGE_DISABLED_MESSAGE);
response.setData(null);
@@ -130,7 +131,7 @@ public class RecentOperationsDataSource extends
}
}
- GWTServiceLookup.getOperationService().findRecentCompletedOperations(pageSize,
+
GWTServiceLookup.getOperationService().findRecentCompletedOperations(pageControl,
new
AsyncCallback<List<DisambiguationReport<ResourceOperationLastCompletedComposite>>>()
{
public void onFailure(Throwable throwable) {
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/GwtRelativeDurationConverter.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/GwtRelativeDurationConverter.java
index 36dee5e..1679e3f 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/GwtRelativeDurationConverter.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/GwtRelativeDurationConverter.java
@@ -1,12 +1,14 @@
package org.rhq.enterprise.gui.coregui.client.util;
-//import java.text.SimpleDateFormat;
import java.util.Date;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.TimeZone;
import com.google.gwt.i18n.client.TimeZoneInfo;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+
/** An RPC gwt serializable implemenation of the jsf RelativeDurationConverter
* utility.
*
@@ -23,10 +25,9 @@ public class GwtRelativeDurationConverter {
private static final long NEVER = -1;
private static final long MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
- // private static final SimpleDateFormat dayFormatter = new
SimpleDateFormat("D");
- // private static final SimpleDateFormat formatter = new
SimpleDateFormat("hh:mm aaa z");
- private static final DateTimeFormat dayFormatter =
DateTimeFormat.getFormat("D");
- private static final DateTimeFormat formatter = DateTimeFormat.getFormat("hh:mm
aaa z");
+ private static final DateTimeFormat dayFormatter =
DateTimeFormat.getFormat("d");
+ private static final DateTimeFormat formatter = DateTimeFormat.getFormat("hh:mm
aaa Z");
+ private static final Messages MSG = CoreGUI.getMessages();
public static TimeZone tz = null;
@@ -39,18 +40,17 @@ public class GwtRelativeDurationConverter {
result = formatter.format(new Date(eventMillis));
} else if (dayOfYearEvent == dayOfYearToday - 1) {
// "yesterday" <time>
- result = "Yesterday, " + formatter.format(new Date(eventMillis));
+ result = MSG.common_label_yesterday() + ", " + formatter.format(new
Date(eventMillis));
} else {
// <time> "ago"
- result = getRelativeTimeAgo(eventMillis) + " ago";
+ result = getRelativeTimeAgo(eventMillis) + " " +
MSG.common_label_ago();
}
return result;
}
private static TimeZone getTimeZone() {
if (tz == null) {
- // return TimeZone.getDefault();
- return
TimeZone.createTimeZone(TimeZoneInfo.buildTimeZoneData(String.valueOf(System.currentTimeMillis())));
+ return
TimeZone.createTimeZone(TimeZoneInfo.buildTimeZoneData(""));
} else {
return tz;
}
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
index 6db4693..c3c2607 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/OperationGWTServiceImpl.java
@@ -116,9 +116,8 @@ public class OperationGWTServiceImpl extends AbstractGWTServiceImpl
implements O
*
*/
public
List<DisambiguationReport<ResourceOperationLastCompletedComposite>>
findRecentCompletedOperations(
- int pageSize) throws RuntimeException {
+ PageControl pageControl) throws RuntimeException {
try {
- PageControl pageControl = new PageControl(0, pageSize);
PageList<ResourceOperationLastCompletedComposite>
lastCompletedResourceOps = operationManager
.findRecentlyCompletedResourceOperations(getSessionSubject(), null,
pageControl);
diff --git
a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index a7de6fa..424cf7b 100644
---
a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++
b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -43,6 +43,7 @@ common_button_uninventory = Uninventory
# Common Labels
#------------------------
+common_label_ago=ago
common_label_all = ALL
common_label_all_resources = all resources
common_label_day = day
@@ -65,6 +66,7 @@ common_label_user = user
common_label_users = users
common_label_week = week
common_label_weeks = weeks
+common_label_yesterday=Yesterday
# Common Titles
#--------------